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 ) ;
}