15 #ifdef HAVE_LINUX_UNWIND_BACKTRACE
27 const void* _Unwind_Find_FDE (
void*,
void*);
28 void __register_frame_info (
const void*,
void*);
29 void __deregister_frame_info (
const void*);
38 using ubyte =
unsigned char;
44 DW_EH_PE_absptr = 0x00
50 DW_CFA_advance_loc = 0x40,
52 DW_CFA_restore = 0xc0,
56 DW_CFA_set_loc = 0x01,
57 DW_CFA_advance_loc1 = 0x02,
58 DW_CFA_advance_loc2 = 0x03,
59 DW_CFA_advance_loc4 = 0x04,
60 DW_CFA_offset_extended = 0x05,
61 DW_CFA_restore_extended = 0x06,
62 DW_CFA_undefined = 0x07,
63 DW_CFA_same_value = 0x08,
64 DW_CFA_register = 0x09,
65 DW_CFA_remember_state = 0x0a,
66 DW_CFA_restore_state = 0x0b,
67 DW_CFA_def_cfa = 0x0c,
68 DW_CFA_def_cfa_register = 0x0d,
70 DW_CFA_def_cfa_offset = 0x0e,
71 DW_CFA_def_cfa_expression = 0x0f,
72 DW_CFA_expression = 0x10,
73 DW_CFA_offset_extended_sf = 0x11,
74 DW_CFA_def_cfa_sf = 0x12,
75 DW_CFA_def_cfa_offset_sf = 0x13,
76 DW_CFA_val_offset = 0x14,
77 DW_CFA_val_offset_sf = 0x15,
78 DW_CFA_val_expression = 0x16,
80 DW_CFA_low_user = 0x1c,
81 DW_CFA_MIPS_advance_loc8 = 0x1d,
82 DW_CFA_GNU_window_save = 0x2d,
83 DW_CFA_GNU_args_size = 0x2e,
84 DW_CFA_GNU_negative_offset_extended = 0x2f,
85 DW_CFA_high_user = 0x3f
119 unsigned char augmentation[1] = {0};
120 ubyte address_size =
sizeof(
void*);
121 ubyte segment_size = 0;
122 ubyte code_alignment_factor = 1;
123 ubyte data_alignment_factor = 0x78;
124 ubyte return_address_register = REG_RA;
132 ubyte insns[9] = {DW_CFA_def_cfa, REG_RSP, 8,
133 DW_CFA_offset + REG_RA, 1,
134 DW_CFA_nop,DW_CFA_nop,DW_CFA_nop,DW_CFA_nop};
148 struct SynthFDEVector
150 const void* orig_data =
nullptr;
152 const struct SynthFDE*
array[1] = {
nullptr};
162 const SynthFDE* single;
163 SynthFDEVector*
sort;
167 unsigned long from_aray : 1;
168 unsigned long mixed_encoding : 1;
170 unsigned long count : 21;
188 SynthData() :
vec (reinterpret_cast<SynthFDEVector*>(
malloc (sizeof (SynthFDEVector)))) {}
189 ~SynthData() {
if (
vec) free (
vec); }
190 SynthData (
const SynthData&) =
delete;
191 SynthData& operator= (
const SynthData&) =
delete;
209 bool tryUnwindFixup (_Unwind_Ptr addr)
212 static std::atomic<int> fixed = 0;
214 if (!fixed.compare_exchange_strong (
exp, 1)) {
219 SynthData&
data = synthData;
220 data.cie.length =
sizeof (
data.cie) -
sizeof (
data.cie.length);
221 data.fde.length =
sizeof (
data.fde) -
sizeof (
data.fde.length);
223 data.fde.CIE_delta =
reinterpret_cast<char*
>(&
data.fde.CIE_delta) -
reinterpret_cast<char*
>(&
data.cie.length);
224 data.fde.pc_begin = (
void*)addr;
225 data.fde.pc_range = 8;
229 __register_frame_info (&
data.fde, &
data.ob);
238 std::atomic_thread_fence (std::memory_order_seq_cst);
242 std::atomic_thread_fence (std::memory_order_seq_cst);
245 data.ob.b.encoding = DW_EH_PE_absptr;
246 data.ob.pc_begin =
data.fde.pc_begin;
248 std::atomic_thread_fence (std::memory_order_seq_cst);
249 data.ob.b.sorted = 1;
259 struct dwarf_eh_bases
268 struct UnwindBacktraceData
270 static constexpr
unsigned MAX_DEPTH = 128;
272 _Unwind_Ptr addrs[MAX_DEPTH] = {0};
284 unwindBacktraceCallback (_Unwind_Context *ctx,
void *data_in)
287 auto&
data = *
reinterpret_cast<UnwindBacktraceData*
> (data_in);
288 _Unwind_Ptr
ip = _Unwind_GetIP (ctx);
291 if (
ip == 0 && !
data.sawBad) {
293 _Unwind_Word cfa = _Unwind_GetCFA (ctx);
295 void*
x = *
reinterpret_cast<void**
>(cfa);
297 dwarf_eh_bases bases;
298 if (_Unwind_Find_FDE (
x, &bases) !=
nullptr) {
300 return _URC_END_OF_STACK;
307 dwarf_eh_bases bases;
308 if (!
data.sawBad && _Unwind_Find_FDE (
reinterpret_cast<void*
>(
ip), &bases) ==
nullptr)
311 return _URC_END_OF_STACK;
316 if (
data.naddr == UnwindBacktraceData::MAX_DEPTH)
317 return _URC_END_OF_STACK;
319 return _URC_NO_REASON;
329 void backtraceByUnwind (backtraceLineFn* lineFn,
IOFD fd)
332 UnwindBacktraceData
data;
333 _Unwind_Backtrace (unwindBacktraceCallback, &
data);
337 if (
data.sawBad && tryUnwindFixup (
data.addrs[
data.naddr-1])) {
339 _Unwind_Backtrace (unwindBacktraceCallback, &
data);
347 for (
unsigned i = 0;
i <
data.naddr;
i++) {
364 CxxUtils::SynthData
data;
365 data.cie.length =
sizeof (
data.cie) -
sizeof (
data.cie.length);
366 data.fde.length =
sizeof (
data.fde) -
sizeof (
data.fde.length);
368 data.fde.CIE_delta =
reinterpret_cast<char*
>(&
data.fde.CIE_delta) -
reinterpret_cast<char*
>(&
data.cie.length);
370 data.fde.pc_range = 8;
373 __register_frame_info (&
data.fde, &
data.ob);
374 __deregister_frame_info (&
data.fde);
377 const static bool initUnwindFlag = initUnwind();