This is the mail archive of the gdb-patches@sourceware.org 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]

[commit] MIPS support for non-PIC / -mplt


MIPS Linux tools (gcc, binutils, and glibc so far) recently gained
support for a mode in which executables are no longer position
independent.  Here are some adjustments to GDB to improve debugging of
such binaries.

One change is to use the normal glibc mechanism to skip the solib
resolver, now that it works, in addition to any MIPS-specific
mechanisms.  There are also new MIPS stubs, ".pic.FUNCTION_NAME", for
calls from non-PIC code to PIC code in the same executable; the PIC
code expects $25 to be set up on entry.  GDB can skip these stubs
automatically.  And I fixed a related bug in infrun; if we skip an
architecture trampoline and it takes us to a PLT entry, we should skip
the PLT entry too.

Tested on mips-linux and committed.

-- 
Daniel Jacobowitz
CodeSourcery

2008-10-02  Daniel Jacobowitz  <dan@codesourcery.com>

	* mips-linux-tdep.c (mips_linux_in_dynsym_resolve_code): Update
	comments.
	(mips_linux_skip_resolver): Also use glibc_skip_solib_resolver.
	(mips_linux_init_abi): Do not override skip_trampoline_code.
	* configure.tgt (mips*-*-linux*): Add glibc-tdep.o.
	* mips-tdep.c (mips32_scan_prologue): Stop scanning at branches.
	(mips_stub_frame_sniffer): Use the stub frame sniffer for PIC stubs.
	(mips_skip_mips16_trampoline_code): Rename from
	mips_skip_trampoline_code.
	(mips_skip_pic_trampoline_code, mips_skip_trampoline_code): New.
	* infrun.c (handle_inferior_event): Do not pass zero to
	in_solib_dynsym_resolve_code.

Index: gdb/configure.tgt
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/configure.tgt,v
retrieving revision 1.203
diff -u -p -r1.203 configure.tgt
--- gdb/configure.tgt	1 May 2008 23:09:14 -0000	1.203
+++ gdb/configure.tgt	27 Jun 2008 14:28:26 -0000
@@ -297,7 +297,7 @@ mips*-sgi-irix6*)
 	;;
 mips*-*-linux*)
 	# Target: Linux/MIPS
-	gdb_target_obs="mips-tdep.o mips-linux-tdep.o \
+	gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
 			corelow.o solib.o solib-svr4.o symfile-mem.o"
 	gdb_sim=../sim/mips/libsim.a
 	build_gdbserver=yes
Index: gdb/infrun.c
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/infrun.c,v
retrieving revision 1.301
diff -u -p -r1.301 infrun.c
--- gdb/infrun.c	22 Jul 2008 02:10:14 -0000	1.301
+++ gdb/infrun.c	11 Aug 2008 20:34:13 -0000
@@ -3107,7 +3107,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (
       if (real_stop_pc != 0)
 	ecs->stop_func_start = real_stop_pc;
 
-      if (in_solib_dynsym_resolve_code (ecs->stop_func_start))
+      if (real_stop_pc != 0 && in_solib_dynsym_resolve_code (real_stop_pc))
 	{
 	  struct symtab_and_line sr_sal;
 	  init_sal (&sr_sal);
Index: gdb/mips-linux-tdep.c
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.74
diff -u -p -r1.74 mips-linux-tdep.c
--- gdb/mips-linux-tdep.c	27 Jul 2008 20:52:42 -0000	1.74
+++ gdb/mips-linux-tdep.c	11 Aug 2008 20:32:52 -0000
@@ -37,6 +37,7 @@
 #include "symtab.h"
 #include "target-descriptions.h"
 #include "mips-linux-tdep.h"
+#include "glibc-tdep.h"
 
 static struct target_so_ops mips_svr4_so_ops;
 
@@ -666,13 +667,13 @@ mips_linux_in_dynsym_stub (CORE_ADDR pc,
 }
 
 /* Return non-zero iff PC belongs to the dynamic linker resolution
-   code or to a stub.  */
+   code, a PLT entry, or a lazy binding stub.  */
 
 static 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.  */
+     whether it is in the .plt section, used by non-PIC executables.  */
   if (svr4_in_dynsym_resolve_code (pc))
     return 1;
 
@@ -688,8 +689,8 @@ mips_linux_in_dynsym_resolve_code (CORE_
    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 GNU/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" directly.  An unresolved lazy binding
+   stub will point to _dl_runtime_resolve, which will first call
    __dl_runtime_resolve, and then pass control to the resolved
    function.  */
 
@@ -703,7 +704,7 @@ mips_linux_skip_resolver (struct gdbarch
   if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc)
     return frame_pc_unwind (get_current_frame ());
 
-  return 0;
+  return glibc_skip_solib_resolver (gdbarch, pc);
 }
 
 /* Signal trampoline support.  There are four supported layouts for a
@@ -1171,7 +1172,6 @@ mips_linux_init_abi (struct gdbarch_info
 	break;
     }
 
-  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
   set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);
 
   set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
Index: gdb/mips-tdep.c
===================================================================
RCS file: /scratch/gcc/repos/src/src/gdb/mips-tdep.c,v
retrieving revision 1.478
diff -u -p -r1.478 mips-tdep.c
--- gdb/mips-tdep.c	27 Jul 2008 20:52:42 -0000	1.478
+++ gdb/mips-tdep.c	11 Aug 2008 20:32:52 -0000
@@ -1897,6 +1897,7 @@ mips32_scan_prologue (CORE_ADDR start_pc
   CORE_ADDR end_prologue_addr = 0;
   int seen_sp_adjust = 0;
   int load_immediate_bytes = 0;
+  int in_delay_slot = 0;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
 
@@ -2054,7 +2055,18 @@ restart:
             instructions?  */
          if (end_prologue_addr == 0)
            end_prologue_addr = cur_pc;
+
+	 /* Check for branches and jumps.  For now, only jump to
+	    register are caught (i.e. returns).  */
+	 if ((itype_op (inst) & 0x07) == 0 && rtype_funct (inst) == 8)
+	   in_delay_slot = 1;
        }
+
+      /* If the previous instruction was a jump, we must have reached
+	 the end of the prologue by now.  Stop scanning so that we do
+	 not go past the function return.  */
+      if (in_delay_slot)
+	break;
     }
 
   if (this_cache != NULL)
@@ -2256,6 +2268,7 @@ mips_stub_frame_sniffer (const struct fr
   gdb_byte dummy[4];
   struct obj_section *s;
   CORE_ADDR pc = get_frame_address_in_block (this_frame);
+  struct minimal_symbol *msym;
 
   /* Use the stub unwinder for unreadable code.  */
   if (target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
@@ -2272,6 +2285,14 @@ mips_stub_frame_sniffer (const struct fr
 		 ".MIPS.stubs") == 0)
     return 1;
 
+  /* Calling a PIC function from a non-PIC function passes through a
+     stub.  The stub for foo is named ".pic.foo".  */
+  msym = lookup_minimal_symbol_by_pc (pc);
+  if (msym != NULL
+      && SYMBOL_LINKAGE_NAME (msym) != NULL
+      && strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) == 0)
+    return 1;
+
   return 0;
 }
 
@@ -5031,7 +5052,7 @@ mips_breakpoint_from_pc (struct gdbarch 
    gory details.  */
 
 static CORE_ADDR
-mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
   char *name;
   CORE_ADDR start_addr;
@@ -5110,6 +5131,80 @@ mips_skip_trampoline_code (struct frame_
   return 0;			/* not a stub */
 }
 
+/* If the current PC is the start of a non-PIC-to-PIC stub, return the
+   PC of the stub target.  The stub just loads $t9 and jumps to it,
+   so that $t9 has the correct value at function entry.  */
+
+static CORE_ADDR
+mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+{
+  struct minimal_symbol *msym;
+  int i;
+  gdb_byte stub_code[16];
+  int32_t stub_words[4];
+
+  /* The stub for foo is named ".pic.foo", and is either two
+     instructions inserted before foo or a three instruction sequence
+     which jumps to foo.  */
+  msym = lookup_minimal_symbol_by_pc (pc);
+  if (msym == NULL
+      || SYMBOL_VALUE_ADDRESS (msym) != pc
+      || SYMBOL_LINKAGE_NAME (msym) == NULL
+      || strncmp (SYMBOL_LINKAGE_NAME (msym), ".pic.", 5) != 0)
+    return 0;
+
+  /* A two-instruction header.  */
+  if (MSYMBOL_SIZE (msym) == 8)
+    return pc + 8;
+
+  /* A three-instruction (plus delay slot) trampoline.  */
+  if (MSYMBOL_SIZE (msym) == 16)
+    {
+      if (target_read_memory (pc, stub_code, 16) != 0)
+	return 0;
+      for (i = 0; i < 4; i++)
+	stub_words[i] = extract_unsigned_integer (stub_code + i * 4, 4);
+
+      /* A stub contains these instructions:
+	 lui	t9, %hi(target)
+	 j	target
+	  addiu	t9, t9, %lo(target)
+	 nop
+
+	 This works even for N64, since stubs are only generated with
+	 -msym32.  */
+      if ((stub_words[0] & 0xffff0000U) == 0x3c190000
+	  && (stub_words[1] & 0xfc000000U) == 0x08000000
+	  && (stub_words[2] & 0xffff0000U) == 0x27390000
+	  && stub_words[3] == 0x00000000)
+	return (((stub_words[0] & 0x0000ffff) << 16)
+		+ (stub_words[2] & 0x0000ffff));
+    }
+
+  /* Not a recognized stub.  */
+  return 0;
+}
+
+static CORE_ADDR
+mips_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+{
+  CORE_ADDR target_pc;
+
+  target_pc = mips_skip_mips16_trampoline_code (frame, pc);
+  if (target_pc)
+    return target_pc;
+
+  target_pc = find_solib_trampoline_target (frame, pc);
+  if (target_pc)
+    return target_pc;
+
+  target_pc = mips_skip_pic_trampoline_code (frame, pc);
+  if (target_pc)
+    return target_pc;
+
+  return 0;
+}
+
 /* Convert a dbx stab register number (from `r' declaration) to a GDB
    [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
 


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