Add OpenBSD/powerpc support.
[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 {
113 if (i == SP_REGNUM)
43bd9a9e 114 fsr[SP_REGNUM] = read_memory_integer (tmp + 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 {
158 if (i == SP_REGNUM)
159 fsr[SP_REGNUM] = read_memory_integer (tmp1 + SP_REGNUM * 8, 8);
160 else if (i >= FP0_REGNUM)
161 fsr[i] = tmp2 + (i - FP0_REGNUM) * 8;
162 else
163 fsr[i] = tmp1 + i * 8;
164 }
165}
166
4c02c60c
AC
167/* Exception handling support for the HP-UX ANSI C++ compiler.
168 The compiler (aCC) provides a callback for exception events;
169 GDB can set a breakpoint on this callback and find out what
170 exception event has occurred. */
171
172/* The name of the hook to be set to point to the callback function */
173static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
174/* The name of the function to be used to set the hook value */
175static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
176/* The name of the callback function in end.o */
177static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
178/* Name of function in end.o on which a break is set (called by above) */
179static char HP_ACC_EH_break[] = "__d_eh_break";
180/* Name of flag (in end.o) that enables catching throws */
181static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
182/* Name of flag (in end.o) that enables catching catching */
183static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
184/* The enum used by aCC */
185typedef enum
186 {
187 __EH_NOTIFY_THROW,
188 __EH_NOTIFY_CATCH
189 }
190__eh_notification;
191
192/* Is exception-handling support available with this executable? */
193static int hp_cxx_exception_support = 0;
194/* Has the initialize function been run? */
195int hp_cxx_exception_support_initialized = 0;
4c02c60c
AC
196/* Address of __eh_notify_hook */
197static CORE_ADDR eh_notify_hook_addr = 0;
198/* Address of __d_eh_notify_callback */
199static CORE_ADDR eh_notify_callback_addr = 0;
200/* Address of __d_eh_break */
201static CORE_ADDR eh_break_addr = 0;
202/* Address of __d_eh_catch_catch */
203static CORE_ADDR eh_catch_catch_addr = 0;
204/* Address of __d_eh_catch_throw */
205static CORE_ADDR eh_catch_throw_addr = 0;
206/* Sal for __d_eh_break */
207static struct symtab_and_line *break_callback_sal = 0;
208
209/* Code in end.c expects __d_pid to be set in the inferior,
210 otherwise __d_eh_notify_callback doesn't bother to call
211 __d_eh_break! So we poke the pid into this symbol
212 ourselves.
213 0 => success
214 1 => failure */
215int
216setup_d_pid_in_inferior (void)
217{
218 CORE_ADDR anaddr;
219 struct minimal_symbol *msymbol;
220 char buf[4]; /* FIXME 32x64? */
221
222 /* Slam the pid of the process into __d_pid; failing is only a warning! */
223 msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
224 if (msymbol == NULL)
225 {
226 warning ("Unable to find __d_pid symbol in object file.");
227 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
228 return 1;
229 }
230
231 anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
232 store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
233 if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
234 {
235 warning ("Unable to write __d_pid");
236 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
237 return 1;
238 }
239 return 0;
240}
241
242/* elz: Used to lookup a symbol in the shared libraries.
243 This function calls shl_findsym, indirectly through a
244 call to __d_shl_get. __d_shl_get is in end.c, which is always
245 linked in by the hp compilers/linkers.
246 The call to shl_findsym cannot be made directly because it needs
247 to be active in target address space.
248 inputs: - minimal symbol pointer for the function we want to look up
249 - address in target space of the descriptor for the library
250 where we want to look the symbol up.
251 This address is retrieved using the
252 som_solib_get_solib_by_pc function (somsolib.c).
253 output: - real address in the library of the function.
254 note: the handle can be null, in which case shl_findsym will look for
255 the symbol in all the loaded shared libraries.
256 files to look at if you need reference on this stuff:
257 dld.c, dld_shl_findsym.c
258 end.c
259 man entry for shl_findsym */
260
261CORE_ADDR
262find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
263{
264 struct symbol *get_sym, *symbol2;
265 struct minimal_symbol *buff_minsym, *msymbol;
266 struct type *ftype;
267 struct value **args;
268 struct value *funcval;
269 struct value *val;
270
271 int x, namelen, err_value, tmp = -1;
272 CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
273 CORE_ADDR stub_addr;
274
275
276 args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
277 funcval = find_function_in_inferior ("__d_shl_get");
278 get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
279 buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
280 msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
281 symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
282 endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
283 namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
284 value_return_addr = endo_buff_addr + namelen;
285 ftype = check_typedef (SYMBOL_TYPE (get_sym));
286
287 /* do alignment */
288 if ((x = value_return_addr % 64) != 0)
289 value_return_addr = value_return_addr + 64 - x;
290
291 errno_return_addr = value_return_addr + 64;
292
293
294 /* set up stuff needed by __d_shl_get in buffer in end.o */
295
296 target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
297
298 target_write_memory (value_return_addr, (char *) &tmp, 4);
299
300 target_write_memory (errno_return_addr, (char *) &tmp, 4);
301
302 target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
303 (char *) &handle, 4);
304
305 /* now prepare the arguments for the call */
306
307 args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
308 args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
309 args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
310 args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
311 args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
312 args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
313
314 /* now call the function */
315
316 val = call_function_by_hand (funcval, 6, args);
317
318 /* now get the results */
319
320 target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
321
322 target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
323 if (stub_addr <= 0)
324 error ("call to __d_shl_get failed, error code is %d", err_value);
325
326 return (stub_addr);
327}
328
329/* Cover routine for find_stub_with_shl_get to pass to catch_errors */
330static int
331cover_find_stub_with_shl_get (void *args_untyped)
332{
333 args_for_find_stub *args = args_untyped;
334 args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
335 return 0;
336}
337
338/* Initialize exception catchpoint support by looking for the
339 necessary hooks/callbacks in end.o, etc., and set the hook value to
340 point to the required debug function
341
342 Return 0 => failure
343 1 => success */
344
345static int
346initialize_hp_cxx_exception_support (void)
347{
348 struct symtabs_and_lines sals;
349 struct cleanup *old_chain;
350 struct cleanup *canonical_strings_chain = NULL;
351 int i;
352 char *addr_start;
353 char *addr_end = NULL;
354 char **canonical = (char **) NULL;
355 int thread = -1;
356 struct symbol *sym = NULL;
357 struct minimal_symbol *msym = NULL;
358 struct objfile *objfile;
359 asection *shlib_info;
360
361 /* Detect and disallow recursion. On HP-UX with aCC, infinite
362 recursion is a possibility because finding the hook for exception
363 callbacks involves making a call in the inferior, which means
364 re-inserting breakpoints which can re-invoke this code */
365
366 static int recurse = 0;
367 if (recurse > 0)
368 {
369 hp_cxx_exception_support_initialized = 0;
f83f82bc 370 deprecated_exception_support_initialized = 0;
4c02c60c
AC
371 return 0;
372 }
373
374 hp_cxx_exception_support = 0;
375
376 /* First check if we have seen any HP compiled objects; if not,
377 it is very unlikely that HP's idiosyncratic callback mechanism
378 for exception handling debug support will be available!
379 This will percolate back up to breakpoint.c, where our callers
380 will decide to try the g++ exception-handling support instead. */
f83f82bc 381 if (!deprecated_hp_som_som_object_present)
4c02c60c
AC
382 return 0;
383
384 /* We have a SOM executable with SOM debug info; find the hooks */
385
386 /* First look for the notify hook provided by aCC runtime libs */
387 /* If we find this symbol, we conclude that the executable must
388 have HP aCC exception support built in. If this symbol is not
389 found, even though we're a HP SOM-SOM file, we may have been
390 built with some other compiler (not aCC). This results percolates
391 back up to our callers in breakpoint.c which can decide to
392 try the g++ style of exception support instead.
393 If this symbol is found but the other symbols we require are
394 not found, there is something weird going on, and g++ support
395 should *not* be tried as an alternative.
396
397 ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
398 ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
399
400 /* libCsup has this hook; it'll usually be non-debuggable */
401 msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
402 if (msym)
403 {
404 eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
405 hp_cxx_exception_support = 1;
406 }
407 else
408 {
409 warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
410 warning ("Executable may not have been compiled debuggable with HP aCC.");
411 warning ("GDB will be unable to intercept exception events.");
412 eh_notify_hook_addr = 0;
413 hp_cxx_exception_support = 0;
414 return 0;
415 }
416
417 /* Next look for the notify callback routine in end.o */
418 /* This is always available in the SOM symbol dictionary if end.o is linked in */
419 msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
420 if (msym)
421 {
422 eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
423 hp_cxx_exception_support = 1;
424 }
425 else
426 {
427 warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
428 warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
429 warning ("GDB will be unable to intercept exception events.");
430 eh_notify_callback_addr = 0;
431 return 0;
432 }
433
434#ifndef GDB_TARGET_IS_HPPA_20W
435 /* Check whether the executable is dynamically linked or archive bound */
436 /* With an archive-bound executable we can use the raw addresses we find
437 for the callback function, etc. without modification. For an executable
438 with shared libraries, we have to do more work to find the plabel, which
439 can be the target of a call through $$dyncall from the aCC runtime support
440 library (libCsup) which is linked shared by default by aCC. */
441 /* This test below was copied from somsolib.c/somread.c. It may not be a very
442 reliable one to test that an executable is linked shared. pai/1997-07-18 */
443 shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
444 if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
445 {
446 /* The minsym we have has the local code address, but that's not the
447 plabel that can be used by an inter-load-module call. */
448 /* Find solib handle for main image (which has end.o), and use that
449 and the min sym as arguments to __d_shl_get() (which does the equivalent
450 of shl_findsym()) to find the plabel. */
451
452 args_for_find_stub args;
453 static char message[] = "Error while finding exception callback hook:\n";
454
455 args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
456 args.msym = msym;
457 args.return_val = 0;
458
459 recurse++;
460 catch_errors (cover_find_stub_with_shl_get, &args, message,
461 RETURN_MASK_ALL);
462 eh_notify_callback_addr = args.return_val;
463 recurse--;
464
f83f82bc 465 deprecated_exception_catchpoints_are_fragile = 1;
4c02c60c
AC
466
467 if (!eh_notify_callback_addr)
468 {
469 /* We can get here either if there is no plabel in the export list
470 for the main image, or if something strange happened (?) */
471 warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
472 warning ("GDB will not be able to intercept exception events.");
473 return 0;
474 }
475 }
476 else
f83f82bc 477 deprecated_exception_catchpoints_are_fragile = 0;
4c02c60c
AC
478#endif
479
480 /* Now, look for the breakpointable routine in end.o */
481 /* This should also be available in the SOM symbol dict. if end.o linked in */
482 msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
483 if (msym)
484 {
485 eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
486 hp_cxx_exception_support = 1;
487 }
488 else
489 {
490 warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
491 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
492 warning ("GDB will be unable to intercept exception events.");
493 eh_break_addr = 0;
494 return 0;
495 }
496
497 /* Next look for the catch enable flag provided in end.o */
498 sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
499 VAR_DOMAIN, 0, (struct symtab **) NULL);
500 if (sym) /* sometimes present in debug info */
501 {
502 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
503 hp_cxx_exception_support = 1;
504 }
505 else
506 /* otherwise look in SOM symbol dict. */
507 {
508 msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
509 if (msym)
510 {
511 eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
512 hp_cxx_exception_support = 1;
513 }
514 else
515 {
516 warning ("Unable to enable interception of exception catches.");
517 warning ("Executable may not have been compiled debuggable with HP aCC.");
518 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
519 return 0;
520 }
521 }
522
523 /* Next look for the catch enable flag provided end.o */
524 sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
525 VAR_DOMAIN, 0, (struct symtab **) NULL);
526 if (sym) /* sometimes present in debug info */
527 {
528 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
529 hp_cxx_exception_support = 1;
530 }
531 else
532 /* otherwise look in SOM symbol dict. */
533 {
534 msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
535 if (msym)
536 {
537 eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
538 hp_cxx_exception_support = 1;
539 }
540 else
541 {
542 warning ("Unable to enable interception of exception throws.");
543 warning ("Executable may not have been compiled debuggable with HP aCC.");
544 warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
545 return 0;
546 }
547 }
548
549 /* Set the flags */
550 hp_cxx_exception_support = 2; /* everything worked so far */
551 hp_cxx_exception_support_initialized = 1;
f83f82bc 552 deprecated_exception_support_initialized = 1;
4c02c60c
AC
553
554 return 1;
555}
556
557/* Target operation for enabling or disabling interception of
558 exception events.
559 KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
560 ENABLE is either 0 (disable) or 1 (enable).
561 Return value is NULL if no support found;
562 -1 if something went wrong,
563 or a pointer to a symtab/line struct if the breakpointable
564 address was found. */
565
566struct symtab_and_line *
567child_enable_exception_callback (enum exception_event_kind kind, int enable)
568{
569 char buf[4];
570
f83f82bc
AC
571 if (!deprecated_exception_support_initialized
572 || !hp_cxx_exception_support_initialized)
4c02c60c
AC
573 if (!initialize_hp_cxx_exception_support ())
574 return NULL;
575
576 switch (hp_cxx_exception_support)
577 {
578 case 0:
579 /* Assuming no HP support at all */
580 return NULL;
581 case 1:
582 /* HP support should be present, but something went wrong */
583 return (struct symtab_and_line *) -1; /* yuck! */
584 /* there may be other cases in the future */
585 }
586
587 /* Set the EH hook to point to the callback routine */
588 store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
589 /* pai: (temp) FIXME should there be a pack operation first? */
590 if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
591 {
592 warning ("Could not write to target memory for exception event callback.");
593 warning ("Interception of exception events may not work.");
594 return (struct symtab_and_line *) -1;
595 }
596 if (enable)
597 {
598 /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
599 if (PIDGET (inferior_ptid) > 0)
600 {
601 if (setup_d_pid_in_inferior ())
602 return (struct symtab_and_line *) -1;
603 }
604 else
605 {
606 warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
607 return (struct symtab_and_line *) -1;
608 }
609 }
610
611 switch (kind)
612 {
613 case EX_EVENT_THROW:
614 store_unsigned_integer (buf, 4, enable ? 1 : 0);
615 if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
616 {
617 warning ("Couldn't enable exception throw interception.");
618 return (struct symtab_and_line *) -1;
619 }
620 break;
621 case EX_EVENT_CATCH:
622 store_unsigned_integer (buf, 4, enable ? 1 : 0);
623 if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
624 {
625 warning ("Couldn't enable exception catch interception.");
626 return (struct symtab_and_line *) -1;
627 }
628 break;
629 default:
630 error ("Request to enable unknown or unsupported exception event.");
631 }
632
633 /* Copy break address into new sal struct, malloc'ing if needed. */
634 if (!break_callback_sal)
635 {
636 break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
637 }
638 init_sal (break_callback_sal);
639 break_callback_sal->symtab = NULL;
640 break_callback_sal->pc = eh_break_addr;
641 break_callback_sal->line = 0;
642 break_callback_sal->end = eh_break_addr;
643
644 return break_callback_sal;
645}
646
647/* Record some information about the current exception event */
648static struct exception_event_record current_ex_event;
649/* Convenience struct */
650static struct symtab_and_line null_symtab_and_line =
651{NULL, 0, 0, 0};
652
653/* Report current exception event. Returns a pointer to a record
654 that describes the kind of the event, where it was thrown from,
655 and where it will be caught. More information may be reported
656 in the future */
657struct exception_event_record *
658child_get_current_exception_event (void)
659{
660 CORE_ADDR event_kind;
661 CORE_ADDR throw_addr;
662 CORE_ADDR catch_addr;
663 struct frame_info *fi, *curr_frame;
664 int level = 1;
665
666 curr_frame = get_current_frame ();
667 if (!curr_frame)
668 return (struct exception_event_record *) NULL;
669
670 /* Go up one frame to __d_eh_notify_callback, because at the
671 point when this code is executed, there's garbage in the
672 arguments of __d_eh_break. */
673 fi = find_relative_frame (curr_frame, &level);
674 if (level != 0)
675 return (struct exception_event_record *) NULL;
676
677 select_frame (fi);
678
679 /* Read in the arguments */
680 /* __d_eh_notify_callback() is called with 3 arguments:
681 1. event kind catch or throw
682 2. the target address if known
683 3. a flag -- not sure what this is. pai/1997-07-17 */
684 event_kind = read_register (ARG0_REGNUM);
685 catch_addr = read_register (ARG1_REGNUM);
686
687 /* Now go down to a user frame */
688 /* For a throw, __d_eh_break is called by
689 __d_eh_notify_callback which is called by
690 __notify_throw which is called
691 from user code.
692 For a catch, __d_eh_break is called by
693 __d_eh_notify_callback which is called by
694 <stackwalking stuff> which is called by
695 __throw__<stuff> or __rethrow_<stuff> which is called
696 from user code. */
697 /* FIXME: Don't use such magic numbers; search for the frames */
698 level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
699 fi = find_relative_frame (curr_frame, &level);
700 if (level != 0)
701 return (struct exception_event_record *) NULL;
702
703 select_frame (fi);
704 throw_addr = get_frame_pc (fi);
705
706 /* Go back to original (top) frame */
707 select_frame (curr_frame);
708
709 current_ex_event.kind = (enum exception_event_kind) event_kind;
710 current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
711 current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
712
713 return &current_ex_event;
714}
715
7d773d96
JB
716static void
717hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
718{
f561f026 719 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, hppa_hpux_pc_in_sigtramp);
7d773d96 720}
60e1ff27 721
273f8429
JB
722static void
723hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
724{
fdd72f95
RC
725 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
726
727 tdep->is_elf = 0;
7d773d96 728 hppa_hpux_init_abi (info, gdbarch);
273f8429
JB
729}
730
731static void
732hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
733{
fdd72f95
RC
734 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
735
736 tdep->is_elf = 1;
7d773d96 737 hppa_hpux_init_abi (info, gdbarch);
273f8429
JB
738}
739
740void
741_initialize_hppa_hpux_tdep (void)
742{
05816f70 743 gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
273f8429 744 hppa_hpux_som_init_abi);
51db5742 745 gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
273f8429
JB
746 hppa_hpux_elf_init_abi);
747}
This page took 0.171515 seconds and 4 git commands to generate.