mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
Initial implementation of CFI based stack unwinding for arm64-linux.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13774
This commit is contained in:
parent
0a13c57c35
commit
68a2a4ce01
@ -2115,7 +2115,7 @@ UWord evalCfiExpr ( XArray* exprs, Int ix,
|
||||
case Creg_MIPS_RA: return eec->uregs->ra;
|
||||
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
# elif defined(VGP_arm64_linux)
|
||||
I_die_here;
|
||||
case Creg_ARM64_X30: return eec->uregs->x30;
|
||||
# else
|
||||
# error "Unsupported arch"
|
||||
# endif
|
||||
@ -2361,7 +2361,12 @@ static Addr compute_cfa ( D3UnwindRegs* uregs,
|
||||
break;
|
||||
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
# elif defined(VGP_arm64_linux)
|
||||
I_die_here;
|
||||
case CFIC_ARM64_SPREL:
|
||||
cfa = cfsi->cfa_off + uregs->sp;
|
||||
break;
|
||||
case CFIC_ARM64_X29REL:
|
||||
cfa = cfsi->cfa_off + uregs->x29;
|
||||
break;
|
||||
# else
|
||||
# error "Unsupported arch"
|
||||
# endif
|
||||
@ -2437,6 +2442,8 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
|
||||
{E,R}SP, {E,R}BP.
|
||||
|
||||
For arm, the unwound registers are: R7 R11 R12 R13 R14 R15.
|
||||
|
||||
For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
|
||||
*/
|
||||
Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
|
||||
Addr min_accessible,
|
||||
@ -2459,7 +2466,7 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
|
||||
ipHere = uregsHere->pc;
|
||||
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
# elif defined(VGP_arm64_linux)
|
||||
I_die_here;
|
||||
ipHere = uregsHere->pc;
|
||||
# else
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
@ -2541,7 +2548,10 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
|
||||
COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
|
||||
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
# elif defined(VGP_arm64_linux)
|
||||
I_die_here;
|
||||
COMPUTE(uregsPrev.pc, uregsHere->pc, cfsi->ra_how, cfsi->ra_off);
|
||||
COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
|
||||
COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi->x30_how, cfsi->x30_off);
|
||||
COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi->x29_how, cfsi->x29_off);
|
||||
# else
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
|
||||
@ -133,7 +133,7 @@ typedef
|
||||
cfa = case cfa_how of
|
||||
CFIC_IA_SPREL -> {e,r}sp + cfa_off
|
||||
CFIC_IA_BPREL -> {e,r}bp + cfa_off
|
||||
CFIR_IA_EXPR -> expr whose index is in cfa_off
|
||||
CFIC_EXPR -> expr whose index is in cfa_off
|
||||
|
||||
Once that is done, the previous frame's {e,r}sp/{e,r}bp values and
|
||||
this frame's {e,r}ra value can be calculated like this:
|
||||
@ -150,11 +150,11 @@ typedef
|
||||
keep track of:
|
||||
|
||||
cfa = case cfa_how of
|
||||
CFIC_R13REL -> r13 + cfa_off
|
||||
CFIC_R12REL -> r12 + cfa_off
|
||||
CFIC_R11REL -> r11 + cfa_off
|
||||
CFIC_R7REL -> r7 + cfa_off
|
||||
CFIR_EXPR -> expr whose index is in cfa_off
|
||||
CFIC_ARM_R13REL -> r13 + cfa_off
|
||||
CFIC_ARM_R12REL -> r12 + cfa_off
|
||||
CFIC_ARM_R11REL -> r11 + cfa_off
|
||||
CFIC_ARM_R7REL -> r7 + cfa_off
|
||||
CFIR_EXPR -> expr whose index is in cfa_off
|
||||
|
||||
old_r14/r13/r12/r11/r7/ra
|
||||
= case r14/r13/r12/r11/r7/ra_how of
|
||||
@ -164,13 +164,28 @@ typedef
|
||||
CFIR_MEMCFAREL -> *( cfa + r14/r13/r12/r11/r7/ra_off )
|
||||
CFIR_EXPR -> expr whose index is in r14/r13/r12/r11/r7/ra_off
|
||||
|
||||
On ARM64:
|
||||
|
||||
cfa = case cfa_how of
|
||||
CFIC_ARM64_SPREL -> sp + cfa_off
|
||||
CFIC_ARM64_X29REL -> x29 + cfa_off
|
||||
CFIC_EXPR -> expr whose index is in cfa_off
|
||||
|
||||
old_sp/x30/x29/ra
|
||||
= case sp/x30/x29/ra_how of
|
||||
CFIR_UNKNOWN -> we don't know, sorry
|
||||
CFIR_SAME -> same as it was before
|
||||
CFIR_CFAREL -> cfa + sp/x30/x29/ra_how
|
||||
CFIR_MEMCFAREL -> *( cfa + sp/x30/x29/ra_how )
|
||||
CFIR_EXPR -> expr whose index is in sp/x30/x29/ra_off
|
||||
|
||||
On s390x we have a similar logic as x86 or amd64. We need the stack pointer
|
||||
(r15), the frame pointer r11 (like BP) and together with the instruction
|
||||
address in the PSW we can calculate the previous values:
|
||||
cfa = case cfa_how of
|
||||
CFIC_IA_SPREL -> r15 + cfa_off
|
||||
CFIC_IA_BPREL -> r11 + cfa_off
|
||||
CFIR_IA_EXPR -> expr whose index is in cfa_off
|
||||
CFIC_EXPR -> expr whose index is in cfa_off
|
||||
|
||||
old_sp/fp/ra
|
||||
= case sp/fp/ra_how of
|
||||
@ -183,12 +198,13 @@ typedef
|
||||
|
||||
#define CFIC_IA_SPREL ((UChar)1)
|
||||
#define CFIC_IA_BPREL ((UChar)2)
|
||||
#define CFIC_IA_EXPR ((UChar)3)
|
||||
#define CFIC_ARM_R13REL ((UChar)4)
|
||||
#define CFIC_ARM_R12REL ((UChar)5)
|
||||
#define CFIC_ARM_R11REL ((UChar)6)
|
||||
#define CFIC_ARM_R7REL ((UChar)7)
|
||||
#define CFIC_EXPR ((UChar)8) /* all targets */
|
||||
#define CFIC_ARM_R13REL ((UChar)3)
|
||||
#define CFIC_ARM_R12REL ((UChar)4)
|
||||
#define CFIC_ARM_R11REL ((UChar)5)
|
||||
#define CFIC_ARM_R7REL ((UChar)6)
|
||||
#define CFIC_ARM64_SPREL ((UChar)7)
|
||||
#define CFIC_ARM64_X29REL ((UChar)8)
|
||||
#define CFIC_EXPR ((UChar)9) /* all targets */
|
||||
|
||||
#define CFIR_UNKNOWN ((UChar)64)
|
||||
#define CFIR_SAME ((UChar)65)
|
||||
@ -232,6 +248,23 @@ typedef
|
||||
Int r7_off;
|
||||
}
|
||||
DiCfSI;
|
||||
#elif defined(VGA_arm64)
|
||||
typedef
|
||||
struct {
|
||||
Addr base;
|
||||
UInt len;
|
||||
UChar cfa_how; /* a CFIC_ value */
|
||||
UChar ra_how; /* a CFIR_ value */
|
||||
UChar sp_how; /* a CFIR_ value */ /*dw31=SP*/
|
||||
UChar x30_how; /* a CFIR_ value */ /*dw30=LR*/
|
||||
UChar x29_how; /* a CFIR_ value */ /*dw29=FP*/
|
||||
Int cfa_off;
|
||||
Int ra_off;
|
||||
Int sp_off;
|
||||
Int x30_off;
|
||||
Int x29_off;
|
||||
}
|
||||
DiCfSI;
|
||||
#elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
/* Just have a struct with the common fields in, so that code that
|
||||
processes the common fields doesn't have to be ifdef'd against
|
||||
@ -277,18 +310,6 @@ typedef
|
||||
Int fp_off;
|
||||
}
|
||||
DiCfSI;
|
||||
#elif defined(VGA_arm64)
|
||||
/* Be generic until we know more about what's needed. */
|
||||
typedef
|
||||
struct {
|
||||
Addr base;
|
||||
UInt len;
|
||||
UChar cfa_how; /* a CFIC_ value */
|
||||
UChar ra_how; /* a CFIR_ value */
|
||||
Int cfa_off;
|
||||
Int ra_off;
|
||||
}
|
||||
DiCfSI;
|
||||
#else
|
||||
# error "Unknown arch"
|
||||
#endif
|
||||
@ -328,6 +349,7 @@ typedef
|
||||
Creg_ARM_R12,
|
||||
Creg_ARM_R15,
|
||||
Creg_ARM_R14,
|
||||
Creg_ARM64_X30,
|
||||
Creg_S390_R14,
|
||||
Creg_MIPS_RA
|
||||
}
|
||||
|
||||
@ -1840,11 +1840,11 @@ void ML_(read_debuginfo_dwarf1) (
|
||||
#elif defined(VGP_arm_linux)
|
||||
# define FP_REG 12
|
||||
# define SP_REG 13
|
||||
# define RA_REG_DEFAULT 14 //???
|
||||
# define RA_REG_DEFAULT 14
|
||||
#elif defined(VGP_arm64_linux)
|
||||
# define FP_REG 29 //???
|
||||
# define SP_REG 31 //???
|
||||
# define RA_REG_DEFAULT 30 //???
|
||||
# define FP_REG 29
|
||||
# define SP_REG 31
|
||||
# define RA_REG_DEFAULT 30
|
||||
#elif defined(VGP_x86_darwin)
|
||||
# define FP_REG 5
|
||||
# define SP_REG 4
|
||||
@ -1878,6 +1878,8 @@ void ML_(read_debuginfo_dwarf1) (
|
||||
# define N_CFI_REGS 72
|
||||
#elif defined(VGP_arm_linux)
|
||||
# define N_CFI_REGS 320
|
||||
#elif defined(VGP_arm64_linux)
|
||||
# define N_CFI_REGS 128
|
||||
#else
|
||||
# define N_CFI_REGS 20
|
||||
#endif
|
||||
@ -2100,6 +2102,11 @@ static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
|
||||
ctx->state[j].reg[12].tag = RR_Same;
|
||||
ctx->state[j].reg[7].tag = RR_Same;
|
||||
/* this can't be right though: R12 (IP) isn't callee saved. */
|
||||
# elif defined(VGA_arm64)
|
||||
/* Callee-saved registers (that we are interested in) should
|
||||
start out as RR_Same. */
|
||||
ctx->state[j].reg[29/*FP*/].tag = RR_Same;
|
||||
ctx->state[j].reg[30/*LR*/].tag = RR_Same;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@ -2121,7 +2128,7 @@ typedef
|
||||
|
||||
static void initCfiSI ( DiCfSI* si )
|
||||
{
|
||||
VG_(memset)(si, 0, sizeof(*si));
|
||||
VG_(bzero_inline)(si, sizeof(*si));
|
||||
}
|
||||
|
||||
|
||||
@ -2184,7 +2191,7 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
# elif defined(VGA_arm)
|
||||
si->cfa_how = CFIC_ARM_R13REL;
|
||||
# elif defined(VGA_arm64)
|
||||
I_die_here;
|
||||
si->cfa_how = CFIC_ARM64_SPREL;
|
||||
# else
|
||||
si->cfa_how = 0; /* invalid */
|
||||
# endif
|
||||
@ -2197,6 +2204,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
si->cfa_how = CFIC_IA_BPREL;
|
||||
# elif defined(VGA_arm)
|
||||
si->cfa_how = CFIC_ARM_R12REL;
|
||||
# elif defined(VGA_arm64)
|
||||
si->cfa_how = CFIC_ARM64_X29REL;
|
||||
# else
|
||||
si->cfa_how = 0; /* invalid */
|
||||
# endif
|
||||
@ -2213,7 +2222,7 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
si->cfa_off = ctxs->cfa_off;
|
||||
}
|
||||
# elif defined(VGA_arm64)
|
||||
if (1) { I_die_here; } // do we need any arm64 specifics here?
|
||||
// do we need any arm64 specifics here?
|
||||
# endif
|
||||
else {
|
||||
why = 1;
|
||||
@ -2348,6 +2357,48 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
|
||||
return True;
|
||||
|
||||
# elif defined(VGA_arm64)
|
||||
|
||||
/* --- entire tail of this fn specialised for arm64 --- */
|
||||
|
||||
SUMMARISE_HOW(si->x30_how, si->x30_off, ctxs->reg[30/*LR*/]);
|
||||
SUMMARISE_HOW(si->x29_how, si->x29_off, ctxs->reg[29/*FP*/]);
|
||||
|
||||
if (ctxs->reg[30/*LR*/].tag == RR_Same
|
||||
&& ctx->ra_reg == 30/*as we expect it always to be*/) {
|
||||
/* Generate a trivial CfiExpr, which merely says "x30". First
|
||||
ensure this DebugInfo has a cfsi_expr array in which to park
|
||||
it. */
|
||||
if (!debuginfo->cfsi_exprs)
|
||||
debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
|
||||
"di.ccCt.2a-arm64",
|
||||
ML_(dinfo_free),
|
||||
sizeof(CfiExpr) );
|
||||
si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
|
||||
Creg_ARM64_X30);
|
||||
si->ra_how = CFIR_EXPR;
|
||||
} else {
|
||||
/* Just summarise it in the normal way */
|
||||
SUMMARISE_HOW(si->ra_how, si->ra_off, ctxs->reg[ctx->ra_reg]);
|
||||
}
|
||||
|
||||
/* on arm64, it seems the old SP value before the call is always
|
||||
the same as the CFA. Therefore ... */
|
||||
si->sp_how = CFIR_CFAREL;
|
||||
si->sp_off = 0;
|
||||
|
||||
/* bogus looking range? Note, we require that the difference is
|
||||
representable in 32 bits. */
|
||||
if (loc_start >= ctx->loc)
|
||||
{ why = 4; goto failed; }
|
||||
if (ctx->loc - loc_start > 10000000 /* let's say */)
|
||||
{ why = 5; goto failed; }
|
||||
|
||||
si->base = loc_start + ctx->initloc;
|
||||
si->len = (UInt)(ctx->loc - loc_start);
|
||||
|
||||
return True;
|
||||
|
||||
# elif defined(VGA_s390x)
|
||||
|
||||
/* --- entire tail of this fn specialised for s390 --- */
|
||||
@ -2440,9 +2491,6 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
|
||||
return True;
|
||||
|
||||
# elif defined(VGA_arm64)
|
||||
I_die_here;
|
||||
|
||||
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
/* These don't use CFI based unwinding (is that really true?) */
|
||||
|
||||
@ -2450,6 +2498,8 @@ static Bool summarise_context( /*OUT*/DiCfSI* si,
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
|
||||
/* --- non-specialised code after this point --- */
|
||||
|
||||
# undef SUMMARISE_HOW
|
||||
|
||||
failed:
|
||||
|
||||
@ -162,6 +162,12 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
|
||||
case CFIC_ARM_R7REL:
|
||||
VG_(printf)("let cfa=oldR7+%d", si->cfa_off);
|
||||
break;
|
||||
case CFIC_ARM64_SPREL:
|
||||
VG_(printf)("let cfa=oldSP+%d", si->cfa_off);
|
||||
break;
|
||||
case CFIC_ARM64_X29REL:
|
||||
VG_(printf)("let cfa=oldX29+%d", si->cfa_off);
|
||||
break;
|
||||
case CFIC_EXPR:
|
||||
VG_(printf)("let cfa={");
|
||||
ML_(ppCfiExpr)(exprs, si->cfa_off);
|
||||
@ -196,7 +202,12 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si )
|
||||
VG_(printf)(" FP=");
|
||||
SHOW_HOW(si->fp_how, si->fp_off);
|
||||
# elif defined(VGA_arm64)
|
||||
I_die_here;
|
||||
VG_(printf)(" SP=");
|
||||
SHOW_HOW(si->sp_how, si->sp_off);
|
||||
VG_(printf)(" X30=");
|
||||
SHOW_HOW(si->x30_how, si->x30_off);
|
||||
VG_(printf)(" X29=");
|
||||
SHOW_HOW(si->x29_how, si->x29_off);
|
||||
# else
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
@ -671,15 +682,16 @@ static void ppCfiBinop ( CfiBinop op )
|
||||
static void ppCfiReg ( CfiReg reg )
|
||||
{
|
||||
switch (reg) {
|
||||
case Creg_IA_SP: VG_(printf)("xSP"); break;
|
||||
case Creg_IA_BP: VG_(printf)("xBP"); break;
|
||||
case Creg_IA_IP: VG_(printf)("xIP"); break;
|
||||
case Creg_ARM_R13: VG_(printf)("R13"); break;
|
||||
case Creg_ARM_R12: VG_(printf)("R12"); break;
|
||||
case Creg_ARM_R15: VG_(printf)("R15"); break;
|
||||
case Creg_ARM_R14: VG_(printf)("R14"); break;
|
||||
case Creg_MIPS_RA: VG_(printf)("RA"); break;
|
||||
case Creg_S390_R14: VG_(printf)("R14"); break;
|
||||
case Creg_IA_SP: VG_(printf)("xSP"); break;
|
||||
case Creg_IA_BP: VG_(printf)("xBP"); break;
|
||||
case Creg_IA_IP: VG_(printf)("xIP"); break;
|
||||
case Creg_ARM_R13: VG_(printf)("R13"); break;
|
||||
case Creg_ARM_R12: VG_(printf)("R12"); break;
|
||||
case Creg_ARM_R15: VG_(printf)("R15"); break;
|
||||
case Creg_ARM_R14: VG_(printf)("R14"); break;
|
||||
case Creg_ARM64_X30: VG_(printf)("X30"); break;
|
||||
case Creg_MIPS_RA: VG_(printf)("RA"); break;
|
||||
case Creg_S390_R14: VG_(printf)("R14"); break;
|
||||
default: vg_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1044,10 +1044,88 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
|
||||
UnwindStartRegs* startRegs,
|
||||
Addr fp_max_orig )
|
||||
{
|
||||
ips[0] = startRegs->r_pc;
|
||||
if (sps) sps[0] = startRegs->r_sp;
|
||||
if (fps) fps[0] = startRegs->misc.ARM64.x29;
|
||||
return 1;
|
||||
Bool debug = False;
|
||||
Int i;
|
||||
Addr fp_max;
|
||||
UInt n_found = 0;
|
||||
const Int cmrf = VG_(clo_merge_recursive_frames);
|
||||
|
||||
vg_assert(sizeof(Addr) == sizeof(UWord));
|
||||
vg_assert(sizeof(Addr) == sizeof(void*));
|
||||
|
||||
D3UnwindRegs uregs;
|
||||
uregs.pc = startRegs->r_pc;
|
||||
uregs.sp = startRegs->r_sp;
|
||||
uregs.x30 = startRegs->misc.ARM64.x30;
|
||||
uregs.x29 = startRegs->misc.ARM64.x29;
|
||||
Addr fp_min = uregs.sp;
|
||||
|
||||
/* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
|
||||
stopping when the trail goes cold, which we guess to be
|
||||
when FP is not a reasonable stack location. */
|
||||
|
||||
// JRS 2002-sep-17: hack, to round up fp_max to the end of the
|
||||
// current page, at least. Dunno if it helps.
|
||||
// NJN 2002-sep-17: seems to -- stack traces look like 1.0.X again
|
||||
fp_max = VG_PGROUNDUP(fp_max_orig);
|
||||
if (fp_max >= sizeof(Addr))
|
||||
fp_max -= sizeof(Addr);
|
||||
|
||||
if (debug)
|
||||
VG_(printf)("\nmax_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, "
|
||||
"fp_max=0x%lx PC=0x%lx SP=0x%lx\n",
|
||||
max_n_ips, fp_min, fp_max_orig, fp_max,
|
||||
uregs.pc, uregs.sp);
|
||||
|
||||
/* Assertion broken before main() is reached in pthreaded programs; the
|
||||
* offending stack traces only have one item. --njn, 2002-aug-16 */
|
||||
/* vg_assert(fp_min <= fp_max);*/
|
||||
// On Darwin, this kicks in for pthread-related stack traces, so they're
|
||||
// only 1 entry long which is wrong.
|
||||
if (fp_min + 512 >= fp_max) {
|
||||
/* If the stack limits look bogus, don't poke around ... but
|
||||
don't bomb out either. */
|
||||
if (sps) sps[0] = uregs.sp;
|
||||
if (fps) fps[0] = uregs.x29;
|
||||
ips[0] = uregs.pc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
if (sps) sps[0] = uregs.sp;
|
||||
if (fps) fps[0] = uregs.x29;
|
||||
ips[0] = uregs.pc;
|
||||
i = 1;
|
||||
|
||||
/* Loop unwinding the stack, using CFI. */
|
||||
while (True) {
|
||||
if (debug) {
|
||||
VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx\n",
|
||||
i, uregs.pc, uregs.sp);
|
||||
}
|
||||
|
||||
if (i >= max_n_ips)
|
||||
break;
|
||||
|
||||
if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) {
|
||||
if (sps) sps[i] = uregs.sp;
|
||||
if (fps) fps[i] = uregs.x29;
|
||||
ips[i++] = uregs.pc - 1;
|
||||
if (debug)
|
||||
VG_(printf)("USING CFI: pc: 0x%lx, sp: 0x%lx\n",
|
||||
uregs.pc, uregs.sp);
|
||||
uregs.pc = uregs.pc - 1;
|
||||
if (UNLIKELY(cmrf > 0)) {RECURSIVE_MERGE(cmrf,ips,i);};
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No luck. We have to give up. */
|
||||
break;
|
||||
}
|
||||
|
||||
n_found = i;
|
||||
return n_found;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -111,7 +111,6 @@ typedef
|
||||
UInt r7;
|
||||
} ARM;
|
||||
struct {
|
||||
// FIXME ARM64 is this correct?
|
||||
ULong x29; /* FP */
|
||||
ULong x30; /* LR */
|
||||
} ARM64;
|
||||
|
||||
@ -114,7 +114,7 @@ typedef
|
||||
D3UnwindRegs;
|
||||
#elif defined(VGA_arm64)
|
||||
typedef
|
||||
struct { Addr pc; Addr sp; Addr lr; Addr fp; } /* PC, 31, 30, 29 */
|
||||
struct { Addr pc; Addr sp; Addr x30; Addr x29; } /* PC, SP, LR, FP */
|
||||
D3UnwindRegs;
|
||||
#elif defined(VGA_ppc32) || defined(VGA_ppc64)
|
||||
typedef
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user