/* arm64-linux.elf-so_entry.S -- Linux DT_INIT & decompressor (Elf shared lib) * * This file is part of the UPX executable compressor. * * Copyright (C) 1996-2021 Markus Franz Xaver Johannes Oberhumer * Copyright (C) 1996-2021 Laszlo Molnar * Copyright (C) 2000-2025 John F. Reiser * All Rights Reserved. * * UPX and the UCL library are free software; you can redistribute them * and/or modify them under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING. * If not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Markus F.X.J. Oberhumer Laszlo Molnar * * * John F. Reiser * */ NBPW= 8 #include "arch/arm64/v8/macros.S" lr .req x30 #define DEBUG 0 sz_Elf64_Ehdr = 8*NBPW sz_Elf64_Phdr = 7*NBPW sz_b_info= 12 sz_unc= 0 sz_cpr= 4 b_method= 8 sz_l_info= 12 sz_p_info= 12 PROT_READ= 1 PROT_WRITE= 2 PROT_EXEC= 4 MAP_PRIVATE= 2 MAP_FIXED= 0x10 MAP_ANONYMOUS= 0x20 // /usr/include/asm-generic/unistd.h __NR_close = 0x39 // 57 __NR_exit = 0x5d // 93 __NR_memfd_create = 0x117 // 279 __NR_mmap = 0xde // 222 __NR_mprotect = 0xe2 // 226 __NR_munmap = 0xd7 // 215 __NR_openat = 0x38 // 56 __NR_read = 0x3f // 63 __NR_write = 0x40 // 64 arg1 .req x0 arg1w .req w0 arg2 .req x1 arg2w .req w1 arg3 .req x2 arg3w .req w2 arg4 .req x3 arg4w .req w3 arg5 .req x4 arg5w .req w4 arg6 .req x5 arg6w .req w5 #define bkpt brk #0 #define call bl section ELFMAINX // .long offset(b_info)|(asl_delta>>12) src for f_exp FIXME: really? //SO_INFO: // .word offset(.) // detect relocation // .word offset(user DT_INIT) // .word offset(escape_hatch) // override with round_up(2, PT_LOAD[0]{.p_memsz + .p_vaddr}) // .word offset(dst for f_exp) .balign 4 _start: .globl _start // bkpt // DEBUG PUSH4 (x0,x1,x2,lr) // MATCH_00 sub sp,sp,#2*NBPW // space for ADRU, LENU F_ADRU= 0 * NBPW F_LENU= 1 * NBPW F_ARGC= 2 * NBPW adr x30,fold_info // assembler bug: 'lr' not an integer register foldi .req x30 old_sp .req x14 // busy: lr,x14 mov old_sp,sp ldr w0,[foldi,#sz_unc] str x0,[old_sp,#F_LENU] sub x0,sp,x0 // alloca and sp,x0,#-2*NBPW // align stack psa_fd .req w5 aux_end .req x4 page_m .req x7 AT_PAGESZ= 6 O_RDONLY= 0 mov w2,#O_RDONLY adr x1,str_psa mov w0,#0 do_sys __NR_openat; mov psa_fd,w0 mov x1,sp // buffer mov x2,#512 // len do_sys __NR_read; add aux_end,x1,x0 // end mov w0,psa_fd; do_sys __NR_close .unreq psa_fd 0: ldr x0,[x1,#NBPW] // value ldr x2,[x1],#2*NBPW // tag cmp x2,#AT_PAGESZ; beq 1f cmp x1,aux_end; blo 0b; mov x0,#1<<12 // default 4KiB .unreq aux_end 1: sub page_m,xzr,x0 // PAGE_MASK add arg4,old_sp,#F_LENU // &dstlen mov arg3,sp // dst for decompress ldr arg2w,[foldi,#sz_cpr] // srclen add arg1,foldi,#sz_b_info // src .unreq foldi // busy: x14 bl f_decompress mov arg2w,#0 adr arg1,str_upx mfd .req w15 // busy: x15,x14 do_sys __NR_memfd_create; mov mfd, w0 str page_m, [sp,#0] mov arg2,sp ldr arg3,[old_sp,#F_LENU] do_sys __NR_write mov sp,old_sp // de-alloca .unreq old_sp // busy: x15 mov arg6,#0 // beginning of file mov arg5w,mfd mov arg4w,#MAP_PRIVATE // modes mov arg3w,#PROT_READ|PROT_EXEC // prot ldr arg2,[sp,#F_LENU] mov arg1,#0 // addr (kernel chooses) do_sys __NR_mmap; str x0,[sp,#F_ADRU] u_ptr .req x14 // busy: x15,x14 mov u_ptr,x0 mov arg1w,mfd .unreq mfd // busy: x14 do_sys __NR_close adr arg1,_start - 4*4 // &SO_INFO add arg2,sp,#F_ARGC // &{argc, argv, envp} add u_ptr,u_ptr,2*NBPW br u_ptr .unreq u_ptr str_upx: .asciz "upx" str_psa: .asciz "/proc/self/auxv" .balign 4 //%esp: // MATCH_04 ptr unfolded_code // MATCH_10 len unfolded_code // MATCH_00 argc,argv,envp,lr(_start) f_decompress: // nrv2b code is hard-wired here #define NO_METHOD_CHECK 1 // only one de-compressor; build 'eof' return #undef DAISY_CHAIN // use of mmap() forces implcit cache sync #define NO_SYNC_CACHE 1 off .req w5 #include "arch/arm64/v8/nrv2b_d32.S" // IDENTSTR goes here section ELFMAINZ fold_info: // b_info (sz_unc, sz_cpr, method) of folded code (C-language, etc.) /* vim:set ts=8 sw=8 et: */