X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/a752c20fda86bcc14a23539fc20bea32fb541e18..HEAD:/base/regdump.h diff --git a/base/regdump.h b/base/regdump.h index aae35bc5..4934f5ca 100644 --- a/base/regdump.h +++ b/base/regdump.h @@ -135,6 +135,7 @@ union gp64 { uint64 u64; int64 i64; PTR64 }; #define REGSRC_SIMD 0x04000000 /* SIMD vector register */ #define REGSRC_STMMX 0x05000000 /* x86-specific: x87/MMX register */ #define REGSRC_SEG 0x06000000 /* x86-specific: segment register */ +#define REGSRC_NONE 0x0f000000 /* just a message */ /* Where to find the values. */ #define REGF_WDMASK 0xf0000000 @@ -186,10 +187,10 @@ union gp64 { uint64 u64; int64 i64; PTR64 }; #if !__ASSEMBLER__ #if CPUFAM_X86 -typedef union gp32 gpreg; + typedef union gp32 gpreg; #endif #if CPUFAM_AMD64 -typedef union gp64 gpreg; + typedef union gp64 gpreg; #endif struct gpsave { @@ -202,7 +203,7 @@ union stmmx { #if FLT_RADIX == 2 && LDBL_MANT_DIG == 64 long double f80; #endif -unsigned char _pad[16]; + unsigned char _pad[16]; }; union xmm { SIMD_COMMON(128); }; @@ -262,20 +263,34 @@ struct regmap { #else .extern regdump_gpsave + // Save general-purpose registers at r/esp; flags, r/eax, and, on + // x86, ebx, should have been filled in already, together with the + // focus address, in `REGIX_ADDR', if relevant. Return required + // extended save area size in ecx, and leave r/ebp pointing to the + // save area. + .extern regdump_xtsave + // Save extended registers at r/esp, leaving r/ebp pointing to the + // register map. + .extern regdump_xtrstr + // Restore extended registers from register map in r/ebp, leaving + // r/ebp pointing to general-purpose save area. + .extern regdump_gprstr + // Restore general-purpose registers, except r/esp, from save area + // at r/ebp. regmap_gp = 0*WORDSZ regmap_fx = 1*WORDSZ regmap_avx = 2*WORDSZ regmap_size = 3*WORDSZ -#define REGDEF_GPX86_COMMON(rn, RN) \ - regsrc.e##rn = REGSRC_GP | REGIX_##RN; \ +#define REGDEF_GPX86_COMMON(rn, ix) \ + regsrc.e##rn = REGSRC_GP | ix; \ regty.e##rn = REGF_32; \ regfmt.e##rn = REGF_HEX; \ - regsrc.r##rn = REGSRC_GP | REGIX_##RN; \ + regsrc.r##rn = REGSRC_GP | ix; \ regty.r##rn = REGF_64; \ regfmt.r##rn = REGF_HEX @@ -289,7 +304,7 @@ struct regmap { regsrc.rn##x = REGSRC_GP | REGIX_##RN##X; \ regty.rn##x = REGF_16; \ regfmt.rn##x = REGF_HEX; \ - REGDEF_GPX86_COMMON(rn##x, RN##X) + REGDEF_GPX86_COMMON(rn##x, REGIX_##RN##X) REGDEF_GPX86_ABCD(a, A) REGDEF_GPX86_ABCD(b, B) REGDEF_GPX86_ABCD(c, C) @@ -297,12 +312,12 @@ REGDEF_GPX86_ABCD(d, D) regsrc.eflags = REGSRC_GP | REGIX_FLAGS regty.eflags = REGF_32 - regty.eflags = 0 + regfmt.eflags = 0 #if CPUFAM_AMD64 regsrc.rflags = REGSRC_GP | REGIX_FLAGS regty.rflags = REGF_64 - regty.rflags = 0 + regfmt.rflags = 0 #endif #define REGDEF_GPX86_XP(rn, RN) \ @@ -312,7 +327,7 @@ REGDEF_GPX86_ABCD(d, D) regsrc.rn = REGSRC_GP | REGIX_##RN; \ regty.rn = REGF_16; \ regfmt.rn = REGF_HEX; \ - REGDEF_GPX86_COMMON(rn, RN) + REGDEF_GPX86_COMMON(rn, REGIX_##RN) REGDEF_GPX86_XP(ip, IP) REGDEF_GPX86_XP(si, SI) REGDEF_GPX86_XP(di, DI) @@ -381,32 +396,32 @@ DO8(REGDEF_SIMD) // Stash r/eax. This is bletcherous: hope we don't get a signal in // the next few instructions. - mov [R_sp(r) - REGDUMP_SPADJ + (REGIX_AX - 1)*WORDSZ], R_a(r) + mov [SP - REGDUMP_SPADJ + (REGIX_AX - 1)*WORDSZ], AX .ifnes "\addr", "nil" - // Collect the effective address for the following dump, leaving it - // in the `addr' slot of the dump. - lea R_a(r), \addr - mov [R_sp(r) - REGDUMP_SPADJ + (REGIX_ADDR - 1)*WORDSZ], R_a(r) + // Collect the focus address for the following dump, leaving it in + // the `addr' slot of the dump. + lea AX, \addr + mov [SP - REGDUMP_SPADJ + (REGIX_ADDR - 1)*WORDSZ], AX .endif // Make space for the register save area. On AMD64 with System/V // ABI, also skip the red zone. Use `lea' here to preserve the // flags. - lea R_sp(r), [R_sp(r) - REGDUMP_SPADJ] + lea SP, [SP - REGDUMP_SPADJ] // Save flags and general-purpose registers. On 32-bit x86, we save // ebx here and establish a GOT pointer here for the benefit of the // PLT-indirect calls made later on. pushf # if CPUFAM_X86 - mov [esp + 4*REGIX_BX], ebx + mov [SP + 4*REGIX_BX], ebx ldgot # endif callext F(regdump_gpsave) // Make space for the extended registers. - sub R_sp(r), R_c(r) + sub SP, CX callext F(regdump_xtsave) // Prepare for calling back into C. On 32-bit x86, leave space for @@ -414,11 +429,11 @@ DO8(REGDEF_SIMD) // the `shadow space' for the called-function's arguments. Also, // forcibly align the stack pointer to a 16-byte boundary. # if CPUFAM_X86 - sub esp, 16 + sub SP, 16 # elif ABI_WIN - sub rsp, 32 + sub SP, 32 # endif - and R_sp(r), ~15 + and SP, ~15 .endm .macro _rstrregs @@ -426,27 +441,38 @@ DO8(REGDEF_SIMD) // We assume r/ebp still points to the register map. callext F(regdump_xtrstr) - mov R_sp(r), R_bp(r) + mov SP, BP callext F(regdump_gprstr) popf - lea R_sp(r), [R_sp(r) + REGDUMP_SPADJ] + lea SP, [SP + REGDUMP_SPADJ] +.endm + +.macro _nilbase +# if CPUFAM_X86 + xor eax, eax + mov [SP + 0], eax +# elif ABI_SYSV + xor edi, edi +# elif ABI_WIN + xor ecx, ecx +# endif .endm .macro _regbase # if CPUFAM_X86 - mov [esp + 0], ebp + mov [SP + 0], BP # elif ABI_SYSV - mov rdi, rbp + mov rdi, BP # elif ABI_WIN - mov rcx, rbp + mov rcx, BP # endif .endm .macro _membase - mov R_a(r), [R_bp(r) + regmap_gp] + mov AX, [BP + regmap_gp] # if CPUFAM_X86 mov eax, [eax + REGIX_ADDR*WORDSZ] - mov [esp + 0], eax + mov [SP + 0], eax # elif ABI_SYSV mov rdi, [rax + REGIX_ADDR*WORDSZ] # elif ABI_WIN @@ -457,7 +483,7 @@ DO8(REGDEF_SIMD) .macro _reglbl msg .ifeqs "\msg", "" # if CPUFAM_X86 - mov dword ptr [esp + 4], 0 + mov dword ptr [SP + 4], 0 # elif ABI_SYSV xor esi, esi # elif ABI_WIN @@ -466,7 +492,7 @@ DO8(REGDEF_SIMD) .else # if CPUFAM_X86 lea eax, [INTADDR(.L$_reglbl$\@)] - mov [esp + 4], eax + mov [SP + 4], eax # elif ABI_SYSV lea rsi, [INTADDR(.L$_reglbl$\@)] # elif ABI_WIN @@ -481,7 +507,7 @@ DO8(REGDEF_SIMD) .macro _regfmt arg # if CPUFAM_X86 - mov dword ptr [esp + 8], \arg + mov dword ptr [SP + 8], \arg # elif ABI_SYSV mov edx, \arg # elif ABI_WIN @@ -534,9 +560,22 @@ struct regmap { #else .extern regdump_gpsave + // Save general-purpose registers at r13; r12 and r14 should have + // been filled in already, along with the focus address in + // `REGIX_ADDR', if relevant. Return required extended save area + // size in r0, leave r4 pointing to the save area, and set r6 to + // the focus address. + .extern regdump_xtsave + // Save extended registers at r13, leaving r5 pointing to the + // register map. + .extern regdump_xtrstr + // Restore extended registers from register map at r5. + .extern regdump_gprstr + // Restore general-purpose registers, except r13 and r14, from save + // area at r4. regmap_gp = 0 regmap_fp = 4 @@ -586,8 +625,8 @@ DO16(REGDEF_NEONQ) str r14, [r13, #-REGDUMP_GPSIZE + 14*4] .ifnes "\base,\off", "nil,#0" - // Collect the effective address for the following dump, leaving it - // in the `addr' slot of the dump. + // Collect the focus address for the following dump, leaving it in + // the `addr' slot of the dump. .ifeqs "\base", "nil" adrl r14, \off .else @@ -600,6 +639,8 @@ DO16(REGDEF_NEONQ) sub r13, r13, #REGDUMP_GPSIZE // Save flags and general-purpose registers. + mrs r14, cpsr + str r14, [r13, #4*REGIX_CPSR] str r12, [r13, #4*12] bl regdump_gpsave @@ -625,6 +666,10 @@ DO16(REGDEF_NEONQ) add r13, r13, #REGDUMP_GPSIZE .endm +.macro _nilbase + mov r0, #0 +.endm + .macro _regbase mov r0, r5 .endm @@ -643,8 +688,8 @@ DO16(REGDEF_NEONQ) .endm .macro _regfmt arg - movw r2, #\arg&0xffff - movt r2, #(\arg >> 16)&0xffff + movw r2, #(\arg)&0xffff + movt r2, #((\arg) >> 16)&0xffff .endm #endif @@ -681,9 +726,22 @@ struct regmap { #else .extern regdump_gpsave + // Save general-purpose registers at sp; x16, x17, and x30, should + // have been filled in already, along with the focus address in + // `REGIX_ADDR', if relevant. Return required extended save area + // size in x0, leave x20 pointing to the save area, and set x22 to + // the focus address. + .extern regdump_xtsave + // Save extended registers at sp, leaving x21 pointing to the + // register map. + .extern regdump_xtrstr + // Restore extended registers from register map at x21. + .extern regdump_gprstr + // Restore general-purpose registers, except sp and x30, from save + // area at x20. regmap_gp = 0 regmap_fp = 8 @@ -743,8 +801,8 @@ DO32(REGDEF_FP) str x30, [sp, #-REGDUMP_GPSIZE + 30*8] .ifnes "\base,\off", "nil,#0" - // Collect the effective address for the following dump, leaving it - // in the `addr' slot of the dump. + // Collect the focus address for the following dump, leaving it in + // the `addr' slot of the dump. .ifeqs "\base", "nil" adr x30, \off .else @@ -756,8 +814,15 @@ DO32(REGDEF_FP) // Make space for the register save area. sub sp, sp, #REGDUMP_GPSIZE - // Save flags and general-purpose registers. - stp x16, x17, [sp, #8*16] + // Save flags and general-purpose registers. The PLT linkage code + // makes free with x8--x17, so we must save those here. + mrs x30, nzcv + str x30, [sp, #8*REGIX_NZCV] + stp x8, x9, [sp, #64] + stp x10, x11, [sp, #80] + stp x12, x13, [sp, #96] + stp x14, x15, [sp, #112] + stp x16, x17, [sp, #128] bl regdump_gpsave // Make space for the extended registers. @@ -776,6 +841,10 @@ DO32(REGDEF_FP) add sp, sp, #REGDUMP_GPSIZE .endm +.macro _nilbase + mov x0, #0 +.endm + .macro _regbase mov x0, x21 .endm @@ -794,8 +863,8 @@ DO32(REGDEF_FP) .endm .macro _regfmt arg - movz w2, #\arg&0xffff - movk w2, #(\arg >> 16)&0xffff, lsl #16 + movz w2, #(\arg)&0xffff + movk w2, #((\arg) >> 16)&0xffff, lsl #16 .endm #endif @@ -889,6 +958,15 @@ extern void regdump_freshline(void); _rstrregs .endm +.macro msg lbl + _saveregs + _nilbase + _reglbl "\lbl" + _regfmt REGSRC_NONE | (1 << REGF_WDSHIFT) + callext F(regdump) + _rstrregs +.endm + .macro reg lbl, rn, fmt=0 _saveregs _regbase