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"
27 #include "frame-unwind.h"
28 #include "trad-frame.h"
34 #include "hppa-tdep.h"
37 #include <machine/save_state.h>
40 #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
43 /* Forward declarations. */
44 extern void _initialize_hppa_hpux_tdep (void);
45 extern initialize_file_ftype _initialize_hppa_hpux_tdep;
49 struct minimal_symbol *msym;
50 CORE_ADDR solib_handle;
55 /* Return one if PC is in the call path of a trampoline, else return zero.
57 Note we return one for *any* call trampoline (long-call, arg-reloc), not
58 just shared library trampolines (import, export). */
61 hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
63 struct minimal_symbol *minsym;
64 struct unwind_table_entry *u;
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"))
71 minsym = lookup_minimal_symbol_by_pc (pc);
72 if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
75 /* Get the unwind descriptor corresponding to PC, return zero
76 if no unwind was found. */
77 u = find_unwind_entry (pc);
81 /* If this isn't a linker stub, then return now. */
82 if (u->stub_unwind.stub_type == 0)
85 /* By definition a long-branch stub is a call stub. */
86 if (u->stub_unwind.stub_type == LONG_BRANCH)
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
92 if (u->stub_unwind.stub_type == IMPORT)
95 /* Parameter relocation stubs always have a call path and may have a
97 if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
98 || u->stub_unwind.stub_type == EXPORT)
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)
108 insn = read_memory_integer (addr, 4);
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)
114 else if ((insn & 0xfc00e001) == 0xe800c000
115 || (insn & 0xfc000000) == 0xe0000000)
119 /* Should never happen. */
120 warning ("Unable to find branch in parameter relocation stub.\n");
124 /* Unknown stub type. For now, just return zero. */
129 hppa64_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
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
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
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.
144 Finally peek at the instructions to see if they look like a stub. */
145 struct minimal_symbol *minsym;
150 minsym = lookup_minimal_symbol_by_pc (pc);
154 sec = SYMBOL_BFD_SECTION (minsym);
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)))
161 /* We might be in a stub. Peek at the instructions. Stubs are 3
162 instructions long. */
163 insn = read_memory_integer (pc, 4);
165 /* Find out where we think we are within the stub. */
166 if ((insn & 0xffffc00e) == 0x53610000)
168 else if ((insn & 0xffffffff) == 0xe820d000)
170 else if ((insn & 0xffffc00e) == 0x537b0000)
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)
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)
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)
190 /* Looks like a stub. */
194 /* Return one if PC is in the return path of a trampoline, else return zero.
196 Note we return one for *any* call trampoline (long-call, arg-reloc), not
197 just shared library trampolines (import, export). */
200 hppa_hpux_in_solib_return_trampoline (CORE_ADDR pc, char *name)
202 struct unwind_table_entry *u;
204 /* Get the unwind descriptor corresponding to PC, return zero
205 if no unwind was found. */
206 u = find_unwind_entry (pc);
210 /* If this isn't a linker stub or it's just a long branch stub, then
212 if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
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
218 if (u->stub_unwind.stub_type == IMPORT)
221 /* Parameter relocation stubs always have a call path and may have a
223 if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
224 || u->stub_unwind.stub_type == EXPORT)
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)
234 insn = read_memory_integer (addr, 4);
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)
240 else if ((insn & 0xfc00e001) == 0xe800c000
241 || (insn & 0xfc000000) == 0xe0000000)
245 /* Should never happen. */
246 warning ("Unable to find branch in parameter relocation stub.\n");
250 /* Unknown stub type. For now, just return zero. */
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.
258 Simple code examination probably is not a good idea since the code
259 sequences in trampolines can also appear in user code.
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.
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. */
273 hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
276 long prev_inst, curr_inst, loc;
277 struct minimal_symbol *msym;
278 struct unwind_table_entry *u;
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"))
284 pc = (CORE_ADDR) read_register (22);
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. */
290 pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
292 if (pc == hppa_symbol_address("$$dyncall_external"))
294 pc = (CORE_ADDR) read_register (22);
295 pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
297 else if (pc == hppa_symbol_address("_sr4export"))
298 pc = (CORE_ADDR) (read_register (22));
300 /* Get the unwind descriptor corresponding to PC, return zero
301 if no unwind was found. */
302 u = find_unwind_entry (pc);
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)
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);
331 if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
332 return orig_pc == pc ? 0 : pc & ~0x3;
334 else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
336 struct objfile *objfile;
337 struct minimal_symbol *msymbol;
338 int function_found = 0;
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 */
345 ALL_MSYMBOLS (objfile, msymbol)
347 if (MSYMBOL_TYPE (msymbol) == mst_text
348 && DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
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;
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 */
365 MSYMBOL_TYPE (msym) = mst_text;
366 return orig_pc == pc ? 0 : pc & ~0x3;
370 /*--------------------------------------------------------------------------*/
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. */
383 /* Make sure we haven't walked outside the range of this stub. */
384 if (u != find_unwind_entry (loc))
386 warning ("Unable to find branch in linker stub");
387 return orig_pc == pc ? 0 : pc & ~0x3;
390 prev_inst = curr_inst;
391 curr_inst = read_memory_integer (loc, 4);
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)
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;
403 warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
404 return orig_pc == pc ? 0 : pc & ~0x3;
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.
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).
420 So we have try an alternative approach.
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
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))
434 struct minimal_symbol *stubsym, *libsym;
436 stubsym = lookup_minimal_symbol_by_pc (loc);
439 warning ("Unable to find symbol for 0x%lx", loc);
440 return orig_pc == pc ? 0 : pc & ~0x3;
443 libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
446 warning ("Unable to find library symbol for %s\n",
447 DEPRECATED_SYMBOL_NAME (stubsym));
448 return orig_pc == pc ? 0 : pc & ~0x3;
451 return SYMBOL_VALUE (libsym);
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. */
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;
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)
469 /* Yup. See if the previous instruction loaded
471 if (prev_inst == 0x4bc23ff1)
472 return (read_memory_integer
473 (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
476 warning ("Unable to find restore of %%rp before bv (%%rp).");
477 return orig_pc == pc ? 0 : pc & ~0x3;
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)
486 return (read_memory_integer
487 (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
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)
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;
502 /* Haven't found the branch yet, but we're still in the stub.
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. */
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 */
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;
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
558 setup_d_pid_in_inferior (void)
561 struct minimal_symbol *msymbol;
562 char buf[4]; /* FIXME 32x64? */
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);
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).");
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? */
577 warning ("Unable to write __d_pid");
578 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
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
601 man entry for shl_findsym */
604 find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
606 struct symbol *get_sym, *symbol2;
607 struct minimal_symbol *buff_minsym, *msymbol;
610 struct value *funcval;
613 int x, namelen, err_value, tmp = -1;
614 CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
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));
630 if ((x = value_return_addr % 64) != 0)
631 value_return_addr = value_return_addr + 64 - x;
633 errno_return_addr = value_return_addr + 64;
636 /* set up stuff needed by __d_shl_get in buffer in end.o */
638 target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
640 target_write_memory (value_return_addr, (char *) &tmp, 4);
642 target_write_memory (errno_return_addr, (char *) &tmp, 4);
644 target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
645 (char *) &handle, 4);
647 /* now prepare the arguments for the call */
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);
656 /* now call the function */
658 val = call_function_by_hand (funcval, 6, args);
660 /* now get the results */
662 target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
664 target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
666 error ("call to __d_shl_get failed, error code is %d", err_value);
671 /* Cover routine for find_stub_with_shl_get to pass to catch_errors */
673 cover_find_stub_with_shl_get (void *args_untyped)
675 args_for_find_stub *args = args_untyped;
676 args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
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
688 initialize_hp_cxx_exception_support (void)
690 struct symtabs_and_lines sals;
691 struct cleanup *old_chain;
692 struct cleanup *canonical_strings_chain = NULL;
695 char *addr_end = NULL;
696 char **canonical = (char **) NULL;
698 struct symbol *sym = NULL;
699 struct minimal_symbol *msym = NULL;
700 struct objfile *objfile;
701 asection *shlib_info;
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 */
708 static int recurse = 0;
711 hp_cxx_exception_support_initialized = 0;
712 deprecated_exception_support_initialized = 0;
716 hp_cxx_exception_support = 0;
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)
726 /* We have a SOM executable with SOM debug info; find the hooks */
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.
739 ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
740 ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
742 /* libCsup has this hook; it'll usually be non-debuggable */
743 msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
746 eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
747 hp_cxx_exception_support = 1;
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;
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);
764 eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
765 hp_cxx_exception_support = 1;
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;
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))
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. */
794 args_for_find_stub args;
795 static char message[] = "Error while finding exception callback hook:\n";
797 args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
802 catch_errors (cover_find_stub_with_shl_get, &args, message,
804 eh_notify_callback_addr = args.return_val;
807 deprecated_exception_catchpoints_are_fragile = 1;
809 if (!eh_notify_callback_addr)
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.");
819 deprecated_exception_catchpoints_are_fragile = 0;
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);
827 eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
828 hp_cxx_exception_support = 1;
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.");
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 */
844 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
845 hp_cxx_exception_support = 1;
848 /* otherwise look in SOM symbol dict. */
850 msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
853 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
854 hp_cxx_exception_support = 1;
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).");
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 */
870 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
871 hp_cxx_exception_support = 1;
874 /* otherwise look in SOM symbol dict. */
876 msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
879 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
880 hp_cxx_exception_support = 1;
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).");
892 hp_cxx_exception_support = 2; /* everything worked so far */
893 hp_cxx_exception_support_initialized = 1;
894 deprecated_exception_support_initialized = 1;
899 /* Target operation for enabling or disabling interception of
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. */
908 struct symtab_and_line *
909 child_enable_exception_callback (enum exception_event_kind kind, int enable)
913 if (!deprecated_exception_support_initialized
914 || !hp_cxx_exception_support_initialized)
915 if (!initialize_hp_cxx_exception_support ())
918 switch (hp_cxx_exception_support)
921 /* Assuming no HP support at all */
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 */
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 */
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;
940 /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
941 if (PIDGET (inferior_ptid) > 0)
943 if (setup_d_pid_in_inferior ())
944 return (struct symtab_and_line *) -1;
948 warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
949 return (struct symtab_and_line *) -1;
956 store_unsigned_integer (buf, 4, enable ? 1 : 0);
957 if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
959 warning ("Couldn't enable exception throw interception.");
960 return (struct symtab_and_line *) -1;
964 store_unsigned_integer (buf, 4, enable ? 1 : 0);
965 if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
967 warning ("Couldn't enable exception catch interception.");
968 return (struct symtab_and_line *) -1;
972 error ("Request to enable unknown or unsupported exception event.");
975 /* Copy break address into new sal struct, malloc'ing if needed. */
976 if (!break_callback_sal)
978 break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
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;
986 return break_callback_sal;
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 =
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
999 struct exception_event_record *
1000 child_get_current_exception_event (void)
1002 CORE_ADDR event_kind;
1003 CORE_ADDR throw_addr;
1004 CORE_ADDR catch_addr;
1005 struct frame_info *fi, *curr_frame;
1008 curr_frame = get_current_frame ();
1010 return (struct exception_event_record *) NULL;
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);
1017 return (struct exception_event_record *) NULL;
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);
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
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
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);
1043 return (struct exception_event_record *) NULL;
1046 throw_addr = get_frame_pc (fi);
1048 /* Go back to original (top) frame */
1049 select_frame (curr_frame);
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);
1055 return ¤t_ex_event;
1058 /* Signal frames. */
1059 struct hppa_hpux_sigtramp_unwind_cache
1062 struct trad_frame_saved_reg *saved_regs;
1065 static int hppa_hpux_tramp_reg[] = {
1067 HPPA_PCOQ_HEAD_REGNUM,
1068 HPPA_PCSQ_HEAD_REGNUM,
1069 HPPA_PCOQ_TAIL_REGNUM,
1070 HPPA_PCSQ_TAIL_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,
1092 HPPA_TR0_REGNUM + 1,
1093 HPPA_TR0_REGNUM + 2,
1097 static struct hppa_hpux_sigtramp_unwind_cache *
1098 hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
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;
1106 CORE_ADDR sp, scptr;
1107 int i, incr, off, szoff;
1112 info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache);
1114 info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
1116 sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1121 /* See /usr/include/machine/save_state.h for the structure of the save_state_t
1124 flag = read_memory_unsigned_integer(scptr, 4);
1128 /* Narrow registers. */
1129 off = scptr + offsetof (save_state_t, ss_narrow);
1135 /* Wide registers. */
1136 off = scptr + offsetof (save_state_t, ss_wide) + 8;
1138 szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
1141 for (i = 1; i < 32; i++)
1143 info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff;
1148 i < sizeof(hppa_hpux_tramp_reg) / sizeof(hppa_hpux_tramp_reg[0]);
1151 if (hppa_hpux_tramp_reg[i] > 0)
1152 info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff;
1158 info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1164 hppa_hpux_sigtramp_frame_this_id (struct frame_info *next_frame,
1165 void **this_prologue_cache,
1166 struct frame_id *this_id)
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));
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,
1179 int *realnump, void *valuep)
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);
1187 static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
1189 hppa_hpux_sigtramp_frame_this_id,
1190 hppa_hpux_sigtramp_frame_prev_register
1193 static const struct frame_unwind *
1194 hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
1196 CORE_ADDR pc = frame_pc_unwind (next_frame);
1199 find_pc_partial_function (pc, &name, NULL, NULL);
1201 if (name && strcmp(name, "_sigreturn") == 0)
1202 return &hppa_hpux_sigtramp_frame_unwind;
1208 hppa_hpux_som_find_global_pointer (struct value *function)
1212 faddr = value_as_address (function);
1214 /* Is this a plabel? If so, dereference it to get the gp value. */
1222 status = target_read_memory (faddr + 4, buf, sizeof (buf));
1224 return extract_unsigned_integer (buf, sizeof (buf));
1227 return som_solib_get_got_by_pc (faddr);
1231 hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
1232 CORE_ADDR funcaddr, int using_gcc,
1233 struct value **args, int nargs,
1234 struct type *value_type,
1235 CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
1237 /* FIXME: tausq/2004-06-09: This needs much more testing. It is broken
1238 for pa64, but we should be able to get it to work with a little bit
1239 of work. gdb-6.1 has a lot of code to handle various cases; I've tried to
1240 simplify it and avoid compile-time conditionals. */
1242 /* On HPUX, functions in the main executable and in libraries can be located
1243 in different spaces. In order for us to be able to select the right
1244 space for the function call, we need to go through an instruction seqeunce
1245 to select the right space for the target function, call it, and then
1246 restore the space on return.
1248 There are two helper routines that can be used for this task -- if
1249 an application is linked with gcc, it will contain a __gcc_plt_call
1250 helper function. __gcc_plt_call, when passed the entry point of an
1251 import stub, will do the necessary space setting/restoration for the
1254 For programs that are compiled/linked with the HP compiler, a similar
1255 function called __d_plt_call exists; __d_plt_call expects a PLABEL instead
1256 of an import stub as an argument.
1259 To summarize, the call flow is:
1260 current function -> dummy frame -> __gcc_plt_call (import stub)
1263 current function -> dummy frame -> __d_plt_call (plabel)
1267 In general the "funcaddr" argument passed to push_dummy_code is the actual
1268 entry point of the target function. For __gcc_plt_call, we need to
1269 locate the import stub for the corresponding function. Failing that,
1270 we construct a dummy "import stub" on the stack to pass as an argument.
1271 For __d_plt_call, we similarly synthesize a PLABEL on the stack to
1272 pass to the helper function.
1274 An additional twist is that, in order for us to restore the space register
1275 to its starting state, we need __gcc_plt_call/__d_plt_call to return
1276 to the instruction where we started the call. However, if we put
1277 the breakpoint there, gdb will complain because it will find two
1278 frames on the stack with the same (sp, pc) (with the dummy frame in
1279 between). Currently, we set the return pointer to (pc - 4) of the
1280 current function. FIXME: This is not an ideal solution; possibly if the
1281 current pc is at the beginning of a page, this will cause a page fault.
1282 Need to understand this better and figure out a better way to fix it. */
1284 struct minimal_symbol *sym;
1286 /* Nonzero if we will use GCC's PLT call routine. This routine must be
1287 passed an import stub, not a PLABEL. It is also necessary to get %r19
1288 before performing the call. (This is done by push_dummy_call.) */
1289 int use_gcc_plt_call = 1;
1291 /* See if __gcc_plt_call is available; if not we will use the HP version
1293 sym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
1295 use_gcc_plt_call = 0;
1297 /* If using __gcc_plt_call, we need to make sure we pass in an import
1298 stub. funcaddr can be pointing to an export stub or a real function,
1299 so we try to resolve it to the import stub. */
1300 if (use_gcc_plt_call)
1302 struct objfile *objfile;
1303 struct minimal_symbol *funsym, *stubsym;
1304 CORE_ADDR stubaddr = 0;
1306 funsym = lookup_minimal_symbol_by_pc (funcaddr);
1308 error ("Unable to find symbol for target function.\n");
1310 ALL_OBJFILES (objfile)
1312 stubsym = lookup_minimal_symbol_solib_trampoline
1313 (SYMBOL_LINKAGE_NAME (funsym), objfile);
1317 struct unwind_table_entry *u;
1319 u = find_unwind_entry (SYMBOL_VALUE (stubsym));
1321 || (u->stub_unwind.stub_type != IMPORT
1322 && u->stub_unwind.stub_type != IMPORT_SHLIB))
1325 stubaddr = SYMBOL_VALUE (stubsym);
1327 /* If we found an IMPORT stub, then we can stop searching;
1328 if we found an IMPORT_SHLIB, we want to continue the search
1329 in the hopes that we will find an IMPORT stub. */
1330 if (u->stub_unwind.stub_type == IMPORT)
1337 /* Argument to __gcc_plt_call is passed in r22. */
1338 regcache_cooked_write_unsigned (current_regcache, 22, stubaddr);
1342 /* No import stub found; let's synthesize one. */
1344 /* ldsid %r21, %r1 */
1345 write_memory_unsigned_integer (sp, 4, 0x02a010a1);
1347 write_memory_unsigned_integer (sp + 4, 4, 0x00011820);
1348 /* be 0(%sr0, %r21) */
1349 write_memory_unsigned_integer (sp + 8, 4, 0xe2a00000);
1351 write_memory_unsigned_integer (sp + 12, 4, 0x08000240);
1353 regcache_cooked_write_unsigned (current_regcache, 21, funcaddr);
1354 regcache_cooked_write_unsigned (current_regcache, 22, sp);
1357 /* We set the breakpoint address and r31 to (close to) where the current
1358 pc is; when __gcc_plt_call returns, it will restore pcsqh to the
1359 current value based on this. The -4 is needed for frame unwinding
1360 to work properly -- we need to land in a different function than
1361 the current function. */
1362 *bp_addr = (read_register (HPPA_PCOQ_HEAD_REGNUM) & ~3) - 4;
1363 regcache_cooked_write_unsigned (current_regcache, 31, *bp_addr);
1365 /* Continue from __gcc_plt_call. */
1366 *real_pc = SYMBOL_VALUE (sym);
1372 /* Use __d_plt_call as a fallback; __d_plt_call expects to be called
1373 with a plabel, so we need to build one. */
1375 sym = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
1377 error("Can't find an address for __d_plt_call or __gcc_plt_call "
1378 "trampoline\nSuggest linking executable with -g or compiling "
1381 gp = gdbarch_tdep (gdbarch)->find_global_pointer (funcaddr);
1382 write_memory_unsigned_integer (sp, 4, funcaddr);
1383 write_memory_unsigned_integer (sp + 4, 4, gp);
1385 /* plabel is passed in r22 */
1386 regcache_cooked_write_unsigned (current_regcache, 22, sp);
1389 /* Pushed one stack frame, which has to be 64-byte aligned. */
1396 hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
1398 /* Some HP-UX related globals to clear when a new "main"
1399 symbol file is loaded. HP-specific. */
1400 deprecated_hp_som_som_object_present = 0;
1401 hp_cxx_exception_support_initialized = 0;
1405 hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1407 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1409 if (tdep->bytes_per_address == 4)
1410 set_gdbarch_in_solib_call_trampoline (gdbarch,
1411 hppa32_hpux_in_solib_call_trampoline);
1413 set_gdbarch_in_solib_call_trampoline (gdbarch,
1414 hppa64_hpux_in_solib_call_trampoline);
1416 set_gdbarch_in_solib_return_trampoline (gdbarch,
1417 hppa_hpux_in_solib_return_trampoline);
1418 set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
1420 set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code);
1421 set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
1423 frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
1425 observer_attach_inferior_created (hppa_hpux_inferior_created);
1429 hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1431 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1435 tdep->find_global_pointer = hppa_hpux_som_find_global_pointer;
1436 hppa_hpux_init_abi (info, gdbarch);
1440 hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1442 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1445 hppa_hpux_init_abi (info, gdbarch);
1449 _initialize_hppa_hpux_tdep (void)
1451 gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
1452 hppa_hpux_som_init_abi);
1453 gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
1454 hppa_hpux_elf_init_abi);