Mercurial > projects > ddbg_continued
view src/codeview/coff.d @ 1:4a9dcbd9e54f
-files of 0.13 beta
-fixes so that it now compiles with the current dmd version
author | marton@basel.hu |
---|---|
date | Tue, 05 Apr 2011 20:44:01 +0200 |
parents | |
children |
line wrap: on
line source
/* Ddbg - Win32 Debugger for the D programming language * Copyright (c) 2007 Jascha Wetzel * All rights reserved. See LICENSE.TXT for details. */ module codeview.coff; import std.file; import std.stdio; import std.c.string; import util; import codeview.parser; import codeview.codeview; import win32.winnt; /************************************************************************************************** Type indeces for COFF debug sections. **************************************************************************************************/ enum DebugType { UNKNOWN = 0, COFF, CODEVIEW } /************************************************************************************************** Represents a COFF section. **************************************************************************************************/ class Section { PIMAGE_SECTION_HEADER header; ubyte[] data; this(PIMAGE_SECTION_HEADER csh, DataReader dr) { uint old_cursor = dr.cursor; header = csh; assert(dr.data.length>=csh.PointerToRawData+csh.SizeOfRawData); data = dr.data[csh.PointerToRawData .. csh.PointerToRawData+csh.SizeOfRawData]; dr.seek(old_cursor); } } /************************************************************************************************** Represents a COFF executable image file. **************************************************************************************************/ class COFFImage { private PIMAGE_FILE_HEADER header; private PIMAGE_OPTIONAL_HEADER opt_header; private IMAGE_DEBUG_DIRECTORY[] debug_dirs; Section[] sections; CodeView[] codeview_data; size_t codebase, code_section_index; string name; size_t imageSize() { assert(opt_header !is null); return opt_header.SizeOfImage; } size_t imageBase() { assert(opt_header !is null); return opt_header.ImageBase; } CodeView codeView() { if ( codeview_data.length == 0 ) return null; return codeview_data[0]; } void load(string filename) { load(cast(ubyte[])read(filename), filename); } /********************************************************************************************** Very dirty, preliminary COFF image reader to extract codeview data **********************************************************************************************/ void load(ubyte[] data, string filename=null) { DataReader dr = new DataReader(data); dr.seek(0x3c); uint pe_offset; dr.read(pe_offset); uint pe_sig; dr.seek(pe_offset); dr.read(pe_sig); if ( pe_sig != 0x4550 ) throw new Exception("File is not an COFF PE executable"); ubyte[] buf; assert ( IMAGE_FILE_HEADER.sizeof == 5*4); dr.readA(buf, IMAGE_FILE_HEADER.sizeof); header = cast(PIMAGE_FILE_HEADER)buf.ptr; if ( header.Machine != 0x14c ) throw new Exception("Unsupported machine Id in COFF file"); uint headersize = header.SizeOfOptionalHeader; assert(headersize>=IMAGE_OPTIONAL_HEADER.sizeof); headersize -= IMAGE_OPTIONAL_HEADER.sizeof; dr.readA(buf, IMAGE_OPTIONAL_HEADER.sizeof); opt_header = cast(PIMAGE_OPTIONAL_HEADER)buf.ptr; if ( opt_header.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) throw new Exception("Unknown optional header magic"); assert ( IMAGE_SIZEOF_SHORT_NAME+8*4 == IMAGE_SECTION_HEADER.sizeof); for ( int i = 0; i < header.NumberOfSections; ++i ) { dr.readA(buf, IMAGE_SECTION_HEADER.sizeof); sections ~= new Section(cast(PIMAGE_SECTION_HEADER)buf.ptr, dr); } dr.seek(fileOffsetFromRVA(opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress)); assert ( IMAGE_DEBUG_DIRECTORY.sizeof == 7*4); dr.readA(debug_dirs, opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size/IMAGE_DEBUG_DIRECTORY.sizeof); foreach ( IMAGE_DEBUG_DIRECTORY dd; debug_dirs ) { if ( dd.Type == DebugType.CODEVIEW ) { auto cv = CodeViewParser.parse(this, dr.data[dd.PointerToRawData..dd.PointerToRawData+dd.SizeOfData]); if ( cv !is null ) codeview_data ~= cv; } else { debug DbgIO.println("Unsupported COFF Debug Information format 0x%x", dd.Type); } } if ( opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size > 0 ) { dr.seek(fileOffsetFromRVA(opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)); assert ( IMAGE_EXPORT_DIRECTORY.sizeof == 10*4 ); dr.readA(buf, IMAGE_EXPORT_DIRECTORY.sizeof); PIMAGE_EXPORT_DIRECTORY export_dir = cast(PIMAGE_EXPORT_DIRECTORY)buf.ptr; dr.seek(fileOffsetFromRVA(export_dir.Name)); char c; for ( dr.read(c); c != '\0'; dr.read(c) ) name ~= c; } if ( name is null && filename !is null ) name = filename; if ( codeview_data.length > 0 ) { if ( name !is null ) DbgIO.println("Loading symbols from %s", name is null?filename:name); else DbgIO.println("Loading symbols"); } else { if ( name !is null ) DbgIO.println("No symbols available from %s", name is null?filename:name); else DbgIO.println("No symbols available"); } } /********************************************************************************************** Calculates the file offset from a given virtual address. **********************************************************************************************/ private uint fileOffsetFromRVA(uint rva) { foreach ( Section s; sections ) { with ( *s.header ) { if( rva >= VirtualAddress && rva <= VirtualAddress+Misc.VirtualSize ) return rva-VirtualAddress+PointerToRawData; } } return 0; } /********************************************************************************************** Calculates the virtual base address where code from this image is loaded to. **********************************************************************************************/ size_t getCodeBase() { if ( codebase == 0 ) { assert ( opt_header !is null ); Section s = findSection(0x20000000, code_section_index); assert ( s !is null ); codebase = opt_header.ImageBase + s.header.VirtualAddress; } return codebase; } /********************************************************************************************** Calculates the base address for the given section. **********************************************************************************************/ uint getSectionBase(uint section) { if ( section > sections.length ) return opt_header.ImageBase; return opt_header.ImageBase + sections[section-1].header.VirtualAddress; } /********************************************************************************************** Finds a section with the given characteristics. **********************************************************************************************/ private Section findSection(uint characteristics, out uint index) { foreach( int i, s; sections ) { if( (s.header.Characteristics & characteristics) == characteristics ) { index = i; return s; } } return null; } }