comparison 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
comparison
equal deleted inserted replaced
0:586e4a649642 1:4a9dcbd9e54f
1 /* Ddbg - Win32 Debugger for the D programming language
2 * Copyright (c) 2007 Jascha Wetzel
3 * All rights reserved. See LICENSE.TXT for details.
4 */
5
6 module codeview.coff;
7
8 import std.file;
9 import std.stdio;
10 import std.c.string;
11
12 import util;
13 import codeview.parser;
14 import codeview.codeview;
15
16 import win32.winnt;
17
18 /**************************************************************************************************
19 Type indeces for COFF debug sections.
20 **************************************************************************************************/
21 enum DebugType
22 {
23 UNKNOWN = 0,
24 COFF,
25 CODEVIEW
26 }
27
28 /**************************************************************************************************
29 Represents a COFF section.
30 **************************************************************************************************/
31 class Section
32 {
33 PIMAGE_SECTION_HEADER header;
34 ubyte[] data;
35
36 this(PIMAGE_SECTION_HEADER csh, DataReader dr)
37 {
38 uint old_cursor = dr.cursor;
39 header = csh;
40 assert(dr.data.length>=csh.PointerToRawData+csh.SizeOfRawData);
41 data = dr.data[csh.PointerToRawData .. csh.PointerToRawData+csh.SizeOfRawData];
42 dr.seek(old_cursor);
43 }
44 }
45
46 /**************************************************************************************************
47 Represents a COFF executable image file.
48 **************************************************************************************************/
49 class COFFImage
50 {
51 private PIMAGE_FILE_HEADER header;
52 private PIMAGE_OPTIONAL_HEADER opt_header;
53 private IMAGE_DEBUG_DIRECTORY[] debug_dirs;
54 Section[] sections;
55 CodeView[] codeview_data;
56
57 size_t codebase,
58 code_section_index;
59
60 string name;
61
62 size_t imageSize()
63 {
64 assert(opt_header !is null);
65 return opt_header.SizeOfImage;
66 }
67
68 size_t imageBase()
69 {
70 assert(opt_header !is null);
71 return opt_header.ImageBase;
72 }
73
74 CodeView codeView()
75 {
76 if ( codeview_data.length == 0 )
77 return null;
78 return codeview_data[0];
79 }
80
81 void load(string filename)
82 {
83 load(cast(ubyte[])read(filename), filename);
84 }
85
86 /**********************************************************************************************
87 Very dirty, preliminary COFF image reader to extract codeview data
88 **********************************************************************************************/
89 void load(ubyte[] data, string filename=null)
90 {
91 DataReader dr = new DataReader(data);
92
93 dr.seek(0x3c);
94 uint pe_offset;
95 dr.read(pe_offset);
96
97 uint pe_sig;
98 dr.seek(pe_offset);
99 dr.read(pe_sig);
100 if ( pe_sig != 0x4550 )
101 throw new Exception("File is not an COFF PE executable");
102
103 ubyte[] buf;
104 assert ( IMAGE_FILE_HEADER.sizeof == 5*4);
105 dr.readA(buf, IMAGE_FILE_HEADER.sizeof);
106 header = cast(PIMAGE_FILE_HEADER)buf.ptr;
107 if ( header.Machine != 0x14c )
108 throw new Exception("Unsupported machine Id in COFF file");
109 uint headersize = header.SizeOfOptionalHeader;
110
111 assert(headersize>=IMAGE_OPTIONAL_HEADER.sizeof);
112 headersize -= IMAGE_OPTIONAL_HEADER.sizeof;
113 dr.readA(buf, IMAGE_OPTIONAL_HEADER.sizeof);
114 opt_header = cast(PIMAGE_OPTIONAL_HEADER)buf.ptr;
115 if ( opt_header.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
116 throw new Exception("Unknown optional header magic");
117
118 assert ( IMAGE_SIZEOF_SHORT_NAME+8*4 == IMAGE_SECTION_HEADER.sizeof);
119 for ( int i = 0; i < header.NumberOfSections; ++i )
120 {
121 dr.readA(buf, IMAGE_SECTION_HEADER.sizeof);
122 sections ~= new Section(cast(PIMAGE_SECTION_HEADER)buf.ptr, dr);
123 }
124
125 dr.seek(fileOffsetFromRVA(opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress));
126 assert ( IMAGE_DEBUG_DIRECTORY.sizeof == 7*4);
127 dr.readA(debug_dirs, opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size/IMAGE_DEBUG_DIRECTORY.sizeof);
128
129 foreach ( IMAGE_DEBUG_DIRECTORY dd; debug_dirs )
130 {
131 if ( dd.Type == DebugType.CODEVIEW )
132 {
133 auto cv = CodeViewParser.parse(this, dr.data[dd.PointerToRawData..dd.PointerToRawData+dd.SizeOfData]);
134 if ( cv !is null )
135 codeview_data ~= cv;
136 }
137 else {
138 debug DbgIO.println("Unsupported COFF Debug Information format 0x%x", dd.Type);
139 }
140 }
141
142 if ( opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size > 0 )
143 {
144 dr.seek(fileOffsetFromRVA(opt_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
145 assert ( IMAGE_EXPORT_DIRECTORY.sizeof == 10*4 );
146 dr.readA(buf, IMAGE_EXPORT_DIRECTORY.sizeof);
147 PIMAGE_EXPORT_DIRECTORY export_dir = cast(PIMAGE_EXPORT_DIRECTORY)buf.ptr;
148 dr.seek(fileOffsetFromRVA(export_dir.Name));
149
150 char c;
151 for ( dr.read(c); c != '\0'; dr.read(c) )
152 name ~= c;
153 }
154 if ( name is null && filename !is null )
155 name = filename;
156 if ( codeview_data.length > 0 )
157 {
158 if ( name !is null )
159 DbgIO.println("Loading symbols from %s", name is null?filename:name);
160 else
161 DbgIO.println("Loading symbols");
162 }
163 else
164 {
165 if ( name !is null )
166 DbgIO.println("No symbols available from %s", name is null?filename:name);
167 else
168 DbgIO.println("No symbols available");
169 }
170 }
171
172 /**********************************************************************************************
173 Calculates the file offset from a given virtual address.
174 **********************************************************************************************/
175 private uint fileOffsetFromRVA(uint rva)
176 {
177 foreach ( Section s; sections )
178 {
179 with ( *s.header )
180 {
181 if( rva >= VirtualAddress && rva <= VirtualAddress+Misc.VirtualSize )
182 return rva-VirtualAddress+PointerToRawData;
183 }
184 }
185 return 0;
186 }
187
188 /**********************************************************************************************
189 Calculates the virtual base address where code from this image is loaded to.
190 **********************************************************************************************/
191 size_t getCodeBase()
192 {
193 if ( codebase == 0 )
194 {
195 assert ( opt_header !is null );
196 Section s = findSection(0x20000000, code_section_index);
197 assert ( s !is null );
198 codebase = opt_header.ImageBase + s.header.VirtualAddress;
199 }
200 return codebase;
201 }
202
203 /**********************************************************************************************
204 Calculates the base address for the given section.
205 **********************************************************************************************/
206 uint getSectionBase(uint section)
207 {
208 if ( section > sections.length )
209 return opt_header.ImageBase;
210 return opt_header.ImageBase + sections[section-1].header.VirtualAddress;
211 }
212
213 /**********************************************************************************************
214 Finds a section with the given characteristics.
215 **********************************************************************************************/
216 private Section findSection(uint characteristics, out uint index)
217 {
218 foreach( int i, s; sections )
219 {
220 if( (s.header.Characteristics & characteristics) == characteristics ) {
221 index = i;
222 return s;
223 }
224 }
225 return null;
226 }
227 }