[lld][Darwin] Add support for the -sectcreate option.

llvm-svn: 251183
This commit is contained in:
Lang Hames 2015-10-24 08:20:51 +00:00
parent 25ca34c727
commit b1b67f4daf
10 changed files with 152 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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">,

View File

@ -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) {

View File

@ -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

View File

@ -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);
}
};

View File

@ -0,0 +1 @@
hello

View File

@ -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