forked from OSchip/llvm-project
[lld-macho] Check platform and version when constructor ObjFile
Differential Revision: https://reviews.llvm.org/D97979
This commit is contained in:
parent
6410ee0d09
commit
fc5d804ddb
|
@ -149,20 +149,6 @@ Optional<MemoryBufferRef> macho::readFile(StringRef path) {
|
|||
return None;
|
||||
}
|
||||
|
||||
const load_command *macho::findCommand(const mach_header_64 *hdr,
|
||||
uint32_t type) {
|
||||
const uint8_t *p =
|
||||
reinterpret_cast<const uint8_t *>(hdr) + sizeof(mach_header_64);
|
||||
|
||||
for (uint32_t i = 0, n = hdr->ncmds; i < n; ++i) {
|
||||
auto *cmd = reinterpret_cast<const load_command *>(p);
|
||||
if (cmd->cmd == type)
|
||||
return cmd;
|
||||
p += cmd->cmdsize;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ObjFile::parseSections(ArrayRef<section_64> sections) {
|
||||
subsections.reserve(sections.size());
|
||||
auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
|
||||
|
@ -352,6 +338,33 @@ static macho::Symbol *createDefined(const structs::nlist_64 &sym,
|
|||
/*isExternal=*/false, /*isPrivateExtern=*/false);
|
||||
}
|
||||
|
||||
// Checks if the version specified in `cmd` is compatible with target
|
||||
// version in `config`. IOW, check if cmd's version >= config's version.
|
||||
static bool hasCompatVersion(const InputFile *input,
|
||||
const build_version_command *cmd,
|
||||
const Configuration *config) {
|
||||
|
||||
if (config->target.Platform != static_cast<PlatformKind>(cmd->platform)) {
|
||||
error(toString(input) + " has platform " +
|
||||
getPlatformName(static_cast<PlatformKind>(cmd->platform)) +
|
||||
Twine(", which is different from target platform ") +
|
||||
getPlatformName(config->target.Platform));
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned major = cmd->minos >> 16;
|
||||
unsigned minor = (cmd->minos >> 8) & 0xffu;
|
||||
unsigned subMinor = cmd->minos & 0xffu;
|
||||
VersionTuple version(major, minor, subMinor);
|
||||
if (version >= config->platformInfo.minimum)
|
||||
return true;
|
||||
|
||||
error(toString(input) + " has version " + version.getAsString() +
|
||||
", which is incompatible with target version of " +
|
||||
config->platformInfo.minimum.getAsString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Absolute symbols are defined symbols that do not have an associated
|
||||
// InputSection. They cannot be weak.
|
||||
static macho::Symbol *createAbsolute(const structs::nlist_64 &sym,
|
||||
|
@ -496,7 +509,12 @@ ObjFile::ObjFile(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName)
|
|||
getArchitectureName(config->target.Arch));
|
||||
return;
|
||||
}
|
||||
// TODO: check platform too
|
||||
|
||||
if (const auto *cmd =
|
||||
findCommand<build_version_command>(hdr, LC_BUILD_VERSION)) {
|
||||
if (!hasCompatVersion(this, cmd, config))
|
||||
return;
|
||||
}
|
||||
|
||||
if (const load_command *cmd = findCommand(hdr, LC_LINKER_OPTION)) {
|
||||
auto *c = reinterpret_cast<const linker_option_command *>(cmd);
|
||||
|
@ -653,6 +671,12 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
|
|||
return;
|
||||
}
|
||||
|
||||
if (const build_version_command *cmd =
|
||||
findCommand<build_version_command>(hdr, LC_BUILD_VERSION)) {
|
||||
if (!hasCompatVersion(this, cmd, config))
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize symbols.
|
||||
DylibFile *exportingFile = isImplicitlyLinked(dylibName) ? this : umbrella;
|
||||
if (const load_command *cmd = findCommand(hdr, LC_DYLD_INFO_ONLY)) {
|
||||
|
|
|
@ -175,8 +175,20 @@ extern llvm::SetVector<InputFile *> inputFiles;
|
|||
|
||||
llvm::Optional<MemoryBufferRef> readFile(StringRef path);
|
||||
|
||||
const llvm::MachO::load_command *
|
||||
findCommand(const llvm::MachO::mach_header_64 *, uint32_t type);
|
||||
template <class CommandType = llvm::MachO::load_command>
|
||||
const CommandType *findCommand(const llvm::MachO::mach_header_64 *hdr,
|
||||
uint32_t type) {
|
||||
const uint8_t *p = reinterpret_cast<const uint8_t *>(hdr) +
|
||||
sizeof(llvm::MachO::mach_header_64);
|
||||
|
||||
for (uint32_t i = 0, n = hdr->ncmds; i < n; ++i) {
|
||||
auto *cmd = reinterpret_cast<const CommandType *>(p);
|
||||
if (cmd->cmd == type)
|
||||
return cmd;
|
||||
p += cmd->cmdsize;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace macho
|
||||
|
||||
|
|
|
@ -1,8 +1,31 @@
|
|||
# REQUIRES: aarch64
|
||||
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t.o
|
||||
# RUN: not %lld -arch x86_64 -lSystem %t.o -o /dev/null 2>&1 | FileCheck %s -DFILE=%t.o
|
||||
# REQUIRES: aarch64, x86
|
||||
|
||||
# RUN: rm -rf %t && mkdir -p %t
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t/test.o
|
||||
# RUN: not %lld -arch x86_64 -lSystem %t/test.o -o /dev/null 2>&1 | FileCheck %s -DFILE=%t/test.o
|
||||
# CHECK: error: {{.*}}[[FILE]] has architecture arm64 which is incompatible with target architecture x86_64
|
||||
|
||||
# RUN: %lld -dylib -arch arm64 -platform_version macOS 9.0 11.0 -o %t/out.dylib %t/test.o
|
||||
|
||||
# RUN: not %lld -dylib -arch arm64 -platform_version iOS 9.0 11.0 %t/out.dylib \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=DYLIB-PLAT
|
||||
# DYLIB-PLAT: {{.*}}out.dylib has platform macOS, which is different from target platform iOS
|
||||
|
||||
# RUN: not %lld -dylib -arch arm64 -platform_version macOS 14.0 15.0 %t/out.dylib \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=DYLIB-VERSION
|
||||
# DYLIB-VERSION: {{.*}}out.dylib has version 9.0.0, which is incompatible with target version of 14.0
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos10.15.0 %s -o %t/test_x86.o
|
||||
|
||||
# RUN: not %lld %t/test_x86.o -lSystem -arch x86_64 -platform_version iOS 10.0 15.0 \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJ-PLAT
|
||||
# OBJ-PLAT: {{.*}}test_x86.o has platform macOS, which is different from target platform iOS
|
||||
|
||||
# RUN: not %lld %t/test_x86.o -lSystem -arch x86_64 -platform_version macOS 14.0 15.0 \
|
||||
# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=OBJ-VERSION
|
||||
# OBJ-VERSION: {{.*}}test_x86.o has version 10.15.0, which is incompatible with target version of 14.0
|
||||
|
||||
.globl _main
|
||||
_main:
|
||||
ret
|
||||
|
|
Loading…
Reference in New Issue