xref: /openbsd-src/gnu/usr.bin/binutils/gdb/libunwind-frame.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* Frame unwinder for frames using the libunwind library.
2b725ae77Skettenis 
3*11efff7fSkettenis    Copyright 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis 
5b725ae77Skettenis    Written by Jeff Johnston, contributed by Red Hat Inc.
6b725ae77Skettenis 
7b725ae77Skettenis    This file is part of GDB.
8b725ae77Skettenis 
9b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
10b725ae77Skettenis    it under the terms of the GNU General Public License as published by
11b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
12b725ae77Skettenis    (at your option) any later version.
13b725ae77Skettenis 
14b725ae77Skettenis    This program is distributed in the hope that it will be useful,
15b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
16b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17b725ae77Skettenis    GNU General Public License for more details.
18b725ae77Skettenis 
19b725ae77Skettenis    You should have received a copy of the GNU General Public License
20b725ae77Skettenis    along with this program; if not, write to the Free Software
21b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
22b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
23b725ae77Skettenis 
24b725ae77Skettenis #include "defs.h"
25b725ae77Skettenis 
26b725ae77Skettenis #include "inferior.h"
27b725ae77Skettenis #include "frame.h"
28b725ae77Skettenis #include "frame-base.h"
29b725ae77Skettenis #include "frame-unwind.h"
30b725ae77Skettenis #include "gdbcore.h"
31b725ae77Skettenis #include "gdbtypes.h"
32b725ae77Skettenis #include "symtab.h"
33b725ae77Skettenis #include "objfiles.h"
34b725ae77Skettenis #include "regcache.h"
35b725ae77Skettenis 
36b725ae77Skettenis #include <dlfcn.h>
37b725ae77Skettenis 
38b725ae77Skettenis #include "gdb_assert.h"
39b725ae77Skettenis #include "gdb_string.h"
40b725ae77Skettenis 
41b725ae77Skettenis #include "libunwind-frame.h"
42b725ae77Skettenis 
43b725ae77Skettenis #include "complaints.h"
44b725ae77Skettenis 
45b725ae77Skettenis static int libunwind_initialized;
46b725ae77Skettenis static struct gdbarch_data *libunwind_descr_handle;
47b725ae77Skettenis 
48b725ae77Skettenis /* Required function pointers from libunwind.  */
49b725ae77Skettenis static int (*unw_get_reg_p) (unw_cursor_t *, unw_regnum_t, unw_word_t *);
50b725ae77Skettenis static int (*unw_get_fpreg_p) (unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
51b725ae77Skettenis static int (*unw_get_saveloc_p) (unw_cursor_t *, unw_regnum_t, unw_save_loc_t *);
52b725ae77Skettenis static int (*unw_step_p) (unw_cursor_t *);
53b725ae77Skettenis static int (*unw_init_remote_p) (unw_cursor_t *, unw_addr_space_t, void *);
54b725ae77Skettenis static unw_addr_space_t (*unw_create_addr_space_p) (unw_accessors_t *, int);
55b725ae77Skettenis static int (*unw_search_unwind_table_p) (unw_addr_space_t, unw_word_t, unw_dyn_info_t *,
56b725ae77Skettenis 					 unw_proc_info_t *, int, void *);
57b725ae77Skettenis static unw_word_t (*unw_find_dyn_list_p) (unw_addr_space_t, unw_dyn_info_t *,
58b725ae77Skettenis 					  void *);
59b725ae77Skettenis 
60b725ae77Skettenis 
61b725ae77Skettenis struct libunwind_frame_cache
62b725ae77Skettenis {
63b725ae77Skettenis   CORE_ADDR base;
64b725ae77Skettenis   CORE_ADDR func_addr;
65b725ae77Skettenis   unw_cursor_t cursor;
66b725ae77Skettenis };
67b725ae77Skettenis 
68b725ae77Skettenis /* We need to qualify the function names with a platform-specific prefix to match
69b725ae77Skettenis    the names used by the libunwind library.  The UNW_OBJ macro is provided by the
70b725ae77Skettenis    libunwind.h header file.  */
71b725ae77Skettenis #define STRINGIFY2(name)	#name
72b725ae77Skettenis #define STRINGIFY(name)		STRINGIFY2(name)
73b725ae77Skettenis 
74*11efff7fSkettenis #ifndef LIBUNWIND_SO
75*11efff7fSkettenis #define LIBUNWIND_SO "libunwind-" STRINGIFY(UNW_TARGET) ".so"
76*11efff7fSkettenis #endif
77*11efff7fSkettenis 
78b725ae77Skettenis static char *get_reg_name = STRINGIFY(UNW_OBJ(get_reg));
79b725ae77Skettenis static char *get_fpreg_name = STRINGIFY(UNW_OBJ(get_fpreg));
80b725ae77Skettenis static char *get_saveloc_name = STRINGIFY(UNW_OBJ(get_save_loc));
81b725ae77Skettenis static char *step_name = STRINGIFY(UNW_OBJ(step));
82b725ae77Skettenis static char *init_remote_name = STRINGIFY(UNW_OBJ(init_remote));
83b725ae77Skettenis static char *create_addr_space_name = STRINGIFY(UNW_OBJ(create_addr_space));
84b725ae77Skettenis static char *search_unwind_table_name = STRINGIFY(UNW_OBJ(search_unwind_table));
85b725ae77Skettenis static char *find_dyn_list_name = STRINGIFY(UNW_OBJ(find_dyn_list));
86b725ae77Skettenis 
87b725ae77Skettenis static struct libunwind_descr *
libunwind_descr(struct gdbarch * gdbarch)88b725ae77Skettenis libunwind_descr (struct gdbarch *gdbarch)
89b725ae77Skettenis {
90b725ae77Skettenis   return gdbarch_data (gdbarch, libunwind_descr_handle);
91b725ae77Skettenis }
92b725ae77Skettenis 
93b725ae77Skettenis static void *
libunwind_descr_init(struct gdbarch * gdbarch)94b725ae77Skettenis libunwind_descr_init (struct gdbarch *gdbarch)
95b725ae77Skettenis {
96b725ae77Skettenis   struct libunwind_descr *descr = GDBARCH_OBSTACK_ZALLOC (gdbarch,
97b725ae77Skettenis 							  struct libunwind_descr);
98b725ae77Skettenis   return descr;
99b725ae77Skettenis }
100b725ae77Skettenis 
101b725ae77Skettenis void
libunwind_frame_set_descr(struct gdbarch * gdbarch,struct libunwind_descr * descr)102b725ae77Skettenis libunwind_frame_set_descr (struct gdbarch *gdbarch, struct libunwind_descr *descr)
103b725ae77Skettenis {
104b725ae77Skettenis   struct libunwind_descr *arch_descr;
105b725ae77Skettenis 
106b725ae77Skettenis   gdb_assert (gdbarch != NULL);
107b725ae77Skettenis 
108b725ae77Skettenis   arch_descr = gdbarch_data (gdbarch, libunwind_descr_handle);
109b725ae77Skettenis 
110b725ae77Skettenis   if (arch_descr == NULL)
111b725ae77Skettenis     {
112b725ae77Skettenis       /* First time here.  Must initialize data area.  */
113b725ae77Skettenis       arch_descr = libunwind_descr_init (gdbarch);
114*11efff7fSkettenis       deprecated_set_gdbarch_data (gdbarch, libunwind_descr_handle, arch_descr);
115b725ae77Skettenis     }
116b725ae77Skettenis 
117b725ae77Skettenis   /* Copy new descriptor info into arch descriptor.  */
118b725ae77Skettenis   arch_descr->gdb2uw = descr->gdb2uw;
119b725ae77Skettenis   arch_descr->uw2gdb = descr->uw2gdb;
120b725ae77Skettenis   arch_descr->is_fpreg = descr->is_fpreg;
121b725ae77Skettenis   arch_descr->accessors = descr->accessors;
122b725ae77Skettenis }
123b725ae77Skettenis 
124b725ae77Skettenis static struct libunwind_frame_cache *
libunwind_frame_cache(struct frame_info * next_frame,void ** this_cache)125b725ae77Skettenis libunwind_frame_cache (struct frame_info *next_frame, void **this_cache)
126b725ae77Skettenis {
127b725ae77Skettenis   unw_accessors_t *acc;
128b725ae77Skettenis   unw_addr_space_t as;
129b725ae77Skettenis   unw_word_t fp;
130b725ae77Skettenis   unw_regnum_t uw_sp_regnum;
131b725ae77Skettenis   struct libunwind_frame_cache *cache;
132b725ae77Skettenis   struct libunwind_descr *descr;
133b725ae77Skettenis   int i, ret;
134b725ae77Skettenis 
135b725ae77Skettenis   if (*this_cache)
136b725ae77Skettenis     return *this_cache;
137b725ae77Skettenis 
138b725ae77Skettenis   /* Allocate a new cache.  */
139b725ae77Skettenis   cache = FRAME_OBSTACK_ZALLOC (struct libunwind_frame_cache);
140b725ae77Skettenis 
141b725ae77Skettenis   cache->func_addr = frame_func_unwind (next_frame);
142b725ae77Skettenis 
143b725ae77Skettenis   /* Get a libunwind cursor to the previous frame.  We do this by initializing
144b725ae77Skettenis      a cursor.  Libunwind treats a new cursor as the top of stack and will get
145b725ae77Skettenis      the current register set via the libunwind register accessor.  Now, we
146b725ae77Skettenis      provide the platform-specific accessors and we set up the register accessor to use
147b725ae77Skettenis      the frame register unwinding interfaces so that we properly get the registers for
148b725ae77Skettenis      the current frame rather than the top.  We then use the  unw_step function to
149b725ae77Skettenis      move the libunwind cursor back one frame.  We can later use this cursor to find previous
150b725ae77Skettenis      registers via the unw_get_reg interface which will invoke libunwind's special logic.  */
151b725ae77Skettenis   descr = libunwind_descr (get_frame_arch (next_frame));
152b725ae77Skettenis   acc = descr->accessors;
153b725ae77Skettenis   as =  unw_create_addr_space_p (acc,
154b725ae77Skettenis 				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
155b725ae77Skettenis 				 ? __BIG_ENDIAN
156b725ae77Skettenis 				 : __LITTLE_ENDIAN);
157b725ae77Skettenis 
158b725ae77Skettenis   unw_init_remote_p (&cache->cursor, as, next_frame);
159b725ae77Skettenis   unw_step_p (&cache->cursor);
160b725ae77Skettenis 
161b725ae77Skettenis   /* To get base address, get sp from previous frame.  */
162b725ae77Skettenis   uw_sp_regnum = descr->gdb2uw (SP_REGNUM);
163b725ae77Skettenis   ret = unw_get_reg_p (&cache->cursor, uw_sp_regnum, &fp);
164b725ae77Skettenis   if (ret < 0)
165b725ae77Skettenis     error ("Can't get libunwind sp register.");
166b725ae77Skettenis 
167b725ae77Skettenis   cache->base = (CORE_ADDR)fp;
168b725ae77Skettenis 
169b725ae77Skettenis   *this_cache = cache;
170b725ae77Skettenis   return cache;
171b725ae77Skettenis }
172b725ae77Skettenis 
173b725ae77Skettenis unw_word_t
libunwind_find_dyn_list(unw_addr_space_t as,unw_dyn_info_t * di,void * arg)174b725ae77Skettenis libunwind_find_dyn_list (unw_addr_space_t as, unw_dyn_info_t *di, void *arg)
175b725ae77Skettenis {
176b725ae77Skettenis   return unw_find_dyn_list_p (as, di, arg);
177b725ae77Skettenis }
178b725ae77Skettenis 
179b725ae77Skettenis static const struct frame_unwind libunwind_frame_unwind =
180b725ae77Skettenis {
181b725ae77Skettenis   NORMAL_FRAME,
182b725ae77Skettenis   libunwind_frame_this_id,
183b725ae77Skettenis   libunwind_frame_prev_register
184b725ae77Skettenis };
185b725ae77Skettenis 
186b725ae77Skettenis /* Verify if there is sufficient libunwind information for the frame to use
187b725ae77Skettenis    libunwind frame unwinding.  */
188b725ae77Skettenis const struct frame_unwind *
libunwind_frame_sniffer(struct frame_info * next_frame)189b725ae77Skettenis libunwind_frame_sniffer (struct frame_info *next_frame)
190b725ae77Skettenis {
191b725ae77Skettenis   unw_cursor_t cursor;
192b725ae77Skettenis   unw_accessors_t *acc;
193b725ae77Skettenis   unw_addr_space_t as;
194b725ae77Skettenis   struct libunwind_descr *descr;
195b725ae77Skettenis   int i, ret;
196b725ae77Skettenis 
197b725ae77Skettenis   /* To test for libunwind unwind support, initialize a cursor to the current frame and try to back
198b725ae77Skettenis      up.  We use this same method when setting up the frame cache (see libunwind_frame_cache()).
199b725ae77Skettenis      If libunwind returns success for this operation, it means that it has found sufficient
200b725ae77Skettenis      libunwind unwinding information to do so.  */
201b725ae77Skettenis 
202b725ae77Skettenis   descr = libunwind_descr (get_frame_arch (next_frame));
203b725ae77Skettenis   acc = descr->accessors;
204b725ae77Skettenis   as =  unw_create_addr_space_p (acc,
205b725ae77Skettenis 				 TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
206b725ae77Skettenis 				 ? __BIG_ENDIAN
207b725ae77Skettenis 				 : __LITTLE_ENDIAN);
208b725ae77Skettenis 
209b725ae77Skettenis   ret = unw_init_remote_p (&cursor, as, next_frame);
210b725ae77Skettenis 
211b725ae77Skettenis   if (ret >= 0)
212b725ae77Skettenis     ret = unw_step_p (&cursor);
213b725ae77Skettenis 
214b725ae77Skettenis   if (ret < 0)
215b725ae77Skettenis     return NULL;
216b725ae77Skettenis 
217b725ae77Skettenis   return &libunwind_frame_unwind;
218b725ae77Skettenis }
219b725ae77Skettenis 
220b725ae77Skettenis void
libunwind_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)221b725ae77Skettenis libunwind_frame_this_id (struct frame_info *next_frame, void **this_cache,
222b725ae77Skettenis 		      struct frame_id *this_id)
223b725ae77Skettenis {
224b725ae77Skettenis   struct libunwind_frame_cache *cache =
225b725ae77Skettenis     libunwind_frame_cache (next_frame, this_cache);
226b725ae77Skettenis 
227b725ae77Skettenis   (*this_id) = frame_id_build (cache->base, cache->func_addr);
228b725ae77Skettenis }
229b725ae77Skettenis 
230b725ae77Skettenis void
libunwind_frame_prev_register(struct frame_info * next_frame,void ** this_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)231b725ae77Skettenis libunwind_frame_prev_register (struct frame_info *next_frame, void **this_cache,
232b725ae77Skettenis 			       int regnum, int *optimizedp,
233b725ae77Skettenis 			       enum lval_type *lvalp, CORE_ADDR *addrp,
234b725ae77Skettenis 			       int *realnump, void *valuep)
235b725ae77Skettenis {
236b725ae77Skettenis   struct libunwind_frame_cache *cache =
237b725ae77Skettenis     libunwind_frame_cache (next_frame, this_cache);
238b725ae77Skettenis 
239b725ae77Skettenis   void *ptr;
240b725ae77Skettenis   unw_cursor_t *c;
241b725ae77Skettenis   unw_save_loc_t sl;
242b725ae77Skettenis   int i, ret;
243b725ae77Skettenis   unw_word_t intval;
244b725ae77Skettenis   unw_fpreg_t fpval;
245b725ae77Skettenis   unw_regnum_t uw_regnum;
246b725ae77Skettenis   struct libunwind_descr *descr;
247b725ae77Skettenis 
248b725ae77Skettenis   /* Convert from gdb register number to libunwind register number.  */
249b725ae77Skettenis   descr = libunwind_descr (get_frame_arch (next_frame));
250b725ae77Skettenis   uw_regnum = descr->gdb2uw (regnum);
251b725ae77Skettenis 
252b725ae77Skettenis   gdb_assert (regnum >= 0);
253b725ae77Skettenis 
254b725ae77Skettenis   if (!target_has_registers)
255b725ae77Skettenis     error ("No registers.");
256b725ae77Skettenis 
257b725ae77Skettenis   *optimizedp = 0;
258b725ae77Skettenis   *addrp = 0;
259b725ae77Skettenis   *lvalp = not_lval;
260b725ae77Skettenis   *realnump = -1;
261b725ae77Skettenis 
262*11efff7fSkettenis   if (valuep)
263b725ae77Skettenis     memset (valuep, 0, register_size (current_gdbarch, regnum));
264b725ae77Skettenis 
265b725ae77Skettenis   if (uw_regnum < 0)
266b725ae77Skettenis     return;
267b725ae77Skettenis 
268b725ae77Skettenis   /* To get the previous register, we use the libunwind register APIs with
269b725ae77Skettenis      the cursor we have already pushed back to the previous frame.  */
270b725ae77Skettenis 
271b725ae77Skettenis   if (descr->is_fpreg (uw_regnum))
272b725ae77Skettenis     {
273b725ae77Skettenis       ret = unw_get_fpreg_p (&cache->cursor, uw_regnum, &fpval);
274b725ae77Skettenis       ptr = &fpval;
275b725ae77Skettenis     }
276b725ae77Skettenis   else
277b725ae77Skettenis     {
278b725ae77Skettenis       ret = unw_get_reg_p (&cache->cursor, uw_regnum, &intval);
279b725ae77Skettenis       ptr = &intval;
280b725ae77Skettenis     }
281b725ae77Skettenis 
282b725ae77Skettenis   if (ret < 0)
283b725ae77Skettenis     return;
284b725ae77Skettenis 
285*11efff7fSkettenis   if (valuep)
286b725ae77Skettenis     memcpy (valuep, ptr, register_size (current_gdbarch, regnum));
287b725ae77Skettenis 
288b725ae77Skettenis   if (unw_get_saveloc_p (&cache->cursor, uw_regnum, &sl) < 0)
289b725ae77Skettenis     return;
290b725ae77Skettenis 
291b725ae77Skettenis   switch (sl.type)
292b725ae77Skettenis     {
293b725ae77Skettenis     case UNW_SLT_NONE:
294b725ae77Skettenis       *optimizedp = 1;
295b725ae77Skettenis       break;
296b725ae77Skettenis 
297b725ae77Skettenis     case UNW_SLT_MEMORY:
298b725ae77Skettenis       *lvalp = lval_memory;
299b725ae77Skettenis       *addrp = sl.u.addr;
300b725ae77Skettenis       break;
301b725ae77Skettenis 
302b725ae77Skettenis     case UNW_SLT_REG:
303b725ae77Skettenis       *lvalp = lval_register;
304b725ae77Skettenis       *realnump = regnum;
305b725ae77Skettenis       break;
306b725ae77Skettenis     }
307b725ae77Skettenis }
308b725ae77Skettenis 
309b725ae77Skettenis CORE_ADDR
libunwind_frame_base_address(struct frame_info * next_frame,void ** this_cache)310b725ae77Skettenis libunwind_frame_base_address (struct frame_info *next_frame, void **this_cache)
311b725ae77Skettenis {
312b725ae77Skettenis   struct libunwind_frame_cache *cache =
313b725ae77Skettenis     libunwind_frame_cache (next_frame, this_cache);
314b725ae77Skettenis 
315b725ae77Skettenis   return cache->base;
316b725ae77Skettenis }
317b725ae77Skettenis 
318b725ae77Skettenis /* The following is a glue routine to call the libunwind unwind table
319b725ae77Skettenis    search function to get unwind information for a specified ip address.  */
320b725ae77Skettenis int
libunwind_search_unwind_table(void * as,long ip,void * di,void * pi,int need_unwind_info,void * args)321b725ae77Skettenis libunwind_search_unwind_table (void *as, long ip, void *di,
322b725ae77Skettenis 			       void *pi, int need_unwind_info, void *args)
323b725ae77Skettenis {
324b725ae77Skettenis   return unw_search_unwind_table_p (*(unw_addr_space_t *)as, (unw_word_t )ip,
325b725ae77Skettenis 				    di, pi, need_unwind_info, args);
326b725ae77Skettenis }
327b725ae77Skettenis 
328b725ae77Skettenis static int
libunwind_load(void)329b725ae77Skettenis libunwind_load (void)
330b725ae77Skettenis {
331b725ae77Skettenis   void *handle;
332b725ae77Skettenis 
333b725ae77Skettenis   handle = dlopen (LIBUNWIND_SO, RTLD_NOW);
334b725ae77Skettenis   if (handle == NULL)
335b725ae77Skettenis     return 0;
336b725ae77Skettenis 
337b725ae77Skettenis   /* Initialize pointers to the dynamic library functions we will use.  */
338b725ae77Skettenis 
339b725ae77Skettenis   unw_get_reg_p = dlsym (handle, get_reg_name);
340b725ae77Skettenis   if (unw_get_reg_p == NULL)
341b725ae77Skettenis     return 0;
342b725ae77Skettenis 
343b725ae77Skettenis   unw_get_fpreg_p = dlsym (handle, get_fpreg_name);
344b725ae77Skettenis   if (unw_get_fpreg_p == NULL)
345b725ae77Skettenis     return 0;
346b725ae77Skettenis 
347b725ae77Skettenis   unw_get_saveloc_p = dlsym (handle, get_saveloc_name);
348b725ae77Skettenis   if (unw_get_saveloc_p == NULL)
349b725ae77Skettenis     return 0;
350b725ae77Skettenis 
351b725ae77Skettenis   unw_step_p = dlsym (handle, step_name);
352b725ae77Skettenis   if (unw_step_p == NULL)
353b725ae77Skettenis     return 0;
354b725ae77Skettenis 
355b725ae77Skettenis   unw_init_remote_p = dlsym (handle, init_remote_name);
356b725ae77Skettenis   if (unw_init_remote_p == NULL)
357b725ae77Skettenis     return 0;
358b725ae77Skettenis 
359b725ae77Skettenis   unw_create_addr_space_p = dlsym (handle, create_addr_space_name);
360b725ae77Skettenis   if (unw_create_addr_space_p == NULL)
361b725ae77Skettenis     return 0;
362b725ae77Skettenis 
363b725ae77Skettenis   unw_search_unwind_table_p = dlsym (handle, search_unwind_table_name);
364b725ae77Skettenis   if (unw_search_unwind_table_p == NULL)
365b725ae77Skettenis     return 0;
366b725ae77Skettenis 
367b725ae77Skettenis   unw_find_dyn_list_p = dlsym (handle, find_dyn_list_name);
368b725ae77Skettenis   if (unw_find_dyn_list_p == NULL)
369b725ae77Skettenis     return 0;
370b725ae77Skettenis 
371b725ae77Skettenis   return 1;
372b725ae77Skettenis }
373b725ae77Skettenis 
374b725ae77Skettenis int
libunwind_is_initialized(void)375b725ae77Skettenis libunwind_is_initialized (void)
376b725ae77Skettenis {
377b725ae77Skettenis   return libunwind_initialized;
378b725ae77Skettenis }
379b725ae77Skettenis 
380b725ae77Skettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
381b725ae77Skettenis void _initialize_libunwind_frame (void);
382b725ae77Skettenis 
383b725ae77Skettenis void
_initialize_libunwind_frame(void)384b725ae77Skettenis _initialize_libunwind_frame (void)
385b725ae77Skettenis {
386*11efff7fSkettenis   libunwind_descr_handle = gdbarch_data_register_post_init (libunwind_descr_init);
387b725ae77Skettenis 
388b725ae77Skettenis   libunwind_initialized = libunwind_load ();
389b725ae77Skettenis }
390