summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
Diffstat (limited to 'lld')
-rw-r--r--lld/include/lld/Core/DefinedAtom.h1
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h6
-rw-r--r--lld/lib/Core/DefinedAtom.cpp1
-rw-r--r--lld/lib/Driver/DarwinLdDriver.cpp18
-rw-r--r--lld/lib/Driver/DarwinLdOptions.td5
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp15
-rw-r--r--lld/lib/ReaderWriter/MachO/SectCreateFile.h94
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp1
-rw-r--r--lld/test/mach-o/Inputs/hw.raw_bytes1
-rw-r--r--lld/test/mach-o/sectcreate.yaml12
10 files changed, 152 insertions, 2 deletions
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h
index 6c6d1f9ef9b..e4d4488ccdc 100644
--- a/lld/include/lld/Core/DefinedAtom.h
+++ b/lld/include/lld/Core/DefinedAtom.h
@@ -151,6 +151,7 @@ public:
typeNoAlloc, // Identifies non allocatable sections [ELF]
typeGroupComdat, // Identifies a section group [ELF, COFF]
typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
+ typeSectCreate, // Created via the -sectcreate option [Darwin]
};
// Permission bits for atoms and segments. The order of these values are
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
index a3459693c7d..dc44d3f303f 100644
--- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -27,6 +27,7 @@ namespace mach_o {
class ArchHandler;
class MachODylibFile;
class MachOFile;
+class SectCreateFile;
}
class MachOLinkingContext : public LinkingContext {
@@ -272,6 +273,10 @@ public:
/// Add section alignment constraint on final layout.
void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
+ /// \brief Add a section based on a command-line sectcreate option.
+ void addSectCreateSection(StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content);
+
/// Returns true if specified section had alignment constraints.
bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
@@ -416,6 +421,7 @@ private:
llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
unsigned _orderFileEntries;
File *_flatNamespaceFile;
+ mach_o::SectCreateFile *_sectCreateFile = nullptr;
};
} // end namespace lld
diff --git a/lld/lib/Core/DefinedAtom.cpp b/lld/lib/Core/DefinedAtom.cpp
index b3f81ca65a9..f1d308088ed 100644
--- a/lld/lib/Core/DefinedAtom.cpp
+++ b/lld/lib/Core/DefinedAtom.cpp
@@ -76,6 +76,7 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeGnuLinkOnce:
case typeUnknown:
case typeTempLTO:
+ case typeSectCreate:
return permUnknown;
}
llvm_unreachable("unknown content type");
diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp
index 40a5a7174aa..cf018934e32 100644
--- a/lld/lib/Driver/DarwinLdDriver.cpp
+++ b/lld/lib/Driver/DarwinLdDriver.cpp
@@ -822,7 +822,7 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
}
}
- // Handle input files
+ // Handle input files and sectcreate.
for (auto &arg : parsedArgs) {
bool upward;
ErrorOr<StringRef> resolvedPath = StringRef();
@@ -876,6 +876,22 @@ bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
return false;
}
break;
+ case OPT_sectcreate: {
+ const char* seg = arg->getValue(0);
+ const char* sect = arg->getValue(1);
+ const char* fileName = arg->getValue(2);
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr =
+ MemoryBuffer::getFile(fileName);
+
+ if (!contentOrErr) {
+ diagnostics << "error: can't open -sectcreate file " << fileName << "\n";
+ return false;
+ }
+
+ ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr));
+ }
+ break;
}
}
diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td
index 6631ee9527b..cbf6ac1d4a4 100644
--- a/lld/lib/Driver/DarwinLdOptions.td
+++ b/lld/lib/Driver/DarwinLdOptions.td
@@ -177,7 +177,10 @@ def arch : Separate<["-"], "arch">,
HelpText<"Architecture to link">;
def sectalign : MultiArg<["-"], "sectalign", 3>,
MetaVarName<"<segname> <sectname> <alignment>">,
- HelpText<"alignment for segment/section">;
+ HelpText<"Alignment for segment/section">;
+def sectcreate : MultiArg<["-"], "sectcreate", 3>,
+ MetaVarName<"<segname> <sectname> <file>">,
+ HelpText<"Create section <segname>/<sectname> from contents of <file>">;
def image_base : Separate<["-"], "image_base">;
def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
def demangle : Flag<["-"], "demangle">,
diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 4031eb8840a..1c97c5a39d3 100644
--- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -13,6 +13,7 @@
#include "FlatNamespaceFile.h"
#include "MachONormalizedFile.h"
#include "MachOPasses.h"
+#include "SectCreateFile.h"
#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/PassManager.h"
#include "lld/Core/Reader.h"
@@ -749,6 +750,20 @@ void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
_sectAligns.push_back(entry);
}
+void MachOLinkingContext::addSectCreateSection(
+ StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content) {
+
+ if (!_sectCreateFile) {
+ auto sectCreateFile = llvm::make_unique<mach_o::SectCreateFile>();
+ _sectCreateFile = sectCreateFile.get();
+ getNodes().push_back(llvm::make_unique<FileNode>(std::move(sectCreateFile)));
+ }
+
+ assert(_sectCreateFile && "sectcreate file does not exist.");
+ _sectCreateFile->addSection(seg, sect, std::move(content));
+}
+
bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
uint16_t &align) const {
for (const SectionAlign &entry : _sectAligns) {
diff --git a/lld/lib/ReaderWriter/MachO/SectCreateFile.h b/lld/lib/ReaderWriter/MachO/SectCreateFile.h
new file mode 100644
index 00000000000..ea16e69ab3c
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/SectCreateFile.h
@@ -0,0 +1,94 @@
+//===---- lib/ReaderWriter/MachO/SectCreateFile.h ---------------*- c++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
+#define LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/Simple.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+
+namespace lld {
+namespace mach_o {
+
+//
+// A FlateNamespaceFile instance may be added as a resolution source of last
+// resort, depending on how -flat_namespace and -undefined are set.
+//
+class SectCreateFile : public File {
+public:
+
+ class SectCreateAtom : public SimpleDefinedAtom {
+ public:
+ SectCreateAtom(const File &file, StringRef segName, StringRef sectName,
+ std::unique_ptr<MemoryBuffer> content)
+ : SimpleDefinedAtom(file),
+ _combinedName((segName + "/" + sectName).str()),
+ _content(std::move(content)) {}
+
+ uint64_t size() const override { return _content->getBufferSize(); }
+
+ Scope scope() const override { return scopeGlobal; }
+
+ ContentType contentType() const override { return typeSectCreate; }
+
+ SectionChoice sectionChoice() const override { return sectionCustomRequired; }
+
+ StringRef customSectionName() const override { return _combinedName; }
+
+ DeadStripKind deadStrip() const override { return deadStripNever; }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ const uint8_t *data =
+ reinterpret_cast<const uint8_t*>(_content->getBufferStart());
+ return ArrayRef<uint8_t>(data, _content->getBufferSize());
+ }
+
+ StringRef segmentName() const { return _segName; }
+ StringRef sectionName() const { return _sectName; }
+
+ private:
+ std::string _combinedName;
+ StringRef _segName;
+ StringRef _sectName;
+ std::unique_ptr<MemoryBuffer> _content;
+ };
+
+ SectCreateFile() : File("sectcreate", kindObject) {}
+
+ void addSection(StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content) {
+ _definedAtoms.push_back(
+ new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
+ }
+
+ const AtomVector<DefinedAtom> &defined() const {
+ return _definedAtoms;
+ }
+
+ const AtomVector<UndefinedAtom> &undefined() const {
+ return _noUndefinedAtoms;
+ }
+
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const {
+ return _noSharedLibraryAtoms;
+ }
+
+ const AtomVector<AbsoluteAtom> &absolute() const {
+ return _noAbsoluteAtoms;
+ }
+
+private:
+ AtomVector<DefinedAtom> _definedAtoms;
+};
+
+} // namespace mach_o
+} // namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 182439ed07a..78c6797b713 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -437,6 +437,7 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
io.enumCase(value, "no-alloc", DefinedAtom::typeNoAlloc);
io.enumCase(value, "group-comdat", DefinedAtom::typeGroupComdat);
io.enumCase(value, "gnu-linkonce", DefinedAtom::typeGnuLinkOnce);
+ io.enumCase(value, "sectcreate", DefinedAtom::typeSectCreate);
}
};
diff --git a/lld/test/mach-o/Inputs/hw.raw_bytes b/lld/test/mach-o/Inputs/hw.raw_bytes
new file mode 100644
index 00000000000..ce013625030
--- /dev/null
+++ b/lld/test/mach-o/Inputs/hw.raw_bytes
@@ -0,0 +1 @@
+hello
diff --git a/lld/test/mach-o/sectcreate.yaml b/lld/test/mach-o/sectcreate.yaml
new file mode 100644
index 00000000000..51c59dc5f3d
--- /dev/null
+++ b/lld/test/mach-o/sectcreate.yaml
@@ -0,0 +1,12 @@
+# RUN: lld -flavor darwin -r -arch x86_64 -o %t -sectcreate __DATA __data \
+# RUN: %p/Inputs/hw.raw_bytes -print_atoms | FileCheck %s
+
+# CHECK: --- !native
+# CHECK: path: '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK: - scope: global
+# CHECK: type: sectcreate
+# CHECK: content: [ 68, 65, 6C, 6C, 6F, 0A ]
+# CHECK: section-choice: custom-required
+# CHECK: section-name: __DATA/__data
+# CHECK: dead-strip: never
OpenPOWER on IntegriCloud