Changeset 263

Show
Ignore:
Timestamp:
10/13/06 12:35:30 (2 years ago)
Author:
AgentOrange
Message:

temporary update

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ddl/coff/COFF.d

    r187 r263  
    3939private import std.conv; 
    4040private import std.c.time; 
    41  
    42  
    43 extern (C) 
    44 
    45     void * memcpy (void *dst, void *src, uint); 
    46 }     
    47  
     41private import std.c.string; 
     42//  
     43//  
     44// extern (C) 
     45// { 
     46//  void * memcpy (void *dst, void *src, uint); 
     47// }     
     48//  
    4849 
    4950// PE-COFF constants 
  • trunk/ddl/coff/COFFBinary.d

    r205 r263  
    3434 
    3535import ddl.coff.COFF; 
    36 //import ddl.coff.COFFObject; 
     36import ddl.coff.COFFObject; 
    3737import ddl.coff.COFFWrite; 
    3838import ddl.coff.COFFLibrary; 
    39 //import ddl.coff.COFFImage; 
     39import ddl.coff.COFFImage; 
    4040import ddl.coff.cursor; 
    4141 
    4242import ddl.coff.cv4; 
     43import ddl.Utils; 
    4344//import ddl.coff.CodeView; 
    4445//import ddl.coff.DebugSymbol; 
     
    5051private import std.conv; 
    5152private import std.c.time; 
     53 
     54private import mango.io.model.IBuffer; 
     55private import mango.io.model.IConduit; 
    5256 
    5357// coff binary type 
     
    6973class COFFBinary 
    7074{ 
    71    public: 
    72    // state 
    73        debug static bit verbose = true;   // verbose output 
    74        else  static bit verbose = false;  // silent 
    75  
    76        COFF_TYPE coffType     = COFF_TYPE.UNKNOWN; 
    77  
    78        bit image      = false;            // image file or object file 
    79        bit resolved   = false;            // resolved fixups 
    80        char[] filename;                   // file name 
    81        char[] name;                       // object name 
    82  
    83    // final data 
    84        PublicSymbol[char[]]   publics;    // public symbols 
    85        ExternalSymbol[]       externs;    // external symbols 
    86        Fixup[]                fixups;     // internal fixups 
    87        COFFSection[]          sections;   // COFF sections 
     75public: 
     76// state 
     77    debug static bit verbose = true;  // verbose output 
     78    else  static bit verbose = false; // silent 
     79 
     80    COFF_TYPE coffType    = COFF_TYPE.UNKNOWN; 
     81 
     82    bit image         = false;            // image file or object file 
     83    bit resolved  = false;            // resolved fixups 
     84    char[] filename;                  // file name 
     85    char[] name;                      // object name 
     86 
     87    // final data 
     88    PublicSymbol[char[]]  publics;    // public symbols 
     89    ExternalSymbol[]      externs;    // external symbols 
     90    Fixup[]               fixups;     // internal fixups 
     91    COFFSection[]             sections;   // COFF sections 
    8892 
    8993//      FixupThread[4]      frameThreads; 
    9094//      FixupThread[4]      targetThreads; 
    91         EnumData            enumData;       // most recent enum data record 
    92         uint[char[]]        dependencies;   // extern index dependencies 
    93         Group[char[]]       groups;         // section groups 
    94  
    95     // COFF binary data 
    96         COFFHeader*         coff;           // COFF header 
    97 //      COFFSectionHeader[] sectionTable;   // COFF section table 
    98         COFFSymbolRecord[]  symbolTable;    // COFF symbol table 
    99         char[]              stringTable;    // COFF string table 
    100  
    101         COFFSymbol[uint]    symbols;        // symbols 
    102         Fixup[]             unresolvedFixups; 
    103  
    104     // properties 
    105  
    106         COFF_TYPE type()                    { return coffType;      } 
    107         COFF_TYPE type(COFF_TYPE t)         { return coffType = t;  } 
    108  
    109         ExternalSymbol[] getExterns()       { return externs;       } 
    110         PublicSymbol[char[]] getPublics()   { return publics;       } 
    111         Fixup[] getFixups()                 { return fixups;        } 
    112         COFFSection[] getSections()         { return sections;      } 
    113  
    114         bit isImage()           { return (coffType & COFF_TYPE.IMAGE) != 0;     } 
    115         bit isObject()          { return (coffType & COFF_TYPE.OBJECT) != 0;    } 
    116         bit isObj()             { return (coffType & COFF_TYPE.OBJ) != 0;       } 
    117         bit isLib()             { return (coffType & COFF_TYPE.LIB) != 0;       } 
    118         bit isDLL()             { return (coffType & COFF_TYPE.DLL) != 0;       } 
    119         bit isExe()             { return (coffType & COFF_TYPE.EXE) != 0;       } 
    120          
    121         char[] toString() 
    122         { 
    123             return format( "%s (%s)", name, filename ); 
    124         } 
    125  
    126     // lookup string table 
    127         char[] findString( int nOffset ) 
    128         { 
    129             // verify state 
    130             assert( stringTable.length ); 
    131             assert( nOffset >= 4 ); 
    132             assert( nOffset < stringTable.length ); 
    133             if( nOffset >= stringTable.length ) 
    134                 return null; 
    135  
    136             // copy name 
    137             return std.string.toString( cast(char*) stringTable.ptr + nOffset ).dup; 
    138         } 
    139  
    140     // utils 
    141  
    142         void writeSections() 
    143         { 
    144             // parse each section 
    145             writefln( "\n\tCOFF SECTIONS: ", sections.length ); 
    146             if( verbose ) foreach( int nIndex, COFFSection it; sections ) 
    147             { 
    148                 writeCOFF( it ); 
    149             } 
    150         } 
     95    EnumData            enumData;       // most recent enum data record 
     96    uint[char[]]        dependencies;   // extern index dependencies 
     97    Group[char[]]       groups;         // section groups 
     98 
     99// COFF binary data 
     100    COFFHeader*         coff;           // COFF header 
     101    COFFSymbolRecord[]  symbolTable;    // COFF symbol table 
     102    char[]              stringTable;    // COFF string table 
     103 
     104    COFFSymbol[uint]    symbols;        // symbols 
     105    Fixup[]             unresolvedFixups; 
     106 
     107// properties 
     108 
     109    public char[] getName() { return name; } 
     110 
     111    COFF_TYPE type()                    { return coffType;          } 
     112    COFF_TYPE type(COFF_TYPE t)         { return coffType = t;      } 
     113 
     114    ExternalSymbol[] getExterns()       { return externs;           } 
     115    PublicSymbol[char[]] getPublics()   { return publics;           } 
     116    Fixup[] getFixups()                 { return fixups;            } 
     117 
     118    int getSectionCount()               { return sections.length;   } 
     119    COFFSection[] getSections()         { return sections;          } 
     120    COFFSection getSection(int i)    
     121    {  
     122        if( i >= sections.length ) 
     123            throw new Exception( "COFFBinary.getSection: invalid section number " ); //~ .toString(i) ); 
     124        return sections[i]; 
     125    } 
     126 
     127    bit isImage()           { return (coffType & COFF_TYPE.IMAGE) != 0;     } 
     128    bit isObject()          { return (coffType & COFF_TYPE.OBJECT) != 0;    } 
     129    bit isObj()             { return (coffType & COFF_TYPE.OBJ) != 0;       } 
     130    bit isLib()             { return (coffType & COFF_TYPE.LIB) != 0;       } 
     131    bit isDLL()             { return (coffType & COFF_TYPE.DLL) != 0;       } 
     132    bit isExe()             { return (coffType & COFF_TYPE.EXE) != 0;       } 
    151133     
     134    char[] toString() 
     135    { 
     136        return format( "%s (%s)", name, filename ); 
     137    } 
     138 
     139// lookup string table 
     140    char[] findString( int nOffset ) 
     141    { 
     142        // verify state 
     143        assert( stringTable.length ); 
     144        assert( nOffset >= 4 ); 
     145        assert( nOffset < stringTable.length ); 
     146        if( nOffset >= stringTable.length ) 
     147            return null; 
     148 
     149        // copy name 
     150        return std.string.toString( cast(char*) stringTable.ptr + nOffset ).dup; 
     151    } 
     152 
     153// utils 
     154 
     155    void writeSections() 
     156    { 
     157        // write out each section 
     158        writefln( "\n\tCOFF SECTIONS: ", sections.length ); 
     159        if( verbose ) foreach( int nIndex, COFFSection it; sections ) 
     160        { 
     161            writeCOFF( it ); 
     162        } 
     163    } 
     164 
    152165    // fixups 
    153166    public void fixDependency(char[] name,void* address) 
     
    161174    } 
    162175 
    163     protected void resolveInternals(){   
     176    protected void resolveInternals() 
     177    {    
    164178        // create addresses for all of the public symbols        
    165         foreach(inout PublicSymbol pub; this.publics){ 
     179        foreach(inout PublicSymbol pub; this.publics) 
     180        { 
    166181            debug debugLog("resolve: %s segindex: %d offset: %d\n",pub.name,pub.segmentIndex,pub.offset); 
    167             if(pub.segmentIndex == 0){ 
     182            if(pub.segmentIndex == 0) 
     183            { 
    168184                pub.address = cast(void*)pub.offset; //HACK: treat as absolute address 
    169185                debug debugLog("fixed: %s == 0\n",pub.name); 
    170186            } 
    171             else{    
     187            else 
     188            { 
    172189                //TODO: refactor using .getData(uint ofs) to provide a point for group-based addressing 
    173               pub.address = this.segments[pub.segmentIndex].getData(this.segments,pub.offset); 
     190//!!!             pub.address = this.segments[pub.segmentIndex].getData(this.segments,pub.offset); 
    174191                //pub.address = &this.segments[pub.segmentIndex].data[pub.offset]; 
    175192            } 
    176193        } 
    177      
     194 
    178195        // go through all the external records, and resolve them to PublicSymbols and Dependencies 
    179         for(uint extIdx=1; extIdx<this.externs.length; extIdx++){ 
     196        for(uint extIdx=1; extIdx<this.externs.length; extIdx++) 
     197        { 
    180198            ExternalSymbol* ext = &(this.externs[extIdx]); 
    181199             
    182200        //  if(ext.isResolved) continue; // skip any externals that are already resolved     
    183201             
    184             if(!ext.isResolved){ 
    185                 if(ext.name in this.publics){ 
     202            if(!ext.isResolved) 
     203            { 
     204                if(ext.name in this.publics) 
     205                { 
    186206                    PublicSymbol* pub = &(this.publics[ext.name]); 
    187207                //  ext.segmentIndex = pub.segmentIndex; 
    188208                //  ext.offset = pub.offset; 
    189209                    ext.address = pub.address; 
    190                   ext.isResolved = true; 
     210//!                   ext.isResolved = true; 
    191211                     
    192212                    debug debugLog("extern %s found as public %0.8X",ext.name,pub.address); 
    193213                } 
    194                 else{ 
    195                     this.dependencies[ext.name] ~= extIdx; 
     214                else 
     215                { 
     216                    this.dependencies[ext.name] = extIdx; 
    196217                } 
    197218            } 
    198219        } 
    199220    }    
    200  
     221     
     222    // parse a coff header 
     223     
    201224} 
    202225 
     
    224247    char[]  description;                // section description 
    225248    ubyte[] data;                       // section data 
    226  
     249     
    227250    COFFRelocationRecord[]  relocs;     // relocations 
    228251    COFFLineRecord[]        lines;      // line numbers 
     
    341364    uint    offset; 
    342365    void*   address; 
     366    uint    segmentIndex; 
    343367 
    344368    bit isResolved()    { return address != null; } 
     
    403427{ 
    404428    char[] ext = filename[$-4..$]; 
    405 //TODO: obsoltete thanks to ArchiveLoader 
    406 /*  if( ext == ".lib" ) 
    407     { 
    408         // load library format 
    409         COFFLibrary lib = new COFFLibrary; 
    410         //lib.verbose = verbose; 
    411         lib.loadFromFile( filename ); 
    412         return null; 
    413 //      return lib; 
    414     } 
    415     else*/ if( ext == ".obj" ) 
     429     
     430    if( ext == ".obj" ) 
    416431    { 
    417432        // load object format 
    418433        COFFObject obj = new COFFObject; 
    419434        obj.verbose = verbose; 
    420       obj.loadFromFile( filename ); 
     435//!       obj.loadFromFile( filename ); 
    421436        return obj; 
    422437    } 
    423438    else if( ext == ".exe" || ext == ".dll" ) 
    424439    {    
    425 //      writefln( "FILE TYPE: " ~ ( ( ext == ".exe" ) ? "PE Executable Module" : "PE DLL Module" )  ); 
     440        // load module format 
    426441        COFFImage mod = new COFFImage; 
    427442        mod.verbose = verbose; 
    428       mod.loadFromFile( filename ); 
     443//!       mod.loadFromFile( filename ); 
    429444        return mod; 
    430445    } 
    431446    return null; 
    432447} 
     448 
     449 
     450/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
     451// coff parsing helpers 
     452/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
     453 
     454COFFHeader* parseCOFFHeader( File file ) 
     455{ 
     456    COFFHeader* coff = new COFFHeader; 
     457    if( file.readBlock( coff, COFFHeader.sizeof ) != COFFHeader.sizeof ) 
     458    { 
     459        delete coff; 
     460        writefln( "PE module failed to read coff header"); 
     461        return null; 
     462    } 
     463 
     464    // check machine code 
     465//  if( coff.machine != 0x14C ) 
     466//      writefln( "warning: file is not for IA32 Platform!\n" ); 
     467 
     468    return coff; 
     469} 
     470 
  • trunk/ddl/coff/COFFImage.d

    <
    r205 r263  
    3333module ddl.coff.COFFImage; 
    3434 
    35 private import ddl.ExportSymbol; 
    36 private import ddl.Utils; 
    37  
    38 private import ddl.coff.COFFBinary; 
    39  
    40 private import std.string; 
    41 private import std.stdio; 
    42 private import std.c.time; 
    43 private import std.stream; 
    44  
     35import ddl.ExportSymbol; 
     36import ddl.Utils; 
     37 
     38import ddl.coff.COFF; 
     39import ddl.coff.COFFWrite; 
     40import ddl.coff.COFFBinary; 
     41 
     42import std.string; 
     43import std.stdio; 
     44import std.c.time; 
     45import std.stream; 
     46import std.c.string; 
     47 
     48import ddl.coff.CodeView; 
     49 
     50enum DEBUGTYPE 
     51
     52    Unknown, 
     53    None, 
     54    Codeview 
     55
     56 
     57class DebugData 
     58
     59
    4560 
    4661// COFF PE Image Module - DLL or EXE 
    4762class COFFImage : COFFBinary 
    4863{ 
    49    public: 
    50        // module identity 
    51        char[]                 moduleFile;     // name of module file 
    52        char[]                 internal_name;  // for DLLs, how it was called at compile time 
    53        char[]                 debug_name;     // When there was a MISC debug info section 
    54        bit                        valid = false; 
    55  
    56        // file info elements 
    57        uint                   peoffset;       // offset of PE header in file 
    58        bit                        peplus;         // PE32 (false) or PE32+ (true) header 
    59  
    60        PEHeader*              pe;             // pointer to PE32/PE32+ Header 
    61        PEWindowsHeader*       winpe;          // Windows specific PE32/PE32+ header 
    62        PEDataDirectories*     datadir;        // Data Directory Tables 
    63  
    64 ////  CodeViewData            codeView;       // codeview debug data 
     64public: 
     65    // module identity 
     66    char[]                    moduleFile;     // name of module file 
     67    char[]                    internal_name;  // for DLLs, how it was called at compile time 
     68    char[]                    debug_name;     // When there was a MISC debug info section 
     69    bit                       valid = false; 
     70 
     71    // file info elements 
     72    uint                  peoffset;       // offset of PE header in file 
     73    bit                       peplus;         // PE32 (false) or PE32+ (true) header 
     74 
     75    PEHeader*             pe;             // pointer to PE32/PE32+ Header 
     76    PEWindowsHeader*      winpe;          // Windows specific PE32/PE32+ header 
     77    PEDataDirectories*        datadir;        // Data Directory Tables 
     78 
     79  CodeViewData            codeView;       // codeview debug data 
    6580//      SymbolManager           symbolManager; 
    6681 
    67         // export/import data 
    68         COFFExport*[]           exports;    // the exported functions of this module if any 
    69         PEcoff_import[]         imports;    // the imported modules and their functions if any 
    70  
    71         // loaded image base 
    72         uint                    imageBase; 
    73  
    74         this() 
    75         { 
    76             type = COFF_TYPE.IMAGE; 
    77         } 
     82    // export/import data 
     83    COFFExport*[]           exports;    // the exported functions of this module if any 
     84    PEcoff_import[]         imports;    // the imported modules and their functions if any 
     85 
     86    // loaded image base 
     87    uint                    imageBase; 
     88     
     89    // debug data 
     90    DEBUGTYPE debugType; 
     91    byte[] debugData; 
     92 
     93    this() 
     94    { 
     95        type = COFF_TYPE.IMAGE; 
     96    } 
    7897/* 
    79        this( DataCursor cur, char[] filename ) 
    80        
    81            type = COFF_TYPE.IMAGE; 
    82            moduleFile = filename; 
    83            valid = loadFromFile( filename ); 
    84        
     98    this( DataCursor cur, char[] filename ) 
     99   
     100        type = COFF_TYPE.IMAGE; 
     101        moduleFile = filename; 
     102        valid = loadFromFile( filename ); 
     103   
    85104*/ 
    86     // load from file 
    87         bit loadFromFile( char[] filename ) 
    88         { 
    89             moduleFile  = filename; 
    90             valid       = false; 
    91  
    92             // print debug output 
    93             if( verbose ) writefln( "File: %s\nFile type: PECOFF MODULE\n", filename ); 
    94  
    95             // open & parse the file 
    96             File file = new File(filename); 
    97             if( !file.isOpen ) 
    98             { 
    99                 writefln( "unable to open file: ", filename ); 
    100                 return false; 
    101             } 
    102  
    103             // catch read exceptions 
    104             try 
    105             { 
    106                 valid = parse( file ); 
    107             } 
    108             catch( ReadException e ) 
    109             { 
    110                 writefln( "read exception: " ~ e.toString ); 
    111             } 
    112  
    113             // close the file 
    114             file.close(); 
    115             return valid; 
    116         } 
    117  
    118     private: 
    119  
    120     // parse pe module header 
    121         bit parse( File file ) 
    122         { 
    123             // parse dos header 
    124             if( !parseDOSHeader( file ) ) 
     105// load from file 
     106    bit loadFromFile( char[] filename ) 
     107    { 
     108        moduleFile  = filename; 
     109        valid       = false; 
     110 
     111        // print debug output 
     112        if( verbose ) writefln( "File: %s\nFile type: PECOFF MODULE\n", filename ); 
     113 
     114        // open & parse the file 
     115        File file = new File(filename); 
     116        if( !file.isOpen ) 
     117        { 
     118            writefln( "unable to open file: ", filename ); 
     119            return false; 
     120        } 
     121 
     122        // catch read exceptions 
     123        try 
     124        { 
     125            valid = parse( file ); 
     126        } 
     127        catch( ReadException e ) 
     128        { 
     129            writefln( "read exception: " ~ e.toString ); 
     130        } 
     131 
     132        // close the file 
     133        file.close(); 
     134        return valid; 
     135    } 
     136     
     137//  bit parse( COFFReader reader ) 
     138//  { 
     139//      if( !parseDOSHeader( reader ) ) 
     140//          return false; 
     141//      return true; 
     142//  } 
     143 
     144    /* 
     145        parse pe module header 
     146    */ 
     147 
     148    bit parse( File file ) 
     149    { 
     150        // parse dos header 
     151        if( !parseDOSHeader( file ) ) 
     152            return false; 
     153 
     154        // parse COFF header 
     155        if( ( coff = parseCOFFHeader( file ) ) == null ) 
     156            return false; 
     157 
     158        if( verbose ) writeCOFF( coff ); 
     159 
     160        // parse PE header 
     161        if( !parsePE32Header( file ) ) 
     162            return false; 
     163 
     164        // parse sections 
     165        if( !parseSectionHeaders( file ) ) 
     166            return false; 
     167 
     168        // parse debug data 
     169        if( !parseDebugData( file ) ) 
     170            return false; 
     171 
     172 
     173        /*  
     174            populate imports & exports from file module 
     175        */ 
     176 
     177        // populate exports 
     178        if( !parseExports( file ) ) 
     179            return false; 
     180 
     181        // populate imports 
     182//      if( !parseImports( file ) ) 
     183//          return false; 
     184//  
     185        /* 
     186            load codeview debug data 
     187        */ 
     188        if( debugType == DEBUGTYPE.Codeview ) 
     189        { 
     190        } 
     191 
     192        return true; 
     193    } 
     194 
     195// check debug data 
     196    bit parseDebugData( File file ) 
     197    { 
     198        // check image for debug directory 
     199        if( datadir.Debug.RVA == 0 ) 
     200        { 
     201            debugType = DEBUGTYPE.None; 
     202            writefln( "Image has no debug information\n"); 
     203            return true; 
     204        } 
     205 
     206        // calculate file offset from data directory RVA 
     207        uint debug_dir = RVA2Offset( datadir.Debug.RVA ); 
     208        uint dircnt = datadir.Debug.Size / COFFImageDebugDirectory.sizeof; 
     209        debug writefln( "Found %d debug director%s at file position 0x%X\n",dircnt,dircnt==1?"y":"ies",debug_dir); 
     210         
     211        // can only handle 1 debug directory right now 
     212        assert( dircnt == 1, "unable to handle multiple debug directories yet" ); 
     213 
     214        debugData = null; 
     215        // read debug directories 
     216        for( uint currentdir = 0; currentdir < dircnt; currentdir++ ) 
     217        { 
     218            COFFImageDebugDirectory dir; 
     219            file.position = debug_dir + (currentdir*COFFImageDebugDirectory.sizeof); 
     220            if( file.readBlock( &dir, COFFImageDebugDirectory.sizeof ) != COFFImageDebugDirectory.sizeof ) 
     221            { 
     222                writefln( "ReadDebug(): Failed to read Debug directory with %d left\n",dircnt); 
    125223                return false; 
    126  
    127             // parse COFF header 
    128             if( ( coff = parseCOFFHeader( file ) ) == null ) 
     224            } 
     225             
     226            if( verbose ) writefln( 
     227                "\n\tDEBUG DIRECTORY #%d\n" 
     228                "\t\tType: %s\n" 
     229                "\t\tCharacteristics: %08X\n" 
     230                "\t\tTimeDateStamp: %s %d\n" 
     231                "\t\tVersion: %s.%s\n" 
     232                "\t\tSize of Data: %d\n" 
     233                "\t\tAddress of Raw Data: %08X\n" 
     234                "\t\tPointer to Raw Data: %08X\n", 
     235                currentdir+1, 
     236                DEBUG_TYPE_NAME(dir.Type), 
     237                dir.Characteristics, 
     238                strip(std.string.toString( ctime( cast(time_t*)&(dir.TimeDateStamp)))), dir.TimeDateStamp, 
     239                dir.MajorVersion, dir.MinorVersion, 
     240                dir.SizeOfData, 
     241                dir.AddressOfRawData, 
     242                dir.PointerToRawData ); 
     243 
     244            // verify size is nonzero 
     245            assert(dir.SizeOfData && dir.PointerToRawData, "invalid debug data" ); 
     246            if( dir.SizeOfData == 0 || dir.PointerToRawData == 0 )  
     247            { 
     248                writefln("invalid debug data"); 
     249                return false; 
     250            } 
     251 
     252            // move file to debug data 
     253            file.position = dir.PointerToRawData; 
     254 
     255            // read directory data 
     256            debugType = DEBUGTYPE.Unknown; 
     257            debugData.length = dir.SizeOfData; 
     258            if( file.readBlock( debugData.ptr, debugData.length ) != debugData.length ) 
     259            { 
     260                writefln( "failure reading debug data" ); 
     261                return false; 
     262            } 
     263             
     264            // reset pointer back to debug data and parse 
     265            file.position = dir.PointerToRawData; 
     266             
     267            // process debug data 
     268            switch( dir.Type ) 
     269            { 
     270                case IMAGE_DEBUG_TYPE_COFF: 
     271                    if( verbose ) writefln( "Debug type: COFF" ); 
     272//                      writefln( "debug info type: \n", DEBUG_TYPE_NAME(dir.Type) ); 
     273//                      readDebug_COFF(dir.PointerToRawData); 
     274                    break; 
     275                 
     276                case IMAGE_DEBUG_TYPE_CODEVIEW: 
     277                    if( verbose ) writefln( "Debug type: CodeView" ); 
     278                    // set debug type 
     279                    debugType = DEBUGTYPE.Codeview; 
     280 
     281                    // parse codeview data 
     282                    codeView = new CodeViewData; 
     283                    codeView.verbose = verbose; 
     284                    if( !codeView.parse( this, file) ) 
     285                    { 
     286                        writefln( "codeview parsing failed" ); 
     287                        return false; 
     288                    } 
     289                    else 
     290                    { 
     291                        int i = 0; 
     292                    // create symbols 
     293            //      symbolManager = new SymbolManager; 
     294            //      symbolManager.parse( codeView ); 
     295                    } 
     296 
     297                    break; 
     298 
     299                case IMAGE_DEBUG_TYPE_FPO: 
     300                    if( verbose ) writefln( "Debug type: Frame pointer offset" ); 
     301//                      readDebug_FPO(dir.PointerToRawData); 
     302                    break; 
     303                 
     304                case IMAGE_DEBUG_TYPE_MISC: 
     305                    if( verbose ) writefln( "Debug type: Misc" ); 
     306//                      readDebug_Misc(dir.PointerToRawData); 
     307                    break; 
     308                 
     309                default: 
     310                    writefln( "Don't know how to process %s debug information\n", DEBUG_TYPE_NAME(dir.Type)); 
     311                    break; 
     312            } 
     313 
     314            // next debug directory 
     315        } 
     316 
     317        return true; 
     318    } 
     319 
     320// populate import & export information 
     321    const uint IMAGE_SECOND_HEADER_OFFSET   = 0x3C; 
     322 
     323    // read & verify DOS header 
     324    bit parseDOSHeader(File file) 
     325    { 
     326        ushort  signature; 
     327        ushort  ssv; 
     328        uint    pe_sig; 
     329 
     330        // read signature 
     331        file.position = 0; 
     332        file.read( signature ); 
     333 
     334        // verify signature 
     335        if( signature != IMAGE_DOS_SIGNATURE ) 
     336        { 
     337            writefln( "module has invalid DOS signature %04X\n",signature); 
     338            return false; 
     339        } 
     340 
     341        // read ssv 
     342        file.seekSet( 0x18 ); 
     343        file.read( ssv ); 
     344 
     345        // verify ssv 
     346        if( ssv < 0x40 ) 
     347        { 
     348            writefln( "module does not appear to be a Windows file\n"); 
     349            return false; 
     350        } 
     351 
     352        // read pefile offset 
     353        file.seekSet( IMAGE_SECOND_HEADER_OFFSET ); 
     354        file.read( peoffset ); 
     355        if( verbose ) writefln( "\tPE header offset = 0x%08X", peoffset ); 
     356 
     357        // read pe signature 
     358        file.seekSet( peoffset ); 
     359        file.read( pe_sig ); 
     360        if( verbose ) writefln( "\tPE signature = 0x%X", pe_sig ); 
     361 
     362        // verify NT signature 
     363        if( pe_sig != IMAGE_NT_SIGNATURE ) 
     364        { 
     365            writefln( "invalid PE signature 0x%08X\n",pe_sig); 
     366            return false; 
     367        } 
     368 
     369        return true; 
     370    } 
     371//const uint IMAGE_BASE_OFFSET             = 13 * uint.sizeof; 
     372 
     373    bit parsePE32Header( File file ) 
     374    { 
     375        assert( coff !is null ); 
     376        PEPlusHeader p; 
     377        uint base; 
     378        uint size_remaining; 
     379 
     380        // verify optional header size 
     381        if( p.sizeof > coff.SizeOfOptionalHeader ) 
     382        { 
     383            writefln( "PE Module COFF SizeOfOptionalHeader is too small\n"); 
     384            return false; 
     385        } 
     386        size_remaining = coff.SizeOfOptionalHeader; 
     387 
     388        // read PE+ header 
     389        if( file.readBlock( &p, p.sizeof ) != p.sizeof ) 
     390        { 
     391            writefln( "failed to read PE32 header\n"); 
     392            return false; 
     393        } 
     394        size_remaining -= p.sizeof; 
     395 
     396        // check magic value 
     397        if( p.Magic == PECOFF_MAGIC_PE ) 
     398        { 
     399            // setup PE32 header 
     400            peplus  = false; 
     401            pe      = new PEHeader; 
     402            memcpy( pe, &p, p.sizeof ); 
     403 
     404            // read the extra header value 
     405            file.read( pe.BaseOfData ); 
     406            size_remaining -= base.sizeof; 
     407 
     408            // debug print 
     409//              if( verbose ) writeCOFF( cast(PEHeader*) pe ); 
     410        } 
     411        else if( p.Magic == PECOFF_MAGIC_PEPLUS ) 
     412        { 
     413            // setup PE32+ header 
     414            peplus  = true; 
     415            pe      = cast(PEHeader*) new PEPlusHeader; 
     416            memcpy( pe, &p, p.sizeof ); 
     417        } 
     418        else 
     419        { 
     420            // invalid magic number 
     421            writefln( "illegal PE32 header magic: %08X\n",p.Magic); 
     422            return false; 
     423        } 
     424 
     425        // write header values 
     426        if( verbose ) 
     427        { 
     428            if( peplus ) 
     429                writeCOFF( cast(PEPlusHeader*) pe ); 
     430            else 
     431                writeCOFF( cast(PEHeader*) pe ); 
     432        } 
     433 
     434        // read the windows specific PE32 header 
     435        if( !peplus ) 
     436        { 
     437            // verify size 
     438            if( size_remaining < PEWindowsHeader.sizeof ) 
     439            { 
     440                writefln( "COFF SizeOfOptionalHeader is too small for Windows specific header"); 
    129441                return false; 
    130  
    131             if( verbose ) writeCOFF( coff ); 
    132  
    133             // parse PE header 
    134             if( !parsePE32Header( file ) ) 
     442            } 
     443 
     444            winpe = new PEWindowsHeader; 
     445            if( file.readBlock( winpe, PEWindowsHeader.sizeof ) != PEWindowsHeader.sizeof ) 
     446            { 
     447                writefln( "failed to read PE32 windows header"); 
    135448                return false; 
    136  
    137             // parse sections 
    138             if( !parseSectionHeaders( file ) ) 
     449            } 
     450 
     451            size_remaining -= PEWindowsHeader.sizeof; 
     452        } 
     453        else 
     454        { 
     455            // PE32+ 
     456            if( size_remaining < PEPlusWindowsHeader.sizeof ) 
     457            { 
     458                writefln( "COFF SizeOfOptionalHeader is too small for Windows specific header"); 
    139459                return false; 
    140  
    141             // parse debug data 
    142             if( !parseDebugData( file ) ) 
     460            } 
     461 
     462            winpe = cast(PEWindowsHeader*) new PEPlusWindowsHeader; 
     463            if( file.readBlock( winpe, PEPlusWindowsHeader.sizeof ) != PEPlusWindowsHeader.sizeof ) 
     464            { 
     465                writefln( "failed to read PE32 windows header"); 
    143466                return false; 
    144  
    145  
    146         // populate imports & exports from file module 
    147             // populate exports 
    148             if( !parseExports( file ) ) 
     467            } 
     468            size_remaining -= PEPlusWindowsHeader.sizeof; 
     469        } 
     470 
     471        // debug print 
     472        if( verbose ) writeCOFF( winpe ); 
     473// 
     474        // read data directory tables 
     475        uint dataSize = winpe.NumberOfRVAAndSizes * PEDataDirectory.sizeof; 
     476        if( size_remaining < dataSize ) 
     477        { 
     478            writefln( "COFF SizeOfOptionalHeader is too small for data directories"); 
     479            return false; 
     480        } 
     481 
     482//          writefln( winpe.NumberOfRVAAndSizes * PEDataDirectory.sizeof ); 
     483        datadir = new PEDataDirectories; 
     484        if( file.readBlock( datadir, dataSize ) != dataSize ) 
     485        { 
     486            writefln( "failed to read PE32 data directories\n"); 
     487            return false; 
     488        } 
     489 
     490        // debug print 
     491        if( verbose ) writeCOFF( datadir ); 
     492 
     493        imageBase = winpe.ImageBase; 
     494        return true; 
     495    } 
     496 
     497    bit parseSectionHeaders( File file ) 
     498    { 
     499        uint                inVal; 
     500        char[]              tName; 
     501//          COFFSectionHeader*  s; 
     502 
     503        // read section headers 
     504        COFFSectionHeader[] sectionTable; 
     505        sectionTable.length = coff.NumberOfSections; 
     506        if( file.readBlock( sectionTable.ptr, sectionTable.length * COFFSectionHeader.sizeof ) != sectionTable.length * COFFSectionHeader.sizeof ) 
     507            return false; 
     508 
     509//          COFFSection sect = parseCOFFSectionHeader( COFFSectionHeader* s, file ); 
     510        uint i=0; 
     511        while( i < coff.NumberOfSections ) 
     512        { 
     513            COFFSection sect = parseCOFFSectionHeader( &sectionTable[i], file ); 
     514 
     515            /* 
     516            s = new COFFSectionHeader; 
     517            if( !.ReadFile( fh, s, COFFSectionHeader.sizeof, &inVal, null ) ) 
     518            { 
     519                writefln( "ReadSectionHeaders(): failed to read section header %d",i); 
    149520                return false; 
    150  
    151             // populate imports 
    152 //          if( !parseImports( file ) ) 
    153 //              return false; 
    154  
     521            } 
     522            */ 
     523 
     524            sect.index = i++; 
     525            sections ~= sect; 
     526//          i++; 
     527        } 
     528 
     529        if( verbose ) writeSections(); 
     530        /* 
     531//          for( it=section.begin(); it < section.end(); it++) 
     532        foreach( COFFSectionHeader it; sectionTable ) 
     533        { 
     534            tName = .toString(cast(char*)it.Name.ptr); 
     535//!             memcpy(tName,&(it.Name),sizeof(it.Name)); 
     536            writefln( 
     537                "\tSection info:\n" 
     538                "\t\tName: %s\n" 
     539                "\t\tVirtual Size: 0x%X\n" 
     540                "\t\tVirtual Address: 0x%08X\n" 
     541                "\t\tSize of Raw Data: %d\n" 
     542                "\t\tPointer to Raw Data: 0x%08X\n" 
     543                "\t\tPointer to Relocations: 0x%08X\n" 
     544                "\t\tPointer to Line numbers: 0x%08X\n" 
     545                "\t\tNumber of Relocations: %d\n" 
     546                "\t\tNumber of Line numbers: %d\n" 
     547                "\t\tCharacteristics: %08X\n", 
     548                tName, 
     549                it.VirtualSize, 
     550                it.VirtualAddress, 
     551                it.SizeOfRawData, 
     552                it.PointerToRawData, 
     553                it.PointerToRelocations, 
     554                it.PointerToLineNumbers, 
     555                it.NumberOfRelocations, 
     556                it.NumberOfLineNumbers, 
     557                it.Characteristics); 
     558        } 
     559        */ 
     560 
     561        return true; 
     562    } 
     563 
     564// pe-coff exports 
     565    bit parseExports( File file ) 
     566    { 
     567        // skip empty export directories 
     568        if( datadir.Export.RVA == 0 ) 
     569        { 
     570