source: branches/libc-0.6/src/binutils/gprof/tahoe.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.2 KB
Line 
1/*
2 * Copyright (c) 1983, 1993, 2001
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
16 *
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
27 * SUCH DAMAGE.
28 */
29#include "gprof.h"
30#include "search_list.h"
31#include "source.h"
32#include "symtab.h"
33#include "cg_arcs.h"
34#include "corefile.h"
35#include "hist.h"
36
37 /*
38 * opcode of the `callf' instruction
39 */
40#define CALLF 0xfe
41
42 /*
43 * register for pc relative addressing
44 */
45#define PC 0xf
46
47enum tahoe_opermodes
48 {
49 literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
50 bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
51 immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
52 longrel, longreldef
53 };
54typedef enum tahoe_opermodes tahoe_operandenum;
55
56/*
57 * A symbol to be the child of indirect callf:
58 */
59static Sym indirectchild;
60
61static tahoe_operandenum tahoe_operandmode PARAMS ((unsigned char *));
62static char *tahoe_operandname PARAMS ((tahoe_operandenum));
63static long tahoe_operandlength PARAMS ((unsigned char *));
64static bfd_signed_vma tahoe_offset PARAMS ((unsigned char *));
65void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
66
67static tahoe_operandenum
68tahoe_operandmode (modep)
69 unsigned char *modep;
70{
71 long usesreg = *modep & 0xf;
72
73 switch ((*modep >> 4) & 0xf)
74 {
75 case 0:
76 case 1:
77 case 2:
78 case 3:
79 return literal;
80 case 4:
81 return indexed;
82 case 5:
83 return reg;
84 case 6:
85 return regdef;
86 case 7:
87 return autodec;
88 case 8:
89 return usesreg != 0xe ? autoinc : immediate;
90 case 9:
91 return usesreg != PC ? autoincdef : absolute;
92 case 10:
93 return usesreg != PC ? bytedisp : byterel;
94 case 11:
95 return usesreg != PC ? bytedispdef : bytereldef;
96 case 12:
97 return usesreg != PC ? worddisp : wordrel;
98 case 13:
99 return usesreg != PC ? worddispdef : wordreldef;
100 case 14:
101 return usesreg != PC ? longdisp : longrel;
102 case 15:
103 return usesreg != PC ? longdispdef : longreldef;
104 }
105 /* NOTREACHED */
106 abort ();
107}
108
109static char *
110tahoe_operandname (mode)
111 tahoe_operandenum mode;
112{
113
114 switch (mode)
115 {
116 case literal:
117 return "literal";
118 case indexed:
119 return "indexed";
120 case reg:
121 return "register";
122 case regdef:
123 return "register deferred";
124 case autodec:
125 return "autodecrement";
126 case autoinc:
127 return "autoincrement";
128 case autoincdef:
129 return "autoincrement deferred";
130 case bytedisp:
131 return "byte displacement";
132 case bytedispdef:
133 return "byte displacement deferred";
134 case byterel:
135 return "byte relative";
136 case bytereldef:
137 return "byte relative deferred";
138 case worddisp:
139 return "word displacement";
140 case worddispdef:
141 return "word displacement deferred";
142 case wordrel:
143 return "word relative";
144 case wordreldef:
145 return "word relative deferred";
146 case immediate:
147 return "immediate";
148 case absolute:
149 return "absolute";
150 case longdisp:
151 return "long displacement";
152 case longdispdef:
153 return "long displacement deferred";
154 case longrel:
155 return "long relative";
156 case longreldef:
157 return "long relative deferred";
158 }
159 /* NOTREACHED */
160 abort ();
161}
162
163static long
164tahoe_operandlength (modep)
165 unsigned char *modep;
166{
167
168 switch (tahoe_operandmode (modep))
169 {
170 case literal:
171 case reg:
172 case regdef:
173 case autodec:
174 case autoinc:
175 case autoincdef:
176 return 1;
177 case bytedisp:
178 case bytedispdef:
179 case byterel:
180 case bytereldef:
181 return 2;
182 case worddisp:
183 case worddispdef:
184 case wordrel:
185 case wordreldef:
186 return 3;
187 case immediate:
188 case absolute:
189 case longdisp:
190 case longdispdef:
191 case longrel:
192 case longreldef:
193 return 5;
194 case indexed:
195 return 1 + tahoe_operandlength (modep + 1);
196 }
197 /* NOTREACHED */
198 abort ();
199}
200
201static bfd_signed_vma
202tahoe_offset (modep)
203 unsigned char *modep;
204{
205 tahoe_operandenum mode = tahoe_operandmode (modep);
206
207 ++modep; /* skip over the mode */
208 switch (mode)
209 {
210 default:
211 fprintf (stderr, "[reladdr] not relative address\n");
212 return 0;
213 case byterel:
214 return 1 + bfd_get_signed_8 (core_bfd, modep);
215 case wordrel:
216 return 2 + bfd_get_signed_16 (core_bfd, modep);
217 case longrel:
218 return 4 + bfd_get_signed_32 (core_bfd, modep);
219 }
220}
221
222void
223tahoe_find_call (parent, p_lowpc, p_highpc)
224 Sym *parent;
225 bfd_vma p_lowpc;
226 bfd_vma p_highpc;
227{
228 unsigned char *instructp;
229 long length;
230 Sym *child;
231 tahoe_operandenum mode;
232 tahoe_operandenum firstmode;
233 bfd_vma pc, destpc;
234 static bfd_boolean inited = FALSE;
235
236 if (!inited)
237 {
238 inited = TRUE;
239 sym_init (&indirectchild);
240 indirectchild.cg.prop.fract = 1.0;
241 indirectchild.cg.cyc.head = &indirectchild;
242 }
243
244 if (core_text_space == 0)
245 {
246 return;
247 }
248 if (p_lowpc < s_lowpc)
249 {
250 p_lowpc = s_lowpc;
251 }
252 if (p_highpc > s_highpc)
253 {
254 p_highpc = s_highpc;
255 }
256 DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
257 parent->name, (unsigned long) p_lowpc,
258 (unsigned long) p_highpc));
259 for (pc = p_lowpc; pc < p_highpc; pc += length)
260 {
261 length = 1;
262 instructp = ((unsigned char *) core_text_space
263 + pc - core_text_sect->vma);
264 if ((*instructp & 0xff) == CALLF)
265 {
266 /*
267 * maybe a callf, better check it out.
268 * skip the count of the number of arguments.
269 */
270 DBG (CALLDEBUG, printf ("[findcall]\t0x%lx:callf",
271 (unsigned long) pc));
272 firstmode = tahoe_operandmode (instructp + length);
273 switch (firstmode)
274 {
275 case literal:
276 case immediate:
277 break;
278 default:
279 goto botched;
280 }
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));
286 );
287 switch (mode)
288 {
289 case regdef:
290 case bytedispdef:
291 case worddispdef:
292 case longdispdef:
293 case bytereldef:
294 case wordreldef:
295 case longreldef:
296 /*
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???]
303 */
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:
310 /*
311 * regular pc relative addressing
312 * check that this is the address of
313 * a function.
314 */
315 destpc = pc + tahoe_offset (instructp + length);
316 if (destpc >= s_lowpc && destpc <= s_highpc)
317 {
318 child = sym_lookup (&symtab, destpc);
319 DBG (CALLDEBUG,
320 printf ("[findcall]\tdestpc 0x%lx",
321 (unsigned long) destpc);
322 printf (" child->name %s", child->name);
323 printf (" child->addr 0x%lx\n",
324 (unsigned long) child->addr);
325 );
326 if (child->addr == destpc)
327 {
328 /*
329 * a hit
330 */
331 arc_add (parent, child, (unsigned long) 0);
332 length += tahoe_operandlength (instructp + length);
333 continue;
334 }
335 goto botched;
336 }
337 /*
338 * else:
339 * it looked like a callf,
340 * but it wasn't to anywhere.
341 */
342 goto botched;
343 default:
344 botched:
345 /*
346 * something funny going on.
347 */
348 DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));
349 length = 1;
350 continue;
351 }
352 }
353 }
354}
Note: See TracBrowser for help on using the repository browser.