forked from OSchip/llvm-project
[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
This commit is contained in:
parent
334e4ffc0d
commit
8c0bf75ef5
|
@ -15,6 +15,7 @@
|
|||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
|
||||
|
@ -25,7 +26,7 @@ using llvm::MachO::HeaderFileType;
|
|||
namespace lld {
|
||||
|
||||
namespace mach_o {
|
||||
class ArchHandler;
|
||||
class ArchHandler;
|
||||
class MachODylibFile;
|
||||
}
|
||||
|
||||
|
@ -51,6 +52,12 @@ public:
|
|||
iOS_simulator
|
||||
};
|
||||
|
||||
enum class ExportMode {
|
||||
globals, // Default, all global symbols exported.
|
||||
whiteList, // -exported_symbol[s_list], only listed symbols exported.
|
||||
blackList // -unexported_symbol[s_list], no listed symbol exported.
|
||||
};
|
||||
|
||||
/// Initializes the context to sane default values given the specified output
|
||||
/// file type, arch, os, and minimum os version. This should be called before
|
||||
/// other setXXX() methods.
|
||||
|
@ -79,6 +86,15 @@ public:
|
|||
StringRef archName() const { return nameFromArch(_arch); }
|
||||
OS os() const { return _os; }
|
||||
|
||||
ExportMode exportMode() const { return _exportMode; }
|
||||
void setExportMode(ExportMode mode) { _exportMode = mode; }
|
||||
void addExportSymbol(StringRef sym);
|
||||
bool exportRestrictMode() const { return _exportMode != ExportMode::globals; }
|
||||
bool exportSymbolNamed(StringRef sym) const;
|
||||
|
||||
bool keepPrivateExterns() const { return _keepPrivateExterns; }
|
||||
void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
|
||||
|
||||
bool minOS(StringRef mac, StringRef iOS) const;
|
||||
void setDoNothing(bool value) { _doNothing = value; }
|
||||
bool doNothing() const { return _doNothing; }
|
||||
|
@ -222,6 +238,8 @@ public:
|
|||
private:
|
||||
Writer &writer() const override;
|
||||
mach_o::MachODylibFile* loadIndirectDylib(StringRef path) const;
|
||||
void checkExportWhiteList(const DefinedAtom *atom) const;
|
||||
void checkExportBlackList(const DefinedAtom *atom) const;
|
||||
|
||||
|
||||
struct ArchInfo {
|
||||
|
@ -258,6 +276,7 @@ private:
|
|||
bool _deadStrippableDylib;
|
||||
bool _printAtoms;
|
||||
bool _testingFileUsage;
|
||||
bool _keepPrivateExterns;
|
||||
StringRef _bundleLoader;
|
||||
mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
|
@ -265,6 +284,8 @@ private:
|
|||
llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
|
||||
std::set<mach_o::MachODylibFile*> _allDylibs;
|
||||
mutable std::vector<std::unique_ptr<class MachOFileNode>> _indirectDylibs;
|
||||
ExportMode _exportMode;
|
||||
llvm::StringSet<> _exportedSymbols;
|
||||
};
|
||||
|
||||
} // end namespace lld
|
||||
|
|
|
@ -88,6 +88,31 @@ void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,
|
|||
new MachOFileNode(path, forceLoad)));
|
||||
}
|
||||
|
||||
// Export lists are one symbol per line. Blank lines are ignored.
|
||||
// Trailing comments start with #.
|
||||
std::error_code parseExportsList(StringRef exportFilePath,
|
||||
MachOLinkingContext &ctx,
|
||||
raw_ostream &diagnostics) {
|
||||
// Map in export list file.
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
|
||||
MemoryBuffer::getFileOrSTDIN(exportFilePath);
|
||||
if (std::error_code ec = mb.getError())
|
||||
return ec;
|
||||
StringRef buffer = mb->get()->getBuffer();
|
||||
while (!buffer.empty()) {
|
||||
// Split off each line in the file.
|
||||
std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
|
||||
StringRef line = lineAndRest.first;
|
||||
// Ignore trailing # comments.
|
||||
std::pair<StringRef, StringRef> symAndComment = line.split('#');
|
||||
StringRef sym = symAndComment.first.trim();
|
||||
if (!sym.empty())
|
||||
ctx.addExportSymbol(sym);
|
||||
buffer = lineAndRest.second;
|
||||
}
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
//
|
||||
// There are two variants of the -filelist option:
|
||||
//
|
||||
|
@ -349,7 +374,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
ctx.appendLLVMOption(llvmArg->getValue());
|
||||
}
|
||||
|
||||
// Handle -print_atoms a
|
||||
// Handle -print_atoms
|
||||
if (parsedArgs->getLastArg(OPT_print_atoms))
|
||||
ctx.setPrintAtoms();
|
||||
|
||||
|
@ -357,6 +382,13 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
if (parsedArgs->getLastArg(OPT_t))
|
||||
ctx.setLogInputFiles(true);
|
||||
|
||||
// Handle -keep_private_externs
|
||||
if (parsedArgs->getLastArg(OPT_keep_private_externs)) {
|
||||
ctx.setKeepPrivateExterns(true);
|
||||
if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
|
||||
diagnostics << "warning: -keep_private_externs only used in -r mode\n";
|
||||
}
|
||||
|
||||
// In -test_file_usage mode, we'll be given an explicit list of paths that
|
||||
// exist. We'll also be expected to print out information about how we located
|
||||
// libraries and so on that the user specified, but not to actually do any
|
||||
|
@ -427,6 +459,64 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
}
|
||||
}
|
||||
|
||||
// Handle -exported_symbols_list <file>
|
||||
for (auto expFile : parsedArgs->filtered(OPT_exported_symbols_list)) {
|
||||
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
|
||||
diagnostics << "error: -exported_symbols_list cannot be combined "
|
||||
<< "with -unexported_symbol[s_list]\n";
|
||||
return false;
|
||||
}
|
||||
ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList);
|
||||
if (std::error_code ec = parseExportsList(expFile->getValue(), ctx,
|
||||
diagnostics)) {
|
||||
diagnostics << "error: " << ec.message()
|
||||
<< ", processing '-exported_symbols_list "
|
||||
<< expFile->getValue()
|
||||
<< "'\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle -exported_symbol <symbol>
|
||||
for (auto symbol : parsedArgs->filtered(OPT_exported_symbol)) {
|
||||
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
|
||||
diagnostics << "error: -exported_symbol cannot be combined "
|
||||
<< "with -unexported_symbol[s_list]\n";
|
||||
return false;
|
||||
}
|
||||
ctx.setExportMode(MachOLinkingContext::ExportMode::whiteList);
|
||||
ctx.addExportSymbol(symbol->getValue());
|
||||
}
|
||||
|
||||
// Handle -unexported_symbols_list <file>
|
||||
for (auto expFile : parsedArgs->filtered(OPT_unexported_symbols_list)) {
|
||||
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
|
||||
diagnostics << "error: -unexported_symbols_list cannot be combined "
|
||||
<< "with -exported_symbol[s_list]\n";
|
||||
return false;
|
||||
}
|
||||
ctx.setExportMode(MachOLinkingContext::ExportMode::blackList);
|
||||
if (std::error_code ec = parseExportsList(expFile->getValue(), ctx,
|
||||
diagnostics)) {
|
||||
diagnostics << "error: " << ec.message()
|
||||
<< ", processing '-unexported_symbols_list "
|
||||
<< expFile->getValue()
|
||||
<< "'\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle -unexported_symbol <symbol>
|
||||
for (auto symbol : parsedArgs->filtered(OPT_unexported_symbol)) {
|
||||
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
|
||||
diagnostics << "error: -unexported_symbol cannot be combined "
|
||||
<< "with -exported_symbol[s_list]\n";
|
||||
return false;
|
||||
}
|
||||
ctx.setExportMode(MachOLinkingContext::ExportMode::blackList);
|
||||
ctx.addExportSymbol(symbol->getValue());
|
||||
}
|
||||
|
||||
// Handle input files
|
||||
for (auto &arg : *parsedArgs) {
|
||||
ErrorOr<StringRef> resolvedPath = StringRef();
|
||||
|
@ -442,7 +532,8 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
diagnostics << "Unable to find library -l" << arg->getValue() << "\n";
|
||||
return false;
|
||||
} else if (ctx.testingFileUsage()) {
|
||||
diagnostics << "Found library " << canonicalizePath(resolvedPath.get()) << '\n';
|
||||
diagnostics << "Found library "
|
||||
<< canonicalizePath(resolvedPath.get()) << '\n';
|
||||
}
|
||||
addFile(resolvedPath.get(), inputGraph, globalWholeArchive);
|
||||
break;
|
||||
|
@ -452,7 +543,8 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
diagnostics << "Unable to find -framework " << arg->getValue() << "\n";
|
||||
return false;
|
||||
} else if (ctx.testingFileUsage()) {
|
||||
diagnostics << "Found framework " << canonicalizePath(resolvedPath.get()) << '\n';
|
||||
diagnostics << "Found framework "
|
||||
<< canonicalizePath(resolvedPath.get()) << '\n';
|
||||
}
|
||||
addFile(resolvedPath.get(), inputGraph, globalWholeArchive);
|
||||
break;
|
||||
|
|
|
@ -34,6 +34,21 @@ def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">,
|
|||
def mllvm : Separate<["-"], "mllvm">,
|
||||
MetaVarName<"<option>">,
|
||||
HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>;
|
||||
def exported_symbols_list : Separate<["-"], "exported_symbols_list">,
|
||||
MetaVarName<"<file-path>">,
|
||||
HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
|
||||
def exported_symbol : Separate<["-"], "exported_symbol">,
|
||||
MetaVarName<"<symbol>">,
|
||||
HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
|
||||
def unexported_symbols_list : Separate<["-"], "unexported_symbols_list">,
|
||||
MetaVarName<"<file-path>">,
|
||||
HelpText<"Lists symbols that should not be exported">, Group<grp_opts>;
|
||||
def unexported_symbol : Separate<["-"], "unexported_symbol">,
|
||||
MetaVarName<"<symbol>">,
|
||||
HelpText<"A symbol which should not be exported">, Group<grp_opts>;
|
||||
def keep_private_externs : Flag<["-"], "keep_private_externs">,
|
||||
HelpText<"Private extern (hidden) symbols should not be transformed "
|
||||
"into local symbols">, Group<grp_opts>;
|
||||
|
||||
// main executable options
|
||||
def grp_main : OptionGroup<"opts">, HelpText<"MAIN EXECUTABLE OPTIONS">;
|
||||
|
|
|
@ -130,7 +130,8 @@ MachOLinkingContext::MachOLinkingContext()
|
|||
_doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
|
||||
_pageZeroSize(0), _pageSize(4096), _compatibilityVersion(0),
|
||||
_currentVersion(0), _deadStrippableDylib(false), _printAtoms(false),
|
||||
_testingFileUsage(false), _archHandler(nullptr) {}
|
||||
_testingFileUsage(false), _keepPrivateExterns(false),
|
||||
_archHandler(nullptr), _exportMode(ExportMode::globals) {}
|
||||
|
||||
MachOLinkingContext::~MachOLinkingContext() {}
|
||||
|
||||
|
@ -448,6 +449,12 @@ bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// If -exported_symbols_list used, all exported symbols must be defined.
|
||||
if (_exportMode == ExportMode::whiteList) {
|
||||
for (const auto &symbol : _exportedSymbols)
|
||||
addInitialUndefinedSymbol(symbol.getKey());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -572,4 +579,23 @@ bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void MachOLinkingContext::addExportSymbol(StringRef sym) {
|
||||
// FIXME: Support wildcards.
|
||||
_exportedSymbols.insert(sym);
|
||||
}
|
||||
|
||||
bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
|
||||
switch (_exportMode) {
|
||||
case ExportMode::globals:
|
||||
llvm_unreachable("exportSymbolNamed() should not be called in this mode");
|
||||
break;
|
||||
case ExportMode::whiteList:
|
||||
return _exportedSymbols.count(sym);
|
||||
case ExportMode::blackList:
|
||||
return !_exportedSymbols.count(sym);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace lld
|
||||
|
|
|
@ -106,7 +106,7 @@ public:
|
|||
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 @@ private:
|
|||
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 @@ void Util::buildAtomToAddressMap() {
|
|||
}
|
||||
}
|
||||
|
||||
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::AtomSorter::operator()(const AtomAndIndex &left,
|
|||
}
|
||||
|
||||
|
||||
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 @@ void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
|
|||
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 @@ void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
|
|||
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 @@ void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
|
|||
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 @@ void Util::addSymbols(const lld::File &atomFile, NormalizedFile &file) {
|
|||
}
|
||||
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 @@ normalizedFromAtoms(const lld::File &atomFile,
|
|||
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);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# For use with exported_symbols_list.yaml
|
||||
#
|
||||
_foo
|
||||
_b
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \
|
||||
# RUN: %s %p/Inputs/libSystem.yaml -o %t \
|
||||
# RUN: -exported_symbols_list %p/Inputs/exported_symbols_list.exp && \
|
||||
# RUN: llvm-nm -m %t | FileCheck %s
|
||||
#
|
||||
# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \
|
||||
# RUN: %s %p/Inputs/libSystem.yaml -o %t2 \
|
||||
# RUN: -exported_symbol _foo -exported_symbol _b && \
|
||||
# RUN: llvm-nm -m %t2 | FileCheck %s
|
||||
#
|
||||
# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \
|
||||
# RUN: %s %p/Inputs/libSystem.yaml -o %t3 \
|
||||
# RUN: -unexported_symbol _bar -unexported_symbol _a && \
|
||||
# RUN: llvm-nm -m %t3 | FileCheck %s
|
||||
#
|
||||
# Test -exported_symbols_list and -exported_symbol properly changes visibility.
|
||||
#
|
||||
|
||||
--- !mach-o
|
||||
arch: x86_64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
address: 0x0000000000000000
|
||||
content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
|
||||
0x89, 0xE5, 0x5D, 0xC3 ]
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
alignment: 2
|
||||
address: 0x000000000000000C
|
||||
content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
|
||||
|
||||
global-symbols:
|
||||
- name: _a
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x000000000000000C
|
||||
- name: _b
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x0000000000000010
|
||||
- name: _bar
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000006
|
||||
- name: _foo
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
|
||||
|
||||
...
|
||||
|
||||
# CHECK: (__DATA,__data) non-external (was a private external) _a
|
||||
# CHECK: (__DATA,__data) external _b
|
||||
# CHECK: (__TEXT,__text) non-external (was a private external) _bar
|
||||
# CHECK: (__TEXT,__text) external _foo
|
|
@ -0,0 +1,67 @@
|
|||
# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t -exported_symbol _bar \
|
||||
# RUN: && llvm-nm -m %t | FileCheck %s
|
||||
#
|
||||
# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t2 -keep_private_externs \
|
||||
# RUN: -exported_symbol _bar && \
|
||||
# RUN: llvm-nm -m %t2 | FileCheck -check-prefix=CHECK_KPE %s
|
||||
#
|
||||
# RUN: not lld -flavor darwin -arch x86_64 -r %s -o %t3 \
|
||||
# RUN: -exported_symbol _foo 2> %t4
|
||||
|
||||
# Test -exported_symbols_list properly changes visibility in -r mode.
|
||||
#
|
||||
|
||||
--- !mach-o
|
||||
arch: x86_64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
address: 0x0000000000000000
|
||||
content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
|
||||
0x89, 0xE5, 0x5D, 0xC3 ]
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
alignment: 2
|
||||
address: 0x000000000000000C
|
||||
content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
|
||||
|
||||
global-symbols:
|
||||
- name: _a
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x000000000000000C
|
||||
- name: _b
|
||||
type: N_SECT
|
||||
scope: [ N_EXT, N_PEXT ]
|
||||
sect: 2
|
||||
value: 0x0000000000000010
|
||||
- name: _bar
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000006
|
||||
- name: _foo
|
||||
type: N_SECT
|
||||
scope: [ N_EXT, N_PEXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
|
||||
|
||||
...
|
||||
|
||||
# CHECK: (__DATA,__data) non-external (was a private external) _a
|
||||
# CHECK: (__DATA,__data) non-external (was a private external) _b
|
||||
# CHECK: (__TEXT,__text) external _bar
|
||||
# CHECK: (__TEXT,__text) non-external (was a private external) _foo
|
||||
|
||||
# CHECK_KPE: (__DATA,__data) non-external (was a private external) _a
|
||||
# CHECK_KPE: (__DATA,__data) private external _b
|
||||
# CHECK_KPE: (__TEXT,__text) external _bar
|
||||
# CHECK_KPE: (__TEXT,__text) private external _foo
|
|
@ -0,0 +1,55 @@
|
|||
# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \
|
||||
# RUN: %s %p/Inputs/libSystem.yaml -o %t -exported_symbol _foobar 2> %t2
|
||||
#
|
||||
# Test -exported_symbol fails if exported symbol not found.
|
||||
#
|
||||
|
||||
--- !mach-o
|
||||
arch: x86_64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
address: 0x0000000000000000
|
||||
content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
|
||||
0x89, 0xE5, 0x5D, 0xC3 ]
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
alignment: 2
|
||||
address: 0x000000000000000C
|
||||
content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
|
||||
|
||||
global-symbols:
|
||||
- name: _a
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x000000000000000C
|
||||
- name: _b
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x0000000000000010
|
||||
- name: _bar
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000006
|
||||
- name: _foo
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
|
||||
|
||||
...
|
||||
|
||||
# CHECK: (__DATA,__data) private external _a
|
||||
# CHECK: (__DATA,__data) external _b
|
||||
# CHECK: (__TEXT,__text) private external _bar
|
||||
# CHECK: (__TEXT,__text) external _foo
|
|
@ -0,0 +1,63 @@
|
|||
# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t \
|
||||
# RUN: && llvm-nm -m %t | FileCheck %s
|
||||
#
|
||||
# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t2 -keep_private_externs \
|
||||
# RUN: && llvm-nm -m %t2 | FileCheck -check-prefix=CHECK_KPE %s
|
||||
#
|
||||
# Test -keep_private_externs in -r mode.
|
||||
#
|
||||
|
||||
--- !mach-o
|
||||
arch: x86_64
|
||||
file-type: MH_OBJECT
|
||||
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
|
||||
address: 0x0000000000000000
|
||||
content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
|
||||
0x89, 0xE5, 0x5D, 0xC3 ]
|
||||
- segment: __DATA
|
||||
section: __data
|
||||
type: S_REGULAR
|
||||
attributes: [ ]
|
||||
alignment: 2
|
||||
address: 0x000000000000000C
|
||||
content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
|
||||
|
||||
global-symbols:
|
||||
- name: _a
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 2
|
||||
value: 0x000000000000000C
|
||||
- name: _b
|
||||
type: N_SECT
|
||||
scope: [ N_EXT, N_PEXT ]
|
||||
sect: 2
|
||||
value: 0x0000000000000010
|
||||
- name: _bar
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000006
|
||||
- name: _foo
|
||||
type: N_SECT
|
||||
scope: [ N_EXT, N_PEXT ]
|
||||
sect: 1
|
||||
value: 0x0000000000000000
|
||||
|
||||
|
||||
...
|
||||
|
||||
# CHECK: (__DATA,__data) external _a
|
||||
# CHECK: (__DATA,__data) non-external (was a private external) _b
|
||||
# CHECK: (__TEXT,__text) external _bar
|
||||
# CHECK: (__TEXT,__text) non-external (was a private external) _foo
|
||||
|
||||
# CHECK_KPE: (__DATA,__data) external _a
|
||||
# CHECK_KPE: (__DATA,__data) private external _b
|
||||
# CHECK_KPE: (__TEXT,__text) external _bar
|
||||
# CHECK_KPE: (__TEXT,__text) private external _foo
|
Loading…
Reference in New Issue