1*fae548d3Szrj /*
2*fae548d3Szrj * Copyright (c) 1983, 1993, 1998
3*fae548d3Szrj * The Regents of the University of California. All rights reserved.
4*fae548d3Szrj *
5*fae548d3Szrj * Redistribution and use in source and binary forms, with or without
6*fae548d3Szrj * modification, are permitted provided that the following conditions
7*fae548d3Szrj * are met:
8*fae548d3Szrj * 1. Redistributions of source code must retain the above copyright
9*fae548d3Szrj * notice, this list of conditions and the following disclaimer.
10*fae548d3Szrj * 2. Redistributions in binary form must reproduce the above copyright
11*fae548d3Szrj * notice, this list of conditions and the following disclaimer in the
12*fae548d3Szrj * documentation and/or other materials provided with the distribution.
13*fae548d3Szrj * 3. Neither the name of the University nor the names of its contributors
14*fae548d3Szrj * may be used to endorse or promote products derived from this software
15*fae548d3Szrj * without specific prior written permission.
16*fae548d3Szrj *
17*fae548d3Szrj * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*fae548d3Szrj * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*fae548d3Szrj * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*fae548d3Szrj * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*fae548d3Szrj * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*fae548d3Szrj * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*fae548d3Szrj * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*fae548d3Szrj * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*fae548d3Szrj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*fae548d3Szrj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*fae548d3Szrj * SUCH DAMAGE.
28*fae548d3Szrj */
29*fae548d3Szrj #include "gprof.h"
30*fae548d3Szrj #include "search_list.h"
31*fae548d3Szrj #include "source.h"
32*fae548d3Szrj #include "symtab.h"
33*fae548d3Szrj #include "cg_arcs.h"
34*fae548d3Szrj #include "corefile.h"
35*fae548d3Szrj #include "hist.h"
36*fae548d3Szrj
37*fae548d3Szrj /*
38*fae548d3Szrj * Opcodes of the call instructions:
39*fae548d3Szrj */
40*fae548d3Szrj #define OP_Jxx 0x1aU
41*fae548d3Szrj #define OP_BSR 0x34U
42*fae548d3Szrj
43*fae548d3Szrj #define Jxx_FUNC_JMP 0U
44*fae548d3Szrj #define Jxx_FUNC_JSR 1U
45*fae548d3Szrj #define Jxx_FUNC_RET 2U
46*fae548d3Szrj #define Jxx_FUNC_JSR_COROUTINE 3U
47*fae548d3Szrj
48*fae548d3Szrj /* *INDENT-OFF* */
49*fae548d3Szrj /* Here to document only. We can't use this when cross compiling as
50*fae548d3Szrj the bitfield layout might not be the same as native.
51*fae548d3Szrj
52*fae548d3Szrj typedef union
53*fae548d3Szrj {
54*fae548d3Szrj struct
55*fae548d3Szrj {
56*fae548d3Szrj unsigned other:26;
57*fae548d3Szrj unsigned op_code:6;
58*fae548d3Szrj }
59*fae548d3Szrj a; -- any format
60*fae548d3Szrj struct
61*fae548d3Szrj {
62*fae548d3Szrj int disp:21;
63*fae548d3Szrj unsigned ra:5;
64*fae548d3Szrj unsigned op_code:6;
65*fae548d3Szrj }
66*fae548d3Szrj b; -- branch format
67*fae548d3Szrj struct
68*fae548d3Szrj {
69*fae548d3Szrj int hint:14;
70*fae548d3Szrj unsigned func:2;
71*fae548d3Szrj unsigned rb:5;
72*fae548d3Szrj unsigned ra:5;
73*fae548d3Szrj unsigned op_code:6;
74*fae548d3Szrj }
75*fae548d3Szrj j; -- jump format
76*fae548d3Szrj }
77*fae548d3Szrj alpha_Instruction;
78*fae548d3Szrj */
79*fae548d3Szrj /* *INDENT-ON* */
80*fae548d3Szrj
81*fae548d3Szrj static Sym indirect_child;
82*fae548d3Szrj
83*fae548d3Szrj void alpha_find_call (Sym *, bfd_vma, bfd_vma);
84*fae548d3Szrj
85*fae548d3Szrj /*
86*fae548d3Szrj * On the Alpha we can only detect PC relative calls, which are
87*fae548d3Szrj * usually generated for calls to functions within the same
88*fae548d3Szrj * object file only. This is still better than nothing, however.
89*fae548d3Szrj * (In particular it should be possible to find functions that
90*fae548d3Szrj * potentially call integer division routines, for example.)
91*fae548d3Szrj */
92*fae548d3Szrj void
alpha_find_call(Sym * parent,bfd_vma p_lowpc,bfd_vma p_highpc)93*fae548d3Szrj alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
94*fae548d3Szrj {
95*fae548d3Szrj bfd_vma pc, dest_pc;
96*fae548d3Szrj unsigned int insn;
97*fae548d3Szrj Sym *child;
98*fae548d3Szrj
99*fae548d3Szrj if (indirect_child.name == NULL)
100*fae548d3Szrj {
101*fae548d3Szrj sym_init (&indirect_child);
102*fae548d3Szrj indirect_child.name = _("<indirect child>");
103*fae548d3Szrj indirect_child.cg.prop.fract = 1.0;
104*fae548d3Szrj indirect_child.cg.cyc.head = &indirect_child;
105*fae548d3Szrj }
106*fae548d3Szrj
107*fae548d3Szrj DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
108*fae548d3Szrj parent->name, (unsigned long) p_lowpc,
109*fae548d3Szrj (unsigned long) p_highpc));
110*fae548d3Szrj for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
111*fae548d3Szrj {
112*fae548d3Szrj insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
113*fae548d3Szrj + pc - core_text_sect->vma));
114*fae548d3Szrj switch (insn & (0x3fU << 26))
115*fae548d3Szrj {
116*fae548d3Szrj case OP_Jxx << 26:
117*fae548d3Szrj /*
118*fae548d3Szrj * There is no simple and reliable way to determine the
119*fae548d3Szrj * target of a jsr (the hint bits help, but there aren't
120*fae548d3Szrj * enough bits to get a satisfactory hit rate). Instead,
121*fae548d3Szrj * for any indirect jump we simply add an arc from PARENT
122*fae548d3Szrj * to INDIRECT_CHILD---that way the user it at least able
123*fae548d3Szrj * to see that there are other calls as well.
124*fae548d3Szrj */
125*fae548d3Szrj if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
126*fae548d3Szrj || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14)
127*fae548d3Szrj {
128*fae548d3Szrj DBG (CALLDEBUG,
129*fae548d3Szrj printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),
130*fae548d3Szrj (unsigned long) pc,
131*fae548d3Szrj ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
132*fae548d3Szrj ? "" : "_coroutine")));
133*fae548d3Szrj arc_add (parent, &indirect_child, (unsigned long) 0);
134*fae548d3Szrj }
135*fae548d3Szrj break;
136*fae548d3Szrj
137*fae548d3Szrj case OP_BSR << 26:
138*fae548d3Szrj DBG (CALLDEBUG,
139*fae548d3Szrj printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc));
140*fae548d3Szrj /*
141*fae548d3Szrj * Regular PC relative addressing. Check that this is the
142*fae548d3Szrj * address of a function. The linker sometimes redirects
143*fae548d3Szrj * the entry point by 8 bytes to skip loading the global
144*fae548d3Szrj * pointer, so we allow for either address:
145*fae548d3Szrj */
146*fae548d3Szrj dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff)
147*fae548d3Szrj ^ 0x100000) - 0x100000);
148*fae548d3Szrj if (hist_check_address (dest_pc))
149*fae548d3Szrj {
150*fae548d3Szrj child = sym_lookup (&symtab, dest_pc);
151*fae548d3Szrj if (child)
152*fae548d3Szrj {
153*fae548d3Szrj DBG (CALLDEBUG,
154*fae548d3Szrj printf (" 0x%lx\t; name=%s, addr=0x%lx",
155*fae548d3Szrj (unsigned long) dest_pc, child->name,
156*fae548d3Szrj (unsigned long) child->addr));
157*fae548d3Szrj if (child->addr == dest_pc || child->addr == dest_pc - 8)
158*fae548d3Szrj {
159*fae548d3Szrj DBG (CALLDEBUG, printf ("\n"));
160*fae548d3Szrj /* a hit: */
161*fae548d3Szrj arc_add (parent, child, (unsigned long) 0);
162*fae548d3Szrj continue;
163*fae548d3Szrj }
164*fae548d3Szrj }
165*fae548d3Szrj }
166*fae548d3Szrj /*
167*fae548d3Szrj * Something funny going on.
168*fae548d3Szrj */
169*fae548d3Szrj DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
170*fae548d3Szrj break;
171*fae548d3Szrj
172*fae548d3Szrj default:
173*fae548d3Szrj break;
174*fae548d3Szrj }
175*fae548d3Szrj }
176*fae548d3Szrj }
177