/src/libunwind/include/libunwind_i.h
Line | Count | Source |
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 | | #if defined(HAVE_THREADS_H) |
62 | | # include <threads.h> |
63 | | #endif |
64 | | |
65 | | #if defined(HAVE_SYS_SYSCALL_H) |
66 | | # include <sys/syscall.h> /* For SYS_xxx definitions */ |
67 | | #endif |
68 | | |
69 | | #if defined(HAVE_ELF_H) |
70 | | # include <elf.h> |
71 | | #elif defined(HAVE_SYS_ELF_H) |
72 | | # include <sys/elf.h> |
73 | | #else |
74 | | # error Could not locate <elf.h> |
75 | | #endif |
76 | | #if defined(ELFCLASS32) |
77 | | # define UNW_ELFCLASS32 ELFCLASS32 |
78 | | #else |
79 | | # define UNW_ELFCLASS32 1 |
80 | | #endif |
81 | | #if defined(ELFCLASS64) |
82 | 256k | # define UNW_ELFCLASS64 ELFCLASS64 |
83 | | #else |
84 | | # define UNW_ELFCLASS64 2 |
85 | | #endif |
86 | | |
87 | | #if defined(HAVE_ENDIAN_H) |
88 | | # include <endian.h> |
89 | | #elif defined(HAVE_SYS_ENDIAN_H) |
90 | | # include <sys/endian.h> |
91 | | #elif defined(HAVE_SYS_PARAM_H) |
92 | | # include <sys/param.h> |
93 | | #endif |
94 | | |
95 | | #if defined(__LITTLE_ENDIAN) |
96 | | # define UNW_LITTLE_ENDIAN __LITTLE_ENDIAN |
97 | | #elif defined(_LITTLE_ENDIAN) |
98 | | # define UNW_LITTLE_ENDIAN _LITTLE_ENDIAN |
99 | | #elif defined(LITTLE_ENDIAN) |
100 | | # define UNW_LITTLE_ENDIAN LITTLE_ENDIAN |
101 | | #else |
102 | | # define UNW_LITTLE_ENDIAN 1234 |
103 | | #endif |
104 | | |
105 | | #if defined(__BIG_ENDIAN) |
106 | | # define UNW_BIG_ENDIAN __BIG_ENDIAN |
107 | | #elif defined(_BIG_ENDIAN) |
108 | | # define UNW_BIG_ENDIAN _BIG_ENDIAN |
109 | | #elif defined(BIG_ENDIAN) |
110 | | # define UNW_BIG_ENDIAN BIG_ENDIAN |
111 | | #else |
112 | | # define UNW_BIG_ENDIAN 4321 |
113 | | #endif |
114 | | |
115 | | #if defined(__BYTE_ORDER) |
116 | | # define UNW_BYTE_ORDER __BYTE_ORDER |
117 | | #elif defined(_BYTE_ORDER) |
118 | | # define UNW_BYTE_ORDER _BYTE_ORDER |
119 | | #elif defined(BIG_ENDIAN) |
120 | | # define UNW_BYTE_ORDER BYTE_ORDER |
121 | | #else |
122 | | # if defined(__hpux) |
123 | | # define UNW_BYTE_ORDER UNW_BIG_ENDIAN |
124 | | # else |
125 | | # error Target has unknown byte ordering. |
126 | | # endif |
127 | | #endif |
128 | | |
129 | | static inline int |
130 | | byte_order_is_valid(int byte_order) |
131 | 0 | { |
132 | 0 | return byte_order == UNW_BIG_ENDIAN |
133 | 0 | || byte_order == UNW_LITTLE_ENDIAN; |
134 | 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 |
135 | | |
136 | | static inline int |
137 | | byte_order_is_big_endian(int byte_order) |
138 | 0 | { |
139 | 0 | return byte_order == UNW_BIG_ENDIAN; |
140 | 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 |
141 | | |
142 | | static inline int |
143 | | target_is_big_endian(void) |
144 | 0 | { |
145 | 0 | return byte_order_is_big_endian(UNW_BYTE_ORDER); |
146 | 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 |
147 | | |
148 | | #if defined(HAVE_C23_UNREACHABLE) |
149 | | # include <stddef.h> |
150 | | #elif defined(HAVE__BUILTIN_UNREACHABLE) |
151 | | # define unreachable() __builtin_unreachable() |
152 | | #else |
153 | | # define unreachable() do { } while (1) |
154 | | #endif |
155 | | |
156 | | /* Make it easy to write thread-safe code which may or may not be |
157 | | linked against libpthread. The macros below can be used |
158 | | unconditionally and if -lpthread is around, they'll call the |
159 | | corresponding routines otherwise, they do nothing. */ |
160 | | |
161 | | #pragma weak pthread_mutex_init |
162 | | #pragma weak pthread_mutex_lock |
163 | | #pragma weak pthread_mutex_unlock |
164 | | #pragma weak pthread_sigmask |
165 | | |
166 | | #define mutex_init(l) \ |
167 | 2 | (pthread_mutex_init != NULL ? pthread_mutex_init ((l), NULL) : 0) |
168 | | #define mutex_lock(l) \ |
169 | 57.1k | (pthread_mutex_lock != NULL ? pthread_mutex_lock (l) : 0) |
170 | | #define mutex_unlock(l) \ |
171 | 57.1k | (pthread_mutex_unlock != NULL ? pthread_mutex_unlock (l) : 0) |
172 | | |
173 | 32.0k | #define UNWI_OBJ(fn) UNW_PASTE(UNW_PREFIX,UNW_PASTE(I,fn)) |
174 | 34 | #define UNWI_ARCH_OBJ(fn) UNW_PASTE(UNW_PASTE(UNW_PASTE(_UI,UNW_TARGET),_), fn) |
175 | | |
176 | 1 | #define unwi_full_mask UNWI_ARCH_OBJ(full_mask) |
177 | | |
178 | | /* Type of a mask that can be used to inhibit preemption. At the |
179 | | userlevel, preemption is caused by signals and hence sigset_t is |
180 | | appropriate. In contrast, the Linux kernel uses "unsigned long" |
181 | | to hold the processor "flags" instead. */ |
182 | | typedef sigset_t intrmask_t; |
183 | | |
184 | | extern intrmask_t unwi_full_mask; |
185 | | |
186 | | /* Silence compiler warnings about variables which are used only if libunwind |
187 | | is configured in a certain way */ |
188 | 0 | static inline void mark_as_used(void *v UNUSED) { |
189 | 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 |
190 | | |
191 | | #if defined(CONFIG_BLOCK_SIGNALS) |
192 | | /* SIGPROCMASK ignores return values, so we do not have to correct for pthread_sigmask() returning |
193 | | errno on failure when sigprocmask() returns -1. */ |
194 | | # define SIGPROCMASK(how, new_mask, old_mask) \ |
195 | 114k | (pthread_sigmask != NULL ? pthread_sigmask((how), (new_mask), (old_mask)) \ |
196 | 114k | : sigprocmask((how), (new_mask), (old_mask))) |
197 | | #else |
198 | | # define SIGPROCMASK(how, new_mask, old_mask) mark_as_used(old_mask) |
199 | | #endif |
200 | | |
201 | | /* Prefer adaptive mutexes if available */ |
202 | | #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP |
203 | | #define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP |
204 | | #else |
205 | | #define UNW_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER |
206 | | #endif |
207 | | |
208 | | #define define_lock(name) \ |
209 | | pthread_mutex_t name = UNW_PTHREAD_MUTEX_INITIALIZER |
210 | 2 | #define lock_init(l) mutex_init (l) |
211 | 57.1k | #define lock_acquire(l,m) \ |
212 | 57.1k | do { \ |
213 | 57.1k | SIGPROCMASK (SIG_SETMASK, &unwi_full_mask, &(m)); \ |
214 | 57.1k | mutex_lock (l); \ |
215 | 57.1k | } while (0) |
216 | 57.1k | #define lock_release(l,m) \ |
217 | 57.1k | do { \ |
218 | 57.1k | mutex_unlock (l); \ |
219 | 57.1k | SIGPROCMASK (SIG_SETMASK, &(m), NULL); \ |
220 | 57.1k | } while (0) |
221 | | |
222 | | #define SOS_MEMORY_SIZE 16384 /* see src/mi/mempool.c */ |
223 | | |
224 | | /* Provide an internal syscall version of mmap to improve signal safety. */ |
225 | | static ALWAYS_INLINE void * |
226 | | mi_mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset) |
227 | 64.1k | { |
228 | 64.1k | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) |
229 | | /* Where supported, bypass libc and invoke the syscall directly. */ |
230 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD |
231 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); |
232 | | # else |
233 | 64.1k | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); |
234 | 64.1k | # endif |
235 | | // @todo this is very likely Linux specific |
236 | 64.1k | if ((unsigned long int)ret > -4096UL) |
237 | 0 | return MAP_FAILED; |
238 | 64.1k | else |
239 | 64.1k | return (void *)ret; |
240 | | #else |
241 | | /* Where direct syscalls are not supported, forward to the libc call. */ |
242 | | return mmap (addr, len, prot, flags, fd, offset); |
243 | | #endif |
244 | 64.1k | } 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 | 227 | 2 | { | 228 | 2 | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) | 229 | | /* Where supported, bypass libc and invoke the syscall directly. */ | 230 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD | 231 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 232 | | # else | 233 | 2 | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 234 | 2 | # endif | 235 | | // @todo this is very likely Linux specific | 236 | 2 | if ((unsigned long int)ret > -4096UL) | 237 | 0 | return MAP_FAILED; | 238 | 2 | else | 239 | 2 | return (void *)ret; | 240 | | #else | 241 | | /* Where direct syscalls are not supported, forward to the libc call. */ | 242 | | return mmap (addr, len, prot, flags, fd, offset); | 243 | | #endif | 244 | 2 | } |
Line | Count | Source | 227 | 64.1k | { | 228 | 64.1k | #if defined(SYS_mmap) && !defined(__i386__) && !defined(__s390x__) | 229 | | /* Where supported, bypass libc and invoke the syscall directly. */ | 230 | | # if defined(__FreeBSD__) // prefer over syscall on *BSD | 231 | | long int ret = __syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 232 | | # else | 233 | 64.1k | long int ret = syscall (SYS_mmap, addr, len, prot, flags, fd, offset); | 234 | 64.1k | # endif | 235 | | // @todo this is very likely Linux specific | 236 | 64.1k | if ((unsigned long int)ret > -4096UL) | 237 | 0 | return MAP_FAILED; | 238 | 64.1k | else | 239 | 64.1k | return (void *)ret; | 240 | | #else | 241 | | /* Where direct syscalls are not supported, forward to the libc call. */ | 242 | | return mmap (addr, len, prot, flags, fd, offset); | 243 | | #endif | 244 | 64.1k | } |
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 |
245 | | |
246 | | /* Provide an internal syscall version of munmap to improve signal safety. */ |
247 | | static ALWAYS_INLINE int |
248 | | mi_munmap (void *addr, size_t len) |
249 | 64.1k | { |
250 | 64.1k | #ifdef SYS_munmap |
251 | 64.1k | return syscall (SYS_munmap, addr, len); |
252 | | #else |
253 | | return munmap (addr, len); |
254 | | #endif |
255 | 64.1k | } 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 | 249 | 32.0k | { | 250 | 32.0k | #ifdef SYS_munmap | 251 | 32.0k | return syscall (SYS_munmap, addr, len); | 252 | | #else | 253 | | return munmap (addr, len); | 254 | | #endif | 255 | 32.0k | } |
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 | 249 | 32.0k | { | 250 | 32.0k | #ifdef SYS_munmap | 251 | 32.0k | return syscall (SYS_munmap, addr, len); | 252 | | #else | 253 | | return munmap (addr, len); | 254 | | #endif | 255 | 32.0k | } |
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 |
256 | | |
257 | | #ifndef MAP_ANONYMOUS |
258 | | # define MAP_ANONYMOUS MAP_ANON |
259 | | #endif |
260 | 32.0k | #define GET_MEMORY(mem, size) \ |
261 | 32.0k | do { \ |
262 | 32.0k | mem = mi_mmap (NULL, size, PROT_READ | PROT_WRITE, \ |
263 | 32.0k | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ |
264 | 32.0k | if (mem == MAP_FAILED) \ |
265 | 32.0k | mem = NULL; \ |
266 | 32.0k | } while (0) |
267 | | |
268 | 32.0k | #define unwi_find_dynamic_proc_info UNWI_OBJ(find_dynamic_proc_info) |
269 | 0 | #define unwi_extract_dynamic_proc_info UNWI_OBJ(extract_dynamic_proc_info) |
270 | 0 | #define unwi_put_dynamic_unwind_info UNWI_OBJ(put_dynamic_unwind_info) |
271 | | #define unwi_dyn_remote_find_proc_info UNWI_OBJ(dyn_remote_find_proc_info) |
272 | | #define unwi_dyn_remote_put_unwind_info UNWI_OBJ(dyn_remote_put_unwind_info) |
273 | | #define unwi_dyn_validate_cache UNWI_OBJ(dyn_validate_cache) |
274 | | |
275 | | extern int unwi_find_dynamic_proc_info (unw_addr_space_t as, |
276 | | unw_word_t ip, |
277 | | unw_proc_info_t *pi, |
278 | | int need_unwind_info, void *arg); |
279 | | extern int unwi_extract_dynamic_proc_info (unw_addr_space_t as, |
280 | | unw_word_t ip, |
281 | | unw_proc_info_t *pi, |
282 | | unw_dyn_info_t *di, |
283 | | int need_unwind_info, |
284 | | void *arg); |
285 | | extern void unwi_put_dynamic_unwind_info (unw_addr_space_t as, |
286 | | unw_proc_info_t *pi, void *arg); |
287 | | |
288 | | /* These handle the remote (cross-address-space) case of accessing |
289 | | dynamic unwind info. */ |
290 | | |
291 | | extern int unwi_dyn_remote_find_proc_info (unw_addr_space_t as, |
292 | | unw_word_t ip, |
293 | | unw_proc_info_t *pi, |
294 | | int need_unwind_info, |
295 | | void *arg); |
296 | | extern void unwi_dyn_remote_put_unwind_info (unw_addr_space_t as, |
297 | | unw_proc_info_t *pi, |
298 | | void *arg); |
299 | | extern int unwi_dyn_validate_cache (unw_addr_space_t as, void *arg); |
300 | | |
301 | | extern unw_dyn_info_list_t _U_dyn_info_list; |
302 | | extern pthread_mutex_t _U_dyn_info_list_lock; |
303 | | |
304 | | #define unw_address_is_valid UNWI_ARCH_OBJ(address_is_valid) |
305 | | HIDDEN bool unw_address_is_valid(unw_word_t, size_t); |
306 | | |
307 | | |
308 | | #if defined(UNW_DEBUG) |
309 | | # define unwi_debug_level UNWI_ARCH_OBJ(debug_level) |
310 | | extern long unwi_debug_level; |
311 | | |
312 | | # include <stdarg.h> |
313 | | # include <stdio.h> |
314 | | # include <unistd.h> |
315 | | |
316 | | #define Debug(level, ...) _unw_debug(level, __FUNCTION__, __VA_ARGS__) |
317 | | |
318 | | /** |
319 | | * Send a debug message to stderr. |
320 | | * |
321 | | * This function may be called from within a signal handler context where |
322 | | * fprintf(3) is not safe to call. The write(2) call is safe, however, and we're |
323 | | * going to have to assume that snprintf(3) is signal safe otherwise it's pretty |
324 | | * pointless to use Debug() calls anywhere. |
325 | | */ |
326 | | static inline void _unw_debug(int level, char const * const fname, char const * const fmt, ...) |
327 | | { |
328 | | if (unwi_debug_level >= level) |
329 | | { |
330 | | enum { buf_size = 512 }; |
331 | | char buf[buf_size]; |
332 | | |
333 | | if (level > 16) level = 16; |
334 | | int bcount = snprintf (buf, buf_size, "%*c>%s: ", level, ' ', fname); |
335 | | ssize_t res = write(STDERR_FILENO, buf, bcount); |
336 | | |
337 | | va_list ap; |
338 | | va_start(ap, fmt); |
339 | | bcount = vsnprintf (buf, buf_size, fmt, ap); |
340 | | va_end(ap); |
341 | | res = write(STDERR_FILENO, buf, bcount); |
342 | | (void)res; /* silence "variable set but not used" warning */ |
343 | | } |
344 | | } |
345 | | # define Dprintf(/* format */ ...) \ |
346 | | fprintf (stderr, /* format */ __VA_ARGS__) |
347 | | #else /* defined(UNW_DEBUG) */ |
348 | | # define Debug(level, /* format */ ...) |
349 | | # define Dprintf( /* format */ ...) |
350 | | #endif /* defined(UNW_DEBUG) */ |
351 | | |
352 | | static ALWAYS_INLINE ssize_t |
353 | | print_error (const char *string) |
354 | 0 | { |
355 | 0 | return write (2, string, strlen (string)); |
356 | 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 |
357 | | |
358 | | HIDDEN extern long unw_page_size; |
359 | | |
360 | | static inline unw_word_t unw_page_start(unw_word_t addr) |
361 | 208k | { |
362 | 208k | return addr & ~(unw_page_size - 1); |
363 | 208k | } 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 | 361 | 208k | { | 362 | 208k | return addr & ~(unw_page_size - 1); | 363 | 208k | } |
Unexecuted instantiation: Ldyn-extract.c:unw_page_start Unexecuted instantiation: Lexpr.c:unw_page_start Unexecuted instantiation: Lfde.c:unw_page_start |
364 | | |
365 | 1 | #define mi_init UNWI_ARCH_OBJ(mi_init) |
366 | | |
367 | | extern void mi_init (void); /* machine-independent initializations */ |
368 | | extern unw_word_t _U_dyn_info_list_addr (void); |
369 | | |
370 | | /* This is needed/used by ELF targets only. */ |
371 | | |
372 | | struct elf_image |
373 | | { |
374 | | void *image; /* pointer to mmap'd image */ |
375 | | size_t size; /* (file-) size of the image */ |
376 | | }; |
377 | | |
378 | | struct elf_dyn_info |
379 | | { |
380 | | struct elf_image ei; |
381 | | unw_dyn_info_t di_cache; |
382 | | unw_dyn_info_t di_debug; /* additional table info for .debug_frame */ |
383 | | #if UNW_TARGET_IA64 |
384 | | unw_dyn_info_t ktab; |
385 | | #endif |
386 | | #if UNW_TARGET_ARM |
387 | | unw_dyn_info_t di_arm; /* additional table info for .ARM.exidx */ |
388 | | #endif |
389 | | }; |
390 | | |
391 | | static inline void invalidate_edi (struct elf_dyn_info *edi) |
392 | 0 | { |
393 | 0 | if (edi->ei.image) |
394 | 0 | mi_munmap (edi->ei.image, edi->ei.size); |
395 | 0 | memset (edi, 0, sizeof (*edi)); |
396 | 0 | edi->di_cache.format = -1; |
397 | 0 | edi->di_debug.format = -1; |
398 | 0 | #if UNW_TARGET_ARM |
399 | 0 | edi->di_arm.format = -1; |
400 | 0 | #endif |
401 | 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 |
402 | | |
403 | | |
404 | | /* Provide a place holder for architecture to override for fast access |
405 | | to memory when known not to need to validate and know the access |
406 | | will be local to the process. A suitable override will improve |
407 | | unw_tdep_trace() performance in particular. */ |
408 | | #define ACCESS_MEM_FAST(ret,validate,cur,addr,to) \ |
409 | | do { (ret) = dwarf_get ((cur), DWARF_MEM_LOC ((cur), (addr)), &(to)); } \ |
410 | | while (0) |
411 | | |
412 | | /* Define GNU and processor specific values for the Phdr p_type field in case |
413 | | they aren't defined by <elf.h>. */ |
414 | | #ifndef PT_GNU_EH_FRAME |
415 | | # define PT_GNU_EH_FRAME 0x6474e550 |
416 | | #endif /* !PT_GNU_EH_FRAME */ |
417 | | #ifndef PT_ARM_EXIDX |
418 | | # define PT_ARM_EXIDX 0x70000001 /* ARM unwind segment */ |
419 | | #endif /* !PT_ARM_EXIDX */ |
420 | | |
421 | 118k | #define DWARF_GET_MEM_LOC(l) DWARF_GET_LOC(l) |
422 | 0 | #define DWARF_GET_REG_LOC(l) ((unw_regnum_t) DWARF_GET_LOC(l)) |
423 | | |
424 | | #include "tdep/libunwind_i.h" |
425 | | |
426 | | #ifndef TDEP_DWARF_SP |
427 | 69.7k | #define TDEP_DWARF_SP UNW_TDEP_SP |
428 | | #endif |
429 | | |
430 | | #ifndef tdep_get_func_addr |
431 | 77.7M | # define tdep_get_func_addr(as,addr,v) (*(v) = addr, 0) |
432 | | #endif |
433 | | |
434 | | #ifndef DWARF_VAL_LOC |
435 | | # define DWARF_IS_VAL_LOC(l) 0 |
436 | | # define DWARF_VAL_LOC(c,v) DWARF_NULL_LOC |
437 | | #endif |
438 | | |
439 | 72.1k | #define UNW_ALIGN(x,a) (((size_t)(x) + (size_t)(a) - 1) & ~((size_t)(a) - 1)) |
440 | | |
441 | | #endif /* libunwind_i_h */ |