diff mbox

[rfa,v2] Detect __aeabi_read_tp even without symbols

Message ID 201103041638.p24Gc4Uu004246@d06av02.portsmouth.uk.ibm.com
State Accepted
Headers show

Commit Message

Ulrich Weigand March 4, 2011, 4:38 p.m. UTC
http://sourceware.org/ml/gdb-patches/2010-12/msg00002.html


ChangeLog:

	* arm-tdep.c (skip_prologue_function): Add GDBARCH and IS_THUMB
	arguments.  Skip in-prologue calls to glibc __aeabi_read_tp
	implementation even if no symbols are available.
	(thumb_analyze_prologue): Update call to skip_prologue_function.
	(arm_analyze_prologue): Likewise.
diff mbox

Patch

Index: gdb/arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.313
diff -u -p -r1.313 arm-tdep.c
--- gdb/arm-tdep.c	18 Nov 2010 16:38:20 -0000	1.313
+++ gdb/arm-tdep.c	1 Dec 2010 13:52:02 -0000
@@ -449,39 +449,55 @@  arm_smash_text_address (struct gdbarch *
 }
 
 /* Return 1 if PC is the start of a compiler helper function which
-   can be safely ignored during prologue skipping.  */
+   can be safely ignored during prologue skipping.  IS_THUMB is true
+   if the function is known to be a Thumb function due to the way it
+   is being called.  */
 static int
-skip_prologue_function (CORE_ADDR pc)
+skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
 {
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   struct minimal_symbol *msym;
-  const char *name;
 
   msym = lookup_minimal_symbol_by_pc (pc);
-  if (msym == NULL || SYMBOL_VALUE_ADDRESS (msym) != pc)
-    return 0;
-
-  name = SYMBOL_LINKAGE_NAME (msym);
-  if (name == NULL)
-    return 0;
-
-  /* The GNU linker's Thumb call stub to foo is named
-     __foo_from_thumb.  */
-  if (strstr (name, "_from_thumb") != NULL)
-    name += 2;
-
-  /* On soft-float targets, __truncdfsf2 is called to convert promoted
-     arguments to their argument types in non-prototyped
-     functions.  */
-  if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
-    return 1;
-  if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
-    return 1;
+  if (msym != NULL
+      && SYMBOL_VALUE_ADDRESS (msym) == pc
+      && SYMBOL_LINKAGE_NAME (msym) != NULL)
+    {
+      const char *name = SYMBOL_LINKAGE_NAME (msym);
+
+      /* The GNU linker's Thumb call stub to foo is named
+	 __foo_from_thumb.  */
+      if (strstr (name, "_from_thumb") != NULL)
+	name += 2;
+
+      /* On soft-float targets, __truncdfsf2 is called to convert promoted
+	 arguments to their argument types in non-prototyped
+	 functions.  */
+      if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
+	return 1;
+      if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
+	return 1;
 
-  /* Internal functions related to thread-local storage.  */
-  if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
-    return 1;
-  if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
-    return 1;
+      /* Internal functions related to thread-local storage.  */
+      if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
+	return 1;
+      if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
+	return 1;
+    }
+  else
+    {
+      /* If we run against a stripped glibc, we may be unable to identify
+	 special functions by name.  Check for one important case,
+	 __aeabi_read_tp, by comparing the *code* against the default
+	 implementation (this is hand-written ARM assembler in glibc).  */
+
+      if (!is_thumb
+	  && read_memory_unsigned_integer (pc, 4, byte_order_for_code)
+	     == 0xe3e00a0f /* mov r0, #0xffff0fff */
+	  && read_memory_unsigned_integer (pc + 4, 4, byte_order_for_code)
+	     == 0xe240f01f) /* sub pc, r0, #31 */
+	return 1;
+    }
 
   return 0;
 }
@@ -825,7 +841,8 @@  thumb_analyze_prologue (struct gdbarch *
 	      if (bit (inst2, 12) == 0)
 		nextpc = nextpc & 0xfffffffc;
 
-	      if (!skip_prologue_function (nextpc))
+	      if (!skip_prologue_function (gdbarch, nextpc,
+					   bit (inst2, 12) != 0))
 		break;
 	    }
 
@@ -1602,7 +1619,7 @@  arm_analyze_prologue (struct gdbarch *gd
 	     the stack.  */
 	  CORE_ADDR dest = BranchDest (current_pc, insn);
 
-	  if (skip_prologue_function (dest))
+	  if (skip_prologue_function (gdbarch, dest, 0))
 	    continue;
 	  else
 	    break;