[obj2yaml] Add -o to specify output filename

-o is very common among tools. yaml2obj supports -o and it surprised me that
obj2yaml doesn't support -o. Just add it which doesn't take much code.

Differential Revision: https://reviews.llvm.org/D129713
This commit is contained in:
Fangrui Song 2022-07-14 00:32:48 -07:00
parent 42b3a5fb46
commit cfec2080b7
9 changed files with 80 additions and 20 deletions

View File

@ -1,4 +1,8 @@
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
# RUN: yaml2obj %s -o %t
# RUN: obj2yaml %t > %t.stdout.yaml
# RUN: obj2yaml %t -o %t.file.yaml 2>&1 | count 0
# RUN: FileCheck --input-file=%t.stdout.yaml %s
# RUN: diff %t.stdout.yaml %t.file.yaml
!Offload
Members:
-

View File

@ -1,4 +1,8 @@
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
# RUN: yaml2obj %s -o %t
# RUN: obj2yaml %t > %t.stdout.yaml
# RUN: obj2yaml %t -o %t.file.yaml 2>&1 | count 0
# RUN: FileCheck --input-file=%t.stdout.yaml %s
# RUN: diff %t.stdout.yaml %t.file.yaml
--- !WASM
FileHeader:
Version: 0x00000001

View File

@ -3,7 +3,10 @@
## Check how we dump an empty archive.
# RUN: yaml2obj %s --docnum=1 -o %t.empty.a
# RUN: obj2yaml %t.empty.a | FileCheck %s --check-prefix=EMPTY
# RUN: obj2yaml %t.empty.a > %t.stdout.yaml
# RUN: obj2yaml %t.empty.a -o %t.file.yaml 2>&1 | count 0
# RUN: FileCheck --input-file=%t.stdout.yaml %s --check-prefix=EMPTY
# RUN: diff %t.stdout.yaml %t.file.yaml
# EMPTY: --- !Arch
# EMPTY-NEXT: Members: []

View File

@ -1,4 +1,7 @@
# RUN: obj2yaml %S/Inputs/test-1.o | yaml2obj -o %t.o
# RUN: obj2yaml %S/Inputs/test-1.o > %t.stdout.yaml
# RUN: obj2yaml %S/Inputs/test-1.o -o %t.file.yaml 2>&1 | count 0
# RUN: yaml2obj %t.stdout.yaml -o %t.o
# RUN: llvm-pdbutil dump --types %t.o | FileCheck %s -check-prefix=ALL
# RUN: diff %t.stdout.yaml %t.file.yaml
# ALL: {{.*}} guid = {00C903AB-0968-4639-84F8-7D3E719A1BE1}

View File

@ -1,4 +1,8 @@
# RUN: yaml2obj %s | obj2yaml | FileCheck %s
# RUN: yaml2obj %s -o %t
# RUN: obj2yaml %t > %t.stdout.yaml
# RUN: obj2yaml %t -o %t.file.yaml 2>&1 | count 0
# RUN: FileCheck --input-file=%t.stdout.yaml %s
# RUN: diff %t.stdout.yaml %t.file.yaml
--- !dxcontainer
Header:

View File

@ -1,4 +1,8 @@
# RUN: yaml2obj %s | obj2yaml - | FileCheck %s
# RUN: yaml2obj %s -o %t
# RUN: obj2yaml %t > %t.stdout.yaml
# RUN: obj2yaml %t -o %t.file.yaml 2>&1 | count 0
# RUN: FileCheck --input-file=%t.stdout.yaml %s
# RUN: diff %t.stdout.yaml %t.file.yaml
--- !minidump
Streams:

View File

@ -2,7 +2,8 @@
# RUN: yaml2obj %s -DMAGIC=0x01DF -o %t-32
# RUN: obj2yaml %t-32 | FileCheck %s --check-prefix=CHECK32
# RUN: yaml2obj %s -DMAGIC=0x01F7 -o %t-64
# RUN: obj2yaml %t-64 | FileCheck %s --check-prefix=CHECK64
# RUN: obj2yaml %t-64 -o %t-64.yaml 2>&1 | count 0
# RUN: FileCheck --input-file %t-64.yaml %s --check-prefix=CHECK64
# CHECK32: --- !XCOFF
# CHECK32-NEXT: FileHeader:

View File

@ -0,0 +1,23 @@
## Test that -o sets the output file name.
# RUN: yaml2obj %s -o %t
# RUN: rm -f %t.yaml && obj2yaml %t -o %t.yaml
# RUN: ls %t.yaml
# RUN: rm -f %t.yaml && cat %t | obj2yaml -o%t.yaml
# RUN: ls %t.yaml
## In case of an error, don't create the output file.
# RUN: rm -f %t.yaml
# RUN: echo | not obj2yaml -o %t.yaml
# RUN: not ls %t.yaml
# RUN: not obj2yaml %t -o %p/path/does/not/exist 2>&1 | FileCheck -DMSG=%errc_ENOENT %s
# CHECK: obj2yaml: error: failed to open '{{.*}}/path/does/not/exist': [[MSG]]
!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_NONE

View File

@ -14,35 +14,40 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
using namespace llvm;
using namespace llvm::object;
static cl::opt<std::string>
InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
cl::value_desc("filename"),
cl::init("-"), cl::Prefix);
static cl::bits<RawSegments> RawSegment(
"raw-segment",
cl::desc("Mach-O: dump the raw contents of the listed segments instead of "
"parsing them:"),
cl::values(clEnumVal(data, "__DATA"), clEnumVal(linkedit, "__LINKEDIT")));
static Error dumpObject(const ObjectFile &Obj) {
static Error dumpObject(const ObjectFile &Obj, raw_ostream &OS) {
if (Obj.isCOFF())
return errorCodeToError(coff2yaml(outs(), cast<COFFObjectFile>(Obj)));
return errorCodeToError(coff2yaml(OS, cast<COFFObjectFile>(Obj)));
if (Obj.isXCOFF())
return xcoff2yaml(outs(), cast<XCOFFObjectFile>(Obj));
return xcoff2yaml(OS, cast<XCOFFObjectFile>(Obj));
if (Obj.isELF())
return elf2yaml(outs(), Obj);
return elf2yaml(OS, Obj);
if (Obj.isWasm())
return errorCodeToError(wasm2yaml(outs(), cast<WasmObjectFile>(Obj)));
return errorCodeToError(wasm2yaml(OS, cast<WasmObjectFile>(Obj)));
llvm_unreachable("unexpected object file format");
}
static Error dumpInput(StringRef File) {
static Error dumpInput(StringRef File, raw_ostream &OS) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
MemoryBuffer::getFileOrSTDIN(File, /*IsText=*/false,
/*RequiresNullTerminator=*/false);
@ -52,11 +57,11 @@ static Error dumpInput(StringRef File) {
MemoryBufferRef MemBuf = Buffer->getMemBufferRef();
switch (identify_magic(MemBuf.getBuffer())) {
case file_magic::archive:
return archive2yaml(outs(), MemBuf);
return archive2yaml(OS, MemBuf);
case file_magic::dxcontainer_object:
return dxcontainer2yaml(outs(), MemBuf);
return dxcontainer2yaml(OS, MemBuf);
case file_magic::offload_binary:
return offload2yaml(outs(), MemBuf);
return offload2yaml(OS, MemBuf);
default:
break;
}
@ -70,11 +75,11 @@ static Error dumpInput(StringRef File) {
// Universal MachO is not a subclass of ObjectFile, so it needs to be handled
// here with the other binary types.
if (Binary.isMachO() || Binary.isMachOUniversalBinary())
return macho2yaml(outs(), Binary, RawSegment.getBits());
return macho2yaml(OS, Binary, RawSegment.getBits());
if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
return dumpObject(*Obj);
return dumpObject(*Obj, OS);
if (MinidumpFile *Minidump = dyn_cast<MinidumpFile>(&Binary))
return minidump2yaml(outs(), *Minidump);
return minidump2yaml(OS, *Minidump);
return Error::success();
}
@ -94,10 +99,19 @@ int main(int argc, char *argv[]) {
InitLLVM X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
if (Error Err = dumpInput(InputFilename)) {
std::error_code EC;
std::unique_ptr<ToolOutputFile> Out(
new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
if (EC) {
WithColor::error(errs(), "obj2yaml")
<< "failed to open '" + OutputFilename + "': " + EC.message() << '\n';
return 1;
}
if (Error Err = dumpInput(InputFilename, Out->os())) {
reportError(InputFilename, std::move(Err));
return 1;
}
Out->keep();
return 0;
}