Skip to content

Commit f823fa3

Browse files
authored
Merge branch 'master' into endianness-fix
2 parents 4052850 + add92c1 commit f823fa3

File tree

9 files changed

+111
-24
lines changed

9 files changed

+111
-24
lines changed

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ AM_INIT_AUTOMAKE([1.11.1 -Wall -Werror dist-bzip2 foreign color-tests parallel-t
66

77
AM_PROG_CC_C_O
88
AC_PROG_CXX
9+
AM_PROG_AS
910

1011
DEFAULT_PAGESIZE=auto
1112
AC_ARG_WITH([page-size],

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
patchelf-new = final.stdenv.mkDerivation {
2828
name = "patchelf-${self.hydraJobs.tarball.version}";
2929
src = "${self.hydraJobs.tarball}/tarballs/*.tar.bz2";
30+
doCheck = true;
3031
};
3132

3233
};

src/elf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,9 @@ typedef struct
366366
required */
367367
#define SHF_GROUP (1 << 9) /* Section is member of a group. */
368368
#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
369+
#define SHF_COMPRESSED (1 << 11) /* Section with compressed data */
369370
#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
371+
#define SHF_GNU_BUILD_NOTE (1 << 20) /* Section contains GNU BUILD ATTRIBUTE notes. */
370372
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
371373
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
372374
(Solaris). */

src/patchelf.cc

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ static void checkPointer(const FileContents & contents, void * p, unsigned int s
380380

381381

382382
template<ElfFileParams>
383-
ElfFile<ElfFileParamNames>::ElfFile(FileContents fileContents)
384-
: fileContents(fileContents)
383+
ElfFile<ElfFileParamNames>::ElfFile(FileContents fContents)
384+
: fileContents(fContents)
385385
, contents(fileContents->data())
386386
{
387387
/* Check the ELF header for basic validity. */
@@ -673,15 +673,15 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
673673
*before* writing the new section contents (below) to prevent
674674
clobbering previously written new section contents. */
675675
for (auto & i : replacedSections) {
676-
std::string sectionName = i.first;
676+
const std::string & sectionName = i.first;
677677
Elf_Shdr & shdr = findSection(sectionName);
678678
if (rdi(shdr.sh_type) != SHT_NOBITS)
679679
memset(contents + rdi(shdr.sh_offset), 'X', rdi(shdr.sh_size));
680680
}
681681

682682
std::set<unsigned int> noted_phdrs = {};
683683
for (auto & i : replacedSections) {
684-
std::string sectionName = i.first;
684+
const std::string & sectionName = i.first;
685685
auto & shdr = findSection(sectionName);
686686
Elf_Shdr orig_shdr = shdr;
687687
debug("rewriting section '%s' from offset 0x%x (size %d) to offset 0x%x (size %d)\n",
@@ -710,7 +710,7 @@ void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
710710

711711
/* If this is the .dynamic section, then the PT_DYNAMIC segment
712712
must be sync'ed with it. */
713-
if (sectionName == ".dynamic") {
713+
else if (sectionName == ".dynamic") {
714714
for (auto & phdr : phdrs) {
715715
if (rdi(phdr.p_type) == PT_DYNAMIC) {
716716
phdr.p_offset = shdr.sh_offset;
@@ -802,11 +802,11 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
802802

803803
/* Compute the total space needed for the replaced sections */
804804
off_t neededSpace = 0;
805-
for (auto & i : replacedSections)
806-
neededSpace += roundUp(i.second.size(), sectionAlignment);
805+
for (auto & s : replacedSections)
806+
neededSpace += roundUp(s.second.size(), sectionAlignment);
807807
debug("needed space is %d\n", neededSpace);
808808

809-
size_t startOffset = roundUp(fileContents->size(), getPageSize());
809+
Elf_Off startOffset = roundUp(fileContents->size(), getPageSize());
810810

811811
growFile(fileContents, startOffset + neededSpace);
812812

@@ -903,7 +903,7 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsExecutable()
903903
debug("replacing section '%s' which is in the way\n", sectionName.c_str());
904904
replaceSection(sectionName, rdi(shdr.sh_size));
905905
}
906-
prevSection = sectionName;
906+
prevSection = std::move(sectionName);
907907
}
908908

909909
debug("first reserved offset/addr is 0x%x/0x%llx\n",
@@ -1003,8 +1003,9 @@ void ElfFile<ElfFileParamNames>::normalizeNoteSegments()
10031003
size_t size = 0;
10041004
for (const auto & shdr : shdrs) {
10051005
if (rdi(shdr.sh_type) != SHT_NOTE) continue;
1006-
if (rdi(shdr.sh_offset) != curr_off) continue;
1006+
if (rdi(shdr.sh_offset) != roundUp(curr_off, rdi(shdr.sh_addralign))) continue;
10071007
size = rdi(shdr.sh_size);
1008+
curr_off = roundUp(curr_off, rdi(shdr.sh_addralign));
10081009
break;
10091010
}
10101011
if (size == 0)
@@ -1146,7 +1147,7 @@ void ElfFile<ElfFileParamNames>::rewriteHeaders(Elf_Addr phdrAddress)
11461147
fprintf(stderr, "warning: entry %d in symbol table refers to a non-existent section, skipping\n", shndx);
11471148
continue;
11481149
}
1149-
std::string section = sectionsByOldIndex.at(shndx);
1150+
const std::string & section = sectionsByOldIndex.at(shndx);
11501151
assert(!section.empty());
11511152
auto newIndex = findSection3(section); // inefficient
11521153
//debug("rewriting symbol %d: index = %d (%s) -> %d\n", entry, shndx, section.c_str(), newIndex);
@@ -1201,7 +1202,7 @@ void ElfFile<ElfFileParamNames>::modifySoname(sonameMode op, const std::string &
12011202

12021203
if (op == printSoname) {
12031204
if (soname) {
1204-
if (std::string(soname ? soname : "").empty())
1205+
if (strlen(soname) == 0)
12051206
debug("DT_SONAME is empty\n");
12061207
else
12071208
printf("%s\n", soname);
@@ -1211,7 +1212,7 @@ void ElfFile<ElfFileParamNames>::modifySoname(sonameMode op, const std::string &
12111212
return;
12121213
}
12131214

1214-
if (std::string(soname ? soname : "") == newSoname) {
1215+
if (soname && soname == newSoname) {
12151216
debug("current and proposed new SONAMEs are equal keeping DT_SONAME entry\n");
12161217
return;
12171218
}
@@ -1372,7 +1373,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
13721373
return;
13731374
}
13741375

1375-
auto dyn = (Elf_Dyn *)(contents + rdi(shdrDynamic.sh_offset));
1376+
dyn = (Elf_Dyn *)(contents + rdi(shdrDynamic.sh_offset));
13761377
Elf_Dyn * last = dyn;
13771378
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
13781379
if (rdi(dyn->d_tag) == DT_RPATH) {
@@ -1402,7 +1403,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
14021403
changed = true;
14031404
}
14041405

1405-
if (std::string(rpath ? rpath : "") == newRPath) {
1406+
if (rpath && rpath == newRPath) {
14061407
return;
14071408
}
14081409

@@ -1507,7 +1508,7 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(const std::map<std::string, std::
15071508
if (rdi(dyn->d_tag) == DT_NEEDED) {
15081509
char * name = strTab + rdi(dyn->d_un.d_val);
15091510
auto i = libs.find(name);
1510-
if (i != libs.end()) {
1511+
if (i != libs.end() && name != i->second) {
15111512
auto replacement = i->second;
15121513

15131514
debug("replacing DT_NEEDED entry '%s' with '%s'\n", name, replacement.c_str());
@@ -1559,7 +1560,7 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(const std::map<std::string, std::
15591560
while (verNeedNum > 0) {
15601561
char * file = verStrTab + rdi(need->vn_file);
15611562
auto i = libs.find(file);
1562-
if (i != libs.end()) {
1563+
if (i != libs.end() && file != i->second) {
15631564
auto replacement = i->second;
15641565

15651566
debug("replacing .gnu.version_r entry '%s' with '%s'\n", file, replacement.c_str());
@@ -1592,12 +1593,15 @@ void ElfFile<ElfFileParamNames>::addNeeded(const std::set<std::string> & libs)
15921593
auto shdrDynamic = findSection(".dynamic");
15931594
auto shdrDynStr = findSection(".dynstr");
15941595

1596+
unsigned int length = 0;
1597+
15951598
/* add all new libs to the dynstr string table */
1596-
unsigned int length = std::count_if(libs.begin(), libs.end(),
1597-
[](const std::string & lib) { return lib.size() + 1; });
1599+
for (auto &lib : libs)
1600+
length += lib.size() + 1;
15981601

15991602
std::string & newDynStr = replaceSection(".dynstr",
16001603
rdi(shdrDynStr.sh_size) + length + 1);
1604+
16011605
std::set<Elf64_Xword> libStrings;
16021606
unsigned int pos = 0;
16031607
for (auto & i : libs) {
@@ -1735,7 +1739,7 @@ static bool printNeeded = false;
17351739
static bool noDefaultLib = false;
17361740

17371741
template<class ElfFile>
1738-
static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, std::string fileName)
1742+
static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, const std::string & fileName)
17391743
{
17401744
if (printInterpreter)
17411745
printf("%s\n", elfFile.getInterpreter().c_str());
@@ -1786,7 +1790,7 @@ static void patchElf()
17861790
debug("patching ELF file '%s'\n", fileName.c_str());
17871791

17881792
auto fileContents = readFile(fileName);
1789-
std::string outputFileName2 = outputFileName.empty() ? fileName : outputFileName;
1793+
const std::string & outputFileName2 = outputFileName.empty() ? fileName : outputFileName;
17901794

17911795
if (getElfType(fileContents).is32Bit)
17921796
patchElf2(ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Versym>(fileContents), fileContents, outputFileName2);

tests/Makefile.am

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
LIBS =
22

3-
check_PROGRAMS = simple main main-scoped big-dynstr no-rpath
3+
check_PROGRAMS = simple main main-scoped big-dynstr no-rpath contiguous_note_sections
44

55
no_rpath_arch_TESTS = \
66
no-rpath-amd64.sh \
@@ -28,7 +28,8 @@ src_TESTS = \
2828
no-rpath-pie-powerpc.sh \
2929
build-id.sh \
3030
invalid-elf.sh \
31-
endianness.sh
31+
endianness.sh \
32+
contiguous_note_sections.sh
3233

3334
build_TESTS = \
3435
$(no_rpath_arch_TESTS)
@@ -107,3 +108,7 @@ libsimple_so_LDFLAGS = $(LDFLAGS_sharedlib)
107108
no_rpath_SOURCES = no-rpath.c
108109
# no -fpic for no-rpath.o
109110
no_rpath_CFLAGS =
111+
112+
contiguous_note_sections_SOURCES = contiguous_note_sections.s contiguous_note_sections.ld
113+
contiguous_note_sections_LDFLAGS = -nostdlib -T contiguous_note_sections.ld
114+
contiguous_note_sections_CFLAGS = -pie

tests/contiguous_note_sections.ld

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
PHDRS
2+
{
3+
headers PT_PHDR PHDRS ;
4+
notes PT_NOTE;
5+
text PT_LOAD FILEHDR PHDRS ;
6+
data PT_LOAD ;
7+
interp PT_INTERP ;
8+
dynamic PT_DYNAMIC ;
9+
}
10+
11+
SECTIONS
12+
{
13+
. = SIZEOF_HEADERS;
14+
. = ALIGN(4);
15+
16+
.note.my-section0 : { *(.note.my-section0) } :notes :text
17+
.note.my-section1 : { *(.note.my-section1) } :notes :text
18+
19+
.interp : { *(.interp) } :text :interp
20+
.text : { *(.text) } :text
21+
.rodata : { *(.rodata) } /* defaults to :text */
22+
23+
.data : { *(.data) } :data
24+
}

tests/contiguous_note_sections.s

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Testcase for error:
3+
* patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
4+
*/
5+
.section ".note.my-section0", "a", @note
6+
.align 4
7+
.long 1f - 0f /* name length (not including padding) */
8+
.long 3f - 2f /* desc length (not including padding) */
9+
.long 1 /* type = NT_VERSION */
10+
0: .asciz "my-version-12345" /* name */
11+
1: .align 4
12+
2: .long 1 /* desc - toolchain version number, 32-bit LE */
13+
3: .align 4
14+
15+
.section ".note.my-section1", "a", @note
16+
.align 8
17+
.long 1f - 0f /* name length (not including padding) */
18+
.long 3f - 2f /* desc length (not including padding) */
19+
.long 1 /* type = NT_VERSION */
20+
0: .asciz "my-version-1" /* name */
21+
1: .align 4
22+
2: .long 1 /* desc - toolchain version number, 32-bit LE */
23+
3: .align 4

tests/contiguous_note_sections.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#! /bin/sh -e
2+
3+
# Running --set-interpreter on this binary should not produce the following
4+
# error:
5+
# patchelf: cannot normalize PT_NOTE segment: non-contiguous SHT_NOTE sections
6+
../src/patchelf --set-interpreter ld-linux-x86-64.so.2 contiguous_note_sections

tests/plain-needed.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11
#! /bin/sh
22
set -e
3+
4+
SCRATCH=scratch/$(basename $0 .sh)
5+
MAIN_ELF="${SCRATCH}/main"
6+
7+
PATCHELF="../src/patchelf"
8+
9+
rm -rf ${SCRATCH}
10+
mkdir -p ${SCRATCH}
11+
cp main ${SCRATCH}/
12+
313
echo "Confirming main requires libfoo"
4-
../src/patchelf --print-needed main | grep -q libfoo.so
14+
${PATCHELF} --print-needed "${MAIN_ELF}" | grep -q libfoo.so
15+
16+
echo "Testing --add-needed functionality"
17+
${PATCHELF} --add-needed bar.so "${MAIN_ELF}"
18+
${PATCHELF} --print-needed "${MAIN_ELF}" | grep -q bar.so
19+
20+
echo "Testing --remove-needed functionality"
21+
${PATCHELF} --remove-needed bar.so "${MAIN_ELF}"
22+
if ${PATCHELF} --print-needed "${MAIN_ELF}" | grep -q bar.so; then
23+
echo "ERROR: --remove-needed did not eliminate bar.so!"
24+
exit 1
25+
fi

0 commit comments

Comments
 (0)