[lld-macho] Handle command-line option -sectcreate SEG SECT FILE
authorGreg McGary <gkm@fb.com>
Tue, 11 Aug 2020 01:47:13 +0000 (18:47 -0700)
committerJez Ng <jezng@fb.com>
Tue, 11 Aug 2020 01:47:13 +0000 (18:47 -0700)
Handle command-line option `-sectcreate SEG SECT FILE`, which inputs a binary blob from `FILE` into `SEG,SECT`

Reviewed By: int3

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

lld/MachO/Driver.cpp
lld/MachO/InputFiles.cpp
lld/MachO/InputFiles.h
lld/MachO/Options.td
lld/test/MachO/sectcreate.s [new file with mode: 0644]

index d332acd..93b61fc 100644 (file)
@@ -495,6 +495,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
     case OPT_Z:
     case OPT_arch:
     case OPT_syslibroot:
+    case OPT_sectcreate:
       // handled elsewhere
       break;
     default:
@@ -524,6 +525,15 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
   createSyntheticSections();
   symtab->addDSOHandle(in.header);
 
+  for (opt::Arg *arg : args.filtered(OPT_sectcreate)) {
+    StringRef segName = arg->getValue(0);
+    StringRef sectName = arg->getValue(1);
+    StringRef fileName = arg->getValue(2);
+    Optional<MemoryBufferRef> buffer = readFile(fileName);
+    if (buffer)
+      inputFiles.push_back(make<OpaqueFile>(*buffer, segName, sectName));
+  }
+
   // Initialize InputSections.
   for (InputFile *file : inputFiles) {
     for (SubsectionMap &map : file->subsections) {
index f1afc18..28e138a 100644 (file)
@@ -301,6 +301,18 @@ void InputFile::parseSymbols(ArrayRef<structs::nlist_64> nList,
   }
 }
 
+OpaqueFile::OpaqueFile(MemoryBufferRef mb, StringRef segName,
+                       StringRef sectName)
+    : InputFile(OpaqueKind, mb) {
+  InputSection *isec = make<InputSection>();
+  isec->file = this;
+  isec->name = sectName.take_front(16);
+  isec->segname = segName.take_front(16);
+  const auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
+  isec->data = {buf, mb.getBufferSize()};
+  subsections.push_back({{0, isec}});
+}
+
 ObjFile::ObjFile(MemoryBufferRef mb) : InputFile(ObjKind, mb) {
   auto *buf = reinterpret_cast<const uint8_t *>(mb.getBufferStart());
   auto *hdr = reinterpret_cast<const mach_header_64 *>(mb.getBufferStart());
index bc5ad86..2aa0301 100644 (file)
@@ -40,6 +40,7 @@ public:
     ObjKind,
     DylibKind,
     ArchiveKind,
+    OpaqueKind,
   };
 
   virtual ~InputFile() = default;
@@ -72,6 +73,14 @@ public:
   static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
 };
 
+// command-line -sectcreate file
+class OpaqueFile : public InputFile {
+public:
+  explicit OpaqueFile(MemoryBufferRef mb, StringRef segName,
+                      StringRef sectName);
+  static bool classof(const InputFile *f) { return f->kind() == OpaqueKind; }
+};
+
 // .dylib file
 class DylibFile : public InputFile {
 public:
index c27ca0d..b606ff5 100644 (file)
@@ -156,7 +156,6 @@ def grp_content : OptionGroup<"content">, HelpText<"ADDITIONAL CONTENT">;
 def sectcreate : MultiArg<["-"], "sectcreate", 3>,
      MetaVarName<"<segment> <section> <file>">,
      HelpText<"Create <section> in <segment> from the contents of <file>">,
-     Flags<[HelpHidden]>,
      Group<grp_content>;
 def segcreate : MultiArg<["-"], "segcreate", 3>,
      MetaVarName<"<segment> <section> <file>">,
diff --git a/lld/test/MachO/sectcreate.s b/lld/test/MachO/sectcreate.s
new file mode 100644 (file)
index 0000000..ac561d8
--- /dev/null
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+# RUN: echo "-sectcreate 1.1" >%t1
+# RUN: echo "-sectcreate 1.2" >%t2
+# RUN: echo "-sectcreate 2" >%t3
+# RUN: lld -flavor darwinnew -Z \
+# RUN:     -sectcreate SEG SEC1 %t1 \
+# RUN:     -sectcreate SEG SEC2 %t3 \
+# RUN:     -sectcreate SEG SEC1 %t2 \
+# RUN:     -o %t %t.o
+# RUN: llvm-objdump -s %t | FileCheck %s
+
+# CHECK: Contents of section __text:
+# CHECK: Contents of section __data:
+# CHECK: my string!.
+# CHECK: Contents of section SEC1:
+# CHECK: -sectcreate 1.1.
+# CHECK: -sectcreate 1.2.
+# CHECK: Contents of section SEC2:
+# CHECK: -sectcreate 2.
+
+.text
+.global _main
+_main:
+  mov $0, %eax
+  ret
+
+.data
+.global my_string
+my_string:
+  .string "my string!"