[llvm] c625b99 - [ORC] Add SectCreateMaterializationUnit, llvm-jitlink -sectcreate option.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 20 10:24:19 PST 2024


Author: Lang Hames
Date: 2024-02-20T10:23:54-08:00
New Revision: c625b996527335c4fd6b6aa246655a993487e846

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

LOG: [ORC] Add SectCreateMaterializationUnit, llvm-jitlink -sectcreate option.

The SectCreateMaterializationUnit creates a LinkGraph with a single named
section containing a single named block whose content is given by a
MemoryBuffer. It is intended to support emulation of ld64's -sectcreate option.

Added: 
    llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h
    llvm/lib/ExecutionEngine/Orc/SectCreate.cpp
    llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt
    llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
    llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
    llvm/tools/llvm-jitlink/llvm-jitlink.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index f4d2f56c34d9d5..30a9383dc0bc15 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -1008,6 +1008,16 @@ class LinkGraph {
       : LinkGraph(std::move(Name), TT, SubtargetFeatures(), PointerSize,
                   Endianness, GetEdgeKindName) {}
 
+  LinkGraph(std::string Name, const Triple &TT,
+            GetEdgeKindNameFunction GetEdgeKindName)
+      : LinkGraph(std::move(Name), TT, SubtargetFeatures(),
+                  Triple::getArchPointerBitWidth(TT.getArch()) / 8,
+                  TT.isLittleEndian() ? endianness::little : endianness::big,
+                  GetEdgeKindName) {
+    assert(!(Triple::getArchPointerBitWidth(TT.getArch()) % 8) &&
+           "Arch bitwidth is not a multiple of 8");
+  }
+
   LinkGraph(const LinkGraph &) = delete;
   LinkGraph &operator=(const LinkGraph &) = delete;
   LinkGraph(LinkGraph &&) = delete;

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h b/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h
new file mode 100644
index 00000000000000..c4254249af69d3
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SectCreate.h
@@ -0,0 +1,61 @@
+//===---- SectCreate.h -- Emulates ld64's -sectcreate option ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Emulates ld64's -sectcreate option.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
+#define LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H
+
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+
+#include <utility>
+#include <vector>
+
+namespace llvm::orc {
+
+class SectCreateMaterializationUnit : public MaterializationUnit {
+public:
+  struct ExtraSymbolInfo {
+    JITSymbolFlags Flags;
+    size_t Offset = 0;
+  };
+
+  using ExtraSymbolsMap = DenseMap<SymbolStringPtr, ExtraSymbolInfo>;
+
+  SectCreateMaterializationUnit(
+      ObjectLinkingLayer &ObjLinkingLayer, std::string SectName, MemProt MP,
+      uint64_t Alignment, std::unique_ptr<MemoryBuffer> Data,
+      ExtraSymbolsMap ExtraSymbols = ExtraSymbolsMap())
+      : MaterializationUnit(getInterface(ExtraSymbols)),
+        ObjLinkingLayer(ObjLinkingLayer), SectName(std::move(SectName)), MP(MP),
+        Alignment(Alignment), Data(std::move(Data)),
+        ExtraSymbols(std::move(ExtraSymbols)) {}
+
+  StringRef getName() const override { return "SectCreate"; }
+
+  void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
+
+private:
+  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+
+  static Interface getInterface(const ExtraSymbolsMap &ExtraSymbols);
+
+  ObjectLinkingLayer &ObjLinkingLayer;
+  std::string SectName;
+  MemProt MP;
+  uint64_t Alignment;
+  std::unique_ptr<MemoryBuffer> Data;
+  ExtraSymbolsMap ExtraSymbols;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_SECTCREATE_H

diff  --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index fdb628ac84d435..f36605bbf03baf 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -41,6 +41,7 @@ add_llvm_component_library(LLVMOrcJIT
   OrcABISupport.cpp
   OrcV2CBindings.cpp
   RTDyldObjectLinkingLayer.cpp
+  SectCreate.cpp
   SimpleRemoteEPC.cpp
   Speculation.cpp
   SpeculateAnalyses.cpp

diff  --git a/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp b/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp
new file mode 100644
index 00000000000000..4f28b8bda529b9
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/SectCreate.cpp
@@ -0,0 +1,52 @@
+//===--------- SectCreate.cpp - Emulate ld64's -sectcreate option ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/SectCreate.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm::jitlink;
+
+namespace llvm::orc {
+
+void SectCreateMaterializationUnit::materialize(
+    std::unique_ptr<MaterializationResponsibility> R) {
+  auto G = std::make_unique<LinkGraph>(
+      "orc_sectcreate_" + SectName,
+      ObjLinkingLayer.getExecutionSession().getTargetTriple(),
+      getGenericEdgeKindName);
+
+  auto &Sect = G->createSection(SectName, MP);
+  auto Content = G->allocateContent(
+      ArrayRef<char>(Data->getBuffer().data(), Data->getBuffer().size()));
+  auto &B = G->createContentBlock(Sect, Content, ExecutorAddr(), Alignment, 0);
+
+  for (auto &[Name, Info] : ExtraSymbols) {
+    auto L = Info.Flags.isStrong() ? Linkage::Strong : Linkage::Weak;
+    auto S = Info.Flags.isExported() ? Scope::Default : Scope::Hidden;
+    G->addDefinedSymbol(B, Info.Offset, *Name, 0, L, S, Info.Flags.isCallable(),
+                        true);
+  }
+
+  ObjLinkingLayer.emit(std::move(R), std::move(G));
+}
+
+void SectCreateMaterializationUnit::discard(const JITDylib &JD,
+                                            const SymbolStringPtr &Name) {
+  ExtraSymbols.erase(Name);
+}
+
+MaterializationUnit::Interface SectCreateMaterializationUnit::getInterface(
+    const ExtraSymbolsMap &ExtraSymbols) {
+  SymbolFlagsMap SymbolFlags;
+  for (auto &[Name, Info] : ExtraSymbols)
+    SymbolFlags[Name] = Info.Flags;
+  return {std::move(SymbolFlags), nullptr};
+}
+
+} // End namespace llvm::orc.

diff  --git a/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt
new file mode 100644
index 00000000000000..bcaec87ab41ba7
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/Inputs/sectcreate-data.txt
@@ -0,0 +1 @@
+**ZZ
\ No newline at end of file

diff  --git a/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
new file mode 100644
index 00000000000000..244827196f485e
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
@@ -0,0 +1,8 @@
+# RUN: llc -filetype=obj -o %t.o %S/Inputs/main-ret-0.ll
+# RUN: llvm-jitlink -noexec \
+# RUN:   -sectcreate __data,%S/Inputs/sectcreate-data.txt:foo=0 \
+# RUN:   %t.o
+#
+# Use -sectcreate to create a section from a data file.
+
+# jitlink-check: *{4}foo = 0x2a2a5a5a
\ No newline at end of file

diff  --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 769ed17ac4cbd5..f6280779ded10f 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
 #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
+#include "llvm/ExecutionEngine/Orc/SectCreate.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
@@ -162,6 +163,12 @@ static cl::list<std::string>
             cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),
             cl::cat(JITLinkCategory));
 
+static cl::list<std::string>
+    SectCreate("sectcreate",
+               cl::desc("given <sectname>,<filename>[:<sym>=<offset>,...]  "
+                        "add the content of <filename> to <sectname>"),
+               cl::cat(JITLinkCategory));
+
 static cl::list<std::string> TestHarnesses("harness", cl::Positional,
                                            cl::desc("Test harness files"),
                                            cl::PositionalEatsArgs,
@@ -1666,6 +1673,57 @@ static Error addAliases(Session &S,
   return Error::success();
 }
 
+static Error addSectCreates(Session &S,
+                            const std::map<unsigned, JITDylib *> &IdxToJD) {
+  for (auto SCItr = SectCreate.begin(), SCEnd = SectCreate.end();
+       SCItr != SCEnd; ++SCItr) {
+
+    unsigned SCArgIdx = SectCreate.getPosition(SCItr - SectCreate.begin());
+    auto &JD = *std::prev(IdxToJD.lower_bound(SCArgIdx))->second;
+
+    StringRef SCArg(*SCItr);
+
+    auto [SectAndFileName, ExtraSymbolsString] = SCArg.split(':');
+    auto [SectName, FileName] = SectAndFileName.rsplit(',');
+    if (SectName.empty())
+      return make_error<StringError>("In -sectcreate=" + SCArg +
+                                         ", filename component cannot be empty",
+                                     inconvertibleErrorCode());
+    if (FileName.empty())
+      return make_error<StringError>("In -sectcreate=" + SCArg +
+                                         ", filename component cannot be empty",
+                                     inconvertibleErrorCode());
+
+    auto Content = MemoryBuffer::getFile(FileName);
+    if (!Content)
+      return createFileError(FileName, errorCodeToError(Content.getError()));
+
+    SectCreateMaterializationUnit::ExtraSymbolsMap ExtraSymbols;
+    while (!ExtraSymbolsString.empty()) {
+      StringRef NextSymPair;
+      std::tie(NextSymPair, ExtraSymbolsString) = ExtraSymbolsString.split(',');
+
+      auto [Sym, OffsetString] = NextSymPair.split('=');
+      size_t Offset;
+
+      if (OffsetString.getAsInteger(0, Offset))
+        return make_error<StringError>("In -sectcreate=" + SCArg + ", " +
+                                           OffsetString +
+                                           " is not a valid integer",
+                                       inconvertibleErrorCode());
+
+      ExtraSymbols[S.ES.intern(Sym)] = {JITSymbolFlags::Exported, Offset};
+    }
+
+    if (auto Err = JD.define(std::make_unique<SectCreateMaterializationUnit>(
+            S.ObjLayer, SectName.str(), MemProt::Read, 16, std::move(*Content),
+            std::move(ExtraSymbols))))
+      return Err;
+  }
+
+  return Error::success();
+}
+
 static Error addTestHarnesses(Session &S) {
   LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");
   for (auto HarnessFile : TestHarnesses) {
@@ -2016,6 +2074,9 @@ static Error addSessionInputs(Session &S) {
   if (auto Err = addAliases(S, IdxToJD))
     return Err;
 
+  if (auto Err = addSectCreates(S, IdxToJD))
+    return Err;
+
   if (!TestHarnesses.empty())
     if (auto Err = addTestHarnesses(S))
       return Err;


        


More information about the llvm-commits mailing list