Coverage Report

Created: 2026-06-08 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
mempool.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
}
os-linux.c:mi_mmap
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
elf64.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
os-linux.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 */