2004-03-23 Andrew Cagney <cagney@redhat.com>
* tramp-frame.h, tramp-frame.h: New files. * Makefile.in (SFILES, tramp_frame_h, COMMON_OBS, tramp-frame.o): Update rules to include "tramp-frame.h" and "tramp-frame.c".
This commit is contained in:
parent
8050c72f30
commit
d2259dd367
@ -1,5 +1,9 @@
|
||||
2004-03-23 Andrew Cagney <cagney@redhat.com>
|
||||
|
||||
* tramp-frame.h, tramp-frame.h: New files.
|
||||
* Makefile.in (SFILES, tramp_frame_h, COMMON_OBS, tramp-frame.o):
|
||||
Update rules to include "tramp-frame.h" and "tramp-frame.c".
|
||||
|
||||
* Makefile.in: Update all dependencies.
|
||||
|
||||
2004-03-23 Andrew Cagney <cagney@redhat.com>
|
||||
|
@ -541,6 +541,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
||||
stabsread.c stack.c std-regs.c symfile.c symmisc.c symtab.c \
|
||||
target.c thread.c top.c tracepoint.c \
|
||||
trad-frame.c \
|
||||
tramp-frame.c \
|
||||
typeprint.c \
|
||||
ui-out.c utils.c ui-file.h ui-file.c \
|
||||
user-regs.c \
|
||||
@ -757,6 +758,7 @@ terminal_h = terminal.h
|
||||
top_h = top.h
|
||||
tracepoint_h = tracepoint.h
|
||||
trad_frame_h = trad-frame.h $(frame_h)
|
||||
tramp_frame_h = tramp-frame.h
|
||||
typeprint_h = typeprint.h
|
||||
ui_file_h = ui-file.h
|
||||
ui_out_h = ui-out.h
|
||||
@ -905,7 +907,8 @@ COMMON_OBS = $(DEPFILES) $(YYOBJ) \
|
||||
gnu-v2-abi.o gnu-v3-abi.o hpacc-abi.o cp-abi.o cp-support.o \
|
||||
cp-namespace.o \
|
||||
reggroups.o \
|
||||
trad-frame.o
|
||||
trad-frame.o \
|
||||
tramp-frame.o
|
||||
|
||||
TSOBS = inflow.o
|
||||
|
||||
@ -2444,6 +2447,9 @@ tracepoint.o: tracepoint.c $(defs_h) $(symtab_h) $(frame_h) $(gdbtypes_h) \
|
||||
$(readline_history_h)
|
||||
trad-frame.o: trad-frame.c $(defs_h) $(frame_h) $(trad_frame_h) \
|
||||
$(regcache_h)
|
||||
tramp-frame.o: tramp-frame.c $(defs_h) $(tramp_frame_h) $(frame_unwind_h) \
|
||||
$(gdbcore_h) $(symtab_h) $(objfiles_h) $(target_h) $(trad_frame_h) \
|
||||
$(frame_base_h)
|
||||
typeprint.o: typeprint.c $(defs_h) $(gdb_obstack_h) $(bfd_h) $(symtab_h) \
|
||||
$(gdbtypes_h) $(expression_h) $(value_h) $(gdbcore_h) $(command_h) \
|
||||
$(gdbcmd_h) $(target_h) $(language_h) $(cp_abi_h) $(typeprint_h) \
|
||||
|
162
gdb/tramp-frame.c
Normal file
162
gdb/tramp-frame.c
Normal file
@ -0,0 +1,162 @@
|
||||
/* Signal trampoline unwinder, for GDB the GNU Debugger.
|
||||
|
||||
Copyright 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "tramp-frame.h"
|
||||
#include "frame-unwind.h"
|
||||
#include "gdbcore.h"
|
||||
#include "symtab.h"
|
||||
#include "objfiles.h"
|
||||
#include "target.h"
|
||||
#include "trad-frame.h"
|
||||
#include "frame-base.h"
|
||||
|
||||
struct frame_data
|
||||
{
|
||||
const struct tramp_frame *tramp_frame;
|
||||
};
|
||||
|
||||
struct tramp_frame_cache
|
||||
{
|
||||
CORE_ADDR func;
|
||||
const struct tramp_frame *tramp_frame;
|
||||
struct trad_frame_cache *trad_cache;
|
||||
};
|
||||
|
||||
static struct trad_frame_cache *
|
||||
tramp_frame_cache (struct frame_info *next_frame,
|
||||
void **this_cache)
|
||||
{
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
struct tramp_frame_cache *tramp_cache = (*this_cache);
|
||||
if (tramp_cache->trad_cache == NULL)
|
||||
{
|
||||
tramp_cache->trad_cache = trad_frame_cache_zalloc (next_frame);
|
||||
tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
|
||||
next_frame,
|
||||
tramp_cache->trad_cache,
|
||||
tramp_cache->func);
|
||||
}
|
||||
return tramp_cache->trad_cache;
|
||||
}
|
||||
|
||||
static void
|
||||
tramp_frame_this_id (struct frame_info *next_frame,
|
||||
void **this_cache,
|
||||
struct frame_id *this_id)
|
||||
{
|
||||
struct trad_frame_cache *trad_cache
|
||||
= tramp_frame_cache (next_frame, this_cache);
|
||||
trad_frame_get_id (trad_cache, this_id);
|
||||
}
|
||||
|
||||
static void
|
||||
tramp_frame_prev_register (struct frame_info *next_frame,
|
||||
void **this_cache,
|
||||
int prev_regnum,
|
||||
int *optimizedp,
|
||||
enum lval_type * lvalp,
|
||||
CORE_ADDR *addrp,
|
||||
int *realnump, void *valuep)
|
||||
{
|
||||
struct trad_frame_cache *trad_cache
|
||||
= tramp_frame_cache (next_frame, this_cache);
|
||||
trad_frame_get_register (trad_cache, next_frame, prev_regnum, optimizedp,
|
||||
lvalp, addrp, realnump, valuep);
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
tramp_frame_start (CORE_ADDR pc, const struct tramp_frame *tramp)
|
||||
{
|
||||
int ti;
|
||||
/* Search through the trampoline for one that matches the
|
||||
instruction sequence around PC. */
|
||||
for (ti = 0; tramp->insn[ti] != 0; ti++)
|
||||
{
|
||||
CORE_ADDR func = pc - tramp->insn_size * ti;
|
||||
int i;
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
bfd_byte buf[sizeof (LONGEST)];
|
||||
CORE_ADDR insn;
|
||||
if (tramp->insn[i] == 0)
|
||||
return func;
|
||||
if (target_read_memory (func + i * tramp->insn_size, buf,
|
||||
tramp->insn_size) != 0)
|
||||
break;
|
||||
insn = extract_unsigned_integer (buf, tramp->insn_size);
|
||||
if (tramp->insn[i] != insn)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Trampoline doesn't match. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tramp_frame_sniffer (const struct frame_unwind *self,
|
||||
struct frame_info *next_frame,
|
||||
void **this_cache)
|
||||
{
|
||||
const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
|
||||
CORE_ADDR pc = frame_pc_unwind (next_frame);
|
||||
CORE_ADDR func;
|
||||
char *name;
|
||||
struct tramp_frame_cache *tramp_cache;
|
||||
|
||||
/* If the function has a valid symbol name, it isn't a
|
||||
trampoline. */
|
||||
find_pc_partial_function (pc, &name, NULL, NULL);
|
||||
if (name != NULL)
|
||||
return 0;
|
||||
/* If the function lives in a valid section (even without a starting
|
||||
point) it isn't a trampoline. */
|
||||
if (find_pc_section (pc) != NULL)
|
||||
return 0;
|
||||
/* Finally, check that the trampoline matches at PC. */
|
||||
func = tramp_frame_start (pc, tramp);
|
||||
if (func == 0)
|
||||
return 0;
|
||||
tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
|
||||
tramp_cache->func = func;
|
||||
tramp_cache->tramp_frame = tramp;
|
||||
(*this_cache) = tramp_cache;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
tramp_frame_append (struct gdbarch *gdbarch,
|
||||
const struct tramp_frame *tramp_frame)
|
||||
{
|
||||
struct frame_data *data;
|
||||
struct frame_unwind *unwinder;
|
||||
|
||||
data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
|
||||
unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);
|
||||
|
||||
data->tramp_frame = tramp_frame;
|
||||
unwinder->type = SIGTRAMP_FRAME;
|
||||
unwinder->unwind_data = data;
|
||||
unwinder->sniffer = tramp_frame_sniffer;
|
||||
unwinder->this_id = tramp_frame_this_id;
|
||||
unwinder->prev_register = tramp_frame_prev_register;
|
||||
frame_unwind_register_unwinder (gdbarch, unwinder);
|
||||
}
|
64
gdb/tramp-frame.h
Normal file
64
gdb/tramp-frame.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* Signal trampoline unwinder, for GDB the GNU Debugger.
|
||||
|
||||
Copyright 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef TRAMP_FRAME_H
|
||||
#define TRAMP_FRAME_H
|
||||
|
||||
struct trad_frame;
|
||||
struct frame_info;
|
||||
struct trad_frame_cache;
|
||||
|
||||
/* A trampoline consists of a small sequence of instructions placed at
|
||||
an unspecified location in the inferior's address space. The only
|
||||
identifying attribute of the trampoline's address is that it does
|
||||
not fall inside an object file's section.
|
||||
|
||||
The only way to identify a trampoline is to perform a brute force
|
||||
examination of the instructions at and around the PC.
|
||||
|
||||
This module provides a convent interface for performing that
|
||||
operation. */
|
||||
|
||||
/* A trampoline descriptor. */
|
||||
|
||||
struct tramp_frame
|
||||
{
|
||||
/* The trampoline's entire instruction sequence. Search for this in
|
||||
the inferior at or around the frame's PC. It is assumed that the
|
||||
PC is INSN_SIZE aligned, and that each element of TRAMP contains
|
||||
one INSN_SIZE instruction. It is also assumed that TRAMP[0]
|
||||
contains the first instruction of the trampoline and hence the
|
||||
address of the instruction matching TRAMP[0] is the trampoline's
|
||||
"func" address. */
|
||||
int insn_size;
|
||||
ULONGEST insn[8];
|
||||
/* Initialize a trad-frame cache corresponding to the tramp-frame.
|
||||
FUNC is the address of the instruction TRAMP[0] in memory. */
|
||||
void (*init) (const struct tramp_frame *self,
|
||||
struct frame_info *next_frame,
|
||||
struct trad_frame_cache *this_cache,
|
||||
CORE_ADDR func);
|
||||
};
|
||||
|
||||
void tramp_frame_append (struct gdbarch *gdbarch,
|
||||
const struct tramp_frame *tramp);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user