This is the mail archive of the gdb-patches@sources.redhat.com 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] Shuffle around some hppa code


A big patch that doesn't do very much; moves hpux-specific stuff into
hppa-hpux-tdep.c; makes some utility functions non-static so that
hppa-linux can use them.

Tested on hppa2.0w-hp-hpux11.11

ok to apply?

randolph

2004-04-18  Randolph Chung  <tausq@debian.org>

	* hppa-tdep.h (find_unwind_entry, hppa_get_field, hppa_extract_5_load)
	(hppa_extract_5R_store, hppa_extract_5r_store, hppa_extract_17)
	(hppa_extract_21, hppa_extract_14, hppa_low_sign_extend)
	(hppa_sign_extend): Add prototype.
	* hppa-tdep.c (get_field, extract_5_load, extract_5R_store)
	(extract_5r_store, extract_17, extract_21, extract_14, low_sign_extend)
	(sign_extend): Rename with hppa_ prefix and make non-static.  Other
	hppa targets will also use these functions.
	(find_unwind_entry): Remove prototype (moved to hppa-tdep.h).
	(hppa_in_solib_call_trampoline, hppa_in_solib_return_trampoline)
	(hppa_skip_trampoline_code): Move to hppa-hpux-tdep.c
	(hppa_gdbarch_init): Remove gdbarch setting of 
	skip_trampoline_code, in_solib_call_trampoline and
	in_solib_return_trampoline.
	* hppa-hpux-tdep.c (hppa32_hpux_in_solib_call_trampoline)
	(hppa64_hpux_in_solib_call_trampoline): New functions, split from
	hppa_in_solib_call_trampoline.
	(hppa_hpux_in_solib_return_trampoline, hppa_hpux_skip_trampoline_code):
	Moved from hppa-tdep.c.
 	(hppa_hpux_init_abi): Set gdbarch for skip_trampoline_code, 
	in_solib_call_trampoline and in_solib_return_trampoline.

Index: hppa-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.h,v
retrieving revision 1.3
diff -u -p -r1.3 hppa-tdep.h
--- hppa-tdep.h	17 Apr 2004 17:41:10 -0000	1.3
+++ hppa-tdep.h	19 Apr 2004 06:10:35 -0000
@@ -104,6 +104,8 @@ enum unwind_stub_types
     IMPORT_SHLIB = 12,
   };
 
+struct unwind_table_entry *find_unwind_entry (CORE_ADDR);
+
 /* We use the objfile->obj_private pointer for two things:
  * 1.  An unwind table;
  *
@@ -133,5 +135,15 @@ struct hppa_objfile_private
   };
 
 extern const struct objfile_data *hppa_objfile_priv_data;
+
+int hppa_get_field (unsigned word, int from, int to);
+int hppa_extract_5_load (unsigned int);
+unsigned hppa_extract_5R_store (unsigned int);
+unsigned hppa_extract_5r_store (unsigned int);
+int hppa_extract_17 (unsigned int);
+int hppa_extract_21 (unsigned);
+int hppa_extract_14 (unsigned);
+int hppa_low_sign_extend (unsigned int, unsigned int);
+int hppa_sign_extend (unsigned int, unsigned int);
 
 #endif  /* HPPA_TDEP_H */
Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.147
diff -u -p -r1.147 hppa-tdep.c
--- hppa-tdep.c	17 Apr 2004 17:41:10 -0000	1.147
+++ hppa-tdep.c	19 Apr 2004 06:10:35 -0000
@@ -86,28 +86,8 @@ const struct objfile_data *hppa_objfile_
 #define UNWIND_ENTRY_SIZE 16
 #define STUB_UNWIND_ENTRY_SIZE 8
 
-static int get_field (unsigned word, int from, int to);
-
-static int extract_5_load (unsigned int);
-
-static unsigned extract_5R_store (unsigned int);
-
-static unsigned extract_5r_store (unsigned int);
-
-struct unwind_table_entry *find_unwind_entry (CORE_ADDR);
-
-static int extract_17 (unsigned int);
-
-static int extract_21 (unsigned);
-
-static int extract_14 (unsigned);
-
 static void unwind_command (char *, int);
 
-static int low_sign_extend (unsigned int, unsigned int);
-
-static int sign_extend (unsigned int, unsigned int);
-
 static int hppa_alignof (struct type *);
 
 static int prologue_inst_adjust_sp (unsigned long);
@@ -244,16 +224,16 @@ hppa64_return_value (struct gdbarch *gdb
 /* This assumes that no garbage lies outside of the lower bits of 
    value. */
 
-static int
-sign_extend (unsigned val, unsigned bits)
+int
+hppa_sign_extend (unsigned val, unsigned bits)
 {
   return (int) (val >> (bits - 1) ? (-1 << bits) | val : val);
 }
 
 /* For many immediate values the sign bit is the low bit! */
 
-static int
-low_sign_extend (unsigned val, unsigned bits)
+int
+hppa_low_hppa_sign_extend (unsigned val, unsigned bits)
 {
   return (int) ((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
 }
@@ -261,74 +241,74 @@ low_sign_extend (unsigned val, unsigned 
 /* Extract the bits at positions between FROM and TO, using HP's numbering
    (MSB = 0). */
 
-static int
-get_field (unsigned word, int from, int to)
+int
+hppa_get_field (unsigned word, int from, int to)
 {
   return ((word) >> (31 - (to)) & ((1 << ((to) - (from) + 1)) - 1));
 }
 
 /* extract the immediate field from a ld{bhw}s instruction */
 
-static int
-extract_5_load (unsigned word)
+int
+hppa_extract_5_load (unsigned word)
 {
-  return low_sign_extend (word >> 16 & MASK_5, 5);
+  return hppa_low_hppa_sign_extend (word >> 16 & MASK_5, 5);
 }
 
 /* extract the immediate field from a break instruction */
 
-static unsigned
-extract_5r_store (unsigned word)
+unsigned
+hppa_extract_5r_store (unsigned word)
 {
   return (word & MASK_5);
 }
 
 /* extract the immediate field from a {sr}sm instruction */
 
-static unsigned
-extract_5R_store (unsigned word)
+unsigned
+hppa_extract_5R_store (unsigned word)
 {
   return (word >> 16 & MASK_5);
 }
 
 /* extract a 14 bit immediate field */
 
-static int
-extract_14 (unsigned word)
+int
+hppa_extract_14 (unsigned word)
 {
-  return low_sign_extend (word & MASK_14, 14);
+  return hppa_low_hppa_sign_extend (word & MASK_14, 14);
 }
 
 /* extract a 21 bit constant */
 
-static int
-extract_21 (unsigned word)
+int
+hppa_extract_21 (unsigned word)
 {
   int val;
 
   word &= MASK_21;
   word <<= 11;
-  val = get_field (word, 20, 20);
+  val = hppa_get_field (word, 20, 20);
   val <<= 11;
-  val |= get_field (word, 9, 19);
+  val |= hppa_get_field (word, 9, 19);
   val <<= 2;
-  val |= get_field (word, 5, 6);
+  val |= hppa_get_field (word, 5, 6);
   val <<= 5;
-  val |= get_field (word, 0, 4);
+  val |= hppa_get_field (word, 0, 4);
   val <<= 2;
-  val |= get_field (word, 7, 8);
-  return sign_extend (val, 21) << 11;
+  val |= hppa_get_field (word, 7, 8);
+  return hppa_sign_extend (val, 21) << 11;
 }
 
 /* extract a 17 bit constant from branch instructions, returning the
    19 bit signed value. */
 
-static int
-extract_17 (unsigned word)
+int
+hppa_extract_17 (unsigned word)
 {
-  return sign_extend (get_field (word, 19, 28) |
-		      get_field (word, 29, 29) << 10 |
-		      get_field (word, 11, 15) << 11 |
+  return hppa_sign_extend (hppa_get_field (word, 19, 28) |
+		      hppa_get_field (word, 29, 29) << 10 |
+		      hppa_get_field (word, 11, 15) << 11 |
 		      (word & 0x1) << 16, 17) << 2;
 }
 
@@ -1077,515 +1057,6 @@ hppa_alignof (struct type *type)
     }
 }
 
-/* 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).  */
-
-static int
-hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name)
-{
-  struct minimal_symbol *minsym;
-  struct unwind_table_entry *u;
-  static CORE_ADDR dyncall = 0;
-  static CORE_ADDR sr4export = 0;
-
-#ifdef GDB_TARGET_IS_HPPA_20W
-  /* PA64 has a completely different stub/trampoline scheme.  Is it
-     better?  Maybe.  It's certainly harder to determine with any
-     certainty that we are in a stub because we can not refer to the
-     unwinders to help. 
-
-     The heuristic is simple.  Try to lookup the current PC value in th
-     minimal symbol table.  If that fails, then assume we are not in a
-     stub and return.
-
-     Then see if the PC value falls within the section bounds for the
-     section containing the minimal symbol we found in the first
-     step.  If it does, then assume we are not in a stub and return.
-
-     Finally peek at the instructions to see if they look like a stub.  */
-  {
-    struct minimal_symbol *minsym;
-    asection *sec;
-    CORE_ADDR addr;
-    int insn, i;
-
-    minsym = lookup_minimal_symbol_by_pc (pc);
-    if (! minsym)
-      return 0;
-
-    sec = SYMBOL_BFD_SECTION (minsym);
-
-    if (bfd_get_section_vma (sec->owner, sec) <= pc
-	&& pc < (bfd_get_section_vma (sec->owner, sec)
-		 + bfd_section_size (sec->owner, sec)))
-      return 0;
-
-    /* We might be in a stub.  Peek at the instructions.  Stubs are 3
-       instructions long. */
-    insn = read_memory_integer (pc, 4);
-
-    /* Find out where we think we are within the stub.  */
-    if ((insn & 0xffffc00e) == 0x53610000)
-      addr = pc;
-    else if ((insn & 0xffffffff) == 0xe820d000)
-      addr = pc - 4;
-    else if ((insn & 0xffffc00e) == 0x537b0000)
-      addr = pc - 8;
-    else
-      return 0;
-
-    /* Now verify each insn in the range looks like a stub instruction.  */
-    insn = read_memory_integer (addr, 4);
-    if ((insn & 0xffffc00e) != 0x53610000)
-      return 0;
-	
-    /* Now verify each insn in the range looks like a stub instruction.  */
-    insn = read_memory_integer (addr + 4, 4);
-    if ((insn & 0xffffffff) != 0xe820d000)
-      return 0;
-    
-    /* Now verify each insn in the range looks like a stub instruction.  */
-    insn = read_memory_integer (addr + 8, 4);
-    if ((insn & 0xffffc00e) != 0x537b0000)
-      return 0;
-
-    /* Looks like a stub.  */
-    return 1;
-  }
-#endif
-
-  /* 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, NULL);
-      if (minsym)
-	dyncall = SYMBOL_VALUE_ADDRESS (minsym);
-      else
-	dyncall = -1;
-    }
-
-  if (!sr4export)
-    {
-      minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
-      if (minsym)
-	sr4export = SYMBOL_VALUE_ADDRESS (minsym);
-      else
-	sr4export = -1;
-    }
-
-  if (pc == dyncall || pc == sr4export)
-    return 1;
-
-  minsym = lookup_minimal_symbol_by_pc (pc);
-  if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
-    return 1;
-
-  /* Get the unwind descriptor corresponding to PC, return zero
-     if no unwind was found.  */
-  u = find_unwind_entry (pc);
-  if (!u)
-    return 0;
-
-  /* If this isn't a linker stub, then return now.  */
-  if (u->stub_unwind.stub_type == 0)
-    return 0;
-
-  /* By definition a long-branch stub is a call stub.  */
-  if (u->stub_unwind.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_unwind.stub_type == IMPORT)
-    return 1;
-
-  /* Parameter relocation stubs always have a call path and may have a
-     return path.  */
-  if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
-      || u->stub_unwind.stub_type == EXPORT)
-    {
-      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 or be first, then we're on the return path.  */
-	  if ((insn & 0xfc00e000) == 0xe8000000)
-	    return 1;
-	  else if ((insn & 0xfc00e001) == 0xe800c000
-		   || (insn & 0xfc000000) == 0xe0000000)
-	    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 trampoline, else return zero.
-
-   Note we return one for *any* call trampoline (long-call, arg-reloc), not
-   just shared library trampolines (import, export).  */
-
-static int
-hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name)
-{
-  struct unwind_table_entry *u;
-
-  /* Get the unwind descriptor corresponding to PC, return zero
-     if no unwind was found.  */
-  u = find_unwind_entry (pc);
-  if (!u)
-    return 0;
-
-  /* If this isn't a linker stub or it's just a long branch stub, then
-     return zero.  */
-  if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
-    return 0;
-
-  /* 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_unwind.stub_type == IMPORT)
-    return 1;
-
-  /* Parameter relocation stubs always have a call path and may have a
-     return path.  */
-  if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
-      || u->stub_unwind.stub_type == EXPORT)
-    {
-      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 or be first, then we're on the return path.  */
-	  if ((insn & 0xfc00e000) == 0xe8000000)
-	    return 0;
-	  else if ((insn & 0xfc00e001) == 0xe800c000
-		   || (insn & 0xfc000000) == 0xe0000000)
-	    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
-   the trampoline will jump to.  If not in a trampoline, return zero.
-
-   Simple code examination probably is not a good idea since the code
-   sequences in trampolines can also appear in user code.
-
-   We use unwinds and information from the minimal symbol table to
-   determine when we're in a trampoline.  This won't work for ELF
-   (yet) since it doesn't create stub unwind entries.  Whether or
-   not ELF will create stub unwinds or normal unwinds for linker
-   stubs is still being debated.
-
-   This should handle simple calls through dyncall or sr4export,
-   long calls, argument relocation stubs, and dyncall/sr4export
-   calling an argument relocation stub.  It even handles some stubs
-   used in dynamic executables.  */
-
-static CORE_ADDR
-hppa_skip_trampoline_code (CORE_ADDR pc)
-{
-  long orig_pc = pc;
-  long prev_inst, curr_inst, loc;
-  static CORE_ADDR dyncall = 0;
-  static CORE_ADDR dyncall_external = 0;
-  static CORE_ADDR sr4export = 0;
-  struct minimal_symbol *msym;
-  struct unwind_table_entry *u;
-
-  /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
-     new exec file */
-
-  if (!dyncall)
-    {
-      msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
-      if (msym)
-	dyncall = SYMBOL_VALUE_ADDRESS (msym);
-      else
-	dyncall = -1;
-    }
-
-  if (!dyncall_external)
-    {
-      msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
-      if (msym)
-	dyncall_external = SYMBOL_VALUE_ADDRESS (msym);
-      else
-	dyncall_external = -1;
-    }
-
-  if (!sr4export)
-    {
-      msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
-      if (msym)
-	sr4export = SYMBOL_VALUE_ADDRESS (msym);
-      else
-	sr4export = -1;
-    }
-
-  /* Addresses passed to dyncall may *NOT* be the actual address
-     of the function.  So we may have to do something special.  */
-  if (pc == dyncall)
-    {
-      pc = (CORE_ADDR) read_register (22);
-
-      /* If bit 30 (counting from the left) is on, then pc is the address of
-         the PLT entry for this function, not the address of the function
-         itself.  Bit 31 has meaning too, but only for MPE.  */
-      if (pc & 0x2)
-	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
-    }
-  if (pc == dyncall_external)
-    {
-      pc = (CORE_ADDR) read_register (22);
-      pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
-    }
-  else if (pc == sr4export)
-    pc = (CORE_ADDR) (read_register (22));
-
-  /* Get the unwind descriptor corresponding to PC, return zero
-     if no unwind was found.  */
-  u = find_unwind_entry (pc);
-  if (!u)
-    return 0;
-
-  /* If this isn't a linker stub, then return now.  */
-  /* elz: attention here! (FIXME) because of a compiler/linker 
-     error, some stubs which should have a non zero stub_unwind.stub_type 
-     have unfortunately a value of zero. So this function would return here
-     as if we were not in a trampoline. To fix this, we go look at the partial
-     symbol information, which reports this guy as a stub.
-     (FIXME): Unfortunately, we are not that lucky: it turns out that the 
-     partial symbol information is also wrong sometimes. This is because 
-     when it is entered (somread.c::som_symtab_read()) it can happen that
-     if the type of the symbol (from the som) is Entry, and the symbol is
-     in a shared library, then it can also be a trampoline.  This would
-     be OK, except that I believe the way they decide if we are ina shared library
-     does not work. SOOOO..., even if we have a regular function w/o trampolines
-     its minimal symbol can be assigned type mst_solib_trampoline.
-     Also, if we find that the symbol is a real stub, then we fix the unwind
-     descriptor, and define the stub type to be EXPORT.
-     Hopefully this is correct most of the times. */
-  if (u->stub_unwind.stub_type == 0)
-    {
-
-/* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
-   we can delete all the code which appears between the lines */
-/*--------------------------------------------------------------------------*/
-      msym = lookup_minimal_symbol_by_pc (pc);
-
-      if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
-	return orig_pc == pc ? 0 : pc & ~0x3;
-
-      else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
-	{
-	  struct objfile *objfile;
-	  struct minimal_symbol *msymbol;
-	  int function_found = 0;
-
-	  /* go look if there is another minimal symbol with the same name as 
-	     this one, but with type mst_text. This would happen if the msym
-	     is an actual trampoline, in which case there would be another
-	     symbol with the same name corresponding to the real function */
-
-	  ALL_MSYMBOLS (objfile, msymbol)
-	  {
-	    if (MSYMBOL_TYPE (msymbol) == mst_text
-		&& DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
-	      {
-		function_found = 1;
-		break;
-	      }
-	  }
-
-	  if (function_found)
-	    /* the type of msym is correct (mst_solib_trampoline), but
-	       the unwind info is wrong, so set it to the correct value */
-	    u->stub_unwind.stub_type = EXPORT;
-	  else
-	    /* the stub type info in the unwind is correct (this is not a
-	       trampoline), but the msym type information is wrong, it
-	       should be mst_text. So we need to fix the msym, and also
-	       get out of this function */
-	    {
-	      MSYMBOL_TYPE (msym) = mst_text;
-	      return orig_pc == pc ? 0 : pc & ~0x3;
-	    }
-	}
-
-/*--------------------------------------------------------------------------*/
-    }
-
-  /* It's a stub.  Search for a branch and figure out where it goes.
-     Note we have to handle multi insn branch sequences like ldil;ble.
-     Most (all?) other branches can be determined by examining the contents
-     of certain registers and the stack.  */
-
-  loc = pc;
-  curr_inst = 0;
-  prev_inst = 0;
-  while (1)
-    {
-      /* Make sure we haven't walked outside the range of this stub.  */
-      if (u != find_unwind_entry (loc))
-	{
-	  warning ("Unable to find branch in linker stub");
-	  return orig_pc == pc ? 0 : pc & ~0x3;
-	}
-
-      prev_inst = curr_inst;
-      curr_inst = read_memory_integer (loc, 4);
-
-      /* Does it look like a branch external using %r1?  Then it's the
-         branch from the stub to the actual function.  */
-      if ((curr_inst & 0xffe0e000) == 0xe0202000)
-	{
-	  /* Yup.  See if the previous instruction loaded
-	     a value into %r1.  If so compute and return the jump address.  */
-	  if ((prev_inst & 0xffe00000) == 0x20200000)
-	    return (extract_21 (prev_inst) + extract_17 (curr_inst)) & ~0x3;
-	  else
-	    {
-	      warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
-	      return orig_pc == pc ? 0 : pc & ~0x3;
-	    }
-	}
-
-      /* Does it look like a be 0(sr0,%r21)? OR 
-         Does it look like a be, n 0(sr0,%r21)? OR 
-         Does it look like a bve (r21)? (this is on PA2.0)
-         Does it look like a bve, n(r21)? (this is also on PA2.0)
-         That's the branch from an
-         import stub to an export stub.
-
-         It is impossible to determine the target of the branch via
-         simple examination of instructions and/or data (consider
-         that the address in the plabel may be the address of the
-         bind-on-reference routine in the dynamic loader).
-
-         So we have try an alternative approach.
-
-         Get the name of the symbol at our current location; it should
-         be a stub symbol with the same name as the symbol in the
-         shared library.
-
-         Then lookup a minimal symbol with the same name; we should
-         get the minimal symbol for the target routine in the shared
-         library as those take precedence of import/export stubs.  */
-      if ((curr_inst == 0xe2a00000) ||
-	  (curr_inst == 0xe2a00002) ||
-	  (curr_inst == 0xeaa0d000) ||
-	  (curr_inst == 0xeaa0d002))
-	{
-	  struct minimal_symbol *stubsym, *libsym;
-
-	  stubsym = lookup_minimal_symbol_by_pc (loc);
-	  if (stubsym == NULL)
-	    {
-	      warning ("Unable to find symbol for 0x%lx", loc);
-	      return orig_pc == pc ? 0 : pc & ~0x3;
-	    }
-
-	  libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
-	  if (libsym == NULL)
-	    {
-	      warning ("Unable to find library symbol for %s\n",
-		       DEPRECATED_SYMBOL_NAME (stubsym));
-	      return orig_pc == pc ? 0 : pc & ~0x3;
-	    }
-
-	  return SYMBOL_VALUE (libsym);
-	}
-
-      /* Does it look like bl X,%rp or bl X,%r0?  Another way to do a
-         branch from the stub to the actual function.  */
-      /*elz */
-      else if ((curr_inst & 0xffe0e000) == 0xe8400000
-	       || (curr_inst & 0xffe0e000) == 0xe8000000
-	       || (curr_inst & 0xffe0e000) == 0xe800A000)
-	return (loc + extract_17 (curr_inst) + 8) & ~0x3;
-
-      /* Does it look like bv (rp)?   Note this depends on the
-         current stack pointer being the same as the stack
-         pointer in the stub itself!  This is a branch on from the
-         stub back to the original caller.  */
-      /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */
-      else if ((curr_inst & 0xffe0f000) == 0xe840c000)
-	{
-	  /* Yup.  See if the previous instruction loaded
-	     rp from sp - 8.  */
-	  if (prev_inst == 0x4bc23ff1)
-	    return (read_memory_integer
-		    (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
-	  else
-	    {
-	      warning ("Unable to find restore of %%rp before bv (%%rp).");
-	      return orig_pc == pc ? 0 : pc & ~0x3;
-	    }
-	}
-
-      /* elz: added this case to capture the new instruction
-         at the end of the return part of an export stub used by
-         the PA2.0: BVE, n (rp) */
-      else if ((curr_inst & 0xffe0f000) == 0xe840d000)
-	{
-	  return (read_memory_integer
-		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
-	}
-
-      /* What about be,n 0(sr0,%rp)?  It's just another way we return to
-         the original caller from the stub.  Used in dynamic executables.  */
-      else if (curr_inst == 0xe0400002)
-	{
-	  /* The value we jump to is sitting in sp - 24.  But that's
-	     loaded several instructions before the be instruction.
-	     I guess we could check for the previous instruction being
-	     mtsp %r1,%sr0 if we want to do sanity checking.  */
-	  return (read_memory_integer
-		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
-	}
-
-      /* Haven't found the branch yet, but we're still in the stub.
-         Keep looking.  */
-      loc += 4;
-    }
-}
-
-
 /* For the given instruction (INST), return any adjustment it makes
    to the stack pointer or zero for no adjustment. 
 
@@ -1599,11 +1070,11 @@ prologue_inst_adjust_sp (unsigned long i
 
   /* The most common way to perform a stack adjustment ldo X(sp),sp */
   if ((inst & 0xffffc000) == 0x37de0000)
-    return extract_14 (inst);
+    return hppa_extract_14 (inst);
 
   /* stwm X,D(sp) */
   if ((inst & 0xffe00000) == 0x6fc00000)
-    return extract_14 (inst);
+    return hppa_extract_14 (inst);
 
   /* std,ma X,D(sp) */
   if ((inst & 0xffe00008) == 0x73c00008)
@@ -1613,16 +1084,16 @@ prologue_inst_adjust_sp (unsigned long i
      save high bits in save_high21 for later use.  */
   if ((inst & 0xffe00000) == 0x28200000)
     {
-      save_high21 = extract_21 (inst);
+      save_high21 = hppa_extract_21 (inst);
       return 0;
     }
 
   if ((inst & 0xffff0000) == 0x343e0000)
-    return save_high21 + extract_14 (inst);
+    return save_high21 + hppa_extract_14 (inst);
 
   /* fstws as used by the HP compilers.  */
   if ((inst & 0xffffffe0) == 0x2fd01220)
-    return extract_5_load (inst);
+    return hppa_extract_5_load (inst);
 
   /* No adjustment.  */
   return 0;
@@ -1671,17 +1142,17 @@ inst_saves_gr (unsigned long inst)
       || (inst >> 26) == 0x1f
       || ((inst >> 26) == 0x1f
 	  && ((inst >> 6) == 0xa)))
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
 
   /* Does it look like a std?  */
   if ((inst >> 26) == 0x1c
       || ((inst >> 26) == 0x03
 	  && ((inst >> 6) & 0xf) == 0xb))
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
 
   /* Does it look like a stwm?  GCC & HPC may use this in prologues. */
   if ((inst >> 26) == 0x1b)
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
 
   /* Does it look like sth or stb?  HPC versions 9.0 and later use these
      too.  */
@@ -1689,7 +1160,7 @@ inst_saves_gr (unsigned long inst)
       || ((inst >> 26) == 0x3
 	  && (((inst >> 6) & 0xf) == 0x8
 	      || (inst >> 6) & 0xf) == 0x9))
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
 
   return 0;
 }
@@ -1707,14 +1178,14 @@ inst_saves_fr (unsigned long inst)
 {
   /* is this an FSTD ? */
   if ((inst & 0xfc00dfc0) == 0x2c001200)
-    return extract_5r_store (inst);
+    return hppa_extract_5r_store (inst);
   if ((inst & 0xfc000002) == 0x70000002)
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
   /* is this an FSTW ? */
   if ((inst & 0xfc00df80) == 0x24001200)
-    return extract_5r_store (inst);
+    return hppa_extract_5r_store (inst);
   if ((inst & 0xfc000002) == 0x7c000000)
-    return extract_5R_store (inst);
+    return hppa_extract_5R_store (inst);
   return 0;
 }
 
@@ -2137,7 +1608,7 @@ hppa_frame_cache (struct frame_info *nex
 	    && (!u->Save_SP || reg != HPPA_FP_REGNUM))
 	  {
 	    saved_gr_mask &= ~(1 << reg);
-	    if ((inst >> 26) == 0x1b && extract_14 (inst) >= 0)
+	    if ((inst >> 26) == 0x1b && hppa_extract_14 (inst) >= 0)
 	      /* stwm with a positive displacement is a _post_
 		 _modify_.  */
 	      cache->saved_regs[reg].addr = 0;
@@ -2151,9 +1622,9 @@ hppa_frame_cache (struct frame_info *nex
 		if ((inst >> 26) == 0x1c)
 		  offset = (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3);
 		else if ((inst >> 26) == 0x03)
-		  offset = low_sign_extend (inst & 0x1f, 5);
+		  offset = hppa_low_hppa_sign_extend (inst & 0x1f, 5);
 		else
-		  offset = extract_14 (inst);
+		  offset = hppa_extract_14 (inst);
 		
 		/* Handle code with and without frame pointers.  */
 		if (u->Save_SP)
@@ -2175,7 +1646,7 @@ hppa_frame_cache (struct frame_info *nex
 	/* ldo X(%r3),%r1 or ldo X(%r30),%r1.  */
 	if ((inst & 0xffffc000) == 0x34610000
 	    || (inst & 0xffffc000) == 0x37c10000)
-	  fp_loc = extract_14 (inst);
+	  fp_loc = hppa_extract_14 (inst);
 	
 	reg = inst_saves_fr (inst);
 	if (reg >= 12 && reg <= 21)
@@ -2652,10 +2123,6 @@ hppa_gdbarch_init (struct gdbarch_info i
   /* The following gdbarch vector elements do not depend on the address
      size, or in any other gdbarch element previously set.  */
   set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue);
-  set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
-  set_gdbarch_in_solib_call_trampoline (gdbarch, hppa_in_solib_call_trampoline);
-  set_gdbarch_in_solib_return_trampoline (gdbarch,
-                                          hppa_in_solib_return_trampoline);
   set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
   set_gdbarch_sp_regnum (gdbarch, HPPA_SP_REGNUM);
   set_gdbarch_fp0_regnum (gdbarch, HPPA_FP0_REGNUM);
Index: hppa-hpux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-hpux-tdep.c,v
retrieving revision 1.15
diff -u -p -r1.15 hppa-hpux-tdep.c
--- hppa-hpux-tdep.c	17 Apr 2004 17:41:10 -0000	1.15
+++ hppa-hpux-tdep.c	19 Apr 2004 06:10:35 -0000
@@ -164,6 +164,515 @@ hppa64_hpux_frame_find_saved_regs_in_sig
     }
 }
 
+/* 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).  */
+
+static int
+hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *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, NULL);
+      if (minsym)
+	dyncall = SYMBOL_VALUE_ADDRESS (minsym);
+      else
+	dyncall = -1;
+    }
+
+  if (!sr4export)
+    {
+      minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+      if (minsym)
+	sr4export = SYMBOL_VALUE_ADDRESS (minsym);
+      else
+	sr4export = -1;
+    }
+
+  if (pc == dyncall || pc == sr4export)
+    return 1;
+
+  minsym = lookup_minimal_symbol_by_pc (pc);
+  if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
+    return 1;
+
+  /* Get the unwind descriptor corresponding to PC, return zero
+     if no unwind was found.  */
+  u = find_unwind_entry (pc);
+  if (!u)
+    return 0;
+
+  /* If this isn't a linker stub, then return now.  */
+  if (u->stub_unwind.stub_type == 0)
+    return 0;
+
+  /* By definition a long-branch stub is a call stub.  */
+  if (u->stub_unwind.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_unwind.stub_type == IMPORT)
+    return 1;
+
+  /* Parameter relocation stubs always have a call path and may have a
+     return path.  */
+  if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
+      || u->stub_unwind.stub_type == EXPORT)
+    {
+      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 or be first, then we're on the return path.  */
+	  if ((insn & 0xfc00e000) == 0xe8000000)
+	    return 1;
+	  else if ((insn & 0xfc00e001) == 0xe800c000
+		   || (insn & 0xfc000000) == 0xe0000000)
+	    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;
+}
+
+static int
+hppa64_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
+{
+  /* PA64 has a completely different stub/trampoline scheme.  Is it
+     better?  Maybe.  It's certainly harder to determine with any
+     certainty that we are in a stub because we can not refer to the
+     unwinders to help. 
+
+     The heuristic is simple.  Try to lookup the current PC value in th
+     minimal symbol table.  If that fails, then assume we are not in a
+     stub and return.
+
+     Then see if the PC value falls within the section bounds for the
+     section containing the minimal symbol we found in the first
+     step.  If it does, then assume we are not in a stub and return.
+
+     Finally peek at the instructions to see if they look like a stub.  */
+  struct minimal_symbol *minsym;
+  asection *sec;
+  CORE_ADDR addr;
+  int insn, i;
+
+  minsym = lookup_minimal_symbol_by_pc (pc);
+  if (! minsym)
+    return 0;
+
+  sec = SYMBOL_BFD_SECTION (minsym);
+
+  if (bfd_get_section_vma (sec->owner, sec) <= pc
+      && pc < (bfd_get_section_vma (sec->owner, sec)
+		 + bfd_section_size (sec->owner, sec)))
+      return 0;
+
+  /* We might be in a stub.  Peek at the instructions.  Stubs are 3
+     instructions long. */
+  insn = read_memory_integer (pc, 4);
+
+  /* Find out where we think we are within the stub.  */
+  if ((insn & 0xffffc00e) == 0x53610000)
+    addr = pc;
+  else if ((insn & 0xffffffff) == 0xe820d000)
+    addr = pc - 4;
+  else if ((insn & 0xffffc00e) == 0x537b0000)
+    addr = pc - 8;
+  else
+    return 0;
+
+  /* Now verify each insn in the range looks like a stub instruction.  */
+  insn = read_memory_integer (addr, 4);
+  if ((insn & 0xffffc00e) != 0x53610000)
+    return 0;
+	
+  /* Now verify each insn in the range looks like a stub instruction.  */
+  insn = read_memory_integer (addr + 4, 4);
+  if ((insn & 0xffffffff) != 0xe820d000)
+    return 0;
+    
+  /* Now verify each insn in the range looks like a stub instruction.  */
+  insn = read_memory_integer (addr + 8, 4);
+  if ((insn & 0xffffc00e) != 0x537b0000)
+    return 0;
+
+  /* Looks like a stub.  */
+  return 1;
+}
+
+/* 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).  */
+
+static int
+hppa_hpux_in_solib_return_trampoline (CORE_ADDR pc, char *name)
+{
+  struct unwind_table_entry *u;
+
+  /* Get the unwind descriptor corresponding to PC, return zero
+     if no unwind was found.  */
+  u = find_unwind_entry (pc);
+  if (!u)
+    return 0;
+
+  /* If this isn't a linker stub or it's just a long branch stub, then
+     return zero.  */
+  if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
+    return 0;
+
+  /* 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_unwind.stub_type == IMPORT)
+    return 1;
+
+  /* Parameter relocation stubs always have a call path and may have a
+     return path.  */
+  if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
+      || u->stub_unwind.stub_type == EXPORT)
+    {
+      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 or be first, then we're on the return path.  */
+	  if ((insn & 0xfc00e000) == 0xe8000000)
+	    return 0;
+	  else if ((insn & 0xfc00e001) == 0xe800c000
+		   || (insn & 0xfc000000) == 0xe0000000)
+	    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
+   the trampoline will jump to.  If not in a trampoline, return zero.
+
+   Simple code examination probably is not a good idea since the code
+   sequences in trampolines can also appear in user code.
+
+   We use unwinds and information from the minimal symbol table to
+   determine when we're in a trampoline.  This won't work for ELF
+   (yet) since it doesn't create stub unwind entries.  Whether or
+   not ELF will create stub unwinds or normal unwinds for linker
+   stubs is still being debated.
+
+   This should handle simple calls through dyncall or sr4export,
+   long calls, argument relocation stubs, and dyncall/sr4export
+   calling an argument relocation stub.  It even handles some stubs
+   used in dynamic executables.  */
+
+static CORE_ADDR
+hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
+{
+  long orig_pc = pc;
+  long prev_inst, curr_inst, loc;
+  static CORE_ADDR dyncall = 0;
+  static CORE_ADDR dyncall_external = 0;
+  static CORE_ADDR sr4export = 0;
+  struct minimal_symbol *msym;
+  struct unwind_table_entry *u;
+
+  /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
+     new exec file */
+
+  if (!dyncall)
+    {
+      msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
+      if (msym)
+	dyncall = SYMBOL_VALUE_ADDRESS (msym);
+      else
+	dyncall = -1;
+    }
+
+  if (!dyncall_external)
+    {
+      msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
+      if (msym)
+	dyncall_external = SYMBOL_VALUE_ADDRESS (msym);
+      else
+	dyncall_external = -1;
+    }
+
+  if (!sr4export)
+    {
+      msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
+      if (msym)
+	sr4export = SYMBOL_VALUE_ADDRESS (msym);
+      else
+	sr4export = -1;
+    }
+
+  /* Addresses passed to dyncall may *NOT* be the actual address
+     of the function.  So we may have to do something special.  */
+  if (pc == dyncall)
+    {
+      pc = (CORE_ADDR) read_register (22);
+
+      /* If bit 30 (counting from the left) is on, then pc is the address of
+         the PLT entry for this function, not the address of the function
+         itself.  Bit 31 has meaning too, but only for MPE.  */
+      if (pc & 0x2)
+	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
+    }
+  if (pc == dyncall_external)
+    {
+      pc = (CORE_ADDR) read_register (22);
+      pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
+    }
+  else if (pc == sr4export)
+    pc = (CORE_ADDR) (read_register (22));
+
+  /* Get the unwind descriptor corresponding to PC, return zero
+     if no unwind was found.  */
+  u = find_unwind_entry (pc);
+  if (!u)
+    return 0;
+
+  /* If this isn't a linker stub, then return now.  */
+  /* elz: attention here! (FIXME) because of a compiler/linker 
+     error, some stubs which should have a non zero stub_unwind.stub_type 
+     have unfortunately a value of zero. So this function would return here
+     as if we were not in a trampoline. To fix this, we go look at the partial
+     symbol information, which reports this guy as a stub.
+     (FIXME): Unfortunately, we are not that lucky: it turns out that the 
+     partial symbol information is also wrong sometimes. This is because 
+     when it is entered (somread.c::som_symtab_read()) it can happen that
+     if the type of the symbol (from the som) is Entry, and the symbol is
+     in a shared library, then it can also be a trampoline.  This would
+     be OK, except that I believe the way they decide if we are ina shared library
+     does not work. SOOOO..., even if we have a regular function w/o trampolines
+     its minimal symbol can be assigned type mst_solib_trampoline.
+     Also, if we find that the symbol is a real stub, then we fix the unwind
+     descriptor, and define the stub type to be EXPORT.
+     Hopefully this is correct most of the times. */
+  if (u->stub_unwind.stub_type == 0)
+    {
+
+/* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
+   we can delete all the code which appears between the lines */
+/*--------------------------------------------------------------------------*/
+      msym = lookup_minimal_symbol_by_pc (pc);
+
+      if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
+	return orig_pc == pc ? 0 : pc & ~0x3;
+
+      else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
+	{
+	  struct objfile *objfile;
+	  struct minimal_symbol *msymbol;
+	  int function_found = 0;
+
+	  /* go look if there is another minimal symbol with the same name as 
+	     this one, but with type mst_text. This would happen if the msym
+	     is an actual trampoline, in which case there would be another
+	     symbol with the same name corresponding to the real function */
+
+	  ALL_MSYMBOLS (objfile, msymbol)
+	  {
+	    if (MSYMBOL_TYPE (msymbol) == mst_text
+		&& DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
+	      {
+		function_found = 1;
+		break;
+	      }
+	  }
+
+	  if (function_found)
+	    /* the type of msym is correct (mst_solib_trampoline), but
+	       the unwind info is wrong, so set it to the correct value */
+	    u->stub_unwind.stub_type = EXPORT;
+	  else
+	    /* the stub type info in the unwind is correct (this is not a
+	       trampoline), but the msym type information is wrong, it
+	       should be mst_text. So we need to fix the msym, and also
+	       get out of this function */
+	    {
+	      MSYMBOL_TYPE (msym) = mst_text;
+	      return orig_pc == pc ? 0 : pc & ~0x3;
+	    }
+	}
+
+/*--------------------------------------------------------------------------*/
+    }
+
+  /* It's a stub.  Search for a branch and figure out where it goes.
+     Note we have to handle multi insn branch sequences like ldil;ble.
+     Most (all?) other branches can be determined by examining the contents
+     of certain registers and the stack.  */
+
+  loc = pc;
+  curr_inst = 0;
+  prev_inst = 0;
+  while (1)
+    {
+      /* Make sure we haven't walked outside the range of this stub.  */
+      if (u != find_unwind_entry (loc))
+	{
+	  warning ("Unable to find branch in linker stub");
+	  return orig_pc == pc ? 0 : pc & ~0x3;
+	}
+
+      prev_inst = curr_inst;
+      curr_inst = read_memory_integer (loc, 4);
+
+      /* Does it look like a branch external using %r1?  Then it's the
+         branch from the stub to the actual function.  */
+      if ((curr_inst & 0xffe0e000) == 0xe0202000)
+	{
+	  /* Yup.  See if the previous instruction loaded
+	     a value into %r1.  If so compute and return the jump address.  */
+	  if ((prev_inst & 0xffe00000) == 0x20200000)
+	    return (hppa_extract_21 (prev_inst) + hppa_extract_17 (curr_inst)) & ~0x3;
+	  else
+	    {
+	      warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
+	      return orig_pc == pc ? 0 : pc & ~0x3;
+	    }
+	}
+
+      /* Does it look like a be 0(sr0,%r21)? OR 
+         Does it look like a be, n 0(sr0,%r21)? OR 
+         Does it look like a bve (r21)? (this is on PA2.0)
+         Does it look like a bve, n(r21)? (this is also on PA2.0)
+         That's the branch from an
+         import stub to an export stub.
+
+         It is impossible to determine the target of the branch via
+         simple examination of instructions and/or data (consider
+         that the address in the plabel may be the address of the
+         bind-on-reference routine in the dynamic loader).
+
+         So we have try an alternative approach.
+
+         Get the name of the symbol at our current location; it should
+         be a stub symbol with the same name as the symbol in the
+         shared library.
+
+         Then lookup a minimal symbol with the same name; we should
+         get the minimal symbol for the target routine in the shared
+         library as those take precedence of import/export stubs.  */
+      if ((curr_inst == 0xe2a00000) ||
+	  (curr_inst == 0xe2a00002) ||
+	  (curr_inst == 0xeaa0d000) ||
+	  (curr_inst == 0xeaa0d002))
+	{
+	  struct minimal_symbol *stubsym, *libsym;
+
+	  stubsym = lookup_minimal_symbol_by_pc (loc);
+	  if (stubsym == NULL)
+	    {
+	      warning ("Unable to find symbol for 0x%lx", loc);
+	      return orig_pc == pc ? 0 : pc & ~0x3;
+	    }
+
+	  libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
+	  if (libsym == NULL)
+	    {
+	      warning ("Unable to find library symbol for %s\n",
+		       DEPRECATED_SYMBOL_NAME (stubsym));
+	      return orig_pc == pc ? 0 : pc & ~0x3;
+	    }
+
+	  return SYMBOL_VALUE (libsym);
+	}
+
+      /* Does it look like bl X,%rp or bl X,%r0?  Another way to do a
+         branch from the stub to the actual function.  */
+      /*elz */
+      else if ((curr_inst & 0xffe0e000) == 0xe8400000
+	       || (curr_inst & 0xffe0e000) == 0xe8000000
+	       || (curr_inst & 0xffe0e000) == 0xe800A000)
+	return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3;
+
+      /* Does it look like bv (rp)?   Note this depends on the
+         current stack pointer being the same as the stack
+         pointer in the stub itself!  This is a branch on from the
+         stub back to the original caller.  */
+      /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */
+      else if ((curr_inst & 0xffe0f000) == 0xe840c000)
+	{
+	  /* Yup.  See if the previous instruction loaded
+	     rp from sp - 8.  */
+	  if (prev_inst == 0x4bc23ff1)
+	    return (read_memory_integer
+		    (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
+	  else
+	    {
+	      warning ("Unable to find restore of %%rp before bv (%%rp).");
+	      return orig_pc == pc ? 0 : pc & ~0x3;
+	    }
+	}
+
+      /* elz: added this case to capture the new instruction
+         at the end of the return part of an export stub used by
+         the PA2.0: BVE, n (rp) */
+      else if ((curr_inst & 0xffe0f000) == 0xe840d000)
+	{
+	  return (read_memory_integer
+		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
+	}
+
+      /* What about be,n 0(sr0,%rp)?  It's just another way we return to
+         the original caller from the stub.  Used in dynamic executables.  */
+      else if (curr_inst == 0xe0400002)
+	{
+	  /* The value we jump to is sitting in sp - 24.  But that's
+	     loaded several instructions before the be instruction.
+	     I guess we could check for the previous instruction being
+	     mtsp %r1,%sr0 if we want to do sanity checking.  */
+	  return (read_memory_integer
+		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
+	}
+
+      /* Haven't found the branch yet, but we're still in the stub.
+         Keep looking.  */
+      loc += 4;
+    }
+}
+
+
 /* Exception handling support for the HP-UX ANSI C++ compiler.
    The compiler (aCC) provides a callback for exception events;
    GDB can set a breakpoint on this callback and find out what
@@ -716,7 +1225,20 @@ child_get_current_exception_event (void)
 static void
 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, hppa_hpux_pc_in_sigtramp);
+
+  if (tdep->bytes_per_address == 4)
+    set_gdbarch_in_solib_call_trampoline (gdbarch, 
+					  hppa32_hpux_in_solib_call_trampoline);
+  else
+    set_gdbarch_in_solib_call_trampoline (gdbarch, 
+					  hppa64_hpux_in_solib_call_trampoline);
+
+  set_gdbarch_in_solib_return_trampoline (gdbarch,
+					  hppa_hpux_in_solib_return_trampoline);
+  set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
 }
 
 static void

-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


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