1 //===------ utils/obj2yaml.cpp - obj2yaml conversion tool -----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "llvm/BinaryFormat/Magic.h"
11 #include "llvm/Object/Archive.h"
12 #include "llvm/Object/COFF.h"
13 #include "llvm/Object/Minidump.h"
14 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/InitLLVM.h"
17 #include "llvm/Support/ToolOutputFile.h"
18 #include "llvm/Support/WithColor.h"
21 using namespace llvm::object
;
23 static cl::OptionCategory
Cat("obj2yaml Options");
25 static cl::opt
<std::string
>
26 InputFilename(cl::Positional
, cl::desc("<input file>"), cl::init("-"));
27 static cl::opt
<std::string
> OutputFilename("o", cl::desc("Output filename"),
28 cl::value_desc("filename"),
29 cl::init("-"), cl::Prefix
,
31 static cl::bits
<RawSegments
> RawSegment(
33 cl::desc("Mach-O: dump the raw contents of the listed segments instead of "
35 cl::values(clEnumVal(data
, "__DATA"), clEnumVal(linkedit
, "__LINKEDIT")),
38 static Error
dumpObject(const ObjectFile
&Obj
, raw_ostream
&OS
) {
40 return errorCodeToError(coff2yaml(OS
, cast
<COFFObjectFile
>(Obj
)));
43 return xcoff2yaml(OS
, cast
<XCOFFObjectFile
>(Obj
));
46 return elf2yaml(OS
, Obj
);
49 return errorCodeToError(wasm2yaml(OS
, cast
<WasmObjectFile
>(Obj
)));
51 llvm_unreachable("unexpected object file format");
54 static Error
dumpInput(StringRef File
, raw_ostream
&OS
) {
55 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> FileOrErr
=
56 MemoryBuffer::getFileOrSTDIN(File
, /*IsText=*/false,
57 /*RequiresNullTerminator=*/false);
58 if (std::error_code EC
= FileOrErr
.getError())
59 return errorCodeToError(EC
);
60 std::unique_ptr
<MemoryBuffer
> &Buffer
= FileOrErr
.get();
61 MemoryBufferRef MemBuf
= Buffer
->getMemBufferRef();
62 switch (identify_magic(MemBuf
.getBuffer())) {
63 case file_magic::archive
:
64 return archive2yaml(OS
, MemBuf
);
65 case file_magic::dxcontainer_object
:
66 return dxcontainer2yaml(OS
, MemBuf
);
67 case file_magic::offload_binary
:
68 return offload2yaml(OS
, MemBuf
);
73 Expected
<std::unique_ptr
<Binary
>> BinOrErr
=
74 createBinary(MemBuf
, /*Context=*/nullptr);
76 return BinOrErr
.takeError();
78 Binary
&Binary
= *BinOrErr
->get();
79 // Universal MachO is not a subclass of ObjectFile, so it needs to be handled
80 // here with the other binary types.
81 if (Binary
.isMachO() || Binary
.isMachOUniversalBinary())
82 return macho2yaml(OS
, Binary
, RawSegment
.getBits());
83 if (ObjectFile
*Obj
= dyn_cast
<ObjectFile
>(&Binary
))
84 return dumpObject(*Obj
, OS
);
85 if (MinidumpFile
*Minidump
= dyn_cast
<MinidumpFile
>(&Binary
))
86 return minidump2yaml(OS
, *Minidump
);
88 return Error::success();
91 static void reportError(StringRef Input
, Error Err
) {
95 raw_string_ostream
OS(ErrMsg
);
96 logAllUnhandledErrors(std::move(Err
), OS
);
98 errs() << "Error reading file: " << Input
<< ": " << ErrMsg
;
102 int main(int argc
, char *argv
[]) {
103 InitLLVM
X(argc
, argv
);
104 cl::HideUnrelatedOptions(Cat
);
105 cl::ParseCommandLineOptions(
106 argc
, argv
, "Dump a YAML description from an object file", nullptr,
107 nullptr, /*LongOptionsUseDoubleDash=*/true);
110 std::unique_ptr
<ToolOutputFile
> Out(
111 new ToolOutputFile(OutputFilename
, EC
, sys::fs::OF_Text
));
113 WithColor::error(errs(), "obj2yaml")
114 << "failed to open '" + OutputFilename
+ "': " + EC
.message() << '\n';
117 if (Error Err
= dumpInput(InputFilename
, Out
->os())) {
118 reportError(InputFilename
, std::move(Err
));