diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-05-09 13:17:02 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-05-09 13:17:02 +0000 |
commit | b26af71e8f32293dee45d352843afb20398eae10 (patch) | |
tree | 62d19d1cd3fc5016a62d5565114dc0882ab2dc2d /gnu/usr.bin/binutils | |
parent | c88c06ba140ec8f1ebb45f541b0a166190946bdf (diff) |
Handle lazy relocation stubs like Linux does, (but with simplified code since
we only care about N64 binaries).
Diffstat (limited to 'gnu/usr.bin/binutils')
-rw-r--r-- | gnu/usr.bin/binutils/gdb/config/mips/obsd64.mt | 5 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/config/mips/tm-obsd64.h | 31 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c | 73 |
3 files changed, 107 insertions, 2 deletions
diff --git a/gnu/usr.bin/binutils/gdb/config/mips/obsd64.mt b/gnu/usr.bin/binutils/gdb/config/mips/obsd64.mt index de54a2fb74f..f6657d0dd53 100644 --- a/gnu/usr.bin/binutils/gdb/config/mips/obsd64.mt +++ b/gnu/usr.bin/binutils/gdb/config/mips/obsd64.mt @@ -1,3 +1,4 @@ # Target: OpenBSD/mips64 -TDEPFILES= mips-tdep.o mips64obsd-tdep.o corelow.o solib.o solib-svr4.o -DEPRECATED_TM_FILE= solib.h +TDEPFILES= mips-tdep.o mips64obsd-tdep.o obsd-tdep.o \ + corelow.o solib.o solib-svr4.o +DEPRECATED_TM_FILE= tm-obsd64.h diff --git a/gnu/usr.bin/binutils/gdb/config/mips/tm-obsd64.h b/gnu/usr.bin/binutils/gdb/config/mips/tm-obsd64.h new file mode 100644 index 00000000000..5ec0a9f414d --- /dev/null +++ b/gnu/usr.bin/binutils/gdb/config/mips/tm-obsd64.h @@ -0,0 +1,31 @@ +/* Target-dependent definitions for OpenBSD/mips64. + + Copyright 2001, 2002, 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 TM_OBSD64_H +#define TM_OBSD64_H + +#include "solib.h" + +#undef IN_SOLIB_DYNSYM_RESOLVE_CODE +#define IN_SOLIB_DYNSYM_RESOLVE_CODE(PC) mips64obsd_in_dynsym_resolve_code (PC) +int mips64obsd_in_dynsym_resolve_code (CORE_ADDR pc); + +#endif /* TM_OBSD64_H */ diff --git a/gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c b/gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c index 9f4b0684f9e..87eb9ca4081 100644 --- a/gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c +++ b/gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c @@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */ #include "defs.h" +#include "gdbcore.h" #include "osabi.h" #include "regcache.h" #include "regset.h" @@ -30,6 +31,7 @@ #include "gdb_string.h" #include "mips-tdep.h" +#include "obsd-tdep.h" #include "solib-svr4.h" #define MIPS64OBSD_NUM_REGS 73 @@ -127,8 +129,77 @@ static const struct tramp_frame mips64obsd_sigframe = }, mips64obsd_sigframe_init }; + + +/* Check the code at PC for a dynamic linker lazy resolution stub. Because + they aren't in the .plt section, we pattern-match on the code generated + by GNU ld. They look like this: + + ld t9,0x8010(gp) + daddu t7,ra + jalr t9,ra + daddiu t8,zero,INDEX + Also return the dynamic symbol index used in the last instruction. */ + +static int +mips64obsd_in_dynsym_stub (CORE_ADDR pc, char *name) +{ + unsigned char buf[28], *p; + ULONGEST insn; + + read_memory (pc - 12, buf, 28); + + p = buf + 12; + while (p >= buf) + { + insn = extract_unsigned_integer (p, 4); + /* ld t9,0x8010(gp) */ + if (insn == 0xdf998010) + break; + p -= 4; + } + if (p < buf) + return 0; + + insn = extract_unsigned_integer (p + 4, 4); + /* daddu t7,ra */ + if (insn != 0x03e0782d) + return 0; + + insn = extract_unsigned_integer (p + 8, 4); + /* jalr t9,ra */ + if (insn != 0x0320f809) + return 0; + + insn = extract_unsigned_integer (p + 12, 4); + /* daddiu t8,zero,0 */ + if ((insn & 0xffff0000) != 0x64180000) + return 0; + + return (insn & 0xffff); +} + +/* Return non-zero iff PC belongs to the dynamic linker resolution code + or to a stub. */ + +int +mips64obsd_in_dynsym_resolve_code (CORE_ADDR pc) +{ + /* Check whether PC is in the dynamic linker. This also checks whether + it is in the .plt section, which MIPS does not use. */ + if (in_solib_dynsym_resolve_code (pc)) + return 1; + + /* Pattern match for the stub. It would be nice if there were a more + efficient way to avoid this check. */ + if (mips64obsd_in_dynsym_stub (pc, NULL)) + return 1; + + return 0; +} + static void mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -145,8 +216,10 @@ mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) #endif /* OpenBSD/mips64 has SVR4-style shared libraries. */ + set_gdbarch_in_solib_call_trampoline (gdbarch, mips64obsd_in_dynsym_stub); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets); + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); } |