[lld] fc5d804 - [lld-macho] Check platform and version when constructor ObjFile

Vy Nguyen via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 5 14:35:00 PST 2021


Author: Vy Nguyen
Date: 2021-03-05T17:34:38-05:00
New Revision: fc5d804ddbef1522a34701513262a34859b65037

URL: https://github.com/llvm/llvm-project/commit/fc5d804ddbef1522a34701513262a34859b65037
DIFF: https://github.com/llvm/llvm-project/commit/fc5d804ddbef1522a34701513262a34859b65037.diff

LOG: [lld-macho] Check platform and version when constructor ObjFile

Differential Revision: https://reviews.llvm.org/D97979

Added: 
    

Modified: 
    lld/MachO/InputFiles.cpp
    lld/MachO/InputFiles.h
    lld/test/MachO/invalid/incompatible-arch.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index a426a8cea66f..2d7932352618 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -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 
diff erent 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)) {

diff  --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 10935050584d..e122c4cb10b7 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -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
 

diff  --git a/lld/test/MachO/invalid/incompatible-arch.s b/lld/test/MachO/invalid/incompatible-arch.s
index a1b07ef155b6..2bd96cbabf14 100644
--- a/lld/test/MachO/invalid/incompatible-arch.s
+++ b/lld/test/MachO/invalid/incompatible-arch.s
@@ -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 
diff erent 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 
diff erent 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


        


More information about the llvm-commits mailing list