Files

326 lines
8.9 KiB
C++

#include "pe/DebugDirWrapper.h"
#include <QtGlobal>
using namespace pe;
/*
typedef struct _IMAGE_DEBUG_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Type;
DWORD SizeOfData;
DWORD AddressOfRawData;
DWORD PointerToRawData;
} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
*/
bool DebugDirWrapper::loadNextEntry(size_t cntr)
{
const size_t dirSize = this->getSize();
const size_t entriesCount = dirSize / sizeof(IMAGE_DEBUG_DIRECTORY);
if (cntr >= entriesCount) {
return false;
}
DebugDirEntryWrapper* dbgEntry = new DebugDirEntryWrapper(m_PE, this, cntr);
if (!dbgEntry || !dbgEntry->getPtr()) {
delete dbgEntry;
return false;
}
entries.push_back(dbgEntry);
return true;
}
bool DebugDirWrapper::isRepro()
{
for (auto itr = entries.begin(); itr != entries.end(); ++itr) {
DebugDirEntryWrapper* dbgEntry = dynamic_cast<DebugDirEntryWrapper*>(*itr);
if (!dbgEntry) continue;
bool isOk = false;
uint64_t typeVal = dbgEntry->getNumValue(DebugDirEntryWrapper::TYPE, &isOk);
if (isOk && typeVal == pe::DT_REPRO) {
return true;
}
}
return false;
}
//---
bool DebugDirEntryWrapper::wrap()
{
if (this->getDebugStruct()) {
DebugDirCVEntryWrapper *cvWrapper = new DebugDirCVEntryWrapper(m_Exe, this);
this->entries.push_back(cvWrapper);
}
return true;
}
void* DebugDirEntryWrapper::getPtr()
{
return debugDir();
}
bufsize_t DebugDirEntryWrapper::getSize()
{
if (!getPtr()) return 0;
return sizeof(IMAGE_DEBUG_DIRECTORY);
}
void* DebugDirEntryWrapper::getFieldPtr(size_t fId, size_t subField)
{
IMAGE_DEBUG_DIRECTORY* d = debugDir();
if (d == NULL) return NULL;
switch (fId) {
case CHARACTERISTIC: return &d->Characteristics;
case TIMESTAMP: return &d->TimeDateStamp;
case MAJOR_VER: return &d->MajorVersion;
case MINOR_VER: return &d->MinorVersion;
case TYPE: return &d->Type;
case DATA_SIZE: return &d->SizeOfData;
case RAW_DATA_ADDR: return &d->AddressOfRawData;
case RAW_DATA_PTR: return &d->PointerToRawData;
}
return this->getPtr();
}
QString DebugDirEntryWrapper::getFieldName(size_t fieldId)
{
switch (fieldId) {
case CHARACTERISTIC: return "Characteristics";
case TIMESTAMP: return (dbgRootDir && dbgRootDir->isRepro()) ? "ReproChecksum" :"TimeDateStamp";
case MAJOR_VER: return "MajorVersion";
case MINOR_VER: return "MinorVersion";
case TYPE: return "Type";
case DATA_SIZE: return "SizeOfData";
case RAW_DATA_ADDR: return "AddressOfRawData";
case RAW_DATA_PTR: return "PointerToRawData";
}
return getName();
}
Executable::addr_type DebugDirEntryWrapper::containsAddrType(size_t fieldId, size_t subField)
{
switch (fieldId) {
case RAW_DATA_ADDR: return Executable::RVA;
case RAW_DATA_PTR: return Executable::RAW;
}
return Executable::NOT_ADDR;
}
QString DebugDirEntryWrapper::translateType(int type)
{
switch (type) {
case pe::DT_UNKNOWN : return "unknown";
case pe::DT_COFF : return "COFF";
case pe::DT_CODEVIEW : return "Visual C++ (CodeView)";
case pe::DT_FPO : return "Frame pointer omission";
case pe::DT_MISC : return "DBG file";
case pe::DT_EXCEPTION : return "A copy of .pdata section";
case pe::DT_FIXUP : return "Reserved";
case pe::DT_OMAP_TO_SRC : return "mapping from an RVA in image to an RVA in source image";
case pe::DT_OMAP_FROM_SRC : return "mapping from an RVA in source image to an RVA in image";
case pe::DT_BORLAND : return "Borland";
case pe::DT_RESERVED10 : return "Reserved";
case pe::DT_CLSID : return "CLSID";
case pe::DT_VC_FEATURE : return "VC Feature";
case pe::DT_POGO : return "POGO";
case pe::DT_ILTCG : return "ILTCG";
case pe::DT_MPX : return "MPX";
case pe::DT_REPRO : return "REPRO";
}
return "<Unknown>";
}
QString DebugDirEntryWrapper::translateFieldContent(size_t fieldId)
{
if (fieldId != TYPE) return "";
IMAGE_DEBUG_DIRECTORY* d = debugDir();
if (d == NULL) return NULL;
return translateType(d->Type);
}
BYTE* DebugDirEntryWrapper::getDebugStruct()
{
IMAGE_DEBUG_DIRECTORY* d = this->debugDir();
if (d == NULL) return NULL;
if (d->Type != DT_CODEVIEW) {
return NULL;
}
offset_t rva = d->PointerToRawData;
size_t dirSize = d->SizeOfData;
return m_Exe->getContentAt(rva, Executable::RAW, dirSize);
}
DEBUG_RSDSI* DebugDirEntryWrapper::getRDSI()
{
BYTE* debugStr = getDebugStruct();
IMAGE_DEBUG_DIRECTORY* d = debugDir();
if (!debugStr || !d) return NULL;
if (d->SizeOfData < sizeof(DEBUG_RSDSI)) {
return NULL;
}
DEBUG_RSDSI* rdsi = (DEBUG_RSDSI*)debugStr;
if (rdsi->dwSig == CV_SIGNATURE_RSDS) {
return rdsi;
}
return NULL;
}
pe::DEBUG_NB10* DebugDirEntryWrapper::getNB10()
{
BYTE* debugStr = getDebugStruct();
IMAGE_DEBUG_DIRECTORY* d = debugDir();
if (!debugStr || !d) return NULL;
if (d->SizeOfData < sizeof(DEBUG_NB10)) {
return NULL;
}
DEBUG_NB10* nb = (DEBUG_NB10*)debugStr;
if (nb->cvHdr.CvSignature == CV_SIGNATURE_NB10) {
return nb;
}
return NULL;
}
//-------------------------
void* DebugDirCVEntryWrapper::getPtr()
{
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
if (rdsi) {
return rdsi;
}
return parentDir->getNB10();
}
bufsize_t DebugDirCVEntryWrapper::getSize()
{
IMAGE_DEBUG_DIRECTORY* d = parentDir->debugDir();
if (d == NULL) return 0;
return d->SizeOfData;
}
void* DebugDirCVEntryWrapper::getFieldPtr(size_t fId, size_t subField)
{
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
if (rdsi) {
switch (fId) {
case F_CVDBG_SIGN: return &rdsi->dwSig;
case F_CVDBG_GUID: return &rdsi->guidSig;
case F_CVDBG_AGE: return &rdsi->age;
case F_CVDBG_PDB: return &rdsi->szPdb;
}
return rdsi;
}
DEBUG_NB10* dbg = parentDir->getNB10();
if (dbg) {
switch (fId) {
case F_CVDBG_SIGN: return &dbg->cvHdr.CvSignature;
case F_CVDBG_GUID: return &dbg->Signature;
case F_CVDBG_AGE: return &dbg->Age;
case F_CVDBG_PDB: return &dbg->PdbFileName;
}
return dbg;
}
return NULL;
}
QString DebugDirCVEntryWrapper::getGuidString()
{
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
if (rdsi) {
QString chunk4 = "";
for (size_t i = 0; i < sizeof(rdsi->guidSig.Data4); i++) {
QString out;
#if QT_VERSION >= 0x050000
out = QString().asprintf("%02X", rdsi->guidSig.Data4[i]);
#else
out = QString().sprintf("%02X", rdsi->guidSig.Data4[i]);
#endif
chunk4 += out;
}
QString chunk5 = "";
for (size_t i = 0; i < sizeof(rdsi->guidSig.Data5); i++) {
QString out;
#if QT_VERSION >= 0x050000
out = QString().asprintf("%02X", rdsi->guidSig.Data5[i]);
#else
out = QString().sprintf("%02X", rdsi->guidSig.Data5[i]);
#endif
chunk5 += out;
}
QString out;
#if QT_VERSION >= 0x050000
out = QString().asprintf("%08X-%04X-%04X-",
rdsi->guidSig.Data1,
rdsi->guidSig.Data2,
rdsi->guidSig.Data3);
#else
out = QString().sprintf("%08X-%04X-%04X-",
rdsi->guidSig.Data1,
rdsi->guidSig.Data2,
rdsi->guidSig.Data3);
#endif
return "{" + out + chunk4 + "-" + chunk5 + "}";
}
DEBUG_NB10* dbg = parentDir->getNB10();
if (dbg) {
QString out;
#if QT_VERSION >= 0x050000
out = QString().asprintf("%04X", dbg->Signature);
#else
out = QString().sprintf("%04X", dbg->Signature);
#endif
return out;
}
return "";
}
QString DebugDirCVEntryWrapper::getSignature()
{
DEBUG_RSDSI* rdsi = (DEBUG_RSDSI*)this->getPtr();
if (!rdsi) return "";
QString out;
#if QT_VERSION >= 0x050000
out = QString().asprintf("%.4s", (char*)&rdsi->dwSig);
#else
out = QString().sprintf("%.4s", (char*)&rdsi->dwSig);
#endif
return out;
}
QString DebugDirCVEntryWrapper::getFieldName(size_t fId)
{
switch (fId) {
case F_CVDBG_SIGN: return "CvSig";
case F_CVDBG_GUID: return "Signature";
case F_CVDBG_AGE: return "Age";
case F_CVDBG_PDB: return "PDB";
}
return "";
}
QString DebugDirCVEntryWrapper::translateFieldContent(size_t fId)
{
DEBUG_RSDSI* rdsi = parentDir->getRDSI();
DEBUG_NB10* dbg = parentDir->getNB10();
if (!rdsi && !dbg) return "";
char *pdb = NULL;
if (rdsi) pdb = (char*)rdsi->szPdb;
if (dbg) pdb = (char*)dbg->PdbFileName;
switch (fId) {
case F_CVDBG_SIGN: return getSignature();
case F_CVDBG_GUID: return getGuidString();
case F_CVDBG_PDB: return pdb ? pdb : "";
}
return "";
}