2
* Copyright (c) 1983, 1993, 2001
3
* The Regents of the University of California. All rights reserved.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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
30
#include "search_list.h"
38
* opcode of the `calls' instruction
43
* register for pc relative addressing
49
literal, indexed, reg, regdef, autodec, autoinc, autoincdef,
50
bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef,
51
immediate, absolute, byterel, bytereldef, wordrel, wordreldef,
54
typedef enum opermodes operandenum;
57
/* Here to document only. We can't use this when cross compiling as
58
the bitfield layout might not be the same as native.
62
unsigned int regfield:4;
63
unsigned int modefield:4;
69
* A symbol to be the child of indirect calls:
71
static Sym indirectchild;
73
static operandenum vax_operandmode (unsigned char *);
74
static char *vax_operandname (operandenum);
75
static long vax_operandlength (unsigned char *);
76
static bfd_signed_vma vax_offset (unsigned char *);
77
void vax_find_call (Sym *, bfd_vma, bfd_vma);
80
vax_operandmode (unsigned char *modep)
82
int usesreg = *modep & 0xf;
84
switch ((*modep >> 4) & 0xf)
100
return usesreg != PC ? autoinc : immediate;
102
return usesreg != PC ? autoincdef : absolute;
104
return usesreg != PC ? bytedisp : byterel;
106
return usesreg != PC ? bytedispdef : bytereldef;
108
return usesreg != PC ? worddisp : wordrel;
110
return usesreg != PC ? worddispdef : wordreldef;
112
return usesreg != PC ? longdisp : longrel;
114
return usesreg != PC ? longdispdef : longreldef;
121
vax_operandname (operandenum mode)
133
return "register deferred";
135
return "autodecrement";
137
return "autoincrement";
139
return "autoincrement deferred";
141
return "byte displacement";
143
return "byte displacement deferred";
145
return "byte relative";
147
return "byte relative deferred";
149
return "word displacement";
151
return "word displacement deferred";
153
return "word relative";
155
return "word relative deferred";
161
return "long displacement";
163
return "long displacement deferred";
165
return "long relative";
167
return "long relative deferred";
174
vax_operandlength (unsigned char *modep)
177
switch (vax_operandmode (modep))
204
return 1 + vax_operandlength (modep + 1);
210
static bfd_signed_vma
211
vax_offset (unsigned char *modep)
213
operandenum mode = vax_operandmode (modep);
215
++modep; /* skip over the mode */
219
fprintf (stderr, "[reladdr] not relative address\n");
222
return 1 + bfd_get_signed_8 (core_bfd, modep);
224
return 2 + bfd_get_signed_16 (core_bfd, modep);
226
return 4 + bfd_get_signed_32 (core_bfd, modep);
232
vax_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
234
unsigned char *instructp;
238
operandenum firstmode;
240
static bfd_boolean inited = FALSE;
245
sym_init (&indirectchild);
246
indirectchild.cg.prop.fract = 1.0;
247
indirectchild.cg.cyc.head = &indirectchild;
250
DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
251
parent->name, (unsigned long) p_lowpc,
252
(unsigned long) p_highpc));
253
for (pc = p_lowpc; pc < p_highpc; pc += length)
256
instructp = ((unsigned char *) core_text_space
257
+ pc - core_text_sect->vma);
258
if ((*instructp & 0xff) == CALLS)
261
* maybe a calls, better check it out.
262
* skip the count of the number of arguments.
265
printf ("[findcall]\t0x%lx:calls", (unsigned long) pc));
266
firstmode = vax_operandmode (instructp + length);
275
length += vax_operandlength (instructp + length);
276
mode = vax_operandmode (instructp + length);
278
printf ("\tfirst operand is %s", vax_operandname (firstmode));
279
printf ("\tsecond operand is %s\n", vax_operandname (mode)));
290
* indirect call: call through pointer
291
* either *d(r) as a parameter or local
292
* (r) as a return value
293
* *f as a global pointer
294
* [are there others that we miss?,
295
* e.g. arrays of pointers to functions???]
297
arc_add (parent, &indirectchild, (unsigned long) 0);
298
length += vax_operandlength (instructp + length);
304
* regular pc relative addressing
305
* check that this is the address of
308
destpc = pc + vax_offset (instructp + length);
309
if (hist_check_address (destpc))
311
child = sym_lookup (&symtab, destpc);
315
printf ("[findcall]\tdestpc 0x%lx",
316
(unsigned long) destpc);
317
printf (" child->name %s", child->name);
318
printf (" child->addr 0x%lx\n",
319
(unsigned long) child->addr);
321
if (child->addr == destpc)
326
arc_add (parent, child, (unsigned long) 0);
327
length += vax_operandlength (instructp + length);
335
* it looked like a calls,
336
* but it wasn't to anywhere.
342
* something funny going on.
344
DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n"));