aboutsummaryrefslogtreecommitdiff
path: root/gprof/sparc.c
blob: 98e29ce8554c3472c3dee431649a7a5ac5236127 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that: (1) source distributions retain this entire copyright
 * notice and comment, and (2) distributions including binaries display
 * the following acknowledgement:  ``This product includes software
 * developed by the University of California, Berkeley and its contributors''
 * in the documentation or other materials provided with the distribution
 * and in all advertising materials mentioning features or use of this
 * software. Neither the name of the University nor the names of its
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
#include "gprof.h"
#include "cg_arcs.h"
#include "core.h"
#include "hist.h"
#include "symtab.h"


void
find_call(parent, p_lowpc, p_highpc)
     Sym *parent;
     bfd_vma p_lowpc;
     bfd_vma p_highpc;
{
    bfd_vma dest_pc, delta;
    unsigned int *instr;
    Sym *child;
    
    delta = (bfd_vma) core_text_space - core_text_sect->vma;
    
    if (core_text_space == 0) {
	return;
    } /* if */
    if (p_lowpc < s_lowpc) {
	p_lowpc = s_lowpc;
    } /* if */
    if (p_highpc > s_highpc) {
	p_highpc = s_highpc;
    } /* if */
    DBG(CALLDEBUG, printf("[find_call] %s: 0x%lx to 0x%lx\n",
			  parent->name, p_lowpc, p_highpc));
    for (instr = (unsigned int*)(p_lowpc + delta);
	 instr < (unsigned int*)(p_highpc + delta);
	 ++instr)
    {
	if ((*instr & CALL)) {
	    DBG(CALLDEBUG,
		printf("[find_call] 0x%lx: callf", (bfd_vma) instr - delta));
	    /*
	     * Regular pc relative addressing check that this is the
	     * address of a function.
	     */
	    dest_pc = ((bfd_vma) (instr + (*instr & ~CALL))) - delta;
	    if (dest_pc >= s_lowpc && dest_pc <= s_highpc) {
		child = sym_lookup(&symtab, dest_pc);
		DBG(CALLDEBUG,
		    printf("\tdest_pc=0x%lx, (name=%s, addr=0x%lx)\n",
			   dest_pc, child->name, child->addr));
		if (child->addr == dest_pc) {
		    /* a hit:  */
		    arc_add(parent, child, 0);
		    continue;
		} /* if */
	    } /* if */
	    /*
	     * Something funny going on.
	     */
	    DBG(CALLDEBUG, printf("\tbut it's a botch\n"));
	} /* if */
    } /* for */
} /* find_call */
			/*** end of sparc.c ***/