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