xref: /dflybsd-src/contrib/binutils-2.34/gprof/alpha.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
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