new libunwind, updated to netbsd b1f513eedd
existing libunwind used '0' in lsda_encoding as 'not present,' whereas that is a valid encoding and does occur and would be ignored. a missing encoding is actually 0xff. The commit that addresses this is: commit 8d4b51028d1a12b58d616f4b605254a877caafcf Author: joerg <joerg> Date: Tue Mar 11 23:52:17 2014 +0000 0 is a valid LSDA encoding and can be seen in statically linked programs. Initialize lsdaEncoding to DW_EH_PE_omit and check for that value to decide whether a value should be decoded. more bugfixes are necessary. this update is up to: commit b1f513eedd332426d88acbb118b6e9070966dcb9 Author: joerg <joerg> Date: Wed May 14 22:13:36 2014 +0000 Lazy VFP processing works a lot better if the functions contain a return instruction.
This commit is contained in:
parent
472758f313
commit
b029fb598a
9 changed files with 1838 additions and 91 deletions
|
@ -48,7 +48,6 @@ struct unw_proc_info_t {
|
||||||
uintptr_t lsda; // Address of Language Specific Data Area
|
uintptr_t lsda; // Address of Language Specific Data Area
|
||||||
uintptr_t handler; // Personality routine
|
uintptr_t handler; // Personality routine
|
||||||
uintptr_t extra_args; // Extra stack space for frameless routines
|
uintptr_t extra_args; // Extra stack space for frameless routines
|
||||||
uint32_t unwind_info_size; // Size of DWARF unwind info
|
|
||||||
uintptr_t unwind_info; // Address of DWARF unwind info
|
uintptr_t unwind_info; // Address of DWARF unwind info
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,13 +75,29 @@ public:
|
||||||
pthread_rwlock_init(&fdeTreeLock, NULL);
|
pthread_rwlock_init(&fdeTreeLock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t get8(pint_t addr) { return *((uint8_t *)addr); }
|
uint8_t get8(pint_t addr) {
|
||||||
|
uint8_t val;
|
||||||
|
memcpy(&val, (void *)addr, sizeof(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t get16(pint_t addr) { return *((uint16_t *)addr); }
|
uint16_t get16(pint_t addr) {
|
||||||
|
uint16_t val;
|
||||||
|
memcpy(&val, (void *)addr, sizeof(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get32(pint_t addr) { return *((uint32_t *)addr); }
|
uint32_t get32(pint_t addr) {
|
||||||
|
uint32_t val;
|
||||||
|
memcpy(&val, (void *)addr, sizeof(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t get64(pint_t addr) { return *((uint64_t *)addr); }
|
uint64_t get64(pint_t addr) {
|
||||||
|
uint64_t val;
|
||||||
|
memcpy(&val, (void *)addr, sizeof(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t getP(pint_t addr) {
|
uintptr_t getP(pint_t addr) {
|
||||||
if (sizeof(uintptr_t) == sizeof(uint32_t))
|
if (sizeof(uintptr_t) == sizeof(uint32_t))
|
||||||
|
@ -249,6 +264,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
if (n->hdr_start == 0) {
|
if (n->hdr_start == 0) {
|
||||||
fdeStart = n->hdr_base;
|
fdeStart = n->hdr_base;
|
||||||
|
data_base = n->data_base;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +287,7 @@ public:
|
||||||
len = (len + 1) / 2;
|
len = (len + 1) / 2;
|
||||||
}
|
}
|
||||||
fdeStart = base + (int32_t)get32(first + 4);
|
fdeStart = base + (int32_t)get32(first + 4);
|
||||||
|
data_base = n->data_base;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,9 +353,9 @@ public:
|
||||||
private:
|
private:
|
||||||
findPCRange_t findPCRange;
|
findPCRange_t findPCRange;
|
||||||
bool needsReload;
|
bool needsReload;
|
||||||
#if !defined(__minix)
|
#ifndef __minix
|
||||||
pthread_rwlock_t fdeTreeLock;
|
pthread_rwlock_t fdeTreeLock;
|
||||||
#endif /* !defined(__minix) */
|
#endif
|
||||||
rb_tree_t segmentTree;
|
rb_tree_t segmentTree;
|
||||||
rb_tree_t dsoTree;
|
rb_tree_t dsoTree;
|
||||||
|
|
||||||
|
@ -433,8 +450,8 @@ static int phdr_callback(struct dl_phdr_info *info, size_t size, void *data_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rangeCmp(void *context, const void *n1_, const void *n2_) {
|
static int rangeCmp(void *context, const void *n1_, const void *n2_) {
|
||||||
LocalAddressSpace::Range *n1 = (LocalAddressSpace::Range *)n1_;
|
const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
|
||||||
LocalAddressSpace::Range *n2 = (LocalAddressSpace::Range *)n2_;
|
const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
|
||||||
|
|
||||||
if (n1->first_pc < n2->first_pc)
|
if (n1->first_pc < n2->first_pc)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -445,8 +462,8 @@ static int rangeCmp(void *context, const void *n1_, const void *n2_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rangeCmpKey(void *context, const void *n_, const void *pc_) {
|
static int rangeCmpKey(void *context, const void *n_, const void *pc_) {
|
||||||
LocalAddressSpace::Range *n = (LocalAddressSpace::Range *)n_;
|
const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
|
||||||
LocalAddressSpace::pint_t *pc = (LocalAddressSpace::pint_t *)pc_;
|
const LocalAddressSpace::pint_t *pc = (const LocalAddressSpace::pint_t *)pc_;
|
||||||
if (n->last_pc < *pc)
|
if (n->last_pc < *pc)
|
||||||
return -1;
|
return -1;
|
||||||
if (n->first_pc > *pc)
|
if (n->first_pc > *pc)
|
||||||
|
@ -455,8 +472,8 @@ static int rangeCmpKey(void *context, const void *n_, const void *pc_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsoTableCmp(void *context, const void *n1_, const void *n2_) {
|
static int dsoTableCmp(void *context, const void *n1_, const void *n2_) {
|
||||||
LocalAddressSpace::Range *n1 = (LocalAddressSpace::Range *)n1_;
|
const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_;
|
||||||
LocalAddressSpace::Range *n2 = (LocalAddressSpace::Range *)n2_;
|
const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_;
|
||||||
|
|
||||||
if (n1->ehframe_base < n2->ehframe_base)
|
if (n1->ehframe_base < n2->ehframe_base)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -466,8 +483,8 @@ static int dsoTableCmp(void *context, const void *n1_, const void *n2_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dsoTableCmpKey(void *context, const void *n_, const void *ptr_) {
|
static int dsoTableCmpKey(void *context, const void *n_, const void *ptr_) {
|
||||||
LocalAddressSpace::Range *n = (LocalAddressSpace::Range *)n_;
|
const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_;
|
||||||
LocalAddressSpace::pint_t *ptr = (LocalAddressSpace::pint_t *)ptr_;
|
const LocalAddressSpace::pint_t *ptr = (const LocalAddressSpace::pint_t *)ptr_;
|
||||||
if (n->ehframe_base < *ptr)
|
if (n->ehframe_base < *ptr)
|
||||||
return -1;
|
return -1;
|
||||||
if (n->ehframe_base > *ptr)
|
if (n->ehframe_base > *ptr)
|
||||||
|
|
|
@ -39,12 +39,6 @@ public:
|
||||||
static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
|
static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Pseudo-register used for return addresses.
|
|
||||||
enum {
|
|
||||||
DW_X86_RET_ADDR = 8,
|
|
||||||
DW_X86_64_RET_ADDR = 16,
|
|
||||||
};
|
|
||||||
|
|
||||||
static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
|
static pint_t evaluateExpression(pint_t, A &, const R &, pint_t);
|
||||||
static pint_t
|
static pint_t
|
||||||
getSavedRegister(A &, const R &, pint_t,
|
getSavedRegister(A &, const R &, pint_t,
|
||||||
|
@ -54,9 +48,6 @@ private:
|
||||||
const typename CFI_Parser<A, R>::RegisterLocation &);
|
const typename CFI_Parser<A, R>::RegisterLocation &);
|
||||||
|
|
||||||
static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
|
static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; }
|
||||||
static bool isReturnAddressRegister(int regno, const R &) {
|
|
||||||
return regno == R::IP_PSEUDO_REG;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pint_t getCFA(A &addressSpace,
|
static pint_t getCFA(A &addressSpace,
|
||||||
const typename CFI_Parser<A, R>::PrologInfo &prolog,
|
const typename CFI_Parser<A, R>::PrologInfo &prolog,
|
||||||
|
@ -145,7 +136,7 @@ step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
|
||||||
for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
|
for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
|
||||||
if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
|
if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused)
|
||||||
continue;
|
continue;
|
||||||
if (isReturnAddressRegister(i, registers))
|
if (i == (int)cieInfo.returnAddressRegister)
|
||||||
returnAddress = getSavedRegister(addressSpace, registers, cfa,
|
returnAddress = getSavedRegister(addressSpace, registers, cfa,
|
||||||
prolog.savedRegisters[i]);
|
prolog.savedRegisters[i]);
|
||||||
else if (registers.validRegister(i))
|
else if (registers.validRegister(i))
|
||||||
|
@ -162,7 +153,7 @@ step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
|
||||||
// The CFA is defined as the stack pointer at the call site.
|
// The CFA is defined as the stack pointer at the call site.
|
||||||
// Therefore the SP is restored by setting it to the CFA.
|
// Therefore the SP is restored by setting it to the CFA.
|
||||||
newRegisters.setSP(cfa);
|
newRegisters.setSP(cfa);
|
||||||
newRegisters.setIP(returnAddress);
|
newRegisters.setIP(returnAddress + R::RETURN_OFFSET);
|
||||||
|
|
||||||
// Now replace register set with the working copy.
|
// Now replace register set with the working copy.
|
||||||
registers = newRegisters;
|
registers = newRegisters;
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
uint8_t personalityOffsetInCIE;
|
uint8_t personalityOffsetInCIE;
|
||||||
bool isSignalFrame;
|
bool isSignalFrame;
|
||||||
bool fdesHaveAugmentationData;
|
bool fdesHaveAugmentationData;
|
||||||
|
uint8_t returnAddressRegister;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Information about an FDE (Frame Description Entry)
|
/// Information about an FDE (Frame Description Entry)
|
||||||
|
@ -172,7 +173,7 @@ bool CFI_Parser<A, R>::decodeFDE(A &addressSpace, pint_t fdeStart,
|
||||||
if (cieInfo->fdesHaveAugmentationData) {
|
if (cieInfo->fdesHaveAugmentationData) {
|
||||||
uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
|
uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
|
||||||
pint_t endOfAug = p + augLen;
|
pint_t endOfAug = p + augLen;
|
||||||
if (cieInfo->lsdaEncoding != 0) {
|
if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
|
||||||
// Peek at value (without indirection). Zero means no LSDA.
|
// Peek at value (without indirection). Zero means no LSDA.
|
||||||
pint_t lsdaStart = p;
|
pint_t lsdaStart = p;
|
||||||
if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F,
|
if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F,
|
||||||
|
@ -198,7 +199,7 @@ template <typename A, typename R>
|
||||||
bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
|
bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
|
||||||
CIE_Info *cieInfo) {
|
CIE_Info *cieInfo) {
|
||||||
cieInfo->pointerEncoding = 0;
|
cieInfo->pointerEncoding = 0;
|
||||||
cieInfo->lsdaEncoding = 0;
|
cieInfo->lsdaEncoding = DW_EH_PE_omit;
|
||||||
cieInfo->personalityEncoding = 0;
|
cieInfo->personalityEncoding = 0;
|
||||||
cieInfo->personalityOffsetInCIE = 0;
|
cieInfo->personalityOffsetInCIE = 0;
|
||||||
cieInfo->personality = 0;
|
cieInfo->personality = 0;
|
||||||
|
@ -238,7 +239,7 @@ bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
|
||||||
// Parse data alignment factor
|
// Parse data alignment factor
|
||||||
cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
|
cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
|
||||||
// Parse return address register
|
// Parse return address register
|
||||||
addressSpace.getULEB128(p, cieContentEnd);
|
cieInfo->returnAddressRegister = (uint8_t)addressSpace.getULEB128(p, cieContentEnd);
|
||||||
// Parse augmentation data based on augmentation string.
|
// Parse augmentation data based on augmentation string.
|
||||||
if (addressSpace.get8(strStart) == 'z') {
|
if (addressSpace.get8(strStart) == 'z') {
|
||||||
// parse augmentation data length
|
// parse augmentation data length
|
||||||
|
@ -460,6 +461,8 @@ CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions,
|
||||||
reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
|
reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
|
||||||
offset =
|
offset =
|
||||||
addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
|
||||||
|
if (reg > kMaxRegisterNumber)
|
||||||
|
return false;
|
||||||
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
|
results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
|
||||||
results->savedRegisters[reg].value = offset;
|
results->savedRegisters[reg].value = offset;
|
||||||
break;
|
break;
|
||||||
|
@ -481,6 +484,20 @@ CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions,
|
||||||
length = addressSpace.getULEB128(p, instructionsEnd);
|
length = addressSpace.getULEB128(p, instructionsEnd);
|
||||||
p += length;
|
p += length;
|
||||||
break;
|
break;
|
||||||
|
case DW_CFA_GNU_window_save:
|
||||||
|
#if defined(__sparc__)
|
||||||
|
for (reg = 8; reg < 16; ++reg) {
|
||||||
|
results->savedRegisters[reg].location = kRegisterInRegister;
|
||||||
|
results->savedRegisters[reg].value = reg + 16;
|
||||||
|
}
|
||||||
|
for (reg = 16; reg < 32; ++reg) {
|
||||||
|
results->savedRegisters[reg].location = kRegisterInCFA;
|
||||||
|
results->savedRegisters[reg].value = (reg - 16) * sizeof(typename R::reg_t);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
case DW_CFA_GNU_args_size:
|
case DW_CFA_GNU_args_size:
|
||||||
offset = addressSpace.getULEB128(p, instructionsEnd);
|
offset = addressSpace.getULEB128(p, instructionsEnd);
|
||||||
results->spExtraArgSize = offset;
|
results->spExtraArgSize = offset;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# $NetBSD: Makefile.inc,v 1.1 2013/10/14 01:14:57 joerg Exp $
|
# $NetBSD: Makefile.inc,v 1.5 2014/03/19 16:46:23 joerg Exp $
|
||||||
|
|
||||||
.PATH: ${NETBSDSRCDIR}/sys/lib/libunwind
|
.PATH: ${NETBSDSRCDIR}/sys/lib/libunwind
|
||||||
|
|
||||||
|
@ -7,4 +7,15 @@ SRCS+= libunwind.cxx \
|
||||||
|
|
||||||
INCS+= unwind.h
|
INCS+= unwind.h
|
||||||
|
|
||||||
COPTS.libuwind.cxx+= -funwind-tables -fno-rtti -fno-exceptions -fvisibility=hidden -Wno-old-style-cast
|
.if ${HAVE_GCC:U48} == "4"
|
||||||
|
CLEANFILES+= cstdint
|
||||||
|
DPSRCS+= cstdint
|
||||||
|
|
||||||
|
cstdint:
|
||||||
|
echo '#include <stdint.h>' > ${.TARGET}
|
||||||
|
|
||||||
|
COPTS.libunwind.cxx+= "-D__builtin_unreachable()=abort()"
|
||||||
|
.else
|
||||||
|
COPTS.libunwind.cxx+= ${${ACTIVE_CXX} == "gcc":? -std=c++0x : -std=c++11 }
|
||||||
|
.endif
|
||||||
|
COPTS.libunwind.cxx+= -funwind-tables -fno-rtti -fno-exceptions -fvisibility=hidden -Wno-old-style-cast
|
||||||
|
|
|
@ -32,9 +32,9 @@ enum {
|
||||||
class Registers_x86 {
|
class Registers_x86 {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
LAST_RESTORE_REG = REGNO_X86_EIP,
|
|
||||||
IP_PSEUDO_REG = REGNO_X86_EIP,
|
|
||||||
LAST_REGISTER = REGNO_X86_EIP,
|
LAST_REGISTER = REGNO_X86_EIP,
|
||||||
|
LAST_RESTORE_REG = REGNO_X86_EIP,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
__dso_hidden Registers_x86();
|
__dso_hidden Registers_x86();
|
||||||
|
@ -97,9 +97,9 @@ enum {
|
||||||
class Registers_x86_64 {
|
class Registers_x86_64 {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
LAST_RESTORE_REG = REGNO_X86_64_RIP,
|
|
||||||
IP_PSEUDO_REG = REGNO_X86_64_RIP,
|
|
||||||
LAST_REGISTER = REGNO_X86_64_RIP,
|
LAST_REGISTER = REGNO_X86_64_RIP,
|
||||||
|
LAST_RESTORE_REG = REGNO_X86_64_RIP,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
__dso_hidden Registers_x86_64();
|
__dso_hidden Registers_x86_64();
|
||||||
|
@ -144,19 +144,18 @@ enum {
|
||||||
DWARF_PPC32_R31 = 31,
|
DWARF_PPC32_R31 = 31,
|
||||||
DWARF_PPC32_F0 = 32,
|
DWARF_PPC32_F0 = 32,
|
||||||
DWARF_PPC32_F31 = 63,
|
DWARF_PPC32_F31 = 63,
|
||||||
DWARF_PPC32_V0 = 1124,
|
|
||||||
DWARF_PPC32_V31 = 1155,
|
|
||||||
DWARF_PPC32_LR = 65,
|
DWARF_PPC32_LR = 65,
|
||||||
DWARF_PPC32_CTR = 66,
|
DWARF_PPC32_CR = 70,
|
||||||
DWARF_PPC32_XER = 76,
|
DWARF_PPC32_V0 = 77,
|
||||||
|
DWARF_PPC32_V31 = 108,
|
||||||
|
|
||||||
REGNO_PPC32_R0 = 0,
|
REGNO_PPC32_R0 = 0,
|
||||||
REGNO_PPC32_R1 = 0,
|
REGNO_PPC32_R1 = 1,
|
||||||
REGNO_PPC32_R31 = 31,
|
REGNO_PPC32_R31 = 31,
|
||||||
REGNO_PPC32_CR = 32,
|
REGNO_PPC32_LR = 32,
|
||||||
REGNO_PPC32_LR = 33,
|
REGNO_PPC32_CR = 33,
|
||||||
REGNO_PPC32_CTR = 34,
|
REGNO_PPC32_SRR0 = 34,
|
||||||
REGNO_PPC32_XER = 35,
|
|
||||||
REGNO_PPC32_SRR0 = 36,
|
|
||||||
REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
|
REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1,
|
||||||
REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
|
REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31,
|
||||||
REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
|
REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1,
|
||||||
|
@ -166,9 +165,9 @@ enum {
|
||||||
class Registers_ppc32 {
|
class Registers_ppc32 {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
LAST_RESTORE_REG = REGNO_PPC32_V31,
|
|
||||||
IP_PSEUDO_REG = REGNO_PPC32_SRR0,
|
|
||||||
LAST_REGISTER = REGNO_PPC32_V31,
|
LAST_REGISTER = REGNO_PPC32_V31,
|
||||||
|
LAST_RESTORE_REG = REGNO_PPC32_V31,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
__dso_hidden Registers_ppc32();
|
__dso_hidden Registers_ppc32();
|
||||||
|
@ -180,7 +179,14 @@ public:
|
||||||
return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
|
return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0);
|
||||||
if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
|
if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31)
|
||||||
return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
|
return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0);
|
||||||
return LAST_REGISTER + 1;
|
switch (num) {
|
||||||
|
case DWARF_PPC32_LR:
|
||||||
|
return REGNO_PPC32_LR;
|
||||||
|
case DWARF_PPC32_CR:
|
||||||
|
return REGNO_PPC32_CR;
|
||||||
|
default:
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validRegister(int num) const {
|
bool validRegister(int num) const {
|
||||||
|
@ -225,10 +231,747 @@ private:
|
||||||
uint64_t low, high;
|
uint64_t low, high;
|
||||||
};
|
};
|
||||||
uint32_t reg[REGNO_PPC32_SRR0 + 1];
|
uint32_t reg[REGNO_PPC32_SRR0 + 1];
|
||||||
|
uint32_t dummy;
|
||||||
uint64_t fpreg[32];
|
uint64_t fpreg[32];
|
||||||
vecreg_t vecreg[64];
|
vecreg_t vecreg[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_ARM32_R0 = 0,
|
||||||
|
DWARF_ARM32_R15 = 15,
|
||||||
|
DWARF_ARM32_SPSR = 128,
|
||||||
|
DWARF_ARM32_OLD_S0 = 64,
|
||||||
|
DWARF_ARM32_OLD_S31 = 91,
|
||||||
|
DWARF_ARM32_D0 = 256,
|
||||||
|
DWARF_ARM32_D31 = 287,
|
||||||
|
REGNO_ARM32_R0 = 0,
|
||||||
|
REGNO_ARM32_SP = 13,
|
||||||
|
REGNO_ARM32_R15 = 15,
|
||||||
|
REGNO_ARM32_SPSR = 16,
|
||||||
|
REGNO_ARM32_D0 = 17,
|
||||||
|
REGNO_ARM32_D15 = 32,
|
||||||
|
REGNO_ARM32_D31 = 48,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_arm32 {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_ARM32_D31,
|
||||||
|
LAST_RESTORE_REG = REGNO_ARM32_D31,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_arm32();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15)
|
||||||
|
return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0);
|
||||||
|
if (num == DWARF_ARM32_SPSR)
|
||||||
|
return REGNO_ARM32_SPSR;
|
||||||
|
if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31)
|
||||||
|
return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0);
|
||||||
|
if (num >= DWARF_ARM32_OLD_S0 && num <= DWARF_ARM32_OLD_S31) {
|
||||||
|
assert(num % 2 == 0);
|
||||||
|
return REGNO_ARM32_D0 + (num - DWARF_ARM32_OLD_S0) / 2;
|
||||||
|
}
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_ARM32_SPSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_ARM32_R15]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_ARM32_SP]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_D31);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
if (num <= REGNO_ARM32_D15) {
|
||||||
|
if ((flags & 1) == 0) {
|
||||||
|
lazyVFP1();
|
||||||
|
flags |= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((flags & 2) == 0) {
|
||||||
|
lazyVFP3();
|
||||||
|
flags |= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void lazyVFP1();
|
||||||
|
__dso_hidden void lazyVFP3();
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_ARM32_SPSR + 1];
|
||||||
|
uint32_t flags;
|
||||||
|
uint64_t fpreg[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_VAX_R0 = 0,
|
||||||
|
DWARF_VAX_R15 = 15,
|
||||||
|
DWARF_VAX_PSW = 16,
|
||||||
|
|
||||||
|
REGNO_VAX_R0 = 0,
|
||||||
|
REGNO_VAX_R14 = 14,
|
||||||
|
REGNO_VAX_R15 = 15,
|
||||||
|
REGNO_VAX_PSW = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_vax {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_VAX_PSW,
|
||||||
|
LAST_RESTORE_REG = REGNO_VAX_PSW,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_vax();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15)
|
||||||
|
return REGNO_VAX_R0 + (num - DWARF_VAX_R0);
|
||||||
|
if (num == DWARF_VAX_PSW)
|
||||||
|
return REGNO_VAX_PSW;
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= LAST_RESTORE_REG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_VAX_R15]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_VAX_R14]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_VAX_PSW + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_M68K_A0 = 0,
|
||||||
|
DWARF_M68K_A7 = 7,
|
||||||
|
DWARF_M68K_D0 = 8,
|
||||||
|
DWARF_M68K_D7 = 15,
|
||||||
|
DWARF_M68K_FP0 = 16,
|
||||||
|
DWARF_M68K_FP7 = 23,
|
||||||
|
DWARF_M68K_PC = 24,
|
||||||
|
|
||||||
|
REGNO_M68K_A0 = 0,
|
||||||
|
REGNO_M68K_A7 = 7,
|
||||||
|
REGNO_M68K_D0 = 8,
|
||||||
|
REGNO_M68K_D7 = 15,
|
||||||
|
REGNO_M68K_PC = 16,
|
||||||
|
REGNO_M68K_FP0 = 17,
|
||||||
|
REGNO_M68K_FP7 = 24,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_M68K {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_M68K_FP7,
|
||||||
|
LAST_RESTORE_REG = REGNO_M68K_FP7,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_M68K();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7)
|
||||||
|
return REGNO_M68K_A0 + (num - DWARF_M68K_A0);
|
||||||
|
if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7)
|
||||||
|
return REGNO_M68K_D0 + (num - DWARF_M68K_D0);
|
||||||
|
if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7)
|
||||||
|
return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0);
|
||||||
|
if (num == DWARF_M68K_PC)
|
||||||
|
return REGNO_M68K_PC;
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_M68K_PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_M68K_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_M68K_A7]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
assert(validFloatVectorRegister(num));
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef uint32_t fpreg_t[3];
|
||||||
|
|
||||||
|
uint32_t reg[REGNO_M68K_PC + 1];
|
||||||
|
uint32_t dummy;
|
||||||
|
fpreg_t fpreg[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_SH3_R0 = 0,
|
||||||
|
DWARF_SH3_R15 = 15,
|
||||||
|
DWARF_SH3_PC = 16,
|
||||||
|
DWARF_SH3_PR = 17,
|
||||||
|
|
||||||
|
REGNO_SH3_R0 = 0,
|
||||||
|
REGNO_SH3_R15 = 15,
|
||||||
|
REGNO_SH3_PC = 16,
|
||||||
|
REGNO_SH3_PR = 17,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_SH3 {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_SH3_PR,
|
||||||
|
LAST_RESTORE_REG = REGNO_SH3_PR,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_SH3();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15)
|
||||||
|
return REGNO_SH3_R0 + (num - DWARF_SH3_R0);
|
||||||
|
if (num == DWARF_SH3_PC)
|
||||||
|
return REGNO_SH3_PC;
|
||||||
|
if (num == DWARF_SH3_PR)
|
||||||
|
return REGNO_SH3_PR;
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_SH3_PR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_SH3_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_SH3_R15]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const { return false; }
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_SH3_PR + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_SPARC64_R0 = 0,
|
||||||
|
DWARF_SPARC64_R31 = 31,
|
||||||
|
DWARF_SPARC64_PC = 32,
|
||||||
|
|
||||||
|
REGNO_SPARC64_R0 = 0,
|
||||||
|
REGNO_SPARC64_R14 = 14,
|
||||||
|
REGNO_SPARC64_R15 = 15,
|
||||||
|
REGNO_SPARC64_R31 = 31,
|
||||||
|
REGNO_SPARC64_PC = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_SPARC64 {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_SPARC64_PC,
|
||||||
|
LAST_RESTORE_REG = REGNO_SPARC64_PC,
|
||||||
|
RETURN_OFFSET = 8,
|
||||||
|
};
|
||||||
|
typedef uint64_t reg_t;
|
||||||
|
|
||||||
|
__dso_hidden Registers_SPARC64();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31)
|
||||||
|
return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0);
|
||||||
|
if (num == DWARF_SPARC64_PC)
|
||||||
|
return REGNO_SPARC64_PC;
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_SPARC64_PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const { return false; }
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t reg[REGNO_SPARC64_PC + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_SPARC_R0 = 0,
|
||||||
|
DWARF_SPARC_R31 = 31,
|
||||||
|
DWARF_SPARC_PC = 32,
|
||||||
|
|
||||||
|
REGNO_SPARC_R0 = 0,
|
||||||
|
REGNO_SPARC_R14 = 14,
|
||||||
|
REGNO_SPARC_R15 = 15,
|
||||||
|
REGNO_SPARC_R31 = 31,
|
||||||
|
REGNO_SPARC_PC = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_SPARC {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_SPARC_PC,
|
||||||
|
LAST_RESTORE_REG = REGNO_SPARC_PC,
|
||||||
|
RETURN_OFFSET = 8,
|
||||||
|
};
|
||||||
|
typedef uint32_t reg_t;
|
||||||
|
|
||||||
|
__dso_hidden Registers_SPARC();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31)
|
||||||
|
return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0);
|
||||||
|
if (num == DWARF_SPARC_PC)
|
||||||
|
return REGNO_SPARC_PC;
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_SPARC_PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_SPARC_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_SPARC_R14]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const { return false; }
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_SPARC_PC + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_ALPHA_R0 = 0,
|
||||||
|
DWARF_ALPHA_R30 = 30,
|
||||||
|
DWARF_ALPHA_F0 = 32,
|
||||||
|
DWARF_ALPHA_F30 = 62,
|
||||||
|
|
||||||
|
REGNO_ALPHA_R0 = 0,
|
||||||
|
REGNO_ALPHA_R26 = 26,
|
||||||
|
REGNO_ALPHA_R30 = 30,
|
||||||
|
REGNO_ALPHA_PC = 31,
|
||||||
|
REGNO_ALPHA_F0 = 32,
|
||||||
|
REGNO_ALPHA_F30 = 62,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_Alpha {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_ALPHA_F30,
|
||||||
|
LAST_RESTORE_REG = REGNO_ALPHA_F30,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
typedef uint32_t reg_t;
|
||||||
|
|
||||||
|
__dso_hidden Registers_Alpha();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) { return num; }
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= 0 && num <= REGNO_ALPHA_PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
assert(validFloatVectorRegister(num));
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t reg[REGNO_ALPHA_PC + 1];
|
||||||
|
uint64_t fpreg[31];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_HPPA_R1 = 1,
|
||||||
|
DWARF_HPPA_R31 = 31,
|
||||||
|
DWARF_HPPA_FR4L = 32,
|
||||||
|
DWARF_HPPA_FR31H = 87,
|
||||||
|
|
||||||
|
REGNO_HPPA_PC = 0,
|
||||||
|
REGNO_HPPA_R1 = 1,
|
||||||
|
REGNO_HPPA_R2 = 2,
|
||||||
|
REGNO_HPPA_R30 = 30,
|
||||||
|
REGNO_HPPA_R31 = 31,
|
||||||
|
REGNO_HPPA_FR4L = 32,
|
||||||
|
REGNO_HPPA_FR31H = 87,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_HPPA {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_HPPA_FR31H,
|
||||||
|
LAST_RESTORE_REG = REGNO_HPPA_FR31H,
|
||||||
|
RETURN_OFFSET = -3, // strictly speaking, this is a mask
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_HPPA();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31)
|
||||||
|
return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1);
|
||||||
|
if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H)
|
||||||
|
return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H);
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_HPPA_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_HPPA_R30]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
assert(validFloatVectorRegister(num));
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_HPPA_R31 + 1];
|
||||||
|
uint32_t fpreg[56];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_MIPS_R1 = 0,
|
||||||
|
DWARF_MIPS_R31 = 31,
|
||||||
|
DWARF_MIPS_F0 = 32,
|
||||||
|
DWARF_MIPS_F31 = 63,
|
||||||
|
|
||||||
|
REGNO_MIPS_PC = 0,
|
||||||
|
REGNO_MIPS_R1 = 0,
|
||||||
|
REGNO_MIPS_R29 = 29,
|
||||||
|
REGNO_MIPS_R31 = 31,
|
||||||
|
REGNO_MIPS_F0 = 33,
|
||||||
|
REGNO_MIPS_F31 = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_MIPS {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_MIPS_F31,
|
||||||
|
LAST_RESTORE_REG = REGNO_MIPS_F31,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_MIPS();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31)
|
||||||
|
return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1);
|
||||||
|
if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31)
|
||||||
|
return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0);
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_MIPS_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_MIPS_R29]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
assert(validFloatVectorRegister(num));
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t reg[REGNO_MIPS_R31 + 1];
|
||||||
|
uint64_t fpreg[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DWARF_MIPS64_R1 = 0,
|
||||||
|
DWARF_MIPS64_R31 = 31,
|
||||||
|
DWARF_MIPS64_F0 = 32,
|
||||||
|
DWARF_MIPS64_F31 = 63,
|
||||||
|
|
||||||
|
REGNO_MIPS64_PC = 0,
|
||||||
|
REGNO_MIPS64_R1 = 0,
|
||||||
|
REGNO_MIPS64_R29 = 29,
|
||||||
|
REGNO_MIPS64_R31 = 31,
|
||||||
|
REGNO_MIPS64_F0 = 33,
|
||||||
|
REGNO_MIPS64_F31 = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
class Registers_MIPS64 {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
LAST_REGISTER = REGNO_MIPS64_F31,
|
||||||
|
LAST_RESTORE_REG = REGNO_MIPS64_F31,
|
||||||
|
RETURN_OFFSET = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
__dso_hidden Registers_MIPS64();
|
||||||
|
|
||||||
|
static int dwarf2regno(int num) {
|
||||||
|
if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31)
|
||||||
|
return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1);
|
||||||
|
if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31)
|
||||||
|
return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0);
|
||||||
|
return LAST_REGISTER + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validRegister(int num) const {
|
||||||
|
return num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getRegister(int num) const {
|
||||||
|
assert(validRegister(num));
|
||||||
|
return reg[num];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRegister(int num, uint64_t value) {
|
||||||
|
assert(validRegister(num));
|
||||||
|
reg[num] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; }
|
||||||
|
|
||||||
|
void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; }
|
||||||
|
|
||||||
|
uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; }
|
||||||
|
|
||||||
|
void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; }
|
||||||
|
|
||||||
|
bool validFloatVectorRegister(int num) const {
|
||||||
|
return num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyFloatVectorRegister(int num, uint64_t addr_) {
|
||||||
|
assert(validFloatVectorRegister(num));
|
||||||
|
const void *addr = reinterpret_cast<const void *>(addr_);
|
||||||
|
memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
__dso_hidden void jumpto() const __dead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t reg[REGNO_MIPS64_R31 + 1];
|
||||||
|
uint64_t fpreg[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if __i386__
|
||||||
|
typedef Registers_x86 NativeUnwindRegisters;
|
||||||
|
#elif __x86_64__
|
||||||
|
typedef Registers_x86_64 NativeUnwindRegisters;
|
||||||
|
#elif __powerpc__
|
||||||
|
typedef Registers_ppc32 NativeUnwindRegisters;
|
||||||
|
#elif __arm__
|
||||||
|
typedef Registers_arm32 NativeUnwindRegisters;
|
||||||
|
#elif __vax__
|
||||||
|
typedef Registers_vax NativeUnwindRegisters;
|
||||||
|
#elif __m68k__
|
||||||
|
typedef Registers_M68K NativeUnwindRegisters;
|
||||||
|
#elif __mips_n64 || __mips_n32
|
||||||
|
typedef Registers_MIPS64 NativeUnwindRegisters;
|
||||||
|
#elif __mips__
|
||||||
|
typedef Registers_MIPS NativeUnwindRegisters;
|
||||||
|
#elif __sh3__
|
||||||
|
typedef Registers_SH3 NativeUnwindRegisters;
|
||||||
|
#elif __sparc64__
|
||||||
|
typedef Registers_SPARC64 NativeUnwindRegisters;
|
||||||
|
#elif __sparc__
|
||||||
|
typedef Registers_SPARC NativeUnwindRegisters;
|
||||||
|
#elif __alpha__
|
||||||
|
typedef Registers_Alpha NativeUnwindRegisters;
|
||||||
|
#elif __hppa__
|
||||||
|
typedef Registers_HPPA NativeUnwindRegisters;
|
||||||
|
#endif
|
||||||
} // namespace _Unwind
|
} // namespace _Unwind
|
||||||
|
|
||||||
#endif // __REGISTERS_HPP__
|
#endif // __REGISTERS_HPP__
|
||||||
|
|
|
@ -63,6 +63,9 @@ public:
|
||||||
this->setInfoBasedOnIPRegister(true);
|
this->setInfoBasedOnIPRegister(true);
|
||||||
if (fUnwindInfoMissing)
|
if (fUnwindInfoMissing)
|
||||||
return UNW_STEP_END;
|
return UNW_STEP_END;
|
||||||
|
|
||||||
|
if (fInfo.extra_args)
|
||||||
|
setSP(getSP() + fInfo.extra_args);
|
||||||
return UNW_STEP_SUCCESS;
|
return UNW_STEP_SUCCESS;
|
||||||
}
|
}
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
|
@ -134,7 +137,6 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
||||||
fInfo.handler = cieInfo.personality;
|
fInfo.handler = cieInfo.personality;
|
||||||
fInfo.extra_args = prolog.spExtraArgSize;
|
fInfo.extra_args = prolog.spExtraArgSize;
|
||||||
fInfo.unwind_info = fdeInfo.fdeStart;
|
fInfo.unwind_info = fdeInfo.fdeStart;
|
||||||
fInfo.unwind_info_size = fdeInfo.fdeLength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace _Unwind
|
}; // namespace _Unwind
|
||||||
|
|
|
@ -17,22 +17,12 @@
|
||||||
|
|
||||||
using namespace _Unwind;
|
using namespace _Unwind;
|
||||||
|
|
||||||
#if __i386__
|
typedef CFI_Parser<LocalAddressSpace, NativeUnwindRegisters> MyCFIParser;
|
||||||
typedef Registers_x86 ThisUnwindRegisters;
|
|
||||||
#elif __x86_64__
|
|
||||||
typedef Registers_x86_64 ThisUnwindRegisters;
|
|
||||||
#elif __powerpc__
|
|
||||||
typedef Registers_ppc32 ThisUnwindRegisters;
|
|
||||||
#else
|
|
||||||
#error Unsupported architecture
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef CFI_Parser<LocalAddressSpace, ThisUnwindRegisters> MyCFIParser;
|
|
||||||
|
|
||||||
// Internal object representing the address space of this process.
|
// Internal object representing the address space of this process.
|
||||||
static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange);
|
static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange);
|
||||||
|
|
||||||
typedef UnwindCursor<LocalAddressSpace, ThisUnwindRegisters> ThisUnwindCursor;
|
typedef UnwindCursor<LocalAddressSpace, NativeUnwindRegisters> ThisUnwindCursor;
|
||||||
|
|
||||||
static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor,
|
static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor,
|
||||||
struct _Unwind_Exception *exc) {
|
struct _Unwind_Exception *exc) {
|
||||||
|
@ -197,7 +187,7 @@ static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor,
|
||||||
}
|
}
|
||||||
|
|
||||||
_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
|
_Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
|
||||||
ThisUnwindRegisters registers;
|
NativeUnwindRegisters registers;
|
||||||
ThisUnwindCursor cursor1(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor1(registers, sThisAddressSpace);
|
||||||
ThisUnwindCursor cursor2(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor2(registers, sThisAddressSpace);
|
||||||
|
|
||||||
|
@ -216,7 +206,7 @@ _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
|
||||||
|
|
||||||
_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
|
_Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
|
||||||
_Unwind_Stop_Fn stop, void *stop_arg) {
|
_Unwind_Stop_Fn stop, void *stop_arg) {
|
||||||
ThisUnwindRegisters registers;
|
NativeUnwindRegisters registers;
|
||||||
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
||||||
|
|
||||||
// Mark this as forced unwind for _Unwind_Resume().
|
// Mark this as forced unwind for _Unwind_Resume().
|
||||||
|
@ -227,7 +217,7 @@ _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Unwind_Resume(struct _Unwind_Exception *exc) {
|
void _Unwind_Resume(struct _Unwind_Exception *exc) {
|
||||||
ThisUnwindRegisters registers;
|
NativeUnwindRegisters registers;
|
||||||
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
||||||
|
|
||||||
if (exc->private_1 != 0)
|
if (exc->private_1 != 0)
|
||||||
|
@ -273,17 +263,18 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
|
||||||
return cursor->getIP();
|
return cursor->getIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) {
|
||||||
|
ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
|
||||||
|
*isSignalFrame = cursor->isSignalFrame() ? 1 : 0;
|
||||||
|
return cursor->getIP();
|
||||||
|
}
|
||||||
|
|
||||||
void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) {
|
void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) {
|
||||||
ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
|
ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
|
||||||
cursor->setIP(new_value);
|
cursor->setIP(new_value);
|
||||||
unw_proc_info_t info;
|
unw_proc_info_t info;
|
||||||
cursor->getInfo(&info);
|
cursor->getInfo(&info);
|
||||||
uint64_t orgArgSize = info.extra_args;
|
|
||||||
uint64_t orgFuncStart = info.start_ip;
|
|
||||||
cursor->setInfoBasedOnIPRegister(false);
|
cursor->setInfoBasedOnIPRegister(false);
|
||||||
// Adjust REG_SP if there was a DW_CFA_GNU_args_size.
|
|
||||||
if (orgFuncStart == info.start_ip && orgArgSize != 0)
|
|
||||||
cursor->setSP(cursor->getSP() + orgArgSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) {
|
uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) {
|
||||||
|
@ -301,7 +292,7 @@ uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
|
_Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
|
||||||
ThisUnwindRegisters registers;
|
NativeUnwindRegisters registers;
|
||||||
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
||||||
cursor.setInfoBasedOnIPRegister();
|
cursor.setInfoBasedOnIPRegister();
|
||||||
|
|
||||||
|
@ -327,7 +318,7 @@ uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_Unwind_FindEnclosingFunction(void *pc) {
|
void *_Unwind_FindEnclosingFunction(void *pc) {
|
||||||
ThisUnwindRegisters registers;
|
NativeUnwindRegisters registers;
|
||||||
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
ThisUnwindCursor cursor(registers, sThisAddressSpace);
|
||||||
|
|
||||||
unw_proc_info_t info;
|
unw_proc_info_t info;
|
||||||
|
|
|
@ -67,6 +67,7 @@ void _Unwind_DeleteException(struct _Unwind_Exception *);
|
||||||
uintptr_t _Unwind_GetGR(struct _Unwind_Context *, int);
|
uintptr_t _Unwind_GetGR(struct _Unwind_Context *, int);
|
||||||
void _Unwind_SetGR(struct _Unwind_Context *, int, uintptr_t);
|
void _Unwind_SetGR(struct _Unwind_Context *, int, uintptr_t);
|
||||||
uintptr_t _Unwind_GetIP(struct _Unwind_Context *);
|
uintptr_t _Unwind_GetIP(struct _Unwind_Context *);
|
||||||
|
uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *, int *);
|
||||||
uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
|
uintptr_t _Unwind_GetCFA(struct _Unwind_Context *);
|
||||||
void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t);
|
void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t);
|
||||||
uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *);
|
uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue