2004-06-14 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 void
1208 hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
1209 {
1210   /* Some HP-UX related globals to clear when a new "main"
1211      symbol file is loaded.  HP-specific.  */
1212   deprecated_hp_som_som_object_present = 0;
1213   hp_cxx_exception_support_initialized = 0;
1214 }
1215
1216 static void
1217 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1218 {
1219   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1220
1221   if (tdep->bytes_per_address == 4)
1222     set_gdbarch_in_solib_call_trampoline (gdbarch, 
1223                                           hppa32_hpux_in_solib_call_trampoline);
1224   else
1225     set_gdbarch_in_solib_call_trampoline (gdbarch, 
1226                                           hppa64_hpux_in_solib_call_trampoline);
1227
1228   set_gdbarch_in_solib_return_trampoline (gdbarch,
1229                                           hppa_hpux_in_solib_return_trampoline);
1230   set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
1231
1232   frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
1233
1234   observer_attach_inferior_created (hppa_hpux_inferior_created);
1235 }
1236
1237 static void
1238 hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1239 {
1240   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1241
1242   tdep->is_elf = 0;
1243   hppa_hpux_init_abi (info, gdbarch);
1244 }
1245
1246 static void
1247 hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1248 {
1249   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1250
1251   tdep->is_elf = 1;
1252   hppa_hpux_init_abi (info, gdbarch);
1253 }
1254
1255 void
1256 _initialize_hppa_hpux_tdep (void)
1257 {
1258   gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
1259                           hppa_hpux_som_init_abi);
1260   gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
1261                           hppa_hpux_elf_init_abi);
1262 }