[mach-o] Add support for -exported_symbols_list and -keep_private_externs
Both options control the final scope of atoms.
When -exported_symbols_list <file> is used, the file is parsed into one
symbol per line in the file. Only those symbols will be exported (global)
in the final linked image.
The -keep_private_externs option is only used with -r mode. Normally, -r
mode reduces private extern (scopeLinkageUnit) symbols to non-external. But
add the -keep_private_externs option keeps them private external.
llvm-svn: 216146
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index efb9d9c..1df6e55 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -106,7 +106,7 @@
void copySectionInfo(NormalizedFile &file);
void updateSectionInfo(NormalizedFile &file);
void buildAtomToAddressMap();
- void addSymbols(const lld::File &atomFile, NormalizedFile &file);
+ std::error_code addSymbols(const lld::File &atomFile, NormalizedFile &file);
void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
void addSectionRelocs(const lld::File &, NormalizedFile &file);
@@ -130,20 +130,21 @@
void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
void copySectionContent(SectionInfo *si, ContentBytes &content);
- uint8_t scopeBits(const DefinedAtom* atom);
uint16_t descBits(const DefinedAtom* atom);
int dylibOrdinal(const SharedLibraryAtom *sa);
void segIndexForSection(const SectionInfo *sect,
uint8_t &segmentIndex, uint64_t &segmentStartAddr);
const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
const Atom *targetOfStub(const DefinedAtom *stubAtom);
- bool belongsInGlobalSymbolsSection(const DefinedAtom* atom);
+ std::error_code getSymbolTableRegion(const DefinedAtom* atom,
+ bool &inGlobalsRegion,
+ SymbolScope &symbolScope);
void appendSection(SectionInfo *si, NormalizedFile &file);
uint32_t sectionIndexForAtom(const Atom *atom);
static uint64_t alignTo(uint64_t value, uint8_t align2);
typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
- struct AtomAndIndex { const Atom *atom; uint32_t index; };
+ struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
struct AtomSorter {
bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
};
@@ -635,18 +636,6 @@
}
}
-uint8_t Util::scopeBits(const DefinedAtom* atom) {
- switch (atom->scope()) {
- case Atom::scopeTranslationUnit:
- return 0;
- case Atom::scopeLinkageUnit:
- return N_PEXT | N_EXT;
- case Atom::scopeGlobal:
- return N_EXT;
- }
- llvm_unreachable("Unknown scope");
-}
-
uint16_t Util::descBits(const DefinedAtom* atom) {
uint16_t desc = 0;
switch (atom->merge()) {
@@ -677,16 +666,55 @@
}
-bool Util::belongsInGlobalSymbolsSection(const DefinedAtom* atom) {
- // ScopeLinkageUnit symbols are in globals area of symbol table
- // in object files, but in locals area for final linked images.
- if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
- return (atom->scope() != Atom::scopeTranslationUnit);
- else
- return (atom->scope() == Atom::scopeGlobal);
+std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
+ bool &inGlobalsRegion,
+ SymbolScope &scope) {
+ bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+ switch (atom->scope()) {
+ case Atom::scopeTranslationUnit:
+ scope = 0;
+ inGlobalsRegion = false;
+ return std::error_code();
+ case Atom::scopeLinkageUnit:
+ if ((_context.exportMode() == MachOLinkingContext::ExportMode::whiteList)
+ && _context.exportSymbolNamed(atom->name())) {
+ return make_dynamic_error_code(Twine("cannot export hidden symbol ")
+ + atom->name());
+ }
+ if (rMode) {
+ if (_context.keepPrivateExterns()) {
+ // -keep_private_externs means keep in globals region as N_PEXT.
+ scope = N_PEXT | N_EXT;
+ inGlobalsRegion = true;
+ return std::error_code();
+ }
+ }
+ // scopeLinkageUnit symbols are no longer global once linked.
+ scope = N_PEXT;
+ inGlobalsRegion = false;
+ return std::error_code();
+ case Atom::scopeGlobal:
+ if (_context.exportRestrictMode()) {
+ if (_context.exportSymbolNamed(atom->name())) {
+ scope = N_EXT;
+ inGlobalsRegion = true;
+ return std::error_code();
+ } else {
+ scope = N_PEXT;
+ inGlobalsRegion = false;
+ return std::error_code();
+ }
+ } else {
+ scope = N_EXT;
+ inGlobalsRegion = true;
+ return std::error_code();
+ }
+ break;
+ }
}
-void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
+std::error_code Util::addSymbols(const lld::File &atomFile,
+ NormalizedFile &file) {
bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
// Mach-O symbol table has three regions: locals, globals, undefs.
@@ -697,14 +725,19 @@
for (const AtomInfo &info : sect->atomsAndOffsets) {
const DefinedAtom *atom = info.atom;
if (!atom->name().empty()) {
- if (belongsInGlobalSymbolsSection(atom)) {
- AtomAndIndex ai = { atom, sect->finalSectionIndex };
+ SymbolScope symbolScope;
+ bool inGlobalsRegion;
+ if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
+ return ec;
+ }
+ if (inGlobalsRegion) {
+ AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
globals.push_back(ai);
} else {
Symbol sym;
sym.name = atom->name();
sym.type = N_SECT;
- sym.scope = scopeBits(atom);
+ sym.scope = symbolScope;
sym.sect = sect->finalSectionIndex;
sym.desc = descBits(atom);
sym.value = _atomToAddress[atom];
@@ -737,7 +770,7 @@
Symbol sym;
sym.name = ai.atom->name();
sym.type = N_SECT;
- sym.scope = scopeBits(static_cast<const DefinedAtom*>(ai.atom));
+ sym.scope = ai.scope;
sym.sect = ai.index;
sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom));
sym.value = _atomToAddress[ai.atom];
@@ -750,11 +783,11 @@
std::vector<AtomAndIndex> undefs;
undefs.reserve(128);
for (const UndefinedAtom *atom : atomFile.undefined()) {
- AtomAndIndex ai = { atom, 0 };
+ AtomAndIndex ai = { atom, 0, N_EXT };
undefs.push_back(ai);
}
for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
- AtomAndIndex ai = { atom, 0 };
+ AtomAndIndex ai = { atom, 0, N_EXT };
undefs.push_back(ai);
}
std::sort(undefs.begin(), undefs.end(), AtomSorter());
@@ -768,13 +801,15 @@
}
sym.name = ai.atom->name();
sym.type = N_UNDF;
- sym.scope = N_EXT;
+ sym.scope = ai.scope;
sym.sect = 0;
sym.desc = desc;
sym.value = 0;
_atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
file.undefinedSymbols.push_back(sym);
}
+
+ return std::error_code();
}
const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
@@ -1083,7 +1118,9 @@
util.buildAtomToAddressMap();
util.updateSectionInfo(normFile);
util.copySectionContent(normFile);
- util.addSymbols(atomFile, normFile);
+ if (auto ec = util.addSymbols(atomFile, normFile)) {
+ return ec;
+ }
util.addIndirectSymbols(atomFile, normFile);
util.addRebaseAndBindingInfo(atomFile, normFile);
util.addSectionRelocs(atomFile, normFile);