aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/ELF/Object.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2021-05-05 10:26:57 -0700
committerFangrui Song <i@maskray.me>2021-05-05 10:26:57 -0700
commitb3336bfa2e6a38f16c4ecf4d77bd0f97ec5a46eb (patch)
tree76189759352b4c638793e3d859569be328570dd8 /llvm/tools/llvm-objcopy/ELF/Object.cpp
parentba5c122647c79586a6d060ca649e586feb7f57a0 (diff)
downloadllvm-b3336bfa2e6a38f16c4ecf4d77bd0f97ec5a46eb.zip
llvm-b3336bfa2e6a38f16c4ecf4d77bd0f97ec5a46eb.tar.gz
llvm-b3336bfa2e6a38f16c4ecf4d77bd0f97ec5a46eb.tar.bz2
[llvm-objcopy][ELF] --only-keep-debug: set offset/size of segments with no sections to zero
PR50160: we currently ignore non-PT_PHDR segments with no sections, not accounting for its p_offset and p_filesz: this can cause an out-of-bounds write in `writeSegmentData` if the p_offset+p_filesz is larger than the total file size. This can be fixed by setting p_offset=p_filesz=0. The logic nicely unifies with the logic added in D90897. Reviewed By: jhenderson, rupprecht Differential Revision: https://reviews.llvm.org/D101560
Diffstat (limited to 'llvm/tools/llvm-objcopy/ELF/Object.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/ELF/Object.cpp21
1 files changed, 11 insertions, 10 deletions
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index a8bd135..0ac8b3a 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -2315,18 +2315,19 @@ static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
uint64_t HdrEnd) {
uint64_t MaxOffset = 0;
for (Segment *Seg : Segments) {
- // An empty segment contains no section (see sectionWithinSegment). If it
- // has a parent segment, copy the parent segment's offset field. This works
- // for empty PT_TLS. We don't handle empty segments without a parent for
- // now.
- if (Seg->ParentSegment != nullptr && Seg->MemSize == 0)
- Seg->Offset = Seg->ParentSegment->Offset;
-
- const SectionBase *FirstSec = Seg->firstSection();
- if (Seg->Type == PT_PHDR || !FirstSec)
+ if (Seg->Type == PT_PHDR)
continue;
- uint64_t Offset = FirstSec->Offset;
+ // The segment offset is generally the offset of the first section.
+ //
+ // For a segment containing no section (see sectionWithinSegment), if it has
+ // a parent segment, copy the parent segment's offset field. This works for
+ // empty PT_TLS. If no parent segment, use 0: the segment is not useful for
+ // debugging anyway.
+ const SectionBase *FirstSec = Seg->firstSection();
+ uint64_t Offset =
+ FirstSec ? FirstSec->Offset
+ : (Seg->ParentSegment ? Seg->ParentSegment->Offset : 0);
uint64_t FileSize = 0;
for (const SectionBase *Sec : Seg->Sections) {
uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;