From 6de918a6f50f6f9dbc8ae3628dcee80d0f8e2f64 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Wed, 11 Feb 2004 18:47:27 +0000 Subject: [PATCH] * mips-linux-tdep.c: Include "frame.h". (mips_linux_in_dynsym_stub, mips_linux_in_dynsym_resolve_code) (mips_linux_skip_resolver): New functions. (mips_linux_init_abi): Call set_gdbarch_skip_solib_resolver and set_gdbarch_in_solib_call_trampoline. * mips-tdep.c (mips_gdbarch_init): Move gdbarch_init_osabi call to after set_gdbarch_in_solib_return_trampoline. Only set the solib hooks to mips16 functions if the OS ABI is unknown. * config/mips/tm-linux.h (IN_SOLIB_CALL_TRAMPOLINE): Undefine after including "config/tm-linux.h". (IN_SOLIB_DYNSYM_RESOLVE_CODE): Define. * Makefile.in (mips-linux-tdep.o): Update. --- gdb/ChangeLog | 15 +++++ gdb/Makefile.in | 2 +- gdb/config/mips/tm-linux.h | 13 +++- gdb/mips-linux-tdep.c | 126 +++++++++++++++++++++++++++++++++++++ gdb/mips-tdep.c | 19 ++++-- 5 files changed, 167 insertions(+), 8 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d299904330..930c2fa169 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2004-02-11 Daniel Jacobowitz + + * mips-linux-tdep.c: Include "frame.h". + (mips_linux_in_dynsym_stub, mips_linux_in_dynsym_resolve_code) + (mips_linux_skip_resolver): New functions. + (mips_linux_init_abi): Call set_gdbarch_skip_solib_resolver + and set_gdbarch_in_solib_call_trampoline. + * mips-tdep.c (mips_gdbarch_init): Move gdbarch_init_osabi call + to after set_gdbarch_in_solib_return_trampoline. Only set the + solib hooks to mips16 functions if the OS ABI is unknown. + * config/mips/tm-linux.h (IN_SOLIB_CALL_TRAMPOLINE): Undefine after + including "config/tm-linux.h". + (IN_SOLIB_DYNSYM_RESOLVE_CODE): Define. + * Makefile.in (mips-linux-tdep.o): Update. + 2004-02-11 David Carlton * linespec.c (decode_compound): Only look for a class symbol when diff --git a/gdb/Makefile.in b/gdb/Makefile.in index e5545f4994..2e3c315569 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2064,7 +2064,7 @@ mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h) mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \ $(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \ - $(gdb_assert_h) + $(gdb_assert_h) $(frame_h) mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) mipsnbsd-nat.o: mipsnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \ $(mipsnbsd_tdep_h) diff --git a/gdb/config/mips/tm-linux.h b/gdb/config/mips/tm-linux.h index c049c29aa7..fc3270779d 100644 --- a/gdb/config/mips/tm-linux.h +++ b/gdb/config/mips/tm-linux.h @@ -1,6 +1,6 @@ /* Target-dependent definitions for GNU/Linux MIPS. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -26,7 +26,6 @@ /* We don't want to inherit tm-mips.h's shared library trampoline code. */ -#undef IN_SOLIB_CALL_TRAMPOLINE #undef IN_SOLIB_RETURN_TRAMPOLINE #undef SKIP_TRAMPOLINE_CODE #undef IGNORE_HELPER_CALL @@ -50,4 +49,14 @@ #undef IN_SIGTRAMP #define IN_SIGTRAMP(pc, name) (0) +#undef IN_SOLIB_DYNSYM_RESOLVE_CODE +#define IN_SOLIB_DYNSYM_RESOLVE_CODE(PC) mips_linux_in_dynsym_resolve_code (PC) +int mips_linux_in_dynsym_resolve_code (CORE_ADDR pc); + +/* We don't want all of tm-sysv4.h's shared library trampoline code either. + Note that by undefining IN_SOLIB_CALL_TRAMPOLINE here we will use the + gdbarch vector's version instead. */ + +#undef IN_SOLIB_CALL_TRAMPOLINE + #endif /* TM_MIPSLINUX_H */ diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index a7ee145a95..fb7601b752 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -27,6 +27,7 @@ #include "mips-tdep.h" #include "gdb_string.h" #include "gdb_assert.h" +#include "frame.h" /* Copied from . */ #define ELF_NGREG 45 @@ -676,6 +677,125 @@ init_register_addr_data (struct gdbarch *gdbarch) return 0; } +/* 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: + + lw t9,0x8010(gp) + addu t7,ra + jalr t9,ra + addiu t8,zero,INDEX + + (with the appropriate doubleword instructions for N64). Also return the + dynamic symbol index used in the last instruction. */ + +static int +mips_linux_in_dynsym_stub (CORE_ADDR pc, char *name) +{ + unsigned char buf[28], *p; + ULONGEST insn, insn1; + int n64 = (mips_abi (current_gdbarch) == MIPS_ABI_N64); + + read_memory (pc - 12, buf, 28); + + if (n64) + { + /* ld t9,0x8010(gp) */ + insn1 = 0xdf998010; + } + else + { + /* lw t9,0x8010(gp) */ + insn1 = 0x8f998010; + } + + p = buf + 12; + while (p >= buf) + { + insn = extract_unsigned_integer (p, 4); + if (insn == insn1) + break; + p -= 4; + } + if (p < buf) + return 0; + + insn = extract_unsigned_integer (p + 4, 4); + if (n64) + { + /* daddu t7,ra */ + if (insn != 0x03e0782d) + return 0; + } + else + { + /* addu t7,ra */ + if (insn != 0x03e07821) + return 0; + } + + insn = extract_unsigned_integer (p + 8, 4); + /* jalr t9,ra */ + if (insn != 0x0320f809) + return 0; + + insn = extract_unsigned_integer (p + 12, 4); + if (n64) + { + /* daddiu t8,zero,0 */ + if ((insn & 0xffff0000) != 0x64180000) + return 0; + } + else + { + /* addiu t8,zero,0 */ + if ((insn & 0xffff0000) != 0x24180000) + return 0; + } + + return (insn & 0xffff); +} + +/* Return non-zero iff PC belongs to the dynamic linker resolution code + or to a stub. */ + +int +mips_linux_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 (mips_linux_in_dynsym_stub (pc, NULL)) + return 1; + + return 0; +} + +/* See the comments for SKIP_SOLIB_RESOLVER at the top of infrun.c, + and glibc_skip_solib_resolver in glibc-tdep.c. The normal glibc + implementation of this triggers at "fixup" from the same objfile as + "_dl_runtime_resolve"; MIPS/Linux can trigger at "__dl_runtime_resolve" + directly. An unresolved PLT entry will point to _dl_runtime_resolve, + which will first call __dl_runtime_resolve, and then pass control to + the resolved function. */ + +static CORE_ADDR +mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + struct minimal_symbol *resolver; + + resolver = lookup_minimal_symbol ("__dl_runtime_resolve", NULL, NULL); + + if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc) + return frame_pc_unwind (get_current_frame ()); + + return 0; +} + static void mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -709,6 +829,12 @@ mips_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) internal_error (__FILE__, __LINE__, "can't handle ABI"); break; } + + set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver); + + /* This overrides the MIPS16 stub support from mips-tdep. But no one uses + MIPS16 on Linux yet, so this isn't much of a loss. */ + set_gdbarch_in_solib_call_trampoline (gdbarch, mips_linux_in_dynsym_stub); } void diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 4b45db7341..fb80964e6e 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -5815,13 +5815,22 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) is sitting on? */ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); - /* Hook in OS ABI-specific overrides, if they have been registered. */ - gdbarch_init_osabi (info, gdbarch); - set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_stub); - set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub); - set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub); + /* NOTE drow/2004-02-11: We overload the core solib trampoline code + to support MIPS16. This is a bad thing. Make sure not to do it + if we have an OS ABI that actually supports shared libraries, since + shared library support is more important. If we have an OS someday + that supports both shared libraries and MIPS16, we'll have to find + a better place for these. */ + if (info.osabi == GDB_OSABI_UNKNOWN) + { + set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub); + set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub); + } + + /* Hook in OS ABI-specific overrides, if they have been registered. */ + gdbarch_init_osabi (info, gdbarch); return gdbarch; }