Skip to content

Commit

Permalink
[yaml2obj/ObjectYAML] - Cleanup the error reporting API, add custom e…
Browse files Browse the repository at this point in the history
…rrors 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
  • Loading branch information
George Rimar committed Sep 13, 2019
1 parent 3e78f24 commit 04c5016
Show file tree
Hide file tree
Showing 21 changed files with 350 additions and 345 deletions.
21 changes: 13 additions & 8 deletions include/llvm/ObjectYAML/yaml2obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,22 @@ namespace yaml {
class Input;
struct YamlObjectFile;

bool yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out);
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);
using ErrorHandler = llvm::function_ref<void(const Twine &Msg)>;

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.
Expected<std::unique_ptr<object::ObjectFile>>
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml);
std::unique_ptr<object::ObjectFile>
yaml2ObjectFile(SmallVectorImpl<char> &Storage, StringRef Yaml,
ErrorHandler ErrHandler);

} // namespace yaml
} // namespace llvm
Expand Down
25 changes: 14 additions & 11 deletions lib/ObjectYAML/COFFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ namespace {
/// This parses a yaml stream that represents a COFF object file.
/// See docs/yaml2obj for the yaml scheema.
struct COFFParser {
COFFParser(COFFYAML::Object &Obj)
: Obj(Obj), SectionTableStart(0), SectionTableSize(0) {
COFFParser(COFFYAML::Object &Obj, yaml::ErrorHandler EH)
: Obj(Obj), SectionTableStart(0), SectionTableSize(0), ErrHandler(EH) {
// A COFF string table always starts with a 4 byte size field. Offsets into
// it include this size, so allocate it now.
StringTable.append(4, char(0));
Expand Down Expand Up @@ -81,7 +81,7 @@ struct COFFParser {
unsigned Index = getStringIndex(Name);
std::string str = utostr(Index);
if (str.size() > 7) {
errs() << "String table got too large\n";
ErrHandler("string table got too large");
return false;
}
Sec.Header.Name[0] = '/';
Expand All @@ -90,11 +90,11 @@ struct COFFParser {

if (Sec.Alignment) {
if (Sec.Alignment > 8192) {
errs() << "Section alignment is too large\n";
ErrHandler("section alignment is too large");
return false;
}
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;
}
Sec.Header.Characteristics |= (Log2_32(Sec.Alignment) + 1) << 20;
Expand Down Expand Up @@ -155,6 +155,8 @@ struct COFFParser {
std::string StringTable;
uint32_t SectionTableStart;
uint32_t SectionTableSize;

yaml::ErrorHandler ErrHandler;
};

enum { DOSStubSize = 128 };
Expand Down Expand Up @@ -592,24 +594,25 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
namespace llvm {
namespace yaml {

bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
COFFParser CP(Doc);
bool yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out,
ErrorHandler ErrHandler) {
COFFParser CP(Doc, ErrHandler);
if (!CP.parse()) {
errs() << "yaml2obj: Failed to parse YAML file!\n";
ErrHandler("failed to parse YAML file");
return false;
}

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;
}

if (!layoutCOFF(CP)) {
errs() << "yaml2obj: Failed to layout COFF file!\n";
ErrHandler("failed to layout COFF file");
return false;
}
if (!writeCOFF(CP, Out)) {
errs() << "yaml2obj: Failed to write COFF file!\n";
ErrHandler("failed to write COFF file");
return false;
}
return true;
Expand Down
30 changes: 18 additions & 12 deletions lib/ObjectYAML/ELFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,13 @@ template <class ELFT> class ELFState {
ELFYAML::Object &Doc;

bool HasError = false;
yaml::ErrorHandler ErrHandler;
void reportError(const Twine &Msg);

std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
const StringTableBuilder &Strtab);
unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");
unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);
void reportError(const Twine &Msg);

void buildSectionIndex();
void buildSymbolIndexes();
Expand Down Expand Up @@ -166,9 +167,11 @@ template <class ELFT> class ELFState {
void writeSectionContent(Elf_Shdr &SHeader,
const ELFYAML::DynamicSection &Section,
ContiguousBlobAccumulator &CBA);
ELFState(ELFYAML::Object &D);
ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);

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

Expand All @@ -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 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;
for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections)
if (!D->Name.empty())
Expand Down Expand Up @@ -592,7 +597,7 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
}

template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
WithColor::error() << Msg << "\n";
ErrHandler(Msg);
HasError = true;
}

Expand Down Expand Up @@ -983,8 +988,9 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
}

template <class ELFT>
bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
ELFState<ELFT> State(Doc);
bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
yaml::ErrorHandler EH) {
ELFState<ELFT> State(Doc, EH);

// Finalize .strtab and .dynstr sections. We do that early because want to
// finalize the string table builders before writing the content of the
Expand Down Expand Up @@ -1022,17 +1028,17 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc) {
namespace llvm {
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 Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
if (Is64Bit) {
if (IsLE)
return ELFState<object::ELF64LE>::writeELF(Out, Doc);
return ELFState<object::ELF64BE>::writeELF(Out, Doc);
return ELFState<object::ELF64LE>::writeELF(Out, Doc, EH);
return ELFState<object::ELF64BE>::writeELF(Out, Doc, EH);
}
if (IsLE)
return ELFState<object::ELF32LE>::writeELF(Out, Doc);
return ELFState<object::ELF32BE>::writeELF(Out, Doc);
return ELFState<object::ELF32LE>::writeELF(Out, Doc, EH);
return ELFState<object::ELF32BE>::writeELF(Out, Doc, EH);
}

} // namespace yaml
Expand Down
Loading

0 comments on commit 04c5016

Please sign in to comment.