| author | |
| committer | |
| log | 6295415da72eb17b263494a070fdf957e89460fb |
| tree | 308c2c6341b137085dd9dc20168e2509572c2216 |
| parent | a6856ef6d21635641320761a8f17205fd6e99fa9 |
release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db4217 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 1 | 37 | # define _LIBUNWIND_TARGET_LINUX 1 |
| 38 | # endif | 38 | # 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_I386 | 43 | # define _LIBUNWIND_TARGET_I386 |
| 41 | # define _LIBUNWIND_CONTEXT_SIZE 8 | 44 | # define _LIBUNWIND_CONTEXT_SIZE 8 |
| ... | @@ -196,7 +199,7 @@ | ... | @@ -196,7 +199,7 @@ |
| 196 | # define _LIBUNWIND_TARGET_RISCV 1 | 199 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 197 | # define _LIBUNWIND_TARGET_VE 1 | 200 | # define _LIBUNWIND_TARGET_VE 1 |
| 198 | # define _LIBUNWIND_TARGET_S390X 1 | 201 | # define _LIBUNWIND_TARGET_S390X 1 |
| 199 | #define _LIBUNWIND_TARGET_LOONGARCH 1 | 202 | # define _LIBUNWIND_TARGET_LOONGARCH 1 |
| 200 | # define _LIBUNWIND_CONTEXT_SIZE 167 | 203 | # define _LIBUNWIND_CONTEXT_SIZE 167 |
| 201 | # define _LIBUNWIND_CURSOR_SIZE 204 | 204 | # define _LIBUNWIND_CURSOR_SIZE 204 |
| 202 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 | 205 | # 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 compact | 112 | // constant stack size. To return, a constant (encoded in the compact |
| 113 | // unwind encoding) is added to the ESP. Then the return is done by | 113 | // 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 were | 119 | // 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 too | 123 | // 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 in | 126 | // 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 the | 129 | // 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 a | 132 | // 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 saved | 239 | // 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 saved | 241 | // 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 saved | 249 | // 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 is | 250 | // 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 were | 253 | // 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 too | 257 | // 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 in | 260 | // 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 the | 263 | // 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 a | 266 | // 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 the | 307 | // 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 registers | 308 | // 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 contiguous | 309 | // 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 register | 311 | // 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 registers | 315 | // 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 is | 316 | // are saved, they must be pushed onto the stack before any stack space is |
| 317 | // allocated for local variables. The stack sized (including any saved | 317 | // 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 the | 321 | // 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 a | 324 | // 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 { |
| 337 | 337 | ||
| 338 | // | 338 | // |
| 339 | // A compiler can generated compact unwind information for a function by adding | 339 | // 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/range | 346 | // 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 function | 349 | // personality-function or zero if no personality function |
| 350 | // lsda or zero if no LSDA data | 350 | // 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_tab1 | 372 | // .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 until | 380 | // 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 one | 381 | // 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 way | 386 | // 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. |
| 392 | 392 | ||
| 393 | 393 | ||
| 394 | 394 | ||
| ... | @@ -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 address | 404 | // 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 | // |
| 407 | 407 | ||
| 408 | #define UNWIND_SECTION_VERSION 1 | 408 | #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> |
| 55 | bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, | 55 | bool 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 @@ |
| 31 | 31 | ||
| 32 | class _LIBUNWIND_HIDDEN FrameHeaderCache { | 32 | class _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 { |
| 41 | 41 | ||
| 42 | // Can't depend on the C++ standard library in libunwind, so use an array to | 42 | // 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 recently | 43 | // 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 list | 44 | // 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-linked | 45 | // 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 memory | 47 | // 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; } | ||
| 622 | 624 | ||
| 623 | private: | 625 | private: |
| 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; } | ||
| 1192 | 1196 | ||
| 1193 | private: | 1197 | private: |
| 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 != 6 | 2876 | #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 != 6 | 3206 | #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 { |
| 82 | static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; | 82 | static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; |
| 83 | #endif | 83 | #endif |
| 84 | 84 | ||
| 85 | static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { | 85 | static 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 | #else | 89 | #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%" PRIuPTR | 430 | _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 | |||
| 27 | struct _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 | ||
| 38 | thread_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 | } |
| 2308 | 2315 | ||
| 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 | #else | 2321 | #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 | #endif | 2326 | #endif |
| 2320 | 2327 | ||
| 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; |
| 2322 | 2336 | ||
| 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; | ||
| 2325 | 2340 | ||
| 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)); |
| 2332 | 2347 | ||
| 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; |
| 2336 | 2351 | ||
| 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 STKMINALIGN | 2354 | // 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); |
| 2360 | 2375 | ||
| 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]; | ||
| 2384 | 2406 | ||
| 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); |
| 2392 | 2428 | ||
| ... | @@ -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, |
| 2450 | 2486 | ||
| 2451 | struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr); | 2487 | struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr); |
| 2452 | 2488 | ||
| 2453 | _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved); | 2489 | _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved); |
| 2454 | 2490 | ||
| 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, |
| 2480 | 2516 | ||
| 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.S | 2703 | // [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, so | 2705 | // 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 read | 2706 | // directly accessing it could cause a SIGSEGV. |
| 2672 | // the memory safely instead. process_vm_readv was added in Linux 3.2, and | 2707 | if (!isReadableAddr(pc)) |
| 2673 | // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to | 2708 | return false; |
| 2674 | // be present. Unfortunately, there are Linux AArch64 environments where the | 2709 | 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 #0x0 | 2710 | // 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; |
| 2686 | 2713 | ||
| 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 &) { |
| 2730 | template <typename A, typename R> | 2757 | template <typename A, typename R> |
| 2731 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) { | 2758 | bool 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 trampoline | 2765 | // Look for the two instructions used in the sigreturn trampoline |
| 2739 | // __vdso_rt_sigreturn: | 2766 | // __vdso_rt_sigreturn: |
| 2740 | // | 2767 | // |
| 2741 | // 0x08b00893 li a7,0x8b | 2768 | // 0x08b00893 li a7,0x8b |
| 2742 | // 0x00000073 ecall | 2769 | // 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; |
| 2746 | 2772 | ||
| 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, so | 2818 | // 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 to | 2819 | // 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 | } |
| 2944 | 2968 | ||
| 2969 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | ||
| 2970 | template <typename A, typename R> | ||
| 2971 | bool 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) |
| 2946 | extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { | 3001 | extern "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 | #endif | 147 | #endif |
| 148 | 148 | ||
| 149 | // walk each frame | 149 | // 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] |
| 675 | 675 | ||
| 676 | // Finally, restore sp. This must be done after the the last read from the | 676 | // 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 exception | 677 | // 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 been | 678 | // 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 | #endif | 994 | #endif |
| 995 | #endif | 995 | #endif |
| 996 | #if __mips_isa_rev < 6 | ||
| 996 | // restore hi and lo | 997 | // restore hi and lo |
| 997 | lw $8, (4 * 33)($4) | 998 | lw $8, (4 * 33)($4) |
| 998 | mthi $8 | 999 | mthi $8 |
| 999 | lw $8, (4 * 34)($4) | 1000 | lw $8, (4 * 34)($4) |
| 1000 | mtlo $8 | 1001 | mtlo $8 |
| 1002 | #endif | ||
| 1001 | // r0 is zero | 1003 | // 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 | .endr | 1057 | .endr |
| 1056 | #endif | 1058 | #endif |
| 1059 | #if __mips_isa_rev < 6 | ||
| 1057 | // restore hi and lo | 1060 | // restore hi and lo |
| 1058 | ld $8, (8 * 33)($4) | 1061 | ld $8, (8 * 33)($4) |
| 1059 | mthi $8 | 1062 | mthi $8 |
| 1060 | ld $8, (8 * 34)($4) | 1063 | ld $8, (8 * 34)($4) |
| 1061 | mtlo $8 | 1064 | mtlo $8 |
| 1065 | #endif | ||
| 1062 | // r0 is zero | 1066 | // 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 pc | 175 | # 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 lo | 178 | # hi and lo |
| 178 | mfhi $8 | 179 | mfhi $8 |
| 179 | sw $8, (4 * 33)($4) | 180 | sw $8, (4 * 33)($4) |
| 180 | mflo $8 | 181 | mflo $8 |
| 181 | sw $8, (4 * 34)($4) | 182 | sw $8, (4 * 34)($4) |
| 183 | #endif | ||
| 182 | #ifdef __mips_hard_float | 184 | #ifdef __mips_hard_float |
| 183 | #if __mips_fpr != 64 | 185 | #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 | .endr | 257 | .endr |
| 256 | # Store return address to pc | 258 | # 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 lo | 261 | # hi and lo |
| 259 | mfhi $8 | 262 | mfhi $8 |
| 260 | sd $8, (8 * 33)($4) | 263 | sd $8, (8 * 33)($4) |
| 261 | mflo $8 | 264 | mflo $8 |
| 262 | sd $8, (8 * 34)($4) | 265 | sd $8, (8 * 34)($4) |
| 266 | #endif | ||
| 263 | #ifdef __mips_hard_float | 267 | #ifdef __mips_hard_float |
| 264 | .irp i,FROM_0_TO_31 | 268 | .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 0 | 305 | mflr 0 |
| 302 | std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0 | 306 | 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. | ||
| 319 | LnoR2Fix: | ||
| 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 0 | 353 | 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 0 | 359 | mflr 0 |
| 360 | #endif | ||
| 340 | std 0, PPC64_OFFS_LR(3) | 361 | std 0, PPC64_OFFS_LR(3) |
| 341 | mfctr 0 | 362 | 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 0 | 564 | mflr 0 |
| 544 | stw 0, 0(3) // store lr as ssr0 | 565 | 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. | ||
| 578 | LnoR2Fix: | ||
| 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 registers | 615 | // save CR registers |
| 583 | mfcr 0 | 616 | 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 register | 623 | // save CTR register |
| 586 | mfctr 0 | 624 | 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 r0 | 782 | @ 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 restored | 785 | @ 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 unknown | 786 | @ 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 1 | 48 | #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 | #else | 55 | #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 1 | 57 | #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_APIS | 114 | #define _LIBUNWIND_BUILD_SJLJ_APIS |
| 109 | #endif | 115 | #endif |
| 110 | 116 | ||
| 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 | #endif | 27 | #endif |
| 28 | 28 | ||
| 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" |
| 32 | 32 | ||
| ... | @@ -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 | } |
| 348 | 348 | ||
| 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__) | ||
| 351 | 352 | ||
| 352 | #ifdef __APPLE__ | 353 | #ifdef __APPLE__ |
| 353 | 354 |
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", |