forked from OSchip/llvm-project
[yaml2obj] Move core yaml2obj code into lib and include for use in unit tests
Reviewers: jhenderson, rupprecht, MaskRay, grimar, labath Reviewed By: rupprecht Subscribers: gribozavr, mgrang, seiya, mgorny, sbc100, hiraditya, aheejin, jakehehrlich, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65255 llvm-svn: 368119
This commit is contained in:
parent
6cebeafac3
commit
c22d9666fc
|
@ -11,8 +11,18 @@
|
||||||
#ifndef LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H
|
#ifndef LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H
|
||||||
#define LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H
|
#define LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class raw_ostream;
|
class raw_ostream;
|
||||||
|
template <typename T> class SmallVectorImpl;
|
||||||
|
template <typename T> class Expected;
|
||||||
|
|
||||||
|
namespace object {
|
||||||
|
class ObjectFile;
|
||||||
|
}
|
||||||
|
|
||||||
namespace COFFYAML {
|
namespace COFFYAML {
|
||||||
struct Object;
|
struct Object;
|
||||||
|
@ -33,13 +43,20 @@ struct Object;
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
class Input;
|
class Input;
|
||||||
struct YamlObjectFile;
|
struct YamlObjectFile;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out);
|
int yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out);
|
||||||
int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out);
|
int yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out);
|
||||||
int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out);
|
int yaml2macho(YamlObjectFile &Doc, raw_ostream &Out);
|
||||||
int yaml2minidump(llvm::MinidumpYAML::Object &Doc, llvm::raw_ostream &Out);
|
int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out);
|
||||||
int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out);
|
int yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out);
|
||||||
|
|
||||||
|
Error convertYAML(Input &YIn, raw_ostream &Out, unsigned DocNum = 1);
|
||||||
|
|
||||||
|
/// Convenience function for tests.
|
||||||
|
Expected<std::unique_ptr<object::ObjectFile>>
|
||||||
|
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml);
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -3,15 +3,24 @@ add_llvm_library(LLVMObjectYAML
|
||||||
CodeViewYAMLSymbols.cpp
|
CodeViewYAMLSymbols.cpp
|
||||||
CodeViewYAMLTypeHashing.cpp
|
CodeViewYAMLTypeHashing.cpp
|
||||||
CodeViewYAMLTypes.cpp
|
CodeViewYAMLTypes.cpp
|
||||||
|
COFFEmitter.cpp
|
||||||
COFFYAML.cpp
|
COFFYAML.cpp
|
||||||
DWARFEmitter.cpp
|
DWARFEmitter.cpp
|
||||||
DWARFVisitor.cpp
|
DWARFVisitor.cpp
|
||||||
DWARFYAML.cpp
|
DWARFYAML.cpp
|
||||||
|
ELFEmitter.cpp
|
||||||
ELFYAML.cpp
|
ELFYAML.cpp
|
||||||
|
MachOEmitter.cpp
|
||||||
MachOYAML.cpp
|
MachOYAML.cpp
|
||||||
ObjectYAML.cpp
|
ObjectYAML.cpp
|
||||||
|
MinidumpEmitter.cpp
|
||||||
MinidumpYAML.cpp
|
MinidumpYAML.cpp
|
||||||
|
WasmEmitter.cpp
|
||||||
WasmYAML.cpp
|
WasmYAML.cpp
|
||||||
XCOFFYAML.cpp
|
XCOFFYAML.cpp
|
||||||
YAML.cpp
|
YAML.cpp
|
||||||
|
yaml2obj.cpp
|
||||||
|
|
||||||
|
ADDITIONAL_HEADER_DIRS
|
||||||
|
${LLVM_MAIN_INCLUDE_DIR}/llvm/ObjectYAML
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
///
|
///
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "yaml2obj.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringMap.h"
|
#include "llvm/ADT/StringMap.h"
|
||||||
|
@ -20,6 +19,7 @@
|
||||||
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
|
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
|
||||||
#include "llvm/Object/COFF.h"
|
#include "llvm/Object/COFF.h"
|
||||||
#include "llvm/ObjectYAML/ObjectYAML.h"
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
/// This parses a yaml stream that represents a COFF object file.
|
/// This parses a yaml stream that represents a COFF object file.
|
||||||
/// See docs/yaml2obj for the yaml scheema.
|
/// See docs/yaml2obj for the yaml scheema.
|
||||||
struct COFFParser {
|
struct COFFParser {
|
||||||
|
@ -64,7 +66,8 @@ struct COFFParser {
|
||||||
|
|
||||||
bool parseSections() {
|
bool parseSections() {
|
||||||
for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
|
for (std::vector<COFFYAML::Section>::iterator i = Obj.Sections.begin(),
|
||||||
e = Obj.Sections.end(); i != e; ++i) {
|
e = Obj.Sections.end();
|
||||||
|
i != e; ++i) {
|
||||||
COFFYAML::Section &Sec = *i;
|
COFFYAML::Section &Sec = *i;
|
||||||
|
|
||||||
// If the name is less than 8 bytes, store it in place, otherwise
|
// If the name is less than 8 bytes, store it in place, otherwise
|
||||||
|
@ -102,7 +105,8 @@ struct COFFParser {
|
||||||
|
|
||||||
bool parseSymbols() {
|
bool parseSymbols() {
|
||||||
for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
|
for (std::vector<COFFYAML::Symbol>::iterator i = Obj.Symbols.begin(),
|
||||||
e = Obj.Symbols.end(); i != e; ++i) {
|
e = Obj.Symbols.end();
|
||||||
|
i != e; ++i) {
|
||||||
COFFYAML::Symbol &Sym = *i;
|
COFFYAML::Symbol &Sym = *i;
|
||||||
|
|
||||||
// If the name is less than 8 bytes, store it in place, otherwise
|
// If the name is less than 8 bytes, store it in place, otherwise
|
||||||
|
@ -113,8 +117,8 @@ struct COFFParser {
|
||||||
} else {
|
} else {
|
||||||
// Add string to the string table and format the index for output.
|
// Add string to the string table and format the index for output.
|
||||||
unsigned Index = getStringIndex(Name);
|
unsigned Index = getStringIndex(Name);
|
||||||
*reinterpret_cast<support::aligned_ulittle32_t*>(
|
*reinterpret_cast<support::aligned_ulittle32_t *>(Sym.Header.Name + 4) =
|
||||||
Sym.Header.Name + 4) = Index;
|
Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sym.Header.Type = Sym.SimpleType;
|
Sym.Header.Type = Sym.SimpleType;
|
||||||
|
@ -153,6 +157,10 @@ struct COFFParser {
|
||||||
uint32_t SectionTableSize;
|
uint32_t SectionTableSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { DOSStubSize = 128 };
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
// Take a CP and assign addresses and sizes to everything. Returns false if the
|
// Take a CP and assign addresses and sizes to everything. Returns false if the
|
||||||
// layout is not valid to do.
|
// layout is not valid to do.
|
||||||
static bool layoutOptionalHeader(COFFParser &CP) {
|
static bool layoutOptionalHeader(COFFParser &CP) {
|
||||||
|
@ -166,10 +174,6 @@ static bool layoutOptionalHeader(COFFParser &CP) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
enum { DOSStubSize = 128 };
|
|
||||||
}
|
|
||||||
|
|
||||||
static yaml::BinaryRef
|
static yaml::BinaryRef
|
||||||
toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections,
|
toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections,
|
||||||
const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) {
|
const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) {
|
||||||
|
@ -271,7 +275,7 @@ static bool layoutCOFF(COFFParser &CP) {
|
||||||
uint32_t NumberOfSymbols = 0;
|
uint32_t NumberOfSymbols = 0;
|
||||||
for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
|
for (std::vector<COFFYAML::Symbol>::iterator i = CP.Obj.Symbols.begin(),
|
||||||
e = CP.Obj.Symbols.end();
|
e = CP.Obj.Symbols.end();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
uint32_t NumberOfAuxSymbols = 0;
|
uint32_t NumberOfAuxSymbols = 0;
|
||||||
if (i->FunctionDefinition)
|
if (i->FunctionDefinition)
|
||||||
NumberOfAuxSymbols += 1;
|
NumberOfAuxSymbols += 1;
|
||||||
|
@ -298,24 +302,23 @@ static bool layoutCOFF(COFFParser &CP) {
|
||||||
else
|
else
|
||||||
CP.Obj.Header.PointerToSymbolTable = 0;
|
CP.Obj.Header.PointerToSymbolTable = 0;
|
||||||
|
|
||||||
*reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0])
|
*reinterpret_cast<support::ulittle32_t *>(&CP.StringTable[0]) =
|
||||||
= CP.StringTable.size();
|
CP.StringTable.size();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename value_type>
|
template <typename value_type> struct binary_le_impl {
|
||||||
struct binary_le_impl {
|
|
||||||
value_type Value;
|
value_type Value;
|
||||||
binary_le_impl(value_type V) : Value(V) {}
|
binary_le_impl(value_type V) : Value(V) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename value_type>
|
template <typename value_type>
|
||||||
raw_ostream &operator <<( raw_ostream &OS
|
raw_ostream &operator<<(raw_ostream &OS,
|
||||||
, const binary_le_impl<value_type> &BLE) {
|
const binary_le_impl<value_type> &BLE) {
|
||||||
char Buffer[sizeof(BLE.Value)];
|
char Buffer[sizeof(BLE.Value)];
|
||||||
support::endian::write<value_type, support::little, support::unaligned>(
|
support::endian::write<value_type, support::little, support::unaligned>(
|
||||||
Buffer, BLE.Value);
|
Buffer, BLE.Value);
|
||||||
OS.write(Buffer, sizeof(BLE.Value));
|
OS.write(Buffer, sizeof(BLE.Value));
|
||||||
return OS;
|
return OS;
|
||||||
}
|
}
|
||||||
|
@ -335,13 +338,13 @@ raw_ostream &operator<<(raw_ostream &OS, const zeros_impl<NumBytes> &) {
|
||||||
return OS;
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> zeros_impl<sizeof(T)> zeros(const T &) {
|
||||||
zeros_impl<sizeof(T)> zeros(const T &) {
|
|
||||||
return zeros_impl<sizeof(T)>();
|
return zeros_impl<sizeof(T)>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Header) {
|
static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic,
|
||||||
|
T Header) {
|
||||||
memset(Header, 0, sizeof(*Header));
|
memset(Header, 0, sizeof(*Header));
|
||||||
Header->Magic = Magic;
|
Header->Magic = Magic;
|
||||||
Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment;
|
Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment;
|
||||||
|
@ -376,10 +379,8 @@ static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Heade
|
||||||
CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
|
CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion;
|
||||||
Header->MinorOperatingSystemVersion =
|
Header->MinorOperatingSystemVersion =
|
||||||
CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
|
CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion;
|
||||||
Header->MajorImageVersion =
|
Header->MajorImageVersion = CP.Obj.OptionalHeader->Header.MajorImageVersion;
|
||||||
CP.Obj.OptionalHeader->Header.MajorImageVersion;
|
Header->MinorImageVersion = CP.Obj.OptionalHeader->Header.MinorImageVersion;
|
||||||
Header->MinorImageVersion =
|
|
||||||
CP.Obj.OptionalHeader->Header.MinorImageVersion;
|
|
||||||
Header->MajorSubsystemVersion =
|
Header->MajorSubsystemVersion =
|
||||||
CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
|
CP.Obj.OptionalHeader->Header.MajorSubsystemVersion;
|
||||||
Header->MinorSubsystemVersion =
|
Header->MinorSubsystemVersion =
|
||||||
|
@ -423,15 +424,13 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
if (CP.useBigObj()) {
|
if (CP.useBigObj()) {
|
||||||
OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
|
OS << binary_le(static_cast<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN))
|
||||||
<< binary_le(static_cast<uint16_t>(0xffff))
|
<< binary_le(static_cast<uint16_t>(0xffff))
|
||||||
<< binary_le(static_cast<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion))
|
<< binary_le(
|
||||||
|
static_cast<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion))
|
||||||
<< binary_le(CP.Obj.Header.Machine)
|
<< binary_le(CP.Obj.Header.Machine)
|
||||||
<< binary_le(CP.Obj.Header.TimeDateStamp);
|
<< binary_le(CP.Obj.Header.TimeDateStamp);
|
||||||
OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
|
OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
|
||||||
OS << zeros(uint32_t(0))
|
OS << zeros(uint32_t(0)) << zeros(uint32_t(0)) << zeros(uint32_t(0))
|
||||||
<< zeros(uint32_t(0))
|
<< zeros(uint32_t(0)) << binary_le(CP.Obj.Header.NumberOfSections)
|
||||||
<< zeros(uint32_t(0))
|
|
||||||
<< zeros(uint32_t(0))
|
|
||||||
<< binary_le(CP.Obj.Header.NumberOfSections)
|
|
||||||
<< binary_le(CP.Obj.Header.PointerToSymbolTable)
|
<< binary_le(CP.Obj.Header.PointerToSymbolTable)
|
||||||
<< binary_le(CP.Obj.Header.NumberOfSymbols);
|
<< binary_le(CP.Obj.Header.NumberOfSymbols);
|
||||||
} else {
|
} else {
|
||||||
|
@ -450,7 +449,8 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
|
OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
|
||||||
} else {
|
} else {
|
||||||
object::pe32_header PEH;
|
object::pe32_header PEH;
|
||||||
uint32_t BaseOfData = initializeOptionalHeader(CP, COFF::PE32Header::PE32, &PEH);
|
uint32_t BaseOfData =
|
||||||
|
initializeOptionalHeader(CP, COFF::PE32Header::PE32, &PEH);
|
||||||
PEH.BaseOfData = BaseOfData;
|
PEH.BaseOfData = BaseOfData;
|
||||||
OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
|
OS.write(reinterpret_cast<char *>(&PEH), sizeof(PEH));
|
||||||
}
|
}
|
||||||
|
@ -472,7 +472,7 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
// Output section table.
|
// Output section table.
|
||||||
for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
|
for (std::vector<COFFYAML::Section>::iterator i = CP.Obj.Sections.begin(),
|
||||||
e = CP.Obj.Sections.end();
|
e = CP.Obj.Sections.end();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
OS.write(i->Header.Name, COFF::NameSize);
|
OS.write(i->Header.Name, COFF::NameSize);
|
||||||
OS << binary_le(i->Header.VirtualSize)
|
OS << binary_le(i->Header.VirtualSize)
|
||||||
<< binary_le(i->Header.VirtualAddress)
|
<< binary_le(i->Header.VirtualAddress)
|
||||||
|
@ -514,8 +514,7 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
} else {
|
} else {
|
||||||
SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
|
SymbolTableIndex = SymbolTableIndexMap[R.SymbolName];
|
||||||
}
|
}
|
||||||
OS << binary_le(R.VirtualAddress)
|
OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex)
|
||||||
<< binary_le(SymbolTableIndex)
|
|
||||||
<< binary_le(R.Type);
|
<< binary_le(R.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,15 +523,14 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
|
|
||||||
for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
|
for (std::vector<COFFYAML::Symbol>::const_iterator i = CP.Obj.Symbols.begin(),
|
||||||
e = CP.Obj.Symbols.end();
|
e = CP.Obj.Symbols.end();
|
||||||
i != e; ++i) {
|
i != e; ++i) {
|
||||||
OS.write(i->Header.Name, COFF::NameSize);
|
OS.write(i->Header.Name, COFF::NameSize);
|
||||||
OS << binary_le(i->Header.Value);
|
OS << binary_le(i->Header.Value);
|
||||||
if (CP.useBigObj())
|
if (CP.useBigObj())
|
||||||
OS << binary_le(i->Header.SectionNumber);
|
OS << binary_le(i->Header.SectionNumber);
|
||||||
else
|
else
|
||||||
OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
|
OS << binary_le(static_cast<int16_t>(i->Header.SectionNumber));
|
||||||
OS << binary_le(i->Header.Type)
|
OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass)
|
||||||
<< binary_le(i->Header.StorageClass)
|
|
||||||
<< binary_le(i->Header.NumberOfAuxSymbols);
|
<< binary_le(i->Header.NumberOfAuxSymbols);
|
||||||
|
|
||||||
if (i->FunctionDefinition) {
|
if (i->FunctionDefinition) {
|
||||||
|
@ -578,8 +576,7 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
}
|
}
|
||||||
if (i->CLRToken) {
|
if (i->CLRToken) {
|
||||||
OS << binary_le(i->CLRToken->AuxType)
|
OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1)
|
||||||
<< zeros(i->CLRToken->unused1)
|
|
||||||
<< binary_le(i->CLRToken->SymbolTableIndex)
|
<< binary_le(i->CLRToken->SymbolTableIndex)
|
||||||
<< zeros(i->CLRToken->unused2);
|
<< zeros(i->CLRToken->unused2);
|
||||||
OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
OS.write_zeros(CP.getSymbolSize() - COFF::Symbol16Size);
|
||||||
|
@ -592,6 +589,9 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
|
int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
|
||||||
COFFParser CP(Doc);
|
COFFParser CP(Doc);
|
||||||
if (!CP.parse()) {
|
if (!CP.parse()) {
|
||||||
|
@ -614,3 +614,6 @@ int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -11,13 +11,13 @@
|
||||||
///
|
///
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "yaml2obj.h"
|
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/StringSet.h"
|
||||||
#include "llvm/BinaryFormat/ELF.h"
|
#include "llvm/BinaryFormat/ELF.h"
|
||||||
#include "llvm/MC/StringTableBuilder.h"
|
#include "llvm/MC/StringTableBuilder.h"
|
||||||
#include "llvm/Object/ELFObjectFile.h"
|
#include "llvm/Object/ELFObjectFile.h"
|
||||||
#include "llvm/ObjectYAML/ELFYAML.h"
|
#include "llvm/ObjectYAML/ELFYAML.h"
|
||||||
#include "llvm/ADT/StringSet.h"
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/Support/EndianStream.h"
|
#include "llvm/Support/EndianStream.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/WithColor.h"
|
#include "llvm/Support/WithColor.h"
|
||||||
|
@ -55,11 +55,9 @@ public:
|
||||||
}
|
}
|
||||||
void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
|
void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
// Used to keep track of section and symbol names, so that in the YAML file
|
// Used to keep track of section and symbol names, so that in the YAML file
|
||||||
// sections and symbols can be referenced by name instead of by index.
|
// sections and symbols can be referenced by name instead of by index.
|
||||||
namespace {
|
|
||||||
class NameToIdxMap {
|
class NameToIdxMap {
|
||||||
StringMap<unsigned> Map;
|
StringMap<unsigned> Map;
|
||||||
|
|
||||||
|
@ -86,29 +84,11 @@ public:
|
||||||
}
|
}
|
||||||
unsigned size() const { return Map.size(); }
|
unsigned size() const { return Map.size(); }
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
static size_t arrayDataSize(ArrayRef<T> A) {
|
|
||||||
return A.size() * sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
|
|
||||||
OS.write((const char *)A.data(), arrayDataSize(A));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
static void zero(T &Obj) {
|
|
||||||
memset(&Obj, 0, sizeof(Obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
/// "Single point of truth" for the ELF file construction.
|
/// "Single point of truth" for the ELF file construction.
|
||||||
/// TODO: This class still has a ways to go before it is truly a "single
|
/// TODO: This class still has a ways to go before it is truly a "single
|
||||||
/// point of truth".
|
/// point of truth".
|
||||||
template <class ELFT>
|
template <class ELFT> class ELFState {
|
||||||
class ELFState {
|
|
||||||
typedef typename ELFT::Ehdr Elf_Ehdr;
|
typedef typename ELFT::Ehdr Elf_Ehdr;
|
||||||
typedef typename ELFT::Phdr Elf_Phdr;
|
typedef typename ELFT::Phdr Elf_Phdr;
|
||||||
typedef typename ELFT::Shdr Elf_Shdr;
|
typedef typename ELFT::Shdr Elf_Shdr;
|
||||||
|
@ -185,8 +165,17 @@ private:
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
template <class ELFT>
|
template <class T> static size_t arrayDataSize(ArrayRef<T> A) {
|
||||||
ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
|
return A.size() * sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
|
||||||
|
OS.write((const char *)A.data(), arrayDataSize(A));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
|
||||||
|
|
||||||
|
template <class ELFT> ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
|
||||||
StringSet<> DocSections;
|
StringSet<> DocSections;
|
||||||
for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
|
for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
|
||||||
if (!D->Name.empty())
|
if (!D->Name.empty())
|
||||||
|
@ -197,7 +186,7 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
|
||||||
Doc.Sections.insert(
|
Doc.Sections.insert(
|
||||||
Doc.Sections.begin(),
|
Doc.Sections.begin(),
|
||||||
llvm::make_unique<ELFYAML::Section>(
|
llvm::make_unique<ELFYAML::Section>(
|
||||||
ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true));
|
ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true));
|
||||||
|
|
||||||
std::vector<StringRef> ImplicitSections = {".symtab", ".strtab", ".shstrtab"};
|
std::vector<StringRef> ImplicitSections = {".symtab", ".strtab", ".shstrtab"};
|
||||||
if (!Doc.DynamicSymbols.empty())
|
if (!Doc.DynamicSymbols.empty())
|
||||||
|
@ -216,8 +205,7 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT> void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
|
||||||
void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
|
|
||||||
using namespace llvm::ELF;
|
using namespace llvm::ELF;
|
||||||
zero(Header);
|
zero(Header);
|
||||||
Header.e_ident[EI_MAG0] = 0x7f;
|
Header.e_ident[EI_MAG0] = 0x7f;
|
||||||
|
@ -700,10 +688,9 @@ static bool isMips64EL(const ELFYAML::Object &Doc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
bool
|
bool ELFState<ELFT>::writeSectionContent(
|
||||||
ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section,
|
||||||
const ELFYAML::RelocationSection &Section,
|
ContiguousBlobAccumulator &CBA) {
|
||||||
ContiguousBlobAccumulator &CBA) {
|
|
||||||
assert((Section.Type == llvm::ELF::SHT_REL ||
|
assert((Section.Type == llvm::ELF::SHT_REL ||
|
||||||
Section.Type == llvm::ELF::SHT_RELA) &&
|
Section.Type == llvm::ELF::SHT_RELA) &&
|
||||||
"Section type is not SHT_REL nor SHT_RELA");
|
"Section type is not SHT_REL nor SHT_RELA");
|
||||||
|
@ -949,7 +936,8 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
|
||||||
else
|
else
|
||||||
SHeader.sh_entsize = sizeof(Elf_Dyn);
|
SHeader.sh_entsize = sizeof(Elf_Dyn);
|
||||||
|
|
||||||
raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
raw_ostream &OS =
|
||||||
|
CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
|
||||||
for (const ELFYAML::DynamicEntry &DE : Section.Entries) {
|
for (const ELFYAML::DynamicEntry &DE : Section.Entries) {
|
||||||
support::endian::write<uintX_t>(OS, DE.Tag, ELFT::TargetEndianness);
|
support::endian::write<uintX_t>(OS, DE.Tag, ELFT::TargetEndianness);
|
||||||
support::endian::write<uintX_t>(OS, DE.Val, ELFT::TargetEndianness);
|
support::endian::write<uintX_t>(OS, DE.Val, ELFT::TargetEndianness);
|
||||||
|
@ -1075,6 +1063,9 @@ int ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
|
int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
|
||||||
bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
|
bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
|
||||||
bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
|
bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
|
||||||
|
@ -1087,3 +1078,6 @@ int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
|
||||||
return ELFState<object::ELF32LE>::writeELF(Out, Doc);
|
return ELFState<object::ELF32LE>::writeELF(Out, Doc);
|
||||||
return ELFState<object::ELF32BE>::writeELF(Out, Doc);
|
return ELFState<object::ELF32BE>::writeELF(Out, Doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -10,4 +10,4 @@
|
||||||
type = Library
|
type = Library
|
||||||
name = ObjectYAML
|
name = ObjectYAML
|
||||||
parent = Libraries
|
parent = Libraries
|
||||||
required_libraries = Object Support DebugInfoCodeView
|
required_libraries = Object Support DebugInfoCodeView MC
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
///
|
///
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "yaml2obj.h"
|
|
||||||
#include "llvm/BinaryFormat/MachO.h"
|
#include "llvm/BinaryFormat/MachO.h"
|
||||||
#include "llvm/ObjectYAML/DWARFEmitter.h"
|
#include "llvm/ObjectYAML/DWARFEmitter.h"
|
||||||
#include "llvm/ObjectYAML/ObjectYAML.h"
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/LEB128.h"
|
#include "llvm/Support/LEB128.h"
|
||||||
#include "llvm/Support/YAMLTraits.h"
|
#include "llvm/Support/YAMLTraits.h"
|
||||||
|
@ -263,8 +263,7 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isVirtualSection(uint8_t type) {
|
static bool isVirtualSection(uint8_t type) {
|
||||||
return (type == MachO::S_ZEROFILL ||
|
return (type == MachO::S_ZEROFILL || type == MachO::S_GB_ZEROFILL ||
|
||||||
type == MachO::S_GB_ZEROFILL ||
|
|
||||||
type == MachO::S_THREAD_LOCAL_ZEROFILL);
|
type == MachO::S_THREAD_LOCAL_ZEROFILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +275,8 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
||||||
case MachO::LC_SEGMENT_64:
|
case MachO::LC_SEGMENT_64:
|
||||||
uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
|
uint64_t segOff = is64Bit ? LC.Data.segment_command_64_data.fileoff
|
||||||
: LC.Data.segment_command_data.fileoff;
|
: LC.Data.segment_command_data.fileoff;
|
||||||
if (0 == strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
|
if (0 ==
|
||||||
|
strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
|
||||||
FoundLinkEditSeg = true;
|
FoundLinkEditSeg = true;
|
||||||
if (auto Err = writeLinkEditData(OS))
|
if (auto Err = writeLinkEditData(OS))
|
||||||
return Err;
|
return Err;
|
||||||
|
@ -592,7 +592,10 @@ void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
int yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) {
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
|
int yaml2macho(YamlObjectFile &Doc, raw_ostream &Out) {
|
||||||
UniversalWriter Writer(Doc);
|
UniversalWriter Writer(Doc);
|
||||||
if (auto Err = Writer.writeMachO(Out)) {
|
if (auto Err = Writer.writeMachO(Out)) {
|
||||||
errs() << toString(std::move(Err));
|
errs() << toString(std::move(Err));
|
||||||
|
@ -600,3 +603,6 @@ int yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -6,13 +6,19 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "yaml2obj.h"
|
|
||||||
#include "llvm/ObjectYAML/MinidumpYAML.h"
|
#include "llvm/ObjectYAML/MinidumpYAML.h"
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out) {
|
int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out) {
|
||||||
writeAsBinary(Doc, Out);
|
writeAsBinary(Doc, Out);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -14,11 +14,13 @@
|
||||||
|
|
||||||
#include "llvm/Object/Wasm.h"
|
#include "llvm/Object/Wasm.h"
|
||||||
#include "llvm/ObjectYAML/ObjectYAML.h"
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/Support/Endian.h"
|
#include "llvm/Support/Endian.h"
|
||||||
#include "llvm/Support/LEB128.h"
|
#include "llvm/Support/LEB128.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
/// This parses a yaml stream that represents a Wasm object file.
|
/// This parses a yaml stream that represents a Wasm object file.
|
||||||
/// See docs/yaml2obj for the yaml scheema.
|
/// See docs/yaml2obj for the yaml scheema.
|
||||||
class WasmWriter {
|
class WasmWriter {
|
||||||
|
@ -58,6 +60,26 @@ private:
|
||||||
uint32_t NumImportedEvents = 0;
|
uint32_t NumImportedEvents = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SubSectionWriter {
|
||||||
|
raw_ostream &OS;
|
||||||
|
std::string OutString;
|
||||||
|
raw_string_ostream StringStream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
|
||||||
|
|
||||||
|
void done() {
|
||||||
|
StringStream.flush();
|
||||||
|
encodeULEB128(OutString.size(), OS);
|
||||||
|
OS << OutString;
|
||||||
|
OutString.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_ostream &getStream() { return StringStream; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end anonymous namespace
|
||||||
|
|
||||||
static int writeUint64(raw_ostream &OS, uint64_t Value) {
|
static int writeUint64(raw_ostream &OS, uint64_t Value) {
|
||||||
char Data[sizeof(Value)];
|
char Data[sizeof(Value)];
|
||||||
support::endian::write64le(Data, Value);
|
support::endian::write64le(Data, Value);
|
||||||
|
@ -119,24 +141,6 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SubSectionWriter {
|
|
||||||
raw_ostream &OS;
|
|
||||||
std::string OutString;
|
|
||||||
raw_string_ostream StringStream;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
|
|
||||||
|
|
||||||
void done() {
|
|
||||||
StringStream.flush();
|
|
||||||
encodeULEB128(OutString.size(), OS);
|
|
||||||
OS << OutString;
|
|
||||||
OutString.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_ostream &getStream() { return StringStream; }
|
|
||||||
};
|
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::DylinkSection &Section) {
|
WasmYAML::DylinkSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
|
@ -651,8 +655,14 @@ int WasmWriter::writeWasm(raw_ostream &OS) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
|
int yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) {
|
||||||
WasmWriter Writer(Doc);
|
WasmWriter Writer(Doc);
|
||||||
|
|
||||||
return Writer.writeWasm(Out);
|
return Writer.writeWasm(Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -0,0 +1,68 @@
|
||||||
|
//===-- yaml2obj.cpp ------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/Object/ObjectFile.h"
|
||||||
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
|
#include "llvm/Support/Errc.h"
|
||||||
|
#include "llvm/Support/YAMLTraits.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace yaml {
|
||||||
|
|
||||||
|
Error convertYAML(yaml::Input &YIn, raw_ostream &Out, unsigned DocNum) {
|
||||||
|
// TODO: make yaml2* functions return Error instead of int.
|
||||||
|
auto IntToErr = [](int Ret) -> Error {
|
||||||
|
if (Ret)
|
||||||
|
return createStringError(errc::invalid_argument, "yaml2obj failed");
|
||||||
|
return Error::success();
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned CurDocNum = 0;
|
||||||
|
do {
|
||||||
|
if (++CurDocNum == DocNum) {
|
||||||
|
yaml::YamlObjectFile Doc;
|
||||||
|
YIn >> Doc;
|
||||||
|
if (std::error_code EC = YIn.error())
|
||||||
|
return createStringError(EC, "Failed to parse YAML input!");
|
||||||
|
if (Doc.Elf)
|
||||||
|
return IntToErr(yaml2elf(*Doc.Elf, Out));
|
||||||
|
if (Doc.Coff)
|
||||||
|
return IntToErr(yaml2coff(*Doc.Coff, Out));
|
||||||
|
if (Doc.MachO || Doc.FatMachO)
|
||||||
|
return IntToErr(yaml2macho(Doc, Out));
|
||||||
|
if (Doc.Minidump)
|
||||||
|
return IntToErr(yaml2minidump(*Doc.Minidump, Out));
|
||||||
|
if (Doc.Wasm)
|
||||||
|
return IntToErr(yaml2wasm(*Doc.Wasm, Out));
|
||||||
|
return createStringError(errc::invalid_argument,
|
||||||
|
"Unknown document type!");
|
||||||
|
}
|
||||||
|
} while (YIn.nextDocument());
|
||||||
|
|
||||||
|
return createStringError(errc::invalid_argument,
|
||||||
|
"Cannot find the %u%s document", DocNum,
|
||||||
|
getOrdinalSuffix(DocNum).data());
|
||||||
|
}
|
||||||
|
|
||||||
|
Expected<std::unique_ptr<object::ObjectFile>>
|
||||||
|
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml) {
|
||||||
|
Storage.clear();
|
||||||
|
raw_svector_ostream OS(Storage);
|
||||||
|
|
||||||
|
yaml::Input YIn(Yaml);
|
||||||
|
if (Error E = convertYAML(YIn, OS))
|
||||||
|
return std::move(E);
|
||||||
|
|
||||||
|
return object::ObjectFile::createObjectFile(
|
||||||
|
MemoryBufferRef(OS.str(), "YamlObject"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace yaml
|
||||||
|
} // namespace llvm
|
|
@ -2,7 +2,7 @@
|
||||||
# RUN: echo -n "" | not yaml2obj 2>&1 | FileCheck %s
|
# RUN: echo -n "" | not yaml2obj 2>&1 | FileCheck %s
|
||||||
# RUN: echo " " | not yaml2obj 2>&1 | FileCheck %s
|
# RUN: echo " " | not yaml2obj 2>&1 | FileCheck %s
|
||||||
# RUN: echo " " | not yaml2obj 2>&1 | FileCheck %s
|
# RUN: echo " " | not yaml2obj 2>&1 | FileCheck %s
|
||||||
# CHECK: yaml2obj: Unknown document type!
|
# CHECK: yaml2obj: error: Unknown document type!
|
||||||
|
|
||||||
# RUN: echo -e -n "\xff" | not yaml2obj 2>&1 | FileCheck %s --check-prefix=INVALID
|
# RUN: echo -e -n "\xff" | not yaml2obj 2>&1 | FileCheck %s --check-prefix=INVALID
|
||||||
# INVALID: yaml2obj: Failed to parse YAML file!
|
# INVALID: yaml2obj: error: Failed to parse YAML input!
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
## Test that an error is reported when a docnum is specified, which is
|
||||||
|
## greater than the number of YAML inputs in the file.
|
||||||
|
|
||||||
|
# RUN: not yaml2obj %s --docnum=3 2>&1 | FileCheck %s
|
||||||
|
# CHECK: yaml2obj: error: Cannot find the 3rd document
|
||||||
|
|
||||||
|
# RUN: not yaml2obj %s --docnum=76768677 2>&1 | FileCheck %s --check-prefix=TWO
|
||||||
|
# TWO: yaml2obj: error: Cannot find the 76768677th document
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
||||||
|
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_DYN
|
||||||
|
Machine: EM_X86_64
|
|
@ -6,4 +6,4 @@ DummyData:
|
||||||
...
|
...
|
||||||
|
|
||||||
# CHECK: YAML:4:1: error: YAML Object File missing document type tag!
|
# CHECK: YAML:4:1: error: YAML Object File missing document type tag!
|
||||||
# CHECK: yaml2obj: Failed to parse YAML file!
|
# CHECK: yaml2obj: error: Failed to parse YAML input!
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
# DOC2: Name: _sym2
|
# DOC2: Name: _sym2
|
||||||
# DOC3: Name: _sym3
|
# DOC3: Name: _sym3
|
||||||
# DOC4: Name: _sym4
|
# DOC4: Name: _sym4
|
||||||
# DOC5: yaml2obj: Cannot find the 5th document
|
# DOC5: yaml2obj: error: Cannot find the 5th document
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader: !FileHeader
|
FileHeader: !FileHeader
|
||||||
|
|
|
@ -175,4 +175,4 @@ Sections:
|
||||||
# ERR2: error: Section size must be greater than or equal to the content size
|
# ERR2: error: Section size must be greater than or equal to the content size
|
||||||
# ERR2-NEXT: - Name: .data
|
# ERR2-NEXT: - Name: .data
|
||||||
# ERR2-NEXT: ^
|
# ERR2-NEXT: ^
|
||||||
# ERR2-NEXT: yaml2obj: Failed to parse YAML file!
|
# ERR2-NEXT: yaml2obj: error: Failed to parse YAML input!
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
set(LLVM_LINK_COMPONENTS
|
set(LLVM_LINK_COMPONENTS
|
||||||
DebugInfoCodeView
|
|
||||||
MC
|
|
||||||
Object
|
|
||||||
ObjectYAML
|
ObjectYAML
|
||||||
Support
|
Support
|
||||||
)
|
)
|
||||||
|
|
||||||
add_llvm_tool(yaml2obj
|
add_llvm_tool(yaml2obj
|
||||||
yaml2obj.cpp
|
yaml2obj.cpp
|
||||||
yaml2coff.cpp
|
|
||||||
yaml2elf.cpp
|
|
||||||
yaml2macho.cpp
|
|
||||||
yaml2minidump.cpp
|
|
||||||
yaml2wasm.cpp
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "yaml2obj.h"
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ObjectYAML/ObjectYAML.h"
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
@ -21,6 +21,7 @@
|
||||||
#include "llvm/Support/InitLLVM.h"
|
#include "llvm/Support/InitLLVM.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/ToolOutputFile.h"
|
#include "llvm/Support/ToolOutputFile.h"
|
||||||
|
#include "llvm/Support/WithColor.h"
|
||||||
#include "llvm/Support/YAMLTraits.h"
|
#include "llvm/Support/YAMLTraits.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
@ -42,32 +43,6 @@ LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int convertYAML(yaml::Input &YIn, raw_ostream &Out) {
|
|
||||||
unsigned CurDocNum = 0;
|
|
||||||
do {
|
|
||||||
if (++CurDocNum == DocNum) {
|
|
||||||
yaml::YamlObjectFile Doc;
|
|
||||||
YIn >> Doc;
|
|
||||||
if (YIn.error())
|
|
||||||
error("yaml2obj: Failed to parse YAML file!");
|
|
||||||
if (Doc.Elf)
|
|
||||||
return yaml2elf(*Doc.Elf, Out);
|
|
||||||
if (Doc.Coff)
|
|
||||||
return yaml2coff(*Doc.Coff, Out);
|
|
||||||
if (Doc.MachO || Doc.FatMachO)
|
|
||||||
return yaml2macho(Doc, Out);
|
|
||||||
if (Doc.Minidump)
|
|
||||||
return yaml2minidump(*Doc.Minidump, Out);
|
|
||||||
if (Doc.Wasm)
|
|
||||||
return yaml2wasm(*Doc.Wasm, Out);
|
|
||||||
error("yaml2obj: Unknown document type!");
|
|
||||||
}
|
|
||||||
} while (YIn.nextDocument());
|
|
||||||
|
|
||||||
error("yaml2obj: Cannot find the " + Twine(DocNum) +
|
|
||||||
llvm::getOrdinalSuffix(DocNum) + " document");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
InitLLVM X(argc, argv);
|
InitLLVM X(argc, argv);
|
||||||
cl::ParseCommandLineOptions(argc, argv);
|
cl::ParseCommandLineOptions(argc, argv);
|
||||||
|
@ -87,10 +62,12 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
yaml::Input YIn(Buf.get()->getBuffer());
|
yaml::Input YIn(Buf.get()->getBuffer());
|
||||||
int Res = convertYAML(YIn, Out->os());
|
if (Error E = convertYAML(YIn, Out->os(), DocNum)) {
|
||||||
if (Res == 0)
|
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
|
||||||
Out->keep();
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Out->keep();
|
||||||
Out->os().flush();
|
Out->os().flush();
|
||||||
return Res;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
|
||||||
|
|
||||||
add_llvm_unittest(ObjectYAMLTests
|
add_llvm_unittest(ObjectYAMLTests
|
||||||
MinidumpYAMLTest.cpp
|
MinidumpYAMLTest.cpp
|
||||||
|
YAML2ObjTest.cpp
|
||||||
YAMLTest.cpp
|
YAMLTest.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
//===- YAML2ObjTest.cpp --------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
#include "llvm/Object/ObjectFile.h"
|
||||||
|
#include "llvm/Support/Error.h"
|
||||||
|
#include "llvm/Testing/Support/Error.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace object;
|
||||||
|
using namespace yaml;
|
||||||
|
|
||||||
|
TEST(yaml2ObjectFile, ELF) {
|
||||||
|
SmallString<0> Storage;
|
||||||
|
Expected<std::unique_ptr<ObjectFile>> ErrOrObj = yaml2ObjectFile(Storage, R"(
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_REL
|
||||||
|
Machine: EM_X86_64)");
|
||||||
|
|
||||||
|
ASSERT_THAT_EXPECTED(ErrOrObj, Succeeded());
|
||||||
|
|
||||||
|
std::unique_ptr<ObjectFile> ObjFile = std::move(ErrOrObj.get());
|
||||||
|
|
||||||
|
ASSERT_TRUE(ObjFile->isELF());
|
||||||
|
ASSERT_TRUE(ObjFile->isRelocatableObject());
|
||||||
|
}
|
Loading…
Reference in New Issue