2004-07-10 Randolph Chung <tausq@debian.org>
[external/binutils.git] / gdb / hppa-hpux-tdep.c
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
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
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
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
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
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
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
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
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 *
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 *
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 *
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
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
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 *
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
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
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
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
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
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
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
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 }