Mercurial > projects > ddbg_continued
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 } |