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