18bd8dd16SAdrian Prantl //===------ utils/obj2yaml.cpp - obj2yaml conversion tool -----------------===// 287a02909SRafael Espindola // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 687a02909SRafael Espindola // 787a02909SRafael Espindola //===----------------------------------------------------------------------===// 887a02909SRafael Espindola 987a02909SRafael Espindola #include "obj2yaml.h" 1047369e19SGeorgii Rymar #include "llvm/BinaryFormat/Magic.h" 1187a02909SRafael Espindola #include "llvm/Object/Archive.h" 1287a02909SRafael Espindola #include "llvm/Object/COFF.h" 133cee663eSPavel Labath #include "llvm/Object/Minidump.h" 1487a02909SRafael Espindola #include "llvm/Support/CommandLine.h" 15357dc1edSGeorgii Rymar #include "llvm/Support/Errc.h" 16197194b6SRui Ueyama #include "llvm/Support/InitLLVM.h" 17cfec2080SFangrui Song #include "llvm/Support/ToolOutputFile.h" 18cfec2080SFangrui Song #include "llvm/Support/WithColor.h" 1987a02909SRafael Espindola 2018192896SChandler Carruth using namespace llvm; 21ba592977SSimon Atanasyan using namespace llvm::object; 2218192896SChandler Carruth 23*df42d63dSFangrui Song static cl::OptionCategory Cat("obj2yaml Options"); 24*df42d63dSFangrui Song 258bd8dd16SAdrian Prantl static cl::opt<std::string> 268bd8dd16SAdrian Prantl InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 27cfec2080SFangrui Song static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), 28cfec2080SFangrui Song cl::value_desc("filename"), 29*df42d63dSFangrui Song cl::init("-"), cl::Prefix, 30*df42d63dSFangrui Song cl::cat(Cat)); 318bd8dd16SAdrian Prantl static cl::bits<RawSegments> RawSegment( 328bd8dd16SAdrian Prantl "raw-segment", 338bd8dd16SAdrian Prantl cl::desc("Mach-O: dump the raw contents of the listed segments instead of " 348bd8dd16SAdrian Prantl "parsing them:"), 35*df42d63dSFangrui Song cl::values(clEnumVal(data, "__DATA"), clEnumVal(linkedit, "__LINKEDIT")), 36*df42d63dSFangrui Song cl::cat(Cat)); 378bd8dd16SAdrian Prantl 38cfec2080SFangrui Song static Error dumpObject(const ObjectFile &Obj, raw_ostream &OS) { 39ba592977SSimon Atanasyan if (Obj.isCOFF()) 40cfec2080SFangrui Song return errorCodeToError(coff2yaml(OS, cast<COFFObjectFile>(Obj))); 41ab2eb2bfSHubert Tong 42ab2eb2bfSHubert Tong if (Obj.isXCOFF()) 43cfec2080SFangrui Song return xcoff2yaml(OS, cast<XCOFFObjectFile>(Obj)); 44ab2eb2bfSHubert Tong 45ae6bb33aSSimon Atanasyan if (Obj.isELF()) 46cfec2080SFangrui Song return elf2yaml(OS, Obj); 47309246e4SGeorge Rimar 48224816baSGeorge Rimar if (Obj.isWasm()) 49cfec2080SFangrui Song return errorCodeToError(wasm2yaml(OS, cast<WasmObjectFile>(Obj))); 50224816baSGeorge Rimar 51357dc1edSGeorgii Rymar llvm_unreachable("unexpected object file format"); 5218192896SChandler Carruth } 5387a02909SRafael Espindola 54cfec2080SFangrui Song static Error dumpInput(StringRef File, raw_ostream &OS) { 5547369e19SGeorgii Rymar ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = 56c83cd8feSAbhina Sreeskantharajan MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false, 5747369e19SGeorgii Rymar /*RequiresNullTerminator=*/false); 5847369e19SGeorgii Rymar if (std::error_code EC = FileOrErr.getError()) 5947369e19SGeorgii Rymar return errorCodeToError(EC); 6047369e19SGeorgii Rymar std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); 6147369e19SGeorgii Rymar MemoryBufferRef MemBuf = Buffer->getMemBufferRef(); 62352c395fSChris Bieneman switch (identify_magic(MemBuf.getBuffer())) { 63352c395fSChris Bieneman case file_magic::archive: 64cfec2080SFangrui Song return archive2yaml(OS, MemBuf); 65352c395fSChris Bieneman case file_magic::dxcontainer_object: 66cfec2080SFangrui Song return dxcontainer2yaml(OS, MemBuf); 67228c8f9cSJoseph Huber case file_magic::offload_binary: 68cfec2080SFangrui Song return offload2yaml(OS, MemBuf); 69352c395fSChris Bieneman default: 70352c395fSChris Bieneman break; 71352c395fSChris Bieneman } 72ba592977SSimon Atanasyan 7347369e19SGeorgii Rymar Expected<std::unique_ptr<Binary>> BinOrErr = 7447369e19SGeorgii Rymar createBinary(MemBuf, /*Context=*/nullptr); 7547369e19SGeorgii Rymar if (!BinOrErr) 7647369e19SGeorgii Rymar return BinOrErr.takeError(); 7747369e19SGeorgii Rymar 7847369e19SGeorgii Rymar Binary &Binary = *BinOrErr->get(); 7993e71193SChris Bieneman // Universal MachO is not a subclass of ObjectFile, so it needs to be handled 8093e71193SChris Bieneman // here with the other binary types. 8193e71193SChris Bieneman if (Binary.isMachO() || Binary.isMachOUniversalBinary()) 82cfec2080SFangrui Song return macho2yaml(OS, Binary, RawSegment.getBits()); 833f6481d0SRafael Espindola if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary)) 84cfec2080SFangrui Song return dumpObject(*Obj, OS); 853cee663eSPavel Labath if (MinidumpFile *Minidump = dyn_cast<MinidumpFile>(&Binary)) 86cfec2080SFangrui Song return minidump2yaml(OS, *Minidump); 87ba592977SSimon Atanasyan 8820c7d432SSam Clegg return Error::success(); 8920c7d432SSam Clegg } 9020c7d432SSam Clegg 9120c7d432SSam Clegg static void reportError(StringRef Input, Error Err) { 9220c7d432SSam Clegg if (Input == "-") 9320c7d432SSam Clegg Input = "<stdin>"; 9420c7d432SSam Clegg std::string ErrMsg; 9520c7d432SSam Clegg raw_string_ostream OS(ErrMsg); 9645eb84f3SJonas Devlieghere logAllUnhandledErrors(std::move(Err), OS); 9720c7d432SSam Clegg OS.flush(); 9820c7d432SSam Clegg errs() << "Error reading file: " << Input << ": " << ErrMsg; 9920c7d432SSam Clegg errs().flush(); 100ba592977SSimon Atanasyan } 10187a02909SRafael Espindola 10287a02909SRafael Espindola int main(int argc, char *argv[]) { 103197194b6SRui Ueyama InitLLVM X(argc, argv); 104*df42d63dSFangrui Song cl::HideUnrelatedOptions(Cat); 105*df42d63dSFangrui Song cl::ParseCommandLineOptions( 106*df42d63dSFangrui Song argc, argv, "Dump a YAML description from an object file", nullptr, 107*df42d63dSFangrui Song nullptr, /*LongOptionsUseDoubleDash=*/true); 10887a02909SRafael Espindola 109cfec2080SFangrui Song std::error_code EC; 110cfec2080SFangrui Song std::unique_ptr<ToolOutputFile> Out( 111cfec2080SFangrui Song new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); 112cfec2080SFangrui Song if (EC) { 113cfec2080SFangrui Song WithColor::error(errs(), "obj2yaml") 114cfec2080SFangrui Song << "failed to open '" + OutputFilename + "': " + EC.message() << '\n'; 115cfec2080SFangrui Song return 1; 116cfec2080SFangrui Song } 117cfec2080SFangrui Song if (Error Err = dumpInput(InputFilename, Out->os())) { 11820c7d432SSam Clegg reportError(InputFilename, std::move(Err)); 119ba592977SSimon Atanasyan return 1; 12087a02909SRafael Espindola } 121cfec2080SFangrui Song Out->keep(); 12287a02909SRafael Espindola 12387a02909SRafael Espindola return 0; 12487a02909SRafael Espindola } 125