1 /* Target-dependent code for HPUX running on PA-RISC, for GDB.
3 Copyright 2002, 2003 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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. */
22 #include "arch-utils.h"
25 #include "gdb_string.h"
31 #include "hppa-tdep.h"
34 #include <machine/save_state.h>
36 /* Forward declarations. */
37 extern void _initialize_hppa_hpux_tdep (void);
38 extern initialize_file_ftype _initialize_hppa_hpux_tdep;
42 struct minimal_symbol *msym;
43 CORE_ADDR solib_handle;
48 /* FIXME: brobecker 2002-12-25. The following functions will eventually
49 become static, after the multiarching conversion is done. */
50 int hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name);
51 void hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
53 void hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
55 void hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
57 void hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi,
59 void hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
61 void hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
65 hppa_hpux_pc_in_sigtramp (CORE_ADDR pc, char *name)
67 /* Actually, for a PA running HPUX the kernel calls the signal handler
68 without an intermediate trampoline. Luckily the kernel always sets
69 the return pointer for the signal handler to point to _sigreturn. */
70 return (name && (strcmp ("_sigreturn", name) == 0));
73 /* For hppa32_hpux_frame_saved_pc_in_sigtramp,
74 hppa32_hpux_frame_base_before_sigtramp and
75 hppa32_hpux_frame_find_saved_regs_in_sigtramp:
77 The signal context structure pointer is always saved at the base
78 of the frame which "calls" the signal handler. We only want to find
79 the hardware save state structure, which lives 10 32bit words into
82 Within the hardware save state structure, registers are found in the
83 same order as the register numbers in GDB.
85 At one time we peeked at %r31 rather than the PC queues to determine
86 what instruction took the fault. This was done on purpose, but I don't
87 remember why. Looking at the PC queues is really the right way, and
88 I don't remember why that didn't work when this code was originally
92 hppa32_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
94 *tmp = read_memory_integer (get_frame_base (fi) + (43 * 4), 4);
98 hppa32_hpux_frame_base_before_sigtramp (struct frame_info *fi,
101 *tmp = read_memory_integer (get_frame_base (fi) + (40 * 4), 4);
105 hppa32_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
109 const CORE_ADDR tmp = get_frame_base (fi) + (10 * 4);
111 for (i = 0; i < NUM_REGS; i++)
114 fsr[SP_REGNUM] = read_memory_integer (tmp + SP_REGNUM * 4, 4);
116 fsr[i] = tmp + i * 4;
120 /* For hppa64_hpux_frame_saved_pc_in_sigtramp,
121 hppa64_hpux_frame_base_before_sigtramp and
122 hppa64_hpux_frame_find_saved_regs_in_sigtramp:
124 These functions are the PA64 ABI equivalents of the 32bits counterparts
125 above. See the comments there.
127 For PA64, the save_state structure is at an offset of 24 32-bit words
128 from the sigcontext structure. The 64 bit general registers are at an
129 offset of 640 bytes from the beginning of the save_state structure,
130 and the floating pointer register are at an offset of 256 bytes from
131 the beginning of the save_state structure. */
134 hppa64_hpux_frame_saved_pc_in_sigtramp (struct frame_info *fi, CORE_ADDR *tmp)
136 *tmp = read_memory_integer
137 (get_frame_base (fi) + (24 * 4) + 640 + (33 * 8), 8);
141 hppa64_hpux_frame_base_before_sigtramp (struct frame_info *fi,
144 *tmp = read_memory_integer
145 (get_frame_base (fi) + (24 * 4) + 640 + (30 * 8), 8);
149 hppa64_hpux_frame_find_saved_regs_in_sigtramp (struct frame_info *fi,
153 const CORE_ADDR tmp1 = get_frame_base (fi) + (24 * 4) + 640;
154 const CORE_ADDR tmp2 = get_frame_base (fi) + (24 * 4) + 256;
156 for (i = 0; i < NUM_REGS; i++)
159 fsr[SP_REGNUM] = read_memory_integer (tmp1 + SP_REGNUM * 8, 8);
160 else if (i >= FP0_REGNUM)
161 fsr[i] = tmp2 + (i - FP0_REGNUM) * 8;
163 fsr[i] = tmp1 + i * 8;
167 /* Return one if PC is in the call path of a trampoline, else return zero.
169 Note we return one for *any* call trampoline (long-call, arg-reloc), not
170 just shared library trampolines (import, export). */
173 hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
175 struct minimal_symbol *minsym;
176 struct unwind_table_entry *u;
177 static CORE_ADDR dyncall = 0;
178 static CORE_ADDR sr4export = 0;
180 /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
183 /* First see if PC is in one of the two C-library trampolines. */
186 minsym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
188 dyncall = SYMBOL_VALUE_ADDRESS (minsym);
195 minsym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
197 sr4export = SYMBOL_VALUE_ADDRESS (minsym);
202 if (pc == dyncall || pc == sr4export)
205 minsym = lookup_minimal_symbol_by_pc (pc);
206 if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
209 /* Get the unwind descriptor corresponding to PC, return zero
210 if no unwind was found. */
211 u = find_unwind_entry (pc);
215 /* If this isn't a linker stub, then return now. */
216 if (u->stub_unwind.stub_type == 0)
219 /* By definition a long-branch stub is a call stub. */
220 if (u->stub_unwind.stub_type == LONG_BRANCH)
223 /* The call and return path execute the same instructions within
224 an IMPORT stub! So an IMPORT stub is both a call and return
226 if (u->stub_unwind.stub_type == IMPORT)
229 /* Parameter relocation stubs always have a call path and may have a
231 if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
232 || u->stub_unwind.stub_type == EXPORT)
236 /* Search forward from the current PC until we hit a branch
237 or the end of the stub. */
238 for (addr = pc; addr <= u->region_end; addr += 4)
242 insn = read_memory_integer (addr, 4);
244 /* Does it look like a bl? If so then it's the call path, if
245 we find a bv or be first, then we're on the return path. */
246 if ((insn & 0xfc00e000) == 0xe8000000)
248 else if ((insn & 0xfc00e001) == 0xe800c000
249 || (insn & 0xfc000000) == 0xe0000000)
253 /* Should never happen. */
254 warning ("Unable to find branch in parameter relocation stub.\n");
258 /* Unknown stub type. For now, just return zero. */
263 hppa64_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
265 /* PA64 has a completely different stub/trampoline scheme. Is it
266 better? Maybe. It's certainly harder to determine with any
267 certainty that we are in a stub because we can not refer to the
270 The heuristic is simple. Try to lookup the current PC value in th
271 minimal symbol table. If that fails, then assume we are not in a
274 Then see if the PC value falls within the section bounds for the
275 section containing the minimal symbol we found in the first
276 step. If it does, then assume we are not in a stub and return.
278 Finally peek at the instructions to see if they look like a stub. */
279 struct minimal_symbol *minsym;
284 minsym = lookup_minimal_symbol_by_pc (pc);
288 sec = SYMBOL_BFD_SECTION (minsym);
290 if (bfd_get_section_vma (sec->owner, sec) <= pc
291 && pc < (bfd_get_section_vma (sec->owner, sec)
292 + bfd_section_size (sec->owner, sec)))
295 /* We might be in a stub. Peek at the instructions. Stubs are 3
296 instructions long. */
297 insn = read_memory_integer (pc, 4);
299 /* Find out where we think we are within the stub. */
300 if ((insn & 0xffffc00e) == 0x53610000)
302 else if ((insn & 0xffffffff) == 0xe820d000)
304 else if ((insn & 0xffffc00e) == 0x537b0000)
309 /* Now verify each insn in the range looks like a stub instruction. */
310 insn = read_memory_integer (addr, 4);
311 if ((insn & 0xffffc00e) != 0x53610000)
314 /* Now verify each insn in the range looks like a stub instruction. */
315 insn = read_memory_integer (addr + 4, 4);
316 if ((insn & 0xffffffff) != 0xe820d000)
319 /* Now verify each insn in the range looks like a stub instruction. */
320 insn = read_memory_integer (addr + 8, 4);
321 if ((insn & 0xffffc00e) != 0x537b0000)
324 /* Looks like a stub. */
328 /* Return one if PC is in the return path of a trampoline, else return zero.
330 Note we return one for *any* call trampoline (long-call, arg-reloc), not
331 just shared library trampolines (import, export). */
334 hppa_hpux_in_solib_return_trampoline (CORE_ADDR pc, char *name)
336 struct unwind_table_entry *u;
338 /* Get the unwind descriptor corresponding to PC, return zero
339 if no unwind was found. */
340 u = find_unwind_entry (pc);
344 /* If this isn't a linker stub or it's just a long branch stub, then
346 if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
349 /* The call and return path execute the same instructions within
350 an IMPORT stub! So an IMPORT stub is both a call and return
352 if (u->stub_unwind.stub_type == IMPORT)
355 /* Parameter relocation stubs always have a call path and may have a
357 if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
358 || u->stub_unwind.stub_type == EXPORT)
362 /* Search forward from the current PC until we hit a branch
363 or the end of the stub. */
364 for (addr = pc; addr <= u->region_end; addr += 4)
368 insn = read_memory_integer (addr, 4);
370 /* Does it look like a bl? If so then it's the call path, if
371 we find a bv or be first, then we're on the return path. */
372 if ((insn & 0xfc00e000) == 0xe8000000)
374 else if ((insn & 0xfc00e001) == 0xe800c000
375 || (insn & 0xfc000000) == 0xe0000000)
379 /* Should never happen. */
380 warning ("Unable to find branch in parameter relocation stub.\n");
384 /* Unknown stub type. For now, just return zero. */
389 /* Figure out if PC is in a trampoline, and if so find out where
390 the trampoline will jump to. If not in a trampoline, return zero.
392 Simple code examination probably is not a good idea since the code
393 sequences in trampolines can also appear in user code.
395 We use unwinds and information from the minimal symbol table to
396 determine when we're in a trampoline. This won't work for ELF
397 (yet) since it doesn't create stub unwind entries. Whether or
398 not ELF will create stub unwinds or normal unwinds for linker
399 stubs is still being debated.
401 This should handle simple calls through dyncall or sr4export,
402 long calls, argument relocation stubs, and dyncall/sr4export
403 calling an argument relocation stub. It even handles some stubs
404 used in dynamic executables. */
407 hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
410 long prev_inst, curr_inst, loc;
411 static CORE_ADDR dyncall = 0;
412 static CORE_ADDR dyncall_external = 0;
413 static CORE_ADDR sr4export = 0;
414 struct minimal_symbol *msym;
415 struct unwind_table_entry *u;
417 /* FIXME XXX - dyncall and sr4export must be initialized whenever we get a
422 msym = lookup_minimal_symbol ("$$dyncall", NULL, NULL);
424 dyncall = SYMBOL_VALUE_ADDRESS (msym);
429 if (!dyncall_external)
431 msym = lookup_minimal_symbol ("$$dyncall_external", NULL, NULL);
433 dyncall_external = SYMBOL_VALUE_ADDRESS (msym);
435 dyncall_external = -1;
440 msym = lookup_minimal_symbol ("_sr4export", NULL, NULL);
442 sr4export = SYMBOL_VALUE_ADDRESS (msym);
447 /* Addresses passed to dyncall may *NOT* be the actual address
448 of the function. So we may have to do something special. */
451 pc = (CORE_ADDR) read_register (22);
453 /* If bit 30 (counting from the left) is on, then pc is the address of
454 the PLT entry for this function, not the address of the function
455 itself. Bit 31 has meaning too, but only for MPE. */
457 pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
459 if (pc == dyncall_external)
461 pc = (CORE_ADDR) read_register (22);
462 pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
464 else if (pc == sr4export)
465 pc = (CORE_ADDR) (read_register (22));
467 /* Get the unwind descriptor corresponding to PC, return zero
468 if no unwind was found. */
469 u = find_unwind_entry (pc);
473 /* If this isn't a linker stub, then return now. */
474 /* elz: attention here! (FIXME) because of a compiler/linker
475 error, some stubs which should have a non zero stub_unwind.stub_type
476 have unfortunately a value of zero. So this function would return here
477 as if we were not in a trampoline. To fix this, we go look at the partial
478 symbol information, which reports this guy as a stub.
479 (FIXME): Unfortunately, we are not that lucky: it turns out that the
480 partial symbol information is also wrong sometimes. This is because
481 when it is entered (somread.c::som_symtab_read()) it can happen that
482 if the type of the symbol (from the som) is Entry, and the symbol is
483 in a shared library, then it can also be a trampoline. This would
484 be OK, except that I believe the way they decide if we are ina shared library
485 does not work. SOOOO..., even if we have a regular function w/o trampolines
486 its minimal symbol can be assigned type mst_solib_trampoline.
487 Also, if we find that the symbol is a real stub, then we fix the unwind
488 descriptor, and define the stub type to be EXPORT.
489 Hopefully this is correct most of the times. */
490 if (u->stub_unwind.stub_type == 0)
493 /* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
494 we can delete all the code which appears between the lines */
495 /*--------------------------------------------------------------------------*/
496 msym = lookup_minimal_symbol_by_pc (pc);
498 if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
499 return orig_pc == pc ? 0 : pc & ~0x3;
501 else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
503 struct objfile *objfile;
504 struct minimal_symbol *msymbol;
505 int function_found = 0;
507 /* go look if there is another minimal symbol with the same name as
508 this one, but with type mst_text. This would happen if the msym
509 is an actual trampoline, in which case there would be another
510 symbol with the same name corresponding to the real function */
512 ALL_MSYMBOLS (objfile, msymbol)
514 if (MSYMBOL_TYPE (msymbol) == mst_text
515 && DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
523 /* the type of msym is correct (mst_solib_trampoline), but
524 the unwind info is wrong, so set it to the correct value */
525 u->stub_unwind.stub_type = EXPORT;
527 /* the stub type info in the unwind is correct (this is not a
528 trampoline), but the msym type information is wrong, it
529 should be mst_text. So we need to fix the msym, and also
530 get out of this function */
532 MSYMBOL_TYPE (msym) = mst_text;
533 return orig_pc == pc ? 0 : pc & ~0x3;
537 /*--------------------------------------------------------------------------*/
540 /* It's a stub. Search for a branch and figure out where it goes.
541 Note we have to handle multi insn branch sequences like ldil;ble.
542 Most (all?) other branches can be determined by examining the contents
543 of certain registers and the stack. */
550 /* Make sure we haven't walked outside the range of this stub. */
551 if (u != find_unwind_entry (loc))
553 warning ("Unable to find branch in linker stub");
554 return orig_pc == pc ? 0 : pc & ~0x3;
557 prev_inst = curr_inst;
558 curr_inst = read_memory_integer (loc, 4);
560 /* Does it look like a branch external using %r1? Then it's the
561 branch from the stub to the actual function. */
562 if ((curr_inst & 0xffe0e000) == 0xe0202000)
564 /* Yup. See if the previous instruction loaded
565 a value into %r1. If so compute and return the jump address. */
566 if ((prev_inst & 0xffe00000) == 0x20200000)
567 return (hppa_extract_21 (prev_inst) + hppa_extract_17 (curr_inst)) & ~0x3;
570 warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
571 return orig_pc == pc ? 0 : pc & ~0x3;
575 /* Does it look like a be 0(sr0,%r21)? OR
576 Does it look like a be, n 0(sr0,%r21)? OR
577 Does it look like a bve (r21)? (this is on PA2.0)
578 Does it look like a bve, n(r21)? (this is also on PA2.0)
579 That's the branch from an
580 import stub to an export stub.
582 It is impossible to determine the target of the branch via
583 simple examination of instructions and/or data (consider
584 that the address in the plabel may be the address of the
585 bind-on-reference routine in the dynamic loader).
587 So we have try an alternative approach.
589 Get the name of the symbol at our current location; it should
590 be a stub symbol with the same name as the symbol in the
593 Then lookup a minimal symbol with the same name; we should
594 get the minimal symbol for the target routine in the shared
595 library as those take precedence of import/export stubs. */
596 if ((curr_inst == 0xe2a00000) ||
597 (curr_inst == 0xe2a00002) ||
598 (curr_inst == 0xeaa0d000) ||
599 (curr_inst == 0xeaa0d002))
601 struct minimal_symbol *stubsym, *libsym;
603 stubsym = lookup_minimal_symbol_by_pc (loc);
606 warning ("Unable to find symbol for 0x%lx", loc);
607 return orig_pc == pc ? 0 : pc & ~0x3;
610 libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
613 warning ("Unable to find library symbol for %s\n",
614 DEPRECATED_SYMBOL_NAME (stubsym));
615 return orig_pc == pc ? 0 : pc & ~0x3;
618 return SYMBOL_VALUE (libsym);
621 /* Does it look like bl X,%rp or bl X,%r0? Another way to do a
622 branch from the stub to the actual function. */
624 else if ((curr_inst & 0xffe0e000) == 0xe8400000
625 || (curr_inst & 0xffe0e000) == 0xe8000000
626 || (curr_inst & 0xffe0e000) == 0xe800A000)
627 return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3;
629 /* Does it look like bv (rp)? Note this depends on the
630 current stack pointer being the same as the stack
631 pointer in the stub itself! This is a branch on from the
632 stub back to the original caller. */
633 /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */
634 else if ((curr_inst & 0xffe0f000) == 0xe840c000)
636 /* Yup. See if the previous instruction loaded
638 if (prev_inst == 0x4bc23ff1)
639 return (read_memory_integer
640 (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
643 warning ("Unable to find restore of %%rp before bv (%%rp).");
644 return orig_pc == pc ? 0 : pc & ~0x3;
648 /* elz: added this case to capture the new instruction
649 at the end of the return part of an export stub used by
650 the PA2.0: BVE, n (rp) */
651 else if ((curr_inst & 0xffe0f000) == 0xe840d000)
653 return (read_memory_integer
654 (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
657 /* What about be,n 0(sr0,%rp)? It's just another way we return to
658 the original caller from the stub. Used in dynamic executables. */
659 else if (curr_inst == 0xe0400002)
661 /* The value we jump to is sitting in sp - 24. But that's
662 loaded several instructions before the be instruction.
663 I guess we could check for the previous instruction being
664 mtsp %r1,%sr0 if we want to do sanity checking. */
665 return (read_memory_integer
666 (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
669 /* Haven't found the branch yet, but we're still in the stub.
676 /* Exception handling support for the HP-UX ANSI C++ compiler.
677 The compiler (aCC) provides a callback for exception events;
678 GDB can set a breakpoint on this callback and find out what
679 exception event has occurred. */
681 /* The name of the hook to be set to point to the callback function */
682 static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
683 /* The name of the function to be used to set the hook value */
684 static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
685 /* The name of the callback function in end.o */
686 static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
687 /* Name of function in end.o on which a break is set (called by above) */
688 static char HP_ACC_EH_break[] = "__d_eh_break";
689 /* Name of flag (in end.o) that enables catching throws */
690 static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
691 /* Name of flag (in end.o) that enables catching catching */
692 static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
693 /* The enum used by aCC */
701 /* Is exception-handling support available with this executable? */
702 static int hp_cxx_exception_support = 0;
703 /* Has the initialize function been run? */
704 int hp_cxx_exception_support_initialized = 0;
705 /* Address of __eh_notify_hook */
706 static CORE_ADDR eh_notify_hook_addr = 0;
707 /* Address of __d_eh_notify_callback */
708 static CORE_ADDR eh_notify_callback_addr = 0;
709 /* Address of __d_eh_break */
710 static CORE_ADDR eh_break_addr = 0;
711 /* Address of __d_eh_catch_catch */
712 static CORE_ADDR eh_catch_catch_addr = 0;
713 /* Address of __d_eh_catch_throw */
714 static CORE_ADDR eh_catch_throw_addr = 0;
715 /* Sal for __d_eh_break */
716 static struct symtab_and_line *break_callback_sal = 0;
718 /* Code in end.c expects __d_pid to be set in the inferior,
719 otherwise __d_eh_notify_callback doesn't bother to call
720 __d_eh_break! So we poke the pid into this symbol
725 setup_d_pid_in_inferior (void)
728 struct minimal_symbol *msymbol;
729 char buf[4]; /* FIXME 32x64? */
731 /* Slam the pid of the process into __d_pid; failing is only a warning! */
732 msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
735 warning ("Unable to find __d_pid symbol in object file.");
736 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
740 anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
741 store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
742 if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
744 warning ("Unable to write __d_pid");
745 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
751 /* elz: Used to lookup a symbol in the shared libraries.
752 This function calls shl_findsym, indirectly through a
753 call to __d_shl_get. __d_shl_get is in end.c, which is always
754 linked in by the hp compilers/linkers.
755 The call to shl_findsym cannot be made directly because it needs
756 to be active in target address space.
757 inputs: - minimal symbol pointer for the function we want to look up
758 - address in target space of the descriptor for the library
759 where we want to look the symbol up.
760 This address is retrieved using the
761 som_solib_get_solib_by_pc function (somsolib.c).
762 output: - real address in the library of the function.
763 note: the handle can be null, in which case shl_findsym will look for
764 the symbol in all the loaded shared libraries.
765 files to look at if you need reference on this stuff:
766 dld.c, dld_shl_findsym.c
768 man entry for shl_findsym */
771 find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
773 struct symbol *get_sym, *symbol2;
774 struct minimal_symbol *buff_minsym, *msymbol;
777 struct value *funcval;
780 int x, namelen, err_value, tmp = -1;
781 CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
785 args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
786 funcval = find_function_in_inferior ("__d_shl_get");
787 get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
788 buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
789 msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
790 symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
791 endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
792 namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
793 value_return_addr = endo_buff_addr + namelen;
794 ftype = check_typedef (SYMBOL_TYPE (get_sym));
797 if ((x = value_return_addr % 64) != 0)
798 value_return_addr = value_return_addr + 64 - x;
800 errno_return_addr = value_return_addr + 64;
803 /* set up stuff needed by __d_shl_get in buffer in end.o */
805 target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
807 target_write_memory (value_return_addr, (char *) &tmp, 4);
809 target_write_memory (errno_return_addr, (char *) &tmp, 4);
811 target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
812 (char *) &handle, 4);
814 /* now prepare the arguments for the call */
816 args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
817 args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
818 args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
819 args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
820 args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
821 args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
823 /* now call the function */
825 val = call_function_by_hand (funcval, 6, args);
827 /* now get the results */
829 target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
831 target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
833 error ("call to __d_shl_get failed, error code is %d", err_value);
838 /* Cover routine for find_stub_with_shl_get to pass to catch_errors */
840 cover_find_stub_with_shl_get (void *args_untyped)
842 args_for_find_stub *args = args_untyped;
843 args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
847 /* Initialize exception catchpoint support by looking for the
848 necessary hooks/callbacks in end.o, etc., and set the hook value to
849 point to the required debug function
855 initialize_hp_cxx_exception_support (void)
857 struct symtabs_and_lines sals;
858 struct cleanup *old_chain;
859 struct cleanup *canonical_strings_chain = NULL;
862 char *addr_end = NULL;
863 char **canonical = (char **) NULL;
865 struct symbol *sym = NULL;
866 struct minimal_symbol *msym = NULL;
867 struct objfile *objfile;
868 asection *shlib_info;
870 /* Detect and disallow recursion. On HP-UX with aCC, infinite
871 recursion is a possibility because finding the hook for exception
872 callbacks involves making a call in the inferior, which means
873 re-inserting breakpoints which can re-invoke this code */
875 static int recurse = 0;
878 hp_cxx_exception_support_initialized = 0;
879 deprecated_exception_support_initialized = 0;
883 hp_cxx_exception_support = 0;
885 /* First check if we have seen any HP compiled objects; if not,
886 it is very unlikely that HP's idiosyncratic callback mechanism
887 for exception handling debug support will be available!
888 This will percolate back up to breakpoint.c, where our callers
889 will decide to try the g++ exception-handling support instead. */
890 if (!deprecated_hp_som_som_object_present)
893 /* We have a SOM executable with SOM debug info; find the hooks */
895 /* First look for the notify hook provided by aCC runtime libs */
896 /* If we find this symbol, we conclude that the executable must
897 have HP aCC exception support built in. If this symbol is not
898 found, even though we're a HP SOM-SOM file, we may have been
899 built with some other compiler (not aCC). This results percolates
900 back up to our callers in breakpoint.c which can decide to
901 try the g++ style of exception support instead.
902 If this symbol is found but the other symbols we require are
903 not found, there is something weird going on, and g++ support
904 should *not* be tried as an alternative.
906 ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
907 ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
909 /* libCsup has this hook; it'll usually be non-debuggable */
910 msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
913 eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
914 hp_cxx_exception_support = 1;
918 warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
919 warning ("Executable may not have been compiled debuggable with HP aCC.");
920 warning ("GDB will be unable to intercept exception events.");
921 eh_notify_hook_addr = 0;
922 hp_cxx_exception_support = 0;
926 /* Next look for the notify callback routine in end.o */
927 /* This is always available in the SOM symbol dictionary if end.o is linked in */
928 msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
931 eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
932 hp_cxx_exception_support = 1;
936 warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
937 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
938 warning ("GDB will be unable to intercept exception events.");
939 eh_notify_callback_addr = 0;
943 #ifndef GDB_TARGET_IS_HPPA_20W
944 /* Check whether the executable is dynamically linked or archive bound */
945 /* With an archive-bound executable we can use the raw addresses we find
946 for the callback function, etc. without modification. For an executable
947 with shared libraries, we have to do more work to find the plabel, which
948 can be the target of a call through $$dyncall from the aCC runtime support
949 library (libCsup) which is linked shared by default by aCC. */
950 /* This test below was copied from somsolib.c/somread.c. It may not be a very
951 reliable one to test that an executable is linked shared. pai/1997-07-18 */
952 shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
953 if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
955 /* The minsym we have has the local code address, but that's not the
956 plabel that can be used by an inter-load-module call. */
957 /* Find solib handle for main image (which has end.o), and use that
958 and the min sym as arguments to __d_shl_get() (which does the equivalent
959 of shl_findsym()) to find the plabel. */
961 args_for_find_stub args;
962 static char message[] = "Error while finding exception callback hook:\n";
964 args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
969 catch_errors (cover_find_stub_with_shl_get, &args, message,
971 eh_notify_callback_addr = args.return_val;
974 deprecated_exception_catchpoints_are_fragile = 1;
976 if (!eh_notify_callback_addr)
978 /* We can get here either if there is no plabel in the export list
979 for the main image, or if something strange happened (?) */
980 warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
981 warning ("GDB will not be able to intercept exception events.");
986 deprecated_exception_catchpoints_are_fragile = 0;
989 /* Now, look for the breakpointable routine in end.o */
990 /* This should also be available in the SOM symbol dict. if end.o linked in */
991 msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
994 eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
995 hp_cxx_exception_support = 1;
999 warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
1000 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
1001 warning ("GDB will be unable to intercept exception events.");
1006 /* Next look for the catch enable flag provided in end.o */
1007 sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
1008 VAR_DOMAIN, 0, (struct symtab **) NULL);
1009 if (sym) /* sometimes present in debug info */
1011 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
1012 hp_cxx_exception_support = 1;
1015 /* otherwise look in SOM symbol dict. */
1017 msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
1020 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
1021 hp_cxx_exception_support = 1;
1025 warning ("Unable to enable interception of exception catches.");
1026 warning ("Executable may not have been compiled debuggable with HP aCC.");
1027 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
1032 /* Next look for the catch enable flag provided end.o */
1033 sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
1034 VAR_DOMAIN, 0, (struct symtab **) NULL);
1035 if (sym) /* sometimes present in debug info */
1037 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
1038 hp_cxx_exception_support = 1;
1041 /* otherwise look in SOM symbol dict. */
1043 msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
1046 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
1047 hp_cxx_exception_support = 1;
1051 warning ("Unable to enable interception of exception throws.");
1052 warning ("Executable may not have been compiled debuggable with HP aCC.");
1053 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
1059 hp_cxx_exception_support = 2; /* everything worked so far */
1060 hp_cxx_exception_support_initialized = 1;
1061 deprecated_exception_support_initialized = 1;
1066 /* Target operation for enabling or disabling interception of
1068 KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
1069 ENABLE is either 0 (disable) or 1 (enable).
1070 Return value is NULL if no support found;
1071 -1 if something went wrong,
1072 or a pointer to a symtab/line struct if the breakpointable
1073 address was found. */
1075 struct symtab_and_line *
1076 child_enable_exception_callback (enum exception_event_kind kind, int enable)
1080 if (!deprecated_exception_support_initialized
1081 || !hp_cxx_exception_support_initialized)
1082 if (!initialize_hp_cxx_exception_support ())
1085 switch (hp_cxx_exception_support)
1088 /* Assuming no HP support at all */
1091 /* HP support should be present, but something went wrong */
1092 return (struct symtab_and_line *) -1; /* yuck! */
1093 /* there may be other cases in the future */
1096 /* Set the EH hook to point to the callback routine */
1097 store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
1098 /* pai: (temp) FIXME should there be a pack operation first? */
1099 if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
1101 warning ("Could not write to target memory for exception event callback.");
1102 warning ("Interception of exception events may not work.");
1103 return (struct symtab_and_line *) -1;
1107 /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
1108 if (PIDGET (inferior_ptid) > 0)
1110 if (setup_d_pid_in_inferior ())
1111 return (struct symtab_and_line *) -1;
1115 warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
1116 return (struct symtab_and_line *) -1;
1122 case EX_EVENT_THROW:
1123 store_unsigned_integer (buf, 4, enable ? 1 : 0);
1124 if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
1126 warning ("Couldn't enable exception throw interception.");
1127 return (struct symtab_and_line *) -1;
1130 case EX_EVENT_CATCH:
1131 store_unsigned_integer (buf, 4, enable ? 1 : 0);
1132 if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
1134 warning ("Couldn't enable exception catch interception.");
1135 return (struct symtab_and_line *) -1;
1139 error ("Request to enable unknown or unsupported exception event.");
1142 /* Copy break address into new sal struct, malloc'ing if needed. */
1143 if (!break_callback_sal)
1145 break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
1147 init_sal (break_callback_sal);
1148 break_callback_sal->symtab = NULL;
1149 break_callback_sal->pc = eh_break_addr;
1150 break_callback_sal->line = 0;
1151 break_callback_sal->end = eh_break_addr;
1153 return break_callback_sal;
1156 /* Record some information about the current exception event */
1157 static struct exception_event_record current_ex_event;
1158 /* Convenience struct */
1159 static struct symtab_and_line null_symtab_and_line =
1162 /* Report current exception event. Returns a pointer to a record
1163 that describes the kind of the event, where it was thrown from,
1164 and where it will be caught. More information may be reported
1166 struct exception_event_record *
1167 child_get_current_exception_event (void)
1169 CORE_ADDR event_kind;
1170 CORE_ADDR throw_addr;
1171 CORE_ADDR catch_addr;
1172 struct frame_info *fi, *curr_frame;
1175 curr_frame = get_current_frame ();
1177 return (struct exception_event_record *) NULL;
1179 /* Go up one frame to __d_eh_notify_callback, because at the
1180 point when this code is executed, there's garbage in the
1181 arguments of __d_eh_break. */
1182 fi = find_relative_frame (curr_frame, &level);
1184 return (struct exception_event_record *) NULL;
1188 /* Read in the arguments */
1189 /* __d_eh_notify_callback() is called with 3 arguments:
1190 1. event kind catch or throw
1191 2. the target address if known
1192 3. a flag -- not sure what this is. pai/1997-07-17 */
1193 event_kind = read_register (ARG0_REGNUM);
1194 catch_addr = read_register (ARG1_REGNUM);
1196 /* Now go down to a user frame */
1197 /* For a throw, __d_eh_break is called by
1198 __d_eh_notify_callback which is called by
1199 __notify_throw which is called
1201 For a catch, __d_eh_break is called by
1202 __d_eh_notify_callback which is called by
1203 <stackwalking stuff> which is called by
1204 __throw__<stuff> or __rethrow_<stuff> which is called
1206 /* FIXME: Don't use such magic numbers; search for the frames */
1207 level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
1208 fi = find_relative_frame (curr_frame, &level);
1210 return (struct exception_event_record *) NULL;
1213 throw_addr = get_frame_pc (fi);
1215 /* Go back to original (top) frame */
1216 select_frame (curr_frame);
1218 current_ex_event.kind = (enum exception_event_kind) event_kind;
1219 current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
1220 current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
1222 return ¤t_ex_event;
1226 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1228 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1230 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, hppa_hpux_pc_in_sigtramp);
1232 if (tdep->bytes_per_address == 4)
1233 set_gdbarch_in_solib_call_trampoline (gdbarch,
1234 hppa32_hpux_in_solib_call_trampoline);
1236 set_gdbarch_in_solib_call_trampoline (gdbarch,
1237 hppa64_hpux_in_solib_call_trampoline);
1239 set_gdbarch_in_solib_return_trampoline (gdbarch,
1240 hppa_hpux_in_solib_return_trampoline);
1241 set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
1245 hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1247 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1250 hppa_hpux_init_abi (info, gdbarch);
1254 hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1256 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1259 hppa_hpux_init_abi (info, gdbarch);
1263 _initialize_hppa_hpux_tdep (void)
1265 gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
1266 hppa_hpux_som_init_abi);
1267 gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
1268 hppa_hpux_elf_init_abi);