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