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:
parent
29387f1fcf
commit
89e25657d8
|
@ -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)) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user