2 * Copyright (c) 1983, 1993, 2001
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include "search_list.h"
38 * opcode of the `calls' instruction
43 * register for pc relative addressing
49 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
50 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
51 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
54 typedef enum opermodes operandenum;
57 /* Here to document only. We can't use this when cross compiling as
58 the bitfield layout might not be the same as native. */
61 unsigned int regfield:4;
62 unsigned int modefield:4;
67 * A symbol to be the child of indirect calls:
69 static Sym indirectchild;
71 static operandenum vax_operandmode PARAMS ((unsigned char *));
72 static char *vax_operandname PARAMS ((operandenum));
73 static long vax_operandlength PARAMS ((unsigned char *));
74 static bfd_signed_vma vax_offset PARAMS ((unsigned char *));
75 void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
78 vax_operandmode (modep)
81 int usesreg = *modep & 0xf;
83 switch ((*modep >> 4) & 0xf)
99 return usesreg != PC ? autoinc : immediate;
101 return usesreg != PC ? autoincdef : absolute;
103 return usesreg != PC ? bytedisp : byterel;
105 return usesreg != PC ? bytedispdef : bytereldef;
107 return usesreg != PC ? worddisp : wordrel;
109 return usesreg != PC ? worddispdef : wordreldef;
111 return usesreg != PC ? longdisp : longrel;
113 return usesreg != PC ? longdispdef : longreldef;
120 vax_operandname (mode)
133 return "register deferred";
135 return "autodecrement";
137 return "autoincrement";
139 return "autoincrement deferred";
141 return "byte displacement";
143 return "byte displacement deferred";
145 return "byte relative";
147 return "byte relative deferred";
149 return "word displacement";
151 return "word displacement deferred";
153 return "word relative";
155 return "word relative deferred";
161 return "long displacement";
163 return "long displacement deferred";
165 return "long relative";
167 return "long relative deferred";
174 vax_operandlength (modep)
175 unsigned char *modep;
178 switch (vax_operandmode (modep))
205 return 1 + vax_operandlength (modep + 1);
211 static bfd_signed_vma
213 unsigned char *modep;
215 operandenum mode = vax_operandmode (modep);
217 ++modep; /* skip over the mode */
221 fprintf (stderr, "[reladdr] not relative address\n");
224 return 1 + bfd_get_signed_8 (core_bfd, modep);
226 return 2 + bfd_get_signed_16 (core_bfd, modep);
228 return 4 + bfd_get_signed_32 (core_bfd, modep);
234 vax_find_call (parent, p_lowpc, p_highpc)
239 unsigned char *instructp;
243 operandenum firstmode;
245 static bfd_boolean inited = FALSE;
250 sym_init (&indirectchild);
251 indirectchild.cg.prop.fract = 1.0;
252 indirectchild.cg.cyc.head = &indirectchild;
255 if (core_text_space == 0)
259 if (p_lowpc < s_lowpc)
263 if (p_highpc > s_highpc)
267 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
268 parent->name, (unsigned long) p_lowpc,
269 (unsigned long) p_highpc));
270 for (pc = p_lowpc; pc < p_highpc; pc += length)
273 instructp = ((unsigned char *) core_text_space
274 + pc - core_text_sect->vma);
275 if ((*instructp & 0xff) == CALLS)
278 * maybe a calls, better check it out.
279 * skip the count of the number of arguments.
282 printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
283 firstmode = vax_operandmode (instructp + length);
292 length += vax_operandlength (instructp + length);
293 mode = vax_operandmode (instructp + length);
295 printf ("\tfirst operand is %s", vax_operandname (firstmode));
296 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
307 * indirect call: call through pointer
308 * either *d(r) as a parameter or local
309 * (r) as a return value
310 * *f as a global pointer
311 * [are there others that we miss?,
312 * e.g. arrays of pointers to functions???]
314 arc_add (parent, &indirectchild, (unsigned long) 0);
315 length += vax_operandlength (instructp + length);
321 * regular pc relative addressing
322 * check that this is the address of
325 destpc = pc + vax_offset (instructp + length);
326 if (destpc >= s_lowpc && destpc <= s_highpc)
328 child = sym_lookup (&symtab, destpc);
330 printf ("[findcall]\tdestpc 0x%lx",
331 (unsigned long) destpc);
332 printf (" child->name %s", child->name);
333 printf (" child->addr 0x%lx\n",
334 (unsigned long) child->addr);
336 if (child->addr == destpc)
341 arc_add (parent, child, (unsigned long) 0);
342 length += vax_operandlength (instructp + length);
349 * it looked like a calls,
350 * but it wasn't to anywhere.
356 * something funny going on.
358 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));