mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 07:16:40 +00:00
[lld][MachO] Respect dylibs linked with -allowable_client
(#114638)
ld64.lld would previously allow you to link against dylibs linked with `-allowable_client`, even if the client's name does not match any allowed client. This change fixes that. See #114146 for related discussion. The test binary `liballowable_client.dylib` was created on macOS with: echo | clang -xc - -dynamiclib -mmacosx-version-min=10.11 -arch x86_64 -Wl,-allowable_client,allowed -o lib/liballowable_client.dylib
This commit is contained in:
parent
fe33bd0617
commit
1de9bc1a27
@ -164,6 +164,7 @@ struct Configuration {
|
||||
llvm::StringRef finalOutput;
|
||||
|
||||
llvm::StringRef installName;
|
||||
llvm::StringRef clientName;
|
||||
llvm::StringRef mapFile;
|
||||
llvm::StringRef ltoObjPath;
|
||||
llvm::StringRef thinLTOJobs;
|
||||
|
@ -1881,6 +1881,15 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
|
||||
config->installName = config->finalOutput;
|
||||
}
|
||||
|
||||
auto getClientName = [&]() {
|
||||
StringRef cn = path::filename(config->finalOutput);
|
||||
cn.consume_front("lib");
|
||||
auto firstDotOrUnderscore = cn.find_first_of("._");
|
||||
cn = cn.take_front(firstDotOrUnderscore);
|
||||
return cn;
|
||||
};
|
||||
config->clientName = args.getLastArgValue(OPT_client_name, getClientName());
|
||||
|
||||
if (args.hasArg(OPT_mark_dead_strippable_dylib)) {
|
||||
if (config->outputType != MH_DYLIB)
|
||||
warn("-mark_dead_strippable_dylib: ignored, only has effect with -dylib");
|
||||
|
@ -268,6 +268,26 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
|
||||
if (newFile->exportingFile)
|
||||
newFile->parseLoadCommands(mbref);
|
||||
}
|
||||
|
||||
if (explicitlyLinked && !newFile->allowableClients.empty()) {
|
||||
bool allowed = std::any_of(
|
||||
newFile->allowableClients.begin(), newFile->allowableClients.end(),
|
||||
[&](StringRef allowableClient) {
|
||||
// We only do a prefix match to match LD64's behaviour.
|
||||
return allowableClient.starts_with(config->clientName);
|
||||
});
|
||||
|
||||
// TODO: This behaviour doesn't quite match the latest available source
|
||||
// release of LD64 (ld64-951.9), which allows "parents" and "siblings"
|
||||
// to link to libraries even when they're not explicitly named as
|
||||
// allowable clients. However, behaviour around this seems to have
|
||||
// changed in the latest release of Xcode (ld64-1115.7.3), so it's not
|
||||
// clear what the correct thing to do is yet.
|
||||
if (!allowed)
|
||||
error("cannot link directly with '" +
|
||||
sys::path::filename(newFile->installName) + "' because " +
|
||||
config->clientName + " is not an allowed client");
|
||||
}
|
||||
return newFile;
|
||||
}
|
||||
|
||||
|
@ -1730,6 +1730,14 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
|
||||
? this
|
||||
: this->umbrella;
|
||||
|
||||
if (!canBeImplicitlyLinked) {
|
||||
for (auto *cmd : findCommands<sub_client_command>(hdr, LC_SUB_CLIENT)) {
|
||||
StringRef allowableClient{reinterpret_cast<const char *>(cmd) +
|
||||
cmd->client};
|
||||
allowableClients.push_back(allowableClient);
|
||||
}
|
||||
}
|
||||
|
||||
const auto *dyldInfo = findCommand<dyld_info_command>(hdr, LC_DYLD_INFO_ONLY);
|
||||
const auto *exportsTrie =
|
||||
findCommand<linkedit_data_command>(hdr, LC_DYLD_EXPORTS_TRIE);
|
||||
@ -1891,6 +1899,12 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
|
||||
exportingFile = (canBeImplicitlyLinked && isImplicitlyLinked(installName))
|
||||
? this
|
||||
: umbrella;
|
||||
|
||||
if (!canBeImplicitlyLinked)
|
||||
for (const auto &allowableClient : interface.allowableClients())
|
||||
allowableClients.push_back(
|
||||
*make<std::string>(allowableClient.getInstallName().data()));
|
||||
|
||||
auto addSymbol = [&](const llvm::MachO::Symbol &symbol,
|
||||
const Twine &name) -> void {
|
||||
StringRef savedName = saver().save(name);
|
||||
|
@ -241,6 +241,7 @@ public:
|
||||
DylibFile *exportingFile = nullptr;
|
||||
DylibFile *umbrella;
|
||||
SmallVector<StringRef, 2> rpaths;
|
||||
SmallVector<StringRef> allowableClients;
|
||||
uint32_t compatibilityVersion = 0;
|
||||
uint32_t currentVersion = 0;
|
||||
int64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
|
||||
|
@ -875,8 +875,7 @@ def allowable_client : Separate<["-"], "allowable_client">,
|
||||
Group<grp_rare>;
|
||||
def client_name : Separate<["-"], "client_name">,
|
||||
MetaVarName<"<name>">,
|
||||
HelpText<"Specifies a <name> this client should match with the -allowable_client <name> in a dependent dylib">,
|
||||
Flags<[HelpHidden]>,
|
||||
HelpText<"Specifies a <name> this client should match with the -allowable_client <name> in an explicitly linked dylib">,
|
||||
Group<grp_rare>;
|
||||
def umbrella : Separate<["-"], "umbrella">,
|
||||
MetaVarName<"<name>">,
|
||||
|
BIN
lld/test/MachO/Inputs/liballowable_client.dylib
Executable file
BIN
lld/test/MachO/Inputs/liballowable_client.dylib
Executable file
Binary file not shown.
74
lld/test/MachO/allowable-client.s
Normal file
74
lld/test/MachO/allowable-client.s
Normal file
@ -0,0 +1,74 @@
|
||||
# REQUIRES: x86
|
||||
# RUN: rm -rf %t; split-file %s %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
|
||||
|
||||
# Check linking against a .dylib
|
||||
# RUN: not %lld -o %t/test %t/test.o -L%S/Inputs -lallowable_client 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-IMPLICIT
|
||||
# RUN: not %lld -o %t/libtest_debug.exe %t/test.o -L%S/Inputs -lallowable_client 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-IMPLICIT
|
||||
# RUN: not %lld -o %t/test %t/test.o -L%S/Inputs -lallowable_client -client_name notallowed 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-EXPLICIT
|
||||
# RUN: %lld -o %t/test %t/test.o -L%S/Inputs -lallowable_client -client_name allowed
|
||||
# RUN: %lld -o %t/test %t/test.o -L%S/Inputs -lallowable_client -client_name all
|
||||
# RUN: %lld -o %t/all %t/test.o -L%S/Inputs -lallowable_client
|
||||
# RUN: %lld -o %t/allowed %t/test.o -L%S/Inputs -lallowable_client
|
||||
# RUN: %lld -o %t/liballowed_debug.exe %t/test.o -L%S/Inputs -lallowable_client
|
||||
|
||||
# Check linking against a .tbd
|
||||
# RUN: not %lld -o %t/test %t/test.o -L%t -lallowable_client 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-IMPLICIT
|
||||
# RUN: not %lld -o %t/libtest_debug.exe %t/test.o -L%t -lallowable_client 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-IMPLICIT
|
||||
# RUN: not %lld -o %t/test %t/test.o -L%t -lallowable_client -client_name notallowed 2>&1 | FileCheck %s --check-prefix=NOTALLOWED-EXPLICIT
|
||||
# RUN: %lld -o %t/test %t/test.o -L%t -lallowable_client -client_name allowed
|
||||
# RUN: %lld -o %t/test %t/test.o -L%t -lallowable_client -client_name all
|
||||
# RUN: %lld -o %t/all %t/test.o -L%t -lallowable_client
|
||||
# RUN: %lld -o %t/allowed %t/test.o -L%t -lallowable_client
|
||||
# RUN: %lld -o %t/liballowed_debug.exe %t/test.o -L%t -lallowable_client
|
||||
|
||||
# NOTALLOWED-IMPLICIT: error: cannot link directly with 'liballowable_client.dylib' because test is not an allowed client
|
||||
# NOTALLOWED-EXPLICIT: error: cannot link directly with 'liballowable_client.dylib' because notallowed is not an allowed client
|
||||
|
||||
#--- test.s
|
||||
.text
|
||||
.globl _main
|
||||
_main:
|
||||
ret
|
||||
|
||||
#--- liballowable_client.tbd
|
||||
{
|
||||
"main_library": {
|
||||
"allowable_clients": [
|
||||
{
|
||||
"clients": [
|
||||
"allowed"
|
||||
]
|
||||
}
|
||||
],
|
||||
"compatibility_versions": [
|
||||
{
|
||||
"version": "0"
|
||||
}
|
||||
],
|
||||
"current_versions": [
|
||||
{
|
||||
"version": "0"
|
||||
}
|
||||
],
|
||||
"flags": [
|
||||
{
|
||||
"attributes": [
|
||||
"not_app_extension_safe"
|
||||
]
|
||||
}
|
||||
],
|
||||
"install_names": [
|
||||
{
|
||||
"name": "lib/liballowable_client.dylib"
|
||||
}
|
||||
],
|
||||
"target_info": [
|
||||
{
|
||||
"min_deployment": "10.11",
|
||||
"target": "x86_64-macos"
|
||||
}
|
||||
]
|
||||
},
|
||||
"tapi_tbd_version": 5
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user