Skip to content

Commit 71075a0

Browse files
committed
Merge in 'release/6.0' changes
2 parents d8f7045 + 3c2d2a1 commit 71075a0

File tree

5 files changed

+118
-41
lines changed

5 files changed

+118
-41
lines changed

src/coreclr/debug/createdump/crashinfomac.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ void CrashInfo::VisitSegment(MachOModule& module, const segment_command_64& segm
277277
uint64_t start = segment.vmaddr + module.LoadBias();
278278
uint64_t end = start + segment.vmsize;
279279

280+
// Add this module segment to the set used by the thread unwinding to lookup the module base address for an ip.
281+
AddModuleAddressRange(start, end, module.BaseAddress());
282+
280283
// Round to page boundary
281284
start = start & PAGE_MASK;
282285
_ASSERTE(start > 0);
@@ -297,9 +300,6 @@ void CrashInfo::VisitSegment(MachOModule& module, const segment_command_64& segm
297300
}
298301
// Add this module segment to the module mappings list
299302
m_moduleMappings.insert(moduleRegion);
300-
301-
// Add this module segment to the set used by the thread unwinding to lookup the module base address for an ip.
302-
AddModuleAddressRange(start, end, module.BaseAddress());
303303
}
304304
else
305305
{

src/coreclr/debug/createdump/stackframe.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,16 @@ struct StackFrame
6666
}
6767
}
6868

69+
// See comment in threadinfo.cpp UnwindNativeFrames function
70+
#if defined(__aarch64__)
71+
#define STACK_POINTER_MASK ~0x7
72+
#else
73+
#define STACK_POINTER_MASK ~0x0
74+
#endif
75+
6976
inline uint64_t ModuleAddress() const { return m_moduleAddress; }
7077
inline uint64_t InstructionPointer() const { return m_instructionPointer; }
71-
inline uint64_t StackPointer() const { return m_stackPointer; }
78+
inline uint64_t StackPointer() const { return m_stackPointer & STACK_POINTER_MASK; }
7279
inline uint32_t NativeOffset() const { return m_nativeOffset; }
7380
inline uint32_t Token() const { return m_token; }
7481
inline uint32_t ILOffset() const { return m_ilOffset; }

src/coreclr/debug/createdump/threadinfo.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ ThreadInfo::UnwindNativeFrames(CONTEXT* pContext)
5353
uint64_t ip = 0, sp = 0;
5454
GetFrameLocation(pContext, &ip, &sp);
5555

56+
#if defined(__aarch64__)
57+
// ARM64 can have frames with the same SP but different IPs. Increment sp so it gets added to the stack
58+
// frames in the correct order and to prevent the below loop termination on non-increasing sp. Since stack
59+
// pointers are always 8 byte align, this increase is masked off in StackFrame::StackPointer() to get the
60+
// original stack pointer.
61+
if (sp == previousSp && ip != previousIp)
62+
{
63+
sp++;
64+
}
65+
#endif
5666
if (ip == 0 || sp <= previousSp) {
5767
TRACE_VERBOSE("Unwind: sp not increasing or ip == 0 sp %p ip %p\n", (void*)sp, (void*)ip);
5868
break;

src/coreclr/debug/dbgutil/machoreader.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,8 @@ MachOModule::ReadLoadCommands()
229229
m_segments.push_back(segment);
230230

231231
// Calculate the load bias for the module. This is the value to add to the vmaddr of a
232-
// segment to get the actual address. For shared modules, this is 0 since those segments
233-
// are absolute address.
234-
if (segment->fileoff == 0 && segment->filesize > 0)
232+
// segment to get the actual address.
233+
if (strcmp(segment->segname, SEG_TEXT) == 0)
235234
{
236235
m_loadBias = m_baseAddress - segment->vmaddr;
237236
}

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

+95-34
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5757
#include <mach-o/nlist.h>
5858
#include <mach-o/dyld_images.h>
5959
#include "compact_unwind_encoding.h"
60+
#define MACOS_ARM64_POINTER_AUTH_MASK 0x7fffffffffffull
6061
#endif
6162

6263
// Sub-headers included from the libunwind.h contain an empty struct
@@ -1422,25 +1423,56 @@ StepWithCompactNoEncoding(const libunwindInfo* info)
14221423

14231424
#if defined(TARGET_ARM64)
14241425

1425-
inline static bool
1426+
#define ARM64_SYSCALL_OPCODE 0xD4001001
1427+
#define ARM64_BL_OPCODE_MASK 0xFC000000
1428+
#define ARM64_BL_OPCODE 0x94000000
1429+
#define ARM64_BLR_OPCODE_MASK 0xFFFFFC00
1430+
#define ARM64_BLR_OPCODE 0xD63F0000
1431+
#define ARM64_BLRA_OPCODE_MASK 0xFEFFF800
1432+
#define ARM64_BLRA_OPCODE 0xD63F0800
1433+
1434+
static bool
1435+
StepWithCompactNoEncoding(const libunwindInfo* info)
1436+
{
1437+
// Check that the function is a syscall "wrapper" and assume there is no frame and pop the return address.
1438+
uint32_t opcode;
1439+
unw_word_t addr = info->Context->Pc - sizeof(opcode);
1440+
if (!ReadValue32(info, &addr, &opcode)) {
1441+
ERROR("StepWithCompactNoEncoding: can read opcode %p\n", (void*)addr);
1442+
return false;
1443+
}
1444+
// Is the IP pointing just after a "syscall" opcode?
1445+
if (opcode != ARM64_SYSCALL_OPCODE) {
1446+
ERROR("StepWithCompactNoEncoding: not in syscall wrapper function\n");
1447+
return false;
1448+
}
1449+
// Pop the return address from the stack
1450+
info->Context->Pc = info->Context->Lr;
1451+
TRACE("StepWithCompactNoEncoding: SUCCESS new pc %p sp %p\n", (void*)info->Context->Pc, (void*)info->Context->Sp);
1452+
return true;
1453+
}
1454+
1455+
static bool
14261456
ReadCompactEncodingRegister(const libunwindInfo* info, unw_word_t* addr, DWORD64* reg)
14271457
{
1428-
*addr -= sizeof(uint64_t);
1429-
if (!ReadValue64(info, addr, (uint64_t*)reg)) {
1458+
uint64_t value;
1459+
if (!info->ReadMemory((PVOID)*addr, &value, sizeof(value))) {
14301460
return false;
14311461
}
1462+
*reg = VAL64(value);
1463+
*addr -= sizeof(uint64_t);
14321464
return true;
14331465
}
14341466

1435-
inline static bool
1436-
ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWORD64*second, DWORD64* first)
1467+
static bool
1468+
ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWORD64* first, DWORD64* second)
14371469
{
14381470
// Registers are effectively pushed in pairs
14391471
//
1472+
// *first = **addr
14401473
// *addr -= 8
1441-
// **addr = *first
1474+
// *second= **addr
14421475
// *addr -= 8
1443-
// **addr = *second
14441476
if (!ReadCompactEncodingRegister(info, addr, first)) {
14451477
return false;
14461478
}
@@ -1450,8 +1482,8 @@ ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWO
14501482
return true;
14511483
}
14521484

1453-
inline static bool
1454-
ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, NEON128*second, NEON128* first)
1485+
static bool
1486+
ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, NEON128* first, NEON128* second)
14551487
{
14561488
if (!ReadCompactEncodingRegisterPair(info, addr, &first->Low, &second->Low)) {
14571489
return false;
@@ -1484,30 +1516,28 @@ static bool
14841516
StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_t compactEncoding, bool hasFrame)
14851517
{
14861518
CONTEXT* context = info->Context;
1519+
unw_word_t addr;
14871520

1488-
unw_word_t callerSp;
1489-
1490-
if (hasFrame) {
1491-
// caller Sp is callee Fp plus saved FP and LR
1492-
callerSp = context->Fp + 2 * sizeof(uint64_t);
1493-
} else {
1521+
if (hasFrame)
1522+
{
1523+
context->Sp = context->Fp + 16;
1524+
addr = context->Fp + 8;
1525+
if (!ReadCompactEncodingRegisterPair(info, &addr, &context->Lr, &context->Fp)) {
1526+
return false;
1527+
}
1528+
// Strip pointer authentication bits
1529+
context->Lr &= MACOS_ARM64_POINTER_AUTH_MASK;
1530+
}
1531+
else
1532+
{
14941533
// Get the leat significant bit in UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK
14951534
uint64_t stackSizeScale = UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK & ~(UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK - 1);
1496-
uint64_t stackSize = (compactEncoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK) / stackSizeScale * 16;
1535+
uint64_t stackSize = ((compactEncoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK) / stackSizeScale) * 16;
14971536

1498-
callerSp = context->Sp + stackSize;
1537+
addr = context->Sp + stackSize;
14991538
}
15001539

1501-
context->Sp = callerSp;
1502-
1503-
unw_word_t addr = callerSp;
1504-
1505-
if (hasFrame &&
1506-
!ReadCompactEncodingRegisterPair(info, &addr, &context->Lr, &context->Fp)) {
1507-
return false;
1508-
}
1509-
1510-
// unwound return address is stored in Lr
1540+
// Unwound return address is stored in Lr
15111541
context->Pc = context->Lr;
15121542

15131543
if (compactEncoding & UNWIND_ARM64_FRAME_X19_X20_PAIR &&
@@ -1546,7 +1576,10 @@ StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_
15461576
!ReadCompactEncodingRegisterPair(info, &addr, &context->V[14], &context->V[15])) {
15471577
return false;
15481578
}
1549-
1579+
if (!hasFrame)
1580+
{
1581+
context->Sp = addr;
1582+
}
15501583
TRACE("SUCCESS: compact step encoding %08x pc %p sp %p fp %p lr %p\n",
15511584
compactEncoding, (void*)context->Pc, (void*)context->Sp, (void*)context->Fp, (void*)context->Lr);
15521585
return true;
@@ -1557,11 +1590,11 @@ StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_
15571590
static bool
15581591
StepWithCompactEncoding(const libunwindInfo* info, compact_unwind_encoding_t compactEncoding, unw_word_t functionStart)
15591592
{
1560-
#if defined(TARGET_AMD64)
15611593
if (compactEncoding == 0)
15621594
{
15631595
return StepWithCompactNoEncoding(info);
15641596
}
1597+
#if defined(TARGET_AMD64)
15651598
switch (compactEncoding & UNWIND_X86_64_MODE_MASK)
15661599
{
15671600
case UNWIND_X86_64_MODE_RBP_FRAME:
@@ -1575,11 +1608,6 @@ StepWithCompactEncoding(const libunwindInfo* info, compact_unwind_encoding_t com
15751608
return false;
15761609
}
15771610
#elif defined(TARGET_ARM64)
1578-
if (compactEncoding == 0)
1579-
{
1580-
TRACE("Compact unwind missing for %p\n", (void*)info->Context->Pc);
1581-
return false;
1582-
}
15831611
switch (compactEncoding & UNWIND_ARM64_MODE_MASK)
15841612
{
15851613
case UNWIND_ARM64_MODE_FRAME:
@@ -1717,6 +1745,12 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext)
17171745
unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28);
17181746
unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp);
17191747
unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr);
1748+
#ifdef __APPLE__
1749+
// Strip pointer authentication bits which seem to be leaking out of libunwind
1750+
// Seems like ptrauth_strip() / __builtin_ptrauth_strip() should work, but currently
1751+
// errors with "this target does not support pointer authentication"
1752+
winContext->Pc = winContext->Pc & MACOS_ARM64_POINTER_AUTH_MASK;
1753+
#endif // __APPLE__
17201754
TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp);
17211755
#elif defined(TARGET_S390X)
17221756
unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->PSWAddr);
@@ -2126,6 +2160,33 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont
21262160
#elif defined(TARGET_ARM64)
21272161
TRACE("Unwind: pc %p sp %p fp %p\n", (void*)context->Pc, (void*)context->Sp, (void*)context->Fp);
21282162
result = GetProcInfo(context->Pc, &procInfo, &info, &step, false);
2163+
if (result && step)
2164+
{
2165+
// If the PC is at the start of the function, the previous instruction is BL and the unwind encoding is frameless
2166+
// with nothing on stack (0x02000000), back up PC by 1 to the previous function and get the unwind info for that
2167+
// function.
2168+
if ((context->Pc == procInfo.start_ip) &&
2169+
(procInfo.format & (UNWIND_ARM64_MODE_MASK | UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) == UNWIND_ARM64_MODE_FRAMELESS)
2170+
{
2171+
uint32_t opcode;
2172+
unw_word_t addr = context->Pc - sizeof(opcode);
2173+
if (ReadValue32(&info, &addr, &opcode))
2174+
{
2175+
// Is the previous instruction a BL opcode?
2176+
if ((opcode & ARM64_BL_OPCODE_MASK) == ARM64_BL_OPCODE ||
2177+
(opcode & ARM64_BLR_OPCODE_MASK) == ARM64_BLR_OPCODE ||
2178+
(opcode & ARM64_BLRA_OPCODE_MASK) == ARM64_BLRA_OPCODE)
2179+
{
2180+
TRACE("Unwind: getting unwind info for PC - 1 opcode %08x\n", opcode);
2181+
result = GetProcInfo(context->Pc - 1, &procInfo, &info, &step, false);
2182+
}
2183+
else
2184+
{
2185+
TRACE("Unwind: not BL* opcode %08x\n", opcode);
2186+
}
2187+
}
2188+
}
2189+
}
21292190
#else
21302191
#error Unexpected architecture
21312192
#endif

0 commit comments

Comments
 (0)