2004-11-30 Randolph Chung <tausq@debian.org>
authorRandolph Chung <tausq@debian.org>
Wed, 1 Dec 2004 06:58:57 +0000 (06:58 +0000)
committerRandolph Chung <tausq@debian.org>
Wed, 1 Dec 2004 06:58:57 +0000 (06:58 +0000)
* hppa-linux-tdep.c (insns_match_pattern_relaxed): New function.
(hppa_linux_in_dyncall): Check that we are inside the range of
$$dyncall, not necessarily at the first insn.
(hppa_linux_in_solib_call_trampoline): Identify a trampoline
even if the pc does not point to the first insn of the trampoline.

gdb/ChangeLog
gdb/hppa-linux-tdep.c

index 379b0e12901f38fa13a162b967738f2d9ce1981d..6e1576baa468674c18ebaf5da85e61ee9efe0619 100644 (file)
@@ -1,3 +1,11 @@
+2004-11-30  Randolph Chung  <tausq@debian.org>
+
+       * hppa-linux-tdep.c (insns_match_pattern_relaxed): New function.
+       (hppa_linux_in_dyncall): Check that we are inside the range of 
+       $$dyncall, not necessarily at the first insn.
+       (hppa_linux_in_solib_call_trampoline): Identify a trampoline 
+       even if the pc does not point to the first insn of the trampoline.
+
 2004-11-30  Randolph Chung  <tausq@debian.org>
 
        * breakpoint.c (break_at_finish_command): Delete.
index b7a00bcd2483d2251065bae927496bd5bad237b6..4a7657aa614b2710156ac2064e3912b2509b4fb0 100644 (file)
@@ -161,10 +161,39 @@ insns_match_pattern (CORE_ADDR pc,
   return 1;
 }
 
+/* The relaxed version of the insn matcher allows us to match from somewhere
+   inside the pattern, by looking backwards in the instruction scheme.  */
+static int
+insns_match_pattern_relaxed (CORE_ADDR pc,
+                            struct insn_pattern *pattern,
+                            unsigned int *insn)
+{
+  int pat_len = 0;
+  int offset;
+
+  while (pattern[pat_len].mask)
+    pat_len++;
+
+  for (offset = 0; offset < pat_len; offset++)
+    {
+      if (insns_match_pattern (pc - offset * 4,
+                              pattern, insn))
+       return 1;
+    }
+
+  return 0;
+}
+
 static int
 hppa_linux_in_dyncall (CORE_ADDR pc)
 {
-  return pc == hppa_symbol_address("$$dyncall");
+  struct unwind_table_entry *u;
+  u = find_unwind_entry (hppa_symbol_address ("$$dyncall"));
+
+  if (!u)
+    return 0;
+       
+  return pc >= u->region_start && pc <= u->region_end;
 }
 
 /* There are several kinds of "trampolines" that we need to deal with:
@@ -182,13 +211,20 @@ hppa_linux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
 {
   unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
   int r;
+  struct unwind_table_entry *u;
+
+  /* on hppa-linux, linker stubs have no unwind information.  Since the pattern
+     matching for linker stubs can be quite slow, we try to avoid it if
+     we can.  */
+  u = find_unwind_entry (pc);
 
   r = in_plt_section (pc, name)
       || hppa_linux_in_dyncall (pc)
-      || insns_match_pattern (pc, hppa_import_stub, insn)
-      || insns_match_pattern (pc, hppa_import_pic_stub, insn)
-      || insns_match_pattern (pc, hppa_long_branch_stub, insn)
-      || insns_match_pattern (pc, hppa_long_branch_pic_stub, insn);
+      || (u == NULL
+         && (insns_match_pattern_relaxed (pc, hppa_import_stub, insn)
+             || insns_match_pattern_relaxed (pc, hppa_import_pic_stub, insn)
+             || insns_match_pattern_relaxed (pc, hppa_long_branch_stub, insn)
+             || insns_match_pattern_relaxed (pc, hppa_long_branch_pic_stub, insn)));
 
   return r;
 }