1 /*
2 * HT Editor
3 * htpe.cc
4 *
5 * Copyright (C) 1999-2002 Stefan Weyergraf
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "log.h"
22 #include "endianess.h"
23 #include "htnewexe.h"
24 #include "htpe.h"
25 #include "htpehead.h"
26 #include "htpeexp.h"
27 #include "htpeil.h"
28 #include "htpeimp.h"
29 #include "htpedimp.h"
30 #include "htpeimg.h"
31 #include "htperes.h"
32 #include "htpereloc.h"
33 #include "stream.h"
34 #include "tools.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 static format_viewer_if *htpe_ifs[] = {
40 &htpeheader_if,
41 &htpeexports_if,
42 &htpeimports_if,
43 &htpereloc_if,
44 &htpedelayimports_if,
45 &htperesources_if,
46 &htpeil_if,
47 &htpeimage_if,
48 0
49 };
50
htpe_init(Bounds * b,File * file,ht_format_group * format_group)51 static ht_view *htpe_init(Bounds *b, File *file, ht_format_group *format_group)
52 {
53 byte pemagic[4];
54 FileOfs h = get_newexe_header_ofs(file);
55 file->seek(h);
56 ;
57 if (file->read(pemagic, 4) != 4
58 || pemagic[0] != PE_MAGIC0 || pemagic[1] != PE_MAGIC1
59 || pemagic[2] != PE_MAGIC2 || pemagic[3] != PE_MAGIC3) return 0;
60
61 ht_pe *g = new ht_pe();
62 g->init(b, file, htpe_ifs, format_group, h);
63 return g;
64 }
65
66 format_viewer_if htpe_if = {
67 htpe_init,
68 0
69 };
70
71 /*
72 * CLASS ht_pe
73 */
init(Bounds * b,File * file,format_viewer_if ** ifs,ht_format_group * format_group,FileOfs header_ofs)74 void ht_pe::init(Bounds *b, File *file, format_viewer_if **ifs, ht_format_group *format_group, FileOfs header_ofs)
75 {
76 ht_format_group::init(b, VO_BROWSABLE | VO_SELECTABLE | VO_RESIZE, DESC_PE, file, false, true, 0, format_group);
77 VIEW_DEBUG_NAME("ht_pe");
78
79 String fn;
80 LOG("%y: PE: found header at 0x%08qx", &file->getFilename(fn), header_ofs);
81 ht_pe_shared_data *pe_shared = new ht_pe_shared_data;
82
83 shared_data = pe_shared;
84 pe_shared->header_ofs = header_ofs;
85
86 pe_shared->exports.funcs = new Array(true);
87 pe_shared->dimports.funcs = new Array(true);
88 pe_shared->dimports.libs = new Array(true);
89 pe_shared->imports.funcs = new Array(true);
90 pe_shared->imports.libs = new Array(true);
91
92 pe_shared->il = NULL;
93 pe_shared->v_image = NULL;
94 pe_shared->v_dimports = NULL;
95 pe_shared->v_imports = NULL;
96 pe_shared->v_exports = NULL;
97 pe_shared->v_resources = NULL;
98 pe_shared->v_header = NULL;
99
100 /* read header */
101 file->seek(header_ofs+4);
102 file->readx(&pe_shared->coffheader, sizeof pe_shared->coffheader);
103 createHostStruct(&pe_shared->coffheader, COFF_HEADER_struct, little_endian);
104 file->readx(&pe_shared->opt_magic, sizeof pe_shared->opt_magic);
105 pe_shared->opt_magic = createHostInt(&pe_shared->opt_magic, sizeof pe_shared->opt_magic, little_endian);
106 file->seek(header_ofs+4+sizeof pe_shared->coffheader);
107 switch (pe_shared->opt_magic) {
108 case COFF_OPTMAGIC_PE32:
109 file->readx(&pe_shared->pe32.header, sizeof pe_shared->pe32.header);
110 createHostStruct(&pe_shared->pe32.header, COFF_OPTIONAL_HEADER32_struct, little_endian);
111 file->readx(&pe_shared->pe32.header_nt, sizeof pe_shared->pe32.header_nt);
112 createHostStruct(&pe_shared->pe32.header_nt, PE_OPTIONAL_HEADER32_NT_struct, little_endian);
113 for (uint i=0; i<PE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
114 createHostStruct(&pe_shared->pe32.header_nt.directory[i], PE_DATA_DIRECTORY_struct, little_endian);
115 }
116 break;
117 case COFF_OPTMAGIC_PE64:
118 file->readx(&pe_shared->pe64.header, sizeof pe_shared->pe64.header);
119 createHostStruct(&pe_shared->pe64.header, COFF_OPTIONAL_HEADER64_struct, little_endian);
120 file->readx(&pe_shared->pe64.header_nt, sizeof pe_shared->pe64.header_nt);
121 createHostStruct(&pe_shared->pe64.header_nt, PE_OPTIONAL_HEADER64_NT_struct, little_endian);
122 for (uint i=0; i<PE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
123 createHostStruct(&pe_shared->pe64.header_nt.directory[i], PE_DATA_DIRECTORY_struct, little_endian);
124 }
125 break;
126 }
127
128 /* read section headers */
129 int os=pe_shared->coffheader.optional_header_size;
130 pe_shared->sections.section_count=pe_shared->coffheader.section_count;
131
132 file->seek(header_ofs+os+sizeof(COFF_HEADER)+4/*magic*/);
133 pe_shared->sections.sections = ht_malloc(pe_shared->sections.section_count * sizeof *pe_shared->sections.sections);
134 file->readx(pe_shared->sections.sections, pe_shared->sections.section_count*sizeof *pe_shared->sections.sections);
135
136 for (uint i=0; i<pe_shared->sections.section_count; i++) {
137 createHostStruct(&pe_shared->sections.sections[i], COFF_SECTION_HEADER_struct, little_endian);
138 /*
139 * To make those uninitialized/initialized flags
140 * correct we guess a little
141 *
142 if (pe_shared->sections.sections[i].data_size &&
143 pe_shared->sections.sections[i].data_offset) {
144
145 pe_shared->sections.sections[i].characteristics |= ;
146 pe_shared->sections.sections[i].characteristics ~= ;
147 } else {
148 pe_shared->sections.sections[i].characteristics |= ;
149 pe_shared->sections.sections[i].characteristics ~= ;
150 }*/
151 }
152
153 shared_data = pe_shared;
154
155 ht_format_group::init_ifs(ifs);
156 }
157
done()158 void ht_pe::done()
159 {
160 ht_format_group::done();
161
162 ht_pe_shared_data *pe_shared = (ht_pe_shared_data*)shared_data;
163
164 delete pe_shared->exports.funcs;
165 delete pe_shared->dimports.funcs;
166 delete pe_shared->dimports.libs;
167 delete pe_shared->imports.funcs;
168 delete pe_shared->imports.libs;
169
170 free(pe_shared->sections.sections);
171 delete pe_shared;
172 }
173
loc_enum_start()174 void ht_pe::loc_enum_start()
175 {
176 /*
177 ht_pe_shared_data *sh=(ht_pe_shared_data*)shared_data;
178 if (sh->opt_magic==COFF_OPTMAGIC_PE32) {
179 loc_enum=1;
180 } else {
181 loc_enum=0;
182 }
183 */
184 }
185
loc_enum_next(ht_format_loc * loc)186 bool ht_pe::loc_enum_next(ht_format_loc *loc)
187 {
188 #if 0
189 ht_pe_shared_data *sh=(ht_pe_shared_data*)shared_data;
190 if (loc_enum) {
191 loc->name="pe";
192 loc->start=sh->header_ofs;
193 // calc pe size
194 uint l=sizeof (COFF_HEADER) + sh->coffheader.optional_header_size;
195 // go through directories
196 for (uint i=0; i<16; i++) {
197 FileOfs o;
198 if (pe_rva_to_ofs(&sh->sections, sh->pe32.header_nt.directory[i].address, &o)) {
199 uint k=o+sh->pe32.header_nt.directory[i].size-sh->header_ofs;
200 l=MAX(k, l);
201 }
202 }
203 // go through sections
204 for (uint i=0; i<sh->sections.section_count; i++) {
205 uint k=sh->sections.sections[i].data_offset+sh->sections.sections[i].data_size-sh->header_ofs;
206 l=MAX(k, l);
207 }
208 loc->length=l;
209
210 loc_enum=0;
211 return true;
212 }
213 return false;
214 #endif
215 return false;
216 }
217
218 /*
219 * rva conversion routines
220 */
221
pe_rva_to_ofs(pe_section_headers * section_headers,RVA rva,FileOfs * ofs)222 bool pe_rva_to_ofs(pe_section_headers *section_headers, RVA rva, FileOfs *ofs)
223 {
224 COFF_SECTION_HEADER *s=section_headers->sections;
225 for (uint i=0; i<section_headers->section_count; i++) {
226 if ((rva>=s->data_address) &&
227 (rva<s->data_address+s->data_size)) {
228 *ofs=rva-s->data_address+s->data_offset;
229 return true;
230 }
231 s++;
232 }
233 return false;
234 }
235
pe_rva_to_section(pe_section_headers * section_headers,RVA rva,int * section)236 bool pe_rva_to_section(pe_section_headers *section_headers, RVA rva, int *section)
237 {
238 COFF_SECTION_HEADER *s=section_headers->sections;
239 for (uint i=0; i<section_headers->section_count; i++) {
240 if ((rva>=s->data_address) &&
241 (rva<s->data_address+MAX(s->data_size, s->data_vsize))) {
242 *section=i;
243 return true;
244 }
245 s++;
246 }
247 return false;
248 }
249
pe_rva_is_valid(pe_section_headers * section_headers,RVA rva)250 bool pe_rva_is_valid(pe_section_headers *section_headers, RVA rva)
251 {
252 COFF_SECTION_HEADER *s=section_headers->sections;
253 for (uint i=0; i<section_headers->section_count; i++) {
254 if ((rva>=s->data_address) &&
255 (rva<s->data_address+MAX(s->data_size, s->data_vsize))) {
256 return true;
257 }
258 s++;
259 }
260 return false;
261 }
262
pe_rva_is_physical(pe_section_headers * section_headers,RVA rva)263 bool pe_rva_is_physical(pe_section_headers *section_headers, RVA rva)
264 {
265 COFF_SECTION_HEADER *s=section_headers->sections;
266 for (uint i=0; i<section_headers->section_count; i++) {
267 if ((rva>=s->data_address) &&
268 (rva<s->data_address+s->data_size)) {
269 return true;
270 }
271 s++;
272 }
273 return false;
274 }
275
276 /*
277 * ofs conversion routines
278 */
279
pe_ofs_to_rva(pe_section_headers * section_headers,FileOfs ofs,RVA * rva)280 bool pe_ofs_to_rva(pe_section_headers *section_headers, FileOfs ofs, RVA *rva)
281 {
282 COFF_SECTION_HEADER *s=section_headers->sections;
283 for (uint i=0; i<section_headers->section_count; i++) {
284 if ((ofs>=s->data_offset) &&
285 (ofs<s->data_offset+s->data_size)) {
286 *rva=ofs-s->data_offset+s->data_address;
287 return true;
288 }
289 s++;
290 }
291 return false;
292 }
293
pe_ofs_to_section(pe_section_headers * section_headers,FileOfs ofs,int * section)294 bool pe_ofs_to_section(pe_section_headers *section_headers, FileOfs ofs, int *section)
295 {
296 COFF_SECTION_HEADER *s=section_headers->sections;
297 for (uint i=0; i<section_headers->section_count; i++) {
298 if ((ofs>=s->data_offset) &&
299 (ofs<s->data_offset+s->data_size)) {
300 *section=i;
301 return true;
302 }
303 s++;
304 }
305 return false;
306 }
307
pe_ofs_to_rva_and_section(pe_section_headers * section_headers,FileOfs ofs,RVA * rva,int * section)308 bool pe_ofs_to_rva_and_section(pe_section_headers *section_headers, FileOfs ofs, RVA *rva, int *section)
309 {
310 bool r = pe_ofs_to_rva(section_headers, ofs, rva);
311 if (r) {
312 r = pe_ofs_to_section(section_headers, ofs, section);
313 }
314 return r;
315 }
316
pe_ofs_is_valid(pe_section_headers * section_headers,FileOfs ofs)317 bool pe_ofs_is_valid(pe_section_headers *section_headers, FileOfs ofs)
318 {
319 RVA rva;
320 return pe_ofs_to_rva(section_headers, ofs, &rva);
321 }
322
323 /*
324 *
325 */
326
pe_section_name_to_section(pe_section_headers * section_headers,const char * name,int * section)327 bool pe_section_name_to_section(pe_section_headers *section_headers, const char *name, int *section)
328 {
329 COFF_SECTION_HEADER *s = section_headers->sections;
330 int slen = strlen(name);
331 slen = MIN(slen, COFF_SIZEOF_SHORT_NAME);
332 for (uint i=0; i < section_headers->section_count; i++) {
333 if (ht_strncmp(name, (char*)&s->name, slen) == 0) {
334 *section = i;
335 return true;
336 }
337 s++;
338 }
339 return false;
340 }
341