Changeset 263
- Timestamp:
- 10/13/06 12:35:30 (2 years ago)
- Files:
-
- trunk/ddl/coff/COFF.d (modified) (1 diff)
- trunk/ddl/coff/COFFBinary.d (modified) (7 diffs)
- trunk/ddl/coff/COFFImage.d (modified) (1 diff)
- trunk/ddl/coff/COFFLibrary.d (modified) (2 diffs)
- trunk/ddl/coff/COFFLoader.d (modified) (1 diff)
- trunk/ddl/coff/COFFModule.d (modified) (7 diffs)
- trunk/ddl/coff/COFFObject.d (modified) (10 diffs)
- trunk/ddl/coff/COFFWrite.d (modified) (1 diff)
- trunk/ddl/coff/CodeView.d (modified) (3 diffs)
- trunk/ddl/coff/DebugSymbol.d (modified) (1 diff)
- trunk/ddl/coff/cursor.d (modified) (2 diffs)
- trunk/ddl/coff/cv4.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ddl/coff/COFF.d
r187 r263 39 39 private import std.conv; 40 40 private import std.c.time; 41 42 43 extern (C) 44 { 45 void * memcpy (void *dst, void *src, uint); 46 } 47 41 private import std.c.string; 42 // 43 // 44 // extern (C) 45 // { 46 // void * memcpy (void *dst, void *src, uint); 47 // } 48 // 48 49 49 50 // PE-COFF constants trunk/ddl/coff/COFFBinary.d
r205 r263 34 34 35 35 import ddl.coff.COFF; 36 //import ddl.coff.COFFObject;36 import ddl.coff.COFFObject; 37 37 import ddl.coff.COFFWrite; 38 38 import ddl.coff.COFFLibrary; 39 //import ddl.coff.COFFImage;39 import ddl.coff.COFFImage; 40 40 import ddl.coff.cursor; 41 41 42 42 import ddl.coff.cv4; 43 import ddl.Utils; 43 44 //import ddl.coff.CodeView; 44 45 //import ddl.coff.DebugSymbol; … … 50 51 private import std.conv; 51 52 private import std.c.time; 53 54 private import mango.io.model.IBuffer; 55 private import mango.io.model.IConduit; 52 56 53 57 // coff binary type … … 69 73 class COFFBinary 70 74 { 71 public:72 // state73 debug static bit verbose = true; // verbose output74 else static bit verbose = false; // silent75 76 COFF_TYPE coffType = COFF_TYPE.UNKNOWN;77 78 bit image = false; // image file or object file79 bit resolved = false; // resolved fixups80 char[] filename; // file name81 char[] name; // object name82 83 // final data84 PublicSymbol[char[]] publics; // public symbols85 ExternalSymbol[] externs; // external symbols86 Fixup[] fixups; // internal fixups87 COFFSection[] sections; // COFF sections75 public: 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 88 92 89 93 // FixupThread[4] frameThreads; 90 94 // 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; } 151 133 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 152 165 // fixups 153 166 public void fixDependency(char[] name,void* address) … … 161 174 } 162 175 163 protected void resolveInternals(){ 176 protected void resolveInternals() 177 { 164 178 // create addresses for all of the public symbols 165 foreach(inout PublicSymbol pub; this.publics){ 179 foreach(inout PublicSymbol pub; this.publics) 180 { 166 181 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 { 168 184 pub.address = cast(void*)pub.offset; //HACK: treat as absolute address 169 185 debug debugLog("fixed: %s == 0\n",pub.name); 170 186 } 171 else{ 187 else 188 { 172 189 //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); 174 191 //pub.address = &this.segments[pub.segmentIndex].data[pub.offset]; 175 192 } 176 193 } 177 194 178 195 // 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 { 180 198 ExternalSymbol* ext = &(this.externs[extIdx]); 181 199 182 200 // if(ext.isResolved) continue; // skip any externals that are already resolved 183 201 184 if(!ext.isResolved){ 185 if(ext.name in this.publics){ 202 if(!ext.isResolved) 203 { 204 if(ext.name in this.publics) 205 { 186 206 PublicSymbol* pub = &(this.publics[ext.name]); 187 207 // ext.segmentIndex = pub.segmentIndex; 188 208 // ext.offset = pub.offset; 189 209 ext.address = pub.address; 190 ext.isResolved = true;210 //! ext.isResolved = true; 191 211 192 212 debug debugLog("extern %s found as public %0.8X",ext.name,pub.address); 193 213 } 194 else{ 195 this.dependencies[ext.name] ~= extIdx; 214 else 215 { 216 this.dependencies[ext.name] = extIdx; 196 217 } 197 218 } 198 219 } 199 220 } 200 221 222 // parse a coff header 223 201 224 } 202 225 … … 224 247 char[] description; // section description 225 248 ubyte[] data; // section data 226 249 227 250 COFFRelocationRecord[] relocs; // relocations 228 251 COFFLineRecord[] lines; // line numbers … … 341 364 uint offset; 342 365 void* address; 366 uint segmentIndex; 343 367 344 368 bit isResolved() { return address != null; } … … 403 427 { 404 428 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" ) 416 431 { 417 432 // load object format 418 433 COFFObject obj = new COFFObject; 419 434 obj.verbose = verbose; 420 obj.loadFromFile( filename );435 //! obj.loadFromFile( filename ); 421 436 return obj; 422 437 } 423 438 else if( ext == ".exe" || ext == ".dll" ) 424 439 { 425 // writefln( "FILE TYPE: " ~ ( ( ext == ".exe" ) ? "PE Executable Module" : "PE DLL Module" ) ); 440 // load module format 426 441 COFFImage mod = new COFFImage; 427 442 mod.verbose = verbose; 428 mod.loadFromFile( filename );443 //! mod.loadFromFile( filename ); 429 444 return mod; 430 445 } 431 446 return null; 432 447 } 448 449 450 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 451 // coff parsing helpers 452 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 453 454 COFFHeader* 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 33 33 module ddl.coff.COFFImage; 34 34 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 35 import ddl.ExportSymbol; 36 import ddl.Utils; 37 38 import ddl.coff.COFF; 39 import ddl.coff.COFFWrite; 40 import ddl.coff.COFFBinary; 41 42 import std.string; 43 import std.stdio; 44 import std.c.time; 45 import std.stream; 46 import std.c.string; 47 48 import ddl.coff.CodeView; 49 50 enum DEBUGTYPE 51 { 52 Unknown, 53 None, 54 Codeview 55 } 56 57 class DebugData 58 { 59 } 45 60 46 61 // COFF PE Image Module - DLL or EXE 47 62 class COFFImage : COFFBinary 48 63 { 49 public:50 // module identity51 char[] moduleFile; // name of module file52 char[] internal_name; // for DLLs, how it was called at compile time53 char[] debug_name; // When there was a MISC debug info section54 bit valid = false;55 56 // file info elements57 uint peoffset; // offset of PE header in file58 bit peplus; // PE32 (false) or PE32+ (true) header59 60 PEHeader* pe; // pointer to PE32/PE32+ Header61 PEWindowsHeader* winpe; // Windows specific PE32/PE32+ header62 PEDataDirectories* datadir; // Data Directory Tables63 64 ////CodeViewData codeView; // codeview debug data64 public: 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 65 80 // SymbolManager symbolManager; 66 81 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 } 78 97 /* 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 } 85 104 */ 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); 125 223 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"); 129 441 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"); 135 448 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"); 139 459 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"); 143 466 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( §ionTable[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); 149 520 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 <
