Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 6d8482c

Browse files
author
Mike McLaughlin
authored
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
1 parent fc18c3d commit 6d8482c

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

clrdefinitions.cmake

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ if (CLR_CMAKE_PLATFORM_UNIX)
6262
elseif (CLR_CMAKE_TARGET_ARCH_ARM)
6363
add_definitions(-DUNIX_ARM_ABI)
6464
add_definitions(-DFEATURE_DATATARGET4)
65-
elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
66-
add_definitions(-DFEATURE_DATATARGET4)
6765
elseif (CLR_CMAKE_TARGET_ARCH_I386)
6866
add_definitions(-DUNIX_X86_ABI)
6967
endif()

src/debug/createdump/threadinfo.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,19 @@ ReadMemoryAdapter(PVOID address, PVOID buffer, SIZE_T size)
110110
void
111111
ThreadInfo::UnwindNativeFrames(CrashInfo& crashInfo, CONTEXT* pContext)
112112
{
113+
uint64_t previousSp = 0;
114+
113115
// For each native frame
114116
while (true)
115117
{
116118
uint64_t ip = 0, sp = 0;
117119
GetFrameLocation(pContext, &ip, &sp);
118120

119121
TRACE("Unwind: sp %" PRIA PRIx64 " ip %" PRIA PRIx64 "\n", sp, ip);
120-
if (ip == 0) {
122+
if (ip == 0 || sp <= previousSp) {
121123
break;
122124
}
125+
123126
// Add two pages around the instruction pointer to the core dump
124127
crashInfo.InsertMemoryRegion(ip - PAGE_SIZE, PAGE_SIZE * 2);
125128

@@ -136,6 +139,7 @@ ThreadInfo::UnwindNativeFrames(CrashInfo& crashInfo, CONTEXT* pContext)
136139
TRACE("Unwind: PAL_VirtualUnwindOutOfProc returned false\n");
137140
break;
138141
}
142+
previousSp = sp;
139143
}
140144
}
141145

src/pal/src/exception/remote-unwind.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,26 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6262

6363
SET_DEFAULT_DEBUG_CHANNEL(EXCEPT);
6464

65-
// Only used on the AMD64 build
66-
#if defined(_AMD64_) && defined(HAVE_UNW_GET_ACCESSORS)
65+
// Only used on the AMD64/ARM64 builds - ARM32 uses EXIDX which isn't currently supported
66+
#if (defined(_AMD64_) || defined(_ARM64_)) && defined(HAVE_UNW_GET_ACCESSORS)
6767

6868
#include <elf.h>
6969
#include <link.h>
7070

71+
#if defined(_X86_) || defined(_ARM_)
72+
#define PRIx PRIx32
73+
#define PRIu PRIu32
74+
#define PRId PRId32
75+
#define PRIA "08"
76+
#define PRIxA PRIA PRIx
77+
#elif defined(_AMD64_) || defined(_ARM64_)
78+
#define PRIx PRIx64
79+
#define PRIu PRIu64
80+
#define PRId PRId64
81+
#define PRIA "016"
82+
#define PRIxA PRIA PRIx
83+
#endif
84+
7185
#ifndef ElfW
7286
#define ElfW(foo) Elf_ ## foo
7387
#endif
@@ -77,7 +91,6 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT);
7791
#define Nhdr ElfW(Nhdr)
7892
#define Dyn ElfW(Dyn)
7993

80-
extern void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext);
8194
extern void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOLATILE_CONTEXT_POINTERS *contextPointers);
8295

8396
typedef struct _libunwindInfo
@@ -128,7 +141,7 @@ typedef struct _libunwindInfo
128141
#define DWARF_CIE_VERSION 3 // GCC emits version 1???
129142

130143
// DWARF frame header
131-
typedef struct _eh_frame_hdr
144+
typedef struct __attribute__((packed)) _eh_frame_hdr
132145
{
133146
unsigned char version;
134147
unsigned char eh_frame_ptr_enc;
@@ -764,6 +777,37 @@ ExtractProcInfoFromFde(const libunwindInfo* info, unw_word_t* addrp, unw_proc_in
764777
return true;
765778
}
766779

780+
static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext)
781+
{
782+
#if defined(_AMD64_)
783+
unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Rip);
784+
unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Rsp);
785+
unw_get_reg(cursor, UNW_X86_64_RBP, (unw_word_t *) &winContext->Rbp);
786+
unw_get_reg(cursor, UNW_X86_64_RBX, (unw_word_t *) &winContext->Rbx);
787+
unw_get_reg(cursor, UNW_X86_64_R12, (unw_word_t *) &winContext->R12);
788+
unw_get_reg(cursor, UNW_X86_64_R13, (unw_word_t *) &winContext->R13);
789+
unw_get_reg(cursor, UNW_X86_64_R14, (unw_word_t *) &winContext->R14);
790+
unw_get_reg(cursor, UNW_X86_64_R15, (unw_word_t *) &winContext->R15);
791+
#elif defined(_ARM64_)
792+
unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc);
793+
unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp);
794+
unw_get_reg(cursor, UNW_AARCH64_X19, (unw_word_t *) &winContext->X19);
795+
unw_get_reg(cursor, UNW_AARCH64_X20, (unw_word_t *) &winContext->X20);
796+
unw_get_reg(cursor, UNW_AARCH64_X21, (unw_word_t *) &winContext->X21);
797+
unw_get_reg(cursor, UNW_AARCH64_X22, (unw_word_t *) &winContext->X22);
798+
unw_get_reg(cursor, UNW_AARCH64_X23, (unw_word_t *) &winContext->X23);
799+
unw_get_reg(cursor, UNW_AARCH64_X24, (unw_word_t *) &winContext->X24);
800+
unw_get_reg(cursor, UNW_AARCH64_X25, (unw_word_t *) &winContext->X25);
801+
unw_get_reg(cursor, UNW_AARCH64_X26, (unw_word_t *) &winContext->X26);
802+
unw_get_reg(cursor, UNW_AARCH64_X27, (unw_word_t *) &winContext->X27);
803+
unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28);
804+
unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp);
805+
unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr);
806+
TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp);
807+
#else
808+
#error unsupported architecture
809+
#endif
810+
}
767811

768812
static int
769813
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
827871
case UNW_ARM_R10: *valp = (unw_word_t)winContext->R10; break;
828872
case UNW_ARM_R11: *valp = (unw_word_t)winContext->R11; break;
829873
#elif defined(_ARM64_)
830-
case UNW_REG_IP: *valp = (unw_word_t)winContext->Pc; break;
831-
case UNW_REG_SP: *valp = (unw_word_t)winContext->Sp; break;
874+
case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break;
875+
case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break;
832876
case UNW_AARCH64_X29: *valp = (unw_word_t)winContext->Fp; break;
833877
case UNW_AARCH64_X30: *valp = (unw_word_t)winContext->Lr; break;
834878
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
845889
#error unsupported architecture
846890
#endif
847891
default:
848-
ASSERT("Attempt to read an unknown register\n");
892+
ASSERT("Attempt to read an unknown register %d\n", regnum);
849893
return -UNW_EBADREG;
850894
}
895+
TRACE("REG: %d %p\n", regnum, *valp);
851896
return UNW_ESUCCESS;
852897
}
853898

@@ -901,7 +946,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee
901946
ERROR("ELF: reading phdrAddr %p\n", phdrAddr);
902947
return -UNW_EINVAL;
903948
}
904-
TRACE("ELF: phdr %p type %d (%x) vaddr %p memsz %016llx paddr %p filesz %016llx offset %p align %016llx\n",
949+
TRACE("ELF: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
905950
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);
906951

907952
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
941986
dynamicAddr++;
942987
}
943988
}
989+
990+
if (ehPhdr.p_offset == 0) {
991+
ASSERT("ELF: No PT_GNU_EH_FRAME program header\n");
992+
return -UNW_EINVAL;
993+
}
944994
unw_word_t ehFrameHdrAddr = ehPhdr.p_offset + info->BaseAddress;
945995
eh_frame_hdr ehFrameHdr;
946996

@@ -970,6 +1020,12 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee
9701020
}
9711021
TRACE("ehFrameStart %p fdeCount %p ip offset %08x\n", ehFrameStart, fdeCount, (int32_t)(ip - ehFrameHdrAddr));
9721022

1023+
// If there are no frame table entries
1024+
if (fdeCount == 0) {
1025+
TRACE("No frame table entries\n");
1026+
return -UNW_ENOINFO;
1027+
}
1028+
9731029
// LookupTableEntry assumes this encoding
9741030
if (ehFrameHdr.table_enc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) {
9751031
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
9961052
return -UNW_EINVAL;
9971053
}
9981054

999-
_ASSERTE(ip >= pip->start_ip && ip <= pip->end_ip);
1055+
if (ip < pip->start_ip || ip >= pip->end_ip) {
1056+
TRACE("ip %p not in range start_ip %p end_ip %p\n", ip, pip->start_ip, pip->end_ip);
1057+
return -UNW_ENOINFO;
1058+
}
10001059
return UNW_ESUCCESS;
10011060
}
10021061

@@ -1066,7 +1125,7 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont
10661125
goto exit;
10671126
}
10681127

1069-
UnwindContextToWinContext(&cursor, context);
1128+
UnwindContextToContext(&cursor, context);
10701129

10711130
if (contextPointers != NULL)
10721131
{

0 commit comments

Comments
 (0)