Back to index

cell-binutils  2.17cvs20070401
alpha.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1983, 1993, 1998
00003  *      The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 #include "gprof.h"
00030 #include "search_list.h"
00031 #include "source.h"
00032 #include "symtab.h"
00033 #include "cg_arcs.h"
00034 #include "corefile.h"
00035 #include "hist.h"
00036 
00037 /*
00038  * Opcodes of the call instructions:
00039  */
00040 #define OP_Jxx       0x1a
00041 #define       OP_BSR 0x34
00042 
00043 #define Jxx_FUNC_JMP        0
00044 #define Jxx_FUNC_JSR        1
00045 #define Jxx_FUNC_RET        2
00046 #define Jxx_FUNC_JSR_COROUTINE     3
00047 
00048 /* *INDENT-OFF* */
00049 /* Here to document only.  We can't use this when cross compiling as
00050    the bitfield layout might not be the same as native.
00051 
00052    typedef union
00053      {
00054        struct
00055          {
00056           unsigned other:26;
00057           unsigned op_code:6;
00058          }
00059        a;                          -- any format
00060        struct
00061          {
00062           int disp:21;
00063           unsigned ra:5;
00064           unsigned op_code:6;
00065          }
00066        b;                          -- branch format
00067        struct
00068          {
00069           int hint:14;
00070           unsigned func:2;
00071           unsigned rb:5;
00072           unsigned ra:5;
00073           unsigned op_code:6;
00074          }
00075        j;                          -- jump format
00076      }
00077     alpha_Instruction;
00078 */
00079 /* *INDENT-ON* */
00080 
00081 static Sym indirect_child;
00082 
00083 void alpha_find_call (Sym *, bfd_vma, bfd_vma);
00084 
00085 /*
00086  * On the Alpha we can only detect PC relative calls, which are
00087  * usually generated for calls to functions within the same
00088  * object file only.  This is still better than nothing, however.
00089  * (In particular it should be possible to find functions that
00090  *  potentially call integer division routines, for example.)
00091  */
00092 void
00093 alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
00094 {
00095   bfd_vma pc, dest_pc;
00096   unsigned int insn;
00097   Sym *child;
00098 
00099   if (indirect_child.name == NULL)
00100     {
00101       sym_init (&indirect_child);
00102       indirect_child.name = _("<indirect child>");
00103       indirect_child.cg.prop.fract = 1.0;
00104       indirect_child.cg.cyc.head = &indirect_child;
00105     }
00106 
00107   if (!core_text_space)
00108     {
00109       return;
00110     }
00111   if (p_lowpc < s_lowpc)
00112     {
00113       p_lowpc = s_lowpc;
00114     }
00115   if (p_highpc > s_highpc)
00116     {
00117       p_highpc = s_highpc;
00118     }
00119   DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
00120                        parent->name, (unsigned long) p_lowpc,
00121                        (unsigned long) p_highpc));
00122   for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
00123     {
00124       insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
00125                                 + pc - core_text_sect->vma));
00126       switch (insn & (0x3f << 26))
00127        {
00128        case OP_Jxx << 26:
00129          /*
00130           * There is no simple and reliable way to determine the
00131           * target of a jsr (the hint bits help, but there aren't
00132           * enough bits to get a satisfactory hit rate).  Instead,
00133           * for any indirect jump we simply add an arc from PARENT
00134           * to INDIRECT_CHILD---that way the user it at least able
00135           * to see that there are other calls as well.
00136           */
00137          if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
00138              || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14)
00139            {
00140              DBG (CALLDEBUG,
00141                  printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),
00142                         (unsigned long) pc,
00143                         ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
00144                          ? "" : "_coroutine")));
00145              arc_add (parent, &indirect_child, (unsigned long) 0);
00146            }
00147          break;
00148 
00149        case OP_BSR << 26:
00150          DBG (CALLDEBUG,
00151               printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc));
00152          /*
00153           * Regular PC relative addressing.  Check that this is the
00154           * address of a function.  The linker sometimes redirects
00155           * the entry point by 8 bytes to skip loading the global
00156           * pointer, so we allow for either address:
00157           */
00158          dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff)
00159                             ^ 0x100000) - 0x100000);
00160          if (dest_pc >= s_lowpc && dest_pc <= s_highpc)
00161            {
00162              child = sym_lookup (&symtab, dest_pc);
00163              DBG (CALLDEBUG,
00164                  printf (" 0x%lx\t; name=%s, addr=0x%lx",
00165                         (unsigned long) dest_pc, child->name,
00166                         (unsigned long) child->addr));
00167              if (child->addr == dest_pc || child->addr == dest_pc - 8)
00168               {
00169                 DBG (CALLDEBUG, printf ("\n"));
00170                 /* a hit:  */
00171                 arc_add (parent, child, (unsigned long) 0);
00172                 continue;
00173               }
00174            }
00175          /*
00176           * Something funny going on.
00177           */
00178          DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
00179          break;
00180 
00181        default:
00182          break;
00183        }
00184     }
00185 }