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