--- /dev/null
+## 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: ''
+...
"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 =
SegFileSize += PaddingSize + Sec->Size;
}
} else {
- if (Sec->isVirtualSection()) {
+ if (!Sec->hasValidOffset()) {
Sec->Offset = 0;
} else {
Sec->Offset = SegOffset + SectOffset;
// 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) &&
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");
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;
getType() == MachO::S_GB_ZEROFILL ||
getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
}
+
+ bool hasValidOffset() const {
+ return !(isVirtualSection() || (OriginalOffset && *OriginalOffset == 0));
+ }
};
struct LoadCommand {