void PE_Debug :: FindDebugInfo() { ClearDebugPtrs() ; // Put everything into a try/catch in case the file has wrong fields try { // Verify that fileBase is a valid pointer to a DOS header if( fileBase->e_magic == IMAGE_DOS_SIGNATURE ) { // Get a pointer to the PE header NT_Header = BasedPtr( PIMAGE_NT_HEADERS, fileBase, fileBase->e_lfanew ) ; // Verify that NT_Header is a valid pointer to a NT header if( NT_Header->Signature == IMAGE_NT_SIGNATURE ) { // Get a pointer to the debug header if any COFFDebugInfo = GetDebugHeader() ; // Get a pointer to the symbol table and retrieve the number of symbols if( NT_Header->FileHeader.PointerToSymbolTable ) COFFSymbolTable = BasedPtr( PIMAGE_SYMBOL, fileBase, NT_Header->FileHeader.PointerToSymbolTable ) ; COFFSymbolCount = NT_Header->FileHeader.NumberOfSymbols ; // The string table starts right after the symbol table stringTable = (const char*)(COFFSymbolTable + COFFSymbolCount) ; } } } catch( ... ) { // Header wrong, do nothing } }
void PE_Debug :: DumpLineNumber(std::ostream& dumpBuffer, DWORD relativeAddress ) { PIMAGE_LINENUMBER line = BasedPtr( PIMAGE_LINENUMBER, COFFDebugInfo, COFFDebugInfo->LvaToFirstLinenumber ) ; DWORD lineCount = COFFDebugInfo->NumberOfLinenumbers ; const DWORD none = (DWORD)-1 ; DWORD maxAddr = 0 ; DWORD lineNum = none ; for( DWORD i=0; i < lineCount; i++ ) { if( line->Linenumber != 0 ) // A regular line number { // look for line with bigger address <= relativeAddress if( line->Type.VirtualAddress <= relativeAddress && line->Type.VirtualAddress > maxAddr ) { maxAddr = line->Type.VirtualAddress ; lineNum = line->Linenumber ; } } line++ ; } if( lineNum != none ) { dumpBuffer << " line " << lineNum << "\n"; } }
void PE_Debug :: DumpLineNumber( DumpBuffer& dumpBuffer, DWORD relativeAddress ) { PIMAGE_LINENUMBER line = BasedPtr( PIMAGE_LINENUMBER, COFFDebugInfo, COFFDebugInfo->LvaToFirstLinenumber ) ; DWORD lineCount = COFFDebugInfo->NumberOfLinenumbers ; const DWORD none = (DWORD)-1 ; DWORD maxAddr = 0 ; DWORD lineNum = none ; for( DWORD i=0; i < lineCount; i++ ) { if( line->Linenumber != 0 ) // A regular line number { // look for line with bigger address <= relativeAddress if( line->Type.VirtualAddress <= relativeAddress && line->Type.VirtualAddress > maxAddr ) { maxAddr = line->Type.VirtualAddress ; lineNum = line->Linenumber ; } } line++ ; } if( lineNum != none ) { dumpBuffer.Printf( " line %d\r\n", lineNum ) ; if (Dump_to_log) { mprintf(( " line %d\r\n", lineNum )) ; } } // else // dumpBuffer.Printf( " line <unknown>\r\n" ) ; }
PIMAGE_COFF_SYMBOLS_HEADER PE_Debug :: GetDebugHeader() { // Some files have a wrong entry in the COFF header, so // first check if the debug info exists at all if( NT_Header->FileHeader.PointerToSymbolTable == 0 ) return( 0 ) ; DWORD debugDirRVA = NT_Header->OptionalHeader. DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ]. VirtualAddress; if( debugDirRVA == 0 ) return( 0 ) ; // The following values must be calculated differently for MS/Borland files PIMAGE_DEBUG_DIRECTORY debugDir ; DWORD size ; // Borland files have the debug directory at the beginning of a .debug section PIMAGE_SECTION_HEADER debugHeader = SectionHeaderFromName( ".debug" ) ; if( debugHeader && debugHeader->VirtualAddress == debugDirRVA ) { debugDir = (PIMAGE_DEBUG_DIRECTORY)(debugHeader->PointerToRawData + (DWORD)fileBase) ; size = NT_Header->OptionalHeader. DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ].Size * sizeof( IMAGE_DEBUG_DIRECTORY ) ; } else // Microsoft debug directory is in the .rdata section { debugHeader = SectionHeaderFromName( ".rdata" ) ; if( debugHeader == 0 ) return( 0 ) ; size = NT_Header->OptionalHeader. DataDirectory[ IMAGE_DIRECTORY_ENTRY_DEBUG ].Size ; DWORD offsetInto_rdata = debugDirRVA - debugHeader->VirtualAddress ; debugDir = BasedPtr( PIMAGE_DEBUG_DIRECTORY, fileBase, debugHeader->PointerToRawData + offsetInto_rdata ) ; } // look for COFF debug info DWORD debugFormats = size / sizeof( IMAGE_DEBUG_DIRECTORY ) ; for( DWORD i = 0; i < debugFormats; i++ ) { if( debugDir->Type == IMAGE_DEBUG_TYPE_COFF ) return( (PIMAGE_COFF_SYMBOLS_HEADER)((DWORD)fileBase + debugDir->PointerToRawData) ) ; else debugDir++ ; } return( NULL ) ; }