(root)/
binutils-2.41/
gprof/
alpha.c
       1  /*
       2   * Copyright (c) 1983, 1993, 1998
       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   * Opcodes of the call instructions:
      39   */
      40  #define OP_Jxx	0x1aU
      41  #define	OP_BSR	0x34U
      42  
      43  #define Jxx_FUNC_JMP		0U
      44  #define Jxx_FUNC_JSR		1U
      45  #define Jxx_FUNC_RET		2U
      46  #define Jxx_FUNC_JSR_COROUTINE	3U
      47  
      48  /* *INDENT-OFF* */
      49  /* Here to document only.  We can't use this when cross compiling as
      50     the bitfield layout might not be the same as native.
      51  
      52     typedef union
      53       {
      54         struct
      55           {
      56  	   unsigned other:26;
      57  	   unsigned op_code:6;
      58           }
      59         a;				-- any format
      60         struct
      61           {
      62  	   int disp:21;
      63  	   unsigned ra:5;
      64  	   unsigned op_code:6;
      65           }
      66         b;				-- branch format
      67         struct
      68           {
      69  	   int hint:14;
      70  	   unsigned func:2;
      71  	   unsigned rb:5;
      72  	   unsigned ra:5;
      73  	   unsigned op_code:6;
      74           }
      75         j;				-- jump format
      76       }
      77      alpha_Instruction;
      78  */
      79  /* *INDENT-ON* */
      80  
      81  static Sym indirect_child;
      82  
      83  void alpha_find_call (Sym *, bfd_vma, bfd_vma);
      84  
      85  /*
      86   * On the Alpha we can only detect PC relative calls, which are
      87   * usually generated for calls to functions within the same
      88   * object file only.  This is still better than nothing, however.
      89   * (In particular it should be possible to find functions that
      90   *  potentially call integer division routines, for example.)
      91   */
      92  void
      93  alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
      94  {
      95    bfd_vma pc, dest_pc;
      96    unsigned int insn;
      97    Sym *child;
      98  
      99    if (indirect_child.name == NULL)
     100      {
     101        sym_init (&indirect_child);
     102        indirect_child.name = _("<indirect child>");
     103        indirect_child.cg.prop.fract = 1.0;
     104        indirect_child.cg.cyc.head = &indirect_child;
     105      }
     106  
     107    DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
     108  			  parent->name, (unsigned long) p_lowpc,
     109  			  (unsigned long) p_highpc));
     110    for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
     111      {
     112        insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
     113  				    + pc - core_text_sect->vma));
     114        switch (insn & (0x3fU << 26))
     115  	{
     116  	case OP_Jxx << 26:
     117  	  /*
     118  	   * There is no simple and reliable way to determine the
     119  	   * target of a jsr (the hint bits help, but there aren't
     120  	   * enough bits to get a satisfactory hit rate).  Instead,
     121  	   * for any indirect jump we simply add an arc from PARENT
     122  	   * to INDIRECT_CHILD---that way the user it at least able
     123  	   * to see that there are other calls as well.
     124  	   */
     125  	  if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
     126  	      || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14)
     127  	    {
     128  	      DBG (CALLDEBUG,
     129  		   printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),
     130  			   (unsigned long) pc,
     131  			   ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
     132  			    ? "" : "_coroutine")));
     133  	      arc_add (parent, &indirect_child, (unsigned long) 0);
     134  	    }
     135  	  break;
     136  
     137  	case OP_BSR << 26:
     138  	  DBG (CALLDEBUG,
     139  	       printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc));
     140  	  /*
     141  	   * Regular PC relative addressing.  Check that this is the
     142  	   * address of a function.  The linker sometimes redirects
     143  	   * the entry point by 8 bytes to skip loading the global
     144  	   * pointer, so we allow for either address:
     145  	   */
     146  	  dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff)
     147  			       ^ 0x100000) - 0x100000);
     148  	  if (hist_check_address (dest_pc))
     149  	    {
     150  	      child = sym_lookup (&symtab, dest_pc);
     151                if (child)
     152                  {
     153  	          DBG (CALLDEBUG,
     154  		       printf (" 0x%lx\t; name=%s, addr=0x%lx",
     155  			       (unsigned long) dest_pc, child->name,
     156  			       (unsigned long) child->addr));
     157  	          if (child->addr == dest_pc || child->addr == dest_pc - 8)
     158  		    {
     159  		      DBG (CALLDEBUG, printf ("\n"));
     160  		      /* a hit:  */
     161  		      arc_add (parent, child, (unsigned long) 0);
     162  		      continue;
     163  		    }
     164                  }
     165  	    }
     166  	  /*
     167  	   * Something funny going on.
     168  	   */
     169  	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
     170  	  break;
     171  
     172  	default:
     173  	  break;
     174  	}
     175      }
     176  }