]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ia64-libunwind-tdep.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / ia64-libunwind-tdep.c
CommitLineData
05e7c244 1/* Frame unwinder for ia64 frames using the libunwind library.
0e5d83e3 2
1d506c26 3 Copyright (C) 2003-2024 Free Software Foundation, Inc.
0e5d83e3
JJ
4
5 Written by Jeff Johnston, contributed by Red Hat Inc.
6
7 This file is part of GDB.
8
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
0e5d83e3
JJ
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
0e5d83e3 21
0e5d83e3
JJ
22
23#include "inferior.h"
24#include "frame.h"
25#include "frame-base.h"
26#include "frame-unwind.h"
27#include "gdbcore.h"
28#include "gdbtypes.h"
29#include "symtab.h"
30#include "objfiles.h"
31#include "regcache.h"
32
33#include <dlfcn.h>
34
05e7c244 35#include "ia64-libunwind-tdep.h"
0e5d83e3 36
268a13a5 37#include "gdbsupport/preprocessor.h"
0e5d83e3 38
05e7c244
JK
39/* IA-64 is the only target that currently uses ia64-libunwind-tdep.
40 Note how UNW_TARGET, UNW_OBJ, etc. are compile time constants below.
b54a8fd7
PA
41 Those come from libunwind's headers, and are target dependent.
42 Also, some of libunwind's typedefs are target dependent, as e.g.,
43 unw_word_t. If some other target wants to use this, we will need
44 to do some abstracting in order to make it possible to select which
45 libunwind we're talking to at runtime (and have one per arch). */
46
3e5e6e2a
JB
47/* The following two macros are normally defined in <endian.h>.
48 But systems such as ia64-hpux do not provide such header, so
49 we just define them here if not already defined. */
50#ifndef __LITTLE_ENDIAN
51#define __LITTLE_ENDIAN 1234
52#endif
53#ifndef __BIG_ENDIAN
54#define __BIG_ENDIAN 4321
55#endif
56
0e5d83e3 57static int libunwind_initialized;
cb275538 58static const registry<gdbarch>::key<libunwind_descr> libunwind_descr_handle;
0e5d83e3 59
0e5d83e3 60/* Required function pointers from libunwind. */
bfb0d950
AS
61typedef int (unw_get_reg_p_ftype) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
62static unw_get_reg_p_ftype *unw_get_reg_p;
63typedef int (unw_get_fpreg_p_ftype) (unw_cursor_t *, unw_regnum_t,
64 unw_fpreg_t *);
65static unw_get_fpreg_p_ftype *unw_get_fpreg_p;
66typedef int (unw_get_saveloc_p_ftype) (unw_cursor_t *, unw_regnum_t,
67 unw_save_loc_t *);
68static unw_get_saveloc_p_ftype *unw_get_saveloc_p;
69typedef int (unw_is_signal_frame_p_ftype) (unw_cursor_t *);
70static unw_is_signal_frame_p_ftype *unw_is_signal_frame_p;
71typedef int (unw_step_p_ftype) (unw_cursor_t *);
72static unw_step_p_ftype *unw_step_p;
73typedef int (unw_init_remote_p_ftype) (unw_cursor_t *, unw_addr_space_t,
74 void *);
75static unw_init_remote_p_ftype *unw_init_remote_p;
76typedef unw_addr_space_t (unw_create_addr_space_p_ftype) (unw_accessors_t *,
77 int);
78static unw_create_addr_space_p_ftype *unw_create_addr_space_p;
79typedef void (unw_destroy_addr_space_p_ftype) (unw_addr_space_t);
80static unw_destroy_addr_space_p_ftype *unw_destroy_addr_space_p;
81typedef int (unw_search_unwind_table_p_ftype) (unw_addr_space_t, unw_word_t,
82 unw_dyn_info_t *,
83 unw_proc_info_t *, int, void *);
84static unw_search_unwind_table_p_ftype *unw_search_unwind_table_p;
85typedef unw_word_t (unw_find_dyn_list_p_ftype) (unw_addr_space_t,
86 unw_dyn_info_t *, void *);
87static unw_find_dyn_list_p_ftype *unw_find_dyn_list_p;
0e5d83e3
JJ
88
89
90struct libunwind_frame_cache
91{
92 CORE_ADDR base;
93 CORE_ADDR func_addr;
94 unw_cursor_t cursor;
272dfcfd 95 unw_addr_space_t as;
0e5d83e3
JJ
96};
97
15c1e57f
JB
98/* We need to qualify the function names with a platform-specific prefix
99 to match the names used by the libunwind library. The UNW_OBJ macro is
100 provided by the libunwind.h header file. */
0e5d83e3 101
38e400fa 102#ifndef LIBUNWIND_SO
70f575cc
JK
103/* Use the stable ABI major version number. `libunwind-ia64.so' is a link time
104 only library, not a runtime one. */
75528772
JK
105#define LIBUNWIND_SO "libunwind-" STRINGIFY(UNW_TARGET) ".so.8"
106
107/* Provide also compatibility with older .so. The two APIs are compatible, .8
108 is only extended a bit, GDB does not use the extended API at all. */
109#define LIBUNWIND_SO_7 "libunwind-" STRINGIFY(UNW_TARGET) ".so.7"
38e400fa
JJ
110#endif
111
e83f4d97
SM
112static const char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
113static const char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
114static const char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc));
115static const char *is_signal_frame_name = STRINGIFY(UNW_OBJ(is_signal_frame));
116static const char *step_name = STRINGIFY(UNW_OBJ(step));
117static const char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
118static const char *create_addr_space_name
119 = STRINGIFY(UNW_OBJ(create_addr_space));
120static const char *destroy_addr_space_name
121 = STRINGIFY(UNW_OBJ(destroy_addr_space));
122static const char *search_unwind_table_name
3e43a32a 123 = STRINGIFY(UNW_OBJ(search_unwind_table));
e83f4d97 124static const char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
0e5d83e3
JJ
125
126static struct libunwind_descr *
127libunwind_descr (struct gdbarch *gdbarch)
128{
cb275538
TT
129 struct libunwind_descr *result = libunwind_descr_handle.get (gdbarch);
130 if (result == nullptr)
131 result = libunwind_descr_handle.emplace (gdbarch);
132 return result;
0e5d83e3
JJ
133}
134
135void
3e43a32a
MS
136libunwind_frame_set_descr (struct gdbarch *gdbarch,
137 struct libunwind_descr *descr)
0e5d83e3
JJ
138{
139 struct libunwind_descr *arch_descr;
140
141 gdb_assert (gdbarch != NULL);
142
cb275538 143 arch_descr = libunwind_descr (gdbarch);
3bc98c0c 144 gdb_assert (arch_descr != NULL);
0e5d83e3
JJ
145
146 /* Copy new descriptor info into arch descriptor. */
147 arch_descr->gdb2uw = descr->gdb2uw;
148 arch_descr->uw2gdb = descr->uw2gdb;
149 arch_descr->is_fpreg = descr->is_fpreg;
150 arch_descr->accessors = descr->accessors;
c5a27d9c 151 arch_descr->special_accessors = descr->special_accessors;
0e5d83e3
JJ
152}
153
154static struct libunwind_frame_cache *
8480a37e 155libunwind_frame_cache (const frame_info_ptr &this_frame, void **this_cache)
0e5d83e3
JJ
156{
157 unw_accessors_t *acc;
158 unw_addr_space_t as;
159 unw_word_t fp;
160 unw_regnum_t uw_sp_regnum;
161 struct libunwind_frame_cache *cache;
162 struct libunwind_descr *descr;
15c1e57f 163 struct gdbarch *gdbarch = get_frame_arch (this_frame);
b4792091 164 int ret;
0e5d83e3
JJ
165
166 if (*this_cache)
bfb0d950 167 return (struct libunwind_frame_cache *) *this_cache;
0e5d83e3
JJ
168
169 /* Allocate a new cache. */
170 cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
171
15c1e57f 172 cache->func_addr = get_frame_func (this_frame);
1b89e62f
JB
173 if (cache->func_addr == 0)
174 /* This can happen when the frame corresponds to a function for which
175 there is no debugging information nor any entry in the symbol table.
176 This is probably a static function for which an entry in the symbol
177 table was not created when the objfile got linked (observed in
178 libpthread.so on ia64-hpux).
179
180 The best we can do, in that case, is use the frame PC as the function
181 address. We don't need to give up since we still have the unwind
182 record to help us perform the unwinding. There is also another
85102364 183 compelling to continue, because abandoning now means stopping
1b89e62f
JB
184 the backtrace, which can never be helpful for the user. */
185 cache->func_addr = get_frame_pc (this_frame);
0e5d83e3 186
15c1e57f
JB
187 /* Get a libunwind cursor to the previous frame.
188
189 We do this by initializing a cursor. Libunwind treats a new cursor
190 as the top of stack and will get the current register set via the
191 libunwind register accessor. Now, we provide the platform-specific
192 accessors and we set up the register accessor to use the frame
193 register unwinding interfaces so that we properly get the registers
194 for the current frame rather than the top. We then use the unw_step
195 function to move the libunwind cursor back one frame. We can later
196 use this cursor to find previous registers via the unw_get_reg
197 interface which will invoke libunwind's special logic. */
8cff2ae6 198 descr = libunwind_descr (gdbarch);
bfb0d950 199 acc = (unw_accessors_t *) descr->accessors;
0e5d83e3 200 as = unw_create_addr_space_p (acc,
8cff2ae6 201 gdbarch_byte_order (gdbarch)
4c6b5505 202 == BFD_ENDIAN_BIG
0e5d83e3
JJ
203 ? __BIG_ENDIAN
204 : __LITTLE_ENDIAN);
205
15c1e57f 206 unw_init_remote_p (&cache->cursor, as, this_frame);
c5a27d9c 207 if (unw_step_p (&cache->cursor) < 0)
f43ae3f1
AS
208 {
209 unw_destroy_addr_space_p (as);
210 return NULL;
211 }
0e5d83e3
JJ
212
213 /* To get base address, get sp from previous frame. */
8cff2ae6 214 uw_sp_regnum = descr->gdb2uw (gdbarch_sp_regnum (gdbarch));
0e5d83e3
JJ
215 ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
216 if (ret < 0)
f43ae3f1
AS
217 {
218 unw_destroy_addr_space_p (as);
219 error (_("Can't get libunwind sp register."));
220 }
0e5d83e3
JJ
221
222 cache->base = (CORE_ADDR)fp;
272dfcfd 223 cache->as = as;
0e5d83e3
JJ
224
225 *this_cache = cache;
226 return cache;
227}
228
272dfcfd 229void
bd2b40ac 230libunwind_frame_dealloc_cache (frame_info_ptr self, void *this_cache)
272dfcfd 231{
bfb0d950
AS
232 struct libunwind_frame_cache *cache
233 = (struct libunwind_frame_cache *) this_cache;
e0881a8e 234
272dfcfd
AS
235 if (cache->as)
236 unw_destroy_addr_space_p (cache->as);
237}
238
503ff15d
KB
239unw_word_t
240libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
0e5d83e3 241{
503ff15d 242 return unw_find_dyn_list_p (as, di, arg);
0e5d83e3
JJ
243}
244
0e5d83e3
JJ
245/* Verify if there is sufficient libunwind information for the frame to use
246 libunwind frame unwinding. */
15c1e57f
JB
247int
248libunwind_frame_sniffer (const struct frame_unwind *self,
8480a37e 249 const frame_info_ptr &this_frame, void **this_cache)
0e5d83e3
JJ
250{
251 unw_cursor_t cursor;
252 unw_accessors_t *acc;
253 unw_addr_space_t as;
254 struct libunwind_descr *descr;
15c1e57f 255 struct gdbarch *gdbarch = get_frame_arch (this_frame);
b4792091 256 int ret;
0e5d83e3 257
15c1e57f
JB
258 /* To test for libunwind unwind support, initialize a cursor to
259 the current frame and try to back up. We use this same method
260 when setting up the frame cache (see libunwind_frame_cache()).
261 If libunwind returns success for this operation, it means that
262 it has found sufficient libunwind unwinding information to do so. */
0e5d83e3 263
8cff2ae6 264 descr = libunwind_descr (gdbarch);
bfb0d950 265 acc = (unw_accessors_t *) descr->accessors;
0e5d83e3 266 as = unw_create_addr_space_p (acc,
8cff2ae6 267 gdbarch_byte_order (gdbarch)
4c6b5505 268 == BFD_ENDIAN_BIG
0e5d83e3
JJ
269 ? __BIG_ENDIAN
270 : __LITTLE_ENDIAN);
271
15c1e57f 272 ret = unw_init_remote_p (&cursor, as, this_frame);
0e5d83e3 273
c5a27d9c 274 if (ret < 0)
f43ae3f1
AS
275 {
276 unw_destroy_addr_space_p (as);
15c1e57f 277 return 0;
f43ae3f1 278 }
c5a27d9c
JJ
279
280
281 /* Check to see if we have libunwind info by checking if we are in a
282 signal frame. If it doesn't return an error, we have libunwind info
283 and can use libunwind. */
284 ret = unw_is_signal_frame_p (&cursor);
f43ae3f1 285 unw_destroy_addr_space_p (as);
0e5d83e3
JJ
286
287 if (ret < 0)
15c1e57f 288 return 0;
0e5d83e3 289
15c1e57f 290 return 1;
0e5d83e3
JJ
291}
292
293void
8480a37e 294libunwind_frame_this_id (const frame_info_ptr &this_frame, void **this_cache,
dda83cd7 295 struct frame_id *this_id)
0e5d83e3
JJ
296{
297 struct libunwind_frame_cache *cache =
15c1e57f 298 libunwind_frame_cache (this_frame, this_cache);
0e5d83e3 299
c5a27d9c
JJ
300 if (cache != NULL)
301 (*this_id) = frame_id_build (cache->base, cache->func_addr);
0e5d83e3
JJ
302}
303
15c1e57f 304struct value *
8480a37e 305libunwind_frame_prev_register (const frame_info_ptr &this_frame,
dda83cd7 306 void **this_cache, int regnum)
0e5d83e3
JJ
307{
308 struct libunwind_frame_cache *cache =
15c1e57f 309 libunwind_frame_cache (this_frame, this_cache);
0e5d83e3 310
0e5d83e3 311 unw_save_loc_t sl;
b4792091 312 int ret;
0e5d83e3
JJ
313 unw_word_t intval;
314 unw_fpreg_t fpval;
315 unw_regnum_t uw_regnum;
316 struct libunwind_descr *descr;
15c1e57f 317 struct value *val = NULL;
0e5d83e3 318
c5a27d9c 319 if (cache == NULL)
15c1e57f 320 return frame_unwind_got_constant (this_frame, regnum, 0);
c5a27d9c 321
0e5d83e3 322 /* Convert from gdb register number to libunwind register number. */
15c1e57f 323 descr = libunwind_descr (get_frame_arch (this_frame));
0e5d83e3
JJ
324 uw_regnum = descr->gdb2uw (regnum);
325
326 gdb_assert (regnum >= 0);
327
9dccd06e 328 if (!target_has_registers ())
8a3fe4f8 329 error (_("No registers."));
0e5d83e3 330
0e5d83e3 331 if (uw_regnum < 0)
15c1e57f 332 return frame_unwind_got_constant (this_frame, regnum, 0);
0e5d83e3
JJ
333
334 if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
15c1e57f 335 return frame_unwind_got_constant (this_frame, regnum, 0);
0e5d83e3
JJ
336
337 switch (sl.type)
338 {
0e5d83e3 339 case UNW_SLT_MEMORY:
15c1e57f 340 val = frame_unwind_got_memory (this_frame, regnum, sl.u.addr);
0e5d83e3
JJ
341 break;
342
343 case UNW_SLT_REG:
15c1e57f 344 val = frame_unwind_got_register (this_frame, regnum,
dda83cd7 345 descr->uw2gdb (sl.u.regnum));
0e5d83e3 346 break;
15c1e57f
JB
347 case UNW_SLT_NONE:
348 {
dda83cd7
SM
349 /* The register is not stored at a specific memory address nor
350 inside another register. So use libunwind to fetch the register
351 value for us, and create a constant value with the result. */
352 if (descr->is_fpreg (uw_regnum))
353 {
354 ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
355 if (ret < 0)
356 return frame_unwind_got_constant (this_frame, regnum, 0);
357 val = frame_unwind_got_bytes (this_frame, regnum,
358 (gdb_byte *) &fpval);
359 }
360 else
361 {
362 ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
363 if (ret < 0)
364 return frame_unwind_got_constant (this_frame, regnum, 0);
365 val = frame_unwind_got_constant (this_frame, regnum, intval);
366 }
367 break;
15c1e57f 368 }
0e5d83e3 369 }
15c1e57f
JB
370
371 return val;
0e5d83e3
JJ
372}
373
0e5d83e3
JJ
374/* The following is a glue routine to call the libunwind unwind table
375 search function to get unwind information for a specified ip address. */
376int
377libunwind_search_unwind_table (void *as, long ip, void *di,
378 void *pi, int need_unwind_info, void *args)
379{
bfb0d950
AS
380 return unw_search_unwind_table_p (*(unw_addr_space_t *) as, (unw_word_t) ip,
381 (unw_dyn_info_t *) di,
382 (unw_proc_info_t *) pi, need_unwind_info,
383 args);
0e5d83e3
JJ
384}
385
c5a27d9c 386/* Verify if we are in a sigtramp frame and we can use libunwind to unwind. */
15c1e57f
JB
387int
388libunwind_sigtramp_frame_sniffer (const struct frame_unwind *self,
8480a37e 389 const frame_info_ptr &this_frame,
dda83cd7 390 void **this_cache)
c5a27d9c
JJ
391{
392 unw_cursor_t cursor;
393 unw_accessors_t *acc;
394 unw_addr_space_t as;
395 struct libunwind_descr *descr;
15c1e57f 396 struct gdbarch *gdbarch = get_frame_arch (this_frame);
b4792091 397 int ret;
c5a27d9c
JJ
398
399 /* To test for libunwind unwind support, initialize a cursor to the
400 current frame and try to back up. We use this same method when
401 setting up the frame cache (see libunwind_frame_cache()). If
402 libunwind returns success for this operation, it means that it
403 has found sufficient libunwind unwinding information to do
404 so. */
405
8cff2ae6 406 descr = libunwind_descr (gdbarch);
bfb0d950 407 acc = (unw_accessors_t *) descr->accessors;
c5a27d9c 408 as = unw_create_addr_space_p (acc,
8cff2ae6 409 gdbarch_byte_order (gdbarch)
4c6b5505 410 == BFD_ENDIAN_BIG
c5a27d9c
JJ
411 ? __BIG_ENDIAN
412 : __LITTLE_ENDIAN);
413
15c1e57f 414 ret = unw_init_remote_p (&cursor, as, this_frame);
c5a27d9c
JJ
415
416 if (ret < 0)
f43ae3f1
AS
417 {
418 unw_destroy_addr_space_p (as);
15c1e57f 419 return 0;
f43ae3f1 420 }
c5a27d9c
JJ
421
422 /* Check to see if we are in a signal frame. */
423 ret = unw_is_signal_frame_p (&cursor);
f43ae3f1 424 unw_destroy_addr_space_p (as);
c5a27d9c 425 if (ret > 0)
15c1e57f 426 return 1;
c5a27d9c 427
15c1e57f 428 return 0;
c5a27d9c
JJ
429}
430
431/* The following routine is for accessing special registers of the top frame.
432 A special set of accessors must be given that work without frame info.
433 This is used by ia64 to access the rse registers r32-r127. While they
434 are usually located at BOF, this is not always true and only the libunwind
435 info can decipher where they actually are. */
436int
933522d1 437libunwind_get_reg_special (struct gdbarch *gdbarch, readable_regcache *regcache,
45ecac4b 438 int regnum, void *buf)
c5a27d9c
JJ
439{
440 unw_cursor_t cursor;
441 unw_accessors_t *acc;
442 unw_addr_space_t as;
443 struct libunwind_descr *descr;
444 int ret;
445 unw_regnum_t uw_regnum;
446 unw_word_t intval;
447 unw_fpreg_t fpval;
448 void *ptr;
449
450
451 descr = libunwind_descr (gdbarch);
bfb0d950 452 acc = (unw_accessors_t *) descr->special_accessors;
c5a27d9c 453 as = unw_create_addr_space_p (acc,
8cff2ae6 454 gdbarch_byte_order (gdbarch)
4c6b5505 455 == BFD_ENDIAN_BIG
c5a27d9c
JJ
456 ? __BIG_ENDIAN
457 : __LITTLE_ENDIAN);
458
45ecac4b 459 ret = unw_init_remote_p (&cursor, as, regcache);
c5a27d9c 460 if (ret < 0)
f43ae3f1
AS
461 {
462 unw_destroy_addr_space_p (as);
463 return -1;
464 }
c5a27d9c
JJ
465
466 uw_regnum = descr->gdb2uw (regnum);
467
468 if (descr->is_fpreg (uw_regnum))
469 {
470 ret = unw_get_fpreg_p (&cursor, uw_regnum, &fpval);
471 ptr = &fpval;
472 }
473 else
474 {
475 ret = unw_get_reg_p (&cursor, uw_regnum, &intval);
476 ptr = &intval;
477 }
478
f43ae3f1
AS
479 unw_destroy_addr_space_p (as);
480
c5a27d9c
JJ
481 if (ret < 0)
482 return -1;
483
484 if (buf)
8cff2ae6 485 memcpy (buf, ptr, register_size (gdbarch, regnum));
c5a27d9c
JJ
486
487 return 0;
488}
489
0e5d83e3
JJ
490static int
491libunwind_load (void)
492{
493 void *handle;
75528772 494 char *so_error = NULL;
0e5d83e3
JJ
495
496 handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
75528772
JK
497 if (handle == NULL)
498 {
499 so_error = xstrdup (dlerror ());
500#ifdef LIBUNWIND_SO_7
501 handle = dlopen (LIBUNWIND_SO_7, RTLD_NOW);
502#endif /* LIBUNWIND_SO_7 */
503 }
0e5d83e3 504 if (handle == NULL)
47c1316c 505 {
6cb06a8c
TT
506 gdb_printf (gdb_stderr, _("[GDB failed to load %s: %s]\n"),
507 LIBUNWIND_SO, so_error);
75528772 508#ifdef LIBUNWIND_SO_7
6cb06a8c
TT
509 gdb_printf (gdb_stderr, _("[GDB failed to load %s: %s]\n"),
510 LIBUNWIND_SO_7, dlerror ());
75528772 511#endif /* LIBUNWIND_SO_7 */
47c1316c 512 }
75528772
JK
513 xfree (so_error);
514 if (handle == NULL)
515 return 0;
0e5d83e3
JJ
516
517 /* Initialize pointers to the dynamic library functions we will use. */
518
bfb0d950 519 unw_get_reg_p = (unw_get_reg_p_ftype *) dlsym (handle, get_reg_name);
0e5d83e3
JJ
520 if (unw_get_reg_p == NULL)
521 return 0;
522
bfb0d950 523 unw_get_fpreg_p = (unw_get_fpreg_p_ftype *) dlsym (handle, get_fpreg_name);
0e5d83e3
JJ
524 if (unw_get_fpreg_p == NULL)
525 return 0;
526
bfb0d950
AS
527 unw_get_saveloc_p
528 = (unw_get_saveloc_p_ftype *) dlsym (handle, get_saveloc_name);
0e5d83e3
JJ
529 if (unw_get_saveloc_p == NULL)
530 return 0;
531
bfb0d950
AS
532 unw_is_signal_frame_p
533 = (unw_is_signal_frame_p_ftype *) dlsym (handle, is_signal_frame_name);
c5a27d9c
JJ
534 if (unw_is_signal_frame_p == NULL)
535 return 0;
536
bfb0d950 537 unw_step_p = (unw_step_p_ftype *) dlsym (handle, step_name);
0e5d83e3
JJ
538 if (unw_step_p == NULL)
539 return 0;
540
bfb0d950
AS
541 unw_init_remote_p
542 = (unw_init_remote_p_ftype *) dlsym (handle, init_remote_name);
0e5d83e3
JJ
543 if (unw_init_remote_p == NULL)
544 return 0;
545
bfb0d950
AS
546 unw_create_addr_space_p
547 = (unw_create_addr_space_p_ftype *) dlsym (handle, create_addr_space_name);
0e5d83e3
JJ
548 if (unw_create_addr_space_p == NULL)
549 return 0;
550
bfb0d950
AS
551 unw_destroy_addr_space_p
552 = (unw_destroy_addr_space_p_ftype *) dlsym (handle,
553 destroy_addr_space_name);
f43ae3f1
AS
554 if (unw_destroy_addr_space_p == NULL)
555 return 0;
556
bfb0d950
AS
557 unw_search_unwind_table_p
558 = (unw_search_unwind_table_p_ftype *) dlsym (handle,
559 search_unwind_table_name);
0e5d83e3
JJ
560 if (unw_search_unwind_table_p == NULL)
561 return 0;
562
bfb0d950
AS
563 unw_find_dyn_list_p
564 = (unw_find_dyn_list_p_ftype *) dlsym (handle, find_dyn_list_name);
0e5d83e3
JJ
565 if (unw_find_dyn_list_p == NULL)
566 return 0;
567
568 return 1;
569}
570
571int
572libunwind_is_initialized (void)
573{
574 return libunwind_initialized;
575}
576
6c265988 577void _initialize_libunwind_frame ();
0e5d83e3 578void
6c265988 579_initialize_libunwind_frame ()
0e5d83e3 580{
0e5d83e3
JJ
581 libunwind_initialized = libunwind_load ();
582}