[lld] r192147 - Supoort mach-o encoded in yaml.

Rui Ueyama ruiu at google.com
Mon Oct 7 17:54:58 PDT 2013


This patch seems to have broken buildbot.

http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-debian-fast/builds/7967


On Mon, Oct 7, 2013 at 5:43 PM, Nick Kledzik <kledzik at apple.com> wrote:

> Author: kledzik
> Date: Mon Oct  7 19:43:34 2013
> New Revision: 192147
>
> URL: http://llvm.org/viewvc/llvm-project?rev=192147&view=rev
> Log:
> Supoort mach-o encoded in yaml.
>
> This is the first step in how I plan to get mach-o object files support
> into
> lld. We need to be able to test the mach-o Reader and Write on systems
> without
> a mach-o tools. Therefore, we want to support a textual way (YAML) to
> represent
> mach-o files.
>
> MachONormalizedFile.h defines an in-memory abstraction of the content of
> mach-o
> files. The in-memory data structures are always native endianess and always
> use 64-bit sizes. That internal data structure can then be converted to or
> from three different formats: 1) yaml (text) encoded mach-o, 2) binary
> mach-o
> files, 3) lld Atoms.
>
> This patch defines the internal model and uses YAML I/O to implement the
> conversion to and from the model to yaml. The next patch will implement
> the conversion from normalized to binary mach-o.
>
> This patch includes unit tests to validate the yaml conversion APIs.
>
> Added:
>     lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
>     lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
>     lld/trunk/unittests/MachOTests/
>     lld/trunk/unittests/MachOTests/CMakeLists.txt
>     lld/trunk/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
> Modified:
>     lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>     lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
>     lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>     lld/trunk/unittests/CMakeLists.txt
>
> Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=192147&r1=192146&r2=192147&view=diff
>
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Mon Oct  7
> 19:43:34 2013
> @@ -47,6 +47,7 @@ public:
>
>    enum Arch {
>      arch_unknown,
> +    arch_ppc,
>      arch_x86,
>      arch_x86_64,
>      arch_armv6,
> @@ -55,7 +56,7 @@ public:
>    };
>
>    enum class OS {
> -    macOSX, iOS, iOS_simulator
> +    unknown, macOSX, iOS, iOS_simulator
>    };
>
>    Arch arch() const { return _arch; }
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt?rev=192147&r1=192146&r2=192147&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/CMakeLists.txt Mon Oct  7 19:43:34
> 2013
> @@ -1,5 +1,6 @@
>  add_lld_library(lldMachO
>    MachOLinkingContext.cpp
> +  MachONormalizedFileYAML.cpp
>    ReferenceKinds.cpp
>    WriterMachO.cpp
>    )
>
> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=192147&r1=192146&r2=192147&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Mon Oct  7
> 19:43:34 2013
> @@ -149,20 +149,19 @@ bool MachOLinkingContext::outputTypeHasE
>  }
>
>  bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
> +  uint32_t parsedVersion;
>    switch (_os) {
> -  case OS::macOSX: {
> -    uint32_t parsedVersion;
> +  case OS::macOSX:
>      if (parsePackedVersion(mac, parsedVersion))
>        return false;
>      return _osMinVersion >= parsedVersion;
> -  }
>    case OS::iOS:
> -  case OS::iOS_simulator: {
> -    uint32_t parsedVersion;
> +  case OS::iOS_simulator:
>      if (parsePackedVersion(iOS, parsedVersion))
>        return false;
>      return _osMinVersion >= parsedVersion;
> -  }
> +  case OS::unknown:
> +    break;
>    }
>    llvm_unreachable("target not configured for iOS or MacOSX");
>  }
>
> Added: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h?rev=192147&view=auto
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFile.h Mon Oct  7
> 19:43:34 2013
> @@ -0,0 +1,279 @@
> +//===- lib/ReaderWriter/MachO/NormalizedFile.h ----------------------===//
> +//
> +//                             The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +///
> +/// \file These data structures comprise the "normalized" view of
> +/// mach-o object files. The normalized view is an in-memory only data
> structure
> +/// which is always in native endianness and pointer size.
> +///
> +/// The normalized view easily converts to and from YAML using YAML I/O.
> +///
> +/// The normalized view converts to and from binary mach-o object files
> using
> +/// the writeBinary() and readBinary() functions.
> +///
> +/// The normalized view converts to and from lld::Atoms using the
> +/// normalizedToAtoms() and normalizedFromAtoms().
> +///
> +/// Overall, the conversion paths available look like:
> +///
> +///                 +---------------+
> +///                 | binary mach-o |
> +///                 +---------------+
> +///                        ^
> +///                        |
> +///                        v
> +///                  +------------+         +------+
> +///                  | normalized |   <->   | yaml |
> +///                  +------------+         +------+
> +///                        ^
> +///                        |
> +///                        v
> +///                    +-------+
> +///                    | Atoms |
> +///                    +-------+
> +///
> +
> +#include "lld/Core/Error.h"
> +#include "lld/Core/LLVM.h"
> +#include "lld/ReaderWriter/MachOLinkingContext.h"
> +
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Support/ErrorOr.h"
> +#include "llvm/Support/MachO.h"
> +#include "llvm/Support/YAMLTraits.h"
> +
> +#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_H_
> +#define LLD_READER_WRITER_MACHO_NORMALIZED_H_
> +
> +using llvm::yaml::Hex64;
> +using llvm::yaml::Hex32;
> +using llvm::yaml::Hex8;
> +using llvm::yaml::SequenceTraits;
> +using llvm::MachO::HeaderFileType;
> +using llvm::MachO::BindType;
> +using llvm::MachO::RebaseType;
> +using llvm::MachO::NListType;
> +using llvm::MachO::RelocationInfoType;
> +using llvm::MachO::SectionType;
> +using llvm::MachO::LoadCommandType;
> +using llvm::MachO::ExportSymbolKind;
> +
> +namespace lld {
> +namespace mach_o {
> +namespace normalized {
> +
> +
> +/// The real mach-o relocation record is 8-bytes on disk and is
> +/// encoded in one of two different bit-field patterns.  This
> +/// normalized form has the union of all possbile fields.
> +struct Relocation {
> +  Relocation() : offset(0), scattered(false),
> +                 type(llvm::MachO::GENERIC_RELOC_VANILLA),
> +                 length(0), pcRel(false), isExtern(false), value(0),
> +                 symbol(0) { }
> +
> +  Hex32               offset;
> +  bool                scattered;
> +  RelocationInfoType  type;
> +  uint8_t             length;
> +  bool                pcRel;
> +  bool                isExtern;
> +  Hex32               value;
> +  uint32_t            symbol;
> +};
> +
> +/// A typedef so that YAML I/O can treat this vector as a sequence.
> +typedef std::vector<Relocation> Relocations;
> +
> +/// A typedef so that YAML I/O can process the raw bytes in a section.
> +typedef std::vector<Hex8> ContentBytes;
> +
> +/// A typedef so that YAML I/O can treat indirect symbols as a flow
> sequence.
> +typedef std::vector<uint32_t> IndirectSymbols;
> +
> +/// A typedef so that YAML I/O can encode/decode section attributes.
> +LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr);
> +
> +/// Mach-O has a 32-bit and 64-bit section record.  This normalized form
> +/// can support either kind.
> +struct Section {
> +  Section() : type(llvm::MachO::S_REGULAR),
> +              attributes(0), alignment(0), address(0) { }
> +
> +  StringRef       segmentName;
> +  StringRef       sectionName;
> +  SectionType     type;
> +  SectionAttr     attributes;
> +  uint32_t        alignment;
> +  Hex64           address;
> +  ContentBytes    content;
> +  Relocations     relocations;
> +  IndirectSymbols indirectSymbols;
> +};
> +
> +
> +/// A typedef so that YAML I/O can encode/decode the scope bits of an
> nlist.
> +LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope);
> +
> +/// A typedef so that YAML I/O can encode/decode the desc bits of an
> nlist.
> +LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc);
> +
> +/// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the
> symbol
> +/// type and scope and mixed in the same n_type field.  This normalized
> form
> +/// works for any pointer size and separates out the type and scope.
> +struct Symbol {
> +  Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0),
> value(0) { }
> +
> +  StringRef     name;
> +  NListType     type;
> +  SymbolScope   scope;
> +  uint8_t       sect;
> +  SymbolDesc    desc;
> +  Hex64         value;
> +};
> +
> +/// A typedef so that YAML I/O can (de/en)code the protection bits of a
> segment.
> +LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect);
> +
> +/// Segments are only used in normalized final linked images (not in
> relocatable
> +/// object files). They specify how a range of the file is loaded.
> +struct Segment {
> +  StringRef     name;
> +  Hex64         address;
> +  Hex64         size;
> +  VMProtect     access;
> +};
> +
> +/// Only used in normalized final linked images to specify on which dylibs
> +/// it depends.
> +struct DependentDylib {
> +  StringRef       path;
> +  LoadCommandType kind;
> +};
> +
> +/// A normalized rebasing entry.  Only used in normalized final linked
> images.
> +struct RebaseLocation {
> +  Hex32         segOffset;
> +  uint8_t       segIndex;
> +  RebaseType    kind;
> +};
> +
> +/// A normalized binding entry.  Only used in normalized final linked
> images.
> +struct BindLocation {
> +  Hex32           segOffset;
> +  uint8_t         segIndex;
> +  BindType        kind;
> +  bool            canBeNull;
> +  int             ordinal;
> +  StringRef       symbolName;
> +  Hex64           addend;
> +};
> +
> +/// A typedef so that YAML I/O can encode/decode export flags.
> +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags);
> +
> +/// A normalized export entry.  Only used in normalized final linked
> images.
> +struct Export {
> +  StringRef         name;
> +  Hex64             offset;
> +  ExportSymbolKind  kind;
> +  ExportFlags       flags;
> +  Hex32             otherOffset;
> +  StringRef         otherName;
> +};
> +
> +
> +/// A typedef so that YAML I/O can encode/decode mach_header.flags.
> +LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags);
> +
> +///
> +struct NormalizedFile {
> +  NormalizedFile() : arch(MachOLinkingContext::arch_unknown),
> +                     fileType(llvm::MachO::MH_OBJECT),
> +                     flags(0),
> +                     hasUUID(false),
> +                     os(MachOLinkingContext::OS::unknown) { }
> +
> +  MachOLinkingContext::Arch   arch;
> +  HeaderFileType              fileType;
> +  FileFlags                   flags;
> +  std::vector<Segment>        segments; // Not used in object files.
> +  std::vector<Section>        sections;
> +
> +  // Symbols sorted by kind.
> +  std::vector<Symbol>         localSymbols;
> +  std::vector<Symbol>         globalSymbols;
> +  std::vector<Symbol>         undefinedSymbols;
> +
> +  // Maps to load commands with no LINKEDIT content (final linked images
> only).
> +  std::vector<DependentDylib> dependentDylibs;
> +  StringRef                   installName;
> +  bool                        hasUUID;
> +  std::vector<StringRef>      rpaths;
> +  Hex64                       entryAddress;
> +  MachOLinkingContext::OS     os;
> +  Hex64                       sourceVersion;
> +  Hex32                       minOSverson;
> +  Hex32                       sdkVersion;
> +
> +  // Maps to load commands with LINKEDIT content (final linked images
> only).
> +  std::vector<RebaseLocation> rebasingInfo;
> +  std::vector<BindLocation>   bindingInfo;
> +  std::vector<BindLocation>   weakBindingInfo;
> +  std::vector<BindLocation>   lazyBindingInfo;
> +  std::vector<Export>         exportInfo;
> +
> +  // TODO:
> +  // code-signature
> +  // split-seg-info
> +  // function-starts
> +  // data-in-code
> +};
> +
> +
> +/// Reads a mach-o file and produces an in-memory normalized view.
> +ErrorOr<std::unique_ptr<NormalizedFile>>
> +readBinary(std::unique_ptr<MemoryBuffer> &mb);
> +
> +/// Takes in-memory normalized view and writes a mach-o object file.
> +error_code
> +writeBinary(const NormalizedFile &file, StringRef path);
> +
> +size_t headerAndLoadCommandsSize(const NormalizedFile &file);
> +
> +
> +/// Parses a yaml encoded mach-o file to produce an in-memory normalized
> view.
> +ErrorOr<std::unique_ptr<NormalizedFile>>
> +readYaml(std::unique_ptr<MemoryBuffer> &mb);
> +
> +/// Writes a yaml encoded mach-o files given an in-memory normalized view.
> +error_code
> +writeYaml(const NormalizedFile &file, llvm::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);
> +
> +/// Takes atoms and generates a normalized macho-o view.
> +ErrorOr<std::unique_ptr<NormalizedFile>>
> +normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext
> &ctxt);
> +
> +
> +
> +} // namespace normalized
> +} // namespace mach_o
> +} // namespace lld
> +
> +#endif // LLD_READER_WRITER_MACHO_NORMALIZED_H_
> +
> +
> +
> +
>
> Added: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp?rev=192147&view=auto
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp (added)
> +++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp Mon Oct
>  7 19:43:34 2013
> @@ -0,0 +1,650 @@
> +//===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
> -----------------===//
> +//
> +//                             The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +///
> +/// \file For mach-o object files, this implementation uses YAML I/O to
> +/// provide the convert between YAML and the normalized mach-o (NM).
> +///
> +///                  +------------+         +------+
> +///                  | normalized |   <->   | yaml |
> +///                  +------------+         +------+
> +
> +#include "MachONormalizedFile.h"
> +
> +#include "lld/Core/Error.h"
> +#include "lld/Core/LLVM.h"
> +
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/StringSwitch.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/Support/Casting.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/MachO.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/SourceMgr.h"
> +#include "llvm/Support/system_error.h"
> +#include "llvm/Support/YAMLTraits.h"
> +
> +
> +using llvm::StringRef;
> +using llvm::error_code;
> +using llvm::dyn_cast;
> +
> +using llvm::yaml::MappingTraits;
> +using llvm::yaml::SequenceTraits;
> +using llvm::yaml::ScalarEnumerationTraits;
> +using llvm::yaml::ScalarBitSetTraits;
> +using llvm::yaml::ScalarTraits;
> +using llvm::yaml::IO;
> +using llvm::yaml::Hex64;
> +using llvm::yaml::Hex32;
> +using llvm::yaml::Hex8;
> +
> +using llvm::MachO::HeaderFileType;
> +using llvm::MachO::RebaseType;
> +using llvm::MachO::BindType;
> +using llvm::MachO::NListType;
> +using llvm::MachO::RelocationInfoType;
> +using llvm::MachO::SectionType;
> +using llvm::MachO::LoadCommandType;
> +
> +using lld::mach_o::normalized::Section;
> +using lld::mach_o::normalized::Symbol;
> +using lld::mach_o::normalized::Relocation;
> +using lld::mach_o::normalized::Relocations;
> +using lld::mach_o::normalized::IndirectSymbols;
> +using lld::mach_o::normalized::ContentBytes;
> +using lld::mach_o::normalized::FileFlags;
> +using lld::mach_o::normalized::SectionAttr;
> +using lld::mach_o::normalized::SymbolScope;
> +using lld::mach_o::normalized::SymbolDesc;
> +using lld::mach_o::normalized::VMProtect;
> +using lld::mach_o::normalized::Segment;
> +using lld::mach_o::normalized::DependentDylib;
> +using lld::mach_o::normalized::RebaseLocation;
> +using lld::mach_o::normalized::BindLocation;
> +using lld::mach_o::normalized::ExportFlags;
> +using lld::mach_o::normalized::Export;
> +using lld::mach_o::normalized::NormalizedFile;
> +
> +// A vector of Sections is a sequence.
> +template<>
> +struct SequenceTraits< std::vector<Section> > {
> +  static size_t size(IO &io, std::vector<Section> &seq) {
> +    return seq.size();
> +  }
> +  static Section& element(IO &io, std::vector<Section> &seq, size_t
> index) {
> +    if ( index >= seq.size() )
> +      seq.resize(index+1);
> +    return seq[index];
> +  }
> +};
> +
> +template<>
> +struct SequenceTraits< std::vector<Symbol> > {
> +  static size_t size(IO &io, std::vector<Symbol> &seq) {
> +    return seq.size();
> +  }
> +  static Symbol& element(IO &io, std::vector<Symbol> &seq, size_t index) {
> +    if ( index >= seq.size() )
> +      seq.resize(index+1);
> +    return seq[index];
> +  }
> +};
> +
> +// A vector of Relocations is a sequence.
> +template<>
> +struct SequenceTraits< Relocations > {
> +  static size_t size(IO &io, Relocations &seq) {
> +    return seq.size();
> +  }
> +  static Relocation& element(IO &io, Relocations &seq, size_t index) {
> +    if ( index >= seq.size() )
> +      seq.resize(index+1);
> +    return seq[index];
> +  }
> +};
> +
> +// The content for a section is represented as a flow sequence of hex
> bytes.
> +template<>
> +struct SequenceTraits< ContentBytes > {
> +  static size_t size(IO &io, ContentBytes &seq) {
> +    return seq.size();
> +  }
> +  static Hex8& element(IO &io, ContentBytes &seq, size_t index) {
> +    if ( index >= seq.size() )
> +      seq.resize(index+1);
> +    return seq[index];
> +  }
> +  static const bool flow = true;
> +};
> +
> +// The indirect symbols for a section is represented as a flow sequence
> +// of numbers (symbol table indexes).
> +template<>
> +struct SequenceTraits< IndirectSymbols > {
> +  static size_t size(IO &io, IndirectSymbols &seq) {
> +    return seq.size();
> +  }
> +  static uint32_t& element(IO &io, IndirectSymbols &seq, size_t index) {
> +    if ( index >= seq.size() )
> +      seq.resize(index+1);
> +    return seq[index];
> +  }
> +  static const bool flow = true;
> +};
> +
> +template <>
> +struct ScalarEnumerationTraits<lld::MachOLinkingContext::Arch> {
> +  static void enumeration(IO &io, lld::MachOLinkingContext::Arch &value) {
> +    io.enumCase(value, "unknown",lld::MachOLinkingContext::arch_unknown);
> +    io.enumCase(value, "ppc",    lld::MachOLinkingContext::arch_ppc);
> +    io.enumCase(value, "x86",    lld::MachOLinkingContext::arch_x86);
> +    io.enumCase(value, "x86_64", lld::MachOLinkingContext::arch_x86_64);
> +    io.enumCase(value, "armv6",  lld::MachOLinkingContext::arch_armv6);
> +    io.enumCase(value, "armv7",  lld::MachOLinkingContext::arch_armv7);
> +    io.enumCase(value, "armv7s", lld::MachOLinkingContext::arch_armv7s);
> +  }
> +};
> +
> +template <>
> +struct ScalarEnumerationTraits<lld::MachOLinkingContext::OS> {
> +  static void enumeration(IO &io, lld::MachOLinkingContext::OS &value) {
> +    io.enumCase(value, "unknown",
> +                          lld::MachOLinkingContext::OS::unknown);
> +    io.enumCase(value, "Mac OS X",
> +                          lld::MachOLinkingContext::OS::macOSX);
> +    io.enumCase(value, "iOS",
> +                          lld::MachOLinkingContext::OS::iOS);
> +    io.enumCase(value, "iOS Simulator",
> +                          lld::MachOLinkingContext::OS::iOS_simulator);
> +  }
> +};
> +
> +
> +template <>
> +struct ScalarEnumerationTraits<HeaderFileType> {
> +  static void enumeration(IO &io, HeaderFileType &value) {
> +    io.enumCase(value, "object",      llvm::MachO::MH_OBJECT);
> +    io.enumCase(value, "dylib",       llvm::MachO::MH_DYLIB);
> +    io.enumCase(value, "executable",  llvm::MachO::MH_EXECUTE);
> +    io.enumCase(value, "bundle",      llvm::MachO::MH_BUNDLE);
> +  }
> +};
> +
> +
> +template <>
> +struct ScalarBitSetTraits<FileFlags> {
> +  static void bitset(IO &io, FileFlags &value) {
> +    io.bitSetCase(value, "MH_TWOLEVEL",
> +                          llvm::MachO::MH_TWOLEVEL);
> +    io.bitSetCase(value, "MH_SUBSECTIONS_VIA_SYMBOLS",
> +                          llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  }
> +};
> +
> +
> +template <>
> +struct ScalarEnumerationTraits<SectionType> {
> +  static void enumeration(IO &io, SectionType &value) {
> +    io.enumCase(value, "S_REGULAR",
> +                        llvm::MachO::S_REGULAR);
> +    io.enumCase(value, "S_ZEROFILL",
> +                        llvm::MachO::S_ZEROFILL);
> +    io.enumCase(value, "S_CSTRING_LITERALS",
> +                        llvm::MachO::S_CSTRING_LITERALS);
> +    io.enumCase(value, "S_4BYTE_LITERALS",
> +                        llvm::MachO::S_4BYTE_LITERALS);
> +    io.enumCase(value, "S_8BYTE_LITERALS",
> +                        llvm::MachO::S_8BYTE_LITERALS);
> +    io.enumCase(value, "S_LITERAL_POINTERS",
> +                        llvm::MachO::S_LITERAL_POINTERS);
> +    io.enumCase(value, "S_NON_LAZY_SYMBOL_POINTERS",
> +                        llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS);
> +    io.enumCase(value, "S_LAZY_SYMBOL_POINTERS",
> +                        llvm::MachO::S_LAZY_SYMBOL_POINTERS);
> +    io.enumCase(value, "S_SYMBOL_STUBS",
> +                        llvm::MachO::S_SYMBOL_STUBS);
> +    io.enumCase(value, "S_MOD_INIT_FUNC_POINTERS",
> +                        llvm::MachO::S_MOD_INIT_FUNC_POINTERS);
> +    io.enumCase(value, "S_MOD_TERM_FUNC_POINTERS",
> +                        llvm::MachO::S_MOD_TERM_FUNC_POINTERS);
> +    io.enumCase(value, "S_COALESCED",
> +                        llvm::MachO::S_COALESCED);
> +    io.enumCase(value, "S_GB_ZEROFILL",
> +                        llvm::MachO::S_GB_ZEROFILL);
> +    io.enumCase(value, "S_INTERPOSING",
> +                        llvm::MachO::S_INTERPOSING);
> +    io.enumCase(value, "S_16BYTE_LITERALS",
> +                        llvm::MachO::S_16BYTE_LITERALS);
> +    io.enumCase(value, "S_DTRACE_DOF",
> +                        llvm::MachO::S_DTRACE_DOF);
> +    io.enumCase(value, "S_LAZY_DYLIB_SYMBOL_POINTERS",
> +                        llvm::MachO::S_LAZY_DYLIB_SYMBOL_POINTERS);
> +    io.enumCase(value, "S_THREAD_LOCAL_REGULAR",
> +                        llvm::MachO::S_THREAD_LOCAL_REGULAR);
> +    io.enumCase(value, "S_THREAD_LOCAL_ZEROFILL",
> +                        llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
> +    io.enumCase(value, "S_THREAD_LOCAL_VARIABLES",
> +                        llvm::MachO::S_THREAD_LOCAL_VARIABLES);
> +    io.enumCase(value, "S_THREAD_LOCAL_VARIABLE_POINTERS",
> +                        llvm::MachO::S_THREAD_LOCAL_VARIABLE_POINTERS);
> +    io.enumCase(value, "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS",
> +
>  llvm::MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
> +  }
> +};
> +
> +template <>
> +struct ScalarBitSetTraits<SectionAttr> {
> +  static void bitset(IO &io, SectionAttr &value) {
> +    io.bitSetCase(value, "S_ATTR_PURE_INSTRUCTIONS",
> +                          llvm::MachO::S_ATTR_PURE_INSTRUCTIONS);
> +    io.bitSetCase(value, "S_ATTR_SOME_INSTRUCTIONS",
> +                          llvm::MachO::S_ATTR_SOME_INSTRUCTIONS);
> +    io.bitSetCase(value, "S_ATTR_NO_DEAD_STRIP",
> +                          llvm::MachO::S_ATTR_NO_DEAD_STRIP);
> +    io.bitSetCase(value, "S_ATTR_EXT_RELOC",
> +                          llvm::MachO::S_ATTR_EXT_RELOC);
> +    io.bitSetCase(value, "S_ATTR_LOC_RELOC",
> +                          llvm::MachO::S_ATTR_LOC_RELOC);
> +  }
> +};
> +
> +template <>
> +struct ScalarEnumerationTraits<NListType> {
> +  static void enumeration(IO &io, NListType &value) {
> +    io.enumCase(value, "N_UNDF",  llvm::MachO::N_UNDF);
> +    io.enumCase(value, "N_ABS",   llvm::MachO::N_ABS);
> +    io.enumCase(value, "N_SECT",  llvm::MachO::N_SECT);
> +  }
> +};
> +
> +template <>
> +struct ScalarBitSetTraits<SymbolScope> {
> +  static void bitset(IO &io, SymbolScope &value) {
> +    io.bitSetCase(value, "N_EXT",   llvm::MachO::N_EXT);
> +    io.bitSetCase(value, "N_PEXT",  llvm::MachO::N_PEXT);
> +  }
> +};
> +
> +template <>
> +struct ScalarBitSetTraits<SymbolDesc> {
> +  static void bitset(IO &io, SymbolDesc &value) {
> +    io.bitSetCase(value, "N_NO_DEAD_STRIP",
> llvm::MachO::N_NO_DEAD_STRIP);
> +    io.bitSetCase(value, "N_WEAK_REF",        llvm::MachO::N_WEAK_REF);
> +    io.bitSetCase(value, "N_WEAK_DEF",        llvm::MachO::N_WEAK_DEF);
> +    io.bitSetCase(value, "N_ARM_THUMB_DEF",
> llvm::MachO::N_ARM_THUMB_DEF);
> +    io.bitSetCase(value, "N_SYMBOL_RESOLVER",
> llvm::MachO::N_SYMBOL_RESOLVER);
> +  }
> +};
> +
> +
> +template <>
> +struct MappingTraits<Section> {
> +  static void mapping(IO &io, Section &sect) {
> +    io.mapRequired("segment",         sect.segmentName);
> +    io.mapRequired("section",         sect.sectionName);
> +    io.mapRequired("type",            sect.type);
> +    io.mapOptional("attributes",      sect.attributes);
> +    io.mapOptional("alignment",       sect.alignment, 0U);
> +    io.mapRequired("address",         sect.address);
> +    io.mapOptional("content",         sect.content);
> +    io.mapOptional("relocations",     sect.relocations);
> +    io.mapOptional("indirect-syms",   sect.indirectSymbols);
> +  }
> +};
> +
> +
> +template <>
> +struct MappingTraits<Relocation> {
> +  static void mapping(IO &io, Relocation &reloc) {
> +    io.mapRequired("offset",    reloc.offset);
> +    io.mapOptional("scattered", reloc.scattered, false);
> +    io.mapRequired("type",      reloc.type);
> +    io.mapRequired("length",    reloc.length);
> +    io.mapRequired("pc-rel",    reloc.pcRel);
> +    if ( !reloc.scattered )
> +     io.mapRequired("extern",   reloc.isExtern);
> +    if ( reloc.scattered )
> +     io.mapRequired("value",    reloc.value);
> +    if ( !reloc.scattered )
> +     io.mapRequired("symbol",   reloc.symbol);
> +  }
> +};
> +
> +
> +template <>
> +struct ScalarEnumerationTraits<RelocationInfoType> {
> +  static void enumeration(IO &io, RelocationInfoType &value) {
> +    NormalizedFile *file =
> reinterpret_cast<NormalizedFile*>(io.getContext());
> +    assert(file != nullptr);
> +    switch (file->arch) {
> +    case lld::MachOLinkingContext::arch_x86_64:
> +      io.enumCase(value, "X86_64_RELOC_UNSIGNED",
> +                                  llvm::MachO::X86_64_RELOC_UNSIGNED);
> +      io.enumCase(value, "X86_64_RELOC_SIGNED",
> +                                  llvm::MachO::X86_64_RELOC_SIGNED);
> +      io.enumCase(value, "X86_64_RELOC_BRANCH",
> +                                  llvm::MachO::X86_64_RELOC_BRANCH);
> +      io.enumCase(value, "X86_64_RELOC_GOT_LOAD",
> +                                  llvm::MachO::X86_64_RELOC_GOT_LOAD);
> +      io.enumCase(value, "X86_64_RELOC_GOT",
> +                                  llvm::MachO::X86_64_RELOC_GOT);
> +      io.enumCase(value, "X86_64_RELOC_SUBTRACTOR",
> +                                  llvm::MachO::X86_64_RELOC_SUBTRACTOR);
> +      io.enumCase(value, "X86_64_RELOC_SIGNED_1",
> +                                  llvm::MachO::X86_64_RELOC_SIGNED_1);
> +      io.enumCase(value, "X86_64_RELOC_SIGNED_2",
> +                                  llvm::MachO::X86_64_RELOC_SIGNED_2);
> +      io.enumCase(value, "X86_64_RELOC_SIGNED_4",
> +                                  llvm::MachO::X86_64_RELOC_SIGNED_4);
> +      io.enumCase(value, "X86_64_RELOC_TLV",
> +                                  llvm::MachO::X86_64_RELOC_TLV);
> +      break;
> +    case lld::MachOLinkingContext::arch_x86:
> +      io.enumCase(value, "GENERIC_RELOC_VANILLA",
> +                                  llvm::MachO::GENERIC_RELOC_VANILLA);
> +      io.enumCase(value, "GENERIC_RELOC_PAIR",
> +                                  llvm::MachO::GENERIC_RELOC_PAIR);
> +      io.enumCase(value, "GENERIC_RELOC_SECTDIFF",
> +                                  llvm::MachO::GENERIC_RELOC_SECTDIFF);
> +      io.enumCase(value, "GENERIC_RELOC_LOCAL_SECTDIFF",
> +
>  llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
> +      io.enumCase(value, "GENERIC_RELOC_TLV",
> +                                  llvm::MachO::GENERIC_RELOC_TLV);
> +      break;
> +    case lld::MachOLinkingContext::arch_armv6:
> +    case lld::MachOLinkingContext::arch_armv7:
> +    case lld::MachOLinkingContext::arch_armv7s:
> +       io.enumCase(value, "ARM_RELOC_VANILLA",
> +                                  llvm::MachO::ARM_RELOC_VANILLA);
> +      io.enumCase(value, "ARM_RELOC_PAIR",
> +                                  llvm::MachO::ARM_RELOC_PAIR);
> +      io.enumCase(value, "ARM_RELOC_SECTDIFF",
> +                                  llvm::MachO::ARM_RELOC_SECTDIFF);
> +      io.enumCase(value, "ARM_RELOC_LOCAL_SECTDIFF",
> +                                  llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF);
> +      io.enumCase(value, "ARM_RELOC_BR24",
> +                                  llvm::MachO::ARM_RELOC_BR24);
> +      io.enumCase(value, "ARM_THUMB_RELOC_BR22",
> +                                  llvm::MachO::ARM_THUMB_RELOC_BR22);
> +      io.enumCase(value, "ARM_RELOC_HALF",
> +                                  llvm::MachO::ARM_RELOC_HALF);
> +      io.enumCase(value, "ARM_RELOC_HALF_SECTDIFF",
> +                                  llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
> +      break;
> +    default:
> +      llvm_unreachable("unknown archictecture");
> +    }
> + }
> +};
> +
> +
> +template <>
> +struct MappingTraits<Symbol> {
> +  static void mapping(IO &io, Symbol& sym) {
> +    io.mapRequired("name",    sym.name);
> +    io.mapRequired("type",    sym.type);
> +    io.mapOptional("scope",   sym.scope, SymbolScope(0));
> +    io.mapOptional("sect",    sym.sect, (uint8_t)0);
> +    io.mapOptional("desc",    sym.desc, SymbolDesc(0));
> +    io.mapRequired("value",   sym.value);
> +  }
> +};
> +
> +// Custom mapping for VMProtect (e.g. "r-x").
> +template <>
> +struct ScalarTraits<VMProtect> {
> +  static void output(const VMProtect &value, void*, llvm::raw_ostream
> &out) {
> +    out << ( (value & llvm::MachO::VM_PROT_READ)    ? 'r' : '-');
> +    out << ( (value & llvm::MachO::VM_PROT_WRITE)   ? 'w' : '-');
> +    out << ( (value & llvm::MachO::VM_PROT_EXECUTE) ? 'x' : '-');
> +  }
> +  static StringRef input(StringRef scalar, void*, VMProtect &value) {
> +    value = 0;
> +    if (scalar.size() != 3)
> +      return "segment access protection must be three chars (e.g.
> \"r-x\")";
> +    switch (scalar[0]) {
> +    case 'r':
> +      value = llvm::MachO::VM_PROT_READ;
> +      break;
> +    case '-':
> +      break;
> +    default:
> +      return "segment access protection first char must be 'r' or '-'";
> +    }
> +    switch (scalar[1]) {
> +    case 'w':
> +      value = value | llvm::MachO::VM_PROT_WRITE;
> +      break;
> +    case '-':
> +      break;
> +    default:
> +      return "segment access protection second char must be 'w' or '-'";
> +    }
> +    switch (scalar[2]) {
> +    case 'x':
> +      value = value | llvm::MachO::VM_PROT_EXECUTE;
> +      break;
> +    case '-':
> +      break;
> +    default:
> +      return "segment access protection third char must be 'x' or '-'";
> +    }
> +    // Return the empty string on success,
> +    return StringRef();
> +  }
> +};
> +
> +
> +template <>
> +struct MappingTraits<Segment> {
> +  static void mapping(IO &io, Segment& seg) {
> +    io.mapRequired("name",      seg.name);
> +    io.mapRequired("address",   seg.address);
> +    io.mapRequired("size",      seg.size);
> +    io.mapRequired("access",    seg.access);
> +  }
> +};
> +LLVM_YAML_IS_SEQUENCE_VECTOR(Segment);
> +
> +template <>
> +struct ScalarEnumerationTraits<LoadCommandType> {
> +  static void enumeration(IO &io, LoadCommandType &value) {
> +    io.enumCase(value, "LC_LOAD_DYLIB",
> +                        llvm::MachO::LC_LOAD_DYLIB);
> +    io.enumCase(value, "LC_LOAD_WEAK_DYLIB",
> +                        llvm::MachO::LC_LOAD_WEAK_DYLIB);
> +    io.enumCase(value, "LC_REEXPORT_DYLIB",
> +                        llvm::MachO::LC_REEXPORT_DYLIB);
> +    io.enumCase(value, "LC_LOAD_UPWARD_DYLIB",
> +                        llvm::MachO::LC_LOAD_UPWARD_DYLIB);
> +    io.enumCase(value, "LC_LAZY_LOAD_DYLIB",
> +                        llvm::MachO::LC_LAZY_LOAD_DYLIB);
> +  }
> +};
> +
> +template <>
> +struct MappingTraits<DependentDylib> {
> +  static void mapping(IO &io, DependentDylib& dylib) {
> +    io.mapRequired("path",    dylib.path);
> +    io.mapOptional("kind",    dylib.kind,
> llvm::MachO::LC_LOAD_DYLIB);
> +  }
> +};
> +
> +LLVM_YAML_IS_SEQUENCE_VECTOR(DependentDylib);
> +
> +template <>
> +struct ScalarEnumerationTraits<RebaseType> {
> +  static void enumeration(IO &io, RebaseType &value) {
> +    io.enumCase(value, "REBASE_TYPE_POINTER",
> +                        llvm::MachO::REBASE_TYPE_POINTER);
> +    io.enumCase(value, "REBASE_TYPE_TEXT_PCREL32",
> +                        llvm::MachO::REBASE_TYPE_TEXT_PCREL32);
> +    io.enumCase(value, "REBASE_TYPE_TEXT_ABSOLUTE32",
> +                        llvm::MachO::REBASE_TYPE_TEXT_ABSOLUTE32);
> +  }
> +};
> +
> +
> +template <>
> +struct MappingTraits<RebaseLocation> {
> +  static void mapping(IO &io, RebaseLocation& rebase) {
> +    io.mapRequired("segment-index",   rebase.segIndex);
> +    io.mapRequired("segment-offset",  rebase.segOffset);
> +    io.mapOptional("kind",            rebase.kind,
> +                                      llvm::MachO::REBASE_TYPE_POINTER);
> +  }
> +};
> +
> +LLVM_YAML_IS_SEQUENCE_VECTOR(RebaseLocation);
> +
> +template <>
> +struct ScalarEnumerationTraits<BindType> {
> +  static void enumeration(IO &io, BindType &value) {
> +    io.enumCase(value, "BIND_TYPE_POINTER",
> +                        llvm::MachO::BIND_TYPE_POINTER);
> +    io.enumCase(value, "BIND_TYPE_TEXT_ABSOLUTE32",
> +                        llvm::MachO::BIND_TYPE_TEXT_ABSOLUTE32);
> +    io.enumCase(value, "BIND_TYPE_TEXT_PCREL32",
> +                        llvm::MachO::BIND_TYPE_TEXT_PCREL32);
> +  }
> +};
> +
> +template <>
> +struct MappingTraits<BindLocation> {
> +  static void mapping(IO &io, BindLocation &bind) {
> +    io.mapRequired("segment-index",   bind.segIndex);
> +    io.mapRequired("segment-offset",  bind.segOffset);
> +    io.mapOptional("kind",            bind.kind,
> +                                      llvm::MachO::BIND_TYPE_POINTER);
> +    io.mapOptional("can-be-null",     bind.canBeNull, false);
> +    io.mapRequired("ordinal",         bind.ordinal);
> +    io.mapRequired("symbol-name",     bind.symbolName);
> +    io.mapOptional("addend",          bind.addend, Hex64(0));
> +  }
> +};
> +
> +LLVM_YAML_IS_SEQUENCE_VECTOR(BindLocation);
> +
> +
> +template <>
> +struct ScalarEnumerationTraits<ExportSymbolKind> {
> +  static void enumeration(IO &io, ExportSymbolKind &value) {
> +    io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_REGULAR",
> +                        llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
> +    io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCALl",
> +
>  llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
> +  }
> +};
> +
> +template <>
> +struct ScalarBitSetTraits<ExportFlags> {
> +  static void bitset(IO &io, ExportFlags &value) {
> +    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION",
> +
>  llvm::MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
> +    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_REEXPORT",
> +                          llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
> +    io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER",
> +
>  llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
> +  }
> +};
> +
> +
> +template <>
> +struct MappingTraits<Export> {
> +  static void mapping(IO &io, Export &exp) {
> +    io.mapRequired("name",         exp.name);
> +    io.mapRequired("offset",       exp.offset);
> +    io.mapOptional("kind",         exp.kind,
> +
>  llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
> +    io.mapOptional("flags",        exp.flags);
> +    io.mapOptional("other-offset", exp.otherOffset, Hex32(0));
> +    io.mapOptional("other-name",   exp.otherName, StringRef());
> +  }
> +};
> +
> +LLVM_YAML_IS_SEQUENCE_VECTOR(Export);
> +LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef);
> +
> +template <>
> +struct MappingTraits<NormalizedFile> {
> +  static void mapping(IO &io, NormalizedFile &file) {
> +    io.mapRequired("arch",             file.arch);
> +    io.mapRequired("file-type",        file.fileType);
> +    io.mapOptional("flags",            file.flags);
> +    io.mapOptional("dependents",       file.dependentDylibs);
> +    io.mapOptional("install-name",     file.installName,    StringRef());
> +    io.mapOptional("has-UUID",         file.hasUUID,        true);
> +    io.mapOptional("rpaths",           file.rpaths);
> +    io.mapOptional("entry-point",      file.entryAddress,   Hex64(0));
> +    io.mapOptional("source-version",   file.sourceVersion,  Hex64(0));
> +    io.mapOptional("OS",               file.os);
> +    io.mapOptional("min-os-version",   file.minOSverson,    Hex32(0));
> +    io.mapOptional("sdk-version",      file.sdkVersion,     Hex32(0));
> +    io.mapOptional("segments",         file.segments);
> +    io.mapOptional("sections",         file.sections);
> +    io.mapOptional("local-symbols",    file.localSymbols);
> +    io.mapOptional("global-symbols",   file.globalSymbols);
> +    io.mapOptional("undefined-symbols",file.undefinedSymbols);
> +    io.mapOptional("rebasings",        file.rebasingInfo);
> +    io.mapOptional("bindings",         file.bindingInfo);
> +    io.mapOptional("weak-bindings",    file.weakBindingInfo);
> +    io.mapOptional("lazy-bindings",    file.lazyBindingInfo);
> +    io.mapOptional("exports",          file.exportInfo);
> +  }
> +};
> +
> +
> +namespace lld {
> +namespace mach_o {
> +namespace normalized {
> +
> +/// Parses a yaml encoded mach-o file to produce an in-memory normalized
> view.
> +ErrorOr<std::unique_ptr<NormalizedFile>>
> +readYaml(std::unique_ptr<MemoryBuffer> &mb) {
> +  // Make empty NormalizedFile.
> +  std::unique_ptr<NormalizedFile> f(new NormalizedFile());
> +
> +  // Create YAML Input parser.
> +  llvm::yaml::Input yin(mb->getBuffer(), f.get());
> +
> +  // Fill NormalizedFile by parsing yaml.
> +  yin >> *f;
> +
> +  // Return error if there were parsing problems.
> +  if (yin.error())
> +    return make_error_code(lld::yaml_reader_error::illegal_value);
> +
> +  // Hand ownership of instantiated NormalizedFile to caller.
> +  return std::move(f);
> +}
> +
> +
> +/// Writes a yaml encoded mach-o files from an in-memory normalized view.
> +error_code
> +writeYaml(const NormalizedFile &file, llvm::raw_ostream &out) {
> +  // YAML I/O is not const aware, so need to cast away ;-(
> +  NormalizedFile *f = const_cast<NormalizedFile*>(&file);
> +
> +  // Create yaml Output writer, using yaml options for context.
> +  llvm::yaml::Output yout(out, f);
> +
> +  // Stream out yaml.
> +  yout << *f;
> +
> +  return error_code::success();
> +}
> +
> +} // namespace normalized
> +} // namespace mach_o
> +} // namespace lld
> +
>
> Modified: lld/trunk/unittests/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/CMakeLists.txt?rev=192147&r1=192146&r2=192147&view=diff
>
> ==============================================================================
> --- lld/trunk/unittests/CMakeLists.txt (original)
> +++ lld/trunk/unittests/CMakeLists.txt Mon Oct  7 19:43:34 2013
> @@ -12,3 +12,4 @@ endfunction()
>
>  add_subdirectory(CoreTests)
>  add_subdirectory(DriverTests)
> +add_subdirectory(MachOTests)
>
> Added: lld/trunk/unittests/MachOTests/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/MachOTests/CMakeLists.txt?rev=192147&view=auto
>
> ==============================================================================
> --- lld/trunk/unittests/MachOTests/CMakeLists.txt (added)
> +++ lld/trunk/unittests/MachOTests/CMakeLists.txt Mon Oct  7 19:43:34 2013
> @@ -0,0 +1,9 @@
> +
> +add_lld_unittest(lldMachOTests
> +  MachONormalizedFileYAMLTests.cpp
> +  )
> +
> +target_link_libraries(lldMachOTests
> +  lldMachO
> +  lldYAML
> +  )
>
> Added: lld/trunk/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp?rev=192147&view=auto
>
> ==============================================================================
> --- lld/trunk/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp (added)
> +++ lld/trunk/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp Mon
> Oct  7 19:43:34 2013
> @@ -0,0 +1,769 @@
> +//===- lld/unittest/MachOTests/MachONormalizedFileYAMLTests.cpp
> -----------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "gtest/gtest.h"
> +
> +#include "llvm/Support/MachO.h"
> +
> +#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
> +
> +#include <assert.h>
> +#include <vector>
> +
> +using llvm::StringRef;
> +using llvm::MemoryBuffer;
> +using llvm::ErrorOr;
> +using lld::mach_o::normalized::NormalizedFile;
> +using lld::mach_o::normalized::Symbol;
> +using lld::mach_o::normalized::Section;
> +using lld::mach_o::normalized::Relocation;
> +
> +
> +static std::unique_ptr<NormalizedFile> fromYAML(StringRef str) {
> +  std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(str));
> +  ErrorOr<std::unique_ptr<NormalizedFile>> r
> +                                    =
> lld::mach_o::normalized::readYaml(mb);
> +  EXPECT_FALSE(!r);
> +  return std::move(*r);
> +}
> +
> +static void toYAML(const NormalizedFile &f, std::string &out) {
> +  llvm::raw_string_ostream ostr(out);
> +  llvm::error_code ec = lld::mach_o::normalized::writeYaml(f, ostr);
> +  EXPECT_TRUE(!ec);
> +}
> +
> +
> +// ppc is no longer supported, but it is here to test endianness handling.
> +TEST(ObjectFileYAML, empty_ppc) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      ppc\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +TEST(ObjectFileYAML, empty_x86_64) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86_64\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +TEST(ObjectFileYAML, empty_x86) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +TEST(ObjectFileYAML, empty_armv6) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      armv6\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +TEST(ObjectFileYAML, empty_armv7) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      armv7\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +TEST(ObjectFileYAML, empty_armv7s) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      armv7s\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7s);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +}
> +
> +
> +TEST(ObjectFileYAML, roundTrip) {
> +  std::string intermediate;
> +  {
> +    NormalizedFile f;
> +    f.arch = lld::MachOLinkingContext::arch_x86_64;
> +    f.fileType = llvm::MachO::MH_OBJECT;
> +    f.flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
> +    f.os = lld::MachOLinkingContext::OS::macOSX;
> +    toYAML(f, intermediate);
> +  }
> +  {
> +    std::unique_ptr<NormalizedFile> f2 = fromYAML(intermediate);
> +    EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_x86_64);
> +    EXPECT_EQ((int)(f2->fileType), llvm::MachO::MH_OBJECT);
> +    EXPECT_EQ((int)(f2->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +    EXPECT_TRUE(f2->sections.empty());
> +    EXPECT_TRUE(f2->localSymbols.empty());
> +    EXPECT_TRUE(f2->globalSymbols.empty());
> +    EXPECT_TRUE(f2->undefinedSymbols.empty());
> +  }
> +}
> +
> +
> +TEST(ObjectFileYAML, oneSymbol) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86_64\n"
> +    "file-type: object\n"
> +    "global-symbols:\n"
> +    "  - name:   _main\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ N_EXT ]\n"
> +    "    sect:   1\n"
> +    "    desc:   [ ]\n"
> +    "    value:  0x100\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_TRUE(f->sections.empty());
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +  EXPECT_EQ(f->globalSymbols.size(), 1UL);
> +  const Symbol& sym = f->globalSymbols[0];
> +  EXPECT_TRUE(sym.name.equals("_main"));
> +  EXPECT_EQ((int)(sym.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym.scope), llvm::MachO::N_EXT);
> +  EXPECT_EQ(sym.sect, 1);
> +  EXPECT_EQ((int)(sym.desc), 0);
> +  EXPECT_EQ((uint64_t)sym.value, 0x100ULL);
> +}
> +
> +
> +TEST(ObjectFileYAML, oneSection) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86_64\n"
> +    "file-type: object\n"
> +    "sections:\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __text\n"
> +    "    type:        S_REGULAR\n"
> +    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS ]\n"
> +    "    alignment:   1\n"
> +    "    address:     0x12345678\n"
> +    "    content:     [ 0x90, 0x90 ]\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_TRUE(f->localSymbols.empty());
> +  EXPECT_TRUE(f->globalSymbols.empty());
> +  EXPECT_TRUE(f->undefinedSymbols.empty());
> +  EXPECT_EQ(f->sections.size(), 1UL);
> +  const Section& sect = f->sections[0];
> +  EXPECT_TRUE(sect.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect.sectionName.equals("__text"));
> +  EXPECT_EQ((uint32_t)(sect.type), (uint32_t)(llvm::MachO::S_REGULAR));
> +  EXPECT_EQ((uint32_t)(sect.attributes),
> +
>  (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS));
> +  EXPECT_EQ(sect.alignment, 1U);
> +  EXPECT_EQ(sect.address, 0x12345678ULL);
> +  EXPECT_EQ(sect.content.size(), 2UL);
> +  EXPECT_EQ((int)(sect.content[0]), 0x90);
> +  EXPECT_EQ((int)(sect.content[1]), 0x90);
> +}
> +
> +
> +TEST(ObjectFileYAML, hello_x86_64) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86_64\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "sections:\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __text\n"
> +    "    type:        S_REGULAR\n"
> +    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS,
> S_ATTR_SOME_INSTRUCTIONS]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0000\n"
> +    "    content:     [ 0x55, 0x48, 0x89, 0xe5, 0x48, 0x8d, 0x3d, 0x00,\n"
> +    "                   0x00, 0x00, 0x00, 0x30, 0xc0, 0xe8, 0x00, 0x00,\n"
> +    "                   0x00, 0x00, 0x31, 0xc0, 0x5d, 0xc3 ]\n"
> +    "    relocations:\n"
> +    "     - offset:     0x0e\n"
> +    "       type:       X86_64_RELOC_BRANCH\n"
> +    "       length:     2\n"
> +    "       pc-rel:     true\n"
> +    "       extern:     true\n"
> +    "       symbol:     2\n"
> +    "     - offset:     0x07\n"
> +    "       type:       X86_64_RELOC_SIGNED\n"
> +    "       length:     2\n"
> +    "       pc-rel:     true\n"
> +    "       extern:     true\n"
> +    "       symbol:     1\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __cstring\n"
> +    "    type:        S_CSTRING_LITERALS\n"
> +    "    attributes:  [ ]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0016\n"
> +    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
> +    "global-symbols:\n"
> +    "  - name:   _main\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ N_EXT ]\n"
> +    "    sect:   1\n"
> +    "    value:  0x0\n"
> +    "local-symbols:\n"
> +    "  - name:   L_.str\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ ]\n"
> +    "    sect:   2\n"
> +    "    value:  0x16\n"
> +    "undefined-symbols:\n"
> +    "  - name:   _printf\n"
> +    "    type:   N_UNDF\n"
> +    "    value:  0x0\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_EQ(f->sections.size(), 2UL);
> +
> +  const Section& sect1 = f->sections[0];
> +  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect1.sectionName.equals("__text"));
> +  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
> +  EXPECT_EQ((uint32_t)(sect1.attributes),
> +
>  (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
> +                                     |
> llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
> +  EXPECT_EQ(sect1.alignment, 0U);
> +  EXPECT_EQ(sect1.address, 0x0ULL);
> +  EXPECT_EQ(sect1.content.size(), 22UL);
> +  EXPECT_EQ((int)(sect1.content[0]), 0x55);
> +  EXPECT_EQ((int)(sect1.content[1]), 0x48);
> +  EXPECT_EQ(sect1.relocations.size(), 2UL);
> +  const Relocation& reloc1 = sect1.relocations[0];
> +  EXPECT_EQ(reloc1.offset, 0x0eU);
> +  EXPECT_FALSE(reloc1.scattered);
> +  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::X86_64_RELOC_BRANCH);
> +  EXPECT_EQ(reloc1.length, 2);
> +  EXPECT_TRUE(reloc1.pcRel);
> +  EXPECT_TRUE(reloc1.isExtern);
> +  EXPECT_EQ(reloc1.symbol, 2U);
> +  EXPECT_EQ((int)(reloc1.value), 0);
> +  const Relocation& reloc2 = sect1.relocations[1];
> +  EXPECT_EQ(reloc2.offset, 0x07U);
> +  EXPECT_FALSE(reloc2.scattered);
> +  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::X86_64_RELOC_SIGNED);
> +  EXPECT_EQ(reloc2.length, 2);
> +  EXPECT_TRUE(reloc2.pcRel);
> +  EXPECT_TRUE(reloc2.isExtern);
> +  EXPECT_EQ(reloc2.symbol, 1U);
> +  EXPECT_EQ((int)(reloc2.value), 0);
> +
> +  const Section& sect2 = f->sections[1];
> +  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
> +  EXPECT_EQ((uint32_t)(sect2.type),
> (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
> +  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
> +  EXPECT_EQ(sect2.alignment, 0U);
> +  EXPECT_EQ(sect2.address, 0x016ULL);
> +  EXPECT_EQ(sect2.content.size(), 7UL);
> +  EXPECT_EQ((int)(sect2.content[0]), 0x68);
> +  EXPECT_EQ((int)(sect2.content[1]), 0x65);
> +  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
> +
> +  EXPECT_EQ(f->globalSymbols.size(), 1UL);
> +  const Symbol& sym1 = f->globalSymbols[0];
> +  EXPECT_TRUE(sym1.name.equals("_main"));
> +  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
> +  EXPECT_EQ(sym1.sect, 1);
> +  EXPECT_EQ((int)(sym1.desc), 0);
> +  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
> +  EXPECT_EQ(f->localSymbols.size(), 1UL);
> +  const Symbol& sym2 = f->localSymbols[0];
> +  EXPECT_TRUE(sym2.name.equals("L_.str"));
> +  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym2.scope), 0);
> +  EXPECT_EQ(sym2.sect, 2);
> +  EXPECT_EQ((int)(sym2.desc), 0);
> +  EXPECT_EQ((uint64_t)sym2.value, 0x16ULL);
> +  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
> +  const Symbol& sym3 = f->undefinedSymbols[0];
> +  EXPECT_TRUE(sym3.name.equals("_printf"));
> +  EXPECT_EQ((int)(sym3.type), llvm::MachO::N_UNDF);
> +  EXPECT_EQ((int)(sym3.scope), 0);
> +  EXPECT_EQ(sym3.sect, 0);
> +  EXPECT_EQ((int)(sym3.desc), 0);
> +  EXPECT_EQ((uint64_t)sym3.value, 0x0ULL);
> +}
> +
> +
> +TEST(ObjectFileYAML, hello_x86) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      x86\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "sections:\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __text\n"
> +    "    type:        S_REGULAR\n"
> +    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS,
> S_ATTR_SOME_INSTRUCTIONS]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0000\n"
> +    "    content:     [ 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0xe8, 0x00,\n"
> +    "                   0x00, 0x00, 0x00, 0x58, 0x8d, 0x80, 0x16, 0x00,\n"
> +    "                   0x00, 0x00, 0x89, 0x04, 0x24, 0xe8, 0xe6, 0xff,\n"
> +    "                   0xff, 0xff, 0x31, 0xc0, 0x83, 0xc4, 0x08, 0x5d,\n"
> +    "                   0xc3 ]\n"
> +    "    relocations:\n"
> +    "     - offset:     0x16\n"
> +    "       type:       GENERIC_RELOC_VANILLA\n"
> +    "       length:     2\n"
> +    "       pc-rel:     true\n"
> +    "       extern:     true\n"
> +    "       symbol:     1\n"
> +    "     - offset:     0x0e\n"
> +    "       scattered:  true\n"
> +    "       type:       GENERIC_RELOC_LOCAL_SECTDIFF\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0x21\n"
> +    "     - offset:     0x0\n"
> +    "       scattered:  true\n"
> +    "       type:       GENERIC_RELOC_PAIR\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0xb\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __cstring\n"
> +    "    type:        S_CSTRING_LITERALS\n"
> +    "    attributes:  [ ]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0021\n"
> +    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
> +    "global-symbols:\n"
> +    "  - name:   _main\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ N_EXT ]\n"
> +    "    sect:   1\n"
> +    "    value:  0x0\n"
> +    "undefined-symbols:\n"
> +    "  - name:   _printf\n"
> +    "    type:   N_UNDF\n"
> +    "    value:  0x0\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_EQ(f->sections.size(), 2UL);
> +
> +  const Section& sect1 = f->sections[0];
> +  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect1.sectionName.equals("__text"));
> +  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
> +  EXPECT_EQ((uint32_t)(sect1.attributes),
> +
>  (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
> +                                     |
> llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
> +  EXPECT_EQ(sect1.alignment, 0U);
> +  EXPECT_EQ(sect1.address, 0x0ULL);
> +  EXPECT_EQ(sect1.content.size(), 33UL);
> +  EXPECT_EQ((int)(sect1.content[0]), 0x55);
> +  EXPECT_EQ((int)(sect1.content[1]), 0x89);
> +  EXPECT_EQ(sect1.relocations.size(), 3UL);
> +  const Relocation& reloc1 = sect1.relocations[0];
> +  EXPECT_EQ(reloc1.offset, 0x16U);
> +  EXPECT_FALSE(reloc1.scattered);
> +  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::GENERIC_RELOC_VANILLA);
> +  EXPECT_EQ(reloc1.length, 2);
> +  EXPECT_TRUE(reloc1.pcRel);
> +  EXPECT_TRUE(reloc1.isExtern);
> +  EXPECT_EQ(reloc1.symbol, 1U);
> +  EXPECT_EQ((int)(reloc1.value), 0);
> +  const Relocation& reloc2 = sect1.relocations[1];
> +  EXPECT_EQ(reloc2.offset, 0x0eU);
> +  EXPECT_TRUE(reloc2.scattered);
> +  EXPECT_EQ((int)reloc2.type,
> (int)llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
> +  EXPECT_EQ(reloc2.length, 2);
> +  EXPECT_FALSE(reloc2.pcRel);
> +  EXPECT_EQ(reloc2.symbol, 0U);
> +  EXPECT_EQ((int)(reloc2.value), 0x21);
> +  const Relocation& reloc3 = sect1.relocations[2];
> +  EXPECT_EQ(reloc3.offset, 0U);
> +  EXPECT_TRUE(reloc3.scattered);
> +  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::GENERIC_RELOC_PAIR);
> +  EXPECT_EQ(reloc3.length, 2);
> +  EXPECT_FALSE(reloc3.pcRel);
> +  EXPECT_EQ(reloc3.symbol, 0U);
> +  EXPECT_EQ((int)(reloc3.value), 0xb);
> +
> +  const Section& sect2 = f->sections[1];
> +  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
> +  EXPECT_EQ((uint32_t)(sect2.type),
> (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
> +  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
> +  EXPECT_EQ(sect2.alignment, 0U);
> +  EXPECT_EQ(sect2.address, 0x021ULL);
> +  EXPECT_EQ(sect2.content.size(), 7UL);
> +  EXPECT_EQ((int)(sect2.content[0]), 0x68);
> +  EXPECT_EQ((int)(sect2.content[1]), 0x65);
> +  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
> +
> +  EXPECT_EQ(f->globalSymbols.size(), 1UL);
> +  const Symbol& sym1 = f->globalSymbols[0];
> +  EXPECT_TRUE(sym1.name.equals("_main"));
> +  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
> +  EXPECT_EQ(sym1.sect, 1);
> +  EXPECT_EQ((int)(sym1.desc), 0);
> +  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
> +  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
> +  const Symbol& sym2 = f->undefinedSymbols[0];
> +  EXPECT_TRUE(sym2.name.equals("_printf"));
> +  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
> +  EXPECT_EQ((int)(sym2.scope), 0);
> +  EXPECT_EQ(sym2.sect, 0);
> +  EXPECT_EQ((int)(sym2.desc), 0);
> +  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
> +}
> +
> +TEST(ObjectFileYAML, hello_armv6) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      armv6\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "sections:\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __text\n"
> +    "    type:        S_REGULAR\n"
> +    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS,
> S_ATTR_SOME_INSTRUCTIONS]\n"
> +    "    alignment:   2\n"
> +    "    address:     0x0000\n"
> +    "    content:     [ 0x80, 0x40, 0x2d, 0xe9, 0x10, 0x00, 0x9f, 0xe5,\n"
> +    "                   0x0d, 0x70, 0xa0, 0xe1, 0x00, 0x00, 0x8f, 0xe0,\n"
> +    "                   0xfa, 0xff, 0xff, 0xeb, 0x00, 0x00, 0xa0, 0xe3,\n"
> +    "                   0x80, 0x80, 0xbd, 0xe8, 0x0c, 0x00, 0x00, 0x00
> ]\n"
> +    "    relocations:\n"
> +    "     - offset:     0x1c\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_SECTDIFF\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0x20\n"
> +    "     - offset:     0x0\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_PAIR\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0xc\n"
> +    "     - offset:     0x10\n"
> +    "       type:       ARM_RELOC_BR24\n"
> +    "       length:     2\n"
> +    "       pc-rel:     true\n"
> +    "       extern:     true\n"
> +    "       symbol:     1\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __cstring\n"
> +    "    type:        S_CSTRING_LITERALS\n"
> +    "    attributes:  [ ]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0020\n"
> +    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
> +    "global-symbols:\n"
> +    "  - name:   _main\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ N_EXT ]\n"
> +    "    sect:   1\n"
> +    "    value:  0x0\n"
> +    "undefined-symbols:\n"
> +    "  - name:   _printf\n"
> +    "    type:   N_UNDF\n"
> +    "    value:  0x0\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_EQ(f->sections.size(), 2UL);
> +
> +  const Section& sect1 = f->sections[0];
> +  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect1.sectionName.equals("__text"));
> +  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
> +  EXPECT_EQ((uint32_t)(sect1.attributes),
> +
>  (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
> +                                     |
> llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
> +  EXPECT_EQ(sect1.alignment, 2U);
> +  EXPECT_EQ(sect1.address, 0x0ULL);
> +  EXPECT_EQ(sect1.content.size(), 32UL);
> +  EXPECT_EQ((int)(sect1.content[0]), 0x80);
> +  EXPECT_EQ((int)(sect1.content[1]), 0x40);
> +  EXPECT_EQ(sect1.relocations.size(), 3UL);
> +  const Relocation& reloc1 = sect1.relocations[0];
> +  EXPECT_EQ(reloc1.offset, 0x1cU);
> +  EXPECT_TRUE(reloc1.scattered);
> +  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_RELOC_SECTDIFF);
> +  EXPECT_EQ(reloc1.length, 2);
> +  EXPECT_FALSE(reloc1.pcRel);
> +  EXPECT_EQ(reloc1.symbol, 0U);
> +  EXPECT_EQ((int)(reloc1.value), 0x20);
> +  const Relocation& reloc2 = sect1.relocations[1];
> +  EXPECT_EQ(reloc2.offset, 0x0U);
> +  EXPECT_TRUE(reloc2.scattered);
> +  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_PAIR);
> +  EXPECT_EQ(reloc2.length, 2);
> +  EXPECT_FALSE(reloc2.pcRel);
> +  EXPECT_EQ(reloc2.symbol, 0U);
> +  EXPECT_EQ((int)(reloc2.value), 0xc);
> +  const Relocation& reloc3 = sect1.relocations[2];
> +  EXPECT_EQ(reloc3.offset, 0x10U);
> +  EXPECT_FALSE(reloc3.scattered);
> +  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_BR24);
> +  EXPECT_EQ(reloc3.length, 2);
> +  EXPECT_TRUE(reloc3.pcRel);
> +  EXPECT_TRUE(reloc3.isExtern);
> +  EXPECT_EQ(reloc3.symbol, 1U);
> +  EXPECT_EQ((int)(reloc3.value), 0);
> +
> +  const Section& sect2 = f->sections[1];
> +  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
> +  EXPECT_EQ((uint32_t)(sect2.type),
> (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
> +  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
> +  EXPECT_EQ(sect2.alignment, 0U);
> +  EXPECT_EQ(sect2.address, 0x020ULL);
> +  EXPECT_EQ(sect2.content.size(), 7UL);
> +  EXPECT_EQ((int)(sect2.content[0]), 0x68);
> +  EXPECT_EQ((int)(sect2.content[1]), 0x65);
> +  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
> +
> +  EXPECT_EQ(f->globalSymbols.size(), 1UL);
> +  const Symbol& sym1 = f->globalSymbols[0];
> +  EXPECT_TRUE(sym1.name.equals("_main"));
> +  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
> +  EXPECT_EQ(sym1.sect, 1);
> +  EXPECT_EQ((int)(sym1.desc), 0);
> +  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
> +  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
> +  const Symbol& sym2 = f->undefinedSymbols[0];
> +  EXPECT_TRUE(sym2.name.equals("_printf"));
> +  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
> +  EXPECT_EQ((int)(sym2.scope), 0);
> +  EXPECT_EQ(sym2.sect, 0);
> +  EXPECT_EQ((int)(sym2.desc), 0);
> +  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
> +}
> +
> +
> +
> +TEST(ObjectFileYAML, hello_armv7) {
> +  std::unique_ptr<NormalizedFile> f = fromYAML(
> +    "---\n"
> +    "arch:      armv7\n"
> +    "file-type: object\n"
> +    "flags:     [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
> +    "sections:\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __text\n"
> +    "    type:        S_REGULAR\n"
> +    "    attributes:  [ S_ATTR_PURE_INSTRUCTIONS,
> S_ATTR_SOME_INSTRUCTIONS]\n"
> +    "    alignment:   1\n"
> +    "    address:     0x0000\n"
> +    "    content:     [ 0x80, 0xb5, 0x40, 0xf2, 0x06, 0x00, 0x6f, 0x46,\n"
> +    "                   0xc0, 0xf2, 0x00, 0x00, 0x78, 0x44, 0xff, 0xf7,\n"
> +    "                   0xf8, 0xef, 0x00, 0x20, 0x80, 0xbd ]\n"
> +    "    relocations:\n"
> +    "     - offset:     0x0e\n"
> +    "       type:       ARM_THUMB_RELOC_BR22\n"
> +    "       length:     2\n"
> +    "       pc-rel:     true\n"
> +    "       extern:     true\n"
> +    "       symbol:     1\n"
> +    "     - offset:     0x08\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_HALF_SECTDIFF\n"
> +    "       length:     3\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0x16\n"
> +    "     - offset:     0x06\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_PAIR\n"
> +    "       length:     3\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0xc\n"
> +    "     - offset:     0x02\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_HALF_SECTDIFF\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0x16\n"
> +    "     - offset:     0x0\n"
> +    "       scattered:  true\n"
> +    "       type:       ARM_RELOC_PAIR\n"
> +    "       length:     2\n"
> +    "       pc-rel:     false\n"
> +    "       value:      0xc\n"
> +    "  - segment:     __TEXT\n"
> +    "    section:     __cstring\n"
> +    "    type:        S_CSTRING_LITERALS\n"
> +    "    attributes:  [ ]\n"
> +    "    alignment:   0\n"
> +    "    address:     0x0016\n"
> +    "    content:     [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
> +    "global-symbols:\n"
> +    "  - name:   _main\n"
> +    "    type:   N_SECT\n"
> +    "    scope:  [ N_EXT ]\n"
> +    "    sect:   1\n"
> +    "    desc:   [ N_ARM_THUMB_DEF ]\n"
> +    "    value:  0x0\n"
> +    "undefined-symbols:\n"
> +    "  - name:   _printf\n"
> +    "    type:   N_UNDF\n"
> +    "    value:  0x0\n"
> +    "...\n");
> +  EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
> +  EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
> +  EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
> +  EXPECT_EQ(f->sections.size(), 2UL);
> +
> +  const Section& sect1 = f->sections[0];
> +  EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect1.sectionName.equals("__text"));
> +  EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
> +  EXPECT_EQ((uint32_t)(sect1.attributes),
> +
>  (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
> +                                     |
> llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
> +  EXPECT_EQ(sect1.alignment, 1U);
> +  EXPECT_EQ(sect1.address, 0x0ULL);
> +  EXPECT_EQ(sect1.content.size(), 22UL);
> +  EXPECT_EQ((int)(sect1.content[0]), 0x80);
> +  EXPECT_EQ((int)(sect1.content[1]), 0xb5);
> +  EXPECT_EQ(sect1.relocations.size(), 5UL);
> +  const Relocation& reloc1 = sect1.relocations[0];
> +  EXPECT_EQ(reloc1.offset, 0x0eU);
> +  EXPECT_FALSE(reloc1.scattered);
> +  EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_THUMB_RELOC_BR22);
> +  EXPECT_EQ(reloc1.length, 2);
> +  EXPECT_TRUE(reloc1.pcRel);
> +  EXPECT_TRUE(reloc1.isExtern);
> +  EXPECT_EQ(reloc1.symbol, 1U);
> +  EXPECT_EQ((int)(reloc1.value), 0);
> +  const Relocation& reloc2 = sect1.relocations[1];
> +  EXPECT_EQ(reloc2.offset, 0x8U);
> +  EXPECT_TRUE(reloc2.scattered);
> +  EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
> +  EXPECT_EQ(reloc2.length, 3);
> +  EXPECT_FALSE(reloc2.pcRel);
> +  EXPECT_EQ(reloc2.symbol, 0U);
> +  EXPECT_EQ((int)(reloc2.value), 0x16);
> +  const Relocation& reloc3 = sect1.relocations[2];
> +  EXPECT_EQ(reloc3.offset, 0x6U);
> +  EXPECT_TRUE(reloc3.scattered);
> +  EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_PAIR);
> +  EXPECT_EQ(reloc3.length, 3);
> +  EXPECT_FALSE(reloc3.pcRel);
> +  EXPECT_EQ(reloc3.symbol, 0U);
> +  EXPECT_EQ((int)(reloc3.value), 0xc);
> +   const Relocation& reloc4 = sect1.relocations[3];
> +  EXPECT_EQ(reloc4.offset, 0x2U);
> +  EXPECT_TRUE(reloc4.scattered);
> +  EXPECT_EQ((int)reloc4.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
> +  EXPECT_EQ(reloc4.length, 2);
> +  EXPECT_FALSE(reloc4.pcRel);
> +  EXPECT_EQ(reloc4.symbol, 0U);
> +  EXPECT_EQ((int)(reloc4.value), 0x16);
> +  const Relocation& reloc5 = sect1.relocations[4];
> +  EXPECT_EQ(reloc5.offset, 0x0U);
> +  EXPECT_TRUE(reloc5.scattered);
> +  EXPECT_EQ((int)reloc5.type, (int)llvm::MachO::ARM_RELOC_PAIR);
> +  EXPECT_EQ(reloc5.length, 2);
> +  EXPECT_FALSE(reloc5.pcRel);
> +  EXPECT_EQ(reloc5.symbol, 0U);
> +  EXPECT_EQ((int)(reloc5.value), 0xc);
> +
> +  const Section& sect2 = f->sections[1];
> +  EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
> +  EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
> +  EXPECT_EQ((uint32_t)(sect2.type),
> (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
> +  EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
> +  EXPECT_EQ(sect2.alignment, 0U);
> +  EXPECT_EQ(sect2.address, 0x016ULL);
> +  EXPECT_EQ(sect2.content.size(), 7UL);
> +  EXPECT_EQ((int)(sect2.content[0]), 0x68);
> +  EXPECT_EQ((int)(sect2.content[1]), 0x65);
> +  EXPECT_EQ((int)(sect2.content[2]), 0x6c);
> +
> +  EXPECT_EQ(f->globalSymbols.size(), 1UL);
> +  const Symbol& sym1 = f->globalSymbols[0];
> +  EXPECT_TRUE(sym1.name.equals("_main"));
> +  EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
> +  EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
> +  EXPECT_EQ(sym1.sect, 1);
> +  EXPECT_EQ((int)(sym1.desc), (int)(llvm::MachO::N_ARM_THUMB_DEF));
> +  EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
> +  EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
> +  const Symbol& sym2 = f->undefinedSymbols[0];
> +  EXPECT_TRUE(sym2.name.equals("_printf"));
> +  EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
> +  EXPECT_EQ((int)(sym2.scope), 0);
> +  EXPECT_EQ(sym2.sect, 0);
> +  EXPECT_EQ((int)(sym2.desc), 0);
> +  EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131007/60e6353c/attachment.html>


More information about the llvm-commits mailing list