summaryrefslogtreecommitdiff
path: root/lld/MachO
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-27 19:50:45 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-27 19:50:54 +0000
commit08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (patch)
tree041e72e32710b1e742516d8c9f1575bf0116d3e3 /lld/MachO
parent4b4fe385e49bd883fd183b5f21c1ea486c722e61 (diff)
the last commit before the upstream release/16.x branch was created.
Diffstat (limited to 'lld/MachO')
-rw-r--r--lld/MachO/Driver.cpp20
-rw-r--r--lld/MachO/DriverUtils.cpp1
-rw-r--r--lld/MachO/InputFiles.cpp60
-rw-r--r--lld/MachO/InputFiles.h12
-rw-r--r--lld/MachO/InputSection.cpp2
-rw-r--r--lld/MachO/Options.td10
-rw-r--r--lld/MachO/SyntheticSections.h6
7 files changed, 71 insertions, 40 deletions
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 454708fad4ef..ce2d55bef456 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -266,7 +266,8 @@ static DenseMap<StringRef, ArchiveFileInfo> loadedArchives;
static InputFile *addFile(StringRef path, LoadType loadType,
bool isLazy = false, bool isExplicit = true,
- bool isBundleLoader = false) {
+ bool isBundleLoader = false,
+ bool isForceHidden = false) {
Optional<MemoryBufferRef> buffer = readFile(path);
if (!buffer)
return nullptr;
@@ -293,7 +294,7 @@ static InputFile *addFile(StringRef path, LoadType loadType,
if (!archive->isEmpty() && !archive->hasSymbolTable())
error(path + ": archive has no index; run ranlib to add one");
- file = make<ArchiveFile>(std::move(archive));
+ file = make<ArchiveFile>(std::move(archive), isForceHidden);
} else {
file = entry->second.file;
// Command-line loads take precedence. If file is previously loaded via
@@ -406,10 +407,12 @@ static InputFile *addFile(StringRef path, LoadType loadType,
}
static void addLibrary(StringRef name, bool isNeeded, bool isWeak,
- bool isReexport, bool isExplicit, LoadType loadType) {
+ bool isReexport, bool isHidden, bool isExplicit,
+ LoadType loadType) {
if (Optional<StringRef> path = findLibrary(name)) {
if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
- addFile(*path, loadType, /*isLazy=*/false, isExplicit))) {
+ addFile(*path, loadType, /*isLazy=*/false, isExplicit,
+ /*isBundleLoader=*/false, isHidden))) {
if (isNeeded)
dylibFile->forceNeeded = true;
if (isWeak)
@@ -473,7 +476,7 @@ void macho::parseLCLinkerOption(InputFile *f, unsigned argc, StringRef data) {
StringRef arg = argv[i];
if (arg.consume_front("-l")) {
addLibrary(arg, /*isNeeded=*/false, /*isWeak=*/false,
- /*isReexport=*/false, /*isExplicit=*/false,
+ /*isReexport=*/false, /*isHidden=*/false, /*isExplicit=*/false,
LoadType::LCLinkerOption);
} else if (arg == "-framework") {
StringRef name = argv[++i];
@@ -1035,12 +1038,19 @@ static void createFiles(const InputArgList &args) {
case OPT_force_load:
addFile(rerootPath(arg->getValue()), LoadType::CommandLineForce);
break;
+ case OPT_load_hidden:
+ addFile(rerootPath(arg->getValue()), LoadType::CommandLine,
+ /*isLazy=*/false, /*isExplicit=*/true, /*isBundleLoader=*/false,
+ /*isForceHidden=*/true);
+ break;
case OPT_l:
case OPT_needed_l:
case OPT_reexport_l:
case OPT_weak_l:
+ case OPT_hidden_l:
addLibrary(arg->getValue(), opt.getID() == OPT_needed_l,
opt.getID() == OPT_weak_l, opt.getID() == OPT_reexport_l,
+ opt.getID() == OPT_hidden_l,
/*isExplicit=*/true, LoadType::CommandLine);
break;
case OPT_framework:
diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index b52d5e851c62..d8e474d15cfd 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -150,6 +150,7 @@ std::string macho::createResponseFile(const InputArgList &args) {
break;
case OPT_force_load:
case OPT_weak_library:
+ case OPT_load_hidden:
os << arg->getSpelling() << " "
<< quote(rewriteInputPath(arg->getValue())) << "\n";
break;
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index e3bf553e5334..b463d7817594 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -768,7 +768,7 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
template <class NList>
static macho::Symbol *createDefined(const NList &sym, StringRef name,
InputSection *isec, uint64_t value,
- uint64_t size) {
+ uint64_t size, bool forceHidden) {
// Symbol scope is determined by sym.n_type & (N_EXT | N_PEXT):
// N_EXT: Global symbols. These go in the symbol table during the link,
// and also in the export table of the output so that the dynamic
@@ -787,7 +787,10 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
(sym.n_desc & (N_WEAK_DEF | N_WEAK_REF)) == (N_WEAK_DEF | N_WEAK_REF);
if (sym.n_type & N_EXT) {
- bool isPrivateExtern = sym.n_type & N_PEXT;
+ // -load_hidden makes us treat global symbols as linkage unit scoped.
+ // Duplicates are reported but the symbol does not go in the export trie.
+ bool isPrivateExtern = sym.n_type & N_PEXT || forceHidden;
+
// lld's behavior for merging symbols is slightly different from ld64:
// ld64 picks the winning symbol based on several criteria (see
// pickBetweenRegularAtoms() in ld64's SymbolTable.cpp), while lld
@@ -844,11 +847,12 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
// InputSection. They cannot be weak.
template <class NList>
static macho::Symbol *createAbsolute(const NList &sym, InputFile *file,
- StringRef name) {
+ StringRef name, bool forceHidden) {
if (sym.n_type & N_EXT) {
+ bool isPrivateExtern = sym.n_type & N_PEXT || forceHidden;
return symtab->addDefined(
name, file, nullptr, sym.n_value, /*size=*/0,
- /*isWeakDef=*/false, sym.n_type & N_PEXT, sym.n_desc & N_ARM_THUMB_DEF,
+ /*isWeakDef=*/false, isPrivateExtern, sym.n_desc & N_ARM_THUMB_DEF,
/*isReferencedDynamically=*/false, sym.n_desc & N_NO_DEAD_STRIP,
/*isWeakDefCanBeHidden=*/false);
}
@@ -864,15 +868,16 @@ template <class NList>
macho::Symbol *ObjFile::parseNonSectionSymbol(const NList &sym,
StringRef name) {
uint8_t type = sym.n_type & N_TYPE;
+ bool isPrivateExtern = sym.n_type & N_PEXT || forceHidden;
switch (type) {
case N_UNDF:
return sym.n_value == 0
? symtab->addUndefined(name, this, sym.n_desc & N_WEAK_REF)
: symtab->addCommon(name, this, sym.n_value,
1 << GET_COMM_ALIGN(sym.n_desc),
- sym.n_type & N_PEXT);
+ isPrivateExtern);
case N_ABS:
- return createAbsolute(sym, this, name);
+ return createAbsolute(sym, this, name, forceHidden);
case N_PBUD:
case N_INDR:
error("TODO: support symbols of type " + std::to_string(type));
@@ -944,7 +949,8 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
" at misaligned offset");
continue;
}
- symbols[symIndex] = createDefined(sym, name, isec, 0, isec->getSize());
+ symbols[symIndex] =
+ createDefined(sym, name, isec, 0, isec->getSize(), forceHidden);
}
continue;
}
@@ -979,8 +985,8 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
// 4. If we have a literal section (e.g. __cstring and __literal4).
if (!subsectionsViaSymbols || symbolOffset == 0 ||
sym.n_desc & N_ALT_ENTRY || !isa<ConcatInputSection>(isec)) {
- symbols[symIndex] =
- createDefined(sym, name, isec, symbolOffset, symbolSize);
+ symbols[symIndex] = createDefined(sym, name, isec, symbolOffset,
+ symbolSize, forceHidden);
continue;
}
auto *concatIsec = cast<ConcatInputSection>(isec);
@@ -998,8 +1004,8 @@ void ObjFile::parseSymbols(ArrayRef<typename LP::section> sectionHeaders,
// By construction, the symbol will be at offset zero in the new
// subsection.
- symbols[symIndex] =
- createDefined(sym, name, nextIsec, /*value=*/0, symbolSize);
+ symbols[symIndex] = createDefined(sym, name, nextIsec, /*value=*/0,
+ symbolSize, forceHidden);
// TODO: ld64 appears to preserve the original alignment as well as each
// subsection's offset from the last aligned address. We should consider
// emulating that behavior.
@@ -1036,8 +1042,8 @@ OpaqueFile::OpaqueFile(MemoryBufferRef mb, StringRef segName,
}
ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
- bool lazy)
- : InputFile(ObjKind, mb, lazy), modTime(modTime) {
+ bool lazy, bool forceHidden)
+ : InputFile(ObjKind, mb, lazy), modTime(modTime), forceHidden(forceHidden) {
this->archiveName = std::string(archiveName);
if (lazy) {
if (target->wordSize == 8)
@@ -2061,26 +2067,27 @@ void DylibFile::checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const {
warn("using '-application_extension' with unsafe dylib: " + toString(this));
}
-ArchiveFile::ArchiveFile(std::unique_ptr<object::Archive> &&f)
- : InputFile(ArchiveKind, f->getMemoryBufferRef()), file(std::move(f)) {}
+ArchiveFile::ArchiveFile(std::unique_ptr<object::Archive> &&f, bool forceHidden)
+ : InputFile(ArchiveKind, f->getMemoryBufferRef()), file(std::move(f)),
+ forceHidden(forceHidden) {}
void ArchiveFile::addLazySymbols() {
for (const object::Archive::Symbol &sym : file->symbols())
symtab->addLazyArchive(sym.getName(), this, sym);
}
-static Expected<InputFile *> loadArchiveMember(MemoryBufferRef mb,
- uint32_t modTime,
- StringRef archiveName,
- uint64_t offsetInArchive) {
+static Expected<InputFile *>
+loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
+ uint64_t offsetInArchive, bool forceHidden) {
if (config->zeroModTime)
modTime = 0;
switch (identify_magic(mb.getBuffer())) {
case file_magic::macho_object:
- return make<ObjFile>(mb, modTime, archiveName);
+ return make<ObjFile>(mb, modTime, archiveName, /*lazy=*/false, forceHidden);
case file_magic::bitcode:
- return make<BitcodeFile>(mb, archiveName, offsetInArchive);
+ return make<BitcodeFile>(mb, archiveName, offsetInArchive, /*lazy=*/false,
+ forceHidden);
default:
return createStringError(inconvertibleErrorCode(),
mb.getBufferIdentifier() +
@@ -2104,8 +2111,8 @@ Error ArchiveFile::fetch(const object::Archive::Child &c, StringRef reason) {
if (!modTime)
return modTime.takeError();
- Expected<InputFile *> file =
- loadArchiveMember(*mb, toTimeT(*modTime), getName(), c.getChildOffset());
+ Expected<InputFile *> file = loadArchiveMember(
+ *mb, toTimeT(*modTime), getName(), c.getChildOffset(), forceHidden);
if (!file)
return file.takeError();
@@ -2153,7 +2160,8 @@ static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
case GlobalValue::DefaultVisibility:
break;
}
- isPrivateExtern = isPrivateExtern || objSym.canBeOmittedFromSymbolTable();
+ isPrivateExtern = isPrivateExtern || objSym.canBeOmittedFromSymbolTable() ||
+ file.forceHidden;
if (objSym.isCommon())
return symtab->addCommon(name, &file, objSym.getCommonSize(),
@@ -2168,8 +2176,8 @@ static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
}
BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
- uint64_t offsetInArchive, bool lazy)
- : InputFile(BitcodeKind, mb, lazy) {
+ uint64_t offsetInArchive, bool lazy, bool forceHidden)
+ : InputFile(BitcodeKind, mb, lazy), forceHidden(forceHidden) {
this->archiveName = std::string(archiveName);
std::string path = mb.getBufferIdentifier().str();
// ThinLTO assumes that all MemoryBufferRefs given to it have a unique
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 5deb05272a6b..ea6802814e4c 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -156,7 +156,7 @@ struct FDE {
class ObjFile final : public InputFile {
public:
ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName,
- bool lazy = false);
+ bool lazy = false, bool forceHidden = false);
ArrayRef<llvm::MachO::data_in_code_entry> getDataInCode() const;
template <class LP> void parse();
@@ -171,6 +171,7 @@ public:
std::unique_ptr<lld::DWARFCache> dwarfCache;
Section *addrSigSection = nullptr;
const uint32_t modTime;
+ bool forceHidden;
std::vector<ConcatInputSection *> debugSections;
std::vector<CallGraphEntry> callGraph;
llvm::DenseMap<ConcatInputSection *, FDE> fdes;
@@ -259,7 +260,8 @@ private:
// .a file
class ArchiveFile final : public InputFile {
public:
- explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file);
+ explicit ArchiveFile(std::unique_ptr<llvm::object::Archive> &&file,
+ bool forceHidden);
void addLazySymbols();
void fetch(const llvm::object::Archive::Symbol &);
// LLD normally doesn't use Error for error-handling, but the underlying
@@ -273,16 +275,20 @@ private:
// Keep track of children fetched from the archive by tracking
// which address offsets have been fetched already.
llvm::DenseSet<uint64_t> seen;
+ // Load all symbols with hidden visibility (-load_hidden).
+ bool forceHidden;
};
class BitcodeFile final : public InputFile {
public:
explicit BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
- uint64_t offsetInArchive, bool lazy = false);
+ uint64_t offsetInArchive, bool lazy = false,
+ bool forceHidden = false);
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
void parse();
std::unique_ptr<llvm::lto::InputFile> obj;
+ bool forceHidden;
private:
void parseLazy();
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 76b11d9da4f8..ca073f8ac6f3 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -67,7 +67,7 @@ std::string InputSection::getLocation(uint64_t off) const {
// First, try to find a symbol that's near the offset. Use it as a reference
// point.
if (auto *sym = getContainingSymbol(off))
- return (toString(getFile()) + ":(symbol " + sym->getName() + "+0x" +
+ return (toString(getFile()) + ":(symbol " + toString(*sym) + "+0x" +
Twine::utohexstr(off - sym->value) + ")")
.str();
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index b3d74a83f582..064862fb1bb0 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -240,6 +240,14 @@ def force_load : Separate<["-"], "force_load">,
def force_load_swift_libs : Flag<["-"], "force_load_swift_libs">,
HelpText<"Apply -force_load to libraries listed in LC_LINKER_OPTIONS whose names start with 'swift'">,
Group<grp_libs>;
+def load_hidden : Separate<["-"], "load_hidden">,
+ MetaVarName<"<path>">,
+ HelpText<"Load all symbols from static library with hidden visibility">,
+ Group<grp_libs>;
+def hidden_l : Joined<["-"], "hidden-l">,
+ MetaVarName<"<name>">,
+ HelpText<"Like -l<name>, but load all symbols with hidden visibility">,
+ Group<grp_libs>;
def grp_content : OptionGroup<"content">, HelpText<"ADDITIONAL CONTENT">;
@@ -1174,7 +1182,7 @@ def allow_simulator_linking_to_macosx_dylibs : Flag<["-"], "allow_simulator_link
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
Group<grp_undocumented>;
-def bitcode_process_mode : Flag<["-"], "bitcode_process_mode">,
+def bitcode_process_mode : Separate<["-"], "bitcode_process_mode">,
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
Group<grp_undocumented>;
diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index afdd46d8a7de..29c2d98c6625 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -70,7 +70,7 @@ public:
// Sections in __LINKEDIT are special: their offsets are recorded in the
// load commands like LC_DYLD_INFO_ONLY and LC_SYMTAB, instead of in section
// headers.
- bool isHidden() const override final { return true; }
+ bool isHidden() const final { return true; }
virtual uint64_t getRawSize() const = 0;
@@ -80,9 +80,7 @@ public:
//
// NOTE: This assumes that the extra bytes required for alignment can be
// zero-valued bytes.
- uint64_t getSize() const override final {
- return llvm::alignTo(getRawSize(), align);
- }
+ uint64_t getSize() const final { return llvm::alignTo(getRawSize(), align); }
};
// The header of the Mach-O file, which must have a file offset of zero.