diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2019-08-19 17:11:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-19 17:11:24 -0700 |
commit | 6d8482c379f67a00d63acd823ef351497a7bba4d (patch) | |
tree | a603dbb5745aea497aee1e27e454642e5510cc05 /src/pal/src | |
parent | fc18c3d7f63b4507f4bf8144b2ee43e96ead0731 (diff) | |
download | coreclr-6d8482c379f67a00d63acd823ef351497a7bba4d.tar.gz coreclr-6d8482c379f67a00d63acd823ef351497a7bba4d.tar.bz2 coreclr-6d8482c379f67a00d63acd823ef351497a7bba4d.zip |
arm64 out of proc unwind for DAC (#26156)
Removed FEATURE_DATATARGET4 for arm64
Added SP check to createdump's native unwind loop to make it more robust.
Issue: https://github.com/dotnet/coreclr/issues/15062
Diffstat (limited to 'src/pal/src')
-rw-r--r-- | src/pal/src/exception/remote-unwind.cpp | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/src/pal/src/exception/remote-unwind.cpp b/src/pal/src/exception/remote-unwind.cpp index 3fefcef82b..893cc026c5 100644 --- a/src/pal/src/exception/remote-unwind.cpp +++ b/src/pal/src/exception/remote-unwind.cpp @@ -62,12 +62,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); -// Only used on the AMD64 build -#if defined(_AMD64_) && defined(HAVE_UNW_GET_ACCESSORS) +// Only used on the AMD64/ARM64 builds - ARM32 uses EXIDX which isn't currently supported +#if (defined(_AMD64_) || defined(_ARM64_)) && defined(HAVE_UNW_GET_ACCESSORS) #include <elf.h> #include <link.h> +#if defined(_X86_) || defined(_ARM_) +#define PRIx PRIx32 +#define PRIu PRIu32 +#define PRId PRId32 +#define PRIA "08" +#define PRIxA PRIA PRIx +#elif defined(_AMD64_) || defined(_ARM64_) +#define PRIx PRIx64 +#define PRIu PRIu64 +#define PRId PRId64 +#define PRIA "016" +#define PRIxA PRIA PRIx +#endif + #ifndef ElfW #define ElfW(foo) Elf_ ## foo #endif @@ -77,7 +91,6 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); #define Nhdr ElfW(Nhdr) #define Dyn ElfW(Dyn) -extern void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext); extern void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOLATILE_CONTEXT_POINTERS *contextPointers); typedef struct _libunwindInfo @@ -128,7 +141,7 @@ typedef struct _libunwindInfo #define DWARF_CIE_VERSION 3 // GCC emits version 1??? // DWARF frame header -typedef struct _eh_frame_hdr +typedef struct __attribute__((packed)) _eh_frame_hdr { unsigned char version; unsigned char eh_frame_ptr_enc; @@ -764,6 +777,37 @@ ExtractProcInfoFromFde(const libunwindInfo* info, unw_word_t* addrp, unw_proc_in return true; } +static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) +{ +#if defined(_AMD64_) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Rip); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Rsp); + unw_get_reg(cursor, UNW_X86_64_RBP, (unw_word_t *) &winContext->Rbp); + unw_get_reg(cursor, UNW_X86_64_RBX, (unw_word_t *) &winContext->Rbx); + unw_get_reg(cursor, UNW_X86_64_R12, (unw_word_t *) &winContext->R12); + unw_get_reg(cursor, UNW_X86_64_R13, (unw_word_t *) &winContext->R13); + unw_get_reg(cursor, UNW_X86_64_R14, (unw_word_t *) &winContext->R14); + unw_get_reg(cursor, UNW_X86_64_R15, (unw_word_t *) &winContext->R15); +#elif defined(_ARM64_) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_AARCH64_X19, (unw_word_t *) &winContext->X19); + unw_get_reg(cursor, UNW_AARCH64_X20, (unw_word_t *) &winContext->X20); + unw_get_reg(cursor, UNW_AARCH64_X21, (unw_word_t *) &winContext->X21); + unw_get_reg(cursor, UNW_AARCH64_X22, (unw_word_t *) &winContext->X22); + unw_get_reg(cursor, UNW_AARCH64_X23, (unw_word_t *) &winContext->X23); + unw_get_reg(cursor, UNW_AARCH64_X24, (unw_word_t *) &winContext->X24); + unw_get_reg(cursor, UNW_AARCH64_X25, (unw_word_t *) &winContext->X25); + unw_get_reg(cursor, UNW_AARCH64_X26, (unw_word_t *) &winContext->X26); + unw_get_reg(cursor, UNW_AARCH64_X27, (unw_word_t *) &winContext->X27); + unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28); + unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr); + TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp); +#else +#error unsupported architecture +#endif +} static int get_dyn_info_list_addr(unw_addr_space_t as, unw_word_t *dilap, void *arg) @@ -827,8 +871,8 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_ARM_R10: *valp = (unw_word_t)winContext->R10; break; case UNW_ARM_R11: *valp = (unw_word_t)winContext->R11; break; #elif defined(_ARM64_) - case UNW_REG_IP: *valp = (unw_word_t)winContext->Pc; break; - case UNW_REG_SP: *valp = (unw_word_t)winContext->Sp; break; + case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break; + case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; case UNW_AARCH64_X29: *valp = (unw_word_t)winContext->Fp; break; case UNW_AARCH64_X30: *valp = (unw_word_t)winContext->Lr; break; case UNW_AARCH64_X19: *valp = (unw_word_t)winContext->X19; break; @@ -845,9 +889,10 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write #error unsupported architecture #endif default: - ASSERT("Attempt to read an unknown register\n"); + ASSERT("Attempt to read an unknown register %d\n", regnum); return -UNW_EBADREG; } + TRACE("REG: %d %p\n", regnum, *valp); return UNW_ESUCCESS; } @@ -901,7 +946,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee ERROR("ELF: reading phdrAddr %p\n", phdrAddr); return -UNW_EINVAL; } - TRACE("ELF: phdr %p type %d (%x) vaddr %p memsz %016llx paddr %p filesz %016llx offset %p align %016llx\n", + TRACE("ELF: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n", phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align); switch (ph.p_type) @@ -941,6 +986,11 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee dynamicAddr++; } } + + if (ehPhdr.p_offset == 0) { + ASSERT("ELF: No PT_GNU_EH_FRAME program header\n"); + return -UNW_EINVAL; + } unw_word_t ehFrameHdrAddr = ehPhdr.p_offset + info->BaseAddress; eh_frame_hdr ehFrameHdr; @@ -970,6 +1020,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee } TRACE("ehFrameStart %p fdeCount %p ip offset %08x\n", ehFrameStart, fdeCount, (int32_t)(ip - ehFrameHdrAddr)); + // If there are no frame table entries + if (fdeCount == 0) { + TRACE("No frame table entries\n"); + return -UNW_ENOINFO; + } + // LookupTableEntry assumes this encoding if (ehFrameHdr.table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { ASSERT("Table encoding not supported %x\n", ehFrameHdr.table_enc); @@ -996,7 +1052,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee return -UNW_EINVAL; } - _ASSERTE(ip >= pip->start_ip && ip <= pip->end_ip); + if (ip < pip->start_ip || ip >= pip->end_ip) { + TRACE("ip %p not in range start_ip %p end_ip %p\n", ip, pip->start_ip, pip->end_ip); + return -UNW_ENOINFO; + } return UNW_ESUCCESS; } @@ -1066,7 +1125,7 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont goto exit; } - UnwindContextToWinContext(&cursor, context); + UnwindContextToContext(&cursor, context); if (contextPointers != NULL) { |