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
|
mov ecx, [4+ eax] ; length of compressed ELF headers
|
||||||
add ecx, byte szb_info
|
add ecx, byte szb_info
|
||||||
pusha ; (AT_table, sz_cpr, f_expand, &tmp_ehdr, {sz_unc, &tmp}, {sz_cpr, &b1st_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
|
EXTERN upx_main
|
||||||
call upx_main ; returns entry address
|
call upx_main ; returns entry address
|
||||||
add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space
|
add esp, dword 8*4 + MAX_ELF_HDR + OVERHEAD ; remove 8 params, temp space
|
||||||
pop ebx ; &Elf32_Ehdr of this stub
|
pop ebx ; &Elf32_Ehdr of this stub
|
||||||
push eax ; save entry address
|
push eax ; save entry address
|
||||||
|
|
||||||
mov esi, edi ; auxv table
|
dec edi ; auxv table
|
||||||
L60: ; search for AT_PHDR
|
sub eax,eax ; 0, also AT_NULL
|
||||||
lodsd ; a_type
|
db 0x3c ; "cmpb al, byte ..." like "jmp 1+L60" but 1 byte shorter
|
||||||
cmp al, byte AT_PHDR
|
L60:
|
||||||
lodsd ; a_un.a_ptr
|
scasd ; a_un
|
||||||
jne L60
|
scasd ; a_val
|
||||||
xchg eax, edi
|
jne L60 ; not AT_NULL
|
||||||
|
mov edx,[edi] ; &hatch
|
||||||
|
stosd ; clear a_un.a_ptr for AT_NULL
|
||||||
|
|
||||||
find_hatch:
|
; _dl_start and company (ld-linux.so.2) once assumed that it had virgin stack,
|
||||||
push edi
|
; and did not initialize all its stack local variables to zero.
|
||||||
EXTERN make_hatch
|
; See bug libc/1165 at http://bugs.gnu.org/cgi-bin/gnatsweb.pl
|
||||||
call make_hatch ; find hatch = make_hatch(phdr)
|
; Found 1999-06-16 glibc-2.1.1
|
||||||
pop ecx ; junk the parameter
|
; Fixed 1999-12-29 glibc-2.1.2
|
||||||
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 .
|
|
||||||
|
|
||||||
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
%define N_STKCLR (0x100 + MAX_ELF_HDR + OVERHEAD)/4
|
||||||
lea edi, [esp - 4*N_STKCLR]
|
%define N_STKCLR 8
|
||||||
pusha ; values will be zeroed
|
; lea edi, [esp - 4*N_STKCLR]
|
||||||
mov esi,esp ; save
|
; pusha ; values will be zeroed
|
||||||
mov esp,edi ; Linux does not grow stack below esp
|
; mov esi,esp ; save
|
||||||
mov ecx, N_STKCLR
|
; mov esp,edi ; Linux does not grow stack below esp
|
||||||
xor eax,eax
|
; mov ecx, N_STKCLR
|
||||||
rep stosd
|
; ; xor eax,eax ; eax already 0 from L60
|
||||||
mov esp,esi ; restore
|
; 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
|
mov ch, PAGE_SIZE>>8 ; 0x1000
|
||||||
add ecx, [p_memsz + szElf32_Ehdr + ebx] ; length to unmap
|
add ecx, [p_memsz + szElf32_Ehdr + ebx] ; length to unmap
|
||||||
mov bh, 0 ; from 0x401000 to 0x400000
|
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
|
jmp edx ; unmap ourselves via escape hatch, then goto entry
|
||||||
|
|
||||||
; called twice:
|
; called twice:
|
||||||
|
|
|
@ -220,8 +220,9 @@ static void
|
||||||
__attribute__ ((regparm(3), stdcall))
|
__attribute__ ((regparm(3), stdcall))
|
||||||
auxv_up(Elf32_auxv_t *av, int const type, unsigned const value)
|
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) {
|
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_type = type;
|
||||||
av->a_un.a_val = value;
|
av->a_un.a_val = value;
|
||||||
return;
|
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
|
frag = (-mlen) &~ PAGE_MASK; // distance to next page boundary
|
||||||
bzero(mlen+addr, frag); // fragment at hi end
|
bzero(mlen+addr, frag); // fragment at hi end
|
||||||
if (xi) {
|
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 (phdr->p_memsz != phdr->p_filesz) { // .bss
|
||||||
if (ET_DYN==ehdr->e_type) { // PT_INTERP whole pages of .bss?
|
if (ET_DYN==ehdr->e_type) { // PT_INTERP whole pages of .bss?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user