forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2993850237
commit
f147f59cd3
|
@ -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: ''
|
||||
...
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue