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 `callf' 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 tahoe_opermodes tahoe_operandenum;
57 * A symbol to be the child of indirect callf:
59 static Sym indirectchild;
61 static tahoe_operandenum tahoe_operandmode (unsigned char *);
62 static char *tahoe_operandname (tahoe_operandenum);
63 static long tahoe_operandlength (unsigned char *);
64 static bfd_signed_vma tahoe_offset (unsigned char *);
65 void tahoe_find_call (Sym *, bfd_vma, bfd_vma);
67 static tahoe_operandenum
68 tahoe_operandmode (unsigned char *modep)
70 long usesreg = *modep & 0xf;
72 switch ((*modep >> 4) & 0xf)
88 return usesreg != 0xe ? autoinc : immediate;
90 return usesreg != PC ? autoincdef : absolute;
92 return usesreg != PC ? bytedisp : byterel;
94 return usesreg != PC ? bytedispdef : bytereldef;
96 return usesreg != PC ? worddisp : wordrel;
98 return usesreg != PC ? worddispdef : wordreldef;
100 return usesreg != PC ? longdisp : longrel;
102 return usesreg != PC ? longdispdef : longreldef;
109 tahoe_operandname (tahoe_operandenum mode)
121 return "register deferred";
123 return "autodecrement";
125 return "autoincrement";
127 return "autoincrement deferred";
129 return "byte displacement";
131 return "byte displacement deferred";
133 return "byte relative";
135 return "byte relative deferred";
137 return "word displacement";
139 return "word displacement deferred";
141 return "word relative";
143 return "word relative deferred";
149 return "long displacement";
151 return "long displacement deferred";
153 return "long relative";
155 return "long relative deferred";
162 tahoe_operandlength (unsigned char *modep
166 switch (tahoe_operandmode (modep))
193 return 1 + tahoe_operandlength (modep + 1);
199 static bfd_signed_vma
200 tahoe_offset (unsigned char *modep)
202 tahoe_operandenum mode = tahoe_operandmode (modep);
204 ++modep; /* skip over the mode */
208 fprintf (stderr, "[reladdr] not relative address\n");
211 return 1 + bfd_get_signed_8 (core_bfd, modep);
213 return 2 + bfd_get_signed_16 (core_bfd, modep);
215 return 4 + bfd_get_signed_32 (core_bfd, modep);
220 tahoe_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
222 unsigned char *instructp;
225 tahoe_operandenum mode;
226 tahoe_operandenum firstmode;
228 static bfd_boolean inited = FALSE;
233 sym_init (&indirectchild);
234 indirectchild.cg.prop.fract = 1.0;
235 indirectchild.cg.cyc.head = &indirectchild;
238 if (core_text_space == 0)
242 if (p_lowpc < s_lowpc)
246 if (p_highpc > s_highpc)
250 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
251 parent->name, (unsigned long) p_lowpc,
252 (unsigned long) p_highpc));
253 for (pc = p_lowpc; pc < p_highpc; pc += length)
256 instructp = ((unsigned char *) core_text_space
257 + pc - core_text_sect->vma);
258 if ((*instructp & 0xff) == CALLF)
261 * maybe a callf, better check it out.
262 * skip the count of the number of arguments.
264 DBG (CALLDEBUG, printf ("[findcall]\t0x%lx:callf",
265 (unsigned long) pc));
266 firstmode = tahoe_operandmode (instructp + length);
275 length += tahoe_operandlength (instructp + length);
276 mode = tahoe_operandmode (instructp + length);
278 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
279 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
291 * indirect call: call through pointer
292 * either *d(r) as a parameter or local
293 * (r) as a return value
294 * *f as a global pointer
295 * [are there others that we miss?,
296 * e.g. arrays of pointers to functions???]
298 arc_add (parent, &indirectchild, (unsigned long) 0);
299 length += tahoe_operandlength (instructp + length);
305 * regular pc relative addressing
306 * check that this is the address of
309 destpc = pc + tahoe_offset (instructp + length);
310 if (destpc >= s_lowpc && destpc <= s_highpc)
312 child = sym_lookup (&symtab, destpc);
314 printf ("[findcall]\tdestpc 0x%lx",
315 (unsigned long) destpc);
316 printf (" child->name %s", child->name);
317 printf (" child->addr 0x%lx\n",
318 (unsigned long) child->addr);
320 if (child->addr == destpc)
325 arc_add (parent, child, (unsigned long) 0);
326 length += tahoe_operandlength (instructp + length);
333 * it looked like a callf,
334 * but it wasn't to anywhere.
340 * something funny going on.
342 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));