OLD | NEW |
1 /* Frame unwinder for frames using the libunwind library. | 1 /* Frame unwinder for ia64 frames using the libunwind library. |
2 | 2 |
3 Copyright (C) 2003-2004, 2006-2012 Free Software Foundation, Inc. | 3 Copyright (C) 2003-2004, 2006-2012 Free Software Foundation, Inc. |
4 | 4 |
5 Written by Jeff Johnston, contributed by Red Hat Inc. | 5 Written by Jeff Johnston, contributed by Red Hat Inc. |
6 | 6 |
7 This file is part of GDB. | 7 This file is part of GDB. |
8 | 8 |
9 This program is free software; you can redistribute it and/or modify | 9 This program is free software; you can redistribute it and/or modify |
10 it under the terms of the GNU General Public License as published by | 10 it under the terms of the GNU General Public License as published by |
11 the Free Software Foundation; either version 3 of the License, or | 11 the Free Software Foundation; either version 3 of the License, or |
(...skipping 17 matching lines...) Expand all Loading... |
29 #include "gdbtypes.h" | 29 #include "gdbtypes.h" |
30 #include "symtab.h" | 30 #include "symtab.h" |
31 #include "objfiles.h" | 31 #include "objfiles.h" |
32 #include "regcache.h" | 32 #include "regcache.h" |
33 | 33 |
34 #include <dlfcn.h> | 34 #include <dlfcn.h> |
35 | 35 |
36 #include "gdb_assert.h" | 36 #include "gdb_assert.h" |
37 #include "gdb_string.h" | 37 #include "gdb_string.h" |
38 | 38 |
39 #include "libunwind-frame.h" | 39 #include "ia64-libunwind-tdep.h" |
40 | 40 |
41 #include "complaints.h" | 41 #include "complaints.h" |
42 | 42 |
| 43 /* IA-64 is the only target that currently uses ia64-libunwind-tdep. |
| 44 Note how UNW_TARGET, UNW_OBJ, etc. are compile time constants below. |
| 45 Those come from libunwind's headers, and are target dependent. |
| 46 Also, some of libunwind's typedefs are target dependent, as e.g., |
| 47 unw_word_t. If some other target wants to use this, we will need |
| 48 to do some abstracting in order to make it possible to select which |
| 49 libunwind we're talking to at runtime (and have one per arch). */ |
| 50 |
43 /* The following two macros are normally defined in <endian.h>. | 51 /* The following two macros are normally defined in <endian.h>. |
44 But systems such as ia64-hpux do not provide such header, so | 52 But systems such as ia64-hpux do not provide such header, so |
45 we just define them here if not already defined. */ | 53 we just define them here if not already defined. */ |
46 #ifndef __LITTLE_ENDIAN | 54 #ifndef __LITTLE_ENDIAN |
47 #define __LITTLE_ENDIAN 1234 | 55 #define __LITTLE_ENDIAN 1234 |
48 #endif | 56 #endif |
49 #ifndef __BIG_ENDIAN | 57 #ifndef __BIG_ENDIAN |
50 #define __BIG_ENDIAN 4321 | 58 #define __BIG_ENDIAN 4321 |
51 #endif | 59 #endif |
52 | 60 |
(...skipping 27 matching lines...) Expand all Loading... |
80 | 88 |
81 /* We need to qualify the function names with a platform-specific prefix | 89 /* We need to qualify the function names with a platform-specific prefix |
82 to match the names used by the libunwind library. The UNW_OBJ macro is | 90 to match the names used by the libunwind library. The UNW_OBJ macro is |
83 provided by the libunwind.h header file. */ | 91 provided by the libunwind.h header file. */ |
84 #define STRINGIFY2(name) #name | 92 #define STRINGIFY2(name) #name |
85 #define STRINGIFY(name) STRINGIFY2(name) | 93 #define STRINGIFY(name) STRINGIFY2(name) |
86 | 94 |
87 #ifndef LIBUNWIND_SO | 95 #ifndef LIBUNWIND_SO |
88 /* Use the stable ABI major version number. `libunwind-ia64.so' is a link time | 96 /* Use the stable ABI major version number. `libunwind-ia64.so' is a link time |
89 only library, not a runtime one. */ | 97 only library, not a runtime one. */ |
90 #define LIBUNWIND_SO "libunwind-" STRINGIFY(UNW_TARGET) ".so.7" | 98 #define LIBUNWIND_SO "libunwind-" STRINGIFY(UNW_TARGET) ".so.8" |
| 99 |
| 100 /* Provide also compatibility with older .so. The two APIs are compatible, .8 |
| 101 is only extended a bit, GDB does not use the extended API at all. */ |
| 102 #define LIBUNWIND_SO_7 "libunwind-" STRINGIFY(UNW_TARGET) ".so.7" |
91 #endif | 103 #endif |
92 | 104 |
93 static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg)); | 105 static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg)); |
94 static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg)); | 106 static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg)); |
95 static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc)); | 107 static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc)); |
96 static char *is_signal_frame_name = STRINGIFY(UNW_OBJ(is_signal_frame)); | 108 static char *is_signal_frame_name = STRINGIFY(UNW_OBJ(is_signal_frame)); |
97 static char *step_name = STRINGIFY(UNW_OBJ(step)); | 109 static char *step_name = STRINGIFY(UNW_OBJ(step)); |
98 static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote)); | 110 static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote)); |
99 static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space)); | 111 static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space)); |
100 static char *destroy_addr_space_name = STRINGIFY(UNW_OBJ(destroy_addr_space)); | 112 static char *destroy_addr_space_name = STRINGIFY(UNW_OBJ(destroy_addr_space)); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 if (cache->as) | 238 if (cache->as) |
227 unw_destroy_addr_space_p (cache->as); | 239 unw_destroy_addr_space_p (cache->as); |
228 } | 240 } |
229 | 241 |
230 unw_word_t | 242 unw_word_t |
231 libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg) | 243 libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg) |
232 { | 244 { |
233 return unw_find_dyn_list_p (as, di, arg); | 245 return unw_find_dyn_list_p (as, di, arg); |
234 } | 246 } |
235 | 247 |
236 static const struct frame_unwind libunwind_frame_unwind = | |
237 { | |
238 NORMAL_FRAME, | |
239 default_frame_unwind_stop_reason, | |
240 libunwind_frame_this_id, | |
241 libunwind_frame_prev_register, | |
242 NULL, | |
243 libunwind_frame_sniffer, | |
244 libunwind_frame_dealloc_cache, | |
245 }; | |
246 | |
247 /* Verify if there is sufficient libunwind information for the frame to use | 248 /* Verify if there is sufficient libunwind information for the frame to use |
248 libunwind frame unwinding. */ | 249 libunwind frame unwinding. */ |
249 int | 250 int |
250 libunwind_frame_sniffer (const struct frame_unwind *self, | 251 libunwind_frame_sniffer (const struct frame_unwind *self, |
251 struct frame_info *this_frame, void **this_cache) | 252 struct frame_info *this_frame, void **this_cache) |
252 { | 253 { |
253 unw_cursor_t cursor; | 254 unw_cursor_t cursor; |
254 unw_accessors_t *acc; | 255 unw_accessors_t *acc; |
255 unw_addr_space_t as; | 256 unw_addr_space_t as; |
256 struct libunwind_descr *descr; | 257 struct libunwind_descr *descr; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 return frame_unwind_got_constant (this_frame, regnum, 0); | 370 return frame_unwind_got_constant (this_frame, regnum, 0); |
370 val = frame_unwind_got_constant (this_frame, regnum, intval); | 371 val = frame_unwind_got_constant (this_frame, regnum, intval); |
371 } | 372 } |
372 break; | 373 break; |
373 } | 374 } |
374 } | 375 } |
375 | 376 |
376 return val; | 377 return val; |
377 } | 378 } |
378 | 379 |
379 CORE_ADDR | |
380 libunwind_frame_base_address (struct frame_info *this_frame, void **this_cache) | |
381 { | |
382 struct libunwind_frame_cache *cache = | |
383 libunwind_frame_cache (this_frame, this_cache); | |
384 | |
385 if (cache == NULL) | |
386 return (CORE_ADDR)NULL; | |
387 return cache->base; | |
388 } | |
389 | |
390 /* The following is a glue routine to call the libunwind unwind table | 380 /* The following is a glue routine to call the libunwind unwind table |
391 search function to get unwind information for a specified ip address. */ | 381 search function to get unwind information for a specified ip address. */ |
392 int | 382 int |
393 libunwind_search_unwind_table (void *as, long ip, void *di, | 383 libunwind_search_unwind_table (void *as, long ip, void *di, |
394 void *pi, int need_unwind_info, void *args) | 384 void *pi, int need_unwind_info, void *args) |
395 { | 385 { |
396 return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip, | 386 return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip, |
397 di, pi, need_unwind_info, args); | 387 di, pi, need_unwind_info, args); |
398 } | 388 } |
399 | 389 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 if (buf) | 488 if (buf) |
499 memcpy (buf, ptr, register_size (gdbarch, regnum)); | 489 memcpy (buf, ptr, register_size (gdbarch, regnum)); |
500 | 490 |
501 return 0; | 491 return 0; |
502 } | 492 } |
503 | 493 |
504 static int | 494 static int |
505 libunwind_load (void) | 495 libunwind_load (void) |
506 { | 496 { |
507 void *handle; | 497 void *handle; |
| 498 char *so_error = NULL; |
508 | 499 |
509 handle = dlopen (LIBUNWIND_SO, RTLD_NOW); | 500 handle = dlopen (LIBUNWIND_SO, RTLD_NOW); |
510 if (handle == NULL) | 501 if (handle == NULL) |
| 502 { |
| 503 so_error = xstrdup (dlerror ()); |
| 504 #ifdef LIBUNWIND_SO_7 |
| 505 handle = dlopen (LIBUNWIND_SO_7, RTLD_NOW); |
| 506 #endif /* LIBUNWIND_SO_7 */ |
| 507 } |
| 508 if (handle == NULL) |
| 509 { |
| 510 fprintf_unfiltered (gdb_stderr, _("[GDB failed to load %s: %s]\n"), |
| 511 LIBUNWIND_SO, so_error); |
| 512 #ifdef LIBUNWIND_SO_7 |
| 513 fprintf_unfiltered (gdb_stderr, _("[GDB failed to load %s: %s]\n"), |
| 514 LIBUNWIND_SO_7, dlerror ()); |
| 515 #endif /* LIBUNWIND_SO_7 */ |
| 516 } |
| 517 xfree (so_error); |
| 518 if (handle == NULL) |
511 return 0; | 519 return 0; |
512 | 520 |
513 /* Initialize pointers to the dynamic library functions we will use. */ | 521 /* Initialize pointers to the dynamic library functions we will use. */ |
514 | 522 |
515 unw_get_reg_p = dlsym (handle, get_reg_name); | 523 unw_get_reg_p = dlsym (handle, get_reg_name); |
516 if (unw_get_reg_p == NULL) | 524 if (unw_get_reg_p == NULL) |
517 return 0; | 525 return 0; |
518 | 526 |
519 unw_get_fpreg_p = dlsym (handle, get_fpreg_name); | 527 unw_get_fpreg_p = dlsym (handle, get_fpreg_name); |
520 if (unw_get_fpreg_p == NULL) | 528 if (unw_get_fpreg_p == NULL) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 void _initialize_libunwind_frame (void); | 573 void _initialize_libunwind_frame (void); |
566 | 574 |
567 void | 575 void |
568 _initialize_libunwind_frame (void) | 576 _initialize_libunwind_frame (void) |
569 { | 577 { |
570 libunwind_descr_handle | 578 libunwind_descr_handle |
571 = gdbarch_data_register_post_init (libunwind_descr_init); | 579 = gdbarch_data_register_post_init (libunwind_descr_init); |
572 | 580 |
573 libunwind_initialized = libunwind_load (); | 581 libunwind_initialized = libunwind_load (); |
574 } | 582 } |
OLD | NEW |