forked from OSchip/llvm-project
[mach-o] enable mach-o and native yaml to be intermixed
The main goal of this patch is to allow "mach-o encoded as yaml" and "native encoded as yaml" documents to be intermixed. They are distinguished via yaml tags at the start of the document. This will enable all mach-o test cases to be written using yaml instead of checking in object files. The Registry was extend to allow yaml tag handlers to be registered. The mach-o Reader adds a yaml tag handler for the tag "!mach-o". Additionally, this patch fixes some buffer ownership issues. When parsing mach-o binaries, the mach-o atoms can have pointers back into the memory mapped .o file. But with yaml encoded mach-o, name and content are ephemeral, so a copyRefs parameter was added to cause the mach-o atoms to make their own copy. llvm-svn: 198986
This commit is contained in:
parent
976d94b834
commit
6edd722a2c
|
@ -21,6 +21,12 @@
|
|||
|
||||
using llvm::sys::fs::file_magic;
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
class IO;
|
||||
}
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
class ELFLinkingContext;
|
||||
class File;
|
||||
|
@ -54,6 +60,29 @@ public:
|
|||
std::vector<std::unique_ptr<File>> &result) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/// \brief An abstract class for handling alternate yaml representations
|
||||
/// of object files.
|
||||
///
|
||||
/// The YAML syntax allows "tags" which are used to specify the type of
|
||||
/// the YAML node. In lld, top level YAML documents can be in many YAML
|
||||
/// representations (e.g mach-o encoded as yaml, etc). A tag is used to
|
||||
/// specify which representation is used in the following YAML document.
|
||||
/// To work, there must be a YamlIOTaggedDocumentHandler registered that
|
||||
/// handles each tag type.
|
||||
class YamlIOTaggedDocumentHandler {
|
||||
public:
|
||||
virtual ~YamlIOTaggedDocumentHandler();
|
||||
|
||||
/// This method is called on each registered YamlIOTaggedDocumentHandler
|
||||
/// until one returns true. If the subclass handles tag type !xyz, then
|
||||
/// this method should call io.mapTag("!xzy") to see if that is the current
|
||||
/// document type, and if so, process the rest of the document using
|
||||
/// YAML I/O, then convert the result into an lld::File* and return it.
|
||||
virtual bool handledDocTag(llvm::yaml::IO &io, const lld::File *&f) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/// A registry to hold the list of currently registered Readers and
|
||||
/// tables which map Reference kind values to strings.
|
||||
/// The linker does not directly invoke Readers. Instead, it registers
|
||||
|
@ -79,6 +108,10 @@ public:
|
|||
bool referenceKindToString(Reference::KindNamespace ns, Reference::KindArch a,
|
||||
Reference::KindValue value, StringRef &) const;
|
||||
|
||||
/// Walk the list of registered tag handlers and have the one that handles
|
||||
/// the current document type process the yaml into an lld::File*.
|
||||
bool handleTaggedDoc(llvm::yaml::IO &io, const lld::File *&file) const;
|
||||
|
||||
// These methods are called to dynamically add support for various file
|
||||
// formats. The methods are also implemented in the appropriate lib*.a
|
||||
// library, so that the code for handling a format is only linked in, if this
|
||||
|
@ -108,6 +141,7 @@ public:
|
|||
void addKindTable(Reference::KindNamespace ns, Reference::KindArch arch,
|
||||
const KindStrings array[]);
|
||||
|
||||
|
||||
private:
|
||||
struct KindEntry {
|
||||
Reference::KindNamespace ns;
|
||||
|
@ -116,9 +150,11 @@ private:
|
|||
};
|
||||
|
||||
void add(std::unique_ptr<Reader>);
|
||||
void add(std::unique_ptr<YamlIOTaggedDocumentHandler>);
|
||||
|
||||
std::vector<std::unique_ptr<Reader>> _readers;
|
||||
std::vector<KindEntry> _kindEntries;
|
||||
std::vector<std::unique_ptr<Reader>> _readers;
|
||||
std::vector<std::unique_ptr<YamlIOTaggedDocumentHandler>> _yamlHandlers;
|
||||
std::vector<KindEntry> _kindEntries;
|
||||
};
|
||||
|
||||
// Utilities for building a KindString table. For instance:
|
||||
|
|
|
@ -39,6 +39,7 @@ struct YamlContext {
|
|||
const Registry *_registry;
|
||||
File *_file;
|
||||
NormalizedFile *_normalizeMachOFile;
|
||||
StringRef _path;
|
||||
};
|
||||
|
||||
} // end namespace lld
|
||||
|
|
|
@ -21,7 +21,16 @@ class MachOFile : public SimpleFile {
|
|||
public:
|
||||
MachOFile(StringRef path) : SimpleFile(path) {}
|
||||
|
||||
void addDefinedAtom(StringRef name, ArrayRef<uint8_t> content) {
|
||||
void addDefinedAtom(StringRef name, ArrayRef<uint8_t> content, bool cpyRefs) {
|
||||
if (cpyRefs) {
|
||||
// Make a copy of the atom's name and content that is owned by this file.
|
||||
char *s = _allocator.Allocate<char>(name.size());
|
||||
memcpy(s, name.data(), name.size());
|
||||
name = StringRef(s, name.size());
|
||||
uint8_t *bytes = _allocator.Allocate<uint8_t>(content.size());
|
||||
memcpy(bytes, content.data(), content.size());
|
||||
content = llvm::makeArrayRef(bytes, content.size());
|
||||
}
|
||||
MachODefinedAtom *atom =
|
||||
new (_allocator) MachODefinedAtom(*this, name, content);
|
||||
addAtom(*atom);
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/MachO.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
|
@ -52,6 +53,7 @@
|
|||
#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
|
||||
#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
|
||||
|
||||
using llvm::BumpPtrAllocator;
|
||||
using llvm::yaml::Hex64;
|
||||
using llvm::yaml::Hex32;
|
||||
using llvm::yaml::Hex8;
|
||||
|
@ -113,7 +115,7 @@ struct Section {
|
|||
SectionAttr attributes;
|
||||
uint32_t alignment;
|
||||
Hex64 address;
|
||||
std::vector<uint8_t> content;
|
||||
ArrayRef<uint8_t> content;
|
||||
Relocations relocations;
|
||||
IndirectSymbols indirectSymbols;
|
||||
};
|
||||
|
@ -235,6 +237,9 @@ struct NormalizedFile {
|
|||
// split-seg-info
|
||||
// function-starts
|
||||
// data-in-code
|
||||
|
||||
// For any allocations in this struct which need to be owned by this struct.
|
||||
BumpPtrAllocator ownedAllocations;
|
||||
};
|
||||
|
||||
|
||||
|
@ -260,15 +265,22 @@ writeYaml(const NormalizedFile &file, raw_ostream &out);
|
|||
|
||||
/// Takes in-memory normalized dylib or object and parses it into lld::File
|
||||
ErrorOr<std::unique_ptr<lld::File>>
|
||||
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path);
|
||||
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
|
||||
bool copyRefs);
|
||||
|
||||
/// Takes atoms and generates a normalized macho-o view.
|
||||
ErrorOr<std::unique_ptr<NormalizedFile>>
|
||||
normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
|
||||
|
||||
|
||||
|
||||
} // namespace normalized
|
||||
|
||||
/// Class for interfacing mach-o yaml files into generic yaml parsing
|
||||
class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
|
||||
bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mach_o
|
||||
} // namespace lld
|
||||
|
||||
|
|
|
@ -175,12 +175,12 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb) {
|
|||
section.attributes = read32(swap, sect->flags) & SECTION_ATTRIBUTES;
|
||||
section.alignment = read32(swap, sect->align);
|
||||
section.address = read64(swap, sect->addr);
|
||||
const char *content = mb->getBufferStart()
|
||||
const uint8_t *content = (uint8_t *)mb->getBufferStart()
|
||||
+ read32(swap, sect->offset);
|
||||
size_t contentSize = read64(swap, sect->size);
|
||||
// Note: this assign() is copying the content bytes. Ideally,
|
||||
// we can use a custom allocator for vector to avoid the copy.
|
||||
section.content.assign(content, content+contentSize);
|
||||
section.content = llvm::makeArrayRef(content, contentSize);
|
||||
appendRelocations(section.relocations, mb->getBuffer(),
|
||||
swap, isBigEndianArch, read32(swap, sect->reloff),
|
||||
read32(swap, sect->nreloc));
|
||||
|
@ -210,12 +210,12 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb) {
|
|||
section.attributes = read32(swap, sect->flags) & SECTION_ATTRIBUTES;
|
||||
section.alignment = read32(swap, sect->align);
|
||||
section.address = read32(swap, sect->addr);
|
||||
const char *content = mb->getBufferStart()
|
||||
const uint8_t *content = (uint8_t *)mb->getBufferStart()
|
||||
+ read32(swap, sect->offset);
|
||||
size_t contentSize = read32(swap, sect->size);
|
||||
// Note: this assign() is copying the content bytes. Ideally,
|
||||
// we can use a custom allocator for vector to avoid the copy.
|
||||
section.content.assign(content, content+contentSize);
|
||||
section.content = llvm::makeArrayRef(content, contentSize);
|
||||
appendRelocations(section.relocations, mb->getBuffer(),
|
||||
swap, isBigEndianArch, read32(swap, sect->reloff),
|
||||
read32(swap, sect->nreloc));
|
||||
|
@ -328,6 +328,8 @@ void Registry::addSupportMachOObjects(StringRef archName) {
|
|||
default:
|
||||
llvm_unreachable("mach-o arch not supported");
|
||||
}
|
||||
add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
|
||||
new mach_o::MachOYamlIOTaggedDocumentHandler()));
|
||||
}
|
||||
|
||||
} // namespace lld
|
||||
|
|
|
@ -422,8 +422,8 @@ void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
|
|||
si->normalizedSectionIndex = file.sections.size()-1;
|
||||
// Copy content from atoms to content buffer for section.
|
||||
// FIXME: zerofill atoms/sections should not take up content space.
|
||||
normSect->content.resize(si->size);
|
||||
uint8_t *sectionContent = normSect->content.data();
|
||||
uint8_t *sectionContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
|
||||
normSect->content = llvm::makeArrayRef(sectionContent, si->size);
|
||||
for (AtomInfo &ai : si->atomsAndOffsets) {
|
||||
// Copy raw bytes.
|
||||
uint8_t *atomContent = reinterpret_cast<uint8_t*>
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace lld {
|
|||
namespace mach_o {
|
||||
namespace normalized {
|
||||
|
||||
static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile,
|
||||
static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile,
|
||||
const Symbol &symbol) {
|
||||
uint64_t symbolAddr = symbol.value;
|
||||
uint8_t symbolSectionIndex = symbol.sect;
|
||||
|
@ -54,18 +54,18 @@ static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile,
|
|||
}
|
||||
|
||||
static ErrorOr<std::unique_ptr<lld::File>>
|
||||
normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
|
||||
normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
|
||||
bool copyRefs) {
|
||||
std::unique_ptr<MachOFile> file(new MachOFile(path));
|
||||
|
||||
for (const Symbol &sym : normalizedFile.globalSymbols) {
|
||||
for (const Symbol &sym : normalizedFile.globalSymbols) {
|
||||
// Mach-O symbol table does have size in it, so need to scan ahead
|
||||
// to find symbol with next highest address.
|
||||
const Section §ion = normalizedFile.sections[sym.sect - 1];
|
||||
uint64_t offset = sym.value - section.address;
|
||||
uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value;
|
||||
ArrayRef<uint8_t> atomContent = llvm::makeArrayRef(§ion.content[offset],
|
||||
size);
|
||||
file->addDefinedAtom(sym.name, atomContent);
|
||||
ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
|
||||
file->addDefinedAtom(sym.name, atomContent, copyRefs);
|
||||
}
|
||||
|
||||
assert(normalizedFile.localSymbols.empty() &&
|
||||
|
@ -77,10 +77,11 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
|
|||
}
|
||||
|
||||
ErrorOr<std::unique_ptr<lld::File>>
|
||||
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
|
||||
normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
|
||||
bool copyRefs) {
|
||||
switch (normalizedFile.fileType) {
|
||||
case MH_OBJECT:
|
||||
return normalizedObjectToAtoms(normalizedFile, path);
|
||||
return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
|
||||
default:
|
||||
llvm_unreachable("unhandled MachO file type!");
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ struct SequenceTraits< ContentBytes > {
|
|||
static const bool flow = true;
|
||||
};
|
||||
|
||||
// The indirect symbols for a section is represented as a flow sequence
|
||||
// The indirect symbols for a section is represented as a flow sequence
|
||||
// of numbers (symbol table indexes).
|
||||
template<>
|
||||
struct SequenceTraits< IndirectSymbols > {
|
||||
|
@ -279,30 +279,36 @@ struct MappingTraits<Section> {
|
|||
io.mapOptional("attributes", sect.attributes);
|
||||
io.mapOptional("alignment", sect.alignment, 0U);
|
||||
io.mapRequired("address", sect.address);
|
||||
MappingNormalization<NormalizedContent, std::vector<uint8_t>> content(
|
||||
MappingNormalization<NormalizedContent, ArrayRef<uint8_t>> content(
|
||||
io, sect.content);
|
||||
io.mapOptional("content", content->normalizedContent);
|
||||
io.mapOptional("content", content->_normalizedContent);
|
||||
io.mapOptional("relocations", sect.relocations);
|
||||
io.mapOptional("indirect-syms", sect.indirectSymbols);
|
||||
}
|
||||
|
||||
// FIXME: It would be good if we could remove this, so we don't need to copy
|
||||
// the content data.
|
||||
struct NormalizedContent {
|
||||
NormalizedContent(IO &) {}
|
||||
NormalizedContent(IO &, std::vector<uint8_t> content) {
|
||||
NormalizedContent(IO &io) : _io(io) {}
|
||||
NormalizedContent(IO &io, ArrayRef<uint8_t> content) : _io(io) {
|
||||
// When writing yaml, copy content byte array to Hex8 vector.
|
||||
for (auto &c : content) {
|
||||
normalizedContent.push_back(c);
|
||||
_normalizedContent.push_back(c);
|
||||
}
|
||||
}
|
||||
std::vector<uint8_t> denormalize(IO &) {
|
||||
std::vector<uint8_t> content;
|
||||
for (auto &c : normalizedContent) {
|
||||
content.push_back(c);
|
||||
}
|
||||
return content;
|
||||
ArrayRef<uint8_t> denormalize(IO &io) {
|
||||
// When reading yaml, allocate byte array owned by NormalizedFile and
|
||||
// copy Hex8 vector to byte array.
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
NormalizedFile *file = info->_normalizeMachOFile;
|
||||
assert(file != nullptr);
|
||||
size_t size = _normalizedContent.size();
|
||||
uint8_t *bytes = file->ownedAllocations.Allocate<uint8_t>(size);
|
||||
std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes);
|
||||
return makeArrayRef(bytes, size);
|
||||
}
|
||||
ContentBytes normalizedContent;
|
||||
|
||||
IO &_io;
|
||||
ContentBytes _normalizedContent;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -612,10 +618,37 @@ struct MappingTraits<NormalizedFile> {
|
|||
|
||||
namespace lld {
|
||||
namespace mach_o {
|
||||
|
||||
/// Handles !mach-o tagged yaml documents.
|
||||
bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
|
||||
const lld::File *&file) const {
|
||||
if (!io.mapTag("!mach-o"))
|
||||
return false;
|
||||
// Step 1: parse yaml into normalized mach-o struct.
|
||||
NormalizedFile nf;
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
assert(info->_normalizeMachOFile == nullptr);
|
||||
info->_normalizeMachOFile = &nf;
|
||||
MappingTraits<NormalizedFile>::mapping(io, nf);
|
||||
// Step 2: parse normalized mach-o struct into atoms.
|
||||
ErrorOr<std::unique_ptr<lld::File>> foe = normalizedToAtoms(nf, info->_path,
|
||||
true);
|
||||
if (foe) {
|
||||
// Transfer ownership to "out" File parameter.
|
||||
std::unique_ptr<lld::File> f = std::move(foe.get());
|
||||
file = f.release();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace normalized {
|
||||
|
||||
/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
|
||||
ErrorOr<std::unique_ptr<NormalizedFile>>
|
||||
ErrorOr<std::unique_ptr<NormalizedFile>>
|
||||
readYaml(std::unique_ptr<MemoryBuffer> &mb) {
|
||||
// Make empty NormalizedFile.
|
||||
std::unique_ptr<NormalizedFile> f(new NormalizedFile());
|
||||
|
@ -638,7 +671,7 @@ readYaml(std::unique_ptr<MemoryBuffer> &mb) {
|
|||
|
||||
|
||||
/// Writes a yaml encoded mach-o files from an in-memory normalized view.
|
||||
error_code
|
||||
error_code
|
||||
writeYaml(const NormalizedFile &file, raw_ostream &out) {
|
||||
// YAML I/O is not const aware, so need to cast away ;-(
|
||||
NormalizedFile *f = const_cast<NormalizedFile*>(&file);
|
||||
|
|
|
@ -21,10 +21,18 @@ namespace lld {
|
|||
Reader::~Reader() {
|
||||
}
|
||||
|
||||
|
||||
YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() { }
|
||||
|
||||
|
||||
void Registry::add(std::unique_ptr<Reader> reader) {
|
||||
_readers.push_back(std::move(reader));
|
||||
}
|
||||
|
||||
void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
|
||||
_yamlHandlers.push_back(std::move(handler));
|
||||
}
|
||||
|
||||
error_code
|
||||
Registry::parseFile(std::unique_ptr<MemoryBuffer> &mb,
|
||||
std::vector<std::unique_ptr<File>> &result) const {
|
||||
|
@ -56,6 +64,16 @@ Registry::Registry() {
|
|||
kindStrings);
|
||||
}
|
||||
|
||||
bool Registry::handleTaggedDoc(llvm::yaml::IO &io,
|
||||
const lld::File *&file) const {
|
||||
for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers) {
|
||||
if (h->handledDocTag(io, file))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Registry::addKindTable(Reference::KindNamespace ns,
|
||||
Reference::KindArch arch,
|
||||
const KindStrings array[]) {
|
||||
|
|
|
@ -664,24 +664,15 @@ template <> struct MappingTraits<const lld::File *> {
|
|||
};
|
||||
|
||||
static void mapping(IO &io, const lld::File *&file) {
|
||||
// We only support writing atom based YAML
|
||||
FileKinds kind = fileKindObjectAtoms;
|
||||
// If reading, peek ahead to see what kind of file this is.
|
||||
io.mapOptional("kind", kind, fileKindObjectAtoms);
|
||||
switch (kind) {
|
||||
case fileKindObjectAtoms:
|
||||
YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
|
||||
assert(info != nullptr);
|
||||
// Let any register tag handler process this.
|
||||
if (info->_registry && info->_registry->handleTaggedDoc(io, file))
|
||||
return;
|
||||
// If no registered handler claims this tag and there is no tag,
|
||||
// grandfather in as "!native".
|
||||
if (io.mapTag("!native", true) || io.mapTag("tag:yaml.org,2002:map"))
|
||||
mappingAtoms(io, file);
|
||||
break;
|
||||
case fileKindArchive:
|
||||
mappingArchive(io, file);
|
||||
break;
|
||||
case fileKindObjectELF:
|
||||
case fileKindObjectMachO:
|
||||
// Eventually we will have an external function to call, similar
|
||||
// to mappingAtoms() and mappingArchive() but implememented
|
||||
// with coresponding file format code.
|
||||
llvm_unreachable("section based YAML not supported yet");
|
||||
}
|
||||
}
|
||||
|
||||
static void mappingAtoms(IO &io, const lld::File *&file) {
|
||||
|
@ -1236,6 +1227,31 @@ private:
|
|||
|
||||
namespace {
|
||||
|
||||
/// Handles !native tagged yaml documents.
|
||||
class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
|
||||
bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const {
|
||||
if (io.mapTag("!native")) {
|
||||
MappingTraits<const lld::File *>::mappingAtoms(io, file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Handles !archive tagged yaml documents.
|
||||
class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
|
||||
bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const {
|
||||
if (io.mapTag("!archive")) {
|
||||
MappingTraits<const lld::File *>::mappingArchive(io, file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class YAMLReader : public Reader {
|
||||
public:
|
||||
YAMLReader(const Registry ®istry) : _registry(registry) {}
|
||||
|
@ -1257,6 +1273,7 @@ public:
|
|||
// Create YAML Input Reader.
|
||||
YamlContext yamlContext;
|
||||
yamlContext._registry = &_registry;
|
||||
yamlContext._path = mb->getBufferIdentifier();
|
||||
llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
|
||||
|
||||
// Fill vector with File objects created by parsing yaml.
|
||||
|
@ -1283,6 +1300,10 @@ private:
|
|||
|
||||
void Registry::addSupportYamlFiles() {
|
||||
add(std::unique_ptr<Reader>(new YAMLReader(*this)));
|
||||
add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
|
||||
new NativeYamlIOTaggedDocumentHandler()));
|
||||
add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
|
||||
new ArchiveYamlIOTaggedDocumentHandler()));
|
||||
}
|
||||
|
||||
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# all atoms in select archive members.
|
||||
#
|
||||
|
||||
---
|
||||
--- !native
|
||||
defined-atoms:
|
||||
- name: foo
|
||||
type: code
|
||||
|
@ -13,11 +13,10 @@ defined-atoms:
|
|||
undefined-atoms:
|
||||
- name: bar
|
||||
|
||||
---
|
||||
kind: archive
|
||||
--- !archive
|
||||
members:
|
||||
- name: bar.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: bar
|
||||
scope: global
|
||||
|
@ -27,7 +26,7 @@ members:
|
|||
type: code
|
||||
|
||||
- name: baz.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: baz
|
||||
scope: global
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Tests that an undefine in one archive can force a load from another archive.
|
||||
#
|
||||
|
||||
---
|
||||
--- !native
|
||||
defined-atoms:
|
||||
- name: foo
|
||||
type: code
|
||||
|
@ -12,11 +12,10 @@ defined-atoms:
|
|||
undefined-atoms:
|
||||
- name: bar1
|
||||
|
||||
---
|
||||
kind: archive
|
||||
--- !archive
|
||||
members:
|
||||
- name: bar1.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: bar1
|
||||
scope: global
|
||||
|
@ -29,7 +28,7 @@ members:
|
|||
- name: baz1
|
||||
|
||||
- name: bar2.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: bar2
|
||||
scope: global
|
||||
|
@ -38,11 +37,10 @@ members:
|
|||
- name: bar2b
|
||||
type: code
|
||||
|
||||
---
|
||||
kind: archive
|
||||
--- !archive
|
||||
members:
|
||||
- name: baz1.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: baz1
|
||||
scope: global
|
||||
|
@ -52,7 +50,7 @@ members:
|
|||
type: code
|
||||
|
||||
- name: baz2.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: baz2
|
||||
scope: global
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# does not search.
|
||||
#
|
||||
|
||||
---
|
||||
--- !native
|
||||
defined-atoms:
|
||||
- name: foo
|
||||
type: code
|
||||
|
@ -17,11 +17,10 @@ defined-atoms:
|
|||
type: zero-fill
|
||||
merge: as-tentative
|
||||
|
||||
---
|
||||
kind: archive
|
||||
--- !archive
|
||||
members:
|
||||
- name: bar.o
|
||||
content:
|
||||
content: !native
|
||||
defined-atoms:
|
||||
- name: bar
|
||||
scope: global
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Test that hello-world can be linked into a mach-o executable
|
||||
#
|
||||
|
||||
--- !atoms
|
||||
--- !native
|
||||
defined-atoms:
|
||||
- name: _main
|
||||
type: code
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t && \
|
||||
# RUN: llvm-nm %t | FileCheck %s
|
||||
#
|
||||
# Test a mix of atoms and mach-o both encoded in yaml
|
||||
#
|
||||
|
||||
--- !native
|
||||
defined-atoms:
|
||||
- name: _main
|
||||
type: code
|
||||
scope: global
|
||||
content: [ 55, 48, 89, E5, 30, C0, E8, 00,
|
||||
00, 00, 00, 31, C0, 5D, C3 ]
|
||||
references:
|
||||
- offset: 7
|
||||
kind: X86_64_RELOC_BRANCH
|
||||
target: _foo
|
||||
|
||||
undefined-atoms:
|
||||
- name: _foo
|
||||
|
||||
|
||||
--- !mach-o
|
||||
arch: x86_64
|
||||
file-type: MH_OBJECT
|
||||
sections:
|
||||
- segment: __TEXT
|
||||
section: __text
|
||||
type: S_REGULAR
|
||||
attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
|
||||
address: 0
|
||||
content: [ 0xC3 ]
|
||||
global-symbols:
|
||||
- name: _foo
|
||||
type: N_SECT
|
||||
scope: [ N_EXT ]
|
||||
sect: 1
|
||||
desc: [ ]
|
||||
value: 0
|
||||
|
||||
...
|
||||
|
||||
# CHECK: {{[0-9a-f]+}} T _foo
|
||||
# CHECK: {{[0-9a-f]+}} T _main
|
|
@ -139,7 +139,7 @@ TEST(BinaryWriterTest, obj_relocs_x86_64) {
|
|||
0x05, 0xfc, 0xff, 0xff, 0xff, 0x78, 0x56, 0x34,
|
||||
0x12, 0x48, 0x8b, 0x3d, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
text.content.assign(textBytes, textBytes+sizeof(textBytes));
|
||||
text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
|
||||
text.relocations.push_back(makeReloc(0x01, false, true, X86_64_RELOC_BRANCH, 1));
|
||||
text.relocations.push_back(makeReloc(0x08, false, true, X86_64_RELOC_GOT_LOAD, 1));
|
||||
text.relocations.push_back(makeReloc(0x0E, false, true, X86_64_RELOC_GOT, 1));
|
||||
|
@ -252,7 +252,7 @@ TEST(BinaryWriterTest, obj_relocs_x86) {
|
|||
0x00, 0x00, 0x8b, 0xb0, 0xfb, 0xff, 0xff, 0xff,
|
||||
0x8b, 0x80, 0x11, 0x00, 0x00, 0x00 };
|
||||
|
||||
text.content.assign(textBytes, textBytes+sizeof(textBytes));
|
||||
text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
|
||||
text.relocations.push_back(makeReloc(0x01, true, true, GENERIC_RELOC_VANILLA, 0));
|
||||
text.relocations.push_back(makeReloc(0x06, false, true, GENERIC_RELOC_VANILLA, 0));
|
||||
text.relocations.push_back(makeScatReloc(0x0c, GENERIC_RELOC_LOCAL_SECTDIFF, 0));
|
||||
|
@ -361,7 +361,7 @@ TEST(BinaryWriterTest, obj_relocs_armv7) {
|
|||
0xc0, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xbf };
|
||||
|
||||
text.content.assign(textBytes, textBytes+sizeof(textBytes));
|
||||
text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
|
||||
text.relocations.push_back(makeReloc(0x00, true, true,
|
||||
ARM_THUMB_RELOC_BR22, 2));
|
||||
text.relocations.push_back(makeScatReloc(0x04,
|
||||
|
@ -492,7 +492,7 @@ TEST(BinaryWriterTest, obj_relocs_ppc) {
|
|||
0x80, 0x42, 0x00, 0x28, 0x80, 0x63, 0x00, 0x28,
|
||||
0x60, 0x00, 0x00, 0x00 };
|
||||
|
||||
text.content.assign(textBytes, textBytes+sizeof(textBytes));
|
||||
text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
|
||||
text.relocations.push_back(makeReloc(0x00, true, true,
|
||||
PPC_RELOC_BR24, 2));
|
||||
text.relocations.push_back(makeReloc(0x04, true, true,
|
||||
|
|
|
@ -23,7 +23,8 @@ using namespace llvm::MachO;
|
|||
TEST(ToAtomsTest, empty_obj_x86_64) {
|
||||
NormalizedFile f;
|
||||
f.arch = lld::MachOLinkingContext::arch_x86_64;
|
||||
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "");
|
||||
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "",
|
||||
false);
|
||||
EXPECT_FALSE(!atom_f);
|
||||
EXPECT_EQ(0U, (*atom_f)->defined().size());
|
||||
}
|
||||
|
@ -34,8 +35,7 @@ TEST(ToAtomsTest, basic_obj_x86_64) {
|
|||
Section textSection;
|
||||
static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3 };
|
||||
const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]);
|
||||
textSection.content.insert(textSection.content.begin(), contentBytes,
|
||||
&contentBytes[contentSize]);
|
||||
textSection.content = llvm::makeArrayRef(contentBytes, contentSize);
|
||||
f.sections.push_back(textSection);
|
||||
Symbol fooSymbol;
|
||||
fooSymbol.name = "_foo";
|
||||
|
@ -50,7 +50,8 @@ TEST(ToAtomsTest, basic_obj_x86_64) {
|
|||
barSymbol.value = 2;
|
||||
f.globalSymbols.push_back(barSymbol);
|
||||
|
||||
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "");
|
||||
ErrorOr<std::unique_ptr<const lld::File>> atom_f = normalizedToAtoms(f, "",
|
||||
false);
|
||||
EXPECT_FALSE(!atom_f);
|
||||
const lld::File &file = **atom_f;
|
||||
EXPECT_EQ(2U, file.defined().size());
|
||||
|
|
Loading…
Reference in New Issue