* arm-tdep.c (skip_prologue_function): Add GDBARCH and IS_THUMB
authorUlrich Weigand <uweigand@de.ibm.com>
Wed, 2 Feb 2011 19:45:32 +0000 (19:45 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Wed, 2 Feb 2011 19:45:32 +0000 (19:45 +0000)
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.

gdb/ChangeLog
gdb/arm-tdep.c

index 2330886..1c467ea 100644 (file)
@@ -1,5 +1,13 @@
 2011-02-02  Ulrich Weigand  <ulrich.weigand@linaro.org>
 
+       * 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.
+
+2011-02-02  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
        * arm-tdep.c: Include "observer.h".
        (arm_prologue_this_id): Use frame PC if get_frame_func returns 0.
        (arm_exidx_data_key): New static variable.
index 5d2b632..a9abf2d 100644 (file)
@@ -451,39 +451,55 @@ arm_smash_text_address (struct gdbarch *gdbarch, CORE_ADDR val)
 }
 
 /* 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;
+  if (msym != NULL
+      && SYMBOL_VALUE_ADDRESS (msym) == pc
+      && SYMBOL_LINKAGE_NAME (msym) != NULL)
+    {
+      const char *name = SYMBOL_LINKAGE_NAME (msym);
 
-  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;
 
-  /* 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;
 
-  /* 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;
+    }
+  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).  */
 
-  /* 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;
+      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;
 }
@@ -842,7 +858,8 @@ thumb_analyze_prologue (struct gdbarch *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;
            }
 
@@ -1814,7 +1831,7 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
             the stack.  */
          CORE_ADDR dest = BranchDest (current_pc, insn);
 
-         if (skip_prologue_function (dest))
+         if (skip_prologue_function (gdbarch, dest, 0))
            continue;
          else
            break;