[llvm] r222289 - llvm-readobj: teach it how to dump COFF base relocation table
Rui Ueyama
ruiu at google.com
Tue Nov 18 16:18:08 PST 2014
Author: ruiu
Date: Tue Nov 18 18:18:07 2014
New Revision: 222289
URL: http://llvm.org/viewvc/llvm-project?rev=222289&view=rev
Log:
llvm-readobj: teach it how to dump COFF base relocation table
Added:
llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386 (with props)
llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test
Modified:
llvm/trunk/include/llvm/Object/COFF.h
llvm/trunk/lib/Object/COFFObjectFile.cpp
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
llvm/trunk/tools/llvm-readobj/ObjDumper.h
llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
Modified: llvm/trunk/include/llvm/Object/COFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/COFF.h (original)
+++ llvm/trunk/include/llvm/Object/COFF.h Tue Nov 18 18:18:07 2014
@@ -28,11 +28,13 @@ class ImportDirectoryEntryRef;
class DelayImportDirectoryEntryRef;
class ExportDirectoryEntryRef;
class ImportedSymbolRef;
+class BaseRelocRef;
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
typedef content_iterator<DelayImportDirectoryEntryRef>
delay_import_directory_iterator;
typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator;
+typedef content_iterator<BaseRelocRef> base_reloc_iterator;
/// The DOS compatible header at the front of all PE/COFF executables.
struct dos_header {
@@ -459,6 +461,17 @@ struct coff_runtime_function_x64 {
support::ulittle32_t UnwindInformation;
};
+struct coff_base_reloc_block_header {
+ support::ulittle32_t PageRVA;
+ support::ulittle32_t BlockSize;
+};
+
+struct coff_base_reloc_block_entry {
+ support::ulittle16_t Data;
+ int getType() const { return Data >> 12; }
+ int getOffset() const { return Data & ((1 << 12) - 1); }
+};
+
class COFFObjectFile : public ObjectFile {
private:
friend class ImportDirectoryEntryRef;
@@ -478,6 +491,8 @@ private:
const delay_import_directory_table_entry *DelayImportDirectory;
uint32_t NumberOfDelayImportDirectory;
const export_directory_table_entry *ExportDirectory;
+ const coff_base_reloc_block_header *BaseRelocHeader;
+ const coff_base_reloc_block_header *BaseRelocEnd;
std::error_code getString(uint32_t offset, StringRef &Res) const;
@@ -490,6 +505,7 @@ private:
std::error_code initImportTablePtr();
std::error_code initDelayImportTablePtr();
std::error_code initExportTablePtr();
+ std::error_code initBaseRelocPtr();
public:
uintptr_t getSymbolTable() const {
@@ -621,11 +637,14 @@ public:
delay_import_directory_iterator delay_import_directory_end() const;
export_directory_iterator export_directory_begin() const;
export_directory_iterator export_directory_end() const;
+ base_reloc_iterator base_reloc_begin() const;
+ base_reloc_iterator base_reloc_end() const;
iterator_range<import_directory_iterator> import_directories() const;
iterator_range<delay_import_directory_iterator>
delay_import_directories() const;
iterator_range<export_directory_iterator> export_directories() const;
+ iterator_range<base_reloc_iterator> base_relocs() const;
const dos_header *getDOSHeader() const {
if (!PE32Header && !PE32PlusHeader)
@@ -798,6 +817,26 @@ private:
uint32_t Index;
const COFFObjectFile *OwningObject;
};
+
+class BaseRelocRef {
+public:
+ BaseRelocRef() : OwningObject(nullptr) {}
+ BaseRelocRef(const coff_base_reloc_block_header *Header,
+ const COFFObjectFile *Owner)
+ : Header(Header), Index(0), OwningObject(Owner) {}
+
+ bool operator==(const BaseRelocRef &Other) const;
+ void moveNext();
+
+ std::error_code getType(uint8_t &Type) const;
+ std::error_code getRVA(uint32_t &Result) const;
+
+private:
+ const coff_base_reloc_block_header *Header;
+ uint32_t Index;
+ const COFFObjectFile *OwningObject;
+};
+
} // end namespace object
} // end namespace llvm
Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/COFFObjectFile.cpp Tue Nov 18 18:18:07 2014
@@ -598,6 +598,23 @@ std::error_code COFFObjectFile::initExpo
return object_error::success;
}
+std::error_code COFFObjectFile::initBaseRelocPtr() {
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry))
+ return object_error::success;
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return object_error::success;
+
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
+ return EC;
+ BaseRelocHeader = reinterpret_cast<const coff_base_reloc_block_header *>(
+ IntPtr);
+ BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
+ IntPtr + DataEntry->Size);
+ return object_error::success;
+}
+
COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
: ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
@@ -605,7 +622,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
ImportDirectory(nullptr), NumberOfImportDirectory(0),
DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
- ExportDirectory(nullptr) {
+ ExportDirectory(nullptr), BaseRelocHeader(nullptr),
+ BaseRelocEnd(nullptr) {
// Check that we at least have enough room for a header.
if (!checkSize(Data, EC, sizeof(coff_file_header)))
return;
@@ -717,6 +735,10 @@ COFFObjectFile::COFFObjectFile(MemoryBuf
if ((EC = initExportTablePtr()))
return;
+ // Initialize the pointer to the base relocation table.
+ if ((EC = initBaseRelocPtr()))
+ return;
+
EC = object_error::success;
}
@@ -783,6 +805,14 @@ section_iterator COFFObjectFile::section
return section_iterator(SectionRef(Ret, this));
}
+base_reloc_iterator COFFObjectFile::base_reloc_begin() const {
+ return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this));
+}
+
+base_reloc_iterator COFFObjectFile::base_reloc_end() const {
+ return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this));
+}
+
uint8_t COFFObjectFile::getBytesInAddress() const {
return getArch() == Triple::x86_64 ? 8 : 4;
}
@@ -829,6 +859,10 @@ COFFObjectFile::export_directories() con
return make_range(export_directory_begin(), export_directory_end());
}
+iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
+ return make_range(base_reloc_begin(), base_reloc_end());
+}
+
std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
Res = PE32Header;
return object_error::success;
@@ -1448,3 +1482,37 @@ ObjectFile::createCOFFObjectFile(MemoryB
return EC;
return std::move(Ret);
}
+
+bool BaseRelocRef::operator==(const BaseRelocRef &Other) const {
+ return Header == Other.Header && Index == Other.Index;
+}
+
+void BaseRelocRef::moveNext() {
+ // Header->BlockSize is the size of the current block, including the
+ // size of the header itself.
+ uint32_t Size = sizeof(*Header) +
+ sizeof(coff_base_reloc_block_entry) * Index;
+ if (Size == Header->BlockSize) {
+ // .reloc contains a list of base relocation blocks. Each block
+ // consists of the header followed by entries. The header contains
+ // how many entories will follow. When we reach the end of the
+ // current block, proceed to the next block.
+ Header = reinterpret_cast<const coff_base_reloc_block_header *>(
+ reinterpret_cast<const uint8_t *>(Header) + Size);
+ Index = 0;
+ } else {
+ ++Index;
+ }
+}
+
+std::error_code BaseRelocRef::getType(uint8_t &Type) const {
+ auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
+ Type = Entry[Index].getType();
+ return object_error::success;
+}
+
+std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
+ auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1);
+ Result = Header->PageRVA + Entry[Index].getOffset();
+ return object_error::success;
+}
Added: llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386?rev=222289&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test?rev=222289&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/coff-basereloc.test Tue Nov 18 18:18:07 2014
@@ -0,0 +1,20 @@
+RUN: llvm-readobj -coff-basereloc %p/Inputs/basereloc.obj.coff-i386 | FileCheck %s
+
+CHECK: Format: COFF-i386
+CHECK: Arch: i386
+CHECK: AddressSize: 32bit
+CHECK: BaseReloc [
+CHECK: Entry {
+CHECK: Type: HIGHLOW
+CHECK: Address: 0x1004
+CHECK: }
+CHECK: Entry {
+CHECK: Type: HIGHLOW
+CHECK: Address: 0x100A
+CHECK: }
+CHECK: Entry {
+CHECK: Type: HIGHLOW
+CHECK: Address: 0x1010
+CHECK: }
+CHECK: ]
+
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Tue Nov 18 18:18:07 2014
@@ -57,6 +57,7 @@ public:
void printUnwindInfo() override;
void printCOFFImports() override;
void printCOFFDirectives() override;
+ void printCOFFBaseReloc() override;
private:
void printSymbol(const SymbolRef &Sym);
@@ -1076,3 +1077,33 @@ void COFFDumper::printCOFFDirectives() {
W.printString("Directive(s)", Contents);
}
}
+
+static StringRef getBaseRelocTypeName(uint8_t Type) {
+ switch (Type) {
+ case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
+ case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
+ case COFF::IMAGE_REL_BASED_LOW: return "LOW";
+ case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
+ case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
+ case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
+ default: return "unknown";
+ }
+}
+
+void COFFDumper::printCOFFBaseReloc() {
+ ListScope D(W, "BaseReloc");
+ for (const BaseRelocRef &I : Obj->base_relocs()) {
+ uint8_t Type;
+ uint32_t RVA;
+ if (error(I.getRVA(RVA)))
+ continue;
+ if (error(I.getType(Type)))
+ continue;
+ // IMAGE_REL_BASED_ABSOLUTE is a NOP entry.
+ if (Type == COFF::IMAGE_REL_BASED_ABSOLUTE)
+ continue;
+ DictScope Import(W, "Entry");
+ W.printString("Type", getBaseRelocTypeName(Type));
+ W.printHex("Address", RVA);
+ }
+}
Modified: llvm/trunk/tools/llvm-readobj/ObjDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ObjDumper.h?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ObjDumper.h (original)
+++ llvm/trunk/tools/llvm-readobj/ObjDumper.h Tue Nov 18 18:18:07 2014
@@ -46,6 +46,7 @@ public:
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
virtual void printCOFFDirectives() { }
+ virtual void printCOFFBaseReloc() { }
protected:
StreamWriter& W;
Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=222289&r1=222288&r2=222289&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Tue Nov 18 18:18:07 2014
@@ -149,7 +149,12 @@ namespace opts {
// -coff-directives
cl::opt<bool>
COFFDirectives("coff-directives",
- cl::desc("Display the contents PE/COFF .drectve section"));
+ cl::desc("Display the PE/COFF .drectve section"));
+
+ // -coff-basereloc
+ cl::opt<bool>
+ COFFBaseRelocs("coff-basereloc",
+ cl::desc("Display the PE/COFF .reloc section"));
} // namespace opts
static int ReturnValue = EXIT_SUCCESS;
@@ -279,6 +284,8 @@ static void dumpObject(const ObjectFile
Dumper->printCOFFImports();
if (opts::COFFDirectives)
Dumper->printCOFFDirectives();
+ if (opts::COFFBaseRelocs)
+ Dumper->printCOFFBaseReloc();
}
More information about the llvm-commits
mailing list