llvm-project/llvm/tools/llvm-readobj/ObjDumper.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

164 lines
5.4 KiB
C
Raw Normal View History

//===-- ObjDumper.h ---------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_READOBJ_OBJDUMPER_H
#define LLVM_TOOLS_LLVM_READOBJ_OBJDUMPER_H
#include <memory>
#include <system_error>
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include <unordered_set>
namespace llvm {
namespace object {
class COFFImportFile;
class ObjectFile;
class XCOFFObjectFile;
class ELFObjectFileBase;
}
namespace codeview {
class GlobalTypeTableBuilder;
class MergingTypeTableBuilder;
} // namespace codeview
class ScopedPrinter;
class ObjDumper {
public:
ObjDumper(ScopedPrinter &Writer, StringRef ObjName);
virtual ~ObjDumper();
Recommit: [llvm-readelf/obj] - Allow dumping of ELF header even if some elements are corrupt. This is recommit for D90903 with fixes for BB: 1) Used std::move<> when returning Expected<> (http://lab.llvm.org:8011/#/builders/112/builds/913) 2) Fixed the name of temporarily file in the file-headers.test (http://lab.llvm.org:8011/#/builders/36/builds/1269) (a local old temporarily file was used before) 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
2020-11-09 17:18:18 +08:00
virtual bool canDumpContent() { return true; }
virtual void printFileHeaders() = 0;
virtual void printSectionHeaders() = 0;
virtual void printRelocations() = 0;
virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) {
if (PrintSymbols)
printSymbols();
if (PrintDynamicSymbols)
printDynamicSymbols();
}
virtual void printProgramHeaders(bool PrintProgramHeaders,
cl::boolOrDefault PrintSectionMapping) {
if (PrintProgramHeaders)
printProgramHeaders();
if (PrintSectionMapping == cl::BOU_TRUE)
printSectionMapping();
}
virtual void printUnwindInfo() = 0;
// Only implemented for ELF at this time.
virtual void printDependentLibs() {}
virtual void printDynamicRelocations() { }
virtual void printDynamicTable() { }
virtual void printNeededLibraries() { }
virtual void printSectionAsHex(StringRef SectionName) {}
virtual void printHashTable() { }
virtual void printGnuHashTable() {}
[llvm-readelf]Revert --dyn-symbols behaviour to make it GNU compatible, and add new --hash-symbols switch for old behaviour In r287786, the behaviour of --dyn-symbols in llvm-readelf (but not llvm-readobj) was changed to print the dynamic symbols as derived from the hash table, rather than to print the dynamic symbol table contents directly. The original change was initially submitted without review, and some comments were made on the commit mailing list implying that the new behavious is GNU compatible. I argue that it is not: 1) It does not include a null symbol. 2) It prints the symbols based on an order derived from the hash table. 3) It prints an extra column indicating which bucket it came from. This could break parsers that expect a fixed number of columns, with the first column being the symbol index. 4) If the input happens to have both .hash and .gnu.hash section, it prints interpretations of them both, resulting in most symbols being printed twice. 5) There is no way of just printing the raw dynamic symbol table, because --symbols also prints the static symbol table. This patch reverts the --dyn-symbols behaviour back to its old behaviour of just printing the contents of the dynamic symbol table, similar to what is printed by --symbols. As the hashed interpretation is still desirable to validate the hash table, it puts it under a new switch "--hash-symbols". This is a no-op on all output forms except for GNU output style for ELF. If there is no hash table, it does nothing, unlike the previous behaviour which printed the raw dynamic symbol table, since the raw dynsym is available under --dyn-symbols. The yaml input for the test is based on that in test/tools/llvm-readobj/demangle.test, but stripped down to the bare minimum to provide a valid dynamic symbol. Note: some LLD tests needed updating. I will commit a separate patch for those. Reviewed by: grimar, rupprecht Differential Revision: https://reviews.llvm.org/D56910 llvm-svn: 351789
2019-01-22 17:35:35 +08:00
virtual void printHashSymbols() {}
virtual void printLoadName() {}
virtual void printVersionInfo() {}
virtual void printGroupSections() {}
virtual void printHashHistograms() {}
virtual void printCGProfile() {}
virtual void printBBAddrMaps() {}
virtual void printAddrsig() {}
virtual void printNotes() {}
virtual void printELFLinkerOptions() {}
virtual void printStackSizes() {}
virtual void printSectionDetails() {}
virtual void printArchSpecificInfo() {}
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
virtual void printCOFFExports() { }
virtual void printCOFFDirectives() { }
virtual void printCOFFBaseReloc() { }
virtual void printCOFFDebugDirectory() { }
virtual void printCOFFTLSDirectory() {}
virtual void printCOFFResources() {}
virtual void printCOFFLoadConfig() { }
virtual void printCodeViewDebugInfo() { }
virtual void
mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
llvm::codeview::MergingTypeTableBuilder &CVTypes,
llvm::codeview::GlobalTypeTableBuilder &GlobalCVIDs,
llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes,
bool GHash) {}
// Only implement for XCOFF
virtual void printAuxiliaryHeader() {}
// Only implemented for MachO.
virtual void printMachODataInCode() { }
virtual void printMachOVersionMin() { }
virtual void printMachODysymtab() { }
virtual void printMachOSegment() { }
virtual void printMachOIndirectSymbols() { }
virtual void printMachOLinkerOptions() { }
// Currently only implemented for XCOFF.
virtual void printStringTable() { }
virtual void printStackMap() const = 0;
void printAsStringList(StringRef StringContent, size_t StringDataOffset = 0);
void printSectionsAsString(const object::ObjectFile &Obj,
ArrayRef<std::string> Sections);
void printSectionsAsHex(const object::ObjectFile &Obj,
ArrayRef<std::string> Sections);
std::function<Error(const Twine &Msg)> WarningHandler;
void reportUniqueWarning(Error Err) const;
void reportUniqueWarning(const Twine &Msg) const;
protected:
ScopedPrinter &W;
private:
virtual void printSymbols() {}
virtual void printDynamicSymbols() {}
virtual void printProgramHeaders() {}
virtual void printSectionMapping() {}
std::unordered_set<std::string> Warnings;
};
std::unique_ptr<ObjDumper> createCOFFDumper(const object::COFFObjectFile &Obj,
ScopedPrinter &Writer);
std::unique_ptr<ObjDumper> createELFDumper(const object::ELFObjectFileBase &Obj,
ScopedPrinter &Writer);
std::unique_ptr<ObjDumper> createMachODumper(const object::MachOObjectFile &Obj,
ScopedPrinter &Writer);
std::unique_ptr<ObjDumper> createWasmDumper(const object::WasmObjectFile &Obj,
ScopedPrinter &Writer);
std::unique_ptr<ObjDumper> createXCOFFDumper(const object::XCOFFObjectFile &Obj,
ScopedPrinter &Writer);
void dumpCOFFImportFile(const object::COFFImportFile *File,
ScopedPrinter &Writer);
void dumpCodeViewMergedTypes(ScopedPrinter &Writer,
ArrayRef<ArrayRef<uint8_t>> IpiRecords,
ArrayRef<ArrayRef<uint8_t>> TpiRecords);
} // namespace llvm
#endif