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