mirror of https://github.com/upx/upx.git
Stub for 64-bit shlib
modified: stub/Makefile modified: stub/src/amd64-expand.S modified: stub/src/amd64-linux.elf-entry.S modified: stub/src/amd64-linux.elf-so_entry.S modified: stub/src/amd64-linux.elf-so_fold.S modified: stub/src/amd64-linux.elf-so_main.c modified: stub/src/arm64-expand.S modified: stub/src/upxfd_linux.c
This commit is contained in:
parent
d04209d30f
commit
bd251c0dbd
|
@ -421,11 +421,13 @@ tc.amd64-linux.elf.gcc += -fno-exceptions -fno-asynchronous-unwind-tables
|
|||
tc.amd64-linux.elf.gcc += -Wall -W -Wcast-align -Wcast-qual -Wstrict-prototypes -Wwrite-strings -Werror
|
||||
|
||||
amd64-linux.elf-entry.h: $(srcdir)/src/$$T.S
|
||||
@echo; echo TARGET=$@ PATH=$(PATH); echo
|
||||
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin
|
||||
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
||||
$(call tc,bin2h) tmp/$T.bin $@
|
||||
|
||||
amd64-linux.elf-so_entry.h: $(srcdir)/src/$$T.S
|
||||
@echo; echo TARGET=$@ PATH=$(PATH); echo
|
||||
$(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin
|
||||
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
||||
$(call tc,bin2h) tmp/$T.bin $@
|
||||
|
@ -433,17 +435,32 @@ amd64-linux.elf-so_entry.h: $(srcdir)/src/$$T.S
|
|||
amd64-linux.elf-fold.h : $(srcdir)/src/$$T.lds \
|
||||
tmp/$$T.o \
|
||||
tmp/amd64-expand.o \
|
||||
tmp/amd64-linux.elf-upxfd_linux.o \
|
||||
tmp/amd64-linux.elf-main2.o
|
||||
@echo; echo TARGET=$@ PATH=$(PATH); echo
|
||||
# FIXME: multiarch-ld-2.18 creates a huge file here, so use 2.17
|
||||
multiarch-ld-2.17 -r -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
|
||||
$(call tc,f-embed_objinfo_without_xstrip_keep_dot_text,tmp/$T.bin)
|
||||
$(call tc,bin2h) tmp/$T.bin $@
|
||||
|
||||
amd64-linux.elf-so_fold.h : tmp/$$T.o tmp/amd64-linux.elf-so_main.o $(srcdir)/src/$$T.lds tmp/amd64-expand.o
|
||||
multiarch-ld-2.17 -r -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
|
||||
amd64-linux.elf-so_fold.h : $(srcdir)/src/$$T.lds \
|
||||
tmp/$$T.o \
|
||||
tmp/amd64-expand.o \
|
||||
tmp/amd64-linux.elf-upxfd_linux.o \
|
||||
tmp/amd64-linux.elf-so_main.o
|
||||
@echo; echo TARGET=$@ PATH=$(PATH); echo
|
||||
# FIXME: multiarch-ld-2.18 creates a huge file here, so use 2.17
|
||||
$(call tc,ld) -r -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
|
||||
# multiarch-ld-2.17 -r -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
|
||||
ls -l tmp/$T.bin
|
||||
$(call tc,f-embed_objinfo_without_xstrip,tmp/$T.bin)
|
||||
$(call tc,bin2h) tmp/$T.bin $@
|
||||
|
||||
tmp/amd64-linux.elf-so_fold.o : $(srcdir)/src/$$T.S
|
||||
$(call tc,gcc) -c $< -o tmp/$T.o
|
||||
$(call tc,objcopy) -R .text $@
|
||||
$(call tc,f-objstrip,$@)
|
||||
|
||||
tmp/amd64-expand.o: $(srcdir)/src/$$T.S
|
||||
$(call tc,gcc) -c $< -o $@
|
||||
|
||||
|
@ -451,11 +468,6 @@ tmp/amd64-linux.elf-fold.o : $(srcdir)/src/$$T.S
|
|||
$(call tc,gcc) -c $< -o $@
|
||||
$(call tc,f-objstrip,$@)
|
||||
|
||||
tmp/amd64-linux.elf-so_fold.o : $(srcdir)/src/$$T.S
|
||||
$(call tc,gcc) -c $< -o $@
|
||||
$(call tc,objcopy) -R .text $@
|
||||
$(call tc,f-objstrip,$@)
|
||||
|
||||
tmp/amd64-linux.elf-main.o : $(srcdir)/src/$$T.c
|
||||
$(call tc,gcc) -c -Os $< -o $@
|
||||
$(call tc,f-objstrip,$@)
|
||||
|
@ -834,6 +846,11 @@ tmp/arm64-expand.o: $(srcdir)/src/$$T.S
|
|||
$(call tc,gcc) -c $< -o $@
|
||||
arm64-linux-objdump-2.25 -Dr $(tc_objdump_disasm_options) tmp/$T.o | $(RTRIM) > tmp/$T.o.disasm
|
||||
|
||||
tmp/amd64-linux.elf-upxfd_linux.o : $(srcdir)/src/upxfd_linux.c
|
||||
$(call tc,gcc) -c -O $< -o $@
|
||||
$(call tc,objcopy) --rename-section .text=UMF_LINUX -R .comment -R .data -R .bss -R .note.GNU-stack $@
|
||||
$(call tc,objdump) -Dr $(tc_objdump_disasm_options) $@ | $(RTRIM) > $@.disasm
|
||||
|
||||
tmp/arm64-linux.elf-main2.o : $(srcdir)/src/$$T.c $(srcdir)/src/amd64-linux.elf-main2.c
|
||||
$(call tc,gcc) -c -Os $(srcdir)/src/arm64-linux.elf-main2.c -o $@
|
||||
$(call tc,f-objstrip,$@)
|
||||
|
|
|
@ -229,3 +229,7 @@ eof_n2e:
|
|||
movl %edi,(%rcx) // actual length used at dst XXX: 4GB
|
||||
sub %rsi,%rax // src -= eof; // return 0: good; else: bad
|
||||
ret
|
||||
|
||||
.balign 4
|
||||
upx_mmap_and_fd: .globl upx_mmap_and_fd
|
||||
// UMF_LINUX goes here
|
||||
|
|
|
@ -129,9 +129,9 @@ D_PMASK= 0*NBPW
|
|||
#define arg2l esi
|
||||
#define arg3l edx
|
||||
// Create anonymous temporary file on mfd; like upxfd_create
|
||||
push $'u'|('p'<<8)|('x'<<16)|(0<<24) // MATCH_22
|
||||
push %rsp; pop %arg1 // "upx"
|
||||
mov $MFD_EXEC,%arg2l
|
||||
push $'u'|('p'<<8)|('X'<<16)|(0<<24) // MATCH_22
|
||||
push %rsp; pop %arg1 // "upX"
|
||||
push $MFD_EXEC; pop %arg2
|
||||
0: // try memfd_create
|
||||
movl $__NR_memfd_create,%eax; syscall
|
||||
test %eax,%eax; jns ok_memfd // success
|
||||
|
|
|
@ -58,6 +58,7 @@ __NR_mmap= 9 // 64-bit mode only! /usr/include/asm/unistd_64.h
|
|||
__NR_mprotect= 10
|
||||
__NR_munmap= 11
|
||||
__NR_memfd_create= 0x13f // 319
|
||||
MFD_EXEC= 0x10
|
||||
|
||||
__NR_write= 1
|
||||
__NR_close= 3
|
||||
|
@ -204,9 +205,20 @@ eof_n2b:
|
|||
|
||||
pop %rbp // MATCH_45
|
||||
|
||||
push $0; pop %arg2
|
||||
call 0f; .asciz "upx"; 0: pop %arg1
|
||||
push $__NR_memfd_create; call do_sys
|
||||
#define arg2l esi
|
||||
// Create anonymous temporary file on mfd; like upxfd_create
|
||||
push $'u'|('p'<<8)|('X'<<16)|(0<<24) // MATCH_22
|
||||
push %rsp; pop %arg1 // "upX"
|
||||
push $MFD_EXEC; pop %arg2
|
||||
0: // try memfd_create
|
||||
movl $__NR_memfd_create,%eax; syscall
|
||||
test %eax,%eax; jns ok_memfd // success
|
||||
test %arg2l,%arg2l; jz no_memfd // memfd_create failed twice
|
||||
xor %arg2l,%arg2l; jmp 0b // try again without MFD_EXEC
|
||||
no_memfd: // so try /dev/shm
|
||||
hlt // FIXME /dev/shm
|
||||
ok_memfd:
|
||||
pop %rcx // MATCH_22 discard "upx"
|
||||
|
||||
push %rax; pop %arg1 // mfd
|
||||
push %rsp; pop %arg2 // buffer
|
||||
|
|
|
@ -98,6 +98,7 @@ __NR_read= 0
|
|||
__NR_write= 1
|
||||
//__NR_open= 2
|
||||
__NR_openat= 257
|
||||
FD_CWD= -100
|
||||
__NR_close= 3
|
||||
|
||||
__NR_mmap= 9
|
||||
|
@ -149,6 +150,13 @@ sysgo: # NOTE: kernel demands 4th arg in %sys4, NOT %arg4
|
|||
syscall; cmp $-4096,%rax; jb 0f; int3; 0:
|
||||
ret
|
||||
|
||||
open: .globl open
|
||||
mov %arg3,%arg4
|
||||
mov %arg2,%arg3
|
||||
mov %arg1,%arg2
|
||||
mov $FD_CWD,%arg1
|
||||
jmp openat
|
||||
|
||||
Punmap: .globl Punmap // page-align the lo end
|
||||
mov %arg1,%rax; and $0xfff,%eax
|
||||
sub %rax,%arg1
|
||||
|
|
|
@ -40,8 +40,6 @@ extern size_t Pwrite(unsigned, void const *, size_t);
|
|||
|
||||
extern void f_int3(int arg);
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#ifndef DEBUG //{
|
||||
#define DEBUG 0
|
||||
#endif //}
|
||||
|
@ -384,10 +382,10 @@ make_hatch(
|
|||
) >> ((pf & (PF_R|PF_W|PF_X))<<2) ))
|
||||
|
||||
#undef PAGE_MASK
|
||||
static unsigned long
|
||||
static ElfW(Addr)
|
||||
get_page_mask(void) // the mask which KEEPS the page, discards the offset
|
||||
{
|
||||
unsigned long rv = ~0xffful; // default to (PAGE_SIZE == 4KiB)
|
||||
ElfW(Addr) rv = ~0xffful; // default to (PAGE_SIZE == 4KiB)
|
||||
int fd = openat(0, addr_string("/proc/self/auxv"), O_RDONLY, 0);
|
||||
if (0 <= fd) {
|
||||
ElfW(auxv_t) data[40];
|
||||
|
@ -454,16 +452,25 @@ fini_SELinux(
|
|||
}
|
||||
|
||||
unsigned
|
||||
prep_SELinux(unsigned size, char *ptr, unsigned len) // returns mfd
|
||||
prep_SELinux(unsigned size, char *ptr, ElfW(Addr) page_mask) // returns mfd
|
||||
{
|
||||
// Cannot set PROT_EXEC except via mmap() into a region (Linux "vma")
|
||||
// that has never had PROT_WRITE. So use a Linux-only "memory file"
|
||||
// to hold the contents.
|
||||
char *val = upx_mmap_and_fd(ptr, size, nullptr);
|
||||
unsigned mfd = 0xfff & (unsigned)(long)val;
|
||||
unsigned saved[65536/sizeof(unsigned)];
|
||||
char *page = (char *)(page_mask & (ElfW(Addr))ptr);
|
||||
unsigned frag = (unsigned)(ptr - page);
|
||||
if (frag) {
|
||||
memcpy(saved, page, frag);
|
||||
}
|
||||
char *val = upx_mmap_and_fd(page, frag + size, nullptr);
|
||||
unsigned mfd = 0xfff & (unsigned)(ElfW(Addr))val;
|
||||
val -= mfd; --mfd;
|
||||
if (len)
|
||||
Pwrite(mfd, ptr, len); // Save lo fragment of contents on first page.
|
||||
if (val != page) {
|
||||
my_bkpt((void const *)0x1262, val, page, ptr, frag);
|
||||
}
|
||||
if (frag)
|
||||
write(mfd, saved, frag); // Save lo fragment of contents on page.
|
||||
return mfd;
|
||||
}
|
||||
|
||||
|
@ -491,7 +498,7 @@ upx_so_main( // returns &escape_hatch
|
|||
ElfW(Ehdr) *elf_tmp // scratch for ElfW(Ehdr) and ElfW(Phdrs)
|
||||
)
|
||||
{
|
||||
unsigned long const page_mask = get_page_mask();
|
||||
ElfW(Addr) const page_mask = get_page_mask();
|
||||
char *const va_load = (char *)&so_info->off_reloc - so_info->off_reloc;
|
||||
So_info so_infc; // So_info Copy
|
||||
memcpy(&so_infc, so_info, sizeof(so_infc)); // before de-compression overwrites
|
||||
|
@ -548,59 +555,41 @@ upx_so_main( // returns &escape_hatch
|
|||
|
||||
for (; phdr < phdrN; ++phdr)
|
||||
if (phdr->p_type == PT_LOAD && !(phdr->p_flags & PF_W)) {
|
||||
unsigned hi_offset = phdr->p_filesz + phdr->p_offset;
|
||||
struct b_info al_bi; // for aligned data from binfo
|
||||
// Need un-aligned read of b_info to determine compression sizes.
|
||||
struct b_info al_bi; // for aligned data from binfo
|
||||
x0.size = sizeof(struct b_info);
|
||||
xread(&x0, (char *)&al_bi, x0.size); // aligned binfo
|
||||
x0.buf -= sizeof(al_bi); // back up (the xread() was a peek)
|
||||
x1.size = hi_offset - xct_off;
|
||||
x1.buf = (void *)(hi_offset + base - al_bi.sz_unc);
|
||||
x0.size = al_bi.sz_cpr;
|
||||
x0.size = al_bi.sz_cpr;
|
||||
x1.size = al_bi.sz_unc;
|
||||
|
||||
DPRINTF("\\nphdr@%%p p_offset=%%p p_vaddr=%%p p_filesz=%%p p_memsz=%%p\\n",
|
||||
phdr, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
|
||||
DPRINTF("x0=%%p x1=%%p\\n", &x0, &x1);
|
||||
|
||||
if (!base) {
|
||||
base = (ElfW(Addr))va_load - phdr->p_vaddr;
|
||||
DPRINTF("base=%%p\\n", base);
|
||||
}
|
||||
DPRINTF("phdr@%%p p_offset=%%p p_vaddr=%%p p_filesz=%%p p_memsz=%%p\\n",
|
||||
phdr, phdr->p_offset, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz);
|
||||
DPRINTF("x0=%%p x1=%%p\\n", &x0, &x1);
|
||||
//my_bkpt((void const *)0x1230, phdr, &x0, &x1);
|
||||
|
||||
unsigned frag = ~page_mask & (unsigned)(long)x1.buf;
|
||||
unsigned mfd = 0;
|
||||
if (!n_load) { // 1st PT_LOAD is special.
|
||||
// Already ELF headers are in place, perhaps already followed
|
||||
// by non-compressed loader tables below xct_off.
|
||||
if (xct_off < hi_offset) { // 1st PT_LOAD also has compressed code, too
|
||||
if (phdr->p_flags & PF_X) {
|
||||
mfd = prep_SELinux(x1.size, x1.buf, frag);
|
||||
}
|
||||
else {
|
||||
underlay(x1.size, x1.buf, page_mask); // also makes PROT_WRITE
|
||||
}
|
||||
unpackExtent(&x0, &x1);
|
||||
if (!hatch && phdr->p_flags & PF_X) {
|
||||
hatch = make_hatch(phdr, x1.buf, ~page_mask);
|
||||
}
|
||||
my_bkpt((void const *)0x1235, &x1);
|
||||
fini_SELinux(x1.size, x1.buf, phdr, mfd, base); // FIXME: x1 changed!
|
||||
x1.buf = (void *)(phdr->p_filesz + phdr->p_vaddr + base - x1.size);
|
||||
if ((phdr->p_filesz + phdr->p_offset) <= xct_off) { // hi_offset <= xct_off
|
||||
if (!n_load) {
|
||||
++n_load;
|
||||
continue; // 1st PT_LOAD is non-compressed loader tables ONLY!
|
||||
}
|
||||
}
|
||||
else { // 2nd and later PT_LOADs
|
||||
x1.buf = (void *)(phdr->p_vaddr + base);
|
||||
x1.size = phdr->p_filesz;
|
||||
if (phdr->p_flags & PF_X) {
|
||||
mfd = prep_SELinux(x1.size, x1.buf, frag);
|
||||
}
|
||||
else {
|
||||
underlay(x1.size, x1.buf, page_mask); // also makes PROT_WRITE
|
||||
}
|
||||
unpackExtent(&x0, &x1);
|
||||
if (!hatch && phdr->p_flags &PF_X) {
|
||||
hatch = make_hatch(phdr, x1.buf, ~page_mask);
|
||||
}
|
||||
fini_SELinux(al_bi.sz_unc, (void *)(phdr->p_vaddr + base), phdr, mfd, base);
|
||||
int mfd = 0;
|
||||
if (phdr->p_flags & PF_X) {
|
||||
mfd = prep_SELinux(x1.size, x1.buf, page_mask);
|
||||
}
|
||||
else {
|
||||
underlay(x1.size, x1.buf, page_mask); // also makes PROT_WRITE
|
||||
}
|
||||
Extent xt = x1;
|
||||
unpackExtent(&x0, &x1);
|
||||
if (!hatch && phdr->p_flags & PF_X) {
|
||||
hatch = make_hatch(phdr, x1.buf, ~page_mask);
|
||||
fini_SELinux(xt.size, xt.buf, phdr, mfd, base); // FIXME: x1 was changed by unpackExtent!
|
||||
}
|
||||
++n_load;
|
||||
}
|
||||
|
|
|
@ -140,6 +140,9 @@ eof_lzma: .globl eof_lzma
|
|||
POP4(x2,x3, fp,lr) // MATCH_94 x2= orig_dst; x3= plen_dst
|
||||
ret
|
||||
|
||||
upx_mmap_and_fd: .globl upx_mmap_and_fd
|
||||
// UMF_LINUX goes here
|
||||
|
||||
#define M_NRV2B_LE32 2
|
||||
#define M_NRV2B_8 3
|
||||
#define M_NRV2D_LE32 5
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* upxfd_create.c -- workaround for 32-bit Android
|
||||
/* upxfd_create.c -- simplify upx_mmap_and_fd_linux for non-Android
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
|
|
Loading…
Reference in New Issue