mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-13 08:56:04 +00:00
[yaml2obj/ObjectYAML] - Cleanup the error reporting API, add custom errors handlers.
This is a continuation of the YAML library error reporting refactoring/improvement and the idea by itself was mentioned in the following thread: https://reviews.llvm.org/D67182?id=218714#inline-603404 This performs a cleanup of all object emitters in the library. It allows using the custom one provided by the caller. One of the nice things is that each tool can now print its tool name, e.g: "yaml2obj: error: <text>" Also, the code became a bit simpler. Differential revision: https://reviews.llvm.org/D67445 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@371865 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3e78f24a79
commit
04c501607e
@ -44,17 +44,22 @@ namespace yaml {
|
|||||||
class Input;
|
class Input;
|
||||||
struct YamlObjectFile;
|
struct YamlObjectFile;
|
||||||
|
|
||||||
bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out);
|
using ErrorHandler = llvm::function_ref<void(const Twine &Msg)>;
|
||||||
bool yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out);
|
|
||||||
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out);
|
|
||||||
bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out);
|
|
||||||
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out);
|
|
||||||
|
|
||||||
Error convertYAML(Input &YIn, raw_ostream &Out, unsigned DocNum = 1);
|
bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
|
||||||
|
bool yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
|
||||||
|
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler EH);
|
||||||
|
bool yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out,
|
||||||
|
ErrorHandler EH);
|
||||||
|
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH);
|
||||||
|
|
||||||
|
bool convertYAML(Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
|
||||||
|
unsigned DocNum = 1);
|
||||||
|
|
||||||
/// Convenience function for tests.
|
/// Convenience function for tests.
|
||||||
Expected<std::unique_ptr<object::ObjectFile>>
|
std::unique_ptr<object::ObjectFile>
|
||||||
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml);
|
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml,
|
||||||
|
ErrorHandler ErrHandler);
|
||||||
|
|
||||||
} // namespace yaml
|
} // namespace yaml
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
@ -34,8 +34,8 @@ 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 {
|
||||||
COFFParser(COFFYAML::Object &Obj)
|
COFFParser(COFFYAML::Object &Obj, yaml::ErrorHandler EH)
|
||||||
: Obj(Obj), SectionTableStart(0), SectionTableSize(0) {
|
: Obj(Obj), SectionTableStart(0), SectionTableSize(0), ErrHandler(EH) {
|
||||||
// A COFF string table always starts with a 4 byte size field. Offsets into
|
// A COFF string table always starts with a 4 byte size field. Offsets into
|
||||||
// it include this size, so allocate it now.
|
// it include this size, so allocate it now.
|
||||||
StringTable.append(4, char(0));
|
StringTable.append(4, char(0));
|
||||||
@ -81,7 +81,7 @@ struct COFFParser {
|
|||||||
unsigned Index = getStringIndex(Name);
|
unsigned Index = getStringIndex(Name);
|
||||||
std::string str = utostr(Index);
|
std::string str = utostr(Index);
|
||||||
if (str.size() > 7) {
|
if (str.size() > 7) {
|
||||||
errs() << "String table got too large\n";
|
ErrHandler("string table got too large");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Sec.Header.Name[0] = '/';
|
Sec.Header.Name[0] = '/';
|
||||||
@ -90,11 +90,11 @@ struct COFFParser {
|
|||||||
|
|
||||||
if (Sec.Alignment) {
|
if (Sec.Alignment) {
|
||||||
if (Sec.Alignment > 8192) {
|
if (Sec.Alignment > 8192) {
|
||||||
errs() << "Section alignment is too large\n";
|
ErrHandler("section alignment is too large");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!isPowerOf2_32(Sec.Alignment)) {
|
if (!isPowerOf2_32(Sec.Alignment)) {
|
||||||
errs() << "Section alignment is not a power of 2\n";
|
ErrHandler("section alignment is not a power of 2");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
|
Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
|
||||||
@ -155,6 +155,8 @@ struct COFFParser {
|
|||||||
std::string StringTable;
|
std::string StringTable;
|
||||||
uint32_t SectionTableStart;
|
uint32_t SectionTableStart;
|
||||||
uint32_t SectionTableSize;
|
uint32_t SectionTableSize;
|
||||||
|
|
||||||
|
yaml::ErrorHandler ErrHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { DOSStubSize = 128 };
|
enum { DOSStubSize = 128 };
|
||||||
@ -592,24 +594,25 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
|
bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out,
|
||||||
COFFParser CP(Doc);
|
ErrorHandler ErrHandler) {
|
||||||
|
COFFParser CP(Doc, ErrHandler);
|
||||||
if (!CP.parse()) {
|
if (!CP.parse()) {
|
||||||
errs() << "yaml2obj: Failed to parse YAML file!\n";
|
ErrHandler("failed to parse YAML file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!layoutOptionalHeader(CP)) {
|
if (!layoutOptionalHeader(CP)) {
|
||||||
errs() << "yaml2obj: Failed to layout optional header for COFF file!\n";
|
ErrHandler("failed to layout optional header for COFF file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!layoutCOFF(CP)) {
|
if (!layoutCOFF(CP)) {
|
||||||
errs() << "yaml2obj: Failed to layout COFF file!\n";
|
ErrHandler("failed to layout COFF file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!writeCOFF(CP, Out)) {
|
if (!writeCOFF(CP, Out)) {
|
||||||
errs() << "yaml2obj: Failed to write COFF file!\n";
|
ErrHandler("failed to write COFF file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -115,12 +115,13 @@ template <class ELFT> class ELFState {
|
|||||||
ELFYAML::Object &Doc;
|
ELFYAML::Object &Doc;
|
||||||
|
|
||||||
bool HasError = false;
|
bool HasError = false;
|
||||||
|
yaml::ErrorHandler ErrHandler;
|
||||||
|
void reportError(const Twine &Msg);
|
||||||
|
|
||||||
std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
|
std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
|
||||||
const StringTableBuilder &Strtab);
|
const StringTableBuilder &Strtab);
|
||||||
unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");
|
unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");
|
||||||
unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);
|
unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);
|
||||||
void reportError(const Twine &Msg);
|
|
||||||
|
|
||||||
void buildSectionIndex();
|
void buildSectionIndex();
|
||||||
void buildSymbolIndexes();
|
void buildSymbolIndexes();
|
||||||
@ -166,9 +167,11 @@ template <class ELFT> class ELFState {
|
|||||||
void writeSectionContent(Elf_Shdr &SHeader,
|
void writeSectionContent(Elf_Shdr &SHeader,
|
||||||
const ELFYAML::DynamicSection &Section,
|
const ELFYAML::DynamicSection &Section,
|
||||||
ContiguousBlobAccumulator &CBA);
|
ContiguousBlobAccumulator &CBA);
|
||||||
ELFState(ELFYAML::Object &D);
|
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc);
|
static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
|
||||||
|
yaml::ErrorHandler EH);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
@ -182,7 +185,9 @@ template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
|
|||||||
|
|
||||||
template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
|
template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }
|
||||||
|
|
||||||
template <class ELFT> ELFState<ELFT>::ELFState(ELFYAML::Object &D) : Doc(D) {
|
template <class ELFT>
|
||||||
|
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
|
||||||
|
: Doc(D), ErrHandler(EH) {
|
||||||
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())
|
||||||
@ -592,7 +597,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
|
template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
|
||||||
WithColor::error() << Msg << "\n";
|
ErrHandler(Msg);
|
||||||
HasError = true;
|
HasError = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,8 +988,9 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
|
bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
|
||||||
ELFState<ELFT> State(Doc);
|
yaml::ErrorHandler EH) {
|
||||||
|
ELFState<ELFT> State(Doc, EH);
|
||||||
|
|
||||||
// Finalize .strtab and .dynstr sections. We do that early because want to
|
// Finalize .strtab and .dynstr sections. We do that early because want to
|
||||||
// finalize the string table builders before writing the content of the
|
// finalize the string table builders before writing the content of the
|
||||||
@ -1022,17 +1028,17 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
|
bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
|
||||||
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);
|
||||||
if (Is64Bit) {
|
if (Is64Bit) {
|
||||||
if (IsLE)
|
if (IsLE)
|
||||||
return ELFState<object::ELF64LE>::writeELF(Out, Doc);
|
return ELFState<object::ELF64LE>::writeELF(Out, Doc, EH);
|
||||||
return ELFState<object::ELF64BE>::writeELF(Out, Doc);
|
return ELFState<object::ELF64BE>::writeELF(Out, Doc, EH);
|
||||||
}
|
}
|
||||||
if (IsLE)
|
if (IsLE)
|
||||||
return ELFState<object::ELF32LE>::writeELF(Out, Doc);
|
return ELFState<object::ELF32LE>::writeELF(Out, Doc, EH);
|
||||||
return ELFState<object::ELF32BE>::writeELF(Out, Doc);
|
return ELFState<object::ELF32BE>::writeELF(Out, Doc, EH);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace yaml
|
} // namespace yaml
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#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/ObjectYAML/yaml2obj.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"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
@ -34,24 +33,24 @@ public:
|
|||||||
memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
|
memset(reinterpret_cast<void *>(&Header), 0, sizeof(MachO::mach_header_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
Error writeMachO(raw_ostream &OS);
|
void writeMachO(raw_ostream &OS);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error writeHeader(raw_ostream &OS);
|
void writeHeader(raw_ostream &OS);
|
||||||
Error writeLoadCommands(raw_ostream &OS);
|
void writeLoadCommands(raw_ostream &OS);
|
||||||
Error writeSectionData(raw_ostream &OS);
|
void writeSectionData(raw_ostream &OS);
|
||||||
Error writeLinkEditData(raw_ostream &OS);
|
void writeLinkEditData(raw_ostream &OS);
|
||||||
|
|
||||||
void writeBindOpcodes(raw_ostream &OS,
|
void writeBindOpcodes(raw_ostream &OS,
|
||||||
std::vector<MachOYAML::BindOpcode> &BindOpcodes);
|
std::vector<MachOYAML::BindOpcode> &BindOpcodes);
|
||||||
// LinkEdit writers
|
// LinkEdit writers
|
||||||
Error writeRebaseOpcodes(raw_ostream &OS);
|
void writeRebaseOpcodes(raw_ostream &OS);
|
||||||
Error writeBasicBindOpcodes(raw_ostream &OS);
|
void writeBasicBindOpcodes(raw_ostream &OS);
|
||||||
Error writeWeakBindOpcodes(raw_ostream &OS);
|
void writeWeakBindOpcodes(raw_ostream &OS);
|
||||||
Error writeLazyBindOpcodes(raw_ostream &OS);
|
void writeLazyBindOpcodes(raw_ostream &OS);
|
||||||
Error writeNameList(raw_ostream &OS);
|
void writeNameList(raw_ostream &OS);
|
||||||
Error writeStringTable(raw_ostream &OS);
|
void writeStringTable(raw_ostream &OS);
|
||||||
Error writeExportTrie(raw_ostream &OS);
|
void writeExportTrie(raw_ostream &OS);
|
||||||
|
|
||||||
void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
|
void dumpExportEntry(raw_ostream &OS, MachOYAML::ExportEntry &Entry);
|
||||||
void ZeroToOffset(raw_ostream &OS, size_t offset);
|
void ZeroToOffset(raw_ostream &OS, size_t offset);
|
||||||
@ -63,18 +62,14 @@ private:
|
|||||||
MachO::mach_header_64 Header;
|
MachO::mach_header_64 Header;
|
||||||
};
|
};
|
||||||
|
|
||||||
Error MachOWriter::writeMachO(raw_ostream &OS) {
|
void MachOWriter::writeMachO(raw_ostream &OS) {
|
||||||
fileStart = OS.tell();
|
fileStart = OS.tell();
|
||||||
if (auto Err = writeHeader(OS))
|
writeHeader(OS);
|
||||||
return Err;
|
writeLoadCommands(OS);
|
||||||
if (auto Err = writeLoadCommands(OS))
|
writeSectionData(OS);
|
||||||
return Err;
|
|
||||||
if (auto Err = writeSectionData(OS))
|
|
||||||
return Err;
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeHeader(raw_ostream &OS) {
|
void MachOWriter::writeHeader(raw_ostream &OS) {
|
||||||
Header.magic = Obj.Header.magic;
|
Header.magic = Obj.Header.magic;
|
||||||
Header.cputype = Obj.Header.cputype;
|
Header.cputype = Obj.Header.cputype;
|
||||||
Header.cpusubtype = Obj.Header.cpusubtype;
|
Header.cpusubtype = Obj.Header.cpusubtype;
|
||||||
@ -90,8 +85,6 @@ Error MachOWriter::writeHeader(raw_ostream &OS) {
|
|||||||
auto header_size =
|
auto header_size =
|
||||||
is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
|
is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
|
||||||
OS.write((const char *)&Header, header_size);
|
OS.write((const char *)&Header, header_size);
|
||||||
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SectionType>
|
template <typename SectionType>
|
||||||
@ -212,7 +205,7 @@ void MachOWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
|
|||||||
ZeroFillBytes(OS, Offset - currOffset);
|
ZeroFillBytes(OS, Offset - currOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
|
void MachOWriter::writeLoadCommands(raw_ostream &OS) {
|
||||||
for (auto &LC : Obj.LoadCommands) {
|
for (auto &LC : Obj.LoadCommands) {
|
||||||
size_t BytesWritten = 0;
|
size_t BytesWritten = 0;
|
||||||
llvm::MachO::macho_load_command Data = LC.Data;
|
llvm::MachO::macho_load_command Data = LC.Data;
|
||||||
@ -259,10 +252,9 @@ Error MachOWriter::writeLoadCommands(raw_ostream &OS) {
|
|||||||
ZeroFillBytes(OS, BytesRemaining);
|
ZeroFillBytes(OS, BytesRemaining);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
void MachOWriter::writeSectionData(raw_ostream &OS) {
|
||||||
bool FoundLinkEditSeg = false;
|
bool FoundLinkEditSeg = false;
|
||||||
for (auto &LC : Obj.LoadCommands) {
|
for (auto &LC : Obj.LoadCommands) {
|
||||||
switch (LC.Data.load_command_data.cmd) {
|
switch (LC.Data.load_command_data.cmd) {
|
||||||
@ -273,8 +265,7 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
|||||||
if (0 ==
|
if (0 ==
|
||||||
strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
|
strncmp(&LC.Data.segment_command_data.segname[0], "__LINKEDIT", 16)) {
|
||||||
FoundLinkEditSeg = true;
|
FoundLinkEditSeg = true;
|
||||||
if (auto Err = writeLinkEditData(OS))
|
writeLinkEditData(OS);
|
||||||
return Err;
|
|
||||||
}
|
}
|
||||||
for (auto &Sec : LC.Sections) {
|
for (auto &Sec : LC.Sections) {
|
||||||
ZeroToOffset(OS, Sec.offset);
|
ZeroToOffset(OS, Sec.offset);
|
||||||
@ -326,11 +317,8 @@ Error MachOWriter::writeSectionData(raw_ostream &OS) {
|
|||||||
}
|
}
|
||||||
// Old PPC Object Files didn't have __LINKEDIT segments, the data was just
|
// Old PPC Object Files didn't have __LINKEDIT segments, the data was just
|
||||||
// stuck at the end of the file.
|
// stuck at the end of the file.
|
||||||
if (!FoundLinkEditSeg) {
|
if (!FoundLinkEditSeg)
|
||||||
if (auto Err = writeLinkEditData(OS))
|
writeLinkEditData(OS);
|
||||||
return Err;
|
|
||||||
}
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MachOWriter::writeBindOpcodes(
|
void MachOWriter::writeBindOpcodes(
|
||||||
@ -377,9 +365,8 @@ void MachOWriter::dumpExportEntry(raw_ostream &OS,
|
|||||||
dumpExportEntry(OS, EE);
|
dumpExportEntry(OS, EE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeExportTrie(raw_ostream &OS) {
|
void MachOWriter::writeExportTrie(raw_ostream &OS) {
|
||||||
dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
|
dumpExportEntry(OS, Obj.LinkEdit.ExportTrie);
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename NListType>
|
template <typename NListType>
|
||||||
@ -397,8 +384,8 @@ void writeNListEntry(MachOYAML::NListEntry &NLE, raw_ostream &OS,
|
|||||||
OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
|
OS.write(reinterpret_cast<const char *>(&ListEntry), sizeof(NListType));
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
|
void MachOWriter::writeLinkEditData(raw_ostream &OS) {
|
||||||
typedef Error (MachOWriter::*writeHandler)(raw_ostream &);
|
typedef void (MachOWriter::*writeHandler)(raw_ostream &);
|
||||||
typedef std::pair<uint64_t, writeHandler> writeOperation;
|
typedef std::pair<uint64_t, writeHandler> writeOperation;
|
||||||
std::vector<writeOperation> WriteQueue;
|
std::vector<writeOperation> WriteQueue;
|
||||||
|
|
||||||
@ -435,57 +422,47 @@ Error MachOWriter::writeLinkEditData(raw_ostream &OS) {
|
|||||||
|
|
||||||
for (auto writeOp : WriteQueue) {
|
for (auto writeOp : WriteQueue) {
|
||||||
ZeroToOffset(OS, writeOp.first);
|
ZeroToOffset(OS, writeOp.first);
|
||||||
if (auto Err = (this->*writeOp.second)(OS))
|
(this->*writeOp.second)(OS);
|
||||||
return Err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
|
void MachOWriter::writeRebaseOpcodes(raw_ostream &OS) {
|
||||||
MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
|
MachOYAML::LinkEditData &LinkEdit = Obj.LinkEdit;
|
||||||
|
|
||||||
for (auto Opcode : LinkEdit.RebaseOpcodes) {
|
for (auto Opcode : LinkEdit.RebaseOpcodes) {
|
||||||
uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
|
uint8_t OpByte = Opcode.Opcode | Opcode.Imm;
|
||||||
OS.write(reinterpret_cast<char *>(&OpByte), 1);
|
OS.write(reinterpret_cast<char *>(&OpByte), 1);
|
||||||
for (auto Data : Opcode.ExtraData) {
|
for (auto Data : Opcode.ExtraData)
|
||||||
encodeULEB128(Data, OS);
|
encodeULEB128(Data, OS);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
|
void MachOWriter::writeBasicBindOpcodes(raw_ostream &OS) {
|
||||||
writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
|
writeBindOpcodes(OS, Obj.LinkEdit.BindOpcodes);
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
|
void MachOWriter::writeWeakBindOpcodes(raw_ostream &OS) {
|
||||||
writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
|
writeBindOpcodes(OS, Obj.LinkEdit.WeakBindOpcodes);
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
|
void MachOWriter::writeLazyBindOpcodes(raw_ostream &OS) {
|
||||||
writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
|
writeBindOpcodes(OS, Obj.LinkEdit.LazyBindOpcodes);
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeNameList(raw_ostream &OS) {
|
void MachOWriter::writeNameList(raw_ostream &OS) {
|
||||||
for (auto NLE : Obj.LinkEdit.NameList) {
|
for (auto NLE : Obj.LinkEdit.NameList) {
|
||||||
if (is64Bit)
|
if (is64Bit)
|
||||||
writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
|
writeNListEntry<MachO::nlist_64>(NLE, OS, Obj.IsLittleEndian);
|
||||||
else
|
else
|
||||||
writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
|
writeNListEntry<MachO::nlist>(NLE, OS, Obj.IsLittleEndian);
|
||||||
}
|
}
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MachOWriter::writeStringTable(raw_ostream &OS) {
|
void MachOWriter::writeStringTable(raw_ostream &OS) {
|
||||||
for (auto Str : Obj.LinkEdit.StringTable) {
|
for (auto Str : Obj.LinkEdit.StringTable) {
|
||||||
OS.write(Str.data(), Str.size());
|
OS.write(Str.data(), Str.size());
|
||||||
OS.write('\0');
|
OS.write('\0');
|
||||||
}
|
}
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class UniversalWriter {
|
class UniversalWriter {
|
||||||
@ -493,11 +470,11 @@ public:
|
|||||||
UniversalWriter(yaml::YamlObjectFile &ObjectFile)
|
UniversalWriter(yaml::YamlObjectFile &ObjectFile)
|
||||||
: ObjectFile(ObjectFile), fileStart(0) {}
|
: ObjectFile(ObjectFile), fileStart(0) {}
|
||||||
|
|
||||||
Error writeMachO(raw_ostream &OS);
|
void writeMachO(raw_ostream &OS);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Error writeFatHeader(raw_ostream &OS);
|
void writeFatHeader(raw_ostream &OS);
|
||||||
Error writeFatArchs(raw_ostream &OS);
|
void writeFatArchs(raw_ostream &OS);
|
||||||
|
|
||||||
void ZeroToOffset(raw_ostream &OS, size_t offset);
|
void ZeroToOffset(raw_ostream &OS, size_t offset);
|
||||||
|
|
||||||
@ -505,30 +482,30 @@ private:
|
|||||||
uint64_t fileStart;
|
uint64_t fileStart;
|
||||||
};
|
};
|
||||||
|
|
||||||
Error UniversalWriter::writeMachO(raw_ostream &OS) {
|
void UniversalWriter::writeMachO(raw_ostream &OS) {
|
||||||
fileStart = OS.tell();
|
fileStart = OS.tell();
|
||||||
if (ObjectFile.MachO) {
|
if (ObjectFile.MachO) {
|
||||||
MachOWriter Writer(*ObjectFile.MachO);
|
MachOWriter Writer(*ObjectFile.MachO);
|
||||||
return Writer.writeMachO(OS);
|
Writer.writeMachO(OS);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (auto Err = writeFatHeader(OS))
|
|
||||||
return Err;
|
writeFatHeader(OS);
|
||||||
if (auto Err = writeFatArchs(OS))
|
writeFatArchs(OS);
|
||||||
return Err;
|
|
||||||
auto &FatFile = *ObjectFile.FatMachO;
|
auto &FatFile = *ObjectFile.FatMachO;
|
||||||
assert(FatFile.FatArchs.size() == FatFile.Slices.size());
|
assert(FatFile.FatArchs.size() == FatFile.Slices.size());
|
||||||
for (size_t i = 0; i < FatFile.Slices.size(); i++) {
|
for (size_t i = 0; i < FatFile.Slices.size(); i++) {
|
||||||
ZeroToOffset(OS, FatFile.FatArchs[i].offset);
|
ZeroToOffset(OS, FatFile.FatArchs[i].offset);
|
||||||
MachOWriter Writer(FatFile.Slices[i]);
|
MachOWriter Writer(FatFile.Slices[i]);
|
||||||
if (auto Err = Writer.writeMachO(OS))
|
Writer.writeMachO(OS);
|
||||||
return Err;
|
|
||||||
auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
|
auto SliceEnd = FatFile.FatArchs[i].offset + FatFile.FatArchs[i].size;
|
||||||
ZeroToOffset(OS, SliceEnd);
|
ZeroToOffset(OS, SliceEnd);
|
||||||
}
|
}
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
|
void UniversalWriter::writeFatHeader(raw_ostream &OS) {
|
||||||
auto &FatFile = *ObjectFile.FatMachO;
|
auto &FatFile = *ObjectFile.FatMachO;
|
||||||
MachO::fat_header header;
|
MachO::fat_header header;
|
||||||
header.magic = FatFile.Header.magic;
|
header.magic = FatFile.Header.magic;
|
||||||
@ -536,7 +513,6 @@ Error UniversalWriter::writeFatHeader(raw_ostream &OS) {
|
|||||||
if (sys::IsLittleEndianHost)
|
if (sys::IsLittleEndianHost)
|
||||||
swapStruct(header);
|
swapStruct(header);
|
||||||
OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
|
OS.write(reinterpret_cast<const char *>(&header), sizeof(MachO::fat_header));
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FatArchType>
|
template <typename FatArchType>
|
||||||
@ -572,7 +548,7 @@ void writeFatArch<MachO::fat_arch_64>(MachOYAML::FatArch &Arch,
|
|||||||
sizeof(MachO::fat_arch_64));
|
sizeof(MachO::fat_arch_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
|
void UniversalWriter::writeFatArchs(raw_ostream &OS) {
|
||||||
auto &FatFile = *ObjectFile.FatMachO;
|
auto &FatFile = *ObjectFile.FatMachO;
|
||||||
bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
|
bool is64Bit = FatFile.Header.magic == MachO::FAT_MAGIC_64;
|
||||||
for (auto Arch : FatFile.FatArchs) {
|
for (auto Arch : FatFile.FatArchs) {
|
||||||
@ -581,8 +557,6 @@ Error UniversalWriter::writeFatArchs(raw_ostream &OS) {
|
|||||||
else
|
else
|
||||||
writeFatArch<MachO::fat_arch>(Arch, OS);
|
writeFatArch<MachO::fat_arch>(Arch, OS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error::success();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
|
void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
|
||||||
@ -596,12 +570,9 @@ void UniversalWriter::ZeroToOffset(raw_ostream &OS, size_t Offset) {
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out) {
|
bool yaml2macho(YamlObjectFile &Doc, raw_ostream &Out, ErrorHandler /*EH*/) {
|
||||||
UniversalWriter Writer(Doc);
|
UniversalWriter Writer(Doc);
|
||||||
if (auto Err = Writer.writeMachO(Out)) {
|
Writer.writeMachO(Out);
|
||||||
errs() << toString(std::move(Err));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,8 @@ static Directory layout(BlobAllocator &File, Stream &S) {
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
bool yaml2minidump(MinidumpYAML::Object &Obj, raw_ostream &Out) {
|
bool yaml2minidump(MinidumpYAML::Object &Obj, raw_ostream &Out,
|
||||||
|
ErrorHandler /*EH*/) {
|
||||||
BlobAllocator File;
|
BlobAllocator File;
|
||||||
File.allocateObject(Obj.Header);
|
File.allocateObject(Obj.Header);
|
||||||
|
|
||||||
|
@ -25,39 +25,46 @@ namespace {
|
|||||||
/// See docs/yaml2obj for the yaml scheema.
|
/// See docs/yaml2obj for the yaml scheema.
|
||||||
class WasmWriter {
|
class WasmWriter {
|
||||||
public:
|
public:
|
||||||
WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
|
WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
|
||||||
|
: Obj(Obj), ErrHandler(EH) {}
|
||||||
bool writeWasm(raw_ostream &OS);
|
bool writeWasm(raw_ostream &OS);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
||||||
uint32_t SectionIndex);
|
uint32_t SectionIndex);
|
||||||
|
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
|
void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
|
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
|
||||||
|
void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
|
||||||
|
void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
|
||||||
|
|
||||||
// Custom section types
|
// Custom section types
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
|
void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
|
||||||
int writeSectionContent(raw_ostream &OS,
|
void writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::TargetFeaturesSection &Section);
|
WasmYAML::TargetFeaturesSection &Section);
|
||||||
WasmYAML::Object &Obj;
|
WasmYAML::Object &Obj;
|
||||||
uint32_t NumImportedFunctions = 0;
|
uint32_t NumImportedFunctions = 0;
|
||||||
uint32_t NumImportedGlobals = 0;
|
uint32_t NumImportedGlobals = 0;
|
||||||
uint32_t NumImportedEvents = 0;
|
uint32_t NumImportedEvents = 0;
|
||||||
|
|
||||||
|
bool HasError = false;
|
||||||
|
yaml::ErrorHandler ErrHandler;
|
||||||
|
void reportError(const Twine &Msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SubSectionWriter {
|
class SubSectionWriter {
|
||||||
@ -115,7 +122,13 @@ static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
|
void WasmWriter::reportError(const Twine &Msg) {
|
||||||
|
ErrHandler(Msg);
|
||||||
|
HasError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WasmWriter::writeInitExpr(raw_ostream &OS,
|
||||||
|
const wasm::WasmInitExpr &InitExpr) {
|
||||||
writeUint8(OS, InitExpr.Opcode);
|
writeUint8(OS, InitExpr.Opcode);
|
||||||
switch (InitExpr.Opcode) {
|
switch (InitExpr.Opcode) {
|
||||||
case wasm::WASM_OPCODE_I32_CONST:
|
case wasm::WASM_OPCODE_I32_CONST:
|
||||||
@ -134,29 +147,26 @@ static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
|
|||||||
encodeULEB128(InitExpr.Value.Global, OS);
|
encodeULEB128(InitExpr.Value.Global, OS);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
|
reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
writeUint8(OS, wasm::WASM_OPCODE_END);
|
writeUint8(OS, wasm::WASM_OPCODE_END);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::DylinkSection &Section) {
|
WasmYAML::DylinkSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
encodeULEB128(Section.MemorySize, OS);
|
encodeULEB128(Section.MemorySize, OS);
|
||||||
encodeULEB128(Section.MemoryAlignment, OS);
|
encodeULEB128(Section.MemoryAlignment, OS);
|
||||||
encodeULEB128(Section.TableSize, OS);
|
encodeULEB128(Section.TableSize, OS);
|
||||||
encodeULEB128(Section.TableAlignment, OS);
|
encodeULEB128(Section.TableAlignment, OS);
|
||||||
encodeULEB128(Section.Needed.size(), OS);
|
encodeULEB128(Section.Needed.size(), OS);
|
||||||
for (StringRef Needed : Section.Needed) {
|
for (StringRef Needed : Section.Needed)
|
||||||
writeStringRef(Needed, OS);
|
writeStringRef(Needed, OS);
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::LinkingSection &Section) {
|
WasmYAML::LinkingSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
encodeULEB128(Section.Version, OS);
|
encodeULEB128(Section.Version, OS);
|
||||||
|
|
||||||
@ -240,12 +250,10 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
}
|
}
|
||||||
SubSection.done();
|
SubSection.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::NameSection &Section) {
|
WasmYAML::NameSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
if (Section.FunctionNames.size()) {
|
if (Section.FunctionNames.size()) {
|
||||||
writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
|
writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
|
||||||
@ -260,16 +268,15 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
|
|
||||||
SubSection.done();
|
SubSection.done();
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::ProducersSection &Section) {
|
WasmYAML::ProducersSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
|
int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
|
||||||
int(!Section.SDKs.empty());
|
int(!Section.SDKs.empty());
|
||||||
if (Fields == 0)
|
if (Fields == 0)
|
||||||
return 0;
|
return;
|
||||||
encodeULEB128(Fields, OS);
|
encodeULEB128(Fields, OS);
|
||||||
for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
|
for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
|
||||||
std::make_pair(StringRef("processed-by"), &Section.Tools),
|
std::make_pair(StringRef("processed-by"), &Section.Tools),
|
||||||
@ -283,52 +290,44 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
writeStringRef(Entry.Version, OS);
|
writeStringRef(Entry.Version, OS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::TargetFeaturesSection &Section) {
|
WasmYAML::TargetFeaturesSection &Section) {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
encodeULEB128(Section.Features.size(), OS);
|
encodeULEB128(Section.Features.size(), OS);
|
||||||
for (auto &E : Section.Features) {
|
for (auto &E : Section.Features) {
|
||||||
writeUint8(OS, E.Prefix);
|
writeUint8(OS, E.Prefix);
|
||||||
writeStringRef(E.Name, OS);
|
writeStringRef(E.Name, OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::CustomSection &Section) {
|
WasmYAML::CustomSection &Section) {
|
||||||
if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
|
if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
|
||||||
if (auto Err = writeSectionContent(OS, *S))
|
writeSectionContent(OS, *S);
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
|
} else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
|
||||||
if (auto Err = writeSectionContent(OS, *S))
|
writeSectionContent(OS, *S);
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
|
} else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
|
||||||
if (auto Err = writeSectionContent(OS, *S))
|
writeSectionContent(OS, *S);
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
|
} else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
|
||||||
if (auto Err = writeSectionContent(OS, *S))
|
writeSectionContent(OS, *S);
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
|
} else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
|
||||||
if (auto Err = writeSectionContent(OS, *S))
|
writeSectionContent(OS, *S);
|
||||||
return Err;
|
|
||||||
} else {
|
} else {
|
||||||
writeStringRef(Section.Name, OS);
|
writeStringRef(Section.Name, OS);
|
||||||
Section.Payload.writeAsBinary(OS);
|
Section.Payload.writeAsBinary(OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::TypeSection &Section) {
|
WasmYAML::TypeSection &Section) {
|
||||||
encodeULEB128(Section.Signatures.size(), OS);
|
encodeULEB128(Section.Signatures.size(), OS);
|
||||||
uint32_t ExpectedIndex = 0;
|
uint32_t ExpectedIndex = 0;
|
||||||
for (const WasmYAML::Signature &Sig : Section.Signatures) {
|
for (const WasmYAML::Signature &Sig : Section.Signatures) {
|
||||||
if (Sig.Index != ExpectedIndex) {
|
if (Sig.Index != ExpectedIndex) {
|
||||||
errs() << "Unexpected type index: " << Sig.Index << "\n";
|
reportError("unexpected type index: " + Twine(Sig.Index));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
++ExpectedIndex;
|
++ExpectedIndex;
|
||||||
writeUint8(OS, Sig.Form);
|
writeUint8(OS, Sig.Form);
|
||||||
@ -342,10 +341,9 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
writeUint8(OS, Sig.ReturnType);
|
writeUint8(OS, Sig.ReturnType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::ImportSection &Section) {
|
WasmYAML::ImportSection &Section) {
|
||||||
encodeULEB128(Section.Imports.size(), OS);
|
encodeULEB128(Section.Imports.size(), OS);
|
||||||
for (const WasmYAML::Import &Import : Section.Imports) {
|
for (const WasmYAML::Import &Import : Section.Imports) {
|
||||||
@ -375,23 +373,20 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
writeLimits(Import.TableImport.TableLimits, OS);
|
writeLimits(Import.TableImport.TableLimits, OS);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errs() << "Unknown import type: " << Import.Kind << "\n";
|
reportError("unknown import type: " +Twine(Import.Kind));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::FunctionSection &Section) {
|
WasmYAML::FunctionSection &Section) {
|
||||||
encodeULEB128(Section.FunctionTypes.size(), OS);
|
encodeULEB128(Section.FunctionTypes.size(), OS);
|
||||||
for (uint32_t FuncType : Section.FunctionTypes) {
|
for (uint32_t FuncType : Section.FunctionTypes)
|
||||||
encodeULEB128(FuncType, OS);
|
encodeULEB128(FuncType, OS);
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::ExportSection &Section) {
|
WasmYAML::ExportSection &Section) {
|
||||||
encodeULEB128(Section.Exports.size(), OS);
|
encodeULEB128(Section.Exports.size(), OS);
|
||||||
for (const WasmYAML::Export &Export : Section.Exports) {
|
for (const WasmYAML::Export &Export : Section.Exports) {
|
||||||
@ -399,83 +394,74 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
writeUint8(OS, Export.Kind);
|
writeUint8(OS, Export.Kind);
|
||||||
encodeULEB128(Export.Index, OS);
|
encodeULEB128(Export.Index, OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::StartSection &Section) {
|
WasmYAML::StartSection &Section) {
|
||||||
encodeULEB128(Section.StartFunction, OS);
|
encodeULEB128(Section.StartFunction, OS);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::TableSection &Section) {
|
WasmYAML::TableSection &Section) {
|
||||||
encodeULEB128(Section.Tables.size(), OS);
|
encodeULEB128(Section.Tables.size(), OS);
|
||||||
for (auto &Table : Section.Tables) {
|
for (auto &Table : Section.Tables) {
|
||||||
writeUint8(OS, Table.ElemType);
|
writeUint8(OS, Table.ElemType);
|
||||||
writeLimits(Table.TableLimits, OS);
|
writeLimits(Table.TableLimits, OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::MemorySection &Section) {
|
WasmYAML::MemorySection &Section) {
|
||||||
encodeULEB128(Section.Memories.size(), OS);
|
encodeULEB128(Section.Memories.size(), OS);
|
||||||
for (const WasmYAML::Limits &Mem : Section.Memories) {
|
for (const WasmYAML::Limits &Mem : Section.Memories)
|
||||||
writeLimits(Mem, OS);
|
writeLimits(Mem, OS);
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::GlobalSection &Section) {
|
WasmYAML::GlobalSection &Section) {
|
||||||
encodeULEB128(Section.Globals.size(), OS);
|
encodeULEB128(Section.Globals.size(), OS);
|
||||||
uint32_t ExpectedIndex = NumImportedGlobals;
|
uint32_t ExpectedIndex = NumImportedGlobals;
|
||||||
for (auto &Global : Section.Globals) {
|
for (auto &Global : Section.Globals) {
|
||||||
if (Global.Index != ExpectedIndex) {
|
if (Global.Index != ExpectedIndex) {
|
||||||
errs() << "Unexpected global index: " << Global.Index << "\n";
|
reportError("unexpected global index: " + Twine(Global.Index));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
++ExpectedIndex;
|
++ExpectedIndex;
|
||||||
writeUint8(OS, Global.Type);
|
writeUint8(OS, Global.Type);
|
||||||
writeUint8(OS, Global.Mutable);
|
writeUint8(OS, Global.Mutable);
|
||||||
writeInitExpr(Global.InitExpr, OS);
|
writeInitExpr(OS, Global.InitExpr);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::EventSection &Section) {
|
WasmYAML::EventSection &Section) {
|
||||||
encodeULEB128(Section.Events.size(), OS);
|
encodeULEB128(Section.Events.size(), OS);
|
||||||
uint32_t ExpectedIndex = NumImportedEvents;
|
uint32_t ExpectedIndex = NumImportedEvents;
|
||||||
for (auto &Event : Section.Events) {
|
for (auto &Event : Section.Events) {
|
||||||
if (Event.Index != ExpectedIndex) {
|
if (Event.Index != ExpectedIndex) {
|
||||||
errs() << "Unexpected event index: " << Event.Index << "\n";
|
reportError("unexpected event index: " + Twine(Event.Index));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
++ExpectedIndex;
|
++ExpectedIndex;
|
||||||
encodeULEB128(Event.Attribute, OS);
|
encodeULEB128(Event.Attribute, OS);
|
||||||
encodeULEB128(Event.SigIndex, OS);
|
encodeULEB128(Event.SigIndex, OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::ElemSection &Section) {
|
WasmYAML::ElemSection &Section) {
|
||||||
encodeULEB128(Section.Segments.size(), OS);
|
encodeULEB128(Section.Segments.size(), OS);
|
||||||
for (auto &Segment : Section.Segments) {
|
for (auto &Segment : Section.Segments) {
|
||||||
encodeULEB128(Segment.TableIndex, OS);
|
encodeULEB128(Segment.TableIndex, OS);
|
||||||
writeInitExpr(Segment.Offset, OS);
|
writeInitExpr(OS, Segment.Offset);
|
||||||
|
|
||||||
encodeULEB128(Segment.Functions.size(), OS);
|
encodeULEB128(Segment.Functions.size(), OS);
|
||||||
for (auto &Function : Segment.Functions) {
|
for (auto &Function : Segment.Functions)
|
||||||
encodeULEB128(Function, OS);
|
encodeULEB128(Function, OS);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::CodeSection &Section) {
|
WasmYAML::CodeSection &Section) {
|
||||||
encodeULEB128(Section.Functions.size(), OS);
|
encodeULEB128(Section.Functions.size(), OS);
|
||||||
uint32_t ExpectedIndex = NumImportedFunctions;
|
uint32_t ExpectedIndex = NumImportedFunctions;
|
||||||
@ -483,8 +469,8 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
std::string OutString;
|
std::string OutString;
|
||||||
raw_string_ostream StringStream(OutString);
|
raw_string_ostream StringStream(OutString);
|
||||||
if (Func.Index != ExpectedIndex) {
|
if (Func.Index != ExpectedIndex) {
|
||||||
errs() << "Unexpected function index: " << Func.Index << "\n";
|
reportError("unexpected function index: " + Twine(Func.Index));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
++ExpectedIndex;
|
++ExpectedIndex;
|
||||||
|
|
||||||
@ -501,31 +487,28 @@ int WasmWriter::writeSectionContent(raw_ostream &OS,
|
|||||||
encodeULEB128(OutString.size(), OS);
|
encodeULEB128(OutString.size(), OS);
|
||||||
OS << OutString;
|
OS << OutString;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::DataSection &Section) {
|
WasmYAML::DataSection &Section) {
|
||||||
encodeULEB128(Section.Segments.size(), OS);
|
encodeULEB128(Section.Segments.size(), OS);
|
||||||
for (auto &Segment : Section.Segments) {
|
for (auto &Segment : Section.Segments) {
|
||||||
encodeULEB128(Segment.InitFlags, OS);
|
encodeULEB128(Segment.InitFlags, OS);
|
||||||
if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
|
if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
|
||||||
encodeULEB128(Segment.MemoryIndex, OS);
|
encodeULEB128(Segment.MemoryIndex, OS);
|
||||||
if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
|
if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
|
||||||
writeInitExpr(Segment.Offset, OS);
|
writeInitExpr(OS, Segment.Offset);
|
||||||
encodeULEB128(Segment.Content.binary_size(), OS);
|
encodeULEB128(Segment.Content.binary_size(), OS);
|
||||||
Segment.Content.writeAsBinary(OS);
|
Segment.Content.writeAsBinary(OS);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeSectionContent(raw_ostream &OS,
|
void WasmWriter::writeSectionContent(raw_ostream &OS,
|
||||||
WasmYAML::DataCountSection &Section) {
|
WasmYAML::DataCountSection &Section) {
|
||||||
encodeULEB128(Section.Count, OS);
|
encodeULEB128(Section.Count, OS);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
||||||
uint32_t SectionIndex) {
|
uint32_t SectionIndex) {
|
||||||
switch (Sec.Type) {
|
switch (Sec.Type) {
|
||||||
case wasm::WASM_SEC_CODE:
|
case wasm::WASM_SEC_CODE:
|
||||||
@ -541,7 +524,6 @@ int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("not yet implemented");
|
llvm_unreachable("not yet implemented");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeULEB128(SectionIndex, OS);
|
encodeULEB128(SectionIndex, OS);
|
||||||
@ -560,7 +542,6 @@ int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
|
|||||||
encodeULEB128(Reloc.Addend, OS);
|
encodeULEB128(Reloc.Addend, OS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasmWriter::writeWasm(raw_ostream &OS) {
|
bool WasmWriter::writeWasm(raw_ostream &OS) {
|
||||||
@ -575,58 +556,46 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
|
|||||||
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
|
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
|
||||||
SecName = S->Name;
|
SecName = S->Name;
|
||||||
if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
|
if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
|
||||||
errs() << "Out of order section type: " << Sec->Type << "\n";
|
reportError("out of order section type: " + Twine(Sec->Type));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
encodeULEB128(Sec->Type, OS);
|
encodeULEB128(Sec->Type, OS);
|
||||||
std::string OutString;
|
std::string OutString;
|
||||||
raw_string_ostream StringStream(OutString);
|
raw_string_ostream StringStream(OutString);
|
||||||
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
|
if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
writeSectionContent(StringStream, *S);
|
||||||
return Err;
|
else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
|
||||||
} else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
|
writeSectionContent(StringStream, *S);
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
|
||||||
return Err;
|
writeSectionContent(StringStream, *S);
|
||||||
} else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
|
else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
writeSectionContent(StringStream, *S);
|
||||||
return Err;
|
else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
|
||||||
} else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
|
writeSectionContent(StringStream, *S);
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
|
||||||
return Err;
|
writeSectionContent(StringStream, *S);
|
||||||
} else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
|
else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
writeSectionContent(StringStream, *S);
|
||||||
return Err;
|
else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
|
||||||
} else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
|
writeSectionContent(StringStream, *S);
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
|
||||||
return Err;
|
writeSectionContent(StringStream, *S);
|
||||||
} else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
|
else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
writeSectionContent(StringStream, *S);
|
||||||
return Err;
|
else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
|
||||||
} else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
|
writeSectionContent(StringStream, *S);
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
|
||||||
return Err;
|
writeSectionContent(StringStream, *S);
|
||||||
} else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
|
else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
writeSectionContent(StringStream, *S);
|
||||||
return Err;
|
else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
|
||||||
} else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
|
writeSectionContent(StringStream, *S);
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
else
|
||||||
return Err;
|
reportError("unknown section type: " + Twine(Sec->Type));
|
||||||
} else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
|
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
if (HasError)
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
|
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
|
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
|
||||||
return Err;
|
|
||||||
} else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get())) {
|
|
||||||
if (auto Err = writeSectionContent(StringStream, *S))
|
|
||||||
return Err;
|
|
||||||
} else {
|
|
||||||
errs() << "Unknown section type: " << Sec->Type << "\n";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
StringStream.flush();
|
StringStream.flush();
|
||||||
|
|
||||||
// Write the section size followed by the content
|
// Write the section size followed by the content
|
||||||
@ -658,8 +627,8 @@ bool WasmWriter::writeWasm(raw_ostream &OS) {
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) {
|
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
|
||||||
WasmWriter Writer(Doc);
|
WasmWriter Writer(Doc, EH);
|
||||||
return Writer.writeWasm(Out);
|
return Writer.writeWasm(Out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,59 +8,69 @@
|
|||||||
|
|
||||||
#include "llvm/ObjectYAML/yaml2obj.h"
|
#include "llvm/ObjectYAML/yaml2obj.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/ObjectYAML/ObjectYAML.h"
|
#include "llvm/ObjectYAML/ObjectYAML.h"
|
||||||
#include "llvm/Support/Errc.h"
|
#include "llvm/Support/Errc.h"
|
||||||
|
#include "llvm/Support/WithColor.h"
|
||||||
#include "llvm/Support/YAMLTraits.h"
|
#include "llvm/Support/YAMLTraits.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
|
||||||
Error convertYAML(yaml::Input &YIn, raw_ostream &Out, unsigned DocNum) {
|
bool convertYAML(yaml::Input &YIn, raw_ostream &Out, ErrorHandler ErrHandler,
|
||||||
auto BoolToErr = [](bool Ret) -> Error {
|
unsigned DocNum) {
|
||||||
if (!Ret)
|
|
||||||
return createStringError(errc::invalid_argument, "yaml2obj failed");
|
|
||||||
return Error::success();
|
|
||||||
};
|
|
||||||
|
|
||||||
unsigned CurDocNum = 0;
|
unsigned CurDocNum = 0;
|
||||||
do {
|
do {
|
||||||
if (++CurDocNum == DocNum) {
|
if (++CurDocNum != DocNum)
|
||||||
yaml::YamlObjectFile Doc;
|
continue;
|
||||||
YIn >> Doc;
|
|
||||||
if (std::error_code EC = YIn.error())
|
yaml::YamlObjectFile Doc;
|
||||||
return createStringError(EC, "Failed to parse YAML input!");
|
YIn >> Doc;
|
||||||
if (Doc.Elf)
|
if (std::error_code EC = YIn.error()) {
|
||||||
return BoolToErr(yaml2elf(*Doc.Elf, Out));
|
ErrHandler("failed to parse YAML input: " + EC.message());
|
||||||
if (Doc.Coff)
|
return false;
|
||||||
return BoolToErr(yaml2coff(*Doc.Coff, Out));
|
|
||||||
if (Doc.MachO || Doc.FatMachO)
|
|
||||||
return BoolToErr(yaml2macho(Doc, Out));
|
|
||||||
if (Doc.Minidump)
|
|
||||||
return BoolToErr(yaml2minidump(*Doc.Minidump, Out));
|
|
||||||
if (Doc.Wasm)
|
|
||||||
return BoolToErr(yaml2wasm(*Doc.Wasm, Out));
|
|
||||||
return createStringError(errc::invalid_argument,
|
|
||||||
"Unknown document type!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Doc.Elf)
|
||||||
|
return yaml2elf(*Doc.Elf, Out, ErrHandler);
|
||||||
|
if (Doc.Coff)
|
||||||
|
return yaml2coff(*Doc.Coff, Out, ErrHandler);
|
||||||
|
if (Doc.MachO || Doc.FatMachO)
|
||||||
|
return yaml2macho(Doc, Out, ErrHandler);
|
||||||
|
if (Doc.Minidump)
|
||||||
|
return yaml2minidump(*Doc.Minidump, Out, ErrHandler);
|
||||||
|
if (Doc.Wasm)
|
||||||
|
return yaml2wasm(*Doc.Wasm, Out, ErrHandler);
|
||||||
|
|
||||||
|
ErrHandler("unknown document type");
|
||||||
|
return false;
|
||||||
|
|
||||||
} while (YIn.nextDocument());
|
} while (YIn.nextDocument());
|
||||||
|
|
||||||
return createStringError(errc::invalid_argument,
|
ErrHandler("cannot find the " + Twine(DocNum) +
|
||||||
"Cannot find the %u%s document", DocNum,
|
getOrdinalSuffix(DocNum).data() + " document");
|
||||||
getOrdinalSuffix(DocNum).data());
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expected<std::unique_ptr<object::ObjectFile>>
|
std::unique_ptr<object::ObjectFile>
|
||||||
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml) {
|
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml,
|
||||||
|
ErrorHandler ErrHandler) {
|
||||||
Storage.clear();
|
Storage.clear();
|
||||||
raw_svector_ostream OS(Storage);
|
raw_svector_ostream OS(Storage);
|
||||||
|
|
||||||
yaml::Input YIn(Yaml);
|
yaml::Input YIn(Yaml);
|
||||||
if (Error E = convertYAML(YIn, OS))
|
if (!convertYAML(YIn, OS, ErrHandler))
|
||||||
return std::move(E);
|
return {};
|
||||||
|
|
||||||
return object::ObjectFile::createObjectFile(
|
Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
|
||||||
MemoryBufferRef(OS.str(), "YamlObject"));
|
object::ObjectFile::createObjectFile(
|
||||||
|
MemoryBufferRef(OS.str(), "YamlObject"));
|
||||||
|
if (ObjOrErr)
|
||||||
|
return std::move(*ObjOrErr);
|
||||||
|
|
||||||
|
ErrHandler(toString(ObjOrErr.takeError()));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace yaml
|
} // namespace yaml
|
||||||
|
@ -14,7 +14,7 @@ Sections:
|
|||||||
- Index: 0
|
- Index: 0
|
||||||
Locals: []
|
Locals: []
|
||||||
Body: 0B
|
Body: 0B
|
||||||
# CHECK: Out of order section type: 3
|
# CHECK: yaml2obj: error: out of order section type: 3
|
||||||
- Type: FUNCTION
|
- Type: FUNCTION
|
||||||
FunctionTypes: [ 0 ]
|
FunctionTypes: [ 0 ]
|
||||||
...
|
...
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# RUN: not yaml2obj %s 2>&1 | FileCheck %s
|
# RUN: not yaml2obj %s 2>&1 | FileCheck %s
|
||||||
|
|
||||||
## CHECK: Section alignment is too large
|
## CHECK: error: section alignment is too large
|
||||||
|
|
||||||
--- !COFF
|
--- !COFF
|
||||||
header:
|
header:
|
||||||
|
@ -31,8 +31,7 @@ DynamicSymbols:
|
|||||||
|
|
||||||
# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE2
|
# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE2
|
||||||
|
|
||||||
# CASE2: error: cannot specify both `Size` and `DynamicSymbols` for symbol table section '.dynsym'
|
# CASE2: yaml2obj: error: cannot specify both `Size` and `DynamicSymbols` for symbol table section '.dynsym'
|
||||||
# CASE2: error: yaml2obj failed
|
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
@ -55,8 +54,7 @@ DynamicSymbols:
|
|||||||
|
|
||||||
# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE3
|
# RUN: not yaml2obj --docnum=3 %s 2>&1 | FileCheck %s --implicit-check-not=error --check-prefix=CASE3
|
||||||
|
|
||||||
# CASE3: error: cannot specify both `Content` and `DynamicSymbols` for symbol table section '.dynsym'
|
# CASE3: yaml2obj: error: cannot specify both `Content` and `DynamicSymbols` for symbol table section '.dynsym'
|
||||||
# CASE3: error: yaml2obj failed
|
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
|
@ -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: error: 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: error: Failed to parse YAML input!
|
# INVALID: yaml2obj: error: failed to parse YAML input
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
## greater than the number of YAML inputs in the file.
|
## greater than the number of YAML inputs in the file.
|
||||||
|
|
||||||
# RUN: not yaml2obj %s --docnum=3 2>&1 | FileCheck %s
|
# RUN: not yaml2obj %s --docnum=3 2>&1 | FileCheck %s
|
||||||
# CHECK: error: Cannot find the 3rd document
|
# CHECK: yaml2obj: error: cannot find the 3rd document
|
||||||
|
|
||||||
# RUN: not yaml2obj %s --docnum=76768677 2>&1 | FileCheck %s --check-prefix=TWO
|
# RUN: not yaml2obj %s --docnum=76768677 2>&1 | FileCheck %s --check-prefix=TWO
|
||||||
# TWO: error: Cannot find the 76768677th document
|
# TWO: yaml2obj: error: cannot find the 76768677th document
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# RUN: not yaml2obj -o %p/path/does/not/exist 2>&1 | FileCheck %s
|
# RUN: not yaml2obj -o %p/path/does/not/exist 2>&1 | FileCheck %s
|
||||||
|
|
||||||
# Don't check the OS-dependent message "No such file or directory".
|
# Don't check the OS-dependent message "No such file or directory".
|
||||||
# CHECK: yaml2obj: Error opening '{{.*}}/path/does/not/exist': {{.*}}
|
# CHECK: yaml2obj: error: failed to open '{{.*}}/path/does/not/exist': {{.*}}
|
||||||
|
@ -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: error: Failed to parse YAML input!
|
# CHECK: 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: error: Cannot find the 5th document
|
# DOC5: error: cannot find the 5th document
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader: !FileHeader
|
FileHeader: !FileHeader
|
||||||
|
@ -30,7 +30,6 @@ Sections:
|
|||||||
|
|
||||||
# ERR: error: unknown section referenced: '.unknown1' by YAML section '.foo'
|
# ERR: error: unknown section referenced: '.unknown1' by YAML section '.foo'
|
||||||
# ERR: error: unknown section referenced: '.unknown2' by YAML section '.bar'
|
# ERR: error: unknown section referenced: '.unknown2' by YAML section '.bar'
|
||||||
# ERR: error: yaml2obj failed
|
|
||||||
|
|
||||||
--- !ELF
|
--- !ELF
|
||||||
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: error: Failed to parse YAML input!
|
# ERR2-NEXT: error: failed to parse YAML input
|
||||||
|
@ -376,12 +376,10 @@ int writeElfStub(const llvm::Triple &T, const std::set<IFSSymbol> &Symbols,
|
|||||||
});
|
});
|
||||||
|
|
||||||
yaml::Input YIn(YamlStr);
|
yaml::Input YIn(YamlStr);
|
||||||
if (Error E = convertYAML(YIn, Out)) {
|
auto ErrHandler = [](const Twine &Msg) {
|
||||||
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), "llvm-ifs"));
|
WithColor::error(errs(), "llvm-ifs") << Msg << "\n";
|
||||||
return 1;
|
};
|
||||||
}
|
return convertYAML(YIn, Out, ErrHandler) ? 0 : 1;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) {
|
int writeIfso(const IFSStub &Stub, bool IsWriteIfs, raw_ostream &Out) {
|
||||||
|
@ -38,11 +38,6 @@ DocNum("docnum", cl::init(1),
|
|||||||
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
|
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
|
||||||
cl::value_desc("filename"));
|
cl::value_desc("filename"));
|
||||||
|
|
||||||
LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) {
|
|
||||||
errs() << Message << "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
@ -50,11 +45,17 @@ int main(int argc, char **argv) {
|
|||||||
if (OutputFilename.empty())
|
if (OutputFilename.empty())
|
||||||
OutputFilename = "-";
|
OutputFilename = "-";
|
||||||
|
|
||||||
|
auto ErrHandler = [](const Twine &Msg) {
|
||||||
|
WithColor::error(errs(), "yaml2obj") << Msg << "\n";
|
||||||
|
};
|
||||||
|
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
std::unique_ptr<ToolOutputFile> Out(
|
std::unique_ptr<ToolOutputFile> Out(
|
||||||
new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
|
new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
|
||||||
if (EC)
|
if (EC) {
|
||||||
error("yaml2obj: Error opening '" + OutputFilename + "': " + EC.message());
|
ErrHandler("failed to open '" + OutputFilename + "': " + EC.message());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
|
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
|
||||||
MemoryBuffer::getFileOrSTDIN(Input);
|
MemoryBuffer::getFileOrSTDIN(Input);
|
||||||
@ -62,10 +63,8 @@ int main(int argc, char **argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
yaml::Input YIn(Buf.get()->getBuffer());
|
yaml::Input YIn(Buf.get()->getBuffer());
|
||||||
if (Error E = convertYAML(YIn, Out->os(), DocNum)) {
|
if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum))
|
||||||
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), argv[0]));
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
Out->keep();
|
Out->keep();
|
||||||
Out->os().flush();
|
Out->os().flush();
|
||||||
|
@ -20,8 +20,9 @@ toBinary(SmallVectorImpl<char> &Storage, StringRef Yaml) {
|
|||||||
Storage.clear();
|
Storage.clear();
|
||||||
raw_svector_ostream OS(Storage);
|
raw_svector_ostream OS(Storage);
|
||||||
yaml::Input YIn(Yaml);
|
yaml::Input YIn(Yaml);
|
||||||
if (Error E = yaml::convertYAML(YIn, OS))
|
if (!yaml::convertYAML(YIn, OS, [](const Twine &Msg) {}))
|
||||||
return std::move(E);
|
return createStringError(std::errc::invalid_argument,
|
||||||
|
"unable to convert YAML");
|
||||||
|
|
||||||
return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary"));
|
return object::MinidumpFile::create(MemoryBufferRef(OS.str(), "Binary"));
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
|
#include "llvm/Support/YAMLTraits.h"
|
||||||
#include "llvm/Testing/Support/Error.h"
|
#include "llvm/Testing/Support/Error.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
@ -18,19 +19,63 @@ using namespace object;
|
|||||||
using namespace yaml;
|
using namespace yaml;
|
||||||
|
|
||||||
TEST(yaml2ObjectFile, ELF) {
|
TEST(yaml2ObjectFile, ELF) {
|
||||||
|
bool ErrorReported = false;
|
||||||
|
auto ErrHandler = [&](const Twine &Msg) { ErrorReported = true; };
|
||||||
|
|
||||||
SmallString<0> Storage;
|
SmallString<0> Storage;
|
||||||
Expected<std::unique_ptr<ObjectFile>> ErrOrObj = yaml2ObjectFile(Storage, R"(
|
std::unique_ptr<ObjectFile> Obj = yaml2ObjectFile(Storage, R"(
|
||||||
--- !ELF
|
--- !ELF
|
||||||
FileHeader:
|
FileHeader:
|
||||||
Class: ELFCLASS64
|
Class: ELFCLASS64
|
||||||
Data: ELFDATA2LSB
|
Data: ELFDATA2LSB
|
||||||
Type: ET_REL
|
Type: ET_REL
|
||||||
Machine: EM_X86_64)");
|
Machine: EM_X86_64)", ErrHandler);
|
||||||
|
|
||||||
ASSERT_THAT_EXPECTED(ErrOrObj, Succeeded());
|
ASSERT_FALSE(ErrorReported);
|
||||||
|
ASSERT_TRUE(Obj);
|
||||||
std::unique_ptr<ObjectFile> ObjFile = std::move(ErrOrObj.get());
|
ASSERT_TRUE(Obj->isELF());
|
||||||
|
ASSERT_TRUE(Obj->isRelocatableObject());
|
||||||
ASSERT_TRUE(ObjFile->isELF());
|
}
|
||||||
ASSERT_TRUE(ObjFile->isRelocatableObject());
|
|
||||||
|
TEST(yaml2ObjectFile, Errors) {
|
||||||
|
std::vector<std::string> Errors;
|
||||||
|
auto ErrHandler = [&](const Twine &Msg) {
|
||||||
|
Errors.push_back("ObjectYAML: " + Msg.str());
|
||||||
|
};
|
||||||
|
|
||||||
|
SmallString<0> Storage;
|
||||||
|
StringRef Yaml = R"(
|
||||||
|
--- !ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_REL
|
||||||
|
Machine: EM_X86_64
|
||||||
|
Symbols:
|
||||||
|
- Name: foo
|
||||||
|
- Name: foo
|
||||||
|
- Name: foo
|
||||||
|
)";
|
||||||
|
|
||||||
|
// 1. Test yaml2ObjectFile().
|
||||||
|
|
||||||
|
std::unique_ptr<ObjectFile> Obj = yaml2ObjectFile(Storage, Yaml, ErrHandler);
|
||||||
|
|
||||||
|
ASSERT_FALSE(Obj);
|
||||||
|
ASSERT_TRUE(Errors.size() == 2);
|
||||||
|
ASSERT_TRUE(Errors[0] == "ObjectYAML: repeated symbol name: 'foo'");
|
||||||
|
ASSERT_TRUE(Errors[1] == Errors[0]);
|
||||||
|
|
||||||
|
// 2. Test convertYAML().
|
||||||
|
|
||||||
|
Errors.clear();
|
||||||
|
Storage.clear();
|
||||||
|
raw_svector_ostream OS(Storage);
|
||||||
|
|
||||||
|
yaml::Input YIn(Yaml);
|
||||||
|
bool Res = convertYAML(YIn, OS, ErrHandler);
|
||||||
|
ASSERT_FALSE(Res);
|
||||||
|
ASSERT_TRUE(Errors.size() == 2);
|
||||||
|
ASSERT_TRUE(Errors[0] == "ObjectYAML: repeated symbol name: 'foo'");
|
||||||
|
ASSERT_TRUE(Errors[1] == Errors[0]);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user