* elf32-i386.c (elf_i386_relocate_section): Check !DEF_REGULAR
[binutils.git] / gprof / tahoe.c
blobf9f72c0ad58a9b4a717819d9f09252092f399d79
1 /*
2 * Copyright (c) 1983, 2001 Regents of the University of California.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that: (1) source distributions retain this entire copyright
7 * notice and comment, and (2) distributions including binaries display
8 * the following acknowledgement: ``This product includes software
9 * developed by the University of California, Berkeley and its contributors''
10 * in the documentation or other materials provided with the distribution
11 * and in all advertising materials mentioning features or use of this
12 * software. Neither the name of the University nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 #include "gprof.h"
20 #include "cg_arcs.h"
21 #include "corefile.h"
22 #include "hist.h"
23 #include "symtab.h"
26 * opcode of the `callf' instruction
28 #define CALLF 0xfe
31 * register for pc relative addressing
33 #define PC 0xf
35 enum tahoe_opermodes
37 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
38 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
39 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
40 longrel, longreldef
42 typedef enum tahoe_opermodes tahoe_operandenum;
45 * A symbol to be the child of indirect callf:
47 Sym indirectchild;
49 tahoe_operandenum tahoe_operandmode PARAMS ((unsigned char *));
50 char *tahoe_operandname PARAMS ((tahoe_operandenum));
51 long tahoe_operandlength PARAMS ((unsigned char *));
52 bfd_vma tahoe_reladdr PARAMS ((char *));
53 void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
55 tahoe_operandenum
56 tahoe_operandmode (modep)
57 unsigned char *modep;
59 long usesreg = ((long) *modep) & 0xf;
61 switch (((long) *modep) >> 4)
63 case 0:
64 case 1:
65 case 2:
66 case 3:
67 return literal;
68 case 4:
69 return indexed;
70 case 5:
71 return reg;
72 case 6:
73 return regdef;
74 case 7:
75 return autodec;
76 case 8:
77 return usesreg != 0xe ? autoinc : immediate;
78 case 9:
79 return usesreg != PC ? autoincdef : absolute;
80 case 10:
81 return usesreg != PC ? bytedisp : byterel;
82 case 11:
83 return usesreg != PC ? bytedispdef : bytereldef;
84 case 12:
85 return usesreg != PC ? worddisp : wordrel;
86 case 13:
87 return usesreg != PC ? worddispdef : wordreldef;
88 case 14:
89 return usesreg != PC ? longdisp : longrel;
90 case 15:
91 return usesreg != PC ? longdispdef : longreldef;
93 /* NOTREACHED */
94 abort ();
97 char *
98 tahoe_operandname (mode)
99 tahoe_operandenum mode;
102 switch (mode)
104 case literal:
105 return "literal";
106 case indexed:
107 return "indexed";
108 case reg:
109 return "register";
110 case regdef:
111 return "register deferred";
112 case autodec:
113 return "autodecrement";
114 case autoinc:
115 return "autoincrement";
116 case autoincdef:
117 return "autoincrement deferred";
118 case bytedisp:
119 return "byte displacement";
120 case bytedispdef:
121 return "byte displacement deferred";
122 case byterel:
123 return "byte relative";
124 case bytereldef:
125 return "byte relative deferred";
126 case worddisp:
127 return "word displacement";
128 case worddispdef:
129 return "word displacement deferred";
130 case wordrel:
131 return "word relative";
132 case wordreldef:
133 return "word relative deferred";
134 case immediate:
135 return "immediate";
136 case absolute:
137 return "absolute";
138 case longdisp:
139 return "long displacement";
140 case longdispdef:
141 return "long displacement deferred";
142 case longrel:
143 return "long relative";
144 case longreldef:
145 return "long relative deferred";
147 /* NOTREACHED */
148 abort ();
151 long
152 tahoe_operandlength (modep)
153 unsigned char *modep;
156 switch (tahoe_operandmode (modep))
158 case literal:
159 case reg:
160 case regdef:
161 case autodec:
162 case autoinc:
163 case autoincdef:
164 return 1;
165 case bytedisp:
166 case bytedispdef:
167 case byterel:
168 case bytereldef:
169 return 2;
170 case worddisp:
171 case worddispdef:
172 case wordrel:
173 case wordreldef:
174 return 3;
175 case immediate:
176 case absolute:
177 case longdisp:
178 case longdispdef:
179 case longrel:
180 case longreldef:
181 return 5;
182 case indexed:
183 return 1 + tahoe_operandlength (modep + 1);
185 /* NOTREACHED */
186 abort ();
189 bfd_vma
190 tahoe_reladdr (modep)
191 char *modep;
193 tahoe_operandenum mode = tahoe_operandmode (modep);
194 char *cp;
195 short *sp;
196 long *lp;
197 int i;
198 long value = 0;
200 cp = modep;
201 ++cp; /* skip over the mode */
202 switch (mode)
204 default:
205 fprintf (stderr, "[reladdr] not relative address\n");
206 return (bfd_vma) modep;
207 case byterel:
208 return (bfd_vma) (cp + sizeof *cp + *cp);
209 case wordrel:
210 for (i = 0; (size_t) i < sizeof *sp; i++)
211 value = (value << 8) + (cp[i] & 0xff);
212 return (bfd_vma) (cp + sizeof *sp + value);
213 case longrel:
214 for (i = 0; (size_t) i < sizeof *lp; i++)
215 value = (value << 8) + (cp[i] & 0xff);
216 return (bfd_vma) (cp + sizeof *lp + value);
220 void
221 tahoe_find_call (parent, p_lowpc, p_highpc)
222 Sym *parent;
223 bfd_vma p_lowpc;
224 bfd_vma p_highpc;
226 unsigned char *instructp;
227 long length;
228 Sym *child;
229 tahoe_operandenum mode;
230 tahoe_operandenum firstmode;
231 bfd_vma destpc;
232 static bool inited = FALSE;
234 if (!inited)
236 inited = TRUE;
237 sym_init (&indirectchild);
238 indirectchild.cg.prop.fract = 1.0;
239 indirectchild.cg.cyc.head = &indirectchild;
242 if (core_text_space == 0)
244 return;
246 if (p_lowpc < s_lowpc)
248 p_lowpc = s_lowpc;
250 if (p_highpc > s_highpc)
252 p_highpc = s_highpc;
254 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
255 parent->name, (unsigned long) p_lowpc,
256 (unsigned long) p_highpc));
257 for (instructp = (unsigned char *) core_text_space + p_lowpc;
258 instructp < (unsigned char *) core_text_space + p_highpc;
259 instructp += length)
261 length = 1;
262 if (*instructp == CALLF)
265 * maybe a callf, better check it out.
266 * skip the count of the number of arguments.
268 DBG (CALLDEBUG, printf ("[findcall]\t0x%lx:callf",
269 ((unsigned long)
270 (instructp
271 - (unsigned char *) core_text_space))));
272 firstmode = tahoe_operandmode (instructp + length);
273 switch (firstmode)
275 case literal:
276 case immediate:
277 break;
278 default:
279 goto botched;
281 length += tahoe_operandlength (instructp + length);
282 mode = tahoe_operandmode (instructp + length);
283 DBG (CALLDEBUG,
284 printf ("\tfirst operand is %s", tahoe_operandname (firstmode));
285 printf ("\tsecond operand is %s\n", tahoe_operandname (mode));
287 switch (mode)
289 case regdef:
290 case bytedispdef:
291 case worddispdef:
292 case longdispdef:
293 case bytereldef:
294 case wordreldef:
295 case longreldef:
297 * indirect call: call through pointer
298 * either *d(r) as a parameter or local
299 * (r) as a return value
300 * *f as a global pointer
301 * [are there others that we miss?,
302 * e.g. arrays of pointers to functions???]
304 arc_add (parent, &indirectchild, (unsigned long) 0);
305 length += tahoe_operandlength (instructp + length);
306 continue;
307 case byterel:
308 case wordrel:
309 case longrel:
311 * regular pc relative addressing
312 * check that this is the address of
313 * a function.
315 destpc = tahoe_reladdr (instructp + length)
316 - (bfd_vma) core_text_space;
317 if (destpc >= s_lowpc && destpc <= s_highpc)
319 child = sym_lookup (&symtab, destpc);
320 DBG (CALLDEBUG,
321 printf ("[findcall]\tdestpc 0x%lx",
322 (unsigned long) destpc);
323 printf (" child->name %s", child->name);
324 printf (" child->addr 0x%lx\n",
325 (unsigned long) child->addr);
327 if (child->addr == destpc)
330 * a hit
332 arc_add (parent, child, (unsigned long) 0);
333 length += tahoe_operandlength (instructp + length);
334 continue;
336 goto botched;
339 * else:
340 * it looked like a callf,
341 * but it wasn't to anywhere.
343 goto botched;
344 default:
345 botched:
347 * something funny going on.
349 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
350 length = 1;
351 continue;