From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25349 invoked by alias); 22 Mar 2004 03:14:22 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 25337 invoked from network); 22 Mar 2004 03:14:20 -0000 Received: from unknown (HELO localhost.redhat.com) (66.30.197.194) by sources.redhat.com with SMTP; 22 Mar 2004 03:14:20 -0000 Received: from gnu.org (localhost [127.0.0.1]) by localhost.redhat.com (Postfix) with ESMTP id 84FAF2B9B; Sun, 21 Mar 2004 22:14:17 -0500 (EST) Message-ID: <405E5A09.2050803@gnu.org> Date: Mon, 22 Mar 2004 03:14:00 -0000 From: Andrew Cagney User-Agent: Mozilla/5.0 (X11; U; NetBSD macppc; en-GB; rv:1.4.1) Gecko/20040217 MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [patch/rfc] signal trampoline frames Content-Type: multipart/mixed; boundary="------------060906090405020500090201" X-SW-Source: 2004-03/txt/msg00490.txt.bz2 This is a multi-part message in MIME format. --------------060906090405020500090201 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 405 Hello, This adds "tramp-frame.[hc]" as a generic signal trampoline frame unwinder. The client architectures, per the revised change to ppcnbsd-tdep.c (it superseeds my original), just needs to provide the signal trampoline instruction sequence and a method to initialize the trad_frame_cache. Thoughts, I'll look to commit the tramp-frame parts in a few days. committed to my tramp branch, Andrew --------------060906090405020500090201 Content-Type: text/plain; name="diffs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="diffs" Content-length: 10938 2004-03-21 Andrew Cagney * 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 (ppcnbsd-tdep.o): Update dependencies. * ppcnbsd-tdep.c: Include "tramp-frame.h" and "trad-frame.h". (ppcnbsd_sigtramp_cache_init, ppcnbsd_sigtramp): Handle signal trampoline. (ppcnbsd_init_abi): Call tramp_frame_append with ppcnbsd_sigtramp. Index: ppcnbsd-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v retrieving revision 1.11 diff -u -r1.11 ppcnbsd-tdep.c --- ppcnbsd-tdep.c 10 Nov 2003 22:47:28 -0000 1.11 +++ ppcnbsd-tdep.c 22 Mar 2004 01:40:26 -0000 @@ -30,6 +30,8 @@ #include "ppc-tdep.h" #include "ppcnbsd-tdep.h" #include "nbsd-tdep.h" +#include "tramp-frame.h" +#include "trad-frame.h" #include "solib-svr4.h" @@ -228,6 +230,58 @@ } static void +ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *next_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + CORE_ADDR base; + CORE_ADDR offset; + int i; + struct gdbarch *gdbarch = get_frame_arch (next_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + base = frame_unwind_register_unsigned (next_frame, SP_REGNUM); + offset = base + 0x18 + 2 * tdep->wordsize; + for (i = 0; i < 32; i++) + { + int regnum = i + tdep->ppc_gp0_regnum; + trad_frame_set_reg_addr (this_cache, regnum, offset); + offset += tdep->wordsize; + } + trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, offset); + offset += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, offset); + offset += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, offset); + offset += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, offset); + offset += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, PC_REGNUM, offset); /* SRR0? */ + offset += tdep->wordsize; + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (base, func)); +} + +/* Given the NEXT frame, examine the instructions at and around this + frame's resume address (aka PC) to see of they look like a signal + trampoline. Return the address of the trampolines first + instruction, or zero if it isn't a signal trampoline. */ + +static const struct tramp_frame ppcnbsd_sigtramp = { + 4, /* insn size */ + { /* insn */ + 0x38610018, /* addi r3,r1,24 */ + 0x38000127, /* li r0,295 */ + 0x44000002, /* sc */ + 0x38000001, /* li r0,1 */ + 0x44000002, /* sc */ + }, + ppcnbsd_sigtramp_cache_init +}; + +static void ppcnbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -237,6 +291,7 @@ set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); set_solib_svr4_fetch_link_map_offsets (gdbarch, nbsd_ilp32_solib_svr4_fetch_link_map_offsets); + tramp_frame_append (gdbarch, &ppcnbsd_sigtramp); } void Index: tramp-frame.c =================================================================== RCS file: tramp-frame.c diff -N tramp-frame.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tramp-frame.c 22 Mar 2004 01:40:27 -0000 @@ -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); +} Index: tramp-frame.h =================================================================== RCS file: tramp-frame.h diff -N tramp-frame.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tramp-frame.h 21 Mar 2004 23:57:38 -0000 1.1.2.2 @@ -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 --------------060906090405020500090201--