1
0
mirror of https://github.com/upx/upx synced 2025-10-05 19:20:23 +08:00

fix cross-platform endian trouble with ELF headers

This commit is contained in:
John Reiser 2006-06-27 13:07:31 -07:00
parent 29387f1fcf
commit 89e25657d8

View File

@ -304,7 +304,8 @@ PackLinuxElf32x86::buildLinuxLoader(
unsigned fold_hdrlen = 0; unsigned fold_hdrlen = 0;
if (0 < szfold) { if (0 < szfold) {
cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold; cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
fold_hdrlen = sizeof(hf->ehdr) + hf->ehdr.e_phentsize * hf->ehdr.e_phnum + fold_hdrlen = sizeof(hf->ehdr) +
get_native16(&hf->ehdr.e_phentsize) * get_native16(&hf->ehdr.e_phnum) +
sizeof(l_info); sizeof(l_info);
if (0 == get_le32(fold_hdrlen + fold)) { if (0 == get_le32(fold_hdrlen + fold)) {
// inconsistent SIZEOF_HEADERS in *.lds (ld, binutils) // inconsistent SIZEOF_HEADERS in *.lds (ld, binutils)
@ -354,11 +355,13 @@ PackLinuxElf32x86::buildLinuxLoader(
// Elf32_Edhr // Elf32_Edhr
sizeof(elfout.ehdr) + sizeof(elfout.ehdr) +
// Elf32_Phdr: 1 for exec86, 2 for sh86, 3 for elf86 // Elf32_Phdr: 1 for exec86, 2 for sh86, 3 for elf86
(elfout.ehdr.e_phentsize * elfout.ehdr.e_phnum) + (get_native16(&elfout.ehdr.e_phentsize) * get_native16(&elfout.ehdr.e_phnum)) +
// checksum UPX! lsize version format // checksum UPX! lsize version format
sizeof(l_info) + sizeof(l_info) +
// PT_DYNAMIC with DT_NEEDED "forwarded" from original file // PT_DYNAMIC with DT_NEEDED "forwarded" from original file
((elfout.ehdr.e_phnum==3) ? (unsigned) elfout.phdr[2].p_memsz : 0) + ((get_native16(&elfout.ehdr.e_phnum)==3)
? (unsigned) get_native32(&elfout.phdr[2].p_memsz)
: 0) +
// p_progid, p_filesize, p_blocksize // p_progid, p_filesize, p_blocksize
sizeof(p_info) + sizeof(p_info) +
// compressed data // compressed data
@ -1002,7 +1005,7 @@ void PackLinuxElf32::pack1(OutputFile */*fo*/, Filter &/*ft*/)
void PackLinuxElf32x86::pack1(OutputFile *fo, Filter &ft) void PackLinuxElf32x86::pack1(OutputFile *fo, Filter &ft)
{ {
super::pack1(fo, ft); super::pack1(fo, ft);
generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, ehdri.e_phnum) ); generateElfHdr(fo, linux_i386elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
} }
void PackLinuxElf32::ARM_pack1(OutputFile *fo, bool const isBE) void PackLinuxElf32::ARM_pack1(OutputFile *fo, bool const isBE)
@ -1023,7 +1026,7 @@ void PackLinuxElf32::ARM_pack1(OutputFile *fo, bool const isBE)
sizeof(Elf32_Ehdr) + (unsigned char const *)&linux_elf32arm_fold, sizeof(Elf32_Ehdr) + (unsigned char const *)&linux_elf32arm_fold,
3*sizeof(Elf32_Phdr) ); 3*sizeof(Elf32_Phdr) );
} }
generateElfHdr(fo, &h3, getbrk(phdri, ehdri.e_phnum) ); generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
} }
void PackLinuxElf32armLe::pack1(OutputFile *fo, Filter &ft) void PackLinuxElf32armLe::pack1(OutputFile *fo, Filter &ft)
@ -1041,7 +1044,7 @@ void PackLinuxElf32armBe::pack1(OutputFile *fo, Filter &ft) // FIXME
void PackLinuxElf32ppc::pack1(OutputFile *fo, Filter &ft) void PackLinuxElf32ppc::pack1(OutputFile *fo, Filter &ft)
{ {
super::pack1(fo, ft); super::pack1(fo, ft);
generateElfHdr(fo, linux_elfppc32_fold, getbrk(phdri, ehdri.e_phnum) ); generateElfHdr(fo, linux_elfppc32_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
} }
void PackLinuxElf64::pack1(OutputFile */*fo*/, Filter &/*ft*/) void PackLinuxElf64::pack1(OutputFile */*fo*/, Filter &/*ft*/)
@ -1063,7 +1066,7 @@ void PackLinuxElf64::pack1(OutputFile */*fo*/, Filter &/*ft*/)
void PackLinuxElf64amd::pack1(OutputFile *fo, Filter &ft) void PackLinuxElf64amd::pack1(OutputFile *fo, Filter &ft)
{ {
super::pack1(fo, ft); super::pack1(fo, ft);
generateElfHdr(fo, linux_elf64amd_fold, getbrk(phdri, ehdri.e_phnum) ); generateElfHdr(fo, linux_elf64amd_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
} }
// Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD // Determine length of gap between PT_LOAD phdr[k] and closest PT_LOAD
@ -1310,12 +1313,13 @@ void PackLinuxElf64amd::pack3(OutputFile *fo, Filter &ft)
len += (7&-lsize) + lsize; len += (7&-lsize) + lsize;
bool const is_big = (lo_va_user < (lo_va_stub + len + 2*PAGE_SIZE)); bool const is_big = (lo_va_user < (lo_va_stub + len + 2*PAGE_SIZE));
if (is_big) { if (is_big) {
elfout.ehdr.e_entry += lo_va_user - lo_va_stub; set_native64( &elfout.ehdr.e_entry,
elfout.phdr[0].p_vaddr = lo_va_user; get_native64(&elfout.ehdr.e_entry) + lo_va_user - lo_va_stub);
elfout.phdr[0].p_paddr = lo_va_user; set_native64(&elfout.phdr[0].p_vaddr, lo_va_user);
set_native64(&elfout.phdr[0].p_paddr, lo_va_user);
lo_va_stub = lo_va_user; lo_va_stub = lo_va_user;
adrc = lo_va_stub; adrc = lo_va_stub;
adrm = getbrk(phdri, ehdri.e_phnum); adrm = getbrk(phdri, get_native16(&ehdri.e_phnum));
adru = PAGE_MASK & (~PAGE_MASK + adrm); // round up to page boundary adru = PAGE_MASK & (~PAGE_MASK + adrm); // round up to page boundary
adrx = adru + hlen; adrx = adru + hlen;
lenm = PAGE_SIZE + len; lenm = PAGE_SIZE + len;
@ -1551,13 +1555,14 @@ void PackLinuxElf32::pack4(OutputFile *fo, Filter &ft)
#endif /*}*/ #endif /*}*/
// rewrite Elf header // rewrite Elf header
if (Elf32_Ehdr::ET_DYN==ehdri.e_type) { if (Elf32_Ehdr::ET_DYN==get_native16(&ehdri.e_type)) {
unsigned const base= elfout.phdr[0].p_vaddr; unsigned const base= get_native32(&elfout.phdr[0].p_vaddr);
elfout.ehdr.e_type= Elf32_Ehdr::ET_DYN; set_native16(&elfout.ehdr.e_type, Elf32_Ehdr::ET_DYN);
elfout.ehdr.e_phnum= 1; set_native16(&elfout.ehdr.e_phnum, 1);
elfout.ehdr.e_entry -= base; set_native32( &elfout.ehdr.e_entry,
elfout.phdr[0].p_vaddr -= base; get_native32(&elfout.ehdr.e_entry) - base);
elfout.phdr[0].p_paddr -= base; set_native32(&elfout.phdr[0].p_vaddr, get_native32(&elfout.phdr[0].p_vaddr) - base);
set_native32(&elfout.phdr[0].p_paddr, get_native32(&elfout.phdr[0].p_paddr) - base);
// Strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X // Strict SELinux (or PaX, grSecurity) disallows PF_W with PF_X
//elfout.phdr[0].p_flags |= Elf32_Phdr::PF_W; //elfout.phdr[0].p_flags |= Elf32_Phdr::PF_W;
} }
@ -1869,7 +1874,7 @@ unsigned
PackLinuxElf32::elf_get_offset_from_address(unsigned const addr) const PackLinuxElf32::elf_get_offset_from_address(unsigned const addr) const
{ {
Elf32_Phdr const *phdr = phdri; Elf32_Phdr const *phdr = phdri;
int j = ehdri.e_phnum; int j = get_native16(&ehdri.e_phnum);
for (; --j>=0; ++phdr) if (PT_LOAD32 == get_native32(&phdr->p_type)) { for (; --j>=0; ++phdr) if (PT_LOAD32 == get_native32(&phdr->p_type)) {
unsigned const t = addr - get_native32(&phdr->p_vaddr); unsigned const t = addr - get_native32(&phdr->p_vaddr);
if (t < get_native32(&phdr->p_filesz)) { if (t < get_native32(&phdr->p_filesz)) {