From d1c80154f6edcd56584eeca941d7672664281f67 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Tue, 12 Feb 2019 21:13:24 -0800 Subject: [PATCH] SHT_NOTE with ~SHF_ALLOC; as for 'gold' linker version https://github.com/upx/upx/issues/243 modified: p_lx_elf.cpp --- src/p_lx_elf.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index c353a265..3b525b50 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -3012,7 +3012,7 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/) if (PT_NOTE32 == get_te32(&phdr->p_type)) { upx_uint32_t memsz = get_te32(&phdr->p_memsz); if (sizeof(buf_notes) < (memsz + len_notes)) { - throwCantPack("PT_NOTES too big"); + throwCantPack("PT_NOTEs too big"); } set_te32(&phdr->p_vaddr, len_notes + (e_shnum * sizeof(Elf32_Shdr)) + xct_off); @@ -3136,11 +3136,17 @@ void PackLinuxElf32::pack1(OutputFile *fo, Filter & /*ft*/) fo->rewrite(rel0, sh_size); } if (Elf32_Shdr::SHT_NOTE == sh_type) { - if (xct_off <= sh_offset) { - set_te32(&shdr->sh_offset, - (e_shnum * sizeof(Elf32_Shdr)) + xct_off); - shdr->sh_addr = shdr->sh_offset; + if (!(Elf32_Shdr::SHF_ALLOC & get_te32(&shdr->sh_flags))) { + // example: version number of 'gold' linker (static binder) + if (sizeof(buf_notes) < (sh_size + len_notes)) { + throwCantPack("SHT_NOTEs too big"); + } + set_te32(&shdro[j].sh_offset, + len_notes + (e_shnum * sizeof(Elf32_Shdr)) + xct_off); + memcpy(&buf_notes[len_notes], &file_image[sh_offset], sh_size); + len_notes += sh_size; } + // else: SHF_ALLOC, thus already in PT_LOAD } } // shstrndx will move @@ -3518,11 +3524,17 @@ void PackLinuxElf64::pack1(OutputFile *fo, Filter & /*ft*/) } } if (Elf64_Shdr::SHT_NOTE == sh_type) { - if (xct_off <= sh_offset) { - set_te64(&shdr->sh_offset, - (e_shnum * sizeof(Elf64_Shdr)) + xct_off); - shdr->sh_addr = shdr->sh_offset; + if (!(Elf64_Shdr::SHF_ALLOC & get_te64(&shdr->sh_flags))) { + // example: version numer of 'gold' linker (static binder) + if (sizeof(buf_notes) < (sh_size + len_notes)) { + throwCantPack("SHT_NOTEs too big"); + } + set_te64(&shdro[j].sh_offset, + len_notes + (e_shnum * sizeof(Elf64_Shdr)) + xct_off); + memcpy(&buf_notes[len_notes], &file_image[sh_offset], sh_size); + len_notes += sh_size; } + // else: SHF_ALLOC, thus already in PT_LOAD } } // shstrndx will move