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
hppa32_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)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
hppa64_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)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
hppa_hpux_in_solib_return_trampoline(CORE_ADDR pc,char * name)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
hppa_hpux_skip_trampoline_code(CORE_ADDR pc)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
setup_d_pid_in_inferior(void)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
find_stub_with_shl_get(struct minimal_symbol * function,CORE_ADDR handle)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
cover_find_stub_with_shl_get(void * args_untyped)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
initialize_hp_cxx_exception_support(void)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 *
child_enable_exception_callback(enum exception_event_kind kind,int enable)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 *
child_get_current_exception_event(void)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 *
hppa_hpux_sigtramp_frame_unwind_cache(struct frame_info * next_frame,void ** this_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
hppa_hpux_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_prologue_cache,struct frame_id * this_id)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
hppa_hpux_sigtramp_frame_prev_register(struct frame_info * next_frame,void ** this_prologue_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)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 *
hppa_hpux_sigtramp_unwind_sniffer(struct frame_info * next_frame)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
hppa_hpux_som_find_global_pointer(struct value * function)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
hppa_hpux_push_dummy_code(struct gdbarch * gdbarch,CORE_ADDR sp,CORE_ADDR funcaddr,int using_gcc,struct value ** args,int nargs,struct type * value_type,CORE_ADDR * real_pc,CORE_ADDR * bp_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
hppa_hpux_inferior_created(struct target_ops * objfile,int from_tty)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
hppa_hpux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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
hppa_hpux_som_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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
hppa_hpux_elf_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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
_initialize_hppa_hpux_tdep(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