diff options
author | Andrew Cagney <cagney@redhat.com> | 2004-03-11 21:59:53 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2004-03-11 21:59:53 +0000 |
commit | 794ec6cc80ead2c363ebe5dcc93148185be1f82a (patch) | |
tree | 343e2c4d7cb1d77a2c82c6ec7f2ce17a7b2f69dc | |
parent | 67f8f0bdebc23b61f6ca3b95fbd7c2ab46443863 (diff) | |
download | gdb-794ec6cc80ead2c363ebe5dcc93148185be1f82a.tar.gz |
New files.
-rw-r--r-- | gdb/tramp-frame.c | 111 | ||||
-rw-r--r-- | gdb/tramp-frame.h | 64 |
2 files changed, 175 insertions, 0 deletions
diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c new file mode 100644 index 00000000000..376ab364653 --- /dev/null +++ b/gdb/tramp-frame.c @@ -0,0 +1,111 @@ +/* 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 "trad-frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "symtab.h" +#include "objfiles.h" +#include "target.h" + +struct trad_frame_data +{ + const struct tramp_frame *tramp_frame; +}; + +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 void +tramp_frame_init (const struct trad_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + const struct tramp_frame *tramp = self->trad_data->tramp_frame; + tramp->init (tramp, next_frame, this_cache, tramp_frame_start (pc, tramp)); +} + +static int +tramp_frame_sniffer (const struct trad_frame *self, + struct frame_info *next_frame) +{ + const struct tramp_frame *tramp = self->trad_data->tramp_frame; + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + /* 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 NULL; + /* 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 NULL; + /* The problem here is that this code, and tramp_frame_cache, both + end up doing a search to find the function start :-(. */ + return (tramp_frame_start (pc, tramp) != 0); +} + +void +tramp_frame_append (struct gdbarch *gdbarch, + const struct tramp_frame *tramp) +{ + struct trad_frame_data *trad_data; + struct trad_frame *trad; + + trad_data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct trad_frame_data); + trad = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct trad_frame); + + trad_data->tramp_frame = tramp; + trad->type = SIGTRAMP_FRAME; + trad->trad_data = trad_data; + trad->sniffer = tramp_frame_sniffer; + trad->init = tramp_frame_init; + trad_frame_append (gdbarch, trad); +} diff --git a/gdb/tramp-frame.h b/gdb/tramp-frame.h new file mode 100644 index 00000000000..03eb35b866f --- /dev/null +++ b/gdb/tramp-frame.h @@ -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 trampline 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 convient 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 containts + 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 trampolines + "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 |