void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion,
MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
uint16_t symbolDescFlags, Atom::Scope symbolScope,
- uint64_t nextSymbolAddr, bool copyRefs) {
+ uint64_t nextSymbolAddr, bool scatterable, bool copyRefs) {
// Mach-O symbol table does have size in it. Instead the size is the
// difference between this and the next symbol.
uint64_t size = nextSymbolAddr - symbolAddr;
uint64_t offset = symbolAddr - section.address;
- bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP);
+ bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
if (section.type == llvm::MachO::S_ZEROFILL) {
file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
noDeadStrip, copyRefs, §ion);
std::error_code processSymboledSection(DefinedAtom::ContentType atomType,
const Section §ion,
const NormalizedFile &normalizedFile,
- MachOFile &file, bool copyRefs) {
+ MachOFile &file, bool scatterable,
+ bool copyRefs) {
// Find section's index.
uint32_t sectIndex = 1;
for (auto § : normalizedFile.sections) {
// Section has no symbols, put all content in one anoymous atom.
atomFromSymbol(atomType, section, file, section.address, StringRef(),
0, Atom::scopeTranslationUnit,
- section.address + section.content.size(), copyRefs);
+ section.address + section.content.size(),
+ scatterable, copyRefs);
}
else if (symbols.front()->value != section.address) {
// Section has anonymous content before first symbol.
atomFromSymbol(atomType, section, file, section.address, StringRef(),
0, Atom::scopeTranslationUnit, symbols.front()->value,
- copyRefs);
+ scatterable, copyRefs);
}
const Symbol *lastSym = nullptr;
|| !lastSym->name.startswith("ltmp")) {
atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
lastSym->desc, atomScope(lastSym->scope), sym->value,
- copyRefs);
+ scatterable, copyRefs);
}
}
lastSym = sym;
if (lastSym != nullptr) {
atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
lastSym->desc, atomScope(lastSym->scope),
- section.address + section.content.size(), copyRefs);
+ section.address + section.content.size(),
+ scatterable, copyRefs);
}
+
+ // If object built without .subsections_via_symbols, add reference chain.
+ if (!scatterable) {
+ MachODefinedAtom *prevAtom = nullptr;
+ file.eachAtomInSection(section,
+ [&](MachODefinedAtom *atom, uint64_t offset)->void {
+ if (prevAtom)
+ prevAtom->addReference(0, Reference::kindLayoutAfter, atom, 0,
+ Reference::KindArch::all,
+ Reference::KindNamespace::all);
+ prevAtom = atom;
+ });
+ }
+
return std::error_code();
}
const Section §ion,
bool customSectionName,
const NormalizedFile &normalizedFile,
- MachOFile &file, bool copyRefs) {
+ MachOFile &file, bool scatterable,
+ bool copyRefs) {
const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
const bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch);
if (atomizeModel == atomizeAtSymbols) {
// Break section up into atoms each with a fixed size.
return processSymboledSection(atomType, section, normalizedFile, file,
- copyRefs);
+ scatterable, copyRefs);
} else {
const uint32_t *cfi;
unsigned int size;
// creates corresponding lld::Reference objects.
std::error_code convertRelocs(const Section §ion,
const NormalizedFile &normalizedFile,
+ bool scatterable,
MachOFile &file,
ArchHandler &handler) {
// Utility function for ArchHandler to find atom by its address.
if (handler.isPairedReloc(reloc)) {
// Handle paired relocations together.
relocErr = handler.getPairReferenceInfo(reloc, *++it, inAtom,
- offsetInAtom, fixupAddress, swap,
- atomByAddr, atomBySymbol, &kind,
- &target, &addend);
+ offsetInAtom, fixupAddress, swap,
+ scatterable, atomByAddr,
+ atomBySymbol, &kind,
+ &target, &addend);
}
else {
// Use ArchHandler to convert relocation record into information
normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
std::unique_ptr<MachOFile> file(new MachOFile(path));
+ bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
+
// Create atoms from each section.
for (auto § : normalizedFile.sections) {
if (isDebugInfoSection(sect))
customSectionName);
if (std::error_code ec =
processSection(atomType, sect, customSectionName, normalizedFile,
- *file, copyRefs))
+ *file, scatterable, copyRefs))
return ec;
}
// Create atoms from undefined symbols.
for (auto § : normalizedFile.sections) {
if (isDebugInfoSection(sect))
continue;
- if (std::error_code ec = convertRelocs(sect, normalizedFile, *file, *handler))
+ if (std::error_code ec = convertRelocs(sect, normalizedFile, scatterable,
+ *file, *handler))
return ec;
}
--- /dev/null
+# RUN: lld -flavor darwin -arch armv7 %s -r -print_atoms -o %t | FileCheck %s
+#
+# Test that assembly written without .subsections_via_symbols is parsed so
+# that atoms are non-dead-strip and there is a layout-after references
+# chaining atoms together.
+#
+
+--- !mach-o
+arch: armv7
+file-type: MH_OBJECT
+flags: [ ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 2
+ address: 0x0000000000000000
+ content: [ 0x04, 0x10, 0x9F, 0xE5, 0x04, 0x20, 0x9F, 0xE5,
+ 0x1E, 0xFF, 0x2F, 0xE1, 0x78, 0x56, 0x34, 0x12,
+ 0x21, 0x43, 0x65, 0x87 ]
+local-symbols:
+ - name: constants1
+ type: N_SECT
+ sect: 1
+ value: 0x000000000000000C
+ - name: constants2
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000010
+global-symbols:
+ - name: _foo
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+...
+
+
+# CHECK:defined-atoms:
+# CHECK: - name: _foo
+# CHECK: scope: global
+# CHECK: content: [ 04, 10, 9F, E5, 04, 20, 9F, E5, 1E, FF, 2F, E1 ]
+# CHECK: dead-strip: never
+# CHECK: references:
+# CHECK: - kind: layout-after
+# CHECK: offset: 0
+# CHECK: target: constants1
+# CHECK: - name: constants1
+# CHECK: content: [ 78, 56, 34, 12 ]
+# CHECK: dead-strip: never
+# CHECK: references:
+# CHECK: - kind: layout-after
+# CHECK: offset: 0
+# CHECK: target: constants2
+# CHECK: - name: constants2
+# CHECK: content: [ 21, 43, 65, 87 ]
+# CHECK: dead-strip: never