From: Rafael Espindola Date: Fri, 5 Apr 2013 20:00:35 +0000 (+0000) Subject: Move yaml2obj to tools too. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=3455b32b3e795ea27a31b6cb1c225812515e3e2c Move yaml2obj to tools too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178904 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 6871e654fb1..1d216924b15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -419,7 +419,6 @@ add_subdirectory(utils/count) add_subdirectory(utils/not) add_subdirectory(utils/llvm-lit) add_subdirectory(utils/yaml-bench) -add_subdirectory(utils/yaml2obj) add_subdirectory(projects) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 9b80ee5a23a..6b7c884516a 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -44,6 +44,7 @@ add_subdirectory(llvm-mcmarkup) add_subdirectory(llvm-symbolizer) add_subdirectory(obj2yaml) +add_subdirectory(yaml2obj) if( NOT WIN32 ) add_subdirectory(lto) diff --git a/tools/Makefile b/tools/Makefile index b8f21d2ce19..eaf9ed35772 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -35,7 +35,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ llvm-diff macho-dump llvm-objdump llvm-readobj \ llvm-rtdyld llvm-dwarfdump llvm-cov \ llvm-size llvm-stress llvm-mcmarkup \ - llvm-symbolizer obj2yaml + llvm-symbolizer obj2yaml yaml2obj # If Intel JIT Events support is configured, build an extra tool to test it. ifeq ($(USE_INTEL_JITEVENTS), 1) diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt new file mode 100644 index 00000000000..f8b11975246 --- /dev/null +++ b/tools/yaml2obj/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_utility(yaml2obj + yaml2obj.cpp + ) + +target_link_libraries(yaml2obj LLVMSupport) diff --git a/tools/yaml2obj/Makefile b/tools/yaml2obj/Makefile new file mode 100644 index 00000000000..cb6f47724b6 --- /dev/null +++ b/tools/yaml2obj/Makefile @@ -0,0 +1,20 @@ +##===- utils/yaml2obj/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TOOLNAME = yaml2obj +LINK_COMPONENTS := support + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS = 1 + +# Don't install this utility +NO_INSTALL = 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp new file mode 100644 index 00000000000..191c49fb59c --- /dev/null +++ b/tools/yaml2obj/yaml2obj.cpp @@ -0,0 +1,707 @@ +//===- yaml2obj - Convert YAML to a binary object file --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program takes a YAML description of an object file and outputs the +// binary equivalent. +// +// This is used for writing tests that require binary files. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include + +using namespace llvm; + +static cl::opt + Input(cl::Positional, cl::desc(""), cl::init("-")); + +template +typename llvm::enable_if_c::is_integer, bool>::type +getAs(const llvm::yaml::ScalarNode *SN, T &Result) { + SmallString<4> Storage; + StringRef Value = SN->getValue(Storage); + if (Value.getAsInteger(0, Result)) + return false; + return true; +} + +// Given a container with begin and end with ::value_type of a character type. +// Iterate through pairs of characters in the the set of [a-fA-F0-9] ignoring +// all other characters. +struct hex_pair_iterator { + StringRef::const_iterator Current, End; + typedef SmallVector value_type; + value_type Pair; + bool IsDone; + + hex_pair_iterator(StringRef C) + : Current(C.begin()), End(C.end()), IsDone(false) { + // Initalize Pair. + ++*this; + } + + // End iterator. + hex_pair_iterator() : Current(), End(), IsDone(true) {} + + value_type operator *() const { + return Pair; + } + + hex_pair_iterator operator ++() { + // We're at the end of the input. + if (Current == End) { + IsDone = true; + return *this; + } + Pair = value_type(); + for (; Current != End && Pair.size() != 2; ++Current) { + // Is a valid hex digit. + if ((*Current >= '0' && *Current <= '9') || + (*Current >= 'a' && *Current <= 'f') || + (*Current >= 'A' && *Current <= 'F')) + Pair.push_back(*Current); + } + // Hit the end without getting 2 hex digits. Pair is invalid. + if (Pair.size() != 2) + IsDone = true; + return *this; + } + + bool operator ==(const hex_pair_iterator Other) { + return (IsDone == Other.IsDone) || + (Current == Other.Current && End == Other.End); + } + + bool operator !=(const hex_pair_iterator Other) { + return !(*this == Other); + } +}; + +template +static bool hexStringToByteArray(StringRef Str, ContainerOut &Out) { + for (hex_pair_iterator I(Str), E; I != E; ++I) { + typename hex_pair_iterator::value_type Pair = *I; + typename ContainerOut::value_type Byte; + if (StringRef(Pair.data(), 2).getAsInteger(16, Byte)) + return false; + Out.push_back(Byte); + } + return true; +} + +// The structure of the yaml files is not an exact 1:1 match to COFF. In order +// to use yaml::IO, we use these structures which are closer to the source. +namespace COFFYAML { + struct Relocation { + uint32_t VirtualAddress; + uint32_t SymbolTableIndex; + COFF::RelocationTypeX86 Type; + }; + + struct Section { + COFF::SectionCharacteristics Characteristics; + StringRef SectionData; + std::vector Relocations; + StringRef Name; + }; + + struct Header { + COFF::MachineTypes Machine; + COFF::Characteristics Characteristics; + }; + + struct Symbol { + COFF::SymbolBaseType SimpleType; + uint8_t NumberOfAuxSymbols; + StringRef Name; + COFF::SymbolStorageClass StorageClass; + StringRef AuxillaryData; + COFF::SymbolComplexType ComplexType; + uint32_t Value; + uint16_t SectionNumber; + }; + + struct Object { + Header HeaderData; + std::vector
Sections; + std::vector Symbols; + }; +} + +/// This parses a yaml stream that represents a COFF object file. +/// See docs/yaml2obj for the yaml scheema. +struct COFFParser { + COFFParser(COFFYAML::Object &Obj) : Obj(Obj) { + std::memset(&Header, 0, sizeof(Header)); + // A COFF string table always starts with a 4 byte size field. Offsets into + // it include this size, so allocate it now. + StringTable.append(4, 0); + } + + void parseHeader() { + Header.Machine = Obj.HeaderData.Machine; + Header.Characteristics = Obj.HeaderData.Characteristics; + } + + bool parseSections() { + for (std::vector::iterator i = Obj.Sections.begin(), + e = Obj.Sections.end(); i != e; ++i) { + const COFFYAML::Section &YamlSection = *i; + Section Sec; + std::memset(&Sec.Header, 0, sizeof(Sec.Header)); + + // If the name is less than 8 bytes, store it in place, otherwise + // store it in the string table. + StringRef Name = YamlSection.Name; + std::fill_n(Sec.Header.Name, unsigned(COFF::NameSize), 0); + if (Name.size() <= COFF::NameSize) { + std::copy(Name.begin(), Name.end(), Sec.Header.Name); + } else { + // Add string to the string table and format the index for output. + unsigned Index = getStringIndex(Name); + std::string str = utostr(Index); + if (str.size() > 7) { + errs() << "String table got too large"; + return false; + } + Sec.Header.Name[0] = '/'; + std::copy(str.begin(), str.end(), Sec.Header.Name + 1); + } + + Sec.Header.Characteristics = YamlSection.Characteristics; + + StringRef Data = YamlSection.SectionData; + if (!hexStringToByteArray(Data, Sec.Data)) { + errs() << "SectionData must be a collection of pairs of hex bytes"; + return false; + } + Sections.push_back(Sec); + } + return true; + } + + bool parseSymbols() { + for (std::vector::iterator i = Obj.Symbols.begin(), + e = Obj.Symbols.end(); i != e; ++i) { + COFFYAML::Symbol YamlSymbol = *i; + Symbol Sym; + std::memset(&Sym.Header, 0, sizeof(Sym.Header)); + + // If the name is less than 8 bytes, store it in place, otherwise + // store it in the string table. + StringRef Name = YamlSymbol.Name; + std::fill_n(Sym.Header.Name, unsigned(COFF::NameSize), 0); + if (Name.size() <= COFF::NameSize) { + std::copy(Name.begin(), Name.end(), Sym.Header.Name); + } else { + // Add string to the string table and format the index for output. + unsigned Index = getStringIndex(Name); + *reinterpret_cast( + Sym.Header.Name + 4) = Index; + } + + Sym.Header.Value = YamlSymbol.Value; + Sym.Header.Type |= YamlSymbol.SimpleType; + Sym.Header.Type |= YamlSymbol.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT; + Sym.Header.StorageClass = YamlSymbol.StorageClass; + Sym.Header.SectionNumber = YamlSymbol.SectionNumber; + + StringRef Data = YamlSymbol.AuxillaryData; + if (!hexStringToByteArray(Data, Sym.AuxSymbols)) { + errs() << "AuxillaryData must be a collection of pairs of hex bytes"; + return false; + } + Symbols.push_back(Sym); + } + return true; + } + + bool parse() { + parseHeader(); + if (!parseSections()) + return false; + if (!parseSymbols()) + return false; + return true; + } + + unsigned getStringIndex(StringRef Str) { + StringMap::iterator i = StringTableMap.find(Str); + if (i == StringTableMap.end()) { + unsigned Index = StringTable.size(); + StringTable.append(Str.begin(), Str.end()); + StringTable.push_back(0); + StringTableMap[Str] = Index; + return Index; + } + return i->second; + } + + COFFYAML::Object &Obj; + COFF::header Header; + + struct Section { + COFF::section Header; + std::vector Data; + std::vector Relocations; + }; + + struct Symbol { + COFF::symbol Header; + std::vector AuxSymbols; + }; + + std::vector
Sections; + std::vector Symbols; + StringMap StringTableMap; + std::string StringTable; +}; + +// Take a CP and assign addresses and sizes to everything. Returns false if the +// layout is not valid to do. +static bool layoutCOFF(COFFParser &CP) { + uint32_t SectionTableStart = 0; + uint32_t SectionTableSize = 0; + + // The section table starts immediately after the header, including the + // optional header. + SectionTableStart = sizeof(COFF::header) + CP.Header.SizeOfOptionalHeader; + SectionTableSize = sizeof(COFF::section) * CP.Sections.size(); + + uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize; + + // Assign each section data address consecutively. + for (std::vector::iterator i = CP.Sections.begin(), + e = CP.Sections.end(); + i != e; ++i) { + if (!i->Data.empty()) { + i->Header.SizeOfRawData = i->Data.size(); + i->Header.PointerToRawData = CurrentSectionDataOffset; + CurrentSectionDataOffset += i->Header.SizeOfRawData; + // TODO: Handle alignment. + } else { + i->Header.SizeOfRawData = 0; + i->Header.PointerToRawData = 0; + } + } + + uint32_t SymbolTableStart = CurrentSectionDataOffset; + + // Calculate number of symbols. + uint32_t NumberOfSymbols = 0; + for (std::vector::iterator i = CP.Symbols.begin(), + e = CP.Symbols.end(); + i != e; ++i) { + if (i->AuxSymbols.size() % COFF::SymbolSize != 0) { + errs() << "AuxillaryData size not a multiple of symbol size!\n"; + return false; + } + i->Header.NumberOfAuxSymbols = i->AuxSymbols.size() / COFF::SymbolSize; + NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols; + } + + // Store all the allocated start addresses in the header. + CP.Header.NumberOfSections = CP.Sections.size(); + CP.Header.NumberOfSymbols = NumberOfSymbols; + CP.Header.PointerToSymbolTable = SymbolTableStart; + + *reinterpret_cast(&CP.StringTable[0]) + = CP.StringTable.size(); + + return true; +} + +template +struct binary_le_impl { + value_type Value; + binary_le_impl(value_type V) : Value(V) {} +}; + +template +raw_ostream &operator <<( raw_ostream &OS + , const binary_le_impl &BLE) { + char Buffer[sizeof(BLE.Value)]; + support::endian::write( + Buffer, BLE.Value); + OS.write(Buffer, sizeof(BLE.Value)); + return OS; +} + +template +binary_le_impl binary_le(value_type V) { + return binary_le_impl(V); +} + +void writeCOFF(COFFParser &CP, raw_ostream &OS) { + OS << binary_le(CP.Header.Machine) + << binary_le(CP.Header.NumberOfSections) + << binary_le(CP.Header.TimeDateStamp) + << binary_le(CP.Header.PointerToSymbolTable) + << binary_le(CP.Header.NumberOfSymbols) + << binary_le(CP.Header.SizeOfOptionalHeader) + << binary_le(CP.Header.Characteristics); + + // Output section table. + for (std::vector::const_iterator i = CP.Sections.begin(), + e = CP.Sections.end(); + i != e; ++i) { + OS.write(i->Header.Name, COFF::NameSize); + OS << binary_le(i->Header.VirtualSize) + << binary_le(i->Header.VirtualAddress) + << binary_le(i->Header.SizeOfRawData) + << binary_le(i->Header.PointerToRawData) + << binary_le(i->Header.PointerToRelocations) + << binary_le(i->Header.PointerToLineNumbers) + << binary_le(i->Header.NumberOfRelocations) + << binary_le(i->Header.NumberOfLineNumbers) + << binary_le(i->Header.Characteristics); + } + + // Output section data. + for (std::vector::const_iterator i = CP.Sections.begin(), + e = CP.Sections.end(); + i != e; ++i) { + if (!i->Data.empty()) + OS.write(reinterpret_cast(&i->Data[0]), i->Data.size()); + } + + // Output symbol table. + + for (std::vector::const_iterator i = CP.Symbols.begin(), + e = CP.Symbols.end(); + i != e; ++i) { + OS.write(i->Header.Name, COFF::NameSize); + OS << binary_le(i->Header.Value) + << binary_le(i->Header.SectionNumber) + << binary_le(i->Header.Type) + << binary_le(i->Header.StorageClass) + << binary_le(i->Header.NumberOfAuxSymbols); + if (!i->AuxSymbols.empty()) + OS.write( reinterpret_cast(&i->AuxSymbols[0]) + , i->AuxSymbols.size()); + } + + // Output string table. + OS.write(&CP.StringTable[0], CP.StringTable.size()); +} + +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) + +namespace llvm { + +namespace COFF { + Characteristics operator|(Characteristics a, Characteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); + } + + SectionCharacteristics + operator|(SectionCharacteristics a, SectionCharacteristics b) { + uint32_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); + } +} + +namespace yaml { + +#define BCase(X) IO.bitSetCase(Value, #X, COFF::X); + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::SectionCharacteristics &Value) { + BCase(IMAGE_SCN_TYPE_NO_PAD); + BCase(IMAGE_SCN_CNT_CODE); + BCase(IMAGE_SCN_CNT_INITIALIZED_DATA); + BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA); + BCase(IMAGE_SCN_LNK_OTHER); + BCase(IMAGE_SCN_LNK_INFO); + BCase(IMAGE_SCN_LNK_REMOVE); + BCase(IMAGE_SCN_LNK_COMDAT); + BCase(IMAGE_SCN_GPREL); + BCase(IMAGE_SCN_MEM_PURGEABLE); + BCase(IMAGE_SCN_MEM_16BIT); + BCase(IMAGE_SCN_MEM_LOCKED); + BCase(IMAGE_SCN_MEM_PRELOAD); + BCase(IMAGE_SCN_ALIGN_1BYTES); + BCase(IMAGE_SCN_ALIGN_2BYTES); + BCase(IMAGE_SCN_ALIGN_4BYTES); + BCase(IMAGE_SCN_ALIGN_8BYTES); + BCase(IMAGE_SCN_ALIGN_16BYTES); + BCase(IMAGE_SCN_ALIGN_32BYTES); + BCase(IMAGE_SCN_ALIGN_64BYTES); + BCase(IMAGE_SCN_ALIGN_128BYTES); + BCase(IMAGE_SCN_ALIGN_256BYTES); + BCase(IMAGE_SCN_ALIGN_512BYTES); + BCase(IMAGE_SCN_ALIGN_1024BYTES); + BCase(IMAGE_SCN_ALIGN_2048BYTES); + BCase(IMAGE_SCN_ALIGN_4096BYTES); + BCase(IMAGE_SCN_ALIGN_8192BYTES); + BCase(IMAGE_SCN_LNK_NRELOC_OVFL); + BCase(IMAGE_SCN_MEM_DISCARDABLE); + BCase(IMAGE_SCN_MEM_NOT_CACHED); + BCase(IMAGE_SCN_MEM_NOT_PAGED); + BCase(IMAGE_SCN_MEM_SHARED); + BCase(IMAGE_SCN_MEM_EXECUTE); + BCase(IMAGE_SCN_MEM_READ); + BCase(IMAGE_SCN_MEM_WRITE); + } +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::Characteristics &Value) { + BCase(IMAGE_FILE_RELOCS_STRIPPED); + BCase(IMAGE_FILE_EXECUTABLE_IMAGE); + BCase(IMAGE_FILE_LINE_NUMS_STRIPPED); + BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED); + BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM); + BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE); + BCase(IMAGE_FILE_BYTES_REVERSED_LO); + BCase(IMAGE_FILE_32BIT_MACHINE); + BCase(IMAGE_FILE_DEBUG_STRIPPED); + BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP); + BCase(IMAGE_FILE_NET_RUN_FROM_SWAP); + BCase(IMAGE_FILE_SYSTEM); + BCase(IMAGE_FILE_DLL); + BCase(IMAGE_FILE_UP_SYSTEM_ONLY); + BCase(IMAGE_FILE_BYTES_REVERSED_HI); + } +}; +#undef BCase + +#define ECase(X) IO.enumCase(Value, #X, COFF::X); + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolComplexType &Value) { + ECase(IMAGE_SYM_DTYPE_NULL); + ECase(IMAGE_SYM_DTYPE_POINTER); + ECase(IMAGE_SYM_DTYPE_FUNCTION); + ECase(IMAGE_SYM_DTYPE_ARRAY); + } +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolStorageClass &Value) { + ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION); + ECase(IMAGE_SYM_CLASS_NULL); + ECase(IMAGE_SYM_CLASS_AUTOMATIC); + ECase(IMAGE_SYM_CLASS_EXTERNAL); + ECase(IMAGE_SYM_CLASS_STATIC); + ECase(IMAGE_SYM_CLASS_REGISTER); + ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF); + ECase(IMAGE_SYM_CLASS_LABEL); + ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_ARGUMENT); + ECase(IMAGE_SYM_CLASS_STRUCT_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION); + ECase(IMAGE_SYM_CLASS_UNION_TAG); + ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION); + ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC); + ECase(IMAGE_SYM_CLASS_ENUM_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM); + ECase(IMAGE_SYM_CLASS_REGISTER_PARAM); + ECase(IMAGE_SYM_CLASS_BIT_FIELD); + ECase(IMAGE_SYM_CLASS_BLOCK); + ECase(IMAGE_SYM_CLASS_FUNCTION); + ECase(IMAGE_SYM_CLASS_END_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_FILE); + ECase(IMAGE_SYM_CLASS_SECTION); + ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL); + ECase(IMAGE_SYM_CLASS_CLR_TOKEN); + } +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::SymbolBaseType &Value) { + ECase(IMAGE_SYM_TYPE_NULL); + ECase(IMAGE_SYM_TYPE_VOID); + ECase(IMAGE_SYM_TYPE_CHAR); + ECase(IMAGE_SYM_TYPE_SHORT); + ECase(IMAGE_SYM_TYPE_INT); + ECase(IMAGE_SYM_TYPE_LONG); + ECase(IMAGE_SYM_TYPE_FLOAT); + ECase(IMAGE_SYM_TYPE_DOUBLE); + ECase(IMAGE_SYM_TYPE_STRUCT); + ECase(IMAGE_SYM_TYPE_UNION); + ECase(IMAGE_SYM_TYPE_ENUM); + ECase(IMAGE_SYM_TYPE_MOE); + ECase(IMAGE_SYM_TYPE_BYTE); + ECase(IMAGE_SYM_TYPE_WORD); + ECase(IMAGE_SYM_TYPE_UINT); + ECase(IMAGE_SYM_TYPE_DWORD); + } +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::MachineTypes &Value) { + ECase(IMAGE_FILE_MACHINE_UNKNOWN); + ECase(IMAGE_FILE_MACHINE_AM33); + ECase(IMAGE_FILE_MACHINE_AMD64); + ECase(IMAGE_FILE_MACHINE_ARM); + ECase(IMAGE_FILE_MACHINE_ARMV7); + ECase(IMAGE_FILE_MACHINE_EBC); + ECase(IMAGE_FILE_MACHINE_I386); + ECase(IMAGE_FILE_MACHINE_IA64); + ECase(IMAGE_FILE_MACHINE_M32R); + ECase(IMAGE_FILE_MACHINE_MIPS16); + ECase(IMAGE_FILE_MACHINE_MIPSFPU); + ECase(IMAGE_FILE_MACHINE_MIPSFPU16); + ECase(IMAGE_FILE_MACHINE_POWERPC); + ECase(IMAGE_FILE_MACHINE_POWERPCFP); + ECase(IMAGE_FILE_MACHINE_R4000); + ECase(IMAGE_FILE_MACHINE_SH3); + ECase(IMAGE_FILE_MACHINE_SH3DSP); + ECase(IMAGE_FILE_MACHINE_SH4); + ECase(IMAGE_FILE_MACHINE_SH5); + ECase(IMAGE_FILE_MACHINE_THUMB); + ECase(IMAGE_FILE_MACHINE_WCEMIPSV2); + } +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value) { + ECase(IMAGE_REL_I386_ABSOLUTE); + ECase(IMAGE_REL_I386_DIR16); + ECase(IMAGE_REL_I386_REL16); + ECase(IMAGE_REL_I386_DIR32); + ECase(IMAGE_REL_I386_DIR32NB); + ECase(IMAGE_REL_I386_SEG12); + ECase(IMAGE_REL_I386_SECTION); + ECase(IMAGE_REL_I386_SECREL); + ECase(IMAGE_REL_I386_TOKEN); + ECase(IMAGE_REL_I386_SECREL7); + ECase(IMAGE_REL_I386_REL32); + ECase(IMAGE_REL_AMD64_ABSOLUTE); + ECase(IMAGE_REL_AMD64_ADDR64); + ECase(IMAGE_REL_AMD64_ADDR32); + ECase(IMAGE_REL_AMD64_ADDR32NB); + ECase(IMAGE_REL_AMD64_REL32); + ECase(IMAGE_REL_AMD64_REL32_1); + ECase(IMAGE_REL_AMD64_REL32_2); + ECase(IMAGE_REL_AMD64_REL32_3); + ECase(IMAGE_REL_AMD64_REL32_4); + ECase(IMAGE_REL_AMD64_REL32_5); + ECase(IMAGE_REL_AMD64_SECTION); + ECase(IMAGE_REL_AMD64_SECREL); + ECase(IMAGE_REL_AMD64_SECREL7); + ECase(IMAGE_REL_AMD64_TOKEN); + ECase(IMAGE_REL_AMD64_SREL32); + ECase(IMAGE_REL_AMD64_PAIR); + ECase(IMAGE_REL_AMD64_SSPAN32); + } +}; + +#undef ECase + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Symbol &S) { + IO.mapRequired("SimpleType", S.SimpleType); + IO.mapOptional("NumberOfAuxSymbols", S.NumberOfAuxSymbols); + IO.mapRequired("Name", S.Name); + IO.mapRequired("StorageClass", S.StorageClass); + IO.mapOptional("AuxillaryData", S.AuxillaryData); // FIXME: typo + IO.mapRequired("ComplexType", S.ComplexType); + IO.mapRequired("Value", S.Value); + IO.mapRequired("SectionNumber", S.SectionNumber); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Header &H) { + IO.mapRequired("Machine", H.Machine); + IO.mapOptional("Characteristics", H.Characteristics); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Relocation &Rel) { + IO.mapRequired("Type", Rel.Type); + IO.mapRequired("VirtualAddress", Rel.VirtualAddress); + IO.mapRequired("SymbolTableIndex", Rel.SymbolTableIndex); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Section &Sec) { + IO.mapOptional("Relocations", Sec.Relocations); + IO.mapRequired("SectionData", Sec.SectionData); + IO.mapRequired("Characteristics", Sec.Characteristics); + IO.mapRequired("Name", Sec.Name); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::Object &Obj) { + IO.mapRequired("sections", Obj.Sections); + IO.mapRequired("header", Obj.HeaderData); + IO.mapRequired("symbols", Obj.Symbols); + } +}; +} // end namespace yaml +} // end namespace llvm + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv); + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + + OwningPtr Buf; + if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) + return 1; + + yaml::Input YIn(Buf->getBuffer()); + COFFYAML::Object Doc; + YIn >> Doc; + if (YIn.error()) { + errs() << "yaml2obj: Failed to parse YAML file!\n"; + return 1; + } + + COFFParser CP(Doc); + if (!CP.parse()) { + errs() << "yaml2obj: Failed to parse YAML file!\n"; + return 1; + } + + if (!layoutCOFF(CP)) { + errs() << "yaml2obj: Failed to layout COFF file!\n"; + return 1; + } + writeCOFF(CP, outs()); +} diff --git a/utils/Makefile b/utils/Makefile index 7a3c17d0325..ecb30bed7c6 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -9,7 +9,7 @@ LEVEL = .. PARALLEL_DIRS := FileCheck FileUpdate TableGen PerfectShuffle \ - count fpcmp llvm-lit not unittest yaml2obj + count fpcmp llvm-lit not unittest EXTRA_DIST := check-each-file codegen-diff countloc.sh \ DSAclean.py DSAextract.py emacs findsym.pl GenLibDeps.pl \ diff --git a/utils/yaml2obj/CMakeLists.txt b/utils/yaml2obj/CMakeLists.txt deleted file mode 100644 index f8b11975246..00000000000 --- a/utils/yaml2obj/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_llvm_utility(yaml2obj - yaml2obj.cpp - ) - -target_link_libraries(yaml2obj LLVMSupport) diff --git a/utils/yaml2obj/Makefile b/utils/yaml2obj/Makefile deleted file mode 100644 index e746d851900..00000000000 --- a/utils/yaml2obj/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -##===- utils/yaml2obj/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -TOOLNAME = yaml2obj -USEDLIBS = LLVMSupport.a - -# This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -# Don't install this utility -NO_INSTALL = 1 - -include $(LEVEL)/Makefile.common diff --git a/utils/yaml2obj/yaml2obj.cpp b/utils/yaml2obj/yaml2obj.cpp deleted file mode 100644 index 191c49fb59c..00000000000 --- a/utils/yaml2obj/yaml2obj.cpp +++ /dev/null @@ -1,707 +0,0 @@ -//===- yaml2obj - Convert YAML to a binary object file --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This program takes a YAML description of an object file and outputs the -// binary equivalent. -// -// This is used for writing tests that require binary files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/COFF.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include - -using namespace llvm; - -static cl::opt - Input(cl::Positional, cl::desc(""), cl::init("-")); - -template -typename llvm::enable_if_c::is_integer, bool>::type -getAs(const llvm::yaml::ScalarNode *SN, T &Result) { - SmallString<4> Storage; - StringRef Value = SN->getValue(Storage); - if (Value.getAsInteger(0, Result)) - return false; - return true; -} - -// Given a container with begin and end with ::value_type of a character type. -// Iterate through pairs of characters in the the set of [a-fA-F0-9] ignoring -// all other characters. -struct hex_pair_iterator { - StringRef::const_iterator Current, End; - typedef SmallVector value_type; - value_type Pair; - bool IsDone; - - hex_pair_iterator(StringRef C) - : Current(C.begin()), End(C.end()), IsDone(false) { - // Initalize Pair. - ++*this; - } - - // End iterator. - hex_pair_iterator() : Current(), End(), IsDone(true) {} - - value_type operator *() const { - return Pair; - } - - hex_pair_iterator operator ++() { - // We're at the end of the input. - if (Current == End) { - IsDone = true; - return *this; - } - Pair = value_type(); - for (; Current != End && Pair.size() != 2; ++Current) { - // Is a valid hex digit. - if ((*Current >= '0' && *Current <= '9') || - (*Current >= 'a' && *Current <= 'f') || - (*Current >= 'A' && *Current <= 'F')) - Pair.push_back(*Current); - } - // Hit the end without getting 2 hex digits. Pair is invalid. - if (Pair.size() != 2) - IsDone = true; - return *this; - } - - bool operator ==(const hex_pair_iterator Other) { - return (IsDone == Other.IsDone) || - (Current == Other.Current && End == Other.End); - } - - bool operator !=(const hex_pair_iterator Other) { - return !(*this == Other); - } -}; - -template -static bool hexStringToByteArray(StringRef Str, ContainerOut &Out) { - for (hex_pair_iterator I(Str), E; I != E; ++I) { - typename hex_pair_iterator::value_type Pair = *I; - typename ContainerOut::value_type Byte; - if (StringRef(Pair.data(), 2).getAsInteger(16, Byte)) - return false; - Out.push_back(Byte); - } - return true; -} - -// The structure of the yaml files is not an exact 1:1 match to COFF. In order -// to use yaml::IO, we use these structures which are closer to the source. -namespace COFFYAML { - struct Relocation { - uint32_t VirtualAddress; - uint32_t SymbolTableIndex; - COFF::RelocationTypeX86 Type; - }; - - struct Section { - COFF::SectionCharacteristics Characteristics; - StringRef SectionData; - std::vector Relocations; - StringRef Name; - }; - - struct Header { - COFF::MachineTypes Machine; - COFF::Characteristics Characteristics; - }; - - struct Symbol { - COFF::SymbolBaseType SimpleType; - uint8_t NumberOfAuxSymbols; - StringRef Name; - COFF::SymbolStorageClass StorageClass; - StringRef AuxillaryData; - COFF::SymbolComplexType ComplexType; - uint32_t Value; - uint16_t SectionNumber; - }; - - struct Object { - Header HeaderData; - std::vector
Sections; - std::vector Symbols; - }; -} - -/// This parses a yaml stream that represents a COFF object file. -/// See docs/yaml2obj for the yaml scheema. -struct COFFParser { - COFFParser(COFFYAML::Object &Obj) : Obj(Obj) { - std::memset(&Header, 0, sizeof(Header)); - // A COFF string table always starts with a 4 byte size field. Offsets into - // it include this size, so allocate it now. - StringTable.append(4, 0); - } - - void parseHeader() { - Header.Machine = Obj.HeaderData.Machine; - Header.Characteristics = Obj.HeaderData.Characteristics; - } - - bool parseSections() { - for (std::vector::iterator i = Obj.Sections.begin(), - e = Obj.Sections.end(); i != e; ++i) { - const COFFYAML::Section &YamlSection = *i; - Section Sec; - std::memset(&Sec.Header, 0, sizeof(Sec.Header)); - - // If the name is less than 8 bytes, store it in place, otherwise - // store it in the string table. - StringRef Name = YamlSection.Name; - std::fill_n(Sec.Header.Name, unsigned(COFF::NameSize), 0); - if (Name.size() <= COFF::NameSize) { - std::copy(Name.begin(), Name.end(), Sec.Header.Name); - } else { - // Add string to the string table and format the index for output. - unsigned Index = getStringIndex(Name); - std::string str = utostr(Index); - if (str.size() > 7) { - errs() << "String table got too large"; - return false; - } - Sec.Header.Name[0] = '/'; - std::copy(str.begin(), str.end(), Sec.Header.Name + 1); - } - - Sec.Header.Characteristics = YamlSection.Characteristics; - - StringRef Data = YamlSection.SectionData; - if (!hexStringToByteArray(Data, Sec.Data)) { - errs() << "SectionData must be a collection of pairs of hex bytes"; - return false; - } - Sections.push_back(Sec); - } - return true; - } - - bool parseSymbols() { - for (std::vector::iterator i = Obj.Symbols.begin(), - e = Obj.Symbols.end(); i != e; ++i) { - COFFYAML::Symbol YamlSymbol = *i; - Symbol Sym; - std::memset(&Sym.Header, 0, sizeof(Sym.Header)); - - // If the name is less than 8 bytes, store it in place, otherwise - // store it in the string table. - StringRef Name = YamlSymbol.Name; - std::fill_n(Sym.Header.Name, unsigned(COFF::NameSize), 0); - if (Name.size() <= COFF::NameSize) { - std::copy(Name.begin(), Name.end(), Sym.Header.Name); - } else { - // Add string to the string table and format the index for output. - unsigned Index = getStringIndex(Name); - *reinterpret_cast( - Sym.Header.Name + 4) = Index; - } - - Sym.Header.Value = YamlSymbol.Value; - Sym.Header.Type |= YamlSymbol.SimpleType; - Sym.Header.Type |= YamlSymbol.ComplexType << COFF::SCT_COMPLEX_TYPE_SHIFT; - Sym.Header.StorageClass = YamlSymbol.StorageClass; - Sym.Header.SectionNumber = YamlSymbol.SectionNumber; - - StringRef Data = YamlSymbol.AuxillaryData; - if (!hexStringToByteArray(Data, Sym.AuxSymbols)) { - errs() << "AuxillaryData must be a collection of pairs of hex bytes"; - return false; - } - Symbols.push_back(Sym); - } - return true; - } - - bool parse() { - parseHeader(); - if (!parseSections()) - return false; - if (!parseSymbols()) - return false; - return true; - } - - unsigned getStringIndex(StringRef Str) { - StringMap::iterator i = StringTableMap.find(Str); - if (i == StringTableMap.end()) { - unsigned Index = StringTable.size(); - StringTable.append(Str.begin(), Str.end()); - StringTable.push_back(0); - StringTableMap[Str] = Index; - return Index; - } - return i->second; - } - - COFFYAML::Object &Obj; - COFF::header Header; - - struct Section { - COFF::section Header; - std::vector Data; - std::vector Relocations; - }; - - struct Symbol { - COFF::symbol Header; - std::vector AuxSymbols; - }; - - std::vector
Sections; - std::vector Symbols; - StringMap StringTableMap; - std::string StringTable; -}; - -// Take a CP and assign addresses and sizes to everything. Returns false if the -// layout is not valid to do. -static bool layoutCOFF(COFFParser &CP) { - uint32_t SectionTableStart = 0; - uint32_t SectionTableSize = 0; - - // The section table starts immediately after the header, including the - // optional header. - SectionTableStart = sizeof(COFF::header) + CP.Header.SizeOfOptionalHeader; - SectionTableSize = sizeof(COFF::section) * CP.Sections.size(); - - uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize; - - // Assign each section data address consecutively. - for (std::vector::iterator i = CP.Sections.begin(), - e = CP.Sections.end(); - i != e; ++i) { - if (!i->Data.empty()) { - i->Header.SizeOfRawData = i->Data.size(); - i->Header.PointerToRawData = CurrentSectionDataOffset; - CurrentSectionDataOffset += i->Header.SizeOfRawData; - // TODO: Handle alignment. - } else { - i->Header.SizeOfRawData = 0; - i->Header.PointerToRawData = 0; - } - } - - uint32_t SymbolTableStart = CurrentSectionDataOffset; - - // Calculate number of symbols. - uint32_t NumberOfSymbols = 0; - for (std::vector::iterator i = CP.Symbols.begin(), - e = CP.Symbols.end(); - i != e; ++i) { - if (i->AuxSymbols.size() % COFF::SymbolSize != 0) { - errs() << "AuxillaryData size not a multiple of symbol size!\n"; - return false; - } - i->Header.NumberOfAuxSymbols = i->AuxSymbols.size() / COFF::SymbolSize; - NumberOfSymbols += 1 + i->Header.NumberOfAuxSymbols; - } - - // Store all the allocated start addresses in the header. - CP.Header.NumberOfSections = CP.Sections.size(); - CP.Header.NumberOfSymbols = NumberOfSymbols; - CP.Header.PointerToSymbolTable = SymbolTableStart; - - *reinterpret_cast(&CP.StringTable[0]) - = CP.StringTable.size(); - - return true; -} - -template -struct binary_le_impl { - value_type Value; - binary_le_impl(value_type V) : Value(V) {} -}; - -template -raw_ostream &operator <<( raw_ostream &OS - , const binary_le_impl &BLE) { - char Buffer[sizeof(BLE.Value)]; - support::endian::write( - Buffer, BLE.Value); - OS.write(Buffer, sizeof(BLE.Value)); - return OS; -} - -template -binary_le_impl binary_le(value_type V) { - return binary_le_impl(V); -} - -void writeCOFF(COFFParser &CP, raw_ostream &OS) { - OS << binary_le(CP.Header.Machine) - << binary_le(CP.Header.NumberOfSections) - << binary_le(CP.Header.TimeDateStamp) - << binary_le(CP.Header.PointerToSymbolTable) - << binary_le(CP.Header.NumberOfSymbols) - << binary_le(CP.Header.SizeOfOptionalHeader) - << binary_le(CP.Header.Characteristics); - - // Output section table. - for (std::vector::const_iterator i = CP.Sections.begin(), - e = CP.Sections.end(); - i != e; ++i) { - OS.write(i->Header.Name, COFF::NameSize); - OS << binary_le(i->Header.VirtualSize) - << binary_le(i->Header.VirtualAddress) - << binary_le(i->Header.SizeOfRawData) - << binary_le(i->Header.PointerToRawData) - << binary_le(i->Header.PointerToRelocations) - << binary_le(i->Header.PointerToLineNumbers) - << binary_le(i->Header.NumberOfRelocations) - << binary_le(i->Header.NumberOfLineNumbers) - << binary_le(i->Header.Characteristics); - } - - // Output section data. - for (std::vector::const_iterator i = CP.Sections.begin(), - e = CP.Sections.end(); - i != e; ++i) { - if (!i->Data.empty()) - OS.write(reinterpret_cast(&i->Data[0]), i->Data.size()); - } - - // Output symbol table. - - for (std::vector::const_iterator i = CP.Symbols.begin(), - e = CP.Symbols.end(); - i != e; ++i) { - OS.write(i->Header.Name, COFF::NameSize); - OS << binary_le(i->Header.Value) - << binary_le(i->Header.SectionNumber) - << binary_le(i->Header.Type) - << binary_le(i->Header.StorageClass) - << binary_le(i->Header.NumberOfAuxSymbols); - if (!i->AuxSymbols.empty()) - OS.write( reinterpret_cast(&i->AuxSymbols[0]) - , i->AuxSymbols.size()); - } - - // Output string table. - OS.write(&CP.StringTable[0], CP.StringTable.size()); -} - -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) -LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) - -namespace llvm { - -namespace COFF { - Characteristics operator|(Characteristics a, Characteristics b) { - uint32_t Ret = static_cast(a) | static_cast(b); - return static_cast(Ret); - } - - SectionCharacteristics - operator|(SectionCharacteristics a, SectionCharacteristics b) { - uint32_t Ret = static_cast(a) | static_cast(b); - return static_cast(Ret); - } -} - -namespace yaml { - -#define BCase(X) IO.bitSetCase(Value, #X, COFF::X); - -template <> -struct ScalarBitSetTraits { - static void bitset(IO &IO, COFF::SectionCharacteristics &Value) { - BCase(IMAGE_SCN_TYPE_NO_PAD); - BCase(IMAGE_SCN_CNT_CODE); - BCase(IMAGE_SCN_CNT_INITIALIZED_DATA); - BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA); - BCase(IMAGE_SCN_LNK_OTHER); - BCase(IMAGE_SCN_LNK_INFO); - BCase(IMAGE_SCN_LNK_REMOVE); - BCase(IMAGE_SCN_LNK_COMDAT); - BCase(IMAGE_SCN_GPREL); - BCase(IMAGE_SCN_MEM_PURGEABLE); - BCase(IMAGE_SCN_MEM_16BIT); - BCase(IMAGE_SCN_MEM_LOCKED); - BCase(IMAGE_SCN_MEM_PRELOAD); - BCase(IMAGE_SCN_ALIGN_1BYTES); - BCase(IMAGE_SCN_ALIGN_2BYTES); - BCase(IMAGE_SCN_ALIGN_4BYTES); - BCase(IMAGE_SCN_ALIGN_8BYTES); - BCase(IMAGE_SCN_ALIGN_16BYTES); - BCase(IMAGE_SCN_ALIGN_32BYTES); - BCase(IMAGE_SCN_ALIGN_64BYTES); - BCase(IMAGE_SCN_ALIGN_128BYTES); - BCase(IMAGE_SCN_ALIGN_256BYTES); - BCase(IMAGE_SCN_ALIGN_512BYTES); - BCase(IMAGE_SCN_ALIGN_1024BYTES); - BCase(IMAGE_SCN_ALIGN_2048BYTES); - BCase(IMAGE_SCN_ALIGN_4096BYTES); - BCase(IMAGE_SCN_ALIGN_8192BYTES); - BCase(IMAGE_SCN_LNK_NRELOC_OVFL); - BCase(IMAGE_SCN_MEM_DISCARDABLE); - BCase(IMAGE_SCN_MEM_NOT_CACHED); - BCase(IMAGE_SCN_MEM_NOT_PAGED); - BCase(IMAGE_SCN_MEM_SHARED); - BCase(IMAGE_SCN_MEM_EXECUTE); - BCase(IMAGE_SCN_MEM_READ); - BCase(IMAGE_SCN_MEM_WRITE); - } -}; - -template <> -struct ScalarBitSetTraits { - static void bitset(IO &IO, COFF::Characteristics &Value) { - BCase(IMAGE_FILE_RELOCS_STRIPPED); - BCase(IMAGE_FILE_EXECUTABLE_IMAGE); - BCase(IMAGE_FILE_LINE_NUMS_STRIPPED); - BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED); - BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM); - BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE); - BCase(IMAGE_FILE_BYTES_REVERSED_LO); - BCase(IMAGE_FILE_32BIT_MACHINE); - BCase(IMAGE_FILE_DEBUG_STRIPPED); - BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP); - BCase(IMAGE_FILE_NET_RUN_FROM_SWAP); - BCase(IMAGE_FILE_SYSTEM); - BCase(IMAGE_FILE_DLL); - BCase(IMAGE_FILE_UP_SYSTEM_ONLY); - BCase(IMAGE_FILE_BYTES_REVERSED_HI); - } -}; -#undef BCase - -#define ECase(X) IO.enumCase(Value, #X, COFF::X); - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, COFF::SymbolComplexType &Value) { - ECase(IMAGE_SYM_DTYPE_NULL); - ECase(IMAGE_SYM_DTYPE_POINTER); - ECase(IMAGE_SYM_DTYPE_FUNCTION); - ECase(IMAGE_SYM_DTYPE_ARRAY); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, COFF::SymbolStorageClass &Value) { - ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION); - ECase(IMAGE_SYM_CLASS_NULL); - ECase(IMAGE_SYM_CLASS_AUTOMATIC); - ECase(IMAGE_SYM_CLASS_EXTERNAL); - ECase(IMAGE_SYM_CLASS_STATIC); - ECase(IMAGE_SYM_CLASS_REGISTER); - ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF); - ECase(IMAGE_SYM_CLASS_LABEL); - ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT); - ECase(IMAGE_SYM_CLASS_ARGUMENT); - ECase(IMAGE_SYM_CLASS_STRUCT_TAG); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION); - ECase(IMAGE_SYM_CLASS_UNION_TAG); - ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION); - ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC); - ECase(IMAGE_SYM_CLASS_ENUM_TAG); - ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM); - ECase(IMAGE_SYM_CLASS_REGISTER_PARAM); - ECase(IMAGE_SYM_CLASS_BIT_FIELD); - ECase(IMAGE_SYM_CLASS_BLOCK); - ECase(IMAGE_SYM_CLASS_FUNCTION); - ECase(IMAGE_SYM_CLASS_END_OF_STRUCT); - ECase(IMAGE_SYM_CLASS_FILE); - ECase(IMAGE_SYM_CLASS_SECTION); - ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL); - ECase(IMAGE_SYM_CLASS_CLR_TOKEN); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, COFF::SymbolBaseType &Value) { - ECase(IMAGE_SYM_TYPE_NULL); - ECase(IMAGE_SYM_TYPE_VOID); - ECase(IMAGE_SYM_TYPE_CHAR); - ECase(IMAGE_SYM_TYPE_SHORT); - ECase(IMAGE_SYM_TYPE_INT); - ECase(IMAGE_SYM_TYPE_LONG); - ECase(IMAGE_SYM_TYPE_FLOAT); - ECase(IMAGE_SYM_TYPE_DOUBLE); - ECase(IMAGE_SYM_TYPE_STRUCT); - ECase(IMAGE_SYM_TYPE_UNION); - ECase(IMAGE_SYM_TYPE_ENUM); - ECase(IMAGE_SYM_TYPE_MOE); - ECase(IMAGE_SYM_TYPE_BYTE); - ECase(IMAGE_SYM_TYPE_WORD); - ECase(IMAGE_SYM_TYPE_UINT); - ECase(IMAGE_SYM_TYPE_DWORD); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, COFF::MachineTypes &Value) { - ECase(IMAGE_FILE_MACHINE_UNKNOWN); - ECase(IMAGE_FILE_MACHINE_AM33); - ECase(IMAGE_FILE_MACHINE_AMD64); - ECase(IMAGE_FILE_MACHINE_ARM); - ECase(IMAGE_FILE_MACHINE_ARMV7); - ECase(IMAGE_FILE_MACHINE_EBC); - ECase(IMAGE_FILE_MACHINE_I386); - ECase(IMAGE_FILE_MACHINE_IA64); - ECase(IMAGE_FILE_MACHINE_M32R); - ECase(IMAGE_FILE_MACHINE_MIPS16); - ECase(IMAGE_FILE_MACHINE_MIPSFPU); - ECase(IMAGE_FILE_MACHINE_MIPSFPU16); - ECase(IMAGE_FILE_MACHINE_POWERPC); - ECase(IMAGE_FILE_MACHINE_POWERPCFP); - ECase(IMAGE_FILE_MACHINE_R4000); - ECase(IMAGE_FILE_MACHINE_SH3); - ECase(IMAGE_FILE_MACHINE_SH3DSP); - ECase(IMAGE_FILE_MACHINE_SH4); - ECase(IMAGE_FILE_MACHINE_SH5); - ECase(IMAGE_FILE_MACHINE_THUMB); - ECase(IMAGE_FILE_MACHINE_WCEMIPSV2); - } -}; - -template <> -struct ScalarEnumerationTraits { - static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value) { - ECase(IMAGE_REL_I386_ABSOLUTE); - ECase(IMAGE_REL_I386_DIR16); - ECase(IMAGE_REL_I386_REL16); - ECase(IMAGE_REL_I386_DIR32); - ECase(IMAGE_REL_I386_DIR32NB); - ECase(IMAGE_REL_I386_SEG12); - ECase(IMAGE_REL_I386_SECTION); - ECase(IMAGE_REL_I386_SECREL); - ECase(IMAGE_REL_I386_TOKEN); - ECase(IMAGE_REL_I386_SECREL7); - ECase(IMAGE_REL_I386_REL32); - ECase(IMAGE_REL_AMD64_ABSOLUTE); - ECase(IMAGE_REL_AMD64_ADDR64); - ECase(IMAGE_REL_AMD64_ADDR32); - ECase(IMAGE_REL_AMD64_ADDR32NB); - ECase(IMAGE_REL_AMD64_REL32); - ECase(IMAGE_REL_AMD64_REL32_1); - ECase(IMAGE_REL_AMD64_REL32_2); - ECase(IMAGE_REL_AMD64_REL32_3); - ECase(IMAGE_REL_AMD64_REL32_4); - ECase(IMAGE_REL_AMD64_REL32_5); - ECase(IMAGE_REL_AMD64_SECTION); - ECase(IMAGE_REL_AMD64_SECREL); - ECase(IMAGE_REL_AMD64_SECREL7); - ECase(IMAGE_REL_AMD64_TOKEN); - ECase(IMAGE_REL_AMD64_SREL32); - ECase(IMAGE_REL_AMD64_PAIR); - ECase(IMAGE_REL_AMD64_SSPAN32); - } -}; - -#undef ECase - -template <> -struct MappingTraits { - static void mapping(IO &IO, COFFYAML::Symbol &S) { - IO.mapRequired("SimpleType", S.SimpleType); - IO.mapOptional("NumberOfAuxSymbols", S.NumberOfAuxSymbols); - IO.mapRequired("Name", S.Name); - IO.mapRequired("StorageClass", S.StorageClass); - IO.mapOptional("AuxillaryData", S.AuxillaryData); // FIXME: typo - IO.mapRequired("ComplexType", S.ComplexType); - IO.mapRequired("Value", S.Value); - IO.mapRequired("SectionNumber", S.SectionNumber); - } -}; - -template <> -struct MappingTraits { - static void mapping(IO &IO, COFFYAML::Header &H) { - IO.mapRequired("Machine", H.Machine); - IO.mapOptional("Characteristics", H.Characteristics); - } -}; - -template <> -struct MappingTraits { - static void mapping(IO &IO, COFFYAML::Relocation &Rel) { - IO.mapRequired("Type", Rel.Type); - IO.mapRequired("VirtualAddress", Rel.VirtualAddress); - IO.mapRequired("SymbolTableIndex", Rel.SymbolTableIndex); - } -}; - -template <> -struct MappingTraits { - static void mapping(IO &IO, COFFYAML::Section &Sec) { - IO.mapOptional("Relocations", Sec.Relocations); - IO.mapRequired("SectionData", Sec.SectionData); - IO.mapRequired("Characteristics", Sec.Characteristics); - IO.mapRequired("Name", Sec.Name); - } -}; - -template <> -struct MappingTraits { - static void mapping(IO &IO, COFFYAML::Object &Obj) { - IO.mapRequired("sections", Obj.Sections); - IO.mapRequired("header", Obj.HeaderData); - IO.mapRequired("symbols", Obj.Symbols); - } -}; -} // end namespace yaml -} // end namespace llvm - -int main(int argc, char **argv) { - cl::ParseCommandLineOptions(argc, argv); - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - OwningPtr Buf; - if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) - return 1; - - yaml::Input YIn(Buf->getBuffer()); - COFFYAML::Object Doc; - YIn >> Doc; - if (YIn.error()) { - errs() << "yaml2obj: Failed to parse YAML file!\n"; - return 1; - } - - COFFParser CP(Doc); - if (!CP.parse()) { - errs() << "yaml2obj: Failed to parse YAML file!\n"; - return 1; - } - - if (!layoutCOFF(CP)) { - errs() << "yaml2obj: Failed to layout COFF file!\n"; - return 1; - } - writeCOFF(CP, outs()); -}