X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Falpha-linux-tdep.c;h=3c71f2f03cd419ba6f0b0debebb1b3f6166f45f0;hb=35aafff4acf2efeb7b039d7a944a51f952ad25f0;hp=519638ddb97fc320f4f599d818ba93530ca4b2c8;hpb=f1a559ae83066397c1367d2bcb30a47417d7634e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c index 519638ddb9..3c71f2f03c 100644 --- a/gdb/alpha-linux-tdep.c +++ b/gdb/alpha-linux-tdep.c @@ -1,11 +1,12 @@ /* Target-dependent code for GNU/Linux on Alpha. - Copyright 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010 + 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,21 +15,17 @@ 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. */ + along with this program. If not, see . */ #include "defs.h" #include "frame.h" -#include "frame-base.h" -#include "frame-unwind.h" -#include "dwarf2-frame.h" -#include "gdbcore.h" #include "gdb_assert.h" +#include "gdb_string.h" #include "osabi.h" +#include "solib-svr4.h" #include "symtab.h" -#include "symfile.h" -#include "value.h" +#include "regset.h" +#include "regcache.h" #include "alpha-tdep.h" @@ -48,9 +45,9 @@ */ static long -alpha_linux_sigtramp_offset_1 (CORE_ADDR pc) +alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc) { - switch (alpha_read_insn (pc)) + switch (alpha_read_insn (gdbarch, pc)) { case 0x47de0410: /* bis $30,$30,$16 */ case 0x47fe0410: /* bis $31,$30,$16 */ @@ -70,7 +67,7 @@ alpha_linux_sigtramp_offset_1 (CORE_ADDR pc) } static LONGEST -alpha_linux_sigtramp_offset (CORE_ADDR pc) +alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) { long i, off; @@ -78,7 +75,7 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) return -1; /* Guess where we might be in the sequence. */ - off = alpha_linux_sigtramp_offset_1 (pc); + off = alpha_linux_sigtramp_offset_1 (gdbarch, pc); if (off < 0) return -1; @@ -88,7 +85,7 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) { if (i == off) continue; - if (alpha_linux_sigtramp_offset_1 (pc + i) != i) + if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i) return -1; } @@ -96,22 +93,24 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) } static int -alpha_linux_pc_in_sigtramp (CORE_ADDR pc, char *func_name) +alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch, + CORE_ADDR pc, char *func_name) { - return alpha_linux_sigtramp_offset (pc) >= 0; + return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0; } static CORE_ADDR -alpha_linux_sigcontext_addr (struct frame_info *next_frame) +alpha_linux_sigcontext_addr (struct frame_info *this_frame) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR pc; ULONGEST sp; long off; - pc = frame_pc_unwind (next_frame); - frame_unwind_unsigned_register (next_frame, ALPHA_SP_REGNUM, &sp); + pc = get_frame_pc (this_frame); + sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM); - off = alpha_linux_sigtramp_offset (pc); + off = alpha_linux_sigtramp_offset (gdbarch, pc); gdb_assert (off >= 0); /* __NR_rt_sigreturn has a couple of structures on the stack. This is: @@ -123,36 +122,125 @@ alpha_linux_sigcontext_addr (struct frame_info *next_frame) offsetof (struct rt_sigframe, uc.uc_mcontext); */ - if (alpha_read_insn (pc - off + 4) == 0x201f015f) + if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f) return sp + 176; /* __NR_sigreturn has the sigcontext structure at the top of the stack. */ return sp; } +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +alpha_linux_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const gdb_byte *regs = gregs; + int i; + gdb_assert (len >= 32 * 8); + + for (i = 0; i < ALPHA_ZERO_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 8); + } + + if (regnum == ALPHA_PC_REGNUM || regnum == -1) + regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8); + + if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1) + regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM, + len >= 33 * 8 ? regs + 32 * 8 : NULL); +} + +/* Supply register REGNUM from the buffer specified by FPREGS and LEN + in the floating-point register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + static void -alpha_linux_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) +alpha_linux_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + const gdb_byte *regs = fpregs; + int i; + gdb_assert (len >= 32 * 8); + + for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8); + } + + if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) + regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8); +} + +static struct regset alpha_linux_gregset = +{ + NULL, + alpha_linux_supply_gregset +}; + +static struct regset alpha_linux_fpregset = +{ + NULL, + alpha_linux_supply_fpregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +static const struct regset * +alpha_linux_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) +{ + if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8) + return &alpha_linux_gregset; + + if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8) + return &alpha_linux_fpregset; + + return NULL; +} + +static void +alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep; /* Hook into the DWARF CFI frame unwinder. */ - frame_unwind_append_predicate (gdbarch, dwarf2_frame_p); - frame_base_append_predicate (gdbarch, dwarf2_frame_base_p); - set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); + alpha_dwarf2_init_abi (info, gdbarch); /* Hook into the MDEBUG frame unwinder. */ alpha_mdebug_init_abi (info, gdbarch); - set_gdbarch_pc_in_sigtramp (gdbarch, alpha_linux_pc_in_sigtramp); - tdep = gdbarch_tdep (gdbarch); tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset; tdep->sigcontext_addr = alpha_linux_sigcontext_addr; + tdep->pc_in_sigtramp = alpha_linux_pc_in_sigtramp; tdep->jb_pc = 2; tdep->jb_elt_size = 8; + + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + + /* Enable TLS support. */ + set_gdbarch_fetch_tls_load_module_address (gdbarch, + svr4_fetch_objfile_link_map); + + set_gdbarch_regset_from_core_section + (gdbarch, alpha_linux_regset_from_core_section); } +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_alpha_linux_tdep; + void _initialize_alpha_linux_tdep (void) {