OSDN Git Service

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