aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-readobj/llvm-readobj.cpp
diff options
context:
space:
mode:
authorGeorgii Rymar <grimar@accesssoftek.com>2020-11-03 14:02:01 +0300
committerGeorgii Rymar <grimar@accesssoftek.com>2020-11-09 11:27:07 +0300
commitea8a0b8b29eb08d3f0f6ac40942a2d8e98ab57ee (patch)
tree3ad91c2aaf55b1046f77e14a8e866d931a61f461 /llvm/tools/llvm-readobj/llvm-readobj.cpp
parentc9d036ad4a2962059c595c77abb51154e2f5ec27 (diff)
downloadllvm-ea8a0b8b29eb08d3f0f6ac40942a2d8e98ab57ee.zip
llvm-ea8a0b8b29eb08d3f0f6ac40942a2d8e98ab57ee.tar.gz
llvm-ea8a0b8b29eb08d3f0f6ac40942a2d8e98ab57ee.tar.bz2
[llvm-readelf/obj] - Allow dumping of ELF header even if some elements are corrupt.
For creating `ELFObjectFile` instances we have the factory method `ELFObjectFile<ELFT>::create(MemoryBufferRef Object)`. The problem of this method is that it scans the section header to locate some sections. When a file is truncated or has broken fields in the ELF header, this approach does not allow us to create the `ELFObjectFile` and dump the ELF header. This is https://bugs.llvm.org/show_bug.cgi?id=40804 This patch suggests a solution - it allows to delay scaning sections in the `ELFObjectFile<ELFT>::create`. It now allows user code to call an object initialization (`initContent()`) later. With that it is possible, for example, for dumpers just to dump the file header and exit. By default initialization is still performed as before, what helps to keep the logic of existent callers untouched. I've experimented with different approaches when worked on this patch. I think this approach is better than doing initialization of sections (i.e. scan of them) on demand, because normally users of `ELFObjectFile` API expect to work with a valid object. In most cases when a section header table can't be read (because of an error), we don't have to continue to work with object. So we probably don't need to implement a more complex API. Differential revision: https://reviews.llvm.org/D90903
Diffstat (limited to 'llvm/tools/llvm-readobj/llvm-readobj.cpp')
-rw-r--r--llvm/tools/llvm-readobj/llvm-readobj.cpp15
1 files changed, 13 insertions, 2 deletions
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index a307735..41cd441 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -458,12 +458,17 @@ createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
}
/// Dumps the specified object file.
-static void dumpObject(const ObjectFile &Obj, ScopedPrinter &Writer,
+static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
const Archive *A = nullptr) {
std::string FileStr =
A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
: Obj.getFileName().str();
+ std::string ContentErrString;
+ if (Error ContentErr = Obj.initContent())
+ ContentErrString = "unable to continue dumping, the file is corrupt: " +
+ toString(std::move(ContentErr));
+
ObjDumper *Dumper;
Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
if (!DumperOrErr)
@@ -486,6 +491,11 @@ static void dumpObject(const ObjectFile &Obj, ScopedPrinter &Writer,
if (opts::FileHeaders)
Dumper->printFileHeaders();
+ // This is only used for ELF currently. In some cases, when an object is
+ // corrupt (e.g. truncated), we can't dump anything except the file header.
+ if (!ContentErrString.empty())
+ reportError(createError(ContentErrString), FileStr);
+
if (opts::SectionDetails || opts::SectionHeaders) {
if (opts::Output == opts::GNU && opts::SectionDetails)
Dumper->printSectionDetails();
@@ -637,7 +647,8 @@ static void dumpWindowsResourceFile(WindowsResource *WinRes,
/// Opens \a File and dumps it.
static void dumpInput(StringRef File, ScopedPrinter &Writer) {
// Attempt to open the binary.
- Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
+ Expected<OwningBinary<Binary>> BinaryOrErr =
+ createBinary(File, /*Context=*/nullptr, /*InitContent=*/false);
if (!BinaryOrErr)
reportError(BinaryOrErr.takeError(), File);
Binary &Binary = *BinaryOrErr.get().getBinary();