[lld][MachO] Recognize __thread_bss sections as zero-fill and set all the

appropriate bits.

This fixes the remaining clang regression test failures when linking clang with
lld on Darwin.

llvm-svn: 255390
This commit is contained in:
Lang Hames 2015-12-11 23:25:09 +00:00
parent 10cf124bb9
commit ac2adce66b
8 changed files with 55 additions and 19 deletions

View File

@ -25,11 +25,11 @@ public:
// Constructor for zero-fill content
MachODefinedAtom(const File &f, const StringRef name, Scope scope,
uint64_t size, bool noDeadStrip, Alignment align)
ContentType type, uint64_t size, bool noDeadStrip,
Alignment align)
: SimpleDefinedAtom(f), _name(name),
_content(ArrayRef<uint8_t>(nullptr, size)), _align(align),
_contentType(DefinedAtom::typeZeroFill),
_scope(scope), _merge(mergeNo), _thumb(false),
_contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
_noDeadStrip(noDeadStrip) {}
uint64_t size() const override { return _content.size(); }

View File

@ -87,9 +87,22 @@ public:
DefinedAtom::Alignment align(
inSection->alignment,
sectionOffset % inSection->alignment);
DefinedAtom::ContentType type = DefinedAtom::typeUnknown;
switch (inSection->type) {
case llvm::MachO::S_ZEROFILL:
type = DefinedAtom::typeZeroFill;
break;
case llvm::MachO::S_THREAD_LOCAL_ZEROFILL:
type = DefinedAtom::typeTLVInitialZeroFill;
break;
default:
llvm_unreachable("Unrecognized zero-fill section");
}
auto *atom =
new (allocator()) MachODefinedAtom(*this, name, scope, size, noDeadStrip,
align);
new (allocator()) MachODefinedAtom(*this, name, scope, type, size,
noDeadStrip, align);
addAtomForSection(inSection, atom, sectionOffset);
}

View File

@ -142,6 +142,14 @@ struct Symbol {
Hex64 value;
};
/// Check whether the given section type indicates a zero-filled section.
// FIXME: Utility functions of this kind should probably be moved into
// llvm/Support.
inline bool isZeroFillSection(SectionType T) {
return (T == llvm::MachO::S_ZEROFILL ||
T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
}
/// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)

View File

@ -289,12 +289,12 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
unsigned relocCount = 0;
uint64_t offset = _startOfSectionsContent;
for (const Section &sect : file.sections) {
if (sect.type != llvm::MachO::S_ZEROFILL) {
if (isZeroFillSection(sect.type))
_sectInfo[&sect].fileOffset = 0;
else {
offset = llvm::RoundUpToAlignment(offset, sect.alignment);
_sectInfo[&sect].fileOffset = offset;
offset += sect.content.size();
} else {
_sectInfo[&sect].fileOffset = 0;
}
relocCount += sect.relocations.size();
}
@ -530,7 +530,7 @@ void MachOFileLayout::buildFileOffsets() {
for (const Section *s : _segInfo[&sg].sections) {
uint32_t sectOffset = s->address - sg.address;
uint32_t sectFileSize =
s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
isZeroFillSection(s->type) ? 0 : s->content.size();
segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
_sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
@ -655,7 +655,7 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
setString16(section->segmentName, sect->segname);
sect->addr = section->address;
sect->size = section->content.size();
if (section->type == llvm::MachO::S_ZEROFILL)
if (isZeroFillSection(section->type))
sect->offset = 0;
else
sect->offset = section->address - seg.address + segInfo.fileOffset;
@ -883,7 +883,7 @@ std::error_code MachOFileLayout::writeLoadCommands() {
void MachOFileLayout::writeSectionContent() {
for (const Section &s : _file.sections) {
// Copy all section content to output buffer.
if (s.type == llvm::MachO::S_ZEROFILL)
if (isZeroFillSection(s.type))
continue;
if (s.content.empty())
continue;

View File

@ -253,6 +253,8 @@ const MachOFinalSectionFromAtomType sectsToAtomType[] = {
typeTLVInitialData),
ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS,
typeTLVInitializerPtr),
ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
typeTLVInitialZeroFill),
ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill),
ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples),
};
@ -582,7 +584,7 @@ void Util::copySectionContent(NormalizedFile &file) {
for (SectionInfo *si : _sectionInfos) {
Section *normSect = &file.sections[si->normalizedSectionIndex];
if (si->type == llvm::MachO::S_ZEROFILL) {
if (isZeroFillSection(si->type)) {
const uint8_t *empty = nullptr;
normSect->content = llvm::makeArrayRef(empty, si->size);
continue;

View File

@ -82,6 +82,8 @@ const MachORelocatableSectionToAtomType sectsToAtomType[] = {
ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
typeThunkTLV),
ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
typeTLVInitialZeroFill),
ENTRY("", "", S_INTERPOSING, typeInterposingTuples),
ENTRY("__LD", "__compact_unwind", S_REGULAR,
typeCompactUnwindInfo),
@ -232,7 +234,7 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
uint64_t size = nextSymbolAddr - symbolAddr;
uint64_t offset = symbolAddr - section.address;
bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
if (section.type == llvm::MachO::S_ZEROFILL) {
if (isZeroFillSection(section.type)) {
file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
noDeadStrip, copyRefs, &section);
} else {

View File

@ -278,7 +278,7 @@ struct MappingTraits<Section> {
io.mapOptional("attributes", sect.attributes);
io.mapOptional("alignment", sect.alignment, (uint16_t)1);
io.mapRequired("address", sect.address);
if (sect.type == llvm::MachO::S_ZEROFILL) {
if (isZeroFillSection(sect.type)) {
// S_ZEROFILL sections use "size:" instead of "content:"
uint64_t size = sect.content.size();
io.mapOptional("size", size);

View File

@ -1,6 +1,7 @@
# RUN: lld -flavor darwin -macosx_version_min 10.7 -arch x86_64 -print_atoms %s -o %t | FileCheck %s
# RUN: not lld -flavor darwin -macosx_version_min 10.6 -arch x86_64 -o %t %s 2> %t2
# RUN: FileCheck < %t2 %s --check-prefix=CHECK-ERROR
# RUN: llvm-objdump -macho -private-headers %t | FileCheck %s --check-prefix=CHECK-LOADCMDS
#
# Test parsing of x86_64 tlv relocations.
@ -30,12 +31,12 @@ sections:
extern: true
symbol: 2
- segment: __DATA
section: __thread_data
type: S_THREAD_LOCAL_REGULAR
section: __thread_bss
type: S_THREAD_LOCAL_ZEROFILL
attributes: [ ]
alignment: 4
address: 0x0000000000000014
content: [ 0x07, 0x00, 0x00, 0x00 ]
size: 4
- segment: __DATA
section: __thread_vars
type: S_THREAD_LOCAL_VARIABLES
@ -111,8 +112,8 @@ page-size: 0x00000000
# CHECK-NEXT: - kind: tlvInitSectionOffset
# CHECK-NEXT: offset: 16
# CHECK-NEXT: target: '_x$tlv$init'
# CHECK-NEXT: - name: '_x$tlv$init'
# CHECK-NEXT: type: tlv-data
# CHECK: - name: '_x$tlv$init'
# CHECK-NEXT: type: tlv-zero-fill
# CHECK: - name: _main
# CHECK-NOT: - name:
# CHECK: references:
@ -131,3 +132,13 @@ page-size: 0x00000000
# CHECK-NEXT: target: _x
# CHECK-ERROR: targeted OS version does not support use of thread local variables in _main for architecture x86_64
# CHECK-LOADCMDS: sectname __thread_bss
# CHECK-LOADCMDS: segname __DATA
# CHECK-LOADCMDS: addr 0x{{[0-9A-F]*}}
# CHECK-LOADCMDS: size 0x0000000000000004
# CHECK-LOADCMDS: offset 0
# CHECK-LOADCMDS: align 2^2 (4)
# CHECK-LOADCMDS: reloff 0
# CHECK-LOADCMDS: nreloc 0
# CHECK-LOADCMDS: type S_THREAD_LOCAL_ZEROFILL