[lld] r192147 - Supoort mach-o encoded in yaml.
Nick Kledzik
kledzik at apple.com
Mon Oct 7 18:10:16 PDT 2013
There was a change needed to include/llvm/Support/MachO.h needed too. I’ve
committed that and will watch to make sure the bots clear.
-Nick
On Oct 7, 2013, at 5:54 PM, Rui Ueyama <ruiu at google.com> wrote:
> 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 §) {
> + 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/c261ec7c/attachment.html>
More information about the llvm-commits
mailing list