Index: llvm/include/llvm/ObjectYAML/yaml2obj.h =================================================================== --- llvm/include/llvm/ObjectYAML/yaml2obj.h +++ llvm/include/llvm/ObjectYAML/yaml2obj.h @@ -11,8 +11,17 @@ #ifndef LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H #define LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H +#include "llvm/ADT/StringRef.h" +#include + namespace llvm { class raw_ostream; +template class SmallVectorImpl; +template class Expected; + +namespace object { +class ObjectFile; +} namespace COFFYAML { struct Object; @@ -33,13 +42,20 @@ namespace yaml { class Input; struct YamlObjectFile; -} -} -int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out); -int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out); -int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out); -int yaml2minidump(llvm::MinidumpYAML::Object &Doc, llvm::raw_ostream &Out); -int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out); +int yaml2coff(COFFYAML::Object &Doc, raw_ostream &Out); +int yaml2elf(ELFYAML::Object &Doc, raw_ostream &Out); +int yaml2macho(YamlObjectFile &Doc, raw_ostream &Out); +int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out); +int yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out); + +int convertYAML(Input &YIn, raw_ostream &Out, unsigned DocNum = 1); + +/// Convenience function for tests. +Expected> +yaml2ObjectFile(SmallVectorImpl &Storage, StringRef Yaml); + +} // namespace yaml +} // namespace llvm #endif Index: llvm/lib/ObjectYAML/CMakeLists.txt =================================================================== --- llvm/lib/ObjectYAML/CMakeLists.txt +++ llvm/lib/ObjectYAML/CMakeLists.txt @@ -14,4 +14,10 @@ WasmYAML.cpp XCOFFYAML.cpp YAML.cpp + yaml2coff.cpp + yaml2elf.cpp + yaml2macho.cpp + yaml2obj.cpp + yaml2minidump.cpp + yaml2wasm.cpp ) Index: llvm/lib/ObjectYAML/yaml2coff.cpp =================================================================== --- llvm/lib/ObjectYAML/yaml2coff.cpp +++ llvm/lib/ObjectYAML/yaml2coff.cpp @@ -11,7 +11,6 @@ /// //===----------------------------------------------------------------------===// -#include "yaml2obj.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" @@ -20,6 +19,7 @@ #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/ObjectYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" @@ -592,7 +592,7 @@ return true; } -int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) { +int yaml::yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) { COFFParser CP(Doc); if (!CP.parse()) { errs() << "yaml2obj: Failed to parse YAML file!\n"; Index: llvm/lib/ObjectYAML/yaml2elf.cpp =================================================================== --- llvm/lib/ObjectYAML/yaml2elf.cpp +++ llvm/lib/ObjectYAML/yaml2elf.cpp @@ -11,12 +11,12 @@ /// //===----------------------------------------------------------------------===// -#include "yaml2obj.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/ObjectYAML/ELFYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/MemoryBuffer.h" @@ -1077,7 +1077,7 @@ return 0; } -int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) { +int yaml::yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) { bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); if (Is64Bit) { Index: llvm/lib/ObjectYAML/yaml2macho.cpp =================================================================== --- llvm/lib/ObjectYAML/yaml2macho.cpp +++ llvm/lib/ObjectYAML/yaml2macho.cpp @@ -11,10 +11,10 @@ /// //===----------------------------------------------------------------------===// -#include "yaml2obj.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/ObjectYAML/DWARFEmitter.h" #include "llvm/ObjectYAML/ObjectYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/Error.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/YAMLTraits.h" @@ -592,7 +592,7 @@ } // end anonymous namespace -int yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) { +int yaml::yaml2macho(yaml::YamlObjectFile &Doc, raw_ostream &Out) { UniversalWriter Writer(Doc); if (auto Err = Writer.writeMachO(Out)) { errs() << toString(std::move(Err)); Index: llvm/lib/ObjectYAML/yaml2minidump.cpp =================================================================== --- llvm/lib/ObjectYAML/yaml2minidump.cpp +++ llvm/lib/ObjectYAML/yaml2minidump.cpp @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#include "yaml2obj.h" #include "llvm/ObjectYAML/MinidumpYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -int yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out) { +int yaml::yaml2minidump(MinidumpYAML::Object &Doc, raw_ostream &Out) { writeAsBinary(Doc, Out); return 0; } Index: llvm/lib/ObjectYAML/yaml2obj.cpp =================================================================== --- /dev/null +++ llvm/lib/ObjectYAML/yaml2obj.cpp @@ -0,0 +1,64 @@ +//===-- 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 { + +LLVM_ATTRIBUTE_NORETURN static void error(Twine Message) { + errs() << Message << "\n"; + exit(1); +} + +int convertYAML(yaml::Input &YIn, raw_ostream &Out, unsigned DocNum) { + 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"); +} + +Expected> +yaml2ObjectFile(SmallVectorImpl &Storage, StringRef Yaml) { + Storage.clear(); + raw_svector_ostream OS(Storage); + + yaml::Input YIn(Yaml); + if (convertYAML(YIn, OS)) + return createStringError(errc::invalid_argument, "Invalid YAML"); + + return object::ObjectFile::createObjectFile( + MemoryBufferRef(OS.str(), "YamlObject")); +} + +} // namespace yaml +} // namespace llvm Index: llvm/lib/ObjectYAML/yaml2wasm.cpp =================================================================== --- llvm/lib/ObjectYAML/yaml2wasm.cpp +++ llvm/lib/ObjectYAML/yaml2wasm.cpp @@ -14,6 +14,7 @@ #include "llvm/Object/Wasm.h" #include "llvm/ObjectYAML/ObjectYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/Endian.h" #include "llvm/Support/LEB128.h" @@ -651,7 +652,7 @@ return 0; } -int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) { +int llvm::yaml::yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) { WasmWriter Writer(Doc); return Writer.writeWasm(Out); Index: llvm/tools/yaml2obj/CMakeLists.txt =================================================================== --- llvm/tools/yaml2obj/CMakeLists.txt +++ llvm/tools/yaml2obj/CMakeLists.txt @@ -8,9 +8,4 @@ add_llvm_tool(yaml2obj yaml2obj.cpp - yaml2coff.cpp - yaml2elf.cpp - yaml2macho.cpp - yaml2minidump.cpp - yaml2wasm.cpp ) Index: llvm/tools/yaml2obj/yaml2obj.cpp =================================================================== --- llvm/tools/yaml2obj/yaml2obj.cpp +++ llvm/tools/yaml2obj/yaml2obj.cpp @@ -13,9 +13,9 @@ // //===----------------------------------------------------------------------===// -#include "yaml2obj.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ObjectYAML/ObjectYAML.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" @@ -42,32 +42,6 @@ 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) { InitLLVM X(argc, argv); cl::ParseCommandLineOptions(argc, argv); @@ -87,7 +61,7 @@ return 1; yaml::Input YIn(Buf.get()->getBuffer()); - int Res = convertYAML(YIn, Out->os()); + int Res = convertYAML(YIn, Out->os(), DocNum); if (Res == 0) Out->keep(); Index: llvm/unittests/ObjectYAML/CMakeLists.txt =================================================================== --- llvm/unittests/ObjectYAML/CMakeLists.txt +++ llvm/unittests/ObjectYAML/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_unittest(ObjectYAMLTests MinidumpYAMLTest.cpp YAMLTest.cpp + yaml2ObjectFileTest.cpp ) target_link_libraries(ObjectYAMLTests PRIVATE LLVMTestingSupport) Index: llvm/unittests/ObjectYAML/yaml2ObjectFileTest.cpp =================================================================== --- /dev/null +++ llvm/unittests/ObjectYAML/yaml2ObjectFileTest.cpp @@ -0,0 +1,36 @@ +//===- yaml2ObjectFileTest.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/ADT/SmallString.h" +#include "llvm/ObjectYAML/yaml2obj.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Error.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace object; +using namespace yaml; + +TEST(yaml2ObjectFile, ELF) { + SmallString<0> Storage; + Expected> ErrOrObj + = yaml2ObjectFile(Storage, R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64)"); + + ASSERT_TRUE(!!ErrOrObj); + + std::unique_ptr ObjFile = std::move(ErrOrObj.get()); + + ASSERT_TRUE(ObjFile->isELF()); + ASSERT_TRUE(ObjFile->isRelocatableObject()); +}