From 6edd722a2cff95551808ee02e69c8882633f6283 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Sat, 11 Jan 2014 01:07:43 +0000 Subject: [PATCH] [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 --- lld/include/lld/ReaderWriter/Reader.h | 40 ++++++++++- lld/include/lld/ReaderWriter/YamlContext.h | 1 + lld/lib/ReaderWriter/MachO/File.h | 11 ++- .../ReaderWriter/MachO/MachONormalizedFile.h | 18 ++++- .../MachO/MachONormalizedFileBinaryReader.cpp | 10 +-- .../MachO/MachONormalizedFileFromAtoms.cpp | 4 +- .../MachO/MachONormalizedFileToAtoms.cpp | 17 ++--- .../MachO/MachONormalizedFileYAML.cpp | 67 ++++++++++++++----- lld/lib/ReaderWriter/Reader.cpp | 18 +++++ .../ReaderWriter/YAML/ReaderWriterYAML.cpp | 55 ++++++++++----- lld/test/core/archive-basic.objtxt | 9 ++- lld/test/core/archive-chain.objtxt | 16 ++--- lld/test/core/archive-tentdef-search.objtxt | 7 +- lld/test/darwin/hello-world.objtxt | 2 +- lld/test/darwin/native-and-mach-o.objtxt | 44 ++++++++++++ .../MachONormalizedFileBinaryWriterTests.cpp | 8 +-- .../MachONormalizedFileToAtomsTests.cpp | 9 +-- 17 files changed, 255 insertions(+), 81 deletions(-) create mode 100644 lld/test/darwin/native-and-mach-o.objtxt diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h index f284eab5b47e..31404d346cb7 100644 --- a/lld/include/lld/ReaderWriter/Reader.h +++ b/lld/include/lld/ReaderWriter/Reader.h @@ -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> &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); + void add(std::unique_ptr); - std::vector> _readers; - std::vector _kindEntries; + std::vector> _readers; + std::vector> _yamlHandlers; + std::vector _kindEntries; }; // Utilities for building a KindString table. For instance: diff --git a/lld/include/lld/ReaderWriter/YamlContext.h b/lld/include/lld/ReaderWriter/YamlContext.h index fa39185f70f0..9d01ea17cce9 100644 --- a/lld/include/lld/ReaderWriter/YamlContext.h +++ b/lld/include/lld/ReaderWriter/YamlContext.h @@ -39,6 +39,7 @@ struct YamlContext { const Registry *_registry; File *_file; NormalizedFile *_normalizeMachOFile; + StringRef _path; }; } // end namespace lld diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index e002a93e4b4f..dad5462c098e 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -21,7 +21,16 @@ class MachOFile : public SimpleFile { public: MachOFile(StringRef path) : SimpleFile(path) {} - void addDefinedAtom(StringRef name, ArrayRef content) { + void addDefinedAtom(StringRef name, ArrayRef 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(name.size()); + memcpy(s, name.data(), name.size()); + name = StringRef(s, name.size()); + uint8_t *bytes = _allocator.Allocate(content.size()); + memcpy(bytes, content.data(), content.size()); + content = llvm::makeArrayRef(bytes, content.size()); + } MachODefinedAtom *atom = new (_allocator) MachODefinedAtom(*this, name, content); addAtom(*atom); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h index 15fd4c3686d1..f76a3164b6da 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h @@ -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 content; + ArrayRef 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> -normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path); +normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path, + bool copyRefs); /// Takes atoms and generates a normalized macho-o view. ErrorOr> 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 diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp index 5fb280242838..330d8311caf7 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp @@ -175,12 +175,12 @@ readBinary(std::unique_ptr &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 &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( + new mach_o::MachOYamlIOTaggedDocumentHandler())); } } // namespace lld diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index 1479ac20da27..f671ff8c7684 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -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(si->size); + normSect->content = llvm::makeArrayRef(sectionContent, si->size); for (AtomInfo &ai : si->atomsAndOffsets) { // Copy raw bytes. uint8_t *atomContent = reinterpret_cast diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index d3ff1e406483..7c3ac8f1b28e 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -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> -normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path) { +normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, + bool copyRefs) { std::unique_ptr 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 atomContent = llvm::makeArrayRef(§ion.content[offset], - size); - file->addDefinedAtom(sym.name, atomContent); + ArrayRef 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> -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!"); } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp index c6736b82a309..5a5a9449158d 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp @@ -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
{ io.mapOptional("attributes", sect.attributes); io.mapOptional("alignment", sect.alignment, 0U); io.mapRequired("address", sect.address); - MappingNormalization> content( + MappingNormalization> 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 content) { + NormalizedContent(IO &io) : _io(io) {} + NormalizedContent(IO &io, ArrayRef 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 denormalize(IO &) { - std::vector content; - for (auto &c : normalizedContent) { - content.push_back(c); - } - return content; + ArrayRef denormalize(IO &io) { + // When reading yaml, allocate byte array owned by NormalizedFile and + // copy Hex8 vector to byte array. + YamlContext *info = reinterpret_cast(io.getContext()); + assert(info != nullptr); + NormalizedFile *file = info->_normalizeMachOFile; + assert(file != nullptr); + size_t size = _normalizedContent.size(); + uint8_t *bytes = file->ownedAllocations.Allocate(size); + std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes); + return makeArrayRef(bytes, size); } - ContentBytes normalizedContent; + + IO &_io; + ContentBytes _normalizedContent; }; }; @@ -612,10 +618,37 @@ struct MappingTraits { 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(io.getContext()); + assert(info != nullptr); + assert(info->_normalizeMachOFile == nullptr); + info->_normalizeMachOFile = &nf; + MappingTraits::mapping(io, nf); + // Step 2: parse normalized mach-o struct into atoms. + ErrorOr> foe = normalizedToAtoms(nf, info->_path, + true); + if (foe) { + // Transfer ownership to "out" File parameter. + std::unique_ptr 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> +ErrorOr> readYaml(std::unique_ptr &mb) { // Make empty NormalizedFile. std::unique_ptr f(new NormalizedFile()); @@ -638,7 +671,7 @@ readYaml(std::unique_ptr &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(&file); diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp index 8a2f0313fe1c..35affd78e2b3 100644 --- a/lld/lib/ReaderWriter/Reader.cpp +++ b/lld/lib/ReaderWriter/Reader.cpp @@ -21,10 +21,18 @@ namespace lld { Reader::~Reader() { } + +YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() { } + + void Registry::add(std::unique_ptr reader) { _readers.push_back(std::move(reader)); } +void Registry::add(std::unique_ptr handler) { + _yamlHandlers.push_back(std::move(handler)); +} + error_code Registry::parseFile(std::unique_ptr &mb, std::vector> &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 &h : _yamlHandlers) { + if (h->handledDocTag(io, file)) + return true; + } + return false; +} + + void Registry::addKindTable(Reference::KindNamespace ns, Reference::KindArch arch, const KindStrings array[]) { diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 72203082252f..2ad986ed949f 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -664,24 +664,15 @@ template <> struct MappingTraits { }; 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(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::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::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(new YAMLReader(*this))); + add(std::unique_ptr( + new NativeYamlIOTaggedDocumentHandler())); + add(std::unique_ptr( + new ArchiveYamlIOTaggedDocumentHandler())); } std::unique_ptr createWriterYAML(const LinkingContext &context) { diff --git a/lld/test/core/archive-basic.objtxt b/lld/test/core/archive-basic.objtxt index c93310762bd1..ec825c1a7e52 100644 --- a/lld/test/core/archive-basic.objtxt +++ b/lld/test/core/archive-basic.objtxt @@ -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 diff --git a/lld/test/core/archive-chain.objtxt b/lld/test/core/archive-chain.objtxt index 191b8520654f..0651dadd71c3 100644 --- a/lld/test/core/archive-chain.objtxt +++ b/lld/test/core/archive-chain.objtxt @@ -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 diff --git a/lld/test/core/archive-tentdef-search.objtxt b/lld/test/core/archive-tentdef-search.objtxt index f1802a193726..3d26778e4986 100644 --- a/lld/test/core/archive-tentdef-search.objtxt +++ b/lld/test/core/archive-tentdef-search.objtxt @@ -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 diff --git a/lld/test/darwin/hello-world.objtxt b/lld/test/darwin/hello-world.objtxt index abcafb0cf36f..d5e88a28165b 100644 --- a/lld/test/darwin/hello-world.objtxt +++ b/lld/test/darwin/hello-world.objtxt @@ -4,7 +4,7 @@ # Test that hello-world can be linked into a mach-o executable # ---- !atoms +--- !native defined-atoms: - name: _main type: code diff --git a/lld/test/darwin/native-and-mach-o.objtxt b/lld/test/darwin/native-and-mach-o.objtxt new file mode 100644 index 000000000000..3f356f5d8598 --- /dev/null +++ b/lld/test/darwin/native-and-mach-o.objtxt @@ -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 diff --git a/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp index 0f2d8d6f3b99..7670da221a54 100644 --- a/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp @@ -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, diff --git a/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp index ddd5591ed08a..2a46e36e8c0a 100644 --- a/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp @@ -23,7 +23,8 @@ using namespace llvm::MachO; TEST(ToAtomsTest, empty_obj_x86_64) { NormalizedFile f; f.arch = lld::MachOLinkingContext::arch_x86_64; - ErrorOr> atom_f = normalizedToAtoms(f, ""); + ErrorOr> 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> atom_f = normalizedToAtoms(f, ""); + ErrorOr> atom_f = normalizedToAtoms(f, "", + false); EXPECT_FALSE(!atom_f); const lld::File &file = **atom_f; EXPECT_EQ(2U, file.defined().size());