authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-26 14:40:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-08 19:37:29-07:00
log6295415da72eb17b263494a070fdf957e89460fb
tree308c2c6341b137085dd9dc20168e2509572c2216
parenta6856ef6d21635641320761a8f17205fd6e99fa9

libunwind: update to LLVM 18

release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42

17 files changed, 389 insertions(+), 128 deletions(-)

lib/libunwind/include/__libunwind_config.h+4-1
...@@ -36,6 +36,9 @@...@@ -36,6 +36,9 @@
36# if defined(__linux__)36# if defined(__linux__)
37# define _LIBUNWIND_TARGET_LINUX 137# define _LIBUNWIND_TARGET_LINUX 1
38# endif38# endif
39# if defined(__HAIKU__)
40# define _LIBUNWIND_TARGET_HAIKU 1
41# endif
39# if defined(__i386__)42# if defined(__i386__)
40# define _LIBUNWIND_TARGET_I38643# define _LIBUNWIND_TARGET_I386
41# define _LIBUNWIND_CONTEXT_SIZE 844# define _LIBUNWIND_CONTEXT_SIZE 8
...@@ -196,7 +199,7 @@...@@ -196,7 +199,7 @@
196# define _LIBUNWIND_TARGET_RISCV 1199# define _LIBUNWIND_TARGET_RISCV 1
197# define _LIBUNWIND_TARGET_VE 1200# define _LIBUNWIND_TARGET_VE 1
198# define _LIBUNWIND_TARGET_S390X 1201# define _LIBUNWIND_TARGET_S390X 1
199 #define _LIBUNWIND_TARGET_LOONGARCH 1202# define _LIBUNWIND_TARGET_LOONGARCH 1
200# define _LIBUNWIND_CONTEXT_SIZE 167203# define _LIBUNWIND_CONTEXT_SIZE 167
201# define _LIBUNWIND_CURSOR_SIZE 204204# define _LIBUNWIND_CURSOR_SIZE 204
202# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287205# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
lib/libunwind/include/libunwind.h+3
...@@ -876,6 +876,9 @@ enum {...@@ -876,6 +876,9 @@ enum {
876 UNW_MIPS_F29 = 61,876 UNW_MIPS_F29 = 61,
877 UNW_MIPS_F30 = 62,877 UNW_MIPS_F30 = 62,
878 UNW_MIPS_F31 = 63,878 UNW_MIPS_F31 = 63,
879 // HI,LO have been dropped since r6, we keep them here.
880 // So, when we add DSP/MSA etc, we can use the same register indexes
881 // for r6 and pre-r6.
879 UNW_MIPS_HI = 64,882 UNW_MIPS_HI = 64,
880 UNW_MIPS_LO = 65,883 UNW_MIPS_LO = 65,
881};884};
lib/libunwind/include/mach-o/compact_unwind_encoding.h+40-40
...@@ -108,7 +108,7 @@ enum {...@@ -108,7 +108,7 @@ enum {
108// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.108// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
109// Each entry contains which register to restore.109// Each entry contains which register to restore.
110// UNWIND_X86_MODE_STACK_IMMD:110// UNWIND_X86_MODE_STACK_IMMD:
111// A "frameless" (EBP not used as frame pointer) function with a small 111// A "frameless" (EBP not used as frame pointer) function with a small
112// constant stack size. To return, a constant (encoded in the compact112// constant stack size. To return, a constant (encoded in the compact
113// unwind encoding) is added to the ESP. Then the return is done by113// unwind encoding) is added to the ESP. Then the return is done by
114// popping the stack into the pc.114// popping the stack into the pc.
...@@ -119,16 +119,16 @@ enum {...@@ -119,16 +119,16 @@ enum {
119// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were119// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
120// saved and their order.120// saved and their order.
121// UNWIND_X86_MODE_STACK_IND:121// UNWIND_X86_MODE_STACK_IND:
122// A "frameless" (EBP not used as frame pointer) function large constant 122// A "frameless" (EBP not used as frame pointer) function large constant
123// stack size. This case is like the previous, except the stack size is too123// stack size. This case is like the previous, except the stack size is too
124// large to encode in the compact unwind encoding. Instead it requires that 124// large to encode in the compact unwind encoding. Instead it requires that
125// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact 125// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
126// encoding contains the offset to the nnnnnnnn value in the function in126// encoding contains the offset to the nnnnnnnn value in the function in
127// UNWIND_X86_FRAMELESS_STACK_SIZE. 127// UNWIND_X86_FRAMELESS_STACK_SIZE.
128// UNWIND_X86_MODE_DWARF:128// UNWIND_X86_MODE_DWARF:
129// No compact unwind encoding is available. Instead the low 24-bits of the129// No compact unwind encoding is available. Instead the low 24-bits of the
130// compact encoding is the offset of the DWARF FDE in the __eh_frame section.130// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
131// This mode is never used in object files. It is only generated by the 131// This mode is never used in object files. It is only generated by the
132// linker in final linked images which have only DWARF unwind info for a132// linker in final linked images which have only DWARF unwind info for a
133// function.133// function.
134//134//
...@@ -233,36 +233,36 @@ enum {...@@ -233,36 +233,36 @@ enum {
233// For x86_64 there are four modes for the compact unwind encoding:233// For x86_64 there are four modes for the compact unwind encoding:
234// UNWIND_X86_64_MODE_RBP_FRAME:234// UNWIND_X86_64_MODE_RBP_FRAME:
235// RBP based frame where RBP is push on stack immediately after return address,235// RBP based frame where RBP is push on stack immediately after return address,
236// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current 236// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
237// EPB value, then RBP is restored by popping off the stack, and the return 237// EPB value, then RBP is restored by popping off the stack, and the return
238// is done by popping the stack once more into the pc.238// is done by popping the stack once more into the pc.
239// All non-volatile registers that need to be restored must have been saved239// All non-volatile registers that need to be restored must have been saved
240// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 240// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
241// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved241// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
242// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.242// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
243// Each entry contains which register to restore. 243// Each entry contains which register to restore.
244// UNWIND_X86_64_MODE_STACK_IMMD:244// UNWIND_X86_64_MODE_STACK_IMMD:
245// A "frameless" (RBP not used as frame pointer) function with a small 245// A "frameless" (RBP not used as frame pointer) function with a small
246// constant stack size. To return, a constant (encoded in the compact 246// constant stack size. To return, a constant (encoded in the compact
247// unwind encoding) is added to the RSP. Then the return is done by 247// unwind encoding) is added to the RSP. Then the return is done by
248// popping the stack into the pc.248// popping the stack into the pc.
249// All non-volatile registers that need to be restored must have been saved249// All non-volatile registers that need to be restored must have been saved
250// on the stack immediately after the return address. The stack_size/8 is250// on the stack immediately after the return address. The stack_size/8 is
251// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).251// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
252// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.252// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
253// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were253// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
254// saved and their order. 254// saved and their order.
255// UNWIND_X86_64_MODE_STACK_IND:255// UNWIND_X86_64_MODE_STACK_IND:
256// A "frameless" (RBP not used as frame pointer) function large constant 256// A "frameless" (RBP not used as frame pointer) function large constant
257// stack size. This case is like the previous, except the stack size is too257// stack size. This case is like the previous, except the stack size is too
258// large to encode in the compact unwind encoding. Instead it requires that 258// large to encode in the compact unwind encoding. Instead it requires that
259// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact 259// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
260// encoding contains the offset to the nnnnnnnn value in the function in260// encoding contains the offset to the nnnnnnnn value in the function in
261// UNWIND_X86_64_FRAMELESS_STACK_SIZE. 261// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
262// UNWIND_X86_64_MODE_DWARF:262// UNWIND_X86_64_MODE_DWARF:
263// No compact unwind encoding is available. Instead the low 24-bits of the263// No compact unwind encoding is available. Instead the low 24-bits of the
264// compact encoding is the offset of the DWARF FDE in the __eh_frame section.264// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
265// This mode is never used in object files. It is only generated by the 265// This mode is never used in object files. It is only generated by the
266// linker in final linked images which have only DWARF unwind info for a266// linker in final linked images which have only DWARF unwind info for a
267// function.267// function.
268//268//
...@@ -307,20 +307,20 @@ enum {...@@ -307,20 +307,20 @@ enum {
307// This is a standard arm64 prolog where FP/LR are immediately pushed on the307// This is a standard arm64 prolog where FP/LR are immediately pushed on the
308// stack, then SP is copied to FP. If there are any non-volatile registers308// stack, then SP is copied to FP. If there are any non-volatile registers
309// saved, then are copied into the stack frame in pairs in a contiguous309// saved, then are copied into the stack frame in pairs in a contiguous
310// range right below the saved FP/LR pair. Any subset of the five X pairs 310// range right below the saved FP/LR pair. Any subset of the five X pairs
311// and four D pairs can be saved, but the memory layout must be in register311// and four D pairs can be saved, but the memory layout must be in register
312// number order. 312// number order.
313// UNWIND_ARM64_MODE_FRAMELESS:313// UNWIND_ARM64_MODE_FRAMELESS:
314// A "frameless" leaf function, where FP/LR are not saved. The return address 314// A "frameless" leaf function, where FP/LR are not saved. The return address
315// remains in LR throughout the function. If any non-volatile registers315// remains in LR throughout the function. If any non-volatile registers
316// are saved, they must be pushed onto the stack before any stack space is316// are saved, they must be pushed onto the stack before any stack space is
317// allocated for local variables. The stack sized (including any saved317// allocated for local variables. The stack sized (including any saved
318// non-volatile registers) divided by 16 is encoded in the bits 318// non-volatile registers) divided by 16 is encoded in the bits
319// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.319// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
320// UNWIND_ARM64_MODE_DWARF:320// UNWIND_ARM64_MODE_DWARF:
321// No compact unwind encoding is available. Instead the low 24-bits of the321// No compact unwind encoding is available. Instead the low 24-bits of the
322// compact encoding is the offset of the DWARF FDE in the __eh_frame section.322// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
323// This mode is never used in object files. It is only generated by the 323// This mode is never used in object files. It is only generated by the
324// linker in final linked images which have only DWARF unwind info for a324// linker in final linked images which have only DWARF unwind info for a
325// function.325// function.
326//326//
...@@ -337,19 +337,19 @@ enum {...@@ -337,19 +337,19 @@ enum {
337337
338//338//
339// A compiler can generated compact unwind information for a function by adding339// A compiler can generated compact unwind information for a function by adding
340// a "row" to the __LD,__compact_unwind section. This section has the 340// a "row" to the __LD,__compact_unwind section. This section has the
341// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. 341// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
342// It is removed by the new linker, so never ends up in final executables. 342// It is removed by the new linker, so never ends up in final executables.
343// This section is a table, initially with one row per function (that needs 343// This section is a table, initially with one row per function (that needs
344// unwind info). The table columns and some conceptual entries are:344// unwind info). The table columns and some conceptual entries are:
345//345//
346// range-start pointer to start of function/range346// range-start pointer to start of function/range
347// range-length 347// range-length
348// compact-unwind-encoding 32-bit encoding 348// compact-unwind-encoding 32-bit encoding
349// personality-function or zero if no personality function349// personality-function or zero if no personality function
350// lsda or zero if no LSDA data350// lsda or zero if no LSDA data
351//351//
352// The length and encoding fields are 32-bits. The other are all pointer sized. 352// The length and encoding fields are 32-bits. The other are all pointer sized.
353//353//
354// In x86_64 assembly, these entry would look like:354// In x86_64 assembly, these entry would look like:
355//355//
...@@ -372,23 +372,23 @@ enum {...@@ -372,23 +372,23 @@ enum {
372// .quad except_tab1372// .quad except_tab1
373//373//
374//374//
375// Notes: There is no need for any labels in the the __compact_unwind section. 375// Notes: There is no need for any labels in the __compact_unwind section.
376// The use of the .set directive is to force the evaluation of the 376// The use of the .set directive is to force the evaluation of the
377// range-length at assembly time, instead of generating relocations.377// range-length at assembly time, instead of generating relocations.
378//378//
379// To support future compiler optimizations where which non-volatile registers 379// To support future compiler optimizations where which non-volatile registers
380// are saved changes within a function (e.g. delay saving non-volatiles until380// are saved changes within a function (e.g. delay saving non-volatiles until
381// necessary), there can by multiple lines in the __compact_unwind table for one381// necessary), there can by multiple lines in the __compact_unwind table for one
382// function, each with a different (non-overlapping) range and each with 382// function, each with a different (non-overlapping) range and each with
383// different compact unwind encodings that correspond to the non-volatiles 383// different compact unwind encodings that correspond to the non-volatiles
384// saved at that range of the function.384// saved at that range of the function.
385//385//
386// If a particular function is so wacky that there is no compact unwind way386// If a particular function is so wacky that there is no compact unwind way
387// to encode it, then the compiler can emit traditional DWARF unwind info. 387// to encode it, then the compiler can emit traditional DWARF unwind info.
388// The runtime will use which ever is available.388// The runtime will use which ever is available.
389//389//
390// Runtime support for compact unwind encodings are only available on 10.6 390// Runtime support for compact unwind encodings are only available on 10.6
391// and later. So, the compiler should not generate it when targeting pre-10.6. 391// and later. So, the compiler should not generate it when targeting pre-10.6.
392392
393393
394394
...@@ -402,7 +402,7 @@ enum {...@@ -402,7 +402,7 @@ enum {
402//402//
403// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.403// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
404// The header of the section contains a coarse index that maps function address404// The header of the section contains a coarse index that maps function address
405// to the page (4096 byte block) containing the unwind info for that function. 405// to the page (4096 byte block) containing the unwind info for that function.
406//406//
407407
408#define UNWIND_SECTION_VERSION 1408#define UNWIND_SECTION_VERSION 1
lib/libunwind/src/AddressSpace.hpp+4-3
...@@ -414,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,...@@ -414,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
414 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;414 cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
415 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;415 cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
416 if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(416 if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
417 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,417 *cbdata->addressSpace, eh_frame_hdr_start,
418 hdrInfo)) {418 eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) {
419 // .eh_frame_hdr records the start of .eh_frame, but not its size.419 // .eh_frame_hdr records the start of .eh_frame, but not its size.
420 // Rely on a zero terminator to find the end of the section.420 // Rely on a zero terminator to find the end of the section.
421 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;421 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
...@@ -638,7 +638,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,...@@ -638,7 +638,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
638 info.dwarf_index_section_length = SIZE_MAX;638 info.dwarf_index_section_length = SIZE_MAX;
639 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;639 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
640 if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(640 if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
641 *this, info.dwarf_index_section, info.dwarf_index_section_length,641 *this, info.dwarf_index_section,
642 info.dwarf_index_section + info.dwarf_index_section_length,
642 hdrInfo)) {643 hdrInfo)) {
643 return false;644 return false;
644 }645 }
lib/libunwind/src/DwarfInstructions.hpp+1-1
...@@ -68,7 +68,7 @@ private:...@@ -68,7 +68,7 @@ private:
68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69 prolog.cfaRegisterOffset);69 prolog.cfaRegisterOffset);
70 if (prolog.cfaExpression != 0)70 if (prolog.cfaExpression != 0)
71 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, 71 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72 registers, 0);72 registers, 0);
73 assert(0 && "getCFA(): unknown location");73 assert(0 && "getCFA(): unknown location");
74 __builtin_unreachable();74 __builtin_unreachable();
lib/libunwind/src/EHHeaderParser.hpp+13
...@@ -55,6 +55,19 @@ template <typename A>...@@ -55,6 +55,19 @@ template <typename A>
55bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,55bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
56 pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {56 pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
57 pint_t p = ehHdrStart;57 pint_t p = ehHdrStart;
58
59 // Ensure that we don't read data beyond the end of .eh_frame_hdr
60 if (ehHdrEnd - ehHdrStart < 4) {
61 // Don't print a message for an empty .eh_frame_hdr (this can happen if
62 // the linker script defines symbols for it even in the empty case).
63 if (ehHdrEnd == ehHdrStart)
64 return false;
65 _LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
66 ": need at least 4 bytes of data but only got %zd",
67 static_cast<uint64_t>(ehHdrStart),
68 static_cast<size_t>(ehHdrEnd - ehHdrStart));
69 return false;
70 }
58 uint8_t version = addressSpace.get8(p++);71 uint8_t version = addressSpace.get8(p++);
59 if (version != 1) {72 if (version != 1) {
60 _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,73 _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,
lib/libunwind/src/FrameHeaderCache.hpp+3-3
...@@ -31,8 +31,8 @@...@@ -31,8 +31,8 @@
3131
32class _LIBUNWIND_HIDDEN FrameHeaderCache {32class _LIBUNWIND_HIDDEN FrameHeaderCache {
33 struct CacheEntry {33 struct CacheEntry {
34 uintptr_t LowPC() { return Info.dso_base; };34 uintptr_t LowPC() { return Info.dso_base; }
35 uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; };35 uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }
36 UnwindInfoSections Info;36 UnwindInfoSections Info;
37 CacheEntry *Next;37 CacheEntry *Next;
38 };38 };
...@@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {...@@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {
4141
42 // Can't depend on the C++ standard library in libunwind, so use an array to42 // Can't depend on the C++ standard library in libunwind, so use an array to
43 // allocate the entries, and two linked lists for ordering unused and recently43 // allocate the entries, and two linked lists for ordering unused and recently
44 // used entries. FIXME: Would the the extra memory for a doubly-linked list44 // used entries. FIXME: Would the extra memory for a doubly-linked list
45 // be better than the runtime cost of traversing a very short singly-linked45 // be better than the runtime cost of traversing a very short singly-linked
46 // list on a cache miss? The entries themselves are all small and consecutive,46 // list on a cache miss? The entries themselves are all small and consecutive,
47 // so unlikely to cause page faults when following the pointers. The memory47 // so unlikely to cause page faults when following the pointers. The memory
lib/libunwind/src/Registers.hpp+18-2
...@@ -619,6 +619,8 @@ public:...@@ -619,6 +619,8 @@ public:
619 void setIP(uint32_t value) { _registers.__srr0 = value; }619 void setIP(uint32_t value) { _registers.__srr0 = value; }
620 uint64_t getCR() const { return _registers.__cr; }620 uint64_t getCR() const { return _registers.__cr; }
621 void setCR(uint32_t value) { _registers.__cr = value; }621 void setCR(uint32_t value) { _registers.__cr = value; }
622 uint64_t getLR() const { return _registers.__lr; }
623 void setLR(uint32_t value) { _registers.__lr = value; }
622624
623private:625private:
624 struct ppc_thread_state_t {626 struct ppc_thread_state_t {
...@@ -1189,6 +1191,8 @@ public:...@@ -1189,6 +1191,8 @@ public:
1189 void setIP(uint64_t value) { _registers.__srr0 = value; }1191 void setIP(uint64_t value) { _registers.__srr0 = value; }
1190 uint64_t getCR() const { return _registers.__cr; }1192 uint64_t getCR() const { return _registers.__cr; }
1191 void setCR(uint64_t value) { _registers.__cr = value; }1193 void setCR(uint64_t value) { _registers.__cr = value; }
1194 uint64_t getLR() const { return _registers.__lr; }
1195 void setLR(uint64_t value) { _registers.__lr = value; }
11921196
1193private:1197private:
1194 struct ppc64_thread_state_t {1198 struct ppc64_thread_state_t {
...@@ -2869,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {...@@ -2869,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
2869 return false;2873 return false;
2870 if (regNum <= UNW_MIPS_R31)2874 if (regNum <= UNW_MIPS_R31)
2871 return true;2875 return true;
2872#if __mips_isa_rev != 62876#if __mips_isa_rev < 6
2873 if (regNum == UNW_MIPS_HI)2877 if (regNum == UNW_MIPS_HI)
2874 return true;2878 return true;
2875 if (regNum == UNW_MIPS_LO)2879 if (regNum == UNW_MIPS_LO)
...@@ -2903,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {...@@ -2903,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
2903 return _registers.__pc;2907 return _registers.__pc;
2904 case UNW_REG_SP:2908 case UNW_REG_SP:
2905 return _registers.__r[29];2909 return _registers.__r[29];
2910#if __mips_isa_rev < 6
2906 case UNW_MIPS_HI:2911 case UNW_MIPS_HI:
2907 return _registers.__hi;2912 return _registers.__hi;
2908 case UNW_MIPS_LO:2913 case UNW_MIPS_LO:
2909 return _registers.__lo;2914 return _registers.__lo;
2915#endif
2910 }2916 }
2911 _LIBUNWIND_ABORT("unsupported mips_o32 register");2917 _LIBUNWIND_ABORT("unsupported mips_o32 register");
2912}2918}
...@@ -2936,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {...@@ -2936,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
2936 case UNW_REG_SP:2942 case UNW_REG_SP:
2937 _registers.__r[29] = value;2943 _registers.__r[29] = value;
2938 return;2944 return;
2945#if __mips_isa_rev < 6
2939 case UNW_MIPS_HI:2946 case UNW_MIPS_HI:
2940 _registers.__hi = value;2947 _registers.__hi = value;
2941 return;2948 return;
2942 case UNW_MIPS_LO:2949 case UNW_MIPS_LO:
2943 _registers.__lo = value;2950 _registers.__lo = value;
2951#endif
2944 return;2952 return;
2945 }2953 }
2946 _LIBUNWIND_ABORT("unsupported mips_o32 register");2954 _LIBUNWIND_ABORT("unsupported mips_o32 register");
...@@ -3120,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {...@@ -3120,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
3120 return "$f30";3128 return "$f30";
3121 case UNW_MIPS_F31:3129 case UNW_MIPS_F31:
3122 return "$f31";3130 return "$f31";
3131#if __mips_isa_rev < 6
3123 case UNW_MIPS_HI:3132 case UNW_MIPS_HI:
3124 return "$hi";3133 return "$hi";
3125 case UNW_MIPS_LO:3134 case UNW_MIPS_LO:
3126 return "$lo";3135 return "$lo";
3136#endif
3127 default:3137 default:
3128 return "unknown register";3138 return "unknown register";
3129 }3139 }
...@@ -3193,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {...@@ -3193,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {
3193 return false;3203 return false;
3194 if (regNum <= UNW_MIPS_R31)3204 if (regNum <= UNW_MIPS_R31)
3195 return true;3205 return true;
3196#if __mips_isa_rev != 63206#if __mips_isa_rev < 6
3197 if (regNum == UNW_MIPS_HI)3207 if (regNum == UNW_MIPS_HI)
3198 return true;3208 return true;
3199 if (regNum == UNW_MIPS_LO)3209 if (regNum == UNW_MIPS_LO)
...@@ -3212,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {...@@ -3212,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
3212 return _registers.__pc;3222 return _registers.__pc;
3213 case UNW_REG_SP:3223 case UNW_REG_SP:
3214 return _registers.__r[29];3224 return _registers.__r[29];
3225#if __mips_isa_rev < 6
3215 case UNW_MIPS_HI:3226 case UNW_MIPS_HI:
3216 return _registers.__hi;3227 return _registers.__hi;
3217 case UNW_MIPS_LO:3228 case UNW_MIPS_LO:
3218 return _registers.__lo;3229 return _registers.__lo;
3230#endif
3219 }3231 }
3220 _LIBUNWIND_ABORT("unsupported mips_newabi register");3232 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3221}3233}
...@@ -3233,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {...@@ -3233,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
3233 case UNW_REG_SP:3245 case UNW_REG_SP:
3234 _registers.__r[29] = value;3246 _registers.__r[29] = value;
3235 return;3247 return;
3248#if __mips_isa_rev < 6
3236 case UNW_MIPS_HI:3249 case UNW_MIPS_HI:
3237 _registers.__hi = value;3250 _registers.__hi = value;
3238 return;3251 return;
3239 case UNW_MIPS_LO:3252 case UNW_MIPS_LO:
3240 _registers.__lo = value;3253 _registers.__lo = value;
3241 return;3254 return;
3255#endif
3242 }3256 }
3243 _LIBUNWIND_ABORT("unsupported mips_newabi register");3257 _LIBUNWIND_ABORT("unsupported mips_newabi register");
3244}3258}
...@@ -3417,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {...@@ -3417,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
3417 return "$f30";3431 return "$f30";
3418 case UNW_MIPS_F31:3432 case UNW_MIPS_F31:
3419 return "$f31";3433 return "$f31";
3434#if __mips_isa_rev < 6
3420 case UNW_MIPS_HI:3435 case UNW_MIPS_HI:
3421 return "$hi";3436 return "$hi";
3422 case UNW_MIPS_LO:3437 case UNW_MIPS_LO:
3423 return "$lo";3438 return "$lo";
3439#endif
3424 default:3440 default:
3425 return "unknown register";3441 return "unknown register";
3426 }3442 }
lib/libunwind/src/Unwind-sjlj.c+6-5
...@@ -82,7 +82,8 @@ struct _Unwind_FunctionContext {...@@ -82,7 +82,8 @@ struct _Unwind_FunctionContext {
82static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;82static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
83#endif83#endif
8484
85static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {85static struct _Unwind_FunctionContext *
86__Unwind_SjLj_GetTopOfFunctionStack(void) {
86#if defined(__APPLE__)87#if defined(__APPLE__)
87 return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);88 return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
88#else89#else
...@@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,...@@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
426/// Called by personality handler during phase 2 to alter register values.427/// Called by personality handler during phase 2 to alter register values.
427_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,428_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
428 uintptr_t new_value) {429 uintptr_t new_value) {
429 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR430 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIxPTR
430 ")",431 ")",
431 (void *)context, index, new_value);432 (void *)context, index, new_value);
432 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;433 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
...@@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,...@@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
437/// Called by personality handler during phase 2 to get instruction pointer.438/// Called by personality handler during phase 2 to get instruction pointer.
438_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {439_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
439 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;440 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
440 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,441 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
441 (void *)context, ufc->resumeLocation + 1);442 (void *)context, ufc->resumeLocation + 1);
442 return ufc->resumeLocation + 1;443 return ufc->resumeLocation + 1;
443}444}
...@@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,...@@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
450 int *ipBefore) {451 int *ipBefore) {
451 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;452 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
452 *ipBefore = 0;453 *ipBefore = 0;
453 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,454 _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIxPTR,
454 (void *)context, (void *)ipBefore,455 (void *)context, (void *)ipBefore,
455 ufc->resumeLocation + 1);456 ufc->resumeLocation + 1);
456 return ufc->resumeLocation + 1;457 return ufc->resumeLocation + 1;
...@@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,...@@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
460/// Called by personality handler during phase 2 to alter instruction pointer.461/// Called by personality handler during phase 2 to alter instruction pointer.
461_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,462_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
462 uintptr_t new_value) {463 uintptr_t new_value) {
463 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",464 _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIxPTR ")",
464 (void *)context, new_value);465 (void *)context, new_value);
465 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;466 _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
466 ufc->resumeLocation = new_value - 1;467 ufc->resumeLocation = new_value - 1;
lib/libunwind/src/Unwind-wasm.c created+123
...@@ -0,0 +1,123 @@
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// Implements Wasm exception handling proposal
9// (https://github.com/WebAssembly/exception-handling) based C++ exceptions
10//
11//===----------------------------------------------------------------------===//
12
13#include <stdbool.h>
14
15#include "config.h"
16
17#ifdef __USING_WASM_EXCEPTIONS__
18
19#include "unwind.h"
20#include <threads.h>
21
22_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
23 uint64_t exceptionClass,
24 _Unwind_Exception *unwind_exception,
25 _Unwind_Context *context);
26
27struct _Unwind_LandingPadContext {
28 // Input information to personality function
29 uintptr_t lpad_index; // landing pad index
30 uintptr_t lsda; // LSDA address
31
32 // Output information computed by personality function
33 uintptr_t selector; // selector value
34};
35
36// Communication channel between compiler-generated user code and personality
37// function
38thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
39
40/// Calls to this function is in landing pads in compiler-generated user code.
41/// In other EH schemes, stack unwinding is done by libunwind library, which
42/// calls the personality function for each each frame it lands. On the other
43/// hand, WebAssembly stack unwinding process is performed by a VM, and the
44/// personality function cannot be called from there. So the compiler inserts
45/// a call to this function in landing pads in the user code, which in turn
46/// calls the personality function.
47_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
48 struct _Unwind_Exception *exception_object =
49 (struct _Unwind_Exception *)exception_ptr;
50 _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
51 (void *)exception_object);
52
53 // Reset the selector.
54 __wasm_lpad_context.selector = 0;
55
56 // Call personality function. Wasm does not have two-phase unwinding, so we
57 // only do the cleanup phase.
58 return __gxx_personality_wasm0(
59 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
60 (struct _Unwind_Context *)&__wasm_lpad_context);
61}
62
63/// Called by __cxa_throw.
64_LIBUNWIND_EXPORT _Unwind_Reason_Code
65_Unwind_RaiseException(_Unwind_Exception *exception_object) {
66 _LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
67 (void *)exception_object);
68 // Use Wasm EH's 'throw' instruction.
69 __builtin_wasm_throw(0, exception_object);
70}
71
72/// Called by __cxa_end_catch.
73_LIBUNWIND_EXPORT void
74_Unwind_DeleteException(_Unwind_Exception *exception_object) {
75 _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
76 (void *)(exception_object));
77 if (exception_object->exception_cleanup != NULL)
78 (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
79 exception_object);
80}
81
82/// Called by personality handler to alter register values.
83_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
84 uintptr_t value) {
85 _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
86 (void *)context, index, value);
87 // We only use this function to set __wasm_lpad_context.selector field, which
88 // is index 1 in the personality function.
89 if (index == 1)
90 ((struct _Unwind_LandingPadContext *)context)->selector = value;
91}
92
93/// Called by personality handler to get instruction pointer.
94_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
95 // The result will be used as an 1-based index after decrementing 1, so we
96 // increment 2 here
97 uintptr_t result =
98 ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
99 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,
100 result);
101 return result;
102}
103
104/// Not used in Wasm.
105_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
106 uintptr_t value) {}
107
108/// Called by personality handler to get LSDA for current frame.
109_LIBUNWIND_EXPORT uintptr_t
110_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
111 uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;
112 _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
113 (void *)context, result);
114 return result;
115}
116
117/// Not used in Wasm.
118_LIBUNWIND_EXPORT uintptr_t
119_Unwind_GetRegionStart(struct _Unwind_Context *context) {
120 return 0;
121}
122
123#endif // defined(__USING_WASM_EXCEPTIONS__)
lib/libunwind/src/UnwindCursor.hpp+114-59
...@@ -33,6 +33,8 @@...@@ -33,6 +33,8 @@
33#if defined(_LIBUNWIND_TARGET_LINUX) && \33#if defined(_LIBUNWIND_TARGET_LINUX) && \
34 (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \34 (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
35 defined(_LIBUNWIND_TARGET_S390X))35 defined(_LIBUNWIND_TARGET_S390X))
36#include <errno.h>
37#include <signal.h>
36#include <sys/syscall.h>38#include <sys/syscall.h>
37#include <sys/uio.h>39#include <sys/uio.h>
38#include <unistd.h>40#include <unistd.h>
...@@ -990,6 +992,7 @@ private:...@@ -990,6 +992,7 @@ private:
990 R dummy;992 R dummy;
991 return stepThroughSigReturn(dummy);993 return stepThroughSigReturn(dummy);
992 }994 }
995 bool isReadableAddr(const pint_t addr) const;
993#if defined(_LIBUNWIND_TARGET_AARCH64)996#if defined(_LIBUNWIND_TARGET_AARCH64)
994 bool setInfoForSigReturn(Registers_arm64 &);997 bool setInfoForSigReturn(Registers_arm64 &);
995 int stepThroughSigReturn(Registers_arm64 &);998 int stepThroughSigReturn(Registers_arm64 &);
...@@ -2301,27 +2304,39 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2301,27 +2304,39 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2301 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {2304 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2302 functionName = ".anonymous.";2305 functionName = ".anonymous.";
2303 }2306 }
2304 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",2307 _LIBUNWIND_TRACE_UNWINDING(
2305 __func__, functionName,2308 "%s: Look up traceback table of func=%s at %p, pc=%p, "
2306 reinterpret_cast<void *>(TBTable));2309 "SP=%p, saves_lr=%d, stores_bc=%d",
2310 __func__, functionName, reinterpret_cast<void *>(TBTable),
2311 reinterpret_cast<void *>(pc),
2312 reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
2313 TBTable->tb.stores_bc);
2307 }2314 }
23082315
2309#if defined(__powerpc64__)2316#if defined(__powerpc64__)
2310 // Instruction to reload TOC register "l r2,40(r1)"2317 // Instruction to reload TOC register "ld r2,40(r1)"
2311 const uint32_t loadTOCRegInst = 0xe8410028;2318 const uint32_t loadTOCRegInst = 0xe8410028;
2312 const int32_t unwPPCF0Index = UNW_PPC64_F0;2319 const int32_t unwPPCF0Index = UNW_PPC64_F0;
2313 const int32_t unwPPCV0Index = UNW_PPC64_V0;2320 const int32_t unwPPCV0Index = UNW_PPC64_V0;
2314#else2321#else
2315 // Instruction to reload TOC register "l r2,20(r1)"2322 // Instruction to reload TOC register "lwz r2,20(r1)"
2316 const uint32_t loadTOCRegInst = 0x80410014;2323 const uint32_t loadTOCRegInst = 0x80410014;
2317 const int32_t unwPPCF0Index = UNW_PPC_F0;2324 const int32_t unwPPCF0Index = UNW_PPC_F0;
2318 const int32_t unwPPCV0Index = UNW_PPC_V0;2325 const int32_t unwPPCV0Index = UNW_PPC_V0;
2319#endif2326#endif
23202327
2328 // lastStack points to the stack frame of the next routine up.
2329 pint_t curStack = static_cast<pint_t>(registers.getSP());
2330 pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
2331
2332 if (lastStack == 0)
2333 return UNW_STEP_END;
2334
2321 R newRegisters = registers;2335 R newRegisters = registers;
23222336
2323 // lastStack points to the stack frame of the next routine up.2337 // If backchain is not stored, use the current stack frame.
2324 pint_t lastStack = *(reinterpret_cast<pint_t *>(registers.getSP()));2338 if (!TBTable->tb.stores_bc)
2339 lastStack = curStack;
23252340
2326 // Return address is the address after call site instruction.2341 // Return address is the address after call site instruction.
2327 pint_t returnAddress;2342 pint_t returnAddress;
...@@ -2331,33 +2346,41 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2331,33 +2346,41 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2331 reinterpret_cast<void *>(lastStack));2346 reinterpret_cast<void *>(lastStack));
23322347
2333 sigcontext *sigContext = reinterpret_cast<sigcontext *>(2348 sigcontext *sigContext = reinterpret_cast<sigcontext *>(
2334 reinterpret_cast<char *>(lastStack) + STKMIN);2349 reinterpret_cast<char *>(lastStack) + STKMINALIGN);
2335 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;2350 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
23362351
2337 _LIBUNWIND_TRACE_UNWINDING("From sigContext=%p, returnAddress=%p\n",2352 bool useSTKMIN = false;
2338 reinterpret_cast<void *>(sigContext),
2339 reinterpret_cast<void *>(returnAddress));
2340
2341 if (returnAddress < 0x10000000) {2353 if (returnAddress < 0x10000000) {
2342 // Try again using STKMINALIGN2354 // Try again using STKMIN.
2343 sigContext = reinterpret_cast<sigcontext *>(2355 sigContext = reinterpret_cast<sigcontext *>(
2344 reinterpret_cast<char *>(lastStack) + STKMINALIGN);2356 reinterpret_cast<char *>(lastStack) + STKMIN);
2345 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;2357 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2346 if (returnAddress < 0x10000000) {2358 if (returnAddress < 0x10000000) {
2347 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p\n",2359 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2348 reinterpret_cast<void *>(returnAddress));2360 reinterpret_cast<void *>(returnAddress),
2361 reinterpret_cast<void *>(sigContext));
2349 return UNW_EBADFRAME;2362 return UNW_EBADFRAME;
2350 } else {
2351 _LIBUNWIND_TRACE_UNWINDING("Tried again using STKMINALIGN: "
2352 "sigContext=%p, returnAddress=%p. "
2353 "Seems to be a valid address\n",
2354 reinterpret_cast<void *>(sigContext),
2355 reinterpret_cast<void *>(returnAddress));
2356 }2363 }
2364 useSTKMIN = true;
2357 }2365 }
2366 _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2367 "sigContext=%p, returnAddress=%p. "
2368 "Seems to be a valid address",
2369 useSTKMIN ? "STKMIN" : "STKMINALIGN",
2370 reinterpret_cast<void *>(sigContext),
2371 reinterpret_cast<void *>(returnAddress));
2372
2358 // Restore the condition register from sigcontext.2373 // Restore the condition register from sigcontext.
2359 newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);2374 newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
23602375
2376 // Save the LR in sigcontext for stepping up when the function that
2377 // raised the signal is a leaf function. This LR has the return address
2378 // to the caller of the leaf function.
2379 newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
2380 _LIBUNWIND_TRACE_UNWINDING(
2381 "Save LR=%p from sigcontext",
2382 reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
2383
2361 // Restore GPRs from sigcontext.2384 // Restore GPRs from sigcontext.
2362 for (int i = 0; i < 32; ++i)2385 for (int i = 0; i < 32; ++i)
2363 newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);2386 newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
...@@ -2380,13 +2403,26 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2380,13 +2403,26 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2380 }2403 }
2381 } else {2404 } else {
2382 // Step up a normal frame.2405 // Step up a normal frame.
2383 returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
23842406
2385 _LIBUNWIND_TRACE_UNWINDING("Extract info from lastStack=%p, "2407 if (!TBTable->tb.saves_lr && registers.getLR()) {
2386 "returnAddress=%p\n",2408 // This case should only occur if we were called from a signal handler
2387 reinterpret_cast<void *>(lastStack),2409 // and the signal occurred in a function that doesn't save the LR.
2388 reinterpret_cast<void *>(returnAddress));2410 returnAddress = static_cast<pint_t>(registers.getLR());
2389 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d\n",2411 _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2412 reinterpret_cast<void *>(returnAddress));
2413 } else {
2414 // Otherwise, use the LR value in the stack link area.
2415 returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
2416 }
2417
2418 // Reset LR in the current context.
2419 newRegisters.setLR(NULL);
2420
2421 _LIBUNWIND_TRACE_UNWINDING(
2422 "Extract info from lastStack=%p, returnAddress=%p",
2423 reinterpret_cast<void *>(lastStack),
2424 reinterpret_cast<void *>(returnAddress));
2425 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2390 TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,2426 TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
2391 TBTable->tb.saves_cr);2427 TBTable->tb.saves_cr);
23922428
...@@ -2450,7 +2486,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2450,7 +2486,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
24502486
2451 struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);2487 struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
24522488
2453 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved);2489 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
24542490
2455 // Restore vector register(s) if saved on the stack.2491 // Restore vector register(s) if saved on the stack.
2456 if (vec_ext->vr_saved) {2492 if (vec_ext->vr_saved) {
...@@ -2480,11 +2516,11 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2480,11 +2516,11 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
24802516
2481 // Do we need to set the TOC register?2517 // Do we need to set the TOC register?
2482 _LIBUNWIND_TRACE_UNWINDING(2518 _LIBUNWIND_TRACE_UNWINDING(
2483 "Current gpr2=%p\n",2519 "Current gpr2=%p",
2484 reinterpret_cast<void *>(newRegisters.getRegister(2)));2520 reinterpret_cast<void *>(newRegisters.getRegister(2)));
2485 if (firstInstruction == loadTOCRegInst) {2521 if (firstInstruction == loadTOCRegInst) {
2486 _LIBUNWIND_TRACE_UNWINDING(2522 _LIBUNWIND_TRACE_UNWINDING(
2487 "Set gpr2=%p from frame\n",2523 "Set gpr2=%p from frame",
2488 reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));2524 reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
2489 newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);2525 newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
2490 }2526 }
...@@ -2516,7 +2552,6 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,...@@ -2516,7 +2552,6 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2516 } else {2552 } else {
2517 isSignalFrame = false;2553 isSignalFrame = false;
2518 }2554 }
2519
2520 return UNW_STEP_SUCCESS;2555 return UNW_STEP_SUCCESS;
2521}2556}
2522#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)2557#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
...@@ -2668,20 +2703,12 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {...@@ -2668,20 +2703,12 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2668 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S2703 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
2669 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));2704 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2670 // The PC might contain an invalid address if the unwind info is bad, so2705 // The PC might contain an invalid address if the unwind info is bad, so
2671 // directly accessing it could cause a segfault. Use process_vm_readv to read2706 // directly accessing it could cause a SIGSEGV.
2672 // the memory safely instead. process_vm_readv was added in Linux 3.2, and2707 if (!isReadableAddr(pc))
2673 // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to2708 return false;
2674 // be present. Unfortunately, there are Linux AArch64 environments where the2709 auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2675 // libc wrapper for the syscall might not be present (e.g. Android 5), so call
2676 // the syscall directly instead.
2677 uint32_t instructions[2];
2678 struct iovec local_iov = {&instructions, sizeof instructions};
2679 struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions};
2680 long bytesRead =
2681 syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0);
2682 // Look for instructions: mov x8, #0x8b; svc #0x02710 // Look for instructions: mov x8, #0x8b; svc #0x0
2683 if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 ||2711 if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)
2684 instructions[1] != 0xd4000001)
2685 return false;2712 return false;
26862713
2687 _info = {};2714 _info = {};
...@@ -2730,18 +2757,17 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {...@@ -2730,18 +2757,17 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2730template <typename A, typename R>2757template <typename A, typename R>
2731bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {2758bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
2732 const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));2759 const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
2733 uint32_t instructions[2];2760 // The PC might contain an invalid address if the unwind info is bad, so
2734 struct iovec local_iov = {&instructions, sizeof instructions};2761 // directly accessing it could cause a SIGSEGV.
2735 struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions};2762 if (!isReadableAddr(pc))
2736 long bytesRead =2763 return false;
2737 syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0);2764 const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2738 // Look for the two instructions used in the sigreturn trampoline2765 // Look for the two instructions used in the sigreturn trampoline
2739 // __vdso_rt_sigreturn:2766 // __vdso_rt_sigreturn:
2740 //2767 //
2741 // 0x08b00893 li a7,0x8b2768 // 0x08b00893 li a7,0x8b
2742 // 0x00000073 ecall2769 // 0x00000073 ecall
2743 if (bytesRead != sizeof instructions || instructions[0] != 0x08b00893 ||2770 if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
2744 instructions[1] != 0x00000073)
2745 return false;2771 return false;
27462772
2747 _info = {};2773 _info = {};
...@@ -2790,13 +2816,11 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {...@@ -2790,13 +2816,11 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
2790 // onto the stack.2816 // onto the stack.
2791 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));2817 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2792 // The PC might contain an invalid address if the unwind info is bad, so2818 // The PC might contain an invalid address if the unwind info is bad, so
2793 // directly accessing it could cause a segfault. Use process_vm_readv to2819 // directly accessing it could cause a SIGSEGV.
2794 // read the memory safely instead.2820 if (!isReadableAddr(pc))
2795 uint16_t inst;2821 return false;
2796 struct iovec local_iov = {&inst, sizeof inst};2822 const auto inst = *reinterpret_cast<const uint16_t *>(pc);
2797 struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof inst};2823 if (inst == 0x0a77 || inst == 0x0aad) {
2798 long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
2799 if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) {
2800 _info = {};2824 _info = {};
2801 _info.start_ip = pc;2825 _info.start_ip = pc;
2802 _info.end_ip = pc + 2;2826 _info.end_ip = pc + 2;
...@@ -2942,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,...@@ -2942,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
2942 buf, bufLen, offset);2966 buf, bufLen, offset);
2943}2967}
29442968
2969#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2970template <typename A, typename R>
2971bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
2972 // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
2973
2974 const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
2975 // We have to check that addr is nullptr because sigprocmask allows that
2976 // as an argument without failure.
2977 if (!sigsetAddr)
2978 return false;
2979 const auto saveErrno = errno;
2980 // We MUST use a raw syscall here, as wrappers may try to access
2981 // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
2982 // safe. Additionally, we need to pass the kernel_sigset_size, which is
2983 // different from libc sizeof(sigset_t). For the majority of architectures,
2984 // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
2985 const auto kernelSigsetSize = NSIG / 8;
2986 [[maybe_unused]] const int Result = syscall(
2987 SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
2988 // Because our "how" is invalid, this syscall should always fail, and our
2989 // errno should always be EINVAL or an EFAULT. This relies on the Linux
2990 // kernel to check copy_from_user before checking if the "how" argument is
2991 // invalid.
2992 assert(Result == -1);
2993 assert(errno == EFAULT || errno == EINVAL);
2994 const auto readable = errno != EFAULT;
2995 errno = saveErrno;
2996 return readable;
2997}
2998#endif
2999
2945#if defined(_LIBUNWIND_USE_CET)3000#if defined(_LIBUNWIND_USE_CET)
2946extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {3001extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
2947 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;3002 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
lib/libunwind/src/UnwindLevel1-gcc-ext.c+1-1
...@@ -143,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {...@@ -143,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
143 // Create a mock exception object for force unwinding.143 // Create a mock exception object for force unwinding.
144 _Unwind_Exception ex;144 _Unwind_Exception ex;
145 memset(&ex, '\0', sizeof(ex));145 memset(&ex, '\0', sizeof(ex));
146 strcpy((char *)&ex.exception_class, "CLNGUNW");146 memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class));
147#endif147#endif
148148
149 // walk each frame149 // walk each frame
lib/libunwind/src/UnwindRegistersRestore.S+5-1
...@@ -673,7 +673,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)...@@ -673,7 +673,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
673 ldr d30, [x0, #0x200]673 ldr d30, [x0, #0x200]
674 ldr d31, [x0, #0x208]674 ldr d31, [x0, #0x208]
675675
676 // Finally, restore sp. This must be done after the the last read from the676 // Finally, restore sp. This must be done after the last read from the
677 // context struct, because it is allocated on the stack, and an exception677 // context struct, because it is allocated on the stack, and an exception
678 // could clobber the de-allocated portion of the stack after sp has been678 // could clobber the de-allocated portion of the stack after sp has been
679 // restored.679 // restored.
...@@ -993,11 +993,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)...@@ -993,11 +993,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
993 ldc1 $f31, (4 * 36 + 8 * 31)($4)993 ldc1 $f31, (4 * 36 + 8 * 31)($4)
994#endif994#endif
995#endif995#endif
996#if __mips_isa_rev < 6
996 // restore hi and lo997 // restore hi and lo
997 lw $8, (4 * 33)($4)998 lw $8, (4 * 33)($4)
998 mthi $8999 mthi $8
999 lw $8, (4 * 34)($4)1000 lw $8, (4 * 34)($4)
1000 mtlo $81001 mtlo $8
1002#endif
1001 // r0 is zero1003 // r0 is zero
1002 lw $1, (4 * 1)($4)1004 lw $1, (4 * 1)($4)
1003 lw $2, (4 * 2)($4)1005 lw $2, (4 * 2)($4)
...@@ -1054,11 +1056,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)...@@ -1054,11 +1056,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
1054 ldc1 $f\i, (280+8*\i)($4)1056 ldc1 $f\i, (280+8*\i)($4)
1055 .endr1057 .endr
1056#endif1058#endif
1059#if __mips_isa_rev < 6
1057 // restore hi and lo1060 // restore hi and lo
1058 ld $8, (8 * 33)($4)1061 ld $8, (8 * 33)($4)
1059 mthi $81062 mthi $8
1060 ld $8, (8 * 34)($4)1063 ld $8, (8 * 34)($4)
1061 mtlo $81064 mtlo $8
1065#endif
1062 // r0 is zero1066 // r0 is zero
1063 ld $1, (8 * 1)($4)1067 ld $1, (8 * 1)($4)
1064 ld $2, (8 * 2)($4)1068 ld $2, (8 * 2)($4)
lib/libunwind/src/UnwindRegistersSave.S+41-3
...@@ -174,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -174,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
174 sw $31, (4 * 31)($4)174 sw $31, (4 * 31)($4)
175 # Store return address to pc175 # Store return address to pc
176 sw $31, (4 * 32)($4)176 sw $31, (4 * 32)($4)
177#if __mips_isa_rev < 6
177 # hi and lo178 # hi and lo
178 mfhi $8179 mfhi $8
179 sw $8, (4 * 33)($4)180 sw $8, (4 * 33)($4)
180 mflo $8181 mflo $8
181 sw $8, (4 * 34)($4)182 sw $8, (4 * 34)($4)
183#endif
182#ifdef __mips_hard_float184#ifdef __mips_hard_float
183#if __mips_fpr != 64185#if __mips_fpr != 64
184 sdc1 $f0, (4 * 36 + 8 * 0)($4)186 sdc1 $f0, (4 * 36 + 8 * 0)($4)
...@@ -255,11 +257,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -255,11 +257,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
255 .endr257 .endr
256 # Store return address to pc258 # Store return address to pc
257 sd $31, (8 * 32)($4)259 sd $31, (8 * 32)($4)
260#if __mips_isa_rev < 6
258 # hi and lo261 # hi and lo
259 mfhi $8262 mfhi $8
260 sd $8, (8 * 33)($4)263 sd $8, (8 * 33)($4)
261 mflo $8264 mflo $8
262 sd $8, (8 * 34)($4)265 sd $8, (8 * 34)($4)
266#endif
263#ifdef __mips_hard_float267#ifdef __mips_hard_float
264 .irp i,FROM_0_TO_31268 .irp i,FROM_0_TO_31
265 sdc1 $f\i, (280+8*\i)($4)269 sdc1 $f\i, (280+8*\i)($4)
...@@ -301,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -301,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
301 mflr 0305 mflr 0
302 std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0306 std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0
303 PPC64_STR(1)307 PPC64_STR(1)
308 PPC64_STR(4) // Save r4 first since it will be used for fixing r2.
309#if defined(_AIX)
310 // The TOC register (r2) was changed by the glue code if unw_getcontext
311 // is called from a different module. Save the original TOC register
312 // in the context if this is the case.
313 mflr 4
314 lwz 4, 0(4) // Get the first instruction at the return address.
315 xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
316 cmplwi 0, 0x28
317 bne 0, LnoR2Fix // No need to fix up r2 if it is not.
318 ld 2, 40(1) // Use the saved TOC register in the stack.
319LnoR2Fix:
320#endif
304 PPC64_STR(2)321 PPC64_STR(2)
305 PPC64_STR(3)322 PPC64_STR(3)
306 PPC64_STR(4)
307 PPC64_STR(5)323 PPC64_STR(5)
308 PPC64_STR(6)324 PPC64_STR(6)
309 PPC64_STR(7)325 PPC64_STR(7)
...@@ -336,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -336,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
336 std 0, PPC64_OFFS_CR(3)352 std 0, PPC64_OFFS_CR(3)
337 mfxer 0353 mfxer 0
338 std 0, PPC64_OFFS_XER(3)354 std 0, PPC64_OFFS_XER(3)
355#if defined(_AIX)
356 // LR value saved from the register is not used, initialize it to 0.
357 li 0, 0
358#else
339 mflr 0359 mflr 0
360#endif
340 std 0, PPC64_OFFS_LR(3)361 std 0, PPC64_OFFS_LR(3)
341 mfctr 0362 mfctr 0
342 std 0, PPC64_OFFS_CTR(3)363 std 0, PPC64_OFFS_CTR(3)
...@@ -543,9 +564,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -543,9 +564,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
543 mflr 0564 mflr 0
544 stw 0, 0(3) // store lr as ssr0565 stw 0, 0(3) // store lr as ssr0
545 stw 1, 12(3)566 stw 1, 12(3)
567 stw 4, 24(3) // Save r4 first since it will be used for fixing r2.
568#if defined(_AIX)
569 // The TOC register (r2) was changed by the glue code if unw_getcontext
570 // is called from a different module. Save the original TOC register
571 // in the context if this is the case.
572 mflr 4
573 lwz 4, 0(4) // Get the instruction at the return address.
574 xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
575 cmplwi 0, 0x14
576 bne 0, LnoR2Fix // No need to fix up r2 if it is not.
577 lwz 2, 20(1) // Use the saved TOC register in the stack.
578LnoR2Fix:
579#endif
546 stw 2, 16(3)580 stw 2, 16(3)
547 stw 3, 20(3)581 stw 3, 20(3)
548 stw 4, 24(3)
549 stw 5, 28(3)582 stw 5, 28(3)
550 stw 6, 32(3)583 stw 6, 32(3)
551 stw 7, 36(3)584 stw 7, 36(3)
...@@ -582,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -582,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
582 // save CR registers615 // save CR registers
583 mfcr 0616 mfcr 0
584 stw 0, 136(3)617 stw 0, 136(3)
618#if defined(_AIX)
619 // LR value from the register is not used, initialize it to 0.
620 li 0, 0
621 stw 0, 144(3)
622#endif
585 // save CTR register623 // save CTR register
586 mfctr 0624 mfctr 0
587 stw 0, 148(3)625 stw 0, 148(3)
...@@ -742,7 +780,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -742,7 +780,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
742@780@
743@ On entry:781@ On entry:
744@ thread_state pointer is in r0782@ thread_state pointer is in r0
745@ 783@
746@ Per EHABI #4.7 this only saves the core integer registers.784@ Per EHABI #4.7 this only saves the core integer registers.
747@ EHABI #7.4.5 notes that in general all VRS registers should be restored785@ EHABI #7.4.5 notes that in general all VRS registers should be restored
748@ however this is very hard to do for VFP registers because it is unknown786@ however this is very hard to do for VFP registers because it is unknown
lib/libunwind/src/config.h+8-6
...@@ -46,6 +46,12 @@...@@ -46,6 +46,12 @@
46#elif defined(_AIX)46#elif defined(_AIX)
47// The traceback table at the end of each function is used for unwinding.47// The traceback table at the end of each function is used for unwinding.
48#define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 148#define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1
49#elif defined(__HAIKU__)
50 #if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB)
51 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
52 #endif
53 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
54 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
49#else55#else
50 // Assume an ELF system with a dl_iterate_phdr function.56 // Assume an ELF system with a dl_iterate_phdr function.
51 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 157 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
...@@ -83,7 +89,7 @@...@@ -83,7 +89,7 @@
83 __asm__(".globl " SYMBOL_NAME(aliasname)); \89 __asm__(".globl " SYMBOL_NAME(aliasname)); \
84 __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \90 __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
85 _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))91 _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))
86#elif defined(__ELF__) || defined(_AIX)92#elif defined(__ELF__) || defined(_AIX) || defined(__wasm__)
87#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \93#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
88 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \94 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
89 __attribute__((weak, alias(#name)));95 __attribute__((weak, alias(#name)));
...@@ -108,10 +114,6 @@...@@ -108,10 +114,6 @@
108#define _LIBUNWIND_BUILD_SJLJ_APIS114#define _LIBUNWIND_BUILD_SJLJ_APIS
109#endif115#endif
110116
111#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
112#define _LIBUNWIND_SUPPORT_FRAME_APIS
113#endif
114
115#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \117#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
116 (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \118 (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
117 defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \119 defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
...@@ -125,7 +127,7 @@...@@ -125,7 +127,7 @@
125#if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \127#if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \
126 defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \128 defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \
127 defined(_LIBUNWIND_IS_BAREMETAL)129 defined(_LIBUNWIND_IS_BAREMETAL)
128#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size)130#define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size)
129#define _LIBUNWIND_REMEMBER_FREE(_ptr) \131#define _LIBUNWIND_REMEMBER_FREE(_ptr) \
130 do { \132 do { \
131 } while (0)133 } while (0)
lib/libunwind/src/libunwind.cpp+4-3
...@@ -26,7 +26,7 @@...@@ -26,7 +26,7 @@
26#include <sanitizer/asan_interface.h>26#include <sanitizer/asan_interface.h>
27#endif27#endif
2828
29#if !defined(__USING_SJLJ_EXCEPTIONS__)29#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
30#include "AddressSpace.hpp"30#include "AddressSpace.hpp"
31#include "UnwindCursor.hpp"31#include "UnwindCursor.hpp"
3232
...@@ -324,7 +324,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {...@@ -324,7 +324,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
324 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;324 CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
325 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;325 CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
326 auto p = (LocalAddressSpace::pint_t)eh_frame_start;326 auto p = (LocalAddressSpace::pint_t)eh_frame_start;
327 while (true) {327 while (LocalAddressSpace::sThisAddressSpace.get32(p)) {
328 if (CFI_Parser<LocalAddressSpace>::decodeFDE(328 if (CFI_Parser<LocalAddressSpace>::decodeFDE(
329 LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,329 LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
330 true) == NULL) {330 true) == NULL) {
...@@ -347,7 +347,8 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {...@@ -347,7 +347,8 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
347}347}
348348
349#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)349#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
350#endif // !defined(__USING_SJLJ_EXCEPTIONS__)350#endif // !defined(__USING_SJLJ_EXCEPTIONS__) &&
351 // !defined(__USING_WASM_EXCEPTIONS__)
351352
352#ifdef __APPLE__353#ifdef __APPLE__
353354
src/libunwind.zig+1
...@@ -164,6 +164,7 @@ const unwind_src_list = [_][]const u8{...@@ -164,6 +164,7 @@ const unwind_src_list = [_][]const u8{
164 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",164 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",
165 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",165 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",
166 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",166 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",
167 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-wasm.c",
167 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",168 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
168 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",169 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
169 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",170 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",