/src/libunwind/include/libunwind_i.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* libunwind - a platform-independent unwind library |
2 | | Copyright (C) 2001-2005 Hewlett-Packard Co |
3 | | Copyright (C) 2007 David Mosberger-Tang |
4 | | Contributed by David Mosberger-Tang <dmosberger@gmail.com> |
5 | | |
6 | | This file is part of libunwind. |
7 | | |
8 | | Permission is hereby granted, free of charge, to any person obtaining |
9 | | a copy of this software and associated documentation files (the |
10 | | "Software"), to deal in the Software without restriction, including |
11 | | without limitation the rights to use, copy, modify, merge, publish, |
12 | | distribute, sublicense, and/or sell copies of the Software, and to |
13 | | permit persons to whom the Software is furnished to do so, subject to |
14 | | the following conditions: |
15 | | |
16 | | The above copyright notice and this permission notice shall be |
17 | | included in all copies or substantial portions of the Software. |
18 | | |
19 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
20 | | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
21 | | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
22 | | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
23 | | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
24 | | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
25 | | WITH 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 | | #include "compiler.h" |
39 | | |
40 | | #if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD |
41 | | #define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_PER_THREAD |
42 | | #else |
43 | 1 | #define UNWI_DEFAULT_CACHING_POLICY UNW_CACHE_GLOBAL |
44 | | #endif |
45 | | |
46 | | /* Platform-independent libunwind-internal declarations. */ |
47 | | |
48 | | #include <sys/types.h> /* HP-UX needs this before include of pthread.h */ |
49 | | |
50 | | #include <assert.h> |
51 | | #include <libunwind.h> |
52 | | #include <pthread.h> |
53 | | #include <signal.h> |
54 | | #include <stdbool.h> |
55 | | #include <stdlib.h> |
56 | | #include <string.h> |
57 | | #include <unistd.h> |
58 | | #include <sys/mman.h> |
59 | | #include <errno.h> |
60 | | #include <stdio.h> |
61 | | |
62 | | #if defined(HAVE_SYS_SYSCALL_H) |
63 | | # include <sys/syscall.h> /* For SYS_xxx definitions */ |
64 | | #endif |
65 | | |
66 | | #if defined(HAVE_ELF_H) |
67 | | # include <elf.h> |
68 | | #elif defined(HAVE_SYS_ELF_H) |
69 | | # include <sys/elf.h> |
70 | | #else |
71 | | # error Could not locate <elf.h> |
72 | | #endif |
73 | | #if defined(ELFCLASS32) |
74 | | # define UNW_ELFCLASS32 ELFCLASS32 |
75 | | #else |
76 | | # define UNW_ELFCLASS32 1 |
77 | | #endif |
78 | | #if defined(ELFCLASS64) |
79 | 189k | # define UNW_ELFCLASS64 ELFCLASS64 |
80 | | #else |
81 | | # define UNW_ELFCLASS64 2 |
82 | | #endif |
83 | | |
84 | | #if defined(HAVE_ENDIAN_H) |
85 | | # include <endian.h> |
86 | | #elif defined(HAVE_SYS_ENDIAN_H) |
87 | | # include <sys/endian.h> |
88 | | #elif defined(HAVE_SYS_PARAM_H) |
89 | | # include <sys/param.h> |
90 | | #endif |
91 | | |
92 | | #if defined(__LITTLE_ENDIAN) |
93 | | # define UNW_LITTLE_ENDIAN __LITTLE_ENDIAN |
94 | | #elif defined(_LITTLE_ENDIAN) |
95 | | # define UNW_LITTLE_ENDIAN _LITTLE_ENDIAN |
96 | | #elif defined(LITTLE_ENDIAN) |
97 | | # define UNW_LITTLE_ENDIAN LITTLE_ENDIAN |
98 | | #else |
99 | | # define UNW_LITTLE_ENDIAN 1234 |
100 | | #endif |
101 | | |
102 | | #if defined(__BIG_ENDIAN) |
103 | | # define UNW_BIG_ENDIAN __BIG_ENDIAN |
104 | | #elif defined(_BIG_ENDIAN) |
105 | | # define UNW_BIG_ENDIAN _BIG_ENDIAN |
106 | | #elif defined(BIG_ENDIAN) |
107 | | # define UNW_BIG_ENDIAN BIG_ENDIAN |
108 | | #else |
109 | | # define UNW_BIG_ENDIAN 4321 |
110 | | #endif |
111 | | |
112 | | #if defined(__BYTE_ORDER) |
113 | | # define UNW_BYTE_ORDER __BYTE_ORDER |
114 | | #elif defined(_BYTE_ORDER) |
115 | | # define UNW_BYTE_ORDER _BYTE_ORDER |
116 | | #elif defined(BIG_ENDIAN) |
117 | | # define UNW_BYTE_ORDER BYTE_ORDER |
118 | | #else |
119 | | # if defined(__hpux) |
120 | | # define UNW_BYTE_ORDER UNW_BIG_ENDIAN |
121 | | # else |
122 | | # error Target has unknown byte ordering. |
123 | | # endif |
124 | | #endif |
125 | | |
126 | | static inline int |
127 | | byte_order_is_valid(int byte_order) |
128 | 0 | { |
129 | 0 | return byte_order == UNW_BIG_ENDIAN |
130 | 0 | || byte_order == UNW_LITTLE_ENDIAN; |
131 | 0 | } Unexecuted instantiation: Lget_proc_name.c:byte_order_is_valid Unexecuted instantiation: Lget_reg.c:byte_order_is_valid Unexecuted instantiation: Lget_save_loc.c:byte_order_is_valid Unexecuted instantiation: Linit_local.c:byte_order_is_valid Unexecuted instantiation: Los-linux.c:byte_order_is_valid Unexecuted instantiation: Lput_dynamic_unwind_info.c:byte_order_is_valid Unexecuted instantiation: Lregs.c:byte_order_is_valid Unexecuted instantiation: Lstep.c:byte_order_is_valid Unexecuted instantiation: Lfind_dynamic_proc_info.c:byte_order_is_valid Unexecuted instantiation: Lfind_proc_info-lsb.c:byte_order_is_valid Unexecuted instantiation: Lget_accessors.c:byte_order_is_valid Unexecuted instantiation: Lglobal.c:byte_order_is_valid Unexecuted instantiation: Linit.c:byte_order_is_valid Unexecuted instantiation: Lparser.c:byte_order_is_valid Unexecuted instantiation: Lpe.c:byte_order_is_valid Unexecuted instantiation: Lresume.c:byte_order_is_valid Unexecuted instantiation: Lstash_frame.c:byte_order_is_valid Unexecuted instantiation: dyn-info-list.c:byte_order_is_valid Unexecuted instantiation: elf64.c:byte_order_is_valid Unexecuted instantiation: flush_cache.c:byte_order_is_valid Unexecuted instantiation: global.c:byte_order_is_valid Unexecuted instantiation: init.c:byte_order_is_valid Unexecuted instantiation: is_fpreg.c:byte_order_is_valid Unexecuted instantiation: mempool.c:byte_order_is_valid Unexecuted instantiation: os-linux.c:byte_order_is_valid Unexecuted instantiation: Laddress_validator.c:byte_order_is_valid Unexecuted instantiation: Ldyn-extract.c:byte_order_is_valid Unexecuted instantiation: Lexpr.c:byte_order_is_valid Unexecuted instantiation: Lfde.c:byte_order_is_valid |
132 | | |
133 | | static inline int |
134 | | byte_order_is_big_endian(int byte_order) |
135 | 0 | { |
136 | 0 | return byte_order == UNW_BIG_ENDIAN; |
137 | 0 | } Unexecuted instantiation: Lget_proc_name.c:byte_order_is_big_endian Unexecuted instantiation: Lget_reg.c:byte_order_is_big_endian Unexecuted instantiation: Lget_save_loc.c:byte_order_is_big_endian Unexecuted instantiation: Linit_local.c:byte_order_is_big_endian Unexecuted instantiation: Los-linux.c:byte_order_is_big_endian Unexecuted instantiation: Lput_dynamic_unwind_info.c:byte_order_is_big_endian Unexecuted instantiation: Lregs.c:byte_order_is_big_endian Unexecuted instantiation: Lstep.c:byte_order_is_big_endian Unexecuted instantiation: Lfind_dynamic_proc_info.c:byte_order_is_big_endian Unexecuted instantiation: Lfind_proc_info-lsb.c:byte_order_is_big_endian Unexecuted instantiation: Lget_accessors.c:byte_order_is_big_endian Unexecuted instantiation: Lglobal.c:byte_order_is_big_endian Unexecuted instantiation: Linit.c:byte_order_is_big_endian Unexecuted instantiation: Lparser.c:byte_order_is_big_endian Unexecuted instantiation: Lpe.c:byte_order_is_big_endian Unexecuted instantiation: Lresume.c:byte_order_is_big_endian Unexecuted instantiation: Lstash_frame.c:byte_order_is_big_endian Unexecuted instantiation: dyn-info-list.c:byte_order_is_big_endian Unexecuted instantiation: elf64.c:byte_order_is_big_endian Unexecuted instantiation: flush_cache.c:byte_order_is_big_endian Unexecuted instantiation: global.c:byte_order_is_big_endian Unexecuted instantiation: init.c:byte_order_is_big_endian Unexecuted instantiation: is_fpreg.c:byte_order_is_big_endian Unexecuted instantiation: mempool.c:byte_order_is_big_endian Unexecuted instantiation: os-linux.c:byte_order_is_big_endian Unexecuted instantiation: Laddress_validator.c:byte_order_is_big_endian Unexecuted instantiation: Ldyn-extract.c:byte_order_is_big_endian Unexecuted instantiation: Lexpr.c:byte_order_is_big_endian Unexecuted instantiation: Lfde.c:byte_order_is_big_endian |
138 | | |
139 | | static inline int |
140 | | target_is_big_endian(void) |
141 | 0 | { |
142 | 0 | return byte_order_is_big_endian(UNW_BYTE_ORDER); |
143 | 0 | } Unexecuted instantiation: Lget_proc_name.c:target_is_big_endian Unexecuted instantiation: Lget_reg.c:target_is_big_endian Unexecuted instantiation: Lget_save_loc.c:target_is_big_endian Unexecuted instantiation: Linit_local.c:target_is_big_endian Unexecuted instantiation: Los-linux.c:target_is_big_endian Unexecuted instantiation: Lput_dynamic_unwind_info.c:target_is_big_endian Unexecuted instantiation: Lregs.c:target_is_big_endian Unexecuted instantiation: Lstep.c:target_is_big_endian Unexecuted instantiation: Lfind_dynamic_proc_info.c:target_is_big_endian Unexecuted instantiation: Lfind_proc_info-lsb.c:target_is_big_endian Unexecuted instantiation: Lget_accessors.c:target_is_big_endian Unexecuted instantiation: Lglobal.c:target_is_big_endian Unexecuted instantiation: Linit.c:target_is_big_endian Unexecuted instantiation: Lparser.c:target_is_big_endian Unexecuted instantiation: Lpe.c:target_is_big_endian Unexecuted instantiation: Lresume.c:target_is_big_endian Unexecuted instantiation: Lstash_frame.c:target_is_big_endian Unexecuted instantiation: dyn-info-list.c:target_is_big_endian Unexecuted instantiation: elf64.c:target_is_big_endian Unexecuted instantiation: flush_cache.c:target_is_big_endian Unexecuted instantiation: global.c:target_is_big_endian Unexecuted instantiation: init.c:target_is_big_endian Unexecuted instantiation: is_fpreg.c:target_is_big_endian Unexecuted instantiation: mempool.c:target_is_big_endian Unexecuted instantiation: os-linux.c:target_is_big_endian Unexecuted instantiation: Laddress_validator.c:target_is_big_endian Unexecuted instantiation: Ldyn-extract.c:target_is_big_endian Unexecuted instantiation: Lexpr.c:target_is_big_endian Unexecuted instantiation: Lfde.c:target_is_big_endian |
144 | | |
145 | | #if defined(HAVE__BUILTIN_UNREACHABLE) |
146 | | # define unreachable() __builtin_unreachable() |
147 | | #else |
148 | | # define unreachable() do { } while (1) |
149 | | #endif |
150 | | |
151 | | /* Make it easy to write thread-safe code which may or may not be |
152 | | linked against libpthread. The macros below can be used |
153 | | unconditionally and if -lpthread is around, they'll call the |
154 | | corresponding routines otherwise, they do nothing. */ |
155 | | |
156 | | #pragma weak pthread_mutex_init |
157 | | #pragma weak pthread_mutex_lock |
158 | | #pragma weak pthread_mutex_unlock |
159 | | #pragma weak pthread_sigmask |
160 | | |
161 | | #define mutex_init(l) \ |
162 | 2 | (pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0) |
163 | | #define mutex_lock(l) \ |
164 | 48.1k | (pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0) |
165 | | #define mutex_unlock(l) \ |
166 | 48.1k | (pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0) |
167 | | |
168 | 23.6k | #define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn)) |
169 | 34 | #define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn) |
170 | | |
171 | 1 | #define unwi_full_mask UNWI_ARCH_OBJ(full_mask) |
172 | | |
173 | | /* Type of a mask that can be used to inhibit preemption. At the |
174 | | userlevel, preemption is caused by signals and hence sigset_t is |
175 | | appropriate. In contrast, the Linux kernel uses "unsigned long" |
176 | | to hold the processor "flags" instead. */ |
177 | | typedef sigset_t intrmask_t; |
178 | | |
179 | | extern intrmask_t unwi_full_mask; |
180 | | |
181 | | /* Silence compiler warnings about variables which are used only if libunwind |
182 | | is configured in a certain way */ |
183 | 0 | static inline void mark_as_used(void *v UNUSED) { |
184 | 0 | } Unexecuted instantiation: Lget_proc_name.c:mark_as_used Unexecuted instantiation: Lget_reg.c:mark_as_used Unexecuted instantiation: Lget_save_loc.c:mark_as_used Unexecuted instantiation: Linit_local.c:mark_as_used Unexecuted instantiation: Los-linux.c:mark_as_used Unexecuted instantiation: Lput_dynamic_unwind_info.c:mark_as_used Unexecuted instantiation: Lregs.c:mark_as_used Unexecuted instantiation: Lstep.c:mark_as_used Unexecuted instantiation: Lfind_dynamic_proc_info.c:mark_as_used Unexecuted instantiation: Lfind_proc_info-lsb.c:mark_as_used Unexecuted instantiation: Lget_accessors.c:mark_as_used Unexecuted instantiation: Lglobal.c:mark_as_used Unexecuted instantiation: Linit.c:mark_as_used Unexecuted instantiation: Lparser.c:mark_as_used Unexecuted instantiation: Lpe.c:mark_as_used Unexecuted instantiation: Lresume.c:mark_as_used Unexecuted instantiation: Lstash_frame.c:mark_as_used Unexecuted instantiation: dyn-info-list.c:mark_as_used Unexecuted instantiation: elf64.c:mark_as_used Unexecuted instantiation: flush_cache.c:mark_as_used Unexecuted instantiation: global.c:mark_as_used Unexecuted instantiation: init.c:mark_as_used Unexecuted instantiation: is_fpreg.c:mark_as_used Unexecuted instantiation: mempool.c:mark_as_used Unexecuted instantiation: os-linux.c:mark_as_used Unexecuted instantiation: Laddress_validator.c:mark_as_used Unexecuted instantiation: Ldyn-extract.c:mark_as_used Unexecuted instantiation: Lexpr.c:mark_as_used Unexecuted instantiation: Lfde.c:mark_as_used |
185 | | |
186 | | #if defined(CONFIG_BLOCK_SIGNALS) |
187 | | /* SIGPROCMASK ignores return values, so we do not have to correct for pthread_sigmask() returning |
188 | | errno on failure when sigprocmask() returns -1. */ |
189 | | # define SIGPROCMASK(how, new_mask, old_mask) \ |
190 | 96.2k | (pthread_sigmask != NULL ? pthread_sigmask((how), (new_mask), (old_mask)) \ |
191 | 96.2k | : sigprocmask((how), (new_mask), (old_mask))) |
192 | | #else |
193 | | # define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask) |
194 | | #endif |
195 | | |
196 | | /* Prefer adaptive mutexes if available */ |
197 | | #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP |
198 | | #define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP |
199 | | #else |
200 | | #define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER |
201 | | #endif |
202 | | |
203 | | #define define_lock(name) \ |
204 | | pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER |
205 | 2 | #define lock_init(l) mutex_init (l) |
206 | 48.1k | #define lock_acquire(l,m) \ |
207 | 48.1k | do { \ |
208 | 48.1k | SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ |
209 | 48.1k | mutex_lock (l); \ |
210 | 48.1k | } while (0) |
211 | 48.1k | #define lock_release(l,m) \ |
212 | 48.1k | do { \ |
213 | 48.1k | mutex_unlock (l); \ |
214 | 48.1k | SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ |
215 | 48.1k | } while (0) |
216 | | |
217 | | #define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */ |
218 | | |
219 | | /* Provide an internal syscall version of mmap to improve signal safety. */ |
220 | | static ALWAYS_INLINE void * |
221 | | mi_mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset) |
222 | 47.2k | { |
223 | 47.2k | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) |
224 | | /* Where supported, bypass libc and invoke the syscall directly. */ |
225 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD |
226 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); |
227 | | # else |
228 | 47.2k | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); |
229 | 47.2k | # endif |
230 | | // @todo this is very likely Linux specific |
231 | 47.2k | if ((unsigned long int)ret > -4096UL) |
232 | 0 | return MAP_FAILED; |
233 | 47.2k | else |
234 | 47.2k | return (void *)ret; |
235 | | #else |
236 | | /* Where direct syscalls are not supported, forward to the libc call. */ |
237 | | return mmap (addr, len, prot, flags, fd, offset); |
238 | | #endif |
239 | 47.2k | } Unexecuted instantiation: Lget_proc_name.c:mi_mmap Unexecuted instantiation: Lget_reg.c:mi_mmap Unexecuted instantiation: Lget_save_loc.c:mi_mmap Unexecuted instantiation: Linit_local.c:mi_mmap Unexecuted instantiation: Los-linux.c:mi_mmap Unexecuted instantiation: Lput_dynamic_unwind_info.c:mi_mmap Unexecuted instantiation: Lregs.c:mi_mmap Unexecuted instantiation: Lstep.c:mi_mmap Unexecuted instantiation: Lfind_dynamic_proc_info.c:mi_mmap Unexecuted instantiation: Lfind_proc_info-lsb.c:mi_mmap Unexecuted instantiation: Lget_accessors.c:mi_mmap Unexecuted instantiation: Lglobal.c:mi_mmap Unexecuted instantiation: Linit.c:mi_mmap Unexecuted instantiation: Lparser.c:mi_mmap Unexecuted instantiation: Lpe.c:mi_mmap Unexecuted instantiation: Lresume.c:mi_mmap Unexecuted instantiation: Lstash_frame.c:mi_mmap Unexecuted instantiation: dyn-info-list.c:mi_mmap Unexecuted instantiation: elf64.c:mi_mmap Unexecuted instantiation: flush_cache.c:mi_mmap Unexecuted instantiation: global.c:mi_mmap Unexecuted instantiation: init.c:mi_mmap Unexecuted instantiation: is_fpreg.c:mi_mmap Line | Count | Source | 222 | 2 | { | 223 | 2 | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) | 224 | | /* Where supported, bypass libc and invoke the syscall directly. */ | 225 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD | 226 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 227 | | # else | 228 | 2 | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 229 | 2 | # endif | 230 | | // @todo this is very likely Linux specific | 231 | 2 | if ((unsigned long int)ret > -4096UL) | 232 | 0 | return MAP_FAILED; | 233 | 2 | else | 234 | 2 | return (void *)ret; | 235 | | #else | 236 | | /* Where direct syscalls are not supported, forward to the libc call. */ | 237 | | return mmap (addr, len, prot, flags, fd, offset); | 238 | | #endif | 239 | 2 | } |
Line | Count | Source | 222 | 47.2k | { | 223 | 47.2k | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) | 224 | | /* Where supported, bypass libc and invoke the syscall directly. */ | 225 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD | 226 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 227 | | # else | 228 | 47.2k | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 229 | 47.2k | # endif | 230 | | // @todo this is very likely Linux specific | 231 | 47.2k | if ((unsigned long int)ret > -4096UL) | 232 | 0 | return MAP_FAILED; | 233 | 47.2k | else | 234 | 47.2k | return (void *)ret; | 235 | | #else | 236 | | /* Where direct syscalls are not supported, forward to the libc call. */ | 237 | | return mmap (addr, len, prot, flags, fd, offset); | 238 | | #endif | 239 | 47.2k | } |
Unexecuted instantiation: Laddress_validator.c:mi_mmap Unexecuted instantiation: Ldyn-extract.c:mi_mmap Unexecuted instantiation: Lexpr.c:mi_mmap Unexecuted instantiation: Lfde.c:mi_mmap |
240 | | |
241 | | /* Provide an internal syscall version of munmap to improve signal safety. */ |
242 | | static ALWAYS_INLINE int |
243 | | mi_munmap (void *addr, size_t len) |
244 | 47.2k | { |
245 | 47.2k | #ifdef SYS_munmap |
246 | 47.2k | return syscall (SYS_munmap, addr, len); |
247 | | #else |
248 | | return munmap (addr, len); |
249 | | #endif |
250 | 47.2k | } Unexecuted instantiation: Lget_proc_name.c:mi_munmap Unexecuted instantiation: Lget_reg.c:mi_munmap Unexecuted instantiation: Lget_save_loc.c:mi_munmap Unexecuted instantiation: Linit_local.c:mi_munmap Unexecuted instantiation: Los-linux.c:mi_munmap Unexecuted instantiation: Lput_dynamic_unwind_info.c:mi_munmap Unexecuted instantiation: Lregs.c:mi_munmap Unexecuted instantiation: Lstep.c:mi_munmap Unexecuted instantiation: Lfind_dynamic_proc_info.c:mi_munmap Unexecuted instantiation: Lfind_proc_info-lsb.c:mi_munmap Unexecuted instantiation: Lget_accessors.c:mi_munmap Unexecuted instantiation: Lglobal.c:mi_munmap Unexecuted instantiation: Linit.c:mi_munmap Unexecuted instantiation: Lparser.c:mi_munmap Unexecuted instantiation: Lpe.c:mi_munmap Unexecuted instantiation: Lresume.c:mi_munmap Unexecuted instantiation: Lstash_frame.c:mi_munmap Unexecuted instantiation: dyn-info-list.c:mi_munmap Line | Count | Source | 244 | 23.6k | { | 245 | 23.6k | #ifdef SYS_munmap | 246 | 23.6k | return syscall (SYS_munmap, addr, len); | 247 | | #else | 248 | | return munmap (addr, len); | 249 | | #endif | 250 | 23.6k | } |
Unexecuted instantiation: flush_cache.c:mi_munmap Unexecuted instantiation: global.c:mi_munmap Unexecuted instantiation: init.c:mi_munmap Unexecuted instantiation: is_fpreg.c:mi_munmap Unexecuted instantiation: mempool.c:mi_munmap Line | Count | Source | 244 | 23.6k | { | 245 | 23.6k | #ifdef SYS_munmap | 246 | 23.6k | return syscall (SYS_munmap, addr, len); | 247 | | #else | 248 | | return munmap (addr, len); | 249 | | #endif | 250 | 23.6k | } |
Unexecuted instantiation: Laddress_validator.c:mi_munmap Unexecuted instantiation: Ldyn-extract.c:mi_munmap Unexecuted instantiation: Lexpr.c:mi_munmap Unexecuted instantiation: Lfde.c:mi_munmap |
251 | | |
252 | | #ifndef MAP_ANONYMOUS |
253 | | # define MAP_ANONYMOUS MAP_ANON |
254 | | #endif |
255 | 23.6k | #define GET_MEMORY(mem, size) \ |
256 | 23.6k | do { \ |
257 | 23.6k | mem = mi_mmap (NULL, size, PROT_READ | PROT_WRITE, \ |
258 | 23.6k | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ |
259 | 23.6k | if (mem == MAP_FAILED) \ |
260 | 23.6k | mem = NULL; \ |
261 | 23.6k | } while (0) |
262 | | |
263 | 23.6k | #define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info) |
264 | 0 | #define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info) |
265 | 0 | #define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info) |
266 | | #define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info) |
267 | | #define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info) |
268 | | #define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache) |
269 | | |
270 | | extern int unwi_find_dynamic_proc_info (unw_addr_space_t as, |
271 | | unw_word_t ip, |
272 | | unw_proc_info_t *pi, |
273 | | int need_unwind_info, void *arg); |
274 | | extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as, |
275 | | unw_word_t ip, |
276 | | unw_proc_info_t *pi, |
277 | | unw_dyn_info_t *di, |
278 | | int need_unwind_info, |
279 | | void *arg); |
280 | | extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as, |
281 | | unw_proc_info_t *pi, void *arg); |
282 | | |
283 | | /* These handle the remote (cross-address-space) case of accessing |
284 | | dynamic unwind info. */ |
285 | | |
286 | | extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as, |
287 | | unw_word_t ip, |
288 | | unw_proc_info_t *pi, |
289 | | int need_unwind_info, |
290 | | void *arg); |
291 | | extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, |
292 | | unw_proc_info_t *pi, |
293 | | void *arg); |
294 | | extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg); |
295 | | |
296 | | extern unw_dyn_info_list_t _U_dyn_info_list; |
297 | | extern pthread_mutex_t _U_dyn_info_list_lock; |
298 | | |
299 | | #define unw_address_is_valid UNWI_ARCH_OBJ(address_is_valid) |
300 | | HIDDEN bool unw_address_is_valid(unw_word_t, size_t); |
301 | | |
302 | | |
303 | | #if defined(UNW_DEBUG) |
304 | | # define unwi_debug_level UNWI_ARCH_OBJ(debug_level) |
305 | | extern long unwi_debug_level; |
306 | | |
307 | | # include <stdarg.h> |
308 | | # include <stdio.h> |
309 | | # include <unistd.h> |
310 | | |
311 | | #define Debug(level, ...) _unw_debug(level, __FUNCTION__, __VA_ARGS__) |
312 | | |
313 | | /** |
314 | | * Send a debug message to stderr. |
315 | | * |
316 | | * This function may be called from within a signal handler context where |
317 | | * fprintf(3) is not safe to call. The write(2) call is safe, however, and we're |
318 | | * going to have to assume that snprintf(3) is signal safe otherwise it's pretty |
319 | | * pointless to use Debug() calls anywhere. |
320 | | */ |
321 | | static inline void _unw_debug(int level, char const * const fname, char const * const fmt, ...) |
322 | | { |
323 | | if (unwi_debug_level >= level) |
324 | | { |
325 | | enum { buf_size = 512 }; |
326 | | char buf[buf_size]; |
327 | | |
328 | | if (level > 16) level = 16; |
329 | | int bcount = snprintf (buf, buf_size, "%*c>%s: ", level, ' ', fname); |
330 | | ssize_t res = write(STDERR_FILENO, buf, bcount); |
331 | | |
332 | | va_list ap; |
333 | | va_start(ap, fmt); |
334 | | bcount = vsnprintf (buf, buf_size, fmt, ap); |
335 | | va_end(ap); |
336 | | res = write(STDERR_FILENO, buf, bcount); |
337 | | (void)res; /* silence "variable set but not used" warning */ |
338 | | } |
339 | | } |
340 | | # define Dprintf(/* format */ ...) \ |
341 | | fprintf (stderr, /* format */ __VA_ARGS__) |
342 | | #else /* defined(UNW_DEBUG) */ |
343 | | # define Debug(level, /* format */ ...) |
344 | | # define Dprintf( /* format */ ...) |
345 | | #endif /* defined(UNW_DEBUG) */ |
346 | | |
347 | | static ALWAYS_INLINE ssize_t |
348 | | print_error (const char *string) |
349 | 0 | { |
350 | 0 | return write (2, string, strlen (string)); |
351 | 0 | } Unexecuted instantiation: Lget_proc_name.c:print_error Unexecuted instantiation: Lget_reg.c:print_error Unexecuted instantiation: Lget_save_loc.c:print_error Unexecuted instantiation: Linit_local.c:print_error Unexecuted instantiation: Los-linux.c:print_error Unexecuted instantiation: Lput_dynamic_unwind_info.c:print_error Unexecuted instantiation: Lregs.c:print_error Unexecuted instantiation: Lstep.c:print_error Unexecuted instantiation: Lfind_dynamic_proc_info.c:print_error Unexecuted instantiation: Lfind_proc_info-lsb.c:print_error Unexecuted instantiation: Lget_accessors.c:print_error Unexecuted instantiation: Lglobal.c:print_error Unexecuted instantiation: Linit.c:print_error Unexecuted instantiation: Lparser.c:print_error Unexecuted instantiation: Lpe.c:print_error Unexecuted instantiation: Lresume.c:print_error Unexecuted instantiation: Lstash_frame.c:print_error Unexecuted instantiation: dyn-info-list.c:print_error Unexecuted instantiation: elf64.c:print_error Unexecuted instantiation: flush_cache.c:print_error Unexecuted instantiation: global.c:print_error Unexecuted instantiation: init.c:print_error Unexecuted instantiation: is_fpreg.c:print_error Unexecuted instantiation: mempool.c:print_error Unexecuted instantiation: os-linux.c:print_error Unexecuted instantiation: Laddress_validator.c:print_error Unexecuted instantiation: Ldyn-extract.c:print_error Unexecuted instantiation: Lexpr.c:print_error Unexecuted instantiation: Lfde.c:print_error |
352 | | |
353 | | HIDDEN extern long unw_page_size; |
354 | | |
355 | | static inline unw_word_t unw_page_start(unw_word_t addr) |
356 | 180k | { |
357 | 180k | return addr & ~(unw_page_size - 1); |
358 | 180k | } Unexecuted instantiation: Lget_proc_name.c:unw_page_start Unexecuted instantiation: Lget_reg.c:unw_page_start Unexecuted instantiation: Lget_save_loc.c:unw_page_start Unexecuted instantiation: Linit_local.c:unw_page_start Unexecuted instantiation: Los-linux.c:unw_page_start Unexecuted instantiation: Lput_dynamic_unwind_info.c:unw_page_start Unexecuted instantiation: Lregs.c:unw_page_start Unexecuted instantiation: Lstep.c:unw_page_start Unexecuted instantiation: Lfind_dynamic_proc_info.c:unw_page_start Unexecuted instantiation: Lfind_proc_info-lsb.c:unw_page_start Unexecuted instantiation: Lget_accessors.c:unw_page_start Unexecuted instantiation: Lglobal.c:unw_page_start Unexecuted instantiation: Linit.c:unw_page_start Unexecuted instantiation: Lparser.c:unw_page_start Unexecuted instantiation: Lpe.c:unw_page_start Unexecuted instantiation: Lresume.c:unw_page_start Unexecuted instantiation: Lstash_frame.c:unw_page_start Unexecuted instantiation: dyn-info-list.c:unw_page_start Unexecuted instantiation: elf64.c:unw_page_start Unexecuted instantiation: flush_cache.c:unw_page_start Unexecuted instantiation: global.c:unw_page_start Unexecuted instantiation: init.c:unw_page_start Unexecuted instantiation: is_fpreg.c:unw_page_start Unexecuted instantiation: mempool.c:unw_page_start Unexecuted instantiation: os-linux.c:unw_page_start Laddress_validator.c:unw_page_start Line | Count | Source | 356 | 180k | { | 357 | 180k | return addr & ~(unw_page_size - 1); | 358 | 180k | } |
Unexecuted instantiation: Ldyn-extract.c:unw_page_start Unexecuted instantiation: Lexpr.c:unw_page_start Unexecuted instantiation: Lfde.c:unw_page_start |
359 | | |
360 | 1 | #define mi_init UNWI_ARCH_OBJ(mi_init) |
361 | | |
362 | | extern void mi_init (void); /* machine-independent initializations */ |
363 | | extern unw_word_t _U_dyn_info_list_addr (void); |
364 | | |
365 | | /* This is needed/used by ELF targets only. */ |
366 | | |
367 | | struct elf_image |
368 | | { |
369 | | void *image; /* pointer to mmap'd image */ |
370 | | size_t size; /* (file-) size of the image */ |
371 | | }; |
372 | | |
373 | | struct elf_dyn_info |
374 | | { |
375 | | struct elf_image ei; |
376 | | unw_dyn_info_t di_cache; |
377 | | unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ |
378 | | #if UNW_TARGET_IA64 |
379 | | unw_dyn_info_t ktab; |
380 | | #endif |
381 | | #if UNW_TARGET_ARM |
382 | | unw_dyn_info_t di_arm; /* additional table info for .ARM.exidx */ |
383 | | #endif |
384 | | }; |
385 | | |
386 | | static inline void invalidate_edi (struct elf_dyn_info *edi) |
387 | 0 | { |
388 | 0 | if (edi->ei.image) |
389 | 0 | mi_munmap (edi->ei.image, edi->ei.size); |
390 | 0 | memset (edi, 0, sizeof (*edi)); |
391 | 0 | edi->di_cache.format = -1; |
392 | 0 | edi->di_debug.format = -1; |
393 | 0 | #if UNW_TARGET_ARM |
394 | 0 | edi->di_arm.format = -1; |
395 | 0 | #endif |
396 | 0 | } Unexecuted instantiation: Lget_proc_name.c:invalidate_edi Unexecuted instantiation: Lget_reg.c:invalidate_edi Unexecuted instantiation: Lget_save_loc.c:invalidate_edi Unexecuted instantiation: Linit_local.c:invalidate_edi Unexecuted instantiation: Los-linux.c:invalidate_edi Unexecuted instantiation: Lput_dynamic_unwind_info.c:invalidate_edi Unexecuted instantiation: Lregs.c:invalidate_edi Unexecuted instantiation: Lstep.c:invalidate_edi Unexecuted instantiation: Lfind_dynamic_proc_info.c:invalidate_edi Unexecuted instantiation: Lfind_proc_info-lsb.c:invalidate_edi Unexecuted instantiation: Lget_accessors.c:invalidate_edi Unexecuted instantiation: Lglobal.c:invalidate_edi Unexecuted instantiation: Linit.c:invalidate_edi Unexecuted instantiation: Lparser.c:invalidate_edi Unexecuted instantiation: Lpe.c:invalidate_edi Unexecuted instantiation: Lresume.c:invalidate_edi Unexecuted instantiation: Lstash_frame.c:invalidate_edi Unexecuted instantiation: dyn-info-list.c:invalidate_edi Unexecuted instantiation: elf64.c:invalidate_edi Unexecuted instantiation: flush_cache.c:invalidate_edi Unexecuted instantiation: global.c:invalidate_edi Unexecuted instantiation: init.c:invalidate_edi Unexecuted instantiation: is_fpreg.c:invalidate_edi Unexecuted instantiation: mempool.c:invalidate_edi Unexecuted instantiation: os-linux.c:invalidate_edi Unexecuted instantiation: Laddress_validator.c:invalidate_edi Unexecuted instantiation: Ldyn-extract.c:invalidate_edi Unexecuted instantiation: Lexpr.c:invalidate_edi Unexecuted instantiation: Lfde.c:invalidate_edi |
397 | | |
398 | | |
399 | | /* Provide a place holder for architecture to override for fast access |
400 | | to memory when known not to need to validate and know the access |
401 | | will be local to the process. A suitable override will improve |
402 | | unw_tdep_trace() performance in particular. */ |
403 | | #define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ |
404 | | do { (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); } \ |
405 | | while (0) |
406 | | |
407 | | /* Define GNU and processor specific values for the Phdr p_type field in case |
408 | | they aren't defined by <elf.h>. */ |
409 | | #ifndef PT_GNU_EH_FRAME |
410 | | # define PT_GNU_EH_FRAME 0x6474e550 |
411 | | #endif /* !PT_GNU_EH_FRAME */ |
412 | | #ifndef PT_ARM_EXIDX |
413 | | # define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */ |
414 | | #endif /* !PT_ARM_EXIDX */ |
415 | | |
416 | 104k | #define DWARF_GET_MEM_LOC(l) DWARF_GET_LOC(l) |
417 | 0 | #define DWARF_GET_REG_LOC(l) ((unw_regnum_t) DWARF_GET_LOC(l)) |
418 | | |
419 | | #include "tdep/libunwind_i.h" |
420 | | |
421 | | #ifndef TDEP_DWARF_SP |
422 | 58.7k | #define TDEP_DWARF_SP UNW_TDEP_SP |
423 | | #endif |
424 | | |
425 | | #ifndef tdep_get_func_addr |
426 | 89.3M | # define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0) |
427 | | #endif |
428 | | |
429 | | #ifndef DWARF_VAL_LOC |
430 | | # define DWARF_IS_VAL_LOC(l) 0 |
431 | | # define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC |
432 | | #endif |
433 | | |
434 | 53.1k | #define UNW_ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) |
435 | | |
436 | | #endif /* libunwind_i_h */ |