* hppa-tdep.c (in_solib_call_trampoline): Recognize calls through

_sr4export and $$dyncall as trampolines.  Likewise for long-call
	stubs and parameter relocation stubs.
	(in_solib_return_trampoline): Recognize a return trampoline for
	return value relocation stubs.
This commit is contained in:
Jeff Law 1994-11-25 09:21:49 +00:00
parent 2848f79344
commit a76c22401c
2 changed files with 135 additions and 27 deletions

View File

@ -1,5 +1,11 @@
Fri Nov 25 00:51:05 1994 Jeff Law (law@snake.cs.utah.edu) Fri Nov 25 00:51:05 1994 Jeff Law (law@snake.cs.utah.edu)
* hppa-tdep.c (in_solib_call_trampoline): Recognize calls through
_sr4export and $$dyncall as trampolines. Likewise for long-call
stubs and parameter relocation stubs.
(in_solib_return_trampoline): Recognize a return trampoline for
return value relocation stubs.
* hpread.c: Include hp-symtab.h instead of hpux-symtab.h. * hpread.c: Include hp-symtab.h instead of hpux-symtab.h.
Various name changes to match those used by hp-symtab.h. Various name changes to match those used by hp-symtab.h.

View File

@ -1572,8 +1572,10 @@ pa_print_fp_reg (i)
} }
} }
/* Return one if PC is in the call path of a shared library trampoline, else /* Return one if PC is in the call path of a trampoline, else return zero.
return zero. */
Note we return one for *any* call trampoline (long-call, arg-reloc), not
just shared library trampolines (import, export). */
in_solib_call_trampoline (pc, name) in_solib_call_trampoline (pc, name)
CORE_ADDR pc; CORE_ADDR pc;
@ -1581,6 +1583,33 @@ in_solib_call_trampoline (pc, name)
{ {
struct minimal_symbol *minsym; struct minimal_symbol *minsym;
struct unwind_table_entry *u; struct unwind_table_entry *u;
static CORE_ADDR dyncall = 0;
static CORE_ADDR sr4export = 0;
/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
new exec file */
/* First see if PC is in one of the two C-library trampolines. */
if (!dyncall)
{
minsym = lookup_minimal_symbol ("$$dyncall", NULL);
if (minsym)
dyncall = SYMBOL_VALUE_ADDRESS (minsym);
else
dyncall = -1;
}
if (!sr4export)
{
minsym = lookup_minimal_symbol ("_sr4export", NULL);
if (minsym)
sr4export = SYMBOL_VALUE_ADDRESS (minsym);
else
sr4export = -1;
}
if (pc == dyncall || pc == sr4export)
return 1;
/* Get the unwind descriptor corresponding to PC, return zero /* Get the unwind descriptor corresponding to PC, return zero
if no unwind was found. */ if no unwind was found. */
@ -1589,31 +1618,69 @@ in_solib_call_trampoline (pc, name)
return 0; return 0;
/* If this isn't a linker stub, then return now. */ /* If this isn't a linker stub, then return now. */
if (u->stub_type != IMPORT if (u->stub_type == 0)
&& u->stub_type != EXPORT)
return 0; return 0;
/* By definition a long-branch stub is a call stub. */
if (u->stub_type == LONG_BRANCH)
return 1;
/* The call and return path execute the same instructions within /* The call and return path execute the same instructions within
an IMPORT stub! So an IMPORT stub is both a call and return an IMPORT stub! So an IMPORT stub is both a call and return
trampoline. */ trampoline. */
if (u->stub_type == IMPORT) if (u->stub_type == IMPORT)
return 1; return 1;
/* The linker may group many EXPORT stubs into one unwind entry. So if (u->stub_type == EXPORT)
lookup the minimal symbol and use that as the beginning of this {
particular stub. */ /* The linker may group many EXPORT stubs into one unwind entry. So
minsym = lookup_minimal_symbol_by_pc (pc); lookup the minimal symbol and use that as the beginning of this
if (minsym == NULL) particular stub. */
return 0; minsym = lookup_minimal_symbol_by_pc (pc);
if (minsym == NULL)
return 0;
/* Export stubs have distinct call and return paths. The first /* Export stubs have distinct call and return paths. The first
two instructions are the call path, following four are the two instructions are the call path, following four are the
return path. */
return (pc >= SYMBOL_VALUE (minsym) && pc < SYMBOL_VALUE (minsym) + 8);
}
/* Parameter relocation stubs always have a call path and may have a
return path. */ return path. */
return (pc >= SYMBOL_VALUE (minsym) && pc < SYMBOL_VALUE (minsym) + 8); if (u->stub_type == PARAMETER_RELOCATION)
{
CORE_ADDR addr;
/* Search forward from the current PC until we hit a branch
or the end of the stub. */
for (addr = pc; addr <= u->region_end; addr += 4)
{
unsigned long insn;
insn = read_memory_integer (addr, 4);
/* Does it look like a bl? If so then it's the call path, if
we find a bv first, then we're on the return path. */
if ((insn & 0xfc00e000) == 0xe8000000)
return 1;
else if ((insn & 0xfc00e001) == 0xe800c000)
return 0;
}
/* Should never happen. */
warning ("Unable to find branch in parameter relocation stub.\n");
return 0;
}
/* Unknown stub type. For now, just return zero. */
return 0;
} }
/* Return one if PC is in the return path of a shared library trampoline, /* Return one if PC is in the return path of a trampoline, else return zero.
else return zero. */
Note we return one for *any* call trampoline (long-call, arg-reloc), not
just shared library trampolines (import, export). */
in_solib_return_trampoline (pc, name) in_solib_return_trampoline (pc, name)
CORE_ADDR pc; CORE_ADDR pc;
@ -1628,9 +1695,9 @@ in_solib_return_trampoline (pc, name)
if (!u) if (!u)
return 0; return 0;
/* If this isn't a linker stub, then return now. */ /* If this isn't a linker stub or it's just a long branch stub, then
if (u->stub_type != IMPORT return zero. */
&& u->stub_type != EXPORT) if (u->stub_type == 0 || u->stub_type == LONG_BRANCH)
return 0; return 0;
/* The call and return path execute the same instructions within /* The call and return path execute the same instructions within
@ -1639,17 +1706,52 @@ in_solib_return_trampoline (pc, name)
if (u->stub_type == IMPORT) if (u->stub_type == IMPORT)
return 1; return 1;
/* The linker may group many EXPORT stubs into one unwind entry. So if (u->stub_type == EXPORT)
lookup the minimal symbol and use that as the beginning of this {
particular stub. */ /* The linker may group many EXPORT stubs into one unwind entry. So
minsym = lookup_minimal_symbol_by_pc (pc); lookup the minimal symbol and use that as the beginning of this
if (minsym == NULL) particular stub. */
return 0; minsym = lookup_minimal_symbol_by_pc (pc);
if (minsym == NULL)
return 0;
/* Export stubs have distinct call and return paths. The first /* Export stubs have distinct call and return paths. The first
two instructions are the call path, following four are the two instructions are the call path, following four are the
return path. */
return (pc >= SYMBOL_VALUE (minsym) + 8
&& pc < SYMBOL_VALUE (minsym) + 20);
}
/* Parameter relocation stubs always have a call path and may have a
return path. */ return path. */
return (pc >= SYMBOL_VALUE (minsym) + 8 && pc < SYMBOL_VALUE (minsym) + 20); if (u->stub_type == PARAMETER_RELOCATION)
{
CORE_ADDR addr;
/* Search forward from the current PC until we hit a branch
or the end of the stub. */
for (addr = pc; addr <= u->region_end; addr += 4)
{
unsigned long insn;
insn = read_memory_integer (addr, 4);
/* Does it look like a bl? If so then it's the call path, if
we find a bv first, then we're on the return path. */
if ((insn & 0xfc00e000) == 0xe8000000)
return 0;
else if ((insn & 0xfc00e001) == 0xe800c000)
return 1;
}
/* Should never happen. */
warning ("Unable to find branch in parameter relocation stub.\n");
return 0;
}
/* Unknown stub type. For now, just return zero. */
return 0;
} }
/* Figure out if PC is in a trampoline, and if so find out where /* Figure out if PC is in a trampoline, and if so find out where