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]

[patch] Support bionic's jmp_buf.


Hello,

Android uses a libc (bionic) which is derived from BSD instead of glibc,
and stores the PC value at a different location in the jump buffer than
regular arm-linux. Also, since there's no PC mangling this code works
even without SystemTap probes.

I'm using the ELF interpreter field to identify an Android binary (the
program loader is /system/bin/linker). Also, I had to change
gdbarch_tdep->jb_pc to a function so that the code to determine which
kind of program we are dealing with runs when the value is actually
needed. This is because by the time arm_linux_init_abi is called
exec_bfd hasn't been set yet so there's no way to peek at the ELF
interpreter field.

This patch fixes gdb.base/longjmp.exp.

There are no regressions on arm-linux native, arm-linux remote or
i386-linux native.

Ok?

-- 
[]'s
Thiago Jung Bauermann
Linaro Toolchain Working Group


2012-05-20  Thiago Jung Bauermann  <thiago.bauermann@linaro.org>

	Support bionic's jmp_buf.
	* arm-linux-tdep.c (ARM_LINUX_JB_PC_ANDROID): New macro.
	(is_target_linux_android): New function.
	(arm_linux_jb_pc): Likewise.
	(arm_linux_init_abi): Set tdep->jb_pc to arm_linux_jb_pc
	instead of determining the jb_pc value right away.
	* arm-tdep.c (arm_get_longjmp_target): Call tdep->jb_pc.
	(arm_gdbarch_init): tdep->jb_pc is now a pointer. Assign it
	and test its value accordingly.
	* arm-tdep.h (struct gdbarch_tdep): Change jb_pc to a
	function pointer.
	* arm-wince-tdep.c (arm_wince_jb_pc): New function.
	(arm_wince_init_abi): Set tdep->jb_pc to arm_wince_jb_pc.
	* armnbsd-tdep.c (arm_netbsd_jb_pc): New function.
	(arm_netbsd_init_abi_common): Set tdep->jb_pc to arm_netbsd_jb_pc.
	* armobsd-tdep.c (arm_obsd_jb_pc): New function.
	(armobsd_init_abi): Set tdep->jb_pc to arm_obsd_jb_pc.
	* solib-svr4.c (find_program_interpreter): Remove static keyword.
	Rename to ...
	(find_elf_program_interpreter): ... this.
	* solib-svr4.h (find_program_interpreter): New prototype.


diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index f4eaa5c..b9d67b0 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -105,6 +105,7 @@ static const char arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 };
 #define ARM_LINUX_JB_ELEMENT_SIZE	INT_REGISTER_SIZE
 #define ARM_LINUX_JB_PC_FPA		21
 #define ARM_LINUX_JB_PC_EABI		9
+#define ARM_LINUX_JB_PC_ANDROID		29
 
 /*
    Dynamic Linking on ARM GNU/Linux
@@ -1178,6 +1179,54 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch,
   return 1;
 }
 
+/* Determines whether the inferior is an Android application.  */
+
+static int
+is_target_linux_android (void)
+{
+  int ret = 0;
+  gdb_byte *interp;
+
+  interp = find_elf_program_interpreter ();
+  if (interp)
+    {
+      ret = !strcmp (interp, "/system/bin/linker");
+      xfree (interp);
+    }
+
+  return ret;
+}
+
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h.  */
+
+static CORE_ADDR
+arm_linux_jb_pc (struct gdbarch_tdep *tdep)
+{
+  int jb_pc;
+
+  switch (tdep->fp_model)
+    {
+    case ARM_FLOAT_FPA:
+      jb_pc = ARM_LINUX_JB_PC_FPA;
+      break;
+    case ARM_FLOAT_SOFT_FPA:
+    case ARM_FLOAT_SOFT_VFP:
+    case ARM_FLOAT_VFP:
+      jb_pc = ARM_LINUX_JB_PC_EABI;
+      break;
+    default:
+      internal_error
+	(__FILE__, __LINE__,
+         _("arm_linux_init_abi: Floating point model not supported"));
+      break;
+    }
+
+  if (is_target_linux_android ())
+    jb_pc = ARM_LINUX_JB_PC_ANDROID;
+
+  return jb_pc;
+}
+
 static void
 arm_linux_init_abi (struct gdbarch_info info,
 		    struct gdbarch *gdbarch)
@@ -1212,22 +1261,7 @@ arm_linux_init_abi (struct gdbarch_info info,
   if (tdep->fp_model == ARM_FLOAT_AUTO)
     tdep->fp_model = ARM_FLOAT_FPA;
 
-  switch (tdep->fp_model)
-    {
-    case ARM_FLOAT_FPA:
-      tdep->jb_pc = ARM_LINUX_JB_PC_FPA;
-      break;
-    case ARM_FLOAT_SOFT_FPA:
-    case ARM_FLOAT_SOFT_VFP:
-    case ARM_FLOAT_VFP:
-      tdep->jb_pc = ARM_LINUX_JB_PC_EABI;
-      break;
-    default:
-      internal_error
-	(__FILE__, __LINE__,
-         _("arm_linux_init_abi: Floating point model not supported"));
-      break;
-    }
+  tdep->jb_pc = arm_linux_jb_pc;
   tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE;
 
   set_solib_svr4_fetch_link_map_offsets
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index df5dea7..d1aa6b5 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -9083,12 +9083,13 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  CORE_ADDR jb_addr;
+  CORE_ADDR jb_addr, jb_pc;
   char buf[INT_REGISTER_SIZE];
-  
+
   jb_addr = get_frame_register_unsigned (frame, ARM_A1_REGNUM);
+  jb_pc = tdep->jb_pc (tdep);
 
-  if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
+  if (target_read_memory (jb_addr + jb_pc * tdep->jb_elt_size, buf,
 			  INT_REGISTER_SIZE))
     return 0;
 
@@ -10132,7 +10133,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* This should be low enough for everything.  */
   tdep->lowest_pc = 0x20;
-  tdep->jb_pc = -1;	/* Longjump support not enabled by default.  */
+  tdep->jb_pc = NULL;	/* Longjump support not enabled by default.  */
 
   /* The default, for both APCS and AAPCS, is to return small
      structures in registers.  */
@@ -10236,7 +10237,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (tdep->fp_model == ARM_FLOAT_AUTO)
     tdep->fp_model = ARM_FLOAT_SOFT_FPA;
 
-  if (tdep->jb_pc >= 0)
+  if (tdep->jb_pc != NULL)
     set_gdbarch_get_longjmp_target (gdbarch, arm_get_longjmp_target);
 
   /* Floating point sizes and format.  */
diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h
index 97596d5..b95d548 100644
--- a/gdb/arm-tdep.h
+++ b/gdb/arm-tdep.h
@@ -185,9 +185,9 @@ struct gdbarch_tdep
   const char *thumb2_breakpoint;
   int thumb2_breakpoint_size;
 
-  int jb_pc;			/* Offset to PC value in jump buffer.
-				   If this is negative, longjmp support
-				   will be disabled.  */
+  /* Return offset to PC value in jump buffer.  If this is NULL, longjmp
+     support will be disabled.  */
+  CORE_ADDR (*jb_pc) (struct gdbarch_tdep *tdep);
   size_t jb_elt_size;		/* And the size of each entry in the buf.  */
 
   /* Convention for returning structures.  */
diff --git a/gdb/arm-wince-tdep.c b/gdb/arm-wince-tdep.c
index 5bc6473..ce04ba0 100644
--- a/gdb/arm-wince-tdep.c
+++ b/gdb/arm-wince-tdep.c
@@ -111,6 +111,14 @@ arm_wince_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return pc;
 }
 
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h.  */
+
+static CORE_ADDR
+arm_wince_jb_pc (struct gdbarch_tdep *tdep)
+{
+  return ARM_WINCE_JB_PC;
+}
+
 static void
 arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -124,7 +132,7 @@ arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   tdep->fp_model = ARM_FLOAT_SOFT_VFP;
 
-  tdep->jb_pc = ARM_WINCE_JB_PC;
+  tdep->jb_pc = arm_wince_jb_pc;
   tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
 
   /* On ARM WinCE char defaults to signed.  */
diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c
index 19aa000..144bd85 100644
--- a/gdb/armnbsd-tdep.c
+++ b/gdb/armnbsd-tdep.c
@@ -36,6 +36,14 @@ static const char arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11};
 static const char arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde};
 static const char arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe};
 
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h.  */
+
+static CORE_ADDR
+arm_netbsd_jb_pc (struct gdbarch_tdep *tdep)
+{
+  return ARM_NBSD_JB_PC;
+}
+
 static void
 arm_netbsd_init_abi_common (struct gdbarch_info info,
 			    struct gdbarch *gdbarch)
@@ -64,7 +72,7 @@ arm_netbsd_init_abi_common (struct gdbarch_info info,
 		      _("arm_gdbarch_init: bad byte order for float format"));
     }
 
-  tdep->jb_pc = ARM_NBSD_JB_PC;
+  tdep->jb_pc = arm_netbsd_jb_pc;
   tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE;
 
   /* Single stepping.  */
diff --git a/gdb/armobsd-tdep.c b/gdb/armobsd-tdep.c
index fab4e42..e48eeaa 100644
--- a/gdb/armobsd-tdep.c
+++ b/gdb/armobsd-tdep.c
@@ -74,6 +74,14 @@ static const struct tramp_frame armobsd_sigframe =
 static const char arm_obsd_thumb_le_breakpoint[] = {0xfe, 0xdf};
 static const char arm_obsd_thumb_be_breakpoint[] = {0xdf, 0xfe};
 
+/* Implements the gdbarch_tdep.jb_pc function in arm-tdep.h.  */
+
+static CORE_ADDR
+armobsd_jb_pc (struct gdbarch_tdep *tdep)
+{
+  return 24;
+}
+
 static void
 armobsd_init_abi (struct gdbarch_info info,
 		  struct gdbarch *gdbarch)
@@ -90,7 +98,7 @@ armobsd_init_abi (struct gdbarch_info info,
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
   set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver);
 
-  tdep->jb_pc = 24;
+  tdep->jb_pc = armobsd_jb_pc;
   tdep->jb_elt_size = 4;
 
   set_gdbarch_regset_from_core_section
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 69d3cb5..24f224f 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -496,8 +496,8 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size)
 
 
 /* Return program interpreter string.  */
-static gdb_byte *
-find_program_interpreter (void)
+gdb_byte *
+find_elf_program_interpreter (void)
 {
   gdb_byte *buf = NULL;
 
@@ -1520,7 +1520,7 @@ enable_break (struct svr4_info *info, int from_tty)
 
   /* Find the program interpreter; if not found, warn the user and drop
      into the old breakpoint at symbol code.  */
-  interp_name = find_program_interpreter ();
+  interp_name = find_elf_program_interpreter ();
   if (interp_name)
     {
       CORE_ADDR load_addr = 0;
diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h
index f9a02c9..87f088d 100644
--- a/gdb/solib-svr4.h
+++ b/gdb/solib-svr4.h
@@ -84,4 +84,7 @@ extern struct link_map_offsets *svr4_lp64_fetch_link_map_offsets (void);
    SVR4 run time loader.  */
 int svr4_in_dynsym_resolve_code (CORE_ADDR pc);
 
+/* Return program interpreter string.  */
+gdb_byte *find_elf_program_interpreter (void);
+
 #endif /* solib-svr4.h */



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