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