* hppa-tdep.c (in_solib_call_trampoline): Recognize calls through
authorJeff Law <law@redhat.com>
Fri, 25 Nov 1994 09:21:49 +0000 (09:21 +0000)
committerJeff Law <law@redhat.com>
Fri, 25 Nov 1994 09:21:49 +0000 (09:21 +0000)
_sr4export and $$dyncall as trampolines.  Likewise for long-call
stubs and parameter relocation stubs.
(in_solib_return_trampoline): Recognize a return trampoline for
return value relocation stubs.

gdb/ChangeLog
gdb/hppa-tdep.c

index a67d3863c85febcc9c395079b07d458ac181433c..ab3d818264033b330b9051237523be8afd8da85c 100644 (file)
@@ -1,5 +1,11 @@
 Fri Nov 25 00:51:05 1994  Jeff Law  (law@snake.cs.utah.edu)
 
+       * hppa-tdep.c (in_solib_call_trampoline): Recognize calls through
+       _sr4export and $$dyncall as trampolines.  Likewise for long-call
+       stubs and parameter relocation stubs.
+       (in_solib_return_trampoline): Recognize a return trampoline for
+       return value relocation stubs.
+
        * hpread.c: Include hp-symtab.h instead of hpux-symtab.h.
        Various name changes to match those used by hp-symtab.h.
 
index 3ff364c91b6bf0c3a352a9bba4880f083a7061e6..85c076695455004d996df2e00990aee5c749dc6a 100644 (file)
@@ -1572,8 +1572,10 @@ pa_print_fp_reg (i)
     }
 }
 
-/* Return one if PC is in the call path of a shared library trampoline, else
-   return zero.  */
+/* Return one if PC is in the call path of a trampoline, else return zero.
+
+   Note we return one for *any* call trampoline (long-call, arg-reloc), not
+   just shared library trampolines (import, export).  */
 
 in_solib_call_trampoline (pc, name)
      CORE_ADDR pc;
@@ -1581,6 +1583,33 @@ in_solib_call_trampoline (pc, name)
 {
   struct minimal_symbol *minsym;
   struct unwind_table_entry *u;
+  static CORE_ADDR dyncall = 0;
+  static CORE_ADDR sr4export = 0;
+
+/* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
+   new exec file */
+
+  /* First see if PC is in one of the two C-library trampolines.  */
+  if (!dyncall)
+    {
+      minsym = lookup_minimal_symbol ("$$dyncall", NULL);
+      if (minsym)
+       dyncall = SYMBOL_VALUE_ADDRESS (minsym);
+      else
+       dyncall = -1;
+    }
+
+  if (!sr4export)
+    {
+      minsym = lookup_minimal_symbol ("_sr4export", NULL);
+      if (minsym)
+       sr4export = SYMBOL_VALUE_ADDRESS (minsym);
+      else
+       sr4export = -1;
+    }
+
+  if (pc == dyncall || pc == sr4export)
+    return 1;
 
   /* Get the unwind descriptor corresponding to PC, return zero
      if no unwind was found.  */
@@ -1589,31 +1618,69 @@ in_solib_call_trampoline (pc, name)
     return 0;
 
   /* If this isn't a linker stub, then return now.  */
-  if (u->stub_type != IMPORT
-      && u->stub_type != EXPORT)
+  if (u->stub_type == 0)
     return 0;
 
+  /* By definition a long-branch stub is a call stub.  */
+  if (u->stub_type == LONG_BRANCH)
+    return 1;
+
   /* The call and return path execute the same instructions within
      an IMPORT stub!  So an IMPORT stub is both a call and return
      trampoline.  */
   if (u->stub_type == IMPORT)
     return 1;
 
-  /* The linker may group many EXPORT stubs into one unwind entry.  So
-     lookup the minimal symbol and use that as the beginning of this
-     particular stub.  */
-  minsym = lookup_minimal_symbol_by_pc (pc);
-  if (minsym == NULL)
-    return 0;
+  if (u->stub_type == EXPORT)
+    {
+      /* The linker may group many EXPORT stubs into one unwind entry.  So
+        lookup the minimal symbol and use that as the beginning of this
+        particular stub.  */
+      minsym = lookup_minimal_symbol_by_pc (pc);
+      if (minsym == NULL)
+       return 0;
 
-  /* Export stubs have distinct call and return paths.  The first
-     two instructions are the call path, following four are the
+      /* Export stubs have distinct call and return paths.  The first
+        two instructions are the call path, following four are the
+        return path.  */
+      return (pc >= SYMBOL_VALUE (minsym) && pc < SYMBOL_VALUE (minsym) + 8);
+    }
+
+  /* Parameter relocation stubs always have a call path and may have a
      return path.  */
-  return (pc >= SYMBOL_VALUE (minsym) && pc < SYMBOL_VALUE (minsym) + 8);
+  if (u->stub_type == PARAMETER_RELOCATION)
+    {
+      CORE_ADDR addr;
+
+      /* Search forward from the current PC until we hit a branch
+        or the end of the stub.  */
+      for (addr = pc; addr <= u->region_end; addr += 4)
+       {
+         unsigned long insn;
+
+         insn = read_memory_integer (addr, 4);
+
+         /* Does it look like a bl?  If so then it's the call path, if
+            we find a bv first, then we're on the return path.  */
+         if ((insn & 0xfc00e000) == 0xe8000000)
+           return 1;
+         else if ((insn & 0xfc00e001) == 0xe800c000)
+           return 0;
+       }
+
+      /* Should never happen.  */
+      warning ("Unable to find branch in parameter relocation stub.\n");
+      return 0;
+    }
+
+  /* Unknown stub type.  For now, just return zero.  */
+  return 0;
 }
 
-/* Return one if PC is in the return path of a shared library trampoline,
-   else return zero.  */
+/* Return one if PC is in the return path of a trampoline, else return zero.
+
+   Note we return one for *any* call trampoline (long-call, arg-reloc), not
+   just shared library trampolines (import, export).  */
 
 in_solib_return_trampoline (pc, name)
      CORE_ADDR pc;
@@ -1628,9 +1695,9 @@ in_solib_return_trampoline (pc, name)
   if (!u)
     return 0;
 
-  /* If this isn't a linker stub, then return now.  */
-  if (u->stub_type != IMPORT
-      && u->stub_type != EXPORT)
+  /* If this isn't a linker stub or it's just a long branch stub, then
+     return zero.  */
+  if (u->stub_type == 0 || u->stub_type == LONG_BRANCH)
     return 0;
 
   /* The call and return path execute the same instructions within
@@ -1639,17 +1706,52 @@ in_solib_return_trampoline (pc, name)
   if (u->stub_type == IMPORT)
     return 1;
 
-  /* The linker may group many EXPORT stubs into one unwind entry.  So
-     lookup the minimal symbol and use that as the beginning of this
-     particular stub.  */
-  minsym = lookup_minimal_symbol_by_pc (pc);
-  if (minsym == NULL)
-    return 0;
+  if (u->stub_type == EXPORT)
+    {
+      /* The linker may group many EXPORT stubs into one unwind entry.  So
+        lookup the minimal symbol and use that as the beginning of this
+        particular stub.  */
+      minsym = lookup_minimal_symbol_by_pc (pc);
+      if (minsym == NULL)
+       return 0;
 
-  /* Export stubs have distinct call and return paths.  The first
-     two instructions are the call path, following four are the
+      /* Export stubs have distinct call and return paths.  The first
+        two instructions are the call path, following four are the
+        return path.  */
+      return (pc >= SYMBOL_VALUE (minsym) + 8
+             && pc < SYMBOL_VALUE (minsym) + 20);
+    }
+
+  /* Parameter relocation stubs always have a call path and may have a
      return path.  */
-  return (pc >= SYMBOL_VALUE (minsym) + 8 && pc < SYMBOL_VALUE (minsym) + 20);
+  if (u->stub_type == PARAMETER_RELOCATION)
+    {
+      CORE_ADDR addr;
+
+      /* Search forward from the current PC until we hit a branch
+        or the end of the stub.  */
+      for (addr = pc; addr <= u->region_end; addr += 4)
+       {
+         unsigned long insn;
+
+         insn = read_memory_integer (addr, 4);
+
+         /* Does it look like a bl?  If so then it's the call path, if
+            we find a bv first, then we're on the return path.  */
+         if ((insn & 0xfc00e000) == 0xe8000000)
+           return 0;
+         else if ((insn & 0xfc00e001) == 0xe800c000)
+           return 1;
+       }
+
+      /* Should never happen.  */
+      warning ("Unable to find branch in parameter relocation stub.\n");
+      return 0;
+    }
+
+  /* Unknown stub type.  For now, just return zero.  */
+  return 0;
+
 }
 
 /* Figure out if PC is in a trampoline, and if so find out where