forked from OSchip/llvm-project
[llvm-readobj] Add --coff-tls-directory flag to print TLS Directory & test.
Akin to dumpbin's /TLS option, this will print out the TLS directory, if present, in the image. Example output: ``` > llvm-readobj --coff-tls-directory test.exe File: test.exe Format: COFF-x86-64 Arch: x86_64 AddressSize: 64bit TLSDirectory { StartAddressOfRawData: 0x140004000 EndAddressOfRawData: 0x140004040 AddressOfIndex: 0x140002000 AddressOfCallBacks: 0x0 SizeOfZeroFill: 0x0 Characteristics [ (0x0) ] } ``` Reviewed By: jhenderson, grimar Differential Revision: https://reviews.llvm.org/D88635
This commit is contained in:
parent
8e9622f961
commit
568035ac39
|
@ -286,6 +286,10 @@ The following options are implemented only for the PE/COFF file format.
|
|||
|
||||
Display the debug directory.
|
||||
|
||||
.. option:: --coff-tls-directory
|
||||
|
||||
Display the TLS directory.
|
||||
|
||||
.. option:: --coff-directives
|
||||
|
||||
Display the .drectve section.
|
||||
|
|
|
@ -311,6 +311,7 @@ enum SectionCharacteristics : uint32_t {
|
|||
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000,
|
||||
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000,
|
||||
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000,
|
||||
IMAGE_SCN_ALIGN_MASK = 0x00F00000,
|
||||
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000,
|
||||
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000,
|
||||
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000,
|
||||
|
|
|
@ -786,6 +786,8 @@ private:
|
|||
const coff_base_reloc_block_header *BaseRelocEnd;
|
||||
const debug_directory *DebugDirectoryBegin;
|
||||
const debug_directory *DebugDirectoryEnd;
|
||||
const coff_tls_directory32 *TLSDirectory32;
|
||||
const coff_tls_directory64 *TLSDirectory64;
|
||||
// Either coff_load_configuration32 or coff_load_configuration64.
|
||||
const void *LoadConfig = nullptr;
|
||||
|
||||
|
@ -805,6 +807,7 @@ private:
|
|||
Error initExportTablePtr();
|
||||
Error initBaseRelocPtr();
|
||||
Error initDebugDirectoryPtr();
|
||||
Error initTLSDirectoryPtr();
|
||||
Error initLoadConfigPtr();
|
||||
|
||||
public:
|
||||
|
@ -976,6 +979,13 @@ public:
|
|||
return make_range(debug_directory_begin(), debug_directory_end());
|
||||
}
|
||||
|
||||
const coff_tls_directory32 *getTLSDirectory32() const {
|
||||
return TLSDirectory32;
|
||||
}
|
||||
const coff_tls_directory64 *getTLSDirectory64() const {
|
||||
return TLSDirectory64;
|
||||
}
|
||||
|
||||
const dos_header *getDOSHeader() const {
|
||||
if (!PE32Header && !PE32PlusHeader)
|
||||
return nullptr;
|
||||
|
|
|
@ -649,6 +649,38 @@ Error COFFObjectFile::initDebugDirectoryPtr() {
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
Error COFFObjectFile::initTLSDirectoryPtr() {
|
||||
// Get the RVA of the TLS directory. Do nothing if it does not exist.
|
||||
const data_directory *DataEntry = getDataDirectory(COFF::TLS_TABLE);
|
||||
if (!DataEntry)
|
||||
return Error::success();
|
||||
|
||||
// Do nothing if the RVA is NULL.
|
||||
if (DataEntry->RelativeVirtualAddress == 0)
|
||||
return Error::success();
|
||||
|
||||
uint64_t DirSize =
|
||||
is64() ? sizeof(coff_tls_directory64) : sizeof(coff_tls_directory32);
|
||||
|
||||
// Check that the size is correct.
|
||||
if (DataEntry->Size != DirSize)
|
||||
return createStringError(
|
||||
object_error::parse_failed,
|
||||
"TLS Directory size (%u) is not the expected size (%u).",
|
||||
static_cast<uint32_t>(DataEntry->Size), DirSize);
|
||||
|
||||
uintptr_t IntPtr = 0;
|
||||
if (Error E = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
|
||||
return E;
|
||||
|
||||
if (is64())
|
||||
TLSDirectory64 = reinterpret_cast<const coff_tls_directory64 *>(IntPtr);
|
||||
else
|
||||
TLSDirectory32 = reinterpret_cast<const coff_tls_directory32 *>(IntPtr);
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Error COFFObjectFile::initLoadConfigPtr() {
|
||||
// Get the RVA of the debug directory. Do nothing if it does not exist.
|
||||
const data_directory *DataEntry = getDataDirectory(COFF::LOAD_CONFIG_TABLE);
|
||||
|
@ -682,7 +714,8 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object)
|
|||
ImportDirectory(nullptr), DelayImportDirectory(nullptr),
|
||||
NumberOfDelayImportDirectory(0), ExportDirectory(nullptr),
|
||||
BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
|
||||
DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {}
|
||||
DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr),
|
||||
TLSDirectory32(nullptr), TLSDirectory64(nullptr) {}
|
||||
|
||||
Error COFFObjectFile::initialize() {
|
||||
// Check that we at least have enough room for a header.
|
||||
|
@ -809,10 +842,14 @@ Error COFFObjectFile::initialize() {
|
|||
if (Error E = initBaseRelocPtr())
|
||||
return E;
|
||||
|
||||
// Initialize the pointer to the export table.
|
||||
// Initialize the pointer to the debug directory.
|
||||
if (Error E = initDebugDirectoryPtr())
|
||||
return E;
|
||||
|
||||
// Initialize the pointer to the TLS directory.
|
||||
if (Error E = initTLSDirectoryPtr())
|
||||
return E;
|
||||
|
||||
if (Error E = initLoadConfigPtr())
|
||||
return E;
|
||||
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
## Tests for the --coff-tls-directory flag.
|
||||
|
||||
## Test that the output of --coff-tls-directory works on x86.
|
||||
## The binary created from this yaml definition is such that .rdata contains
|
||||
## only the IMAGE_TLS_DIRECTORY structure and hence we should have that
|
||||
## TlsTable.RelativeVirtualAddress == .rdata section VirtualAddress.
|
||||
## Also note that the .rdata section VirtualSize == sizeof(coff_tls_directory32) == sizeof(IMAGE_TLS_DIRECTORY32) == 24
|
||||
|
||||
# RUN: yaml2obj %s --docnum=1 -o %t.32.exe -DTLSRVA=10000 -DTLSSIZE=24
|
||||
# RUN: llvm-readobj --coff-tls-directory %t.32.exe | FileCheck %s --check-prefix I386
|
||||
|
||||
# I386: Arch: i386
|
||||
# I386-NEXT: AddressSize: 32bit
|
||||
# I386-NEXT: TLSDirectory {
|
||||
# I386-NEXT: StartAddressOfRawData: 0x404000
|
||||
# I386-NEXT: EndAddressOfRawData: 0x404008
|
||||
# I386-NEXT: AddressOfIndex: 0x402000
|
||||
# I386-NEXT: AddressOfCallBacks: 0x0
|
||||
# I386-NEXT: SizeOfZeroFill: 0x0
|
||||
# I386-NEXT: Characteristics [ (0x300000)
|
||||
# I386-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
|
||||
# I386-NEXT: ]
|
||||
# I386-NEXT: }
|
||||
|
||||
|
||||
## Test that the output of --coff-tls-directory errors on malformed input.
|
||||
## On x86, the TLS directory should be 24 bytes.
|
||||
## This test has a truncated TLS directory.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=1 -o %t.wrong-size.32.exe -DTLSRVA=10000 -DTLSSIZE=10
|
||||
# RUN: not llvm-readobj --coff-tls-directory %t.wrong-size.32.exe 2>&1 | FileCheck %s --check-prefix I386-WRONG-SIZE-ERR
|
||||
|
||||
# I386-WRONG-SIZE-ERR: error: '{{.*}}': TLS Directory size (10) is not the expected size (24).
|
||||
|
||||
--- !COFF
|
||||
OptionalHeader:
|
||||
AddressOfEntryPoint: 0
|
||||
ImageBase: 0
|
||||
SectionAlignment: 4096
|
||||
FileAlignment: 512
|
||||
MajorOperatingSystemVersion: 0
|
||||
MinorOperatingSystemVersion: 0
|
||||
MajorImageVersion: 0
|
||||
MinorImageVersion: 0
|
||||
MajorSubsystemVersion: 0
|
||||
MinorSubsystemVersion: 0
|
||||
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
DLLCharacteristics: []
|
||||
SizeOfStackReserve: 0
|
||||
SizeOfStackCommit: 0
|
||||
SizeOfHeapReserve: 0
|
||||
SizeOfHeapCommit: 0
|
||||
TlsTable:
|
||||
RelativeVirtualAddress: [[TLSRVA]]
|
||||
Size: [[TLSSIZE]]
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_I386
|
||||
Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_32BIT_MACHINE ]
|
||||
sections:
|
||||
- Name: .rdata
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
VirtualAddress: 10000
|
||||
VirtualSize: 24
|
||||
SectionData: '004040000840400000204000000000000000000000003000'
|
||||
symbols: []
|
||||
|
||||
|
||||
## Test that the output of --coff-tls-directory works on x86_64.
|
||||
## The binary created from this yaml definition is such that .rdata contains
|
||||
## only the IMAGE_TLS_DIRECTORY structure and hence we should have that
|
||||
## TlsTable.RelativeVirtualAddress == .rdata section VirtualAddress.
|
||||
## Also note that the .rdata section VirtualSize == sizeof(coff_tls_directory64) == sizeof(IMAGE_TLS_DIRECTORY64) == 40
|
||||
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t.64.exe -DTLSRVA=10000 -DTLSSIZE=40
|
||||
# RUN: llvm-readobj --coff-tls-directory %t.64.exe | FileCheck %s --check-prefix X86-64
|
||||
|
||||
# X86-64: Arch: x86_64
|
||||
# X86-64-NEXT: AddressSize: 64bit
|
||||
# X86-64-NEXT: TLSDirectory {
|
||||
# X86-64-NEXT: StartAddressOfRawData: 0x140004000
|
||||
# X86-64-NEXT: EndAddressOfRawData: 0x140004008
|
||||
# X86-64-NEXT: AddressOfIndex: 0x140002000
|
||||
# X86-64-NEXT: AddressOfCallBacks: 0x0
|
||||
# X86-64-NEXT: SizeOfZeroFill: 0x0
|
||||
# X86-64-NEXT: Characteristics [ (0x300000)
|
||||
# X86-64-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
|
||||
# X86-64-NEXT: ]
|
||||
# X86-64-NEXT: }
|
||||
|
||||
|
||||
## Test that the output of --coff-tls-directory errors on malformed input.
|
||||
|
||||
## On x86-64, the TLS directory should be 40 bytes.
|
||||
## This test has an erroneously lengthened TLS directory.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t.wrong-size.64.exe -DTLSRVA=10000 -DTLSSIZE=80
|
||||
# RUN: not llvm-readobj --coff-tls-directory %t.wrong-size.64.exe 2>&1 | FileCheck %s --check-prefix X86-64-WRONG-SIZE-ERR
|
||||
|
||||
# X86-64-WRONG-SIZE-ERR: error: '{{.*}}': TLS Directory size (80) is not the expected size (40).
|
||||
|
||||
|
||||
## This test has a correct TLS Directory size but the RVA is invalid.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t.bad-tls-rva.exe -DTLSRVA=999999 -DTLSSIZE=40
|
||||
# RUN: not llvm-readobj --coff-tls-directory %t.bad-tls-rva.exe 2>&1 | FileCheck %s --check-prefix BAD-TLS-RVA-ERR
|
||||
|
||||
# BAD-TLS-RVA-ERR: error: '{{.*}}': Invalid data was encountered while parsing the file
|
||||
|
||||
--- !COFF
|
||||
OptionalHeader:
|
||||
AddressOfEntryPoint: 0
|
||||
ImageBase: 0
|
||||
SectionAlignment: 4096
|
||||
FileAlignment: 512
|
||||
MajorOperatingSystemVersion: 0
|
||||
MinorOperatingSystemVersion: 0
|
||||
MajorImageVersion: 0
|
||||
MinorImageVersion: 0
|
||||
MajorSubsystemVersion: 0
|
||||
MinorSubsystemVersion: 0
|
||||
Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
DLLCharacteristics: []
|
||||
SizeOfStackReserve: 0
|
||||
SizeOfStackCommit: 0
|
||||
SizeOfHeapReserve: 0
|
||||
SizeOfHeapCommit: 0
|
||||
TlsTable:
|
||||
RelativeVirtualAddress: [[TLSRVA]]
|
||||
Size: [[TLSSIZE]]
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
|
||||
sections:
|
||||
- Name: .rdata
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
VirtualAddress: 10000
|
||||
VirtualSize: 40
|
||||
SectionData: '00400040010000000840004001000000002000400100000000000000000000000000000000003000'
|
||||
symbols: []
|
||||
|
||||
|
||||
## Test that --coff-tls-directory doesn't output anything if there's no TLS directory.
|
||||
|
||||
## Case 1: TlsTable.RelativeVirtualAddress/Size = 0.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=2 -o %t.no-tls1.exe -DTLSRVA=0 -DTLSSIZE=0
|
||||
# RUN: llvm-readobj --coff-tls-directory %t.no-tls1.exe | FileCheck %s --check-prefix NO-TLS
|
||||
|
||||
## Case 2: There's no TlsTable listed in the COFF header.
|
||||
|
||||
# RUN: yaml2obj %s --docnum=3 -o %t.no-tls2.exe
|
||||
# RUN: llvm-readobj --coff-tls-directory %t.no-tls2.exe | FileCheck %s --check-prefix NO-TLS
|
||||
|
||||
# NO-TLS: TLSDirectory {
|
||||
# NO-TLS-NEXT: }
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
|
||||
sections: []
|
||||
symbols: []
|
|
@ -89,6 +89,7 @@ public:
|
|||
void printCOFFDirectives() override;
|
||||
void printCOFFBaseReloc() override;
|
||||
void printCOFFDebugDirectory() override;
|
||||
void printCOFFTLSDirectory() override;
|
||||
void printCOFFResources() override;
|
||||
void printCOFFLoadConfig() override;
|
||||
void printCodeViewDebugInfo() override;
|
||||
|
@ -116,6 +117,8 @@ private:
|
|||
void printBaseOfDataField(const pe32plus_header *Hdr);
|
||||
template <typename T>
|
||||
void printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables);
|
||||
template <typename IntTy>
|
||||
void printCOFFTLSDirectory(const coff_tls_directory<IntTy> *TlsTable);
|
||||
typedef void (*PrintExtraCB)(raw_ostream &, const uint8_t *);
|
||||
void printRVATable(uint64_t TableVA, uint64_t Count, uint64_t EntrySize,
|
||||
PrintExtraCB PrintExtra = 0);
|
||||
|
@ -2018,3 +2021,27 @@ void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,
|
|||
Writer.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void COFFDumper::printCOFFTLSDirectory() {
|
||||
if (Obj->is64())
|
||||
printCOFFTLSDirectory(Obj->getTLSDirectory64());
|
||||
else
|
||||
printCOFFTLSDirectory(Obj->getTLSDirectory32());
|
||||
}
|
||||
|
||||
template <typename IntTy>
|
||||
void COFFDumper::printCOFFTLSDirectory(
|
||||
const coff_tls_directory<IntTy> *TlsTable) {
|
||||
DictScope D(W, "TLSDirectory");
|
||||
if (!TlsTable)
|
||||
return;
|
||||
|
||||
W.printHex("StartAddressOfRawData", TlsTable->StartAddressOfRawData);
|
||||
W.printHex("EndAddressOfRawData", TlsTable->EndAddressOfRawData);
|
||||
W.printHex("AddressOfIndex", TlsTable->AddressOfIndex);
|
||||
W.printHex("AddressOfCallBacks", TlsTable->AddressOfCallBacks);
|
||||
W.printHex("SizeOfZeroFill", TlsTable->SizeOfZeroFill);
|
||||
W.printFlags("Characteristics", TlsTable->Characteristics,
|
||||
makeArrayRef(ImageSectionCharacteristics),
|
||||
COFF::SectionCharacteristics(COFF::IMAGE_SCN_ALIGN_MASK));
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ public:
|
|||
virtual void printCOFFDirectives() { }
|
||||
virtual void printCOFFBaseReloc() { }
|
||||
virtual void printCOFFDebugDirectory() { }
|
||||
virtual void printCOFFTLSDirectory() {}
|
||||
virtual void printCOFFResources() {}
|
||||
virtual void printCOFFLoadConfig() { }
|
||||
virtual void printCodeViewDebugInfo() { }
|
||||
|
|
|
@ -272,6 +272,10 @@ namespace opts {
|
|||
COFFDebugDirectory("coff-debug-directory",
|
||||
cl::desc("Display the PE/COFF debug directory"));
|
||||
|
||||
// --coff-tls-directory
|
||||
cl::opt<bool> COFFTLSDirectory("coff-tls-directory",
|
||||
cl::desc("Display the PE/COFF TLS directory"));
|
||||
|
||||
// --coff-resources
|
||||
cl::opt<bool> COFFResources("coff-resources",
|
||||
cl::desc("Display the PE/COFF .rsrc section"));
|
||||
|
@ -533,6 +537,8 @@ static void dumpObject(const ObjectFile &Obj, ScopedPrinter &Writer,
|
|||
Dumper->printCOFFBaseReloc();
|
||||
if (opts::COFFDebugDirectory)
|
||||
Dumper->printCOFFDebugDirectory();
|
||||
if (opts::COFFTLSDirectory)
|
||||
Dumper->printCOFFTLSDirectory();
|
||||
if (opts::COFFResources)
|
||||
Dumper->printCOFFResources();
|
||||
if (opts::COFFLoadConfig)
|
||||
|
|
Loading…
Reference in New Issue