(linenum→info "unix/slp.c:2238")

binutils/2.18/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  0x1a
   41: #define OP_BSR  0x34
   42: 
   43: #define Jxx_FUNC_JMP            0
   44: #define Jxx_FUNC_JSR            1
   45: #define Jxx_FUNC_RET            2
   46: #define Jxx_FUNC_JSR_COROUTINE  3
   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 & (0x3f << 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:               DBG (CALLDEBUG,
  152:                    printf (" 0x%lx\t; name=%s, addr=0x%lx",
  153:                            (unsigned long) dest_pc, child->name,
  154:                            (unsigned long) child->addr));
  155:               if (child->addr == dest_pc || child->addr == dest_pc - 8)
  156:                 {
  157:                   DBG (CALLDEBUG, printf ("\n"));
  158:                   /* a hit:  */
  159:                   arc_add (parent, child, (unsigned long) 0);
  160:                   continue;
  161:                 }
  162:             }
  163:           /*
  164:            * Something funny going on.
  165:            */
  166:           DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
  167:           break;
  168: 
  169:         default:
  170:           break;
  171:         }
  172:     }
  173: }
Syntax (Markdown)