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