This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfa/mips] Shared library trampoline support for mips-linux


On Wed, Feb 11, 2004 at 01:33:33PM -0500, Andrew Cagney wrote:
> >On Tue, Feb 10, 2004 at 06:38:50PM -0500, Andrew Cagney wrote:
> >
> >>>-  /* 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);
> >
> >>
> >>Assuming that the default is no OS, I'm actually wondering why these are 
> >>set at all.
> >
> >
> >Because they're used for MIPS16, presumably.  The fact that MIPS16 call
> >stubs use the solib machinery is why I had a ??? in my question.
> 
> If you can wrap those two in an "if (osabi isn't for an os)", and add a 
> rude comment, I'm ok.
> 
> I get the feeling that infrun should just have a list of per-osabi 
> function names that it either silently step-outof or finishes.  If it 
> were user visible, people could even add to it.

OK, here's what I checked in.  I don't think a list would work - for
one thing, some of them (ARM Thumb, MIPS16) are prefixes without fixed
names.  But maybe it would :)

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2004-02-11  Daniel Jacobowitz  <drow@mvista.com>

	* 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.

Index: Makefile.in
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/Makefile.in,v
retrieving revision 1.492
diff -u -p -r1.492 Makefile.in
--- Makefile.in	9 Feb 2004 05:29:53 -0000	1.492
+++ Makefile.in	10 Feb 2004 23:11:02 -0000
@@ -2069,7 +2069,7 @@ mips-irix-tdep.o: mips-irix-tdep.c $(def
 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)
Index: mips-linux-tdep.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.17
diff -u -p -r1.17 mips-linux-tdep.c
--- mips-linux-tdep.c	16 Nov 2003 19:24:04 -0000	1.17
+++ mips-linux-tdep.c	10 Feb 2004 23:10:39 -0000
@@ -27,6 +27,7 @@
 #include "mips-tdep.h"
 #include "gdb_string.h"
 #include "gdb_assert.h"
+#include "frame.h"
 
 /* Copied from <asm/elf.h>.  */
 #define ELF_NGREG       45
@@ -676,6 +677,125 @@ init_register_addr_data (struct 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
 	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
Index: mips-tdep.c
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/mips-tdep.c,v
retrieving revision 1.279
diff -u -p -r1.279 mips-tdep.c
--- mips-tdep.c	9 Feb 2004 05:29:53 -0000	1.279
+++ mips-tdep.c	11 Feb 2004 18:44:38 -0000
@@ -6406,13 +6406,22 @@ mips_gdbarch_init (struct gdbarch_info i
      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;
 }
Index: config/mips/tm-linux.h
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/config/mips/tm-linux.h,v
retrieving revision 1.7
diff -u -p -r1.7 tm-linux.h
--- config/mips/tm-linux.h	21 Dec 2002 05:07:36 -0000	1.7
+++ config/mips/tm-linux.h	10 Feb 2004 23:09:44 -0000
@@ -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
@@ -49,5 +48,15 @@
 
 #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 */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]