mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Prepare for ability to compress PT_INTERP program.
Also save 16 bytes at cost of incompatible with glibc-2.1.1 (1999-12-29). fold_elf86.asm l_lx_elf.c committer: jreiser <jreiser> 1032625240 +0000
This commit is contained in:
parent
448baac0f4
commit
8ad3d01d81
|
@ -106,50 +106,56 @@ L50:
|
|||
mov ecx, [4+ eax] ; length of compressed ELF headers
|
||||
add ecx, byte szb_info
|
||||
pusha ; (AT_table, sz_cpr, f_expand, &tmp_ehdr, {sz_unc, &tmp}, {sz_cpr, &b1st_info} )
|
||||
inc edi ; swap with above 'pusha' to inhibit auxv_up for PT_INTERP
|
||||
EXTERN upx_main
|
||||
call upx_main ; returns entry address
|
||||
add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space
|
||||
pop ebx ; &Elf32_Ehdr of this stub
|
||||
push eax ; save entry address
|
||||
|
||||
mov esi, edi ; auxv table
|
||||
L60: ; search for AT_PHDR
|
||||
lodsd ; a_type
|
||||
cmp al, byte AT_PHDR
|
||||
lodsd ; a_un.a_ptr
|
||||
jne L60
|
||||
xchg eax, edi
|
||||
dec edi ; auxv table
|
||||
sub eax,eax ; 0, also AT_NULL
|
||||
db 0x3c ; "cmpb al, byte ..." like "jmp 1+L60" but 1 byte shorter
|
||||
L60:
|
||||
scasd ; a_un
|
||||
scasd ; a_val
|
||||
jne L60 ; not AT_NULL
|
||||
mov edx,[edi] ; &hatch
|
||||
stosd ; clear a_un.a_ptr for AT_NULL
|
||||
|
||||
find_hatch:
|
||||
push edi
|
||||
EXTERN make_hatch
|
||||
call make_hatch ; find hatch = make_hatch(phdr)
|
||||
pop ecx ; junk the parameter
|
||||
add edi, byte szElf32_Phdr ; prepare to try next Elf32_Phdr
|
||||
test eax,eax
|
||||
jz find_hatch
|
||||
xchg eax,edx ; edx= &hatch
|
||||
|
||||
; _dl_start and company (ld-linux.so.2) assumes that it has virgin stack,
|
||||
; and does not initialize all its stack local variables to zero.
|
||||
; Ulrich Drepper (drepper@cyngus.com) has refused to fix the bugs.
|
||||
; See GNU wwwgnats libc/1165 .
|
||||
; _dl_start and company (ld-linux.so.2) once assumed that it had virgin stack,
|
||||
; and did not initialize all its stack local variables to zero.
|
||||
; See bug libc/1165 at http://bugs.gnu.org/cgi-bin/gnatsweb.pl
|
||||
; Found 1999-06-16 glibc-2.1.1
|
||||
; Fixed 1999-12-29 glibc-2.1.2
|
||||
|
||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||
lea edi, [esp - 4*N_STKCLR]
|
||||
pusha ; values will be zeroed
|
||||
mov esi,esp ; save
|
||||
mov esp,edi ; Linux does not grow stack below esp
|
||||
mov ecx, N_STKCLR
|
||||
xor eax,eax
|
||||
rep stosd
|
||||
mov esp,esi ; restore
|
||||
%define N_STKCLR 8
|
||||
; lea edi, [esp - 4*N_STKCLR]
|
||||
; pusha ; values will be zeroed
|
||||
; mov esi,esp ; save
|
||||
; mov esp,edi ; Linux does not grow stack below esp
|
||||
; mov ecx, N_STKCLR
|
||||
; ; xor eax,eax ; eax already 0 from L60
|
||||
; rep stosd
|
||||
; mov esp,esi ; restore
|
||||
; xor ecx, ecx ; ecx already 0 from "rep stosd"
|
||||
|
||||
xor ecx, ecx ; 0
|
||||
push eax
|
||||
push eax
|
||||
push eax
|
||||
push eax
|
||||
push eax
|
||||
push eax
|
||||
push eax
|
||||
push eax ; 32 bytes of zeroes now on stack
|
||||
push eax
|
||||
pop ecx ; 0
|
||||
|
||||
mov al, __NR_munmap ; eax was 0 from L60
|
||||
mov ch, PAGE_SIZE>>8 ; 0x1000
|
||||
add ecx, [p_memsz + szElf32_Ehdr + ebx] ; length to unmap
|
||||
mov bh, 0 ; from 0x401000 to 0x400000
|
||||
mov eax, __NR_munmap ; do not dirty the stack with push byte + pop
|
||||
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
||||
|
||||
; called twice:
|
||||
|
|
|
@ -220,8 +220,9 @@ static void
|
|||
__attribute__ ((regparm(3), stdcall))
|
||||
auxv_up(Elf32_auxv_t *av, int const type, unsigned const value)
|
||||
{
|
||||
if (av && 0==(1&(int)av)) /* PT_INTERP usually inhibits, except for hatch */
|
||||
for (;; ++av) {
|
||||
if (av->a_type==type || av->a_type==AT_IGNORE) {
|
||||
if (av->a_type==type || (av->a_type==AT_IGNORE && type!=AT_NULL)) {
|
||||
av->a_type = type;
|
||||
av->a_un.a_val = value;
|
||||
return;
|
||||
|
@ -275,7 +276,11 @@ do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi,
|
|||
frag = (-mlen) &~ PAGE_MASK; // distance to next page boundary
|
||||
bzero(mlen+addr, frag); // fragment at hi end
|
||||
if (xi) {
|
||||
make_hatch(phdr);
|
||||
void *const hatch = make_hatch(phdr);
|
||||
if (0!=hatch) {
|
||||
/* always update AT_NULL, especially for compressed PT_INTERP */
|
||||
auxv_up((Elf32_auxv_t *)(~1 & (int)av), AT_NULL, hatch);
|
||||
}
|
||||
}
|
||||
if (phdr->p_memsz != phdr->p_filesz) { // .bss
|
||||
if (ET_DYN==ehdr->e_type) { // PT_INTERP whole pages of .bss?
|
||||
|
|
Loading…
Reference in New Issue
Block a user