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 (unsigned char *);
72 static char *vax_operandname (operandenum);
73 static long vax_operandlength (unsigned char *);
74 static bfd_signed_vma vax_offset (unsigned char *);
75 void vax_find_call (Sym *, bfd_vma, bfd_vma);
78 vax_operandmode (unsigned char *modep)
80 int usesreg = *modep & 0xf;
82 switch ((*modep >> 4) & 0xf)
98 return usesreg != PC ? autoinc : immediate;
100 return usesreg != PC ? autoincdef : absolute;
102 return usesreg != PC ? bytedisp : byterel;
104 return usesreg != PC ? bytedispdef : bytereldef;
106 return usesreg != PC ? worddisp : wordrel;
108 return usesreg != PC ? worddispdef : wordreldef;
110 return usesreg != PC ? longdisp : longrel;
112 return usesreg != PC ? longdispdef : longreldef;
119 vax_operandname (operandenum mode)
131 return "register deferred";
133 return "autodecrement";
135 return "autoincrement";
137 return "autoincrement deferred";
139 return "byte displacement";
141 return "byte displacement deferred";
143 return "byte relative";
145 return "byte relative deferred";
147 return "word displacement";
149 return "word displacement deferred";
151 return "word relative";
153 return "word relative deferred";
159 return "long displacement";
161 return "long displacement deferred";
163 return "long relative";
165 return "long relative deferred";
172 vax_operandlength (unsigned char *modep)
175 switch (vax_operandmode (modep))
202 return 1 + vax_operandlength (modep + 1);
208 static bfd_signed_vma
209 vax_offset (unsigned char *modep)
211 operandenum mode = vax_operandmode (modep);
213 ++modep; /* skip over the mode */
217 fprintf (stderr, "[reladdr] not relative address\n");
220 return 1 + bfd_get_signed_8 (core_bfd, modep);
222 return 2 + bfd_get_signed_16 (core_bfd, modep);
224 return 4 + bfd_get_signed_32 (core_bfd, modep);
230 vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
232 unsigned char *instructp;
236 operandenum firstmode;
238 static bfd_boolean inited = FALSE;
243 sym_init (&indirectchild);
244 indirectchild.cg.prop.fract = 1.0;
245 indirectchild.cg.cyc.head = &indirectchild;
248 if (core_text_space == 0)
252 if (p_lowpc < s_lowpc)
256 if (p_highpc > s_highpc)
260 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
261 parent->name, (unsigned long) p_lowpc,
262 (unsigned long) p_highpc));
263 for (pc = p_lowpc; pc < p_highpc; pc += length)
266 instructp = ((unsigned char *) core_text_space
267 + pc - core_text_sect->vma);
268 if ((*instructp & 0xff) == CALLS)
271 * maybe a calls, better check it out.
272 * skip the count of the number of arguments.
275 printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
276 firstmode = vax_operandmode (instructp + length);
285 length += vax_operandlength (instructp + length);
286 mode = vax_operandmode (instructp + length);
288 printf ("\tfirst operand is %s", vax_operandname (firstmode));
289 printf ("\tsecond operand is %s\n", vax_operandname (mode)));
300 * indirect call: call through pointer
301 * either *d(r) as a parameter or local
302 * (r) as a return value
303 * *f as a global pointer
304 * [are there others that we miss?,
305 * e.g. arrays of pointers to functions???]
307 arc_add (parent, &indirectchild, (unsigned long) 0);
308 length += vax_operandlength (instructp + length);
314 * regular pc relative addressing
315 * check that this is the address of
318 destpc = pc + vax_offset (instructp + length);
319 if (destpc >= s_lowpc && destpc <= s_highpc)
321 child = sym_lookup (&symtab, destpc);
323 printf ("[findcall]\tdestpc 0x%lx",
324 (unsigned long) destpc);
325 printf (" child->name %s", child->name);
326 printf (" child->addr 0x%lx\n",
327 (unsigned long) child->addr);
329 if (child->addr == destpc)
334 arc_add (parent, child, (unsigned long) 0);
335 length += vax_operandlength (instructp + length);
342 * it looked like a calls,
343 * but it wasn't to anywhere.
349 * something funny going on.
351 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));