[lld] r198986 - [mach-o] enable mach-o and native yaml to be intermixed

Nick Kledzik kledzik at apple.com
Fri Jan 10 17:07:44 PST 2014


Author: kledzik
Date: Fri Jan 10 19:07:43 2014
New Revision: 198986

URL: http://llvm.org/viewvc/llvm-project?rev=198986&view=rev
Log:
[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.  


Added:
    lld/trunk/test/darwin/native-and-mach-o.objtxt
Modified:
    lld/trunk/include/lld/ReaderWriter/Reader.h
    lld/trunk/include/lld/ReaderWriter/YamlContext.h
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
    lld/trunk/lib/ReaderWriter/Reader.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
    lld/trunk/test/core/archive-basic.objtxt
    lld/trunk/test/core/archive-chain.objtxt
    lld/trunk/test/core/archive-tentdef-search.objtxt
    lld/trunk/test/darwin/hello-world.objtxt
    lld/trunk/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
    lld/trunk/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp

Modified: lld/trunk/include/lld/ReaderWriter/Reader.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/Reader.h?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/Reader.h (original)
+++ lld/trunk/include/lld/ReaderWriter/Reader.h Fri Jan 10 19:07:43 2014
@@ -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:

Modified: lld/trunk/include/lld/ReaderWriter/YamlContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/YamlContext.h?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/YamlContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/YamlContext.h Fri Jan 10 19:07:43 2014
@@ -39,6 +39,7 @@ struct YamlContext {
   const Registry *_registry;
   File *_file;
   NormalizedFile *_normalizeMachOFile;
+  StringRef _path;
 };
 
 } // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Fri Jan 10 19:07:43 2014
@@ -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);

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h Fri Jan 10 19:07:43 2014
@@ -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, ra
 
 /// 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
 

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp Fri Jan 10 19:07:43 2014
@@ -175,12 +175,12 @@ readBinary(std::unique_ptr<MemoryBuffer>
           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>
           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(St
   default:
     llvm_unreachable("mach-o arch not supported");
   }
+  add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
+                               new mach_o::MachOYamlIOTaggedDocumentHandler()));
 }
 
 } // namespace lld

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp Fri Jan 10 19:07:43 2014
@@ -422,8 +422,8 @@ void Util::appendSection(SectionInfo *si
   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*>

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp Fri Jan 10 19:07:43 2014
@@ -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
 }
 
 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 &section = 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(&section.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 Normalized
 }
 
 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!");
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp Fri Jan 10 19:07:43 2014
@@ -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> &
 
 
 /// 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);

Modified: lld/trunk/lib/ReaderWriter/Reader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/Reader.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/Reader.cpp (original)
+++ lld/trunk/lib/ReaderWriter/Reader.cpp Fri Jan 10 19:07:43 2014
@@ -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[]) {

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Fri Jan 10 19:07:43 2014
@@ -664,24 +664,15 @@ template <> struct MappingTraits<const l
   };
 
   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 &registry) : _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) {

Modified: lld/trunk/test/core/archive-basic.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/archive-basic.objtxt?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/test/core/archive-basic.objtxt (original)
+++ lld/trunk/test/core/archive-basic.objtxt Fri Jan 10 19:07:43 2014
@@ -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

Modified: lld/trunk/test/core/archive-chain.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/archive-chain.objtxt?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/test/core/archive-chain.objtxt (original)
+++ lld/trunk/test/core/archive-chain.objtxt Fri Jan 10 19:07:43 2014
@@ -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

Modified: lld/trunk/test/core/archive-tentdef-search.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/core/archive-tentdef-search.objtxt?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/test/core/archive-tentdef-search.objtxt (original)
+++ lld/trunk/test/core/archive-tentdef-search.objtxt Fri Jan 10 19:07:43 2014
@@ -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

Modified: lld/trunk/test/darwin/hello-world.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/darwin/hello-world.objtxt?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/test/darwin/hello-world.objtxt (original)
+++ lld/trunk/test/darwin/hello-world.objtxt Fri Jan 10 19:07:43 2014
@@ -4,7 +4,7 @@
 # Test that hello-world can be linked into a mach-o executable
 #
 
---- !atoms
+--- !native
 defined-atoms:
     - name:              _main
       type:              code

Added: lld/trunk/test/darwin/native-and-mach-o.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/darwin/native-and-mach-o.objtxt?rev=198986&view=auto
==============================================================================
--- lld/trunk/test/darwin/native-and-mach-o.objtxt (added)
+++ lld/trunk/test/darwin/native-and-mach-o.objtxt Fri Jan 10 19:07:43 2014
@@ -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

Modified: lld/trunk/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp (original)
+++ lld/trunk/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp Fri Jan 10 19:07:43 2014
@@ -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, 

Modified: lld/trunk/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp?rev=198986&r1=198985&r2=198986&view=diff
==============================================================================
--- lld/trunk/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp (original)
+++ lld/trunk/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp Fri Jan 10 19:07:43 2014
@@ -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());





More information about the llvm-commits mailing list