[llvm] f147f59 - [llvm-objcopy][MachO] Skip sections with zero offset
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 6 13:29:57 PST 2020
Author: Alexander Shaposhnikov
Date: 2020-11-06T13:29:43-08:00
New Revision: f147f59cd377a6be68e5ca5c343eb11df8e7ee6f
URL: https://github.com/llvm/llvm-project/commit/f147f59cd377a6be68e5ca5c343eb11df8e7ee6f
DIFF: https://github.com/llvm/llvm-project/commit/f147f59cd377a6be68e5ca5c343eb11df8e7ee6f.diff
LOG: [llvm-objcopy][MachO] Skip sections with zero offset
Some binaries can contain regular sections with zero offset and zero size.
This diff makes llvm-objcopy's handling of such sections consistent with
cctools's strip (which doesn't modify them),
previously the tool would allocate file space for them.
Test plan: make check-all
Differential revision: https://reviews.llvm.org/D90796
Added:
llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test
Modified:
llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
llvm/tools/llvm-objcopy/MachO/Object.h
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test b/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test
new file mode 100644
index 000000000000..3d14c34ec741
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test
@@ -0,0 +1,43 @@
+## This test verifies that a regular (non-zero-fill) section with zero offset
+## and zero size is not modifed, this behavior is consistent with cctools' strip.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy %t %t.copy
+# RUN: cmp %t %t.copy
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: 0x00000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000001
+ ncmds: 1
+ sizeofcmds: 124
+ flags: 0x00002000
+LoadCommands:
+ - cmd: LC_SEGMENT
+ cmdsize: 124
+ segname: __DATA
+ vmaddr: 4096
+ vmsize: 0
+ fileoff: 152
+ filesize: 0
+ maxprot: 7
+ initprot: 7
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __broken
+ segname: __DATA
+ addr: 0x0000000000001000
+ size: 0
+ offset: 0x00000000
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ content: ''
+...
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
index 947636ac985b..ea01e8519a5c 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
@@ -148,7 +148,7 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
"Section's address cannot be smaller than Segment's one");
uint32_t SectOffset = Sec->Addr - SegmentVmAddr;
if (IsObjectFile) {
- if (Sec->isVirtualSection()) {
+ if (!Sec->hasValidOffset()) {
Sec->Offset = 0;
} else {
uint64_t PaddingSize =
@@ -158,7 +158,7 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
SegFileSize += PaddingSize + Sec->Size;
}
} else {
- if (Sec->isVirtualSection()) {
+ if (!Sec->hasValidOffset()) {
Sec->Offset = 0;
} else {
Sec->Offset = SegOffset + SectOffset;
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
index 6e6975c35139..548a85bd497e 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
@@ -35,7 +35,7 @@ Section constructSectionCommon(SectionType Sec, uint32_t Index) {
S.Index = Index;
S.Addr = Sec.addr;
S.Size = Sec.size;
- S.Offset = Sec.offset;
+ S.OriginalOffset = Sec.offset;
S.Align = Sec.align;
S.RelOff = Sec.reloff;
S.NReloc = Sec.nreloc;
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
index 78e03c818fd0..56dd08df3b09 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
@@ -121,8 +121,10 @@ size_t MachOWriter::totalSize() const {
// Otherwise, use the last section / reloction.
for (const LoadCommand &LC : O.LoadCommands)
for (const std::unique_ptr<Section> &S : LC.Sections) {
- if (S->isVirtualSection()) {
- assert((S->Offset == 0) && "Zero-fill section's offset must be zero");
+ if (!S->hasValidOffset()) {
+ assert((S->Offset == 0) && "Skipped section's offset must be zero");
+ assert((S->isVirtualSection() || S->Size == 0) &&
+ "Non-zero-fill sections with zero offset must have zero size");
continue;
}
assert((S->Offset != 0) &&
@@ -246,8 +248,12 @@ void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) {
void MachOWriter::writeSections() {
for (const LoadCommand &LC : O.LoadCommands)
for (const std::unique_ptr<Section> &Sec : LC.Sections) {
- if (Sec->isVirtualSection())
+ if (!Sec->hasValidOffset()) {
+ assert((Sec->Offset == 0) && "Skipped section's offset must be zero");
+ assert((Sec->isVirtualSection() || Sec->Size == 0) &&
+ "Non-zero-fill sections with zero offset must have zero size");
continue;
+ }
assert(Sec->Offset && "Section offset can not be zero");
assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");
diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h
index 0a930ba19f8e..a743e125c0cd 100644
--- a/llvm/tools/llvm-objcopy/MachO/Object.h
+++ b/llvm/tools/llvm-objcopy/MachO/Object.h
@@ -44,6 +44,8 @@ struct Section {
std::string CanonicalName;
uint64_t Addr = 0;
uint64_t Size = 0;
+ // Offset in the input file.
+ Optional<uint32_t> OriginalOffset;
uint32_t Offset = 0;
uint32_t Align = 0;
uint32_t RelOff = 0;
@@ -73,6 +75,10 @@ struct Section {
getType() == MachO::S_GB_ZEROFILL ||
getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
}
+
+ bool hasValidOffset() const {
+ return !(isVirtualSection() || (OriginalOffset && *OriginalOffset == 0));
+ }
};
struct LoadCommand {
More information about the llvm-commits
mailing list