xref: /openbsd-src/gnu/usr.bin/binutils/gprof/i386.c (revision c074d1c999f3e07019cd5e9a2f190b057ef3b935)
12159047fSniklas /*
26e421504Sfgsch  * Copyright (c) 1983, 1993, 2001
36e421504Sfgsch  *      The Regents of the University of California.  All rights reserved.
42159047fSniklas  *
56e421504Sfgsch  * Redistribution and use in source and binary forms, with or without
66e421504Sfgsch  * modification, are permitted provided that the following conditions
76e421504Sfgsch  * are met:
86e421504Sfgsch  * 1. Redistributions of source code must retain the above copyright
96e421504Sfgsch  *    notice, this list of conditions and the following disclaimer.
106e421504Sfgsch  * 2. Redistributions in binary form must reproduce the above copyright
116e421504Sfgsch  *    notice, this list of conditions and the following disclaimer in the
126e421504Sfgsch  *    documentation and/or other materials provided with the distribution.
136e421504Sfgsch  * 3. Neither the name of the University nor the names of its contributors
146e421504Sfgsch  *    may be used to endorse or promote products derived from this software
156e421504Sfgsch  *    without specific prior written permission.
166e421504Sfgsch  *
176e421504Sfgsch  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
186e421504Sfgsch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
196e421504Sfgsch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
206e421504Sfgsch  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
216e421504Sfgsch  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
226e421504Sfgsch  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
236e421504Sfgsch  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
246e421504Sfgsch  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
256e421504Sfgsch  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
266e421504Sfgsch  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
276e421504Sfgsch  * SUCH DAMAGE.
282159047fSniklas  */
292159047fSniklas #include "gprof.h"
30*c074d1c9Sdrahn #include "search_list.h"
31*c074d1c9Sdrahn #include "source.h"
32*c074d1c9Sdrahn #include "symtab.h"
332159047fSniklas #include "cg_arcs.h"
34f7cc78ecSespie #include "corefile.h"
352159047fSniklas #include "hist.h"
362159047fSniklas 
37*c074d1c9Sdrahn static int i386_iscall PARAMS ((unsigned char *));
38*c074d1c9Sdrahn void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
392159047fSniklas 
40*c074d1c9Sdrahn static int
i386_iscall(ip)41*c074d1c9Sdrahn i386_iscall (ip)
42*c074d1c9Sdrahn      unsigned char *ip;
432159047fSniklas {
44f7cc78ecSespie   if (*ip == 0xe8)
452159047fSniklas     return 1;
462159047fSniklas   return 0;
472159047fSniklas }
482159047fSniklas 
492159047fSniklas 
502159047fSniklas void
i386_find_call(parent,p_lowpc,p_highpc)51f7cc78ecSespie i386_find_call (parent, p_lowpc, p_highpc)
522159047fSniklas      Sym *parent;
532159047fSniklas      bfd_vma p_lowpc;
542159047fSniklas      bfd_vma p_highpc;
552159047fSniklas {
562159047fSniklas   unsigned char *instructp;
572159047fSniklas   Sym *child;
58*c074d1c9Sdrahn   bfd_vma pc, destpc;
592159047fSniklas 
602159047fSniklas   if (core_text_space == 0)
612159047fSniklas     {
622159047fSniklas       return;
632159047fSniklas     }
642159047fSniklas   if (p_lowpc < s_lowpc)
652159047fSniklas     {
662159047fSniklas       p_lowpc = s_lowpc;
672159047fSniklas     }
682159047fSniklas   if (p_highpc > s_highpc)
692159047fSniklas     {
702159047fSniklas       p_highpc = s_highpc;
712159047fSniklas     }
722159047fSniklas   DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
73f7cc78ecSespie 			  parent->name, (unsigned long) p_lowpc,
74f7cc78ecSespie 			  (unsigned long) p_highpc));
75f7cc78ecSespie 
76*c074d1c9Sdrahn   for (pc = p_lowpc; pc < p_highpc; ++pc)
772159047fSniklas     {
78*c074d1c9Sdrahn       instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
79f7cc78ecSespie       if (i386_iscall (instructp))
802159047fSniklas 	{
812159047fSniklas 	  DBG (CALLDEBUG,
82*c074d1c9Sdrahn 	       printf ("[findcall]\t0x%lx:call", (unsigned long) pc));
832159047fSniklas 	  /*
842159047fSniklas 	   *  regular pc relative addressing
852159047fSniklas 	   *    check that this is the address of
862159047fSniklas 	   *    a function.
872159047fSniklas 	   */
88f7cc78ecSespie 
89*c074d1c9Sdrahn 	  destpc = bfd_get_32 (core_bfd, instructp + 1) + pc + 5;
902159047fSniklas 	  if (destpc >= s_lowpc && destpc <= s_highpc)
912159047fSniklas 	    {
922159047fSniklas 	      child = sym_lookup (&symtab, destpc);
93f7cc78ecSespie 	      if (child && child->addr == destpc)
942159047fSniklas 		{
952159047fSniklas 		  /*
962159047fSniklas 		   *      a hit
972159047fSniklas 		   */
98f7cc78ecSespie 		  DBG (CALLDEBUG,
99f7cc78ecSespie 		       printf ("\tdestpc 0x%lx (%s)\n",
100f7cc78ecSespie 			       (unsigned long) destpc, child->name));
101f7cc78ecSespie 		  arc_add (parent, child, (unsigned long) 0);
102f7cc78ecSespie 		  instructp += 4;	/* call is a 5 byte instruction */
1032159047fSniklas 		  continue;
1042159047fSniklas 		}
1052159047fSniklas 	    }
1062159047fSniklas 	  /*
1072159047fSniklas 	   *  else:
108f7cc78ecSespie 	   *    it looked like a callf, but it:
109f7cc78ecSespie 	   *      a) wasn't actually a callf, or
110f7cc78ecSespie 	   *      b) didn't point to a known function in the symtab, or
111f7cc78ecSespie 	   *      c) something funny is going on.
1122159047fSniklas 	   */
113f7cc78ecSespie 	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
1142159047fSniklas 	}
1152159047fSniklas     }
1162159047fSniklas }
117