Index: llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-elfabi/read-tbe-as-elf.test @@ -0,0 +1,18 @@ +# RUN: not llvm-elfabi -elf %s -emit-tbe=%t &> %t.out +# RUN: cat %t.out | FileCheck %s + +--- !tapi-tbe +SoName: somelib.so +TbeVersion: 1.0 +Arch: x86_64 +Symbols: + foo: { Type: Func } + bar: { Type: Object, Size: 42 } + baz: { Type: Object, Size: 8 } + not: { Type: Object, Undefined: true, Size: 128 } + nor: { Type: Func, Undefined: true } +... + +#CHECK: Error: Encountered multiple errors: +#CHECK-NEXT: 0 (BinaryRead): The file was not recognized as a valid object file +#CHECK-NEXT: All file readers failed to read `{{.*}}`. (unsupported/malformed file?) Index: llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-elfabi/read-tbe-as-tbe.test @@ -0,0 +1,14 @@ +# RUN: llvm-elfabi -TBE %s -emit-tbe=%t +# RUN: cat %t | FileCheck %s + +--- !tapi-tbe +TbeVersion: 1.0 +Arch: AArch64 +Symbols: {} +... + +#CHECK: --- !tapi-tbe +#CHECK-NEXT: TbeVersion: {{[1-9]\d*\.(0|([1-9]\d*))}} +#CHECK-NEXT: Arch: AArch64 +#CHECK-NEXT: Symbols: {} +#CHECK-NEXT: ... Index: llvm/tools/llvm-elfabi/llvm-elfabi.cpp =================================================================== --- llvm/tools/llvm-elfabi/llvm-elfabi.cpp +++ llvm/tools/llvm-elfabi/llvm-elfabi.cpp @@ -18,10 +18,31 @@ #include "llvm/TextAPI/ELF/TBEHandler.h" #include +namespace llvm { +namespace elfabi { + +enum class FileFormat { + TBE, + ELF +}; + +} // end namespace elfabi +} // end namespace llvm + using namespace llvm; using namespace llvm::elfabi; // Command line flags: +cl::opt InputFileFormat( + cl::desc("Force input file format:"), + cl::values(clEnumValN(FileFormat::TBE, + "TBE", "Read `input` as text-based ELF stub"), + clEnumValN(FileFormat::TBE, + "tbe", "(alias for TBE)"), + clEnumValN(FileFormat::ELF, + "ELF", "Read `input` as ELF binary"), + clEnumValN(FileFormat::ELF, + "elf", "(alias for ELF)"))); cl::opt InputFilePath(cl::Positional, cl::desc("input"), cl::Required); cl::opt @@ -78,22 +99,28 @@ std::unique_ptr FileReadBuffer = std::move(BufOrError.get()); // First try to read as a binary (fails fast if not binary). - Expected> StubFromELF = - readELFFile(FileReadBuffer->getMemBufferRef()); - Error ELFReadError = StubFromELF.takeError(); - if (!ELFReadError) { - return std::move(StubFromELF.get()); + if (InputFileFormat.getNumOccurrences() == 0 || + InputFileFormat == FileFormat::ELF) { + Expected> StubFromELF = + readELFFile(FileReadBuffer->getMemBufferRef()); + Error ELFReadError = StubFromELF.takeError(); + if (!ELFReadError) { + return std::move(StubFromELF.get()); + } + EC.addError(std::move(ELFReadError), "BinaryRead"); } - EC.addError(std::move(ELFReadError), "BinaryRead"); // Fall back to reading as a tbe. - Expected> StubFromTBE = - readTBEFromBuffer(FileReadBuffer->getBuffer()); - Error TBEReadError = StubFromTBE.takeError(); - if (!TBEReadError) { - return std::move(StubFromTBE.get()); + if (InputFileFormat.getNumOccurrences() == 0 || + InputFileFormat == FileFormat::TBE) { + Expected> StubFromTBE = + readTBEFromBuffer(FileReadBuffer->getBuffer()); + Error TBEReadError = StubFromTBE.takeError(); + if (!TBEReadError) { + return std::move(StubFromTBE.get()); + } + EC.addError(std::move(TBEReadError), "YamlParse"); } - EC.addError(std::move(TBEReadError), "YamlParse"); // If both readers fail, build a new error that includes all information. EC.escalateToFatal();