blob: 9b9d21bca00dd09fba23996b956e6c406b9e4e70 [file] [log] [blame]
hp.com!davidmd5ab8982005-05-20 11:28:16 +00001/* libunwind - a platform-independent unwind library
2 Copyright (C) 2001-2005 Hewlett-Packard Co
David Mosberger-Tange6b9f352007-08-22 13:02:09 -06003 Copyright (C) 2007 David Mosberger-Tang
4 Contributed by David Mosberger-Tang <dmosberger@gmail.com>
hp.com!davidmd5ab8982005-05-20 11:28:16 +00005
6This file is part of libunwind.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice shall be
17included in all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
26
27/* This files contains libunwind-internal definitions which are
28 subject to frequent change and are not to be exposed to
29 libunwind-users. */
30
31#ifndef libunwind_i_h
32#define libunwind_i_h
33
34#ifdef HAVE_CONFIG_H
35# include "config.h"
36#endif
37
38#ifdef HAVE___THREAD
39 /* For now, turn off per-thread caching. It uses up too much TLS
40 memory per thread even when the thread never uses libunwind at
41 all. */
42# undef HAVE___THREAD
43#endif
44
45/* Platform-independent libunwind-internal declarations. */
46
47#include <sys/types.h> /* HP-UX needs this before include of pthread.h */
48
49#include <assert.h>
50#include <libunwind.h>
51#include <pthread.h>
52#include <signal.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
Konstantin Belousov905034c2010-03-06 00:41:37 +020057#if defined(HAVE_ENDIAN_H)
hp.com!davidmd5ab8982005-05-20 11:28:16 +000058# include <endian.h>
Konstantin Belousov905034c2010-03-06 00:41:37 +020059#elif defined(HAVE_SYS_ENDIAN_H)
60# include <sys/endian.h>
hp.com!davidmd5ab8982005-05-20 11:28:16 +000061#else
62# define __LITTLE_ENDIAN 1234
63# define __BIG_ENDIAN 4321
64# if defined(__hpux)
65# define __BYTE_ORDER __BIG_ENDIAN
66# else
67# error Host has unknown byte-order.
68# endif
69#endif
70
71#ifdef __GNUC__
72# define UNUSED __attribute__((unused))
73# define NORETURN __attribute__((noreturn))
74# define ALIAS(name) __attribute__((alias (#name)))
75# if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
76# define ALWAYS_INLINE inline __attribute__((always_inline))
77# define HIDDEN __attribute__((visibility ("hidden")))
78# define PROTECTED __attribute__((visibility ("protected")))
79# else
80# define ALWAYS_INLINE
81# define HIDDEN
82# define PROTECTED
83# endif
84# if (__GNUC__ >= 3)
85# define likely(x) __builtin_expect ((x), 1)
86# define unlikely(x) __builtin_expect ((x), 0)
87# else
88# define likely(x) (x)
89# define unlikely(x) (x)
90# endif
91#else
92# define ALWAYS_INLINE
93# define UNUSED
94# define NORETURN
95# define ALIAS(name)
96# define HIDDEN
97# define PROTECTED
98# define likely(x) (x)
99# define unlikely(x) (x)
100#endif
101
102#ifdef DEBUG
103# define UNW_DEBUG 1
104#else
105# define UNW_DEBUG 0
106#endif
107
108#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
109
110/* Make it easy to write thread-safe code which may or may not be
111 linked against libpthread. The macros below can be used
112 unconditionally and if -lpthread is around, they'll call the
113 corresponding routines otherwise, they do nothing. */
114
115#pragma weak pthread_mutex_init
116#pragma weak pthread_mutex_lock
117#pragma weak pthread_mutex_unlock
118
119#define mutex_init(l) \
120 (pthread_mutex_init != 0 ? pthread_mutex_init ((l), 0) : 0)
121#define mutex_lock(l) \
122 (pthread_mutex_lock != 0 ? pthread_mutex_lock (l) : 0)
123#define mutex_unlock(l) \
124 (pthread_mutex_unlock != 0 ? pthread_mutex_unlock (l) : 0)
125
126#ifdef HAVE_ATOMIC_OPS_H
127# include <atomic_ops.h>
128static inline int
129cmpxchg_ptr (void *addr, void *old, void *new)
130{
131 union
132 {
133 void *vp;
134 AO_t *aop;
135 }
136 u;
137
138 u.vp = addr;
139 return AO_compare_and_swap(u.aop, (AO_t) old, (AO_t) new);
140}
141# define fetch_and_add1(_ptr) AO_fetch_and_add1(_ptr)
142 /* GCC 3.2.0 on HP-UX crashes on cmpxchg_ptr() */
143# if !(defined(__hpux) && __GNUC__ == 3 && __GNUC_MINOR__ == 2)
144# define HAVE_CMPXCHG
145# endif
146# define HAVE_FETCH_AND_ADD1
147#else
148# ifdef HAVE_IA64INTRIN_H
149# include <ia64intrin.h>
150static inline int
151cmpxchg_ptr (void *addr, void *old, void *new)
152{
153 union
154 {
155 void *vp;
156 long *vlp;
157 }
158 u;
159
160 u.vp = addr;
161 return __sync_bool_compare_and_swap(u.vlp, (long) old, (long) new);
162}
163# define fetch_and_add1(_ptr) __sync_fetch_and_add(_ptr, 1)
164# define HAVE_CMPXCHG
165# define HAVE_FETCH_AND_ADD1
166# endif
167#endif
168#define atomic_read(ptr) (*(ptr))
169
170#define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn))
171#define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn)
172
173#define unwi_full_mask UNWI_ARCH_OBJ(full_mask)
174
175/* Type of a mask that can be used to inhibit preemption. At the
176 userlevel, preemption is caused by signals and hence sigset_t is
177 appropriate. In constrast, the Linux kernel uses "unsigned long"
178 to hold the processor "flags" instead. */
179typedef sigset_t intrmask_t;
180
181extern intrmask_t unwi_full_mask;
182
Arun Sharma491d5762009-10-16 14:01:50 -0700183/* Silence compiler warnings about variables which are used only if libunwind
184 is configured in a certain way */
185static inline void mark_as_used(void *v) {
186}
187
Paul Pluzhnikov9aa0d6d2009-09-21 13:04:33 -0700188#if defined(CONFIG_BLOCK_SIGNALS)
Arun Sharmaaf9daf62009-10-15 19:29:49 -0700189# define SIGPROCMASK(how, new_mask, old_mask) \
190 sigprocmask((how), (new_mask), (old_mask))
Paul Pluzhnikov9aa0d6d2009-09-21 13:04:33 -0700191#else
Arun Sharma4ab26bc2009-10-16 15:52:44 -0700192# define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask)
Paul Pluzhnikov9aa0d6d2009-09-21 13:04:33 -0700193#endif
194
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000195#define define_lock(name) \
196 pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER
197#define lock_init(l) mutex_init (l)
198#define lock_acquire(l,m) \
199do { \
Paul Pluzhnikov9aa0d6d2009-09-21 13:04:33 -0700200 SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000201 mutex_lock (l); \
202} while (0)
203#define lock_release(l,m) \
204do { \
205 mutex_unlock (l); \
Paul Pluzhnikov9aa0d6d2009-09-21 13:04:33 -0700206 SIGPROCMASK (SIG_SETMASK, &(m), NULL); \
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000207} while (0)
208
209#define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */
210
Konstantin Belousov8ccebc92010-03-06 16:23:24 +0200211#ifndef MAP_ANONYMOUS
212# define MAP_ANONYMOUS MAP_ANON
213#endif
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000214#define GET_MEMORY(mem, size_in_bytes) \
215do { \
216 /* Hopefully, mmap() goes straight through to a system call stub... */ \
217 mem = mmap (0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, \
218 -1, 0); \
219 if (mem == MAP_FAILED) \
220 mem = NULL; \
221} while (0)
222
223#define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info)
224#define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info)
225#define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info)
226#define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info)
227#define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info)
228#define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache)
229
230extern int unwi_find_dynamic_proc_info (unw_addr_space_t as,
231 unw_word_t ip,
232 unw_proc_info_t *pi,
233 int need_unwind_info, void *arg);
234extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as,
235 unw_word_t ip,
236 unw_proc_info_t *pi,
237 unw_dyn_info_t *di,
238 int need_unwind_info,
239 void *arg);
240extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as,
241 unw_proc_info_t *pi, void *arg);
242
243/* These handle the remote (cross-address-space) case of accessing
244 dynamic unwind info. */
245
246extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as,
247 unw_word_t ip,
248 unw_proc_info_t *pi,
249 int need_unwind_info,
250 void *arg);
251extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as,
252 unw_proc_info_t *pi,
253 void *arg);
254extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg);
255
256extern unw_dyn_info_list_t _U_dyn_info_list;
257extern pthread_mutex_t _U_dyn_info_list_lock;
258
259#if UNW_DEBUG
260#define unwi_debug_level UNWI_ARCH_OBJ(debug_level)
261extern long unwi_debug_level;
262
263# include <stdio.h>
264# define Debug(level,format...) \
265do { \
266 if (unwi_debug_level >= level) \
267 { \
268 int _n = level; \
269 if (_n > 16) \
270 _n = 16; \
271 fprintf (stderr, "%*c>%s: ", _n, ' ', __FUNCTION__); \
272 fprintf (stderr, format); \
273 } \
274} while (0)
Arun Sharmaec53de82009-03-16 18:42:27 +0000275# define Dprintf(format...) fprintf (stderr, format)
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000276# ifdef __GNUC__
277# undef inline
278# define inline UNUSED
279# endif
280#else
281# define Debug(level,format...)
Arun Sharmaec53de82009-03-16 18:42:27 +0000282# define Dprintf(format...)
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000283#endif
284
Arun Sharma491d5762009-10-16 14:01:50 -0700285static ALWAYS_INLINE int
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000286print_error (const char *string)
287{
Arun Sharma491d5762009-10-16 14:01:50 -0700288 return write (2, string, strlen (string));
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000289}
290
291#define mi_init UNWI_ARCH_OBJ(mi_init)
292
293extern void mi_init (void); /* machine-independent initializations */
294extern unw_word_t _U_dyn_info_list_addr (void);
295
296/* This is needed/used by ELF targets only. */
297
298struct elf_image
299 {
300 void *image; /* pointer to mmap'd image */
301 size_t size; /* (file-) size of the image */
302 };
303
304#include "tdep/libunwind_i.h"
305
David Mosberger-Tange6b9f352007-08-22 13:02:09 -0600306#ifndef tdep_get_func_addr
307# define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0)
308#endif
309
hp.com!davidmd5ab8982005-05-20 11:28:16 +0000310#endif /* libunwind_i_h */