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