1 /* Target-dependent code for HPUX running on PA-RISC, for GDB.
2 
3    Copyright 2002, 2003 Free Software Foundation, Inc.
4 
5 This file is part of GDB.
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20 
21 #include "defs.h"
22 #include "arch-utils.h"
23 #include "gdbcore.h"
24 #include "osabi.h"
25 #include "gdb_string.h"
26 #include "frame.h"
27 #include "frame-unwind.h"
28 #include "trad-frame.h"
29 #include "symtab.h"
30 #include "objfiles.h"
31 #include "inferior.h"
32 #include "infcall.h"
33 #include "observer.h"
34 #include "hppa-tdep.h"
35 
36 #include <dl.h>
37 #include <machine/save_state.h>
38 
39 #ifndef offsetof
40 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
41 #endif
42 
43 /* Forward declarations.  */
44 extern void _initialize_hppa_hpux_tdep (void);
45 extern initialize_file_ftype _initialize_hppa_hpux_tdep;
46 
47 typedef struct
48   {
49     struct minimal_symbol *msym;
50     CORE_ADDR solib_handle;
51     CORE_ADDR return_val;
52   }
53 args_for_find_stub;
54 
55 /* Return one if PC is in the call path of a trampoline, else return zero.
56 
57    Note we return one for *any* call trampoline (long-call, arg-reloc), not
58    just shared library trampolines (import, export).  */
59 
60 static int
hppa32_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)61 hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
62 {
63   struct minimal_symbol *minsym;
64   struct unwind_table_entry *u;
65 
66   /* First see if PC is in one of the two C-library trampolines.  */
67   if (pc == hppa_symbol_address("$$dyncall")
68       || pc == hppa_symbol_address("_sr4export"))
69     return 1;
70 
71   minsym = lookup_minimal_symbol_by_pc (pc);
72   if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
73     return 1;
74 
75   /* Get the unwind descriptor corresponding to PC, return zero
76      if no unwind was found.  */
77   u = find_unwind_entry (pc);
78   if (!u)
79     return 0;
80 
81   /* If this isn't a linker stub, then return now.  */
82   if (u->stub_unwind.stub_type == 0)
83     return 0;
84 
85   /* By definition a long-branch stub is a call stub.  */
86   if (u->stub_unwind.stub_type == LONG_BRANCH)
87     return 1;
88 
89   /* The call and return path execute the same instructions within
90      an IMPORT stub!  So an IMPORT stub is both a call and return
91      trampoline.  */
92   if (u->stub_unwind.stub_type == IMPORT)
93     return 1;
94 
95   /* Parameter relocation stubs always have a call path and may have a
96      return path.  */
97   if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
98       || u->stub_unwind.stub_type == EXPORT)
99     {
100       CORE_ADDR addr;
101 
102       /* Search forward from the current PC until we hit a branch
103          or the end of the stub.  */
104       for (addr = pc; addr <= u->region_end; addr += 4)
105 	{
106 	  unsigned long insn;
107 
108 	  insn = read_memory_integer (addr, 4);
109 
110 	  /* Does it look like a bl?  If so then it's the call path, if
111 	     we find a bv or be first, then we're on the return path.  */
112 	  if ((insn & 0xfc00e000) == 0xe8000000)
113 	    return 1;
114 	  else if ((insn & 0xfc00e001) == 0xe800c000
115 		   || (insn & 0xfc000000) == 0xe0000000)
116 	    return 0;
117 	}
118 
119       /* Should never happen.  */
120       warning ("Unable to find branch in parameter relocation stub.\n");
121       return 0;
122     }
123 
124   /* Unknown stub type.  For now, just return zero.  */
125   return 0;
126 }
127 
128 static int
hppa64_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)129 hppa64_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
130 {
131   /* PA64 has a completely different stub/trampoline scheme.  Is it
132      better?  Maybe.  It's certainly harder to determine with any
133      certainty that we are in a stub because we can not refer to the
134      unwinders to help.
135 
136      The heuristic is simple.  Try to lookup the current PC value in th
137      minimal symbol table.  If that fails, then assume we are not in a
138      stub and return.
139 
140      Then see if the PC value falls within the section bounds for the
141      section containing the minimal symbol we found in the first
142      step.  If it does, then assume we are not in a stub and return.
143 
144      Finally peek at the instructions to see if they look like a stub.  */
145   struct minimal_symbol *minsym;
146   asection *sec;
147   CORE_ADDR addr;
148   int insn, i;
149 
150   minsym = lookup_minimal_symbol_by_pc (pc);
151   if (! minsym)
152     return 0;
153 
154   sec = SYMBOL_BFD_SECTION (minsym);
155 
156   if (bfd_get_section_vma (sec->owner, sec) <= pc
157       && pc < (bfd_get_section_vma (sec->owner, sec)
158 		 + bfd_section_size (sec->owner, sec)))
159       return 0;
160 
161   /* We might be in a stub.  Peek at the instructions.  Stubs are 3
162      instructions long. */
163   insn = read_memory_integer (pc, 4);
164 
165   /* Find out where we think we are within the stub.  */
166   if ((insn & 0xffffc00e) == 0x53610000)
167     addr = pc;
168   else if ((insn & 0xffffffff) == 0xe820d000)
169     addr = pc - 4;
170   else if ((insn & 0xffffc00e) == 0x537b0000)
171     addr = pc - 8;
172   else
173     return 0;
174 
175   /* Now verify each insn in the range looks like a stub instruction.  */
176   insn = read_memory_integer (addr, 4);
177   if ((insn & 0xffffc00e) != 0x53610000)
178     return 0;
179 
180   /* Now verify each insn in the range looks like a stub instruction.  */
181   insn = read_memory_integer (addr + 4, 4);
182   if ((insn & 0xffffffff) != 0xe820d000)
183     return 0;
184 
185   /* Now verify each insn in the range looks like a stub instruction.  */
186   insn = read_memory_integer (addr + 8, 4);
187   if ((insn & 0xffffc00e) != 0x537b0000)
188     return 0;
189 
190   /* Looks like a stub.  */
191   return 1;
192 }
193 
194 /* Return one if PC is in the return path of a trampoline, else return zero.
195 
196    Note we return one for *any* call trampoline (long-call, arg-reloc), not
197    just shared library trampolines (import, export).  */
198 
199 static int
hppa_hpux_in_solib_return_trampoline(CORE_ADDR pc,char * name)200 hppa_hpux_in_solib_return_trampoline (CORE_ADDR pc, char *name)
201 {
202   struct unwind_table_entry *u;
203 
204   /* Get the unwind descriptor corresponding to PC, return zero
205      if no unwind was found.  */
206   u = find_unwind_entry (pc);
207   if (!u)
208     return 0;
209 
210   /* If this isn't a linker stub or it's just a long branch stub, then
211      return zero.  */
212   if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
213     return 0;
214 
215   /* The call and return path execute the same instructions within
216      an IMPORT stub!  So an IMPORT stub is both a call and return
217      trampoline.  */
218   if (u->stub_unwind.stub_type == IMPORT)
219     return 1;
220 
221   /* Parameter relocation stubs always have a call path and may have a
222      return path.  */
223   if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
224       || u->stub_unwind.stub_type == EXPORT)
225     {
226       CORE_ADDR addr;
227 
228       /* Search forward from the current PC until we hit a branch
229          or the end of the stub.  */
230       for (addr = pc; addr <= u->region_end; addr += 4)
231 	{
232 	  unsigned long insn;
233 
234 	  insn = read_memory_integer (addr, 4);
235 
236 	  /* Does it look like a bl?  If so then it's the call path, if
237 	     we find a bv or be first, then we're on the return path.  */
238 	  if ((insn & 0xfc00e000) == 0xe8000000)
239 	    return 0;
240 	  else if ((insn & 0xfc00e001) == 0xe800c000
241 		   || (insn & 0xfc000000) == 0xe0000000)
242 	    return 1;
243 	}
244 
245       /* Should never happen.  */
246       warning ("Unable to find branch in parameter relocation stub.\n");
247       return 0;
248     }
249 
250   /* Unknown stub type.  For now, just return zero.  */
251   return 0;
252 
253 }
254 
255 /* Figure out if PC is in a trampoline, and if so find out where
256    the trampoline will jump to.  If not in a trampoline, return zero.
257 
258    Simple code examination probably is not a good idea since the code
259    sequences in trampolines can also appear in user code.
260 
261    We use unwinds and information from the minimal symbol table to
262    determine when we're in a trampoline.  This won't work for ELF
263    (yet) since it doesn't create stub unwind entries.  Whether or
264    not ELF will create stub unwinds or normal unwinds for linker
265    stubs is still being debated.
266 
267    This should handle simple calls through dyncall or sr4export,
268    long calls, argument relocation stubs, and dyncall/sr4export
269    calling an argument relocation stub.  It even handles some stubs
270    used in dynamic executables.  */
271 
272 static CORE_ADDR
hppa_hpux_skip_trampoline_code(CORE_ADDR pc)273 hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
274 {
275   long orig_pc = pc;
276   long prev_inst, curr_inst, loc;
277   struct minimal_symbol *msym;
278   struct unwind_table_entry *u;
279 
280   /* Addresses passed to dyncall may *NOT* be the actual address
281      of the function.  So we may have to do something special.  */
282   if (pc == hppa_symbol_address("$$dyncall"))
283     {
284       pc = (CORE_ADDR) read_register (22);
285 
286       /* If bit 30 (counting from the left) is on, then pc is the address of
287          the PLT entry for this function, not the address of the function
288          itself.  Bit 31 has meaning too, but only for MPE.  */
289       if (pc & 0x2)
290 	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
291     }
292   if (pc == hppa_symbol_address("$$dyncall_external"))
293     {
294       pc = (CORE_ADDR) read_register (22);
295       pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
296     }
297   else if (pc == hppa_symbol_address("_sr4export"))
298     pc = (CORE_ADDR) (read_register (22));
299 
300   /* Get the unwind descriptor corresponding to PC, return zero
301      if no unwind was found.  */
302   u = find_unwind_entry (pc);
303   if (!u)
304     return 0;
305 
306   /* If this isn't a linker stub, then return now.  */
307   /* elz: attention here! (FIXME) because of a compiler/linker
308      error, some stubs which should have a non zero stub_unwind.stub_type
309      have unfortunately a value of zero. So this function would return here
310      as if we were not in a trampoline. To fix this, we go look at the partial
311      symbol information, which reports this guy as a stub.
312      (FIXME): Unfortunately, we are not that lucky: it turns out that the
313      partial symbol information is also wrong sometimes. This is because
314      when it is entered (somread.c::som_symtab_read()) it can happen that
315      if the type of the symbol (from the som) is Entry, and the symbol is
316      in a shared library, then it can also be a trampoline.  This would
317      be OK, except that I believe the way they decide if we are ina shared library
318      does not work. SOOOO..., even if we have a regular function w/o trampolines
319      its minimal symbol can be assigned type mst_solib_trampoline.
320      Also, if we find that the symbol is a real stub, then we fix the unwind
321      descriptor, and define the stub type to be EXPORT.
322      Hopefully this is correct most of the times. */
323   if (u->stub_unwind.stub_type == 0)
324     {
325 
326 /* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
327    we can delete all the code which appears between the lines */
328 /*--------------------------------------------------------------------------*/
329       msym = lookup_minimal_symbol_by_pc (pc);
330 
331       if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
332 	return orig_pc == pc ? 0 : pc & ~0x3;
333 
334       else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
335 	{
336 	  struct objfile *objfile;
337 	  struct minimal_symbol *msymbol;
338 	  int function_found = 0;
339 
340 	  /* go look if there is another minimal symbol with the same name as
341 	     this one, but with type mst_text. This would happen if the msym
342 	     is an actual trampoline, in which case there would be another
343 	     symbol with the same name corresponding to the real function */
344 
345 	  ALL_MSYMBOLS (objfile, msymbol)
346 	  {
347 	    if (MSYMBOL_TYPE (msymbol) == mst_text
348 		&& DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
349 	      {
350 		function_found = 1;
351 		break;
352 	      }
353 	  }
354 
355 	  if (function_found)
356 	    /* the type of msym is correct (mst_solib_trampoline), but
357 	       the unwind info is wrong, so set it to the correct value */
358 	    u->stub_unwind.stub_type = EXPORT;
359 	  else
360 	    /* the stub type info in the unwind is correct (this is not a
361 	       trampoline), but the msym type information is wrong, it
362 	       should be mst_text. So we need to fix the msym, and also
363 	       get out of this function */
364 	    {
365 	      MSYMBOL_TYPE (msym) = mst_text;
366 	      return orig_pc == pc ? 0 : pc & ~0x3;
367 	    }
368 	}
369 
370 /*--------------------------------------------------------------------------*/
371     }
372 
373   /* It's a stub.  Search for a branch and figure out where it goes.
374      Note we have to handle multi insn branch sequences like ldil;ble.
375      Most (all?) other branches can be determined by examining the contents
376      of certain registers and the stack.  */
377 
378   loc = pc;
379   curr_inst = 0;
380   prev_inst = 0;
381   while (1)
382     {
383       /* Make sure we haven't walked outside the range of this stub.  */
384       if (u != find_unwind_entry (loc))
385 	{
386 	  warning ("Unable to find branch in linker stub");
387 	  return orig_pc == pc ? 0 : pc & ~0x3;
388 	}
389 
390       prev_inst = curr_inst;
391       curr_inst = read_memory_integer (loc, 4);
392 
393       /* Does it look like a branch external using %r1?  Then it's the
394          branch from the stub to the actual function.  */
395       if ((curr_inst & 0xffe0e000) == 0xe0202000)
396 	{
397 	  /* Yup.  See if the previous instruction loaded
398 	     a value into %r1.  If so compute and return the jump address.  */
399 	  if ((prev_inst & 0xffe00000) == 0x20200000)
400 	    return (hppa_extract_21 (prev_inst) + hppa_extract_17 (curr_inst)) & ~0x3;
401 	  else
402 	    {
403 	      warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
404 	      return orig_pc == pc ? 0 : pc & ~0x3;
405 	    }
406 	}
407 
408       /* Does it look like a be 0(sr0,%r21)? OR
409          Does it look like a be, n 0(sr0,%r21)? OR
410          Does it look like a bve (r21)? (this is on PA2.0)
411          Does it look like a bve, n(r21)? (this is also on PA2.0)
412          That's the branch from an
413          import stub to an export stub.
414 
415          It is impossible to determine the target of the branch via
416          simple examination of instructions and/or data (consider
417          that the address in the plabel may be the address of the
418          bind-on-reference routine in the dynamic loader).
419 
420          So we have try an alternative approach.
421 
422          Get the name of the symbol at our current location; it should
423          be a stub symbol with the same name as the symbol in the
424          shared library.
425 
426          Then lookup a minimal symbol with the same name; we should
427          get the minimal symbol for the target routine in the shared
428          library as those take precedence of import/export stubs.  */
429       if ((curr_inst == 0xe2a00000) ||
430 	  (curr_inst == 0xe2a00002) ||
431 	  (curr_inst == 0xeaa0d000) ||
432 	  (curr_inst == 0xeaa0d002))
433 	{
434 	  struct minimal_symbol *stubsym, *libsym;
435 
436 	  stubsym = lookup_minimal_symbol_by_pc (loc);
437 	  if (stubsym == NULL)
438 	    {
439 	      warning ("Unable to find symbol for 0x%lx", loc);
440 	      return orig_pc == pc ? 0 : pc & ~0x3;
441 	    }
442 
443 	  libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
444 	  if (libsym == NULL)
445 	    {
446 	      warning ("Unable to find library symbol for %s\n",
447 		       DEPRECATED_SYMBOL_NAME (stubsym));
448 	      return orig_pc == pc ? 0 : pc & ~0x3;
449 	    }
450 
451 	  return SYMBOL_VALUE (libsym);
452 	}
453 
454       /* Does it look like bl X,%rp or bl X,%r0?  Another way to do a
455          branch from the stub to the actual function.  */
456       /*elz */
457       else if ((curr_inst & 0xffe0e000) == 0xe8400000
458 	       || (curr_inst & 0xffe0e000) == 0xe8000000
459 	       || (curr_inst & 0xffe0e000) == 0xe800A000)
460 	return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3;
461 
462       /* Does it look like bv (rp)?   Note this depends on the
463          current stack pointer being the same as the stack
464          pointer in the stub itself!  This is a branch on from the
465          stub back to the original caller.  */
466       /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */
467       else if ((curr_inst & 0xffe0f000) == 0xe840c000)
468 	{
469 	  /* Yup.  See if the previous instruction loaded
470 	     rp from sp - 8.  */
471 	  if (prev_inst == 0x4bc23ff1)
472 	    return (read_memory_integer
473 		    (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
474 	  else
475 	    {
476 	      warning ("Unable to find restore of %%rp before bv (%%rp).");
477 	      return orig_pc == pc ? 0 : pc & ~0x3;
478 	    }
479 	}
480 
481       /* elz: added this case to capture the new instruction
482          at the end of the return part of an export stub used by
483          the PA2.0: BVE, n (rp) */
484       else if ((curr_inst & 0xffe0f000) == 0xe840d000)
485 	{
486 	  return (read_memory_integer
487 		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
488 	}
489 
490       /* What about be,n 0(sr0,%rp)?  It's just another way we return to
491          the original caller from the stub.  Used in dynamic executables.  */
492       else if (curr_inst == 0xe0400002)
493 	{
494 	  /* The value we jump to is sitting in sp - 24.  But that's
495 	     loaded several instructions before the be instruction.
496 	     I guess we could check for the previous instruction being
497 	     mtsp %r1,%sr0 if we want to do sanity checking.  */
498 	  return (read_memory_integer
499 		  (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
500 	}
501 
502       /* Haven't found the branch yet, but we're still in the stub.
503          Keep looking.  */
504       loc += 4;
505     }
506 }
507 
508 
509 /* Exception handling support for the HP-UX ANSI C++ compiler.
510    The compiler (aCC) provides a callback for exception events;
511    GDB can set a breakpoint on this callback and find out what
512    exception event has occurred. */
513 
514 /* The name of the hook to be set to point to the callback function */
515 static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
516 /* The name of the function to be used to set the hook value */
517 static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
518 /* The name of the callback function in end.o */
519 static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
520 /* Name of function in end.o on which a break is set (called by above) */
521 static char HP_ACC_EH_break[] = "__d_eh_break";
522 /* Name of flag (in end.o) that enables catching throws */
523 static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
524 /* Name of flag (in end.o) that enables catching catching */
525 static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
526 /* The enum used by aCC */
527 typedef enum
528   {
529     __EH_NOTIFY_THROW,
530     __EH_NOTIFY_CATCH
531   }
532 __eh_notification;
533 
534 /* Is exception-handling support available with this executable? */
535 static int hp_cxx_exception_support = 0;
536 /* Has the initialize function been run? */
537 static int hp_cxx_exception_support_initialized = 0;
538 /* Address of __eh_notify_hook */
539 static CORE_ADDR eh_notify_hook_addr = 0;
540 /* Address of __d_eh_notify_callback */
541 static CORE_ADDR eh_notify_callback_addr = 0;
542 /* Address of __d_eh_break */
543 static CORE_ADDR eh_break_addr = 0;
544 /* Address of __d_eh_catch_catch */
545 static CORE_ADDR eh_catch_catch_addr = 0;
546 /* Address of __d_eh_catch_throw */
547 static CORE_ADDR eh_catch_throw_addr = 0;
548 /* Sal for __d_eh_break */
549 static struct symtab_and_line *break_callback_sal = 0;
550 
551 /* Code in end.c expects __d_pid to be set in the inferior,
552    otherwise __d_eh_notify_callback doesn't bother to call
553    __d_eh_break!  So we poke the pid into this symbol
554    ourselves.
555    0 => success
556    1 => failure  */
557 int
setup_d_pid_in_inferior(void)558 setup_d_pid_in_inferior (void)
559 {
560   CORE_ADDR anaddr;
561   struct minimal_symbol *msymbol;
562   char buf[4];			/* FIXME 32x64? */
563 
564   /* Slam the pid of the process into __d_pid; failing is only a warning!  */
565   msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
566   if (msymbol == NULL)
567     {
568       warning ("Unable to find __d_pid symbol in object file.");
569       warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
570       return 1;
571     }
572 
573   anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
574   store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
575   if (target_write_memory (anaddr, buf, 4))	/* FIXME 32x64? */
576     {
577       warning ("Unable to write __d_pid");
578       warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
579       return 1;
580     }
581   return 0;
582 }
583 
584 /* elz: Used to lookup a symbol in the shared libraries.
585    This function calls shl_findsym, indirectly through a
586    call to __d_shl_get. __d_shl_get is in end.c, which is always
587    linked in by the hp compilers/linkers.
588    The call to shl_findsym cannot be made directly because it needs
589    to be active in target address space.
590    inputs: - minimal symbol pointer for the function we want to look up
591    - address in target space of the descriptor for the library
592    where we want to look the symbol up.
593    This address is retrieved using the
594    som_solib_get_solib_by_pc function (somsolib.c).
595    output: - real address in the library of the function.
596    note: the handle can be null, in which case shl_findsym will look for
597    the symbol in all the loaded shared libraries.
598    files to look at if you need reference on this stuff:
599    dld.c, dld_shl_findsym.c
600    end.c
601    man entry for shl_findsym */
602 
603 CORE_ADDR
find_stub_with_shl_get(struct minimal_symbol * function,CORE_ADDR handle)604 find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
605 {
606   struct symbol *get_sym, *symbol2;
607   struct minimal_symbol *buff_minsym, *msymbol;
608   struct type *ftype;
609   struct value **args;
610   struct value *funcval;
611   struct value *val;
612 
613   int x, namelen, err_value, tmp = -1;
614   CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
615   CORE_ADDR stub_addr;
616 
617 
618   args = alloca (sizeof (struct value *) * 8);		/* 6 for the arguments and one null one??? */
619   funcval = find_function_in_inferior ("__d_shl_get");
620   get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
621   buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
622   msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
623   symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
624   endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
625   namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
626   value_return_addr = endo_buff_addr + namelen;
627   ftype = check_typedef (SYMBOL_TYPE (get_sym));
628 
629   /* do alignment */
630   if ((x = value_return_addr % 64) != 0)
631     value_return_addr = value_return_addr + 64 - x;
632 
633   errno_return_addr = value_return_addr + 64;
634 
635 
636   /* set up stuff needed by __d_shl_get in buffer in end.o */
637 
638   target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
639 
640   target_write_memory (value_return_addr, (char *) &tmp, 4);
641 
642   target_write_memory (errno_return_addr, (char *) &tmp, 4);
643 
644   target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
645 		       (char *) &handle, 4);
646 
647   /* now prepare the arguments for the call */
648 
649   args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
650   args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
651   args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
652   args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
653   args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
654   args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
655 
656   /* now call the function */
657 
658   val = call_function_by_hand (funcval, 6, args);
659 
660   /* now get the results */
661 
662   target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
663 
664   target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
665   if (stub_addr <= 0)
666     error ("call to __d_shl_get failed, error code is %d", err_value);
667 
668   return (stub_addr);
669 }
670 
671 /* Cover routine for find_stub_with_shl_get to pass to catch_errors */
672 static int
cover_find_stub_with_shl_get(void * args_untyped)673 cover_find_stub_with_shl_get (void *args_untyped)
674 {
675   args_for_find_stub *args = args_untyped;
676   args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
677   return 0;
678 }
679 
680 /* Initialize exception catchpoint support by looking for the
681    necessary hooks/callbacks in end.o, etc., and set the hook value to
682    point to the required debug function
683 
684    Return 0 => failure
685    1 => success          */
686 
687 static int
initialize_hp_cxx_exception_support(void)688 initialize_hp_cxx_exception_support (void)
689 {
690   struct symtabs_and_lines sals;
691   struct cleanup *old_chain;
692   struct cleanup *canonical_strings_chain = NULL;
693   int i;
694   char *addr_start;
695   char *addr_end = NULL;
696   char **canonical = (char **) NULL;
697   int thread = -1;
698   struct symbol *sym = NULL;
699   struct minimal_symbol *msym = NULL;
700   struct objfile *objfile;
701   asection *shlib_info;
702 
703   /* Detect and disallow recursion.  On HP-UX with aCC, infinite
704      recursion is a possibility because finding the hook for exception
705      callbacks involves making a call in the inferior, which means
706      re-inserting breakpoints which can re-invoke this code */
707 
708   static int recurse = 0;
709   if (recurse > 0)
710     {
711       hp_cxx_exception_support_initialized = 0;
712       deprecated_exception_support_initialized = 0;
713       return 0;
714     }
715 
716   hp_cxx_exception_support = 0;
717 
718   /* First check if we have seen any HP compiled objects; if not,
719      it is very unlikely that HP's idiosyncratic callback mechanism
720      for exception handling debug support will be available!
721      This will percolate back up to breakpoint.c, where our callers
722      will decide to try the g++ exception-handling support instead. */
723   if (!deprecated_hp_som_som_object_present)
724     return 0;
725 
726   /* We have a SOM executable with SOM debug info; find the hooks */
727 
728   /* First look for the notify hook provided by aCC runtime libs */
729   /* If we find this symbol, we conclude that the executable must
730      have HP aCC exception support built in.  If this symbol is not
731      found, even though we're a HP SOM-SOM file, we may have been
732      built with some other compiler (not aCC).  This results percolates
733      back up to our callers in breakpoint.c which can decide to
734      try the g++ style of exception support instead.
735      If this symbol is found but the other symbols we require are
736      not found, there is something weird going on, and g++ support
737      should *not* be tried as an alternative.
738 
739      ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
740      ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
741 
742   /* libCsup has this hook; it'll usually be non-debuggable */
743   msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
744   if (msym)
745     {
746       eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
747       hp_cxx_exception_support = 1;
748     }
749   else
750     {
751       warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
752       warning ("Executable may not have been compiled debuggable with HP aCC.");
753       warning ("GDB will be unable to intercept exception events.");
754       eh_notify_hook_addr = 0;
755       hp_cxx_exception_support = 0;
756       return 0;
757     }
758 
759   /* Next look for the notify callback routine in end.o */
760   /* This is always available in the SOM symbol dictionary if end.o is linked in */
761   msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
762   if (msym)
763     {
764       eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
765       hp_cxx_exception_support = 1;
766     }
767   else
768     {
769       warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
770       warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
771       warning ("GDB will be unable to intercept exception events.");
772       eh_notify_callback_addr = 0;
773       return 0;
774     }
775 
776 #ifndef GDB_TARGET_IS_HPPA_20W
777   /* Check whether the executable is dynamically linked or archive bound */
778   /* With an archive-bound executable we can use the raw addresses we find
779      for the callback function, etc. without modification. For an executable
780      with shared libraries, we have to do more work to find the plabel, which
781      can be the target of a call through $$dyncall from the aCC runtime support
782      library (libCsup) which is linked shared by default by aCC. */
783   /* This test below was copied from somsolib.c/somread.c.  It may not be a very
784      reliable one to test that an executable is linked shared. pai/1997-07-18 */
785   shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
786   if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
787     {
788       /* The minsym we have has the local code address, but that's not the
789          plabel that can be used by an inter-load-module call. */
790       /* Find solib handle for main image (which has end.o), and use that
791          and the min sym as arguments to __d_shl_get() (which does the equivalent
792          of shl_findsym()) to find the plabel. */
793 
794       args_for_find_stub args;
795       static char message[] = "Error while finding exception callback hook:\n";
796 
797       args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
798       args.msym = msym;
799       args.return_val = 0;
800 
801       recurse++;
802       catch_errors (cover_find_stub_with_shl_get, &args, message,
803 		    RETURN_MASK_ALL);
804       eh_notify_callback_addr = args.return_val;
805       recurse--;
806 
807       deprecated_exception_catchpoints_are_fragile = 1;
808 
809       if (!eh_notify_callback_addr)
810 	{
811 	  /* We can get here either if there is no plabel in the export list
812 	     for the main image, or if something strange happened (?) */
813 	  warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
814 	  warning ("GDB will not be able to intercept exception events.");
815 	  return 0;
816 	}
817     }
818   else
819     deprecated_exception_catchpoints_are_fragile = 0;
820 #endif
821 
822   /* Now, look for the breakpointable routine in end.o */
823   /* This should also be available in the SOM symbol dict. if end.o linked in */
824   msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
825   if (msym)
826     {
827       eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
828       hp_cxx_exception_support = 1;
829     }
830   else
831     {
832       warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
833       warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
834       warning ("GDB will be unable to intercept exception events.");
835       eh_break_addr = 0;
836       return 0;
837     }
838 
839   /* Next look for the catch enable flag provided in end.o */
840   sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
841 		       VAR_DOMAIN, 0, (struct symtab **) NULL);
842   if (sym)			/* sometimes present in debug info */
843     {
844       eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
845       hp_cxx_exception_support = 1;
846     }
847   else
848     /* otherwise look in SOM symbol dict. */
849     {
850       msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
851       if (msym)
852 	{
853 	  eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
854 	  hp_cxx_exception_support = 1;
855 	}
856       else
857 	{
858 	  warning ("Unable to enable interception of exception catches.");
859 	  warning ("Executable may not have been compiled debuggable with HP aCC.");
860 	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
861 	  return 0;
862 	}
863     }
864 
865   /* Next look for the catch enable flag provided end.o */
866   sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
867 		       VAR_DOMAIN, 0, (struct symtab **) NULL);
868   if (sym)			/* sometimes present in debug info */
869     {
870       eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
871       hp_cxx_exception_support = 1;
872     }
873   else
874     /* otherwise look in SOM symbol dict. */
875     {
876       msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
877       if (msym)
878 	{
879 	  eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
880 	  hp_cxx_exception_support = 1;
881 	}
882       else
883 	{
884 	  warning ("Unable to enable interception of exception throws.");
885 	  warning ("Executable may not have been compiled debuggable with HP aCC.");
886 	  warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
887 	  return 0;
888 	}
889     }
890 
891   /* Set the flags */
892   hp_cxx_exception_support = 2;	/* everything worked so far */
893   hp_cxx_exception_support_initialized = 1;
894   deprecated_exception_support_initialized = 1;
895 
896   return 1;
897 }
898 
899 /* Target operation for enabling or disabling interception of
900    exception events.
901    KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
902    ENABLE is either 0 (disable) or 1 (enable).
903    Return value is NULL if no support found;
904    -1 if something went wrong,
905    or a pointer to a symtab/line struct if the breakpointable
906    address was found. */
907 
908 struct symtab_and_line *
child_enable_exception_callback(enum exception_event_kind kind,int enable)909 child_enable_exception_callback (enum exception_event_kind kind, int enable)
910 {
911   char buf[4];
912 
913   if (!deprecated_exception_support_initialized
914       || !hp_cxx_exception_support_initialized)
915     if (!initialize_hp_cxx_exception_support ())
916       return NULL;
917 
918   switch (hp_cxx_exception_support)
919     {
920     case 0:
921       /* Assuming no HP support at all */
922       return NULL;
923     case 1:
924       /* HP support should be present, but something went wrong */
925       return (struct symtab_and_line *) -1;	/* yuck! */
926       /* there may be other cases in the future */
927     }
928 
929   /* Set the EH hook to point to the callback routine */
930   store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0);	/* FIXME 32x64 problem */
931   /* pai: (temp) FIXME should there be a pack operation first? */
932   if (target_write_memory (eh_notify_hook_addr, buf, 4))	/* FIXME 32x64 problem */
933     {
934       warning ("Could not write to target memory for exception event callback.");
935       warning ("Interception of exception events may not work.");
936       return (struct symtab_and_line *) -1;
937     }
938   if (enable)
939     {
940       /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
941       if (PIDGET (inferior_ptid) > 0)
942 	{
943 	  if (setup_d_pid_in_inferior ())
944 	    return (struct symtab_and_line *) -1;
945 	}
946       else
947 	{
948 	  warning ("Internal error: Invalid inferior pid?  Cannot intercept exception events.");
949 	  return (struct symtab_and_line *) -1;
950 	}
951     }
952 
953   switch (kind)
954     {
955     case EX_EVENT_THROW:
956       store_unsigned_integer (buf, 4, enable ? 1 : 0);
957       if (target_write_memory (eh_catch_throw_addr, buf, 4))	/* FIXME 32x64? */
958 	{
959 	  warning ("Couldn't enable exception throw interception.");
960 	  return (struct symtab_and_line *) -1;
961 	}
962       break;
963     case EX_EVENT_CATCH:
964       store_unsigned_integer (buf, 4, enable ? 1 : 0);
965       if (target_write_memory (eh_catch_catch_addr, buf, 4))	/* FIXME 32x64? */
966 	{
967 	  warning ("Couldn't enable exception catch interception.");
968 	  return (struct symtab_and_line *) -1;
969 	}
970       break;
971     default:
972       error ("Request to enable unknown or unsupported exception event.");
973     }
974 
975   /* Copy break address into new sal struct, malloc'ing if needed. */
976   if (!break_callback_sal)
977     {
978       break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
979     }
980   init_sal (break_callback_sal);
981   break_callback_sal->symtab = NULL;
982   break_callback_sal->pc = eh_break_addr;
983   break_callback_sal->line = 0;
984   break_callback_sal->end = eh_break_addr;
985 
986   return break_callback_sal;
987 }
988 
989 /* Record some information about the current exception event */
990 static struct exception_event_record current_ex_event;
991 /* Convenience struct */
992 static struct symtab_and_line null_symtab_and_line =
993 {NULL, 0, 0, 0};
994 
995 /* Report current exception event.  Returns a pointer to a record
996    that describes the kind of the event, where it was thrown from,
997    and where it will be caught.  More information may be reported
998    in the future */
999 struct exception_event_record *
child_get_current_exception_event(void)1000 child_get_current_exception_event (void)
1001 {
1002   CORE_ADDR event_kind;
1003   CORE_ADDR throw_addr;
1004   CORE_ADDR catch_addr;
1005   struct frame_info *fi, *curr_frame;
1006   int level = 1;
1007 
1008   curr_frame = get_current_frame ();
1009   if (!curr_frame)
1010     return (struct exception_event_record *) NULL;
1011 
1012   /* Go up one frame to __d_eh_notify_callback, because at the
1013      point when this code is executed, there's garbage in the
1014      arguments of __d_eh_break. */
1015   fi = find_relative_frame (curr_frame, &level);
1016   if (level != 0)
1017     return (struct exception_event_record *) NULL;
1018 
1019   select_frame (fi);
1020 
1021   /* Read in the arguments */
1022   /* __d_eh_notify_callback() is called with 3 arguments:
1023      1. event kind catch or throw
1024      2. the target address if known
1025      3. a flag -- not sure what this is. pai/1997-07-17 */
1026   event_kind = read_register (HPPA_ARG0_REGNUM);
1027   catch_addr = read_register (HPPA_ARG1_REGNUM);
1028 
1029   /* Now go down to a user frame */
1030   /* For a throw, __d_eh_break is called by
1031      __d_eh_notify_callback which is called by
1032      __notify_throw which is called
1033      from user code.
1034      For a catch, __d_eh_break is called by
1035      __d_eh_notify_callback which is called by
1036      <stackwalking stuff> which is called by
1037      __throw__<stuff> or __rethrow_<stuff> which is called
1038      from user code. */
1039   /* FIXME: Don't use such magic numbers; search for the frames */
1040   level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
1041   fi = find_relative_frame (curr_frame, &level);
1042   if (level != 0)
1043     return (struct exception_event_record *) NULL;
1044 
1045   select_frame (fi);
1046   throw_addr = get_frame_pc (fi);
1047 
1048   /* Go back to original (top) frame */
1049   select_frame (curr_frame);
1050 
1051   current_ex_event.kind = (enum exception_event_kind) event_kind;
1052   current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
1053   current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
1054 
1055   return &current_ex_event;
1056 }
1057 
1058 /* Signal frames.  */
1059 struct hppa_hpux_sigtramp_unwind_cache
1060 {
1061   CORE_ADDR base;
1062   struct trad_frame_saved_reg *saved_regs;
1063 };
1064 
1065 static int hppa_hpux_tramp_reg[] = {
1066   HPPA_SAR_REGNUM,
1067   HPPA_PCOQ_HEAD_REGNUM,
1068   HPPA_PCSQ_HEAD_REGNUM,
1069   HPPA_PCOQ_TAIL_REGNUM,
1070   HPPA_PCSQ_TAIL_REGNUM,
1071   HPPA_EIEM_REGNUM,
1072   HPPA_IIR_REGNUM,
1073   HPPA_ISR_REGNUM,
1074   HPPA_IOR_REGNUM,
1075   HPPA_IPSW_REGNUM,
1076   -1,
1077   HPPA_SR4_REGNUM,
1078   HPPA_SR4_REGNUM + 1,
1079   HPPA_SR4_REGNUM + 2,
1080   HPPA_SR4_REGNUM + 3,
1081   HPPA_SR4_REGNUM + 4,
1082   HPPA_SR4_REGNUM + 5,
1083   HPPA_SR4_REGNUM + 6,
1084   HPPA_SR4_REGNUM + 7,
1085   HPPA_RCR_REGNUM,
1086   HPPA_PID0_REGNUM,
1087   HPPA_PID1_REGNUM,
1088   HPPA_CCR_REGNUM,
1089   HPPA_PID2_REGNUM,
1090   HPPA_PID3_REGNUM,
1091   HPPA_TR0_REGNUM,
1092   HPPA_TR0_REGNUM + 1,
1093   HPPA_TR0_REGNUM + 2,
1094   HPPA_CR27_REGNUM
1095 };
1096 
1097 static struct hppa_hpux_sigtramp_unwind_cache *
hppa_hpux_sigtramp_frame_unwind_cache(struct frame_info * next_frame,void ** this_cache)1098 hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
1099 				       void **this_cache)
1100 
1101 {
1102   struct gdbarch *gdbarch = get_frame_arch (next_frame);
1103   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1104   struct hppa_hpux_sigtramp_unwind_cache *info;
1105   unsigned int flag;
1106   CORE_ADDR sp, scptr;
1107   int i, incr, off, szoff;
1108 
1109   if (*this_cache)
1110     return *this_cache;
1111 
1112   info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache);
1113   *this_cache = info;
1114   info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
1115 
1116   sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1117 
1118   scptr = sp - 1352;
1119   off = scptr;
1120 
1121   /* See /usr/include/machine/save_state.h for the structure of the save_state_t
1122      structure. */
1123 
1124   flag = read_memory_unsigned_integer(scptr, 4);
1125 
1126   if (!(flag & 0x40))
1127     {
1128       /* Narrow registers. */
1129       off = scptr + offsetof (save_state_t, ss_narrow);
1130       incr = 4;
1131       szoff = 0;
1132     }
1133   else
1134     {
1135       /* Wide registers. */
1136       off = scptr + offsetof (save_state_t, ss_wide) + 8;
1137       incr = 8;
1138       szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
1139     }
1140 
1141   for (i = 1; i < 32; i++)
1142     {
1143       info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff;
1144       off += incr;
1145     }
1146 
1147   for (i = 0;
1148        i < sizeof(hppa_hpux_tramp_reg) / sizeof(hppa_hpux_tramp_reg[0]);
1149        i++)
1150     {
1151       if (hppa_hpux_tramp_reg[i] > 0)
1152         info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff;
1153       off += incr;
1154     }
1155 
1156   /* TODO: fp regs */
1157 
1158   info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1159 
1160   return info;
1161 }
1162 
1163 static void
hppa_hpux_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_prologue_cache,struct frame_id * this_id)1164 hppa_hpux_sigtramp_frame_this_id (struct frame_info *next_frame,
1165 				   void **this_prologue_cache,
1166 				   struct frame_id *this_id)
1167 {
1168   struct hppa_hpux_sigtramp_unwind_cache *info
1169     = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
1170   *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame));
1171 }
1172 
1173 static void
hppa_hpux_sigtramp_frame_prev_register(struct frame_info * next_frame,void ** this_prologue_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)1174 hppa_hpux_sigtramp_frame_prev_register (struct frame_info *next_frame,
1175 					 void **this_prologue_cache,
1176 					 int regnum, int *optimizedp,
1177 					 enum lval_type *lvalp,
1178 					 CORE_ADDR *addrp,
1179 					 int *realnump, void *valuep)
1180 {
1181   struct hppa_hpux_sigtramp_unwind_cache *info
1182     = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
1183   hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
1184 		                   optimizedp, lvalp, addrp, realnump, valuep);
1185 }
1186 
1187 static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
1188   SIGTRAMP_FRAME,
1189   hppa_hpux_sigtramp_frame_this_id,
1190   hppa_hpux_sigtramp_frame_prev_register
1191 };
1192 
1193 static const struct frame_unwind *
hppa_hpux_sigtramp_unwind_sniffer(struct frame_info * next_frame)1194 hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
1195 {
1196   CORE_ADDR pc = frame_pc_unwind (next_frame);
1197   char *name;
1198 
1199   find_pc_partial_function (pc, &name, NULL, NULL);
1200 
1201   if (name && strcmp(name, "_sigreturn") == 0)
1202     return &hppa_hpux_sigtramp_frame_unwind;
1203 
1204   return NULL;
1205 }
1206 
1207 static CORE_ADDR
hppa_hpux_som_find_global_pointer(struct value * function)1208 hppa_hpux_som_find_global_pointer (struct value *function)
1209 {
1210   CORE_ADDR faddr;
1211 
1212   faddr = value_as_address (function);
1213 
1214   /* Is this a plabel? If so, dereference it to get the gp value.  */
1215   if (faddr & 2)
1216     {
1217       int status;
1218       char buf[4];
1219 
1220       faddr &= ~3;
1221 
1222       status = target_read_memory (faddr + 4, buf, sizeof (buf));
1223       if (status == 0)
1224 	return extract_unsigned_integer (buf, sizeof (buf));
1225     }
1226 
1227   return som_solib_get_got_by_pc (faddr);
1228 }
1229 
1230 static CORE_ADDR
hppa_hpux_push_dummy_code(struct gdbarch * gdbarch,CORE_ADDR sp,CORE_ADDR funcaddr,int using_gcc,struct value ** args,int nargs,struct type * value_type,CORE_ADDR * real_pc,CORE_ADDR * bp_addr)1231 hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
1232 			   CORE_ADDR funcaddr, int using_gcc,
1233 			   struct value **args, int nargs,
1234 			   struct type *value_type,
1235 			   CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
1236 {
1237   /* FIXME: tausq/2004-06-09: This needs much more testing.  It is broken
1238      for pa64, but we should be able to get it to work with a little bit
1239      of work. gdb-6.1 has a lot of code to handle various cases; I've tried to
1240      simplify it and avoid compile-time conditionals.  */
1241 
1242   /* On HPUX, functions in the main executable and in libraries can be located
1243      in different spaces.  In order for us to be able to select the right
1244      space for the function call, we need to go through an instruction seqeunce
1245      to select the right space for the target function, call it, and then
1246      restore the space on return.
1247 
1248      There are two helper routines that can be used for this task -- if
1249      an application is linked with gcc, it will contain a __gcc_plt_call
1250      helper function.  __gcc_plt_call, when passed the entry point of an
1251      import stub, will do the necessary space setting/restoration for the
1252      target function.
1253 
1254      For programs that are compiled/linked with the HP compiler, a similar
1255      function called __d_plt_call exists; __d_plt_call expects a PLABEL instead
1256      of an import stub as an argument.
1257 
1258      // *INDENT-OFF*
1259      To summarize, the call flow is:
1260        current function -> dummy frame -> __gcc_plt_call (import stub)
1261                         -> target function
1262      or
1263        current function -> dummy frame -> __d_plt_call (plabel)
1264                         -> target function
1265      // *INDENT-ON*
1266 
1267      In general the "funcaddr" argument passed to push_dummy_code is the actual
1268      entry point of the target function.  For __gcc_plt_call, we need to
1269      locate the import stub for the corresponding function.  Failing that,
1270      we construct a dummy "import stub" on the stack to pass as an argument.
1271      For __d_plt_call, we similarly synthesize a PLABEL on the stack to
1272      pass to the helper function.
1273 
1274      An additional twist is that, in order for us to restore the space register
1275      to its starting state, we need __gcc_plt_call/__d_plt_call to return
1276      to the instruction where we started the call.  However, if we put
1277      the breakpoint there, gdb will complain because it will find two
1278      frames on the stack with the same (sp, pc) (with the dummy frame in
1279      between).  Currently, we set the return pointer to (pc - 4) of the
1280      current function.  FIXME: This is not an ideal solution; possibly if the
1281      current pc is at the beginning of a page, this will cause a page fault.
1282      Need to understand this better and figure out a better way to fix it.  */
1283 
1284   struct minimal_symbol *sym;
1285 
1286   /* Nonzero if we will use GCC's PLT call routine.  This routine must be
1287      passed an import stub, not a PLABEL.  It is also necessary to get %r19
1288      before performing the call.  (This is done by push_dummy_call.)  */
1289   int use_gcc_plt_call = 1;
1290 
1291   /* See if __gcc_plt_call is available; if not we will use the HP version
1292      instead.  */
1293   sym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
1294   if (sym == NULL)
1295     use_gcc_plt_call = 0;
1296 
1297   /* If using __gcc_plt_call, we need to make sure we pass in an import
1298      stub.  funcaddr can be pointing to an export stub or a real function,
1299      so we try to resolve it to the import stub.  */
1300   if (use_gcc_plt_call)
1301     {
1302       struct objfile *objfile;
1303       struct minimal_symbol *funsym, *stubsym;
1304       CORE_ADDR stubaddr = 0;
1305 
1306       funsym = lookup_minimal_symbol_by_pc (funcaddr);
1307       if (!funsym)
1308         error ("Unable to find symbol for target function.\n");
1309 
1310       ALL_OBJFILES (objfile)
1311         {
1312 	  stubsym = lookup_minimal_symbol_solib_trampoline
1313 	    (SYMBOL_LINKAGE_NAME (funsym), objfile);
1314 
1315           if (stubsym)
1316 	    {
1317 	      struct unwind_table_entry *u;
1318 
1319 	      u = find_unwind_entry (SYMBOL_VALUE (stubsym));
1320 	      if (u == NULL
1321 	          || (u->stub_unwind.stub_type != IMPORT
1322 		      && u->stub_unwind.stub_type != IMPORT_SHLIB))
1323 	        continue;
1324 
1325               stubaddr = SYMBOL_VALUE (stubsym);
1326 
1327 	      /* If we found an IMPORT stub, then we can stop searching;
1328 	         if we found an IMPORT_SHLIB, we want to continue the search
1329 		 in the hopes that we will find an IMPORT stub.  */
1330 	      if (u->stub_unwind.stub_type == IMPORT)
1331 	        break;
1332 	    }
1333 	}
1334 
1335       if (stubaddr != 0)
1336         {
1337           /* Argument to __gcc_plt_call is passed in r22.  */
1338           regcache_cooked_write_unsigned (current_regcache, 22, stubaddr);
1339         }
1340       else
1341         {
1342 	  /* No import stub found; let's synthesize one.  */
1343 
1344 	  /* ldsid %r21, %r1 */
1345 	  write_memory_unsigned_integer (sp, 4, 0x02a010a1);
1346 	  /* mtsp %r1,%sr0 */
1347 	  write_memory_unsigned_integer (sp + 4, 4, 0x00011820);
1348 	  /* be 0(%sr0, %r21) */
1349 	  write_memory_unsigned_integer (sp + 8, 4, 0xe2a00000);
1350           /* nop */
1351           write_memory_unsigned_integer (sp + 12, 4, 0x08000240);
1352 
1353           regcache_cooked_write_unsigned (current_regcache, 21, funcaddr);
1354           regcache_cooked_write_unsigned (current_regcache, 22, sp);
1355 	}
1356 
1357       /* We set the breakpoint address and r31 to (close to) where the current
1358          pc is; when __gcc_plt_call returns, it will restore pcsqh to the
1359 	 current value based on this.  The -4 is needed for frame unwinding
1360 	 to work properly -- we need to land in a different function than
1361 	 the current function.  */
1362       *bp_addr = (read_register (HPPA_PCOQ_HEAD_REGNUM) & ~3) - 4;
1363       regcache_cooked_write_unsigned (current_regcache, 31, *bp_addr);
1364 
1365       /* Continue from __gcc_plt_call.  */
1366       *real_pc = SYMBOL_VALUE (sym);
1367     }
1368   else
1369     {
1370       unsigned int gp;
1371 
1372       /* Use __d_plt_call as a fallback; __d_plt_call expects to be called
1373          with a plabel, so we need to build one.  */
1374 
1375       sym = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
1376       if (sym == NULL)
1377         error("Can't find an address for __d_plt_call or __gcc_plt_call "
1378 	      "trampoline\nSuggest linking executable with -g or compiling "
1379 	      "with gcc.");
1380 
1381       gp = gdbarch_tdep (gdbarch)->find_global_pointer (funcaddr);
1382       write_memory_unsigned_integer (sp, 4, funcaddr);
1383       write_memory_unsigned_integer (sp + 4, 4, gp);
1384 
1385       /* plabel is passed in r22 */
1386       regcache_cooked_write_unsigned (current_regcache, 22, sp);
1387     }
1388 
1389   /* Pushed one stack frame, which has to be 64-byte aligned.  */
1390   sp += 64;
1391 
1392   return sp;
1393 }
1394 
1395 static void
hppa_hpux_inferior_created(struct target_ops * objfile,int from_tty)1396 hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
1397 {
1398   /* Some HP-UX related globals to clear when a new "main"
1399      symbol file is loaded.  HP-specific.  */
1400   deprecated_hp_som_som_object_present = 0;
1401   hp_cxx_exception_support_initialized = 0;
1402 }
1403 
1404 static void
hppa_hpux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1405 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1406 {
1407   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1408 
1409   if (tdep->bytes_per_address == 4)
1410     set_gdbarch_in_solib_call_trampoline (gdbarch,
1411 					  hppa32_hpux_in_solib_call_trampoline);
1412   else
1413     set_gdbarch_in_solib_call_trampoline (gdbarch,
1414 					  hppa64_hpux_in_solib_call_trampoline);
1415 
1416   set_gdbarch_in_solib_return_trampoline (gdbarch,
1417 					  hppa_hpux_in_solib_return_trampoline);
1418   set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
1419 
1420   set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code);
1421   set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
1422 
1423   frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
1424 
1425   observer_attach_inferior_created (hppa_hpux_inferior_created);
1426 }
1427 
1428 static void
hppa_hpux_som_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1429 hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1430 {
1431   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1432 
1433   tdep->is_elf = 0;
1434 
1435   tdep->find_global_pointer = hppa_hpux_som_find_global_pointer;
1436   hppa_hpux_init_abi (info, gdbarch);
1437 }
1438 
1439 static void
hppa_hpux_elf_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1440 hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1441 {
1442   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1443 
1444   tdep->is_elf = 1;
1445   hppa_hpux_init_abi (info, gdbarch);
1446 }
1447 
1448 void
_initialize_hppa_hpux_tdep(void)1449 _initialize_hppa_hpux_tdep (void)
1450 {
1451   gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
1452                           hppa_hpux_som_init_abi);
1453   gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
1454                           hppa_hpux_elf_init_abi);
1455 }
1456