diff --git a/src/stub/fold_elf86.asm b/src/stub/fold_elf86.asm index 0d9da6b6..23554a4c 100644 --- a/src/stub/fold_elf86.asm +++ b/src/stub/fold_elf86.asm @@ -49,56 +49,42 @@ fold_begin: ; enter: %ebx= &Elf32_Ehdr of this program pop eax ; discard &sz_uncompressed pop eax ; discard sz_uncompressed -; Move argc,argv,envp down to make room for complete Elf_auxv table. +; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance. +; Move argc,argv,envp down to make room for Elf_auxv table. ; Linux kernel 2.4.2 and earlier give only AT_HWCAP and AT_PLATFORM ; because we have no PT_INTERP. Linux kernel 2.4.5 (and later?) ; give not quite everything. It is simpler and smaller code for us ; to generate a "complete" table where Elf_auxv[k -1].a_type = k. -; ld-linux.so.2 depends on AT_PHDR and AT_ENTRY, for instance +; On second thought, that wastes a lot of stack space (the entire kernel +; auxv, plus those slots that remain empty anyway). So try for minimal +; space on stack, without too much code, by doing it serially. %define AT_NULL 0 %define AT_IGNORE 1 %define AT_PHDR 3 +%define AT_PHENT 4 +%define AT_PHNUM 5 +%define AT_PAGESZ 6 +%define AT_ENTRY 9 %define AT_NUMBER 20 + sub ecx, ecx + mov edx, (1<a_type==type || av->a_type==AT_IGNORE) { + av->a_type = type; + av->a_un.a_val = value; + return; + } + } +} + static Elf32_Addr // entry address do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi, Elf32_auxv_t *const av) @@ -222,7 +234,7 @@ do_xmap(int const fdi, Elf32_Ehdr const *const ehdr, struct Extent *const xi, int j; for (j=0; j < ehdr->e_phnum; ++phdr, ++j) if (PT_PHDR==phdr->p_type) { - av[AT_PHDR -1].a_un.a_val = phdr->p_vaddr; + auxv_up(av, AT_PHDR, phdr->p_vaddr); } else if (PT_LOAD==phdr->p_type) { struct Extent xo; @@ -346,12 +358,12 @@ void *upx_main( xi.buf -= sz_pckhdrs; xi.size = sz_compressed; - // av[AT_PHDR -1].a_un.a_val is set again by do_xmap if PT_PHDR is present. - av[AT_PHDR -1].a_type = AT_PHDR ; av[AT_PHDR -1].a_un.a_ptr = 1+(Elf32_Ehdr *)phdr->p_vaddr; - av[AT_PHENT -1].a_type = AT_PHENT ; av[AT_PHENT -1].a_un.a_val = ehdr->e_phentsize; - av[AT_PHNUM -1].a_type = AT_PHNUM ; av[AT_PHNUM -1].a_un.a_val = ehdr->e_phnum; - av[AT_PAGESZ -1].a_type = AT_PAGESZ; av[AT_PAGESZ -1].a_un.a_val = PAGE_SIZE; - av[AT_ENTRY -1].a_type = AT_ENTRY ; av[AT_ENTRY -1].a_un.a_val = ehdr->e_entry; + // AT_PHDR.a_un.a_val is set again by do_xmap if PT_PHDR is present. + auxv_up(av, AT_PHDR , (unsigned)(1+(Elf32_Ehdr *)phdr->p_vaddr)); + auxv_up(av, AT_PHENT , ehdr->e_phentsize); + auxv_up(av, AT_PHNUM , ehdr->e_phnum); + //auxv_up(av, AT_PAGESZ, PAGE_SIZE); /* ld-linux.so.2 does not need this */ + auxv_up(av, AT_ENTRY , (unsigned)ehdr->e_entry); entry = do_xmap((int)f_decompress, ehdr, &xi, av); { // Map PT_INTERP program interpreter