summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2011-05-09 13:17:02 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2011-05-09 13:17:02 +0000
commitb26af71e8f32293dee45d352843afb20398eae10 (patch)
tree62d19d1cd3fc5016a62d5565114dc0882ab2dc2d /gnu/usr.bin/binutils
parentc88c06ba140ec8f1ebb45f541b0a166190946bdf (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.mt5
-rw-r--r--gnu/usr.bin/binutils/gdb/config/mips/tm-obsd64.h31
-rw-r--r--gnu/usr.bin/binutils/gdb/mips64obsd-tdep.c73
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);
}