]>
Commit | Line | Data |
---|---|---|
ec0806ec JT |
1 | /* |
2 | * Copyright (c) 1983, 1998 Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
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. | |
18 | */ | |
19 | #include "gprof.h" | |
20 | #include "cg_arcs.h" | |
21 | #include "corefile.h" | |
22 | #include "hist.h" | |
23 | #include "symtab.h" | |
24 | ||
25 | static Sym indirect_child; | |
26 | ||
27 | void mips_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); | |
28 | ||
29 | void | |
30 | mips_find_call (parent, p_lowpc, p_highpc) | |
31 | Sym *parent; | |
32 | bfd_vma p_lowpc; | |
33 | bfd_vma p_highpc; | |
34 | { | |
35 | bfd_vma pc, dest_pc; | |
36 | unsigned int op; | |
37 | int offset; | |
38 | Sym *child; | |
39 | static bool inited = FALSE; | |
40 | ||
41 | if (!inited) | |
42 | { | |
43 | inited = TRUE; | |
44 | sym_init (&indirect_child); | |
45 | indirect_child.name = _("<indirect child>"); | |
46 | indirect_child.cg.prop.fract = 1.0; | |
47 | indirect_child.cg.cyc.head = &indirect_child; | |
48 | } | |
49 | ||
50 | if (!core_text_space) | |
51 | { | |
52 | return; | |
53 | } | |
54 | if (p_lowpc < s_lowpc) | |
55 | { | |
56 | p_lowpc = s_lowpc; | |
57 | } | |
58 | if (p_highpc > s_highpc) | |
59 | { | |
60 | p_highpc = s_highpc; | |
61 | } | |
62 | DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"), | |
63 | parent->name, (unsigned long) p_lowpc, | |
64 | (unsigned long) p_highpc)); | |
65 | for (pc = p_lowpc; pc < p_highpc; pc += 4) | |
66 | { | |
67 | op = bfd_get_32 (core_bfd, &((char *)core_text_space)[pc - s_lowpc]); | |
68 | if ((op & 0xfc000000) == 0x0c000000) | |
69 | { | |
70 | /* This is a "jal" instruction. Check that the destination | |
71 | is the address of a function. */ | |
72 | DBG (CALLDEBUG, | |
73 | printf (_("[find_call] 0x%lx: jal"), (unsigned long) pc)); | |
74 | offset = (op & 0x03ffffff) << 2; | |
75 | dest_pc = (pc & ~0xfffffff) | offset; | |
76 | if (dest_pc >= s_lowpc && dest_pc <= s_highpc) | |
77 | { | |
78 | child = sym_lookup (&symtab, dest_pc); | |
79 | DBG (CALLDEBUG, | |
80 | printf (" 0x%lx\t; name=%s, addr=0x%lx", | |
81 | (unsigned long) dest_pc, child->name, | |
82 | (unsigned long) child->addr)); | |
83 | if (child->addr == dest_pc) | |
84 | { | |
85 | DBG (CALLDEBUG, printf ("\n")); | |
86 | /* a hit: */ | |
87 | arc_add (parent, child, (unsigned long) 0); | |
88 | continue; | |
89 | } | |
90 | } | |
91 | /* Something funny going on. */ | |
92 | DBG (CALLDEBUG, printf ("\tbut it's a botch\n")); | |
93 | } | |
94 | else if ((op & 0xfc00f83f) == 0x0000f809) | |
95 | { | |
96 | /* This is a "jalr" instruction (indirect call). */ | |
97 | DBG (CALLDEBUG, | |
98 | printf (_("[find_call] 0x%lx: jalr\n"), (unsigned long) pc)); | |
99 | arc_add (parent, &indirect_child, (unsigned long) 0); | |
100 | } | |
101 | } | |
102 | } |