From 90714cf624b910fb2b666edbcdda12b35617074e Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 6 May 2017 19:37:37 -0700 Subject: [PATCH] arm64 tracing in stub modified: ../../linker.cpp modified: ../../p_lx_elf.cpp modified: arm64-linux.elf-entry.S --- src/linker.cpp | 61 ++++++------- src/p_lx_elf.cpp | 2 +- src/stub/src/arm64-linux.elf-entry.S | 127 ++++++++++++++++++--------- 3 files changed, 116 insertions(+), 74 deletions(-) diff --git a/src/linker.cpp b/src/linker.cpp index ef0efd45..6277d581 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -592,35 +592,6 @@ void ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location, upx_ui super::relocate1(rel, location, value, type); } -void ElfLinkerARM64::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value, - const char *type) { - if (strncmp(type, "R_AARCH64_", 10)) - return super::relocate1(rel, location, value, type); - type += 10; - - if (!strncmp(type, "PREL", 4)) { - value -= rel->section->offset + rel->offset; - type += 4; - - if (!strcmp(type, "16")) - set_le16(location, get_le16(location) + value); - else if (!strncmp(type, "32", 2)) // for "32" and "32S" - set_le32(location, get_le32(location) + value); - else if (!strcmp(type, "64")) - set_le64(location, get_le64(location) + value); - } else if (!strcmp(type, "ABS32")) { - set_le32(location, get_le32(location) + value); - } else if (!strcmp(type, "ABS64")) { - set_le64(location, get_le64(location) + value); - } else if (!strcmp(type, "CONDBR19")) { - value -= rel->section->offset + rel->offset; - upx_uint32_t const m19 = ~(~0u << 19); - upx_uint32_t w = get_le32(location); - set_le32(location, (w & ~(m19 << 5)) | ((((w >> 5) + (value >> 2)) & m19) << 5)); - } else - super::relocate1(rel, location, value, type); -} - void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value, const char *type) { if (strcmp(type, "R_ARM_PC24") == 0) { @@ -670,12 +641,36 @@ void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location, upx_ui } void ElfLinkerArm64LE::relocate1(const Relocation *rel, upx_byte *location, upx_uint64_t value, - const char *type) { - if (strcmp(type, "R_AARCH64_CALL26") == 0) { + const char *type) +{ + if (strncmp(type, "R_AARCH64_", 10)) + return super::relocate1(rel, location, value, type); + type += 10; + + if (!strncmp(type, "PREL", 4)) { value -= rel->section->offset + rel->offset; - set_le24(location, get_le24(location) + value / 4); // FIXME set_le26 - } else if (strcmp(type, "R_AARCH64_ABS32") == 0) { + type += 4; + + if (!strcmp(type, "16")) + set_le16(location, get_le16(location) + value); + else if (!strncmp(type, "32", 2)) // for "32" and "32S" + set_le32(location, get_le32(location) + value); + else if (!strcmp(type, "64")) + set_le64(location, get_le64(location) + value); + } else if (!strcmp(type, "ABS32")) { set_le32(location, get_le32(location) + value); + } else if (!strcmp(type, "ABS64")) { + set_le64(location, get_le64(location) + value); + } else if (!strcmp(type, "CONDBR19")) { + value -= rel->section->offset + rel->offset; + upx_uint32_t const m19 = ~(~0u << 19); + upx_uint32_t w = get_le32(location); + set_le32(location, (w & ~(m19 << 5)) | ((((w >> 5) + (value >> 2)) & m19) << 5)); + } else if (!strcmp(type, "CALL26")) { + value -= rel->section->offset + rel->offset; + upx_uint32_t const m26 = ~(~0u << 26); + upx_uint32_t w = get_le32(location); + set_le32(location, (w & ~m26) | (m26 & (value >> 2))); } else super::relocate1(rel, location, value, type); } diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 822a7652..cd5dce1a 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -647,7 +647,7 @@ Linker* PackLinuxElf64amd::newLinker() const Linker* PackLinuxElf64arm::newLinker() const { - return new ElfLinkerARM64; + return new ElfLinkerArm64LE; } int const * diff --git a/src/stub/src/arm64-linux.elf-entry.S b/src/stub/src/arm64-linux.elf-entry.S index bd4c2793..b8e88553 100644 --- a/src/stub/src/arm64-linux.elf-entry.S +++ b/src/stub/src/arm64-linux.elf-entry.S @@ -60,6 +60,12 @@ __ARM_NR_cacheflush = 255 // FIXME #ifndef DEBUG /*{*/ #define DEBUG 0 #endif /*}*/ +#if DEBUG //{ +#define TRACE(arg) stp lr,x0,[sp,#-2*8]!; mov x0,arg; bl trace; ldr lr,[sp],#2*8 +#else //}{ +#define TRACE(arg) /*empty*/ +#endif //} + //.long sz_pack2 // placed there by ::pack3() section ELFMAINX @@ -78,13 +84,8 @@ _start: .globl _start */ #if DEBUG /*{*/ -#define TRACE_REGS r0-r12,r14,r15 -// sp (r13) is not included because the write-back might cause UNDEFINED behavior -// if the write-back register is not first or last. The actual value of sp -// usually does not matter. Just remember that lr (r14) and pc (r15) are stored -// one word closer to the stack pointer because r13 has been omitted. - - stmdb sp!,{TRACE_REGS}; mov r0,#1; bl trace + brk #0 + TRACE(#0) #endif /*}*/ adr x12,start_params -4 // &sz_pack2 @@ -111,7 +112,7 @@ D_sz_unc=2*8 // stack displacement to sz_unc mov w4,#-1 // fd= -1; cater to *BSD for fd when MAP_ANON do_sys __NR_mmap64 #if DEBUG /*{*/ - stmdb sp!,{TRACE_REGS}; mov r0,#2; bl trace + TRACE(#2) #endif /*}*/ cmn x0,#4096 bcs msg_SELinux @@ -155,52 +156,98 @@ D_stm1=0*8 str w3,[sp,#D_stm1 + D_sz_unc] // sz_unc; lzma needs for EOF add x3, sp,#D_stm1 + D_sz_unc // &sz_unc #if DEBUG /*{*/ - stmdb sp!,{TRACE_REGS}; mov r0,#3; bl trace + TRACE(#3) #endif /*}*/ br x15 // decompress folded code, return to *lr #if DEBUG /*{*/ -TRACE_BUFLEN=512 -trace: - str lr,[sp,#(-1+ 15)*4] @ return pc; [remember: sp is not stored] - mov r4,sp @ &saved_r0 +TRACE_BUFLEN=1024 +trace: // DEFICIENCY: modifies condition code + stp x0, x1,[sp,#-32*8]! + stp x2, x3,[sp,# 2*8] + stp x4, x5,[sp,# 4*8] + stp x6, x7,[sp,# 6*8] + stp x8, x9,[sp,# 8*8] + stp x10,x11,[sp,#10*8] + stp x12,x13,[sp,#12*8] + stp x14,x15,[sp,#14*8] + stp x16,x17,[sp,#16*8] + stp x18,x19,[sp,#18*8] + stp x20,x21,[sp,#20*8] + stp x22,x23,[sp,#22*8] + stp x24,x25,[sp,#24*8] + stp x26,x27,[sp,#26*8] + stp x28,x29,[sp,#28*8] + add x1,lr,#4 // u_pc + add x2,sp, #32*8 + 2*8 // u_sp + stp x1, x2,[sp,#30*8] + + ldr x1,[sp,#(1+ 32)*8] // x1= u_x0 + str x1,[sp] // u_x0 + + mov x4,sp // &u_x0 sub sp,sp,#TRACE_BUFLEN - mov r2,sp @ output string + mov x2,sp // output string - mov r1,#'\n'; bl trace_hex @ In: r0 as label - mov r1,#'>'; strb r1,[r2],#1 + mov w1,#'\n'; bl trace_hex // In: r0 as label + mov w1,#'>'; strb w1,[x2],#1 - mov r5,#3 @ rows to print -L600: @ each row - sub r0,r4,#TRACE_BUFLEN - sub r0,r0,sp - mov r0,r0,lsr #2; mov r1,#'\n'; bl trace_hex @ which block of 8 + mov w5,#10 // nrows to print +L600: // each row + add x1,sp,#TRACE_BUFLEN + sub x0,x4,x1 + lsr x0,x0,#3; mov w1,#'\n'; bl trace_hex2 // which block of 4 - mov r6,#8 @ words per row -L610: @ each word - ldr r0,[r4],#4; mov r1,#' '; bl trace_hex @ next word - subs r6,r6,#1; bgt L610 + mov w6,#4 // 64-bit words per row +L610: // each word + ldr x0,[x4],#8; mov w1,#(' '<<8)|' '; bl trace_hex // next word + sub w6,w6,#1; cbnz w6,L610 - subs r5,r5,#1; bgt L600 + sub w5,w5,#1; cbnz w5,L600 - mov r0,#'\n'; strb r0,[r2],#1 - sub r2,r2,sp @ count - mov r1,sp @ buf - mov r0,#2 @ FD_STDERR + mov w0,#'\n'; strb w0,[x2],#1 + mov x1,sp // buf + sub x2,x2,x1 // count + mov w0,#2 // FD_STDERR do_sys __NR_write add sp,sp,#TRACE_BUFLEN - ldmia sp!,{TRACE_REGS} -trace_hex: // In: r0=val, r1=punctuation before, r2=ptr; Uses: r3, ip - strb r1,[r2],#1 @ punctuation - mov r3,#4*(8 -1) @ shift count - adr ip,hex + ldp x16,x17,[sp,#16*8] + ldp x18,x19,[sp,#18*8] + ldp x20,x21,[sp,#20*8] + ldp x22,x23,[sp,#22*8] + ldp x24,x25,[sp,#24*8] + ldp x26,x27,[sp,#26*8] + ldp x28,x29,[sp,#28*8] + ldp x30, x0,[sp,#30*8] + sub lr, lr,#4 // our lr + + ldp x14,x15,[sp,#14*8] + ldp x12,x13,[sp,#12*8] + ldp x10,x11,[sp,#10*8] + ldp x8, x9,[sp,# 8*8] + ldp x6, x7,[sp,# 6*8] + ldp x4, x5,[sp,# 4*8] + ldp x2, x3,[sp,# 2*8] + ldp x0, x1,[sp],#32*8 + ret + +trace_hex2: + mov w3,#2; b trace_hexwid +trace_hex: // In: x0=val, w1=punctuation before, x2=ptr; Uses: w3, x7 + mov w3,#16 // ndigits +trace_hexwid: + strb w1,[x2],#1; lsr w1,w1,#8; cbnz w1,trace_hexwid // punctuation + adr x7,hex + sub w3,w3,#1 L620: - mov r1,r0,lsr r3 - and r1,r1,#0xf - ldrb r1,[ip, r1] - strb r1,[r2],#1 - subs r3,r3,#4; bge L620 + cmp w3,#-1+ 8; mov w1,#'_'; strb w1,[x2]; cinc x2,x2,eq + lsl w1,w3,#2 // 4 bits per hex digit + lsr x1,x0,x1 // right justify next digit + and x1,x1,#0xf + ldrb w1,[x7, x1] + strb w1,[x2],#1 + subs w3,w3,#1; bge L620 ret hex: .ascii "0123456789abcdef"