aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/ELF/Object.cpp
diff options
context:
space:
mode:
authorJames Henderson <jh7370@my.bristol.ac.uk>2019-03-25 16:36:26 +0000
committerJames Henderson <jh7370@my.bristol.ac.uk>2019-03-25 16:36:26 +0000
commit1f44814952b421ad34411ba15fad3a416e698b6e (patch)
treed30f62cc9d7c951b8c9e13af18e0300d10e567ab /llvm/tools/llvm-objcopy/ELF/Object.cpp
parent36db4898740f21ddb9761815729266c2f5f3672b (diff)
downloadllvm-1f44814952b421ad34411ba15fad3a416e698b6e.zip
llvm-1f44814952b421ad34411ba15fad3a416e698b6e.tar.gz
llvm-1f44814952b421ad34411ba15fad3a416e698b6e.tar.bz2
[llvm-objcopy]Preserve data in segments not covered by sections
llvm-objcopy previously knew nothing about data in segments that wasn't covered by section headers, meaning that it wrote zeroes instead of what was there. As it is possible for this data to be useful to the loader, this patch causes llvm-objcopy to start preserving this data. Data in sections that are explicitly removed continues to be written as zeroes. This fixes https://bugs.llvm.org/show_bug.cgi?id=41005. Reviewed by: jakehehrlich, rupprecht Differential Revision: https://reviews.llvm.org/D59483 llvm-svn: 356919
Diffstat (limited to 'llvm/tools/llvm-objcopy/ELF/Object.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/ELF/Object.cpp38
1 files changed, 35 insertions, 3 deletions
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 4639d905..7cceb70 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -906,7 +906,9 @@ template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
template <class ELFT> void ELFBuilder<ELFT>::readProgramHeaders() {
uint32_t Index = 0;
for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
- Segment &Seg = Obj.addSegment();
+ ArrayRef<uint8_t> Data{ElfFile.base() + Phdr.p_offset,
+ (size_t)Phdr.p_filesz};
+ Segment &Seg = Obj.addSegment(Data);
Seg.Type = Phdr.p_type;
Seg.Flags = Phdr.p_flags;
Seg.OriginalOffset = Phdr.p_offset;
@@ -1350,7 +1352,31 @@ template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
template <class ELFT> void ELFWriter<ELFT>::writeSectionData() {
for (auto &Sec : Obj.sections())
- Sec.accept(*SecWriter);
+ // Segments are responsible for writing their contents, so only write the
+ // section data if the section is not in a segment. Note that this renders
+ // sections in segments effectively immutable.
+ if (Sec.ParentSegment == nullptr)
+ Sec.accept(*SecWriter);
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
+ for (Segment &Seg : Obj.segments()) {
+ uint8_t *B = Buf.getBufferStart() + Seg.Offset;
+ assert(Seg.FileSize == Seg.getContents().size() &&
+ "Segment size must match contents size");
+ std::memcpy(B, Seg.getContents().data(), Seg.FileSize);
+ }
+
+ // Iterate over removed sections and overwrite their old data with zeroes.
+ for (auto &Sec : Obj.removedSections()) {
+ Segment *Parent = Sec.ParentSegment;
+ if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
+ continue;
+ uint64_t Offset =
+ Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
+ uint8_t *B = Buf.getBufferStart();
+ std::memset(B + Offset, 0, Sec.Size);
+ }
}
Error Object::removeSections(
@@ -1396,7 +1422,10 @@ Error Object::removeSections(
return E;
}
- // Now finally get rid of them all togethor.
+ // Transfer removed sections into the Object RemovedSections container for use
+ // later.
+ std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
+ // Now finally get rid of them all together.
Sections.erase(Iter, std::end(Sections));
return Error::success();
}
@@ -1542,6 +1571,9 @@ template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
}
template <class ELFT> Error ELFWriter<ELFT>::write() {
+ // Segment data must be written first, so that the ELF header and program
+ // header tables can overwrite it, if covered by a segment.
+ writeSegmentData();
writeEhdr();
writePhdrs();
writeSectionData();