* i386.c (i386_iscall): Static.
[external/binutils.git] / gprof / i386.c
1 /*
2  * Copyright (c) 1983, 2001 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that: (1) source distributions retain this entire copyright
7  * notice and comment, and (2) distributions including binaries display
8  * the following acknowledgement:  ``This product includes software
9  * developed by the University of California, Berkeley and its contributors''
10  * in the documentation or other materials provided with the distribution
11  * and in all advertising materials mentioning features or use of this
12  * software. Neither the name of the University nor the names of its
13  * contributors may be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19 #include "gprof.h"
20 #include "cg_arcs.h"
21 #include "corefile.h"
22 #include "hist.h"
23 #include "symtab.h"
24
25 static int i386_iscall PARAMS ((unsigned char *));
26 void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
27
28 static int
29 i386_iscall (ip)
30      unsigned char *ip;
31 {
32   if (*ip == 0xe8)
33     return 1;
34   return 0;
35 }
36
37
38 void
39 i386_find_call (parent, p_lowpc, p_highpc)
40      Sym *parent;
41      bfd_vma p_lowpc;
42      bfd_vma p_highpc;
43 {
44   unsigned char *instructp;
45   Sym *child;
46   bfd_vma destpc, delta;
47
48   if (core_text_space == 0)
49     {
50       return;
51     }
52   if (p_lowpc < s_lowpc)
53     {
54       p_lowpc = s_lowpc;
55     }
56   if (p_highpc > s_highpc)
57     {
58       p_highpc = s_highpc;
59     }
60   DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
61                           parent->name, (unsigned long) p_lowpc,
62                           (unsigned long) p_highpc));
63
64   delta = (bfd_vma) core_text_space - core_text_sect->vma;
65
66   for (instructp = (unsigned char *) (p_lowpc + delta);
67        instructp < (unsigned char *) (p_highpc + delta);
68        instructp ++)
69     {
70       if (i386_iscall (instructp))
71         {
72           DBG (CALLDEBUG,
73                printf ("[findcall]\t0x%lx:call",
74                        (unsigned long) (instructp - (unsigned char *) delta)));
75           /*
76            *  regular pc relative addressing
77            *    check that this is the address of
78            *    a function.
79            */
80
81           destpc = ((bfd_vma) bfd_get_32 (core_bfd, instructp + 1)
82                     + (bfd_vma) instructp - (bfd_vma) delta + 5);
83           if (destpc >= s_lowpc && destpc <= s_highpc)
84             {
85               child = sym_lookup (&symtab, destpc);
86               if (child && child->addr == destpc)
87                 {
88                   /*
89                    *      a hit
90                    */
91                   DBG (CALLDEBUG,
92                        printf ("\tdestpc 0x%lx (%s)\n",
93                                (unsigned long) destpc, child->name));
94                   arc_add (parent, child, (unsigned long) 0);
95                   instructp += 4;       /* call is a 5 byte instruction */
96                   continue;
97                 }
98             }
99           /*
100            *  else:
101            *    it looked like a callf, but it:
102            *      a) wasn't actually a callf, or
103            *      b) didn't point to a known function in the symtab, or
104            *      c) something funny is going on.
105            */
106           DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
107         }
108     }
109 }