1 /*
2 * HT Editor
3 * pe_analy.cc
4 *
5 * Copyright (C) 1999-2002 Sebastian Biallas (sb@biallas.net)
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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "analy.h"
26 #include "analy_alpha.h"
27 #include "analy_il.h"
28 #include "analy_names.h"
29 #include "analy_register.h"
30 #include "analy_ppc.h"
31 #include "analy_x86.h"
32 #include "analy_arm.h"
33 #include "htctrl.h"
34 #include "htdebug.h"
35 #include "htiobox.h"
36 #include "htpe.h"
37 #include "strtools.h"
38 #include "ilopc.h"
39 #include "pe_analy.h"
40 #include "pestruct.h"
41 #include "snprintf.h"
42 #include "x86asm.h"
43
init(ht_pe_shared_data * Pe_shared,File * File)44 void PEAnalyser::init(ht_pe_shared_data *Pe_shared, File *File)
45 {
46 pe_shared = Pe_shared;
47 file = File;
48
49 validarea = new Area();
50 validarea->init();
51
52 fixupque_git = Pe_shared->fixupque.begin();
53
54 Analyser::init();
55 }
56
57
58 static char *string_func(uint32 ofs, void *context);
59 static char *token_func(uint32 token, void *context);
60
61 /*
62 *
63 */
load(ObjectStream & f)64 void PEAnalyser::load(ObjectStream &f)
65 {
66 GET_OBJECT(f, validarea);
67 Analyser::load(f);
68 }
69
70 /*
71 *
72 */
done()73 void PEAnalyser::done()
74 {
75 validarea->done();
76 delete validarea;
77 Analyser::done();
78 }
79
80 /*
81 *
82 */
reinit(ht_pe_shared_data * Pe_shared,File * f)83 void PEAnalyser::reinit(ht_pe_shared_data *Pe_shared, File *f)
84 {
85 pe_shared = Pe_shared;
86 file = f;
87 if (disasm->getObjectID() == ATOM_DISASM_IL) {
88 ((ILDisassembler *)disasm)->initialize(string_func, token_func, pe_shared);
89 }
90 }
91
92 /*
93 *
94 */
beginAnalysis()95 void PEAnalyser::beginAnalysis()
96 {
97 char buffer[1024];
98
99 setLocationTreeOptimizeThreshold(100);
100 setSymbolTreeOptimizeThreshold(100);
101
102 bool pe32 = (pe_shared->opt_magic == COFF_OPTMAGIC_PE32);
103
104 /*
105 * entrypoint
106 */
107 Address *entry;
108 if (pe32) {
109 entry = createAddress32(pe_shared->pe32.header.entrypoint_address+pe_shared->pe32.header_nt.image_base);
110 } else {
111 entry = createAddress64(pe_shared->pe64.header.entrypoint_address+pe_shared->pe64.header_nt.image_base);
112 }
113 pushAddress(entry, entry);
114
115 /*
116 * give all sections a descriptive comment:
117 */
118
119 /*struct PE_SECTION_HEADER {
120 byte name[PE_SIZEOF_SHORT_NAME] __attribute__ ((packed));
121 uint32 data_vsize __attribute__ ((packed));
122 uint32 data_address __attribute__ ((packed));
123 uint32 data_size __attribute__ ((packed));
124 uint32 data_offset __attribute__ ((packed));
125 uint32 relocation_offset __attribute__ ((packed));
126 uint32 linenumber_offset __attribute__ ((packed));
127 uint16 relocation_count __attribute__ ((packed));
128 uint16 linenumber_count __attribute__ ((packed));
129 uint32 characteristics __attribute__ ((packed));
130 };*/
131 COFF_SECTION_HEADER *s=pe_shared->sections.sections;
132 char blub[100];
133 for (uint i=0; i<pe_shared->sections.section_count; i++) {
134 Address *secaddr;
135 if (pe32) {
136 secaddr = createAddress32(s->data_address + pe_shared->pe32.header_nt.image_base);
137 } else {
138 secaddr = createAddress64(s->data_address + pe_shared->pe64.header_nt.image_base);
139 }
140 ht_snprintf(blub, sizeof blub, "; section %d <%s>", i+1, getSegmentNameByAddress(secaddr));
141 addComment(secaddr, 0, "");
142 addComment(secaddr, 0, ";******************************************************************");
143 addComment(secaddr, 0, blub);
144 ht_snprintf(blub, sizeof blub, "; virtual address %08x virtual size %08x", s->data_address, s->data_vsize);
145 addComment(secaddr, 0, blub);
146 ht_snprintf(blub, sizeof blub, "; file offset %08x file size %08x", s->data_offset, s->data_size);
147 addComment(secaddr, 0, blub);
148 addComment(secaddr, 0, ";******************************************************************");
149
150 // mark end of sections
151 ht_snprintf(blub, sizeof blub, "; end of section <%s>", getSegmentNameByAddress(secaddr));
152 Address *secend_addr = secaddr->clone();
153 secend_addr->add(MAX(s->data_size, s->data_vsize));
154 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
155 addComment(secend_addr, 0, "");
156 addComment(secend_addr, 0, ";******************************************************************");
157 addComment(secend_addr, 0, blub);
158 addComment(secend_addr, 0, ";******************************************************************");
159
160 validarea->add(secaddr, secend_addr);
161 Address *seciniaddr = secaddr->clone();
162 seciniaddr->add(MIN(s->data_size, s->data_vsize));
163 if (validAddress(secaddr, scinitialized) && validAddress(seciniaddr, scinitialized)) {
164 initialized->add(secaddr, seciniaddr);
165 }
166 s++;
167 delete secaddr;
168 delete secend_addr;
169 delete seciniaddr;
170 }
171
172 // exports
173
174 int export_count=pe_shared->exports.funcs->count();
175 int *entropy = random_permutation(export_count);
176 for (int i=0; i<export_count; i++) {
177 ht_pe_export_function *f=(ht_pe_export_function *)(*pe_shared->exports.funcs)[entropy[i]];
178 Address *faddr;
179 if (pe32) {
180 faddr = createAddress32(f->address + pe_shared->pe32.header_nt.image_base);
181 } else {
182 faddr = createAddress64(f->address + pe_shared->pe64.header_nt.image_base);
183 }
184 if (validAddress(faddr, scvalid)) {
185 char *label;
186 if (f->byname) {
187 ht_snprintf(buffer, sizeof buffer, "; exported function %s, ordinal %04x", f->name, f->ordinal);
188 } else {
189 ht_snprintf(buffer, sizeof buffer, "; unnamed exported function, ordinal %04x", f->ordinal);
190 }
191 label = export_func_name((f->byname) ? f->name : NULL, f->ordinal);
192 addComment(faddr, 0, "");
193 addComment(faddr, 0, ";********************************************************");
194 addComment(faddr, 0, buffer);
195 addComment(faddr, 0, ";********************************************************");
196 pushAddress(faddr, faddr);
197 assignSymbol(faddr, label, label_func);
198 free(label);
199 }
200 delete faddr;
201 }
202 if (entropy) free(entropy);
203
204 int import_count=pe_shared->imports.funcs->count();
205 entropy = random_permutation(import_count);
206 for (int i=0; i<import_count; i++) {
207 ht_pe_import_function *f = (ht_pe_import_function *)(*pe_shared->imports.funcs)[entropy[i]];
208 ht_pe_import_library *d = (ht_pe_import_library *)(*pe_shared->imports.libs)[f->libidx];
209 char *label;
210 label = import_func_name(d->name, (f->byname) ? f->name.name : NULL, f->ordinal);
211 Address *faddr;
212 if (pe32) {
213 faddr = createAddress32(f->address + pe_shared->pe32.header_nt.image_base);
214 } else {
215 faddr = createAddress64(f->address + pe_shared->pe64.header_nt.image_base);
216 }
217 addComment(faddr, 0, "");
218 if (!assignSymbol(faddr, label, label_func)) {
219 // multiple import of a function (duplicate labelname)
220 // -> mangle name a bit more
221 addComment(faddr, 0, "; duplicate import");
222 ht_snprintf(buffer, sizeof buffer, "%s_%x", label, f->address);
223 assignSymbol(faddr, buffer, label_func);
224 }
225 if (pe32) {
226 data->setIntAddressType(faddr, dst_idword, 4);
227 } else {
228 data->setIntAddressType(faddr, dst_iqword, 8);
229 }
230 free(label);
231 delete faddr;
232 }
233 if (entropy) free(entropy);
234
235 int dimport_count=pe_shared->dimports.funcs->count();
236 entropy = random_permutation(dimport_count);
237 for (int i=0; i<dimport_count; i++) {
238 // FIXME: delay imports need work (push addr)
239 ht_pe_import_function *f=(ht_pe_import_function *)(*pe_shared->dimports.funcs)[entropy[i]];
240 ht_pe_import_library *d=(ht_pe_import_library *)(*pe_shared->dimports.libs)[f->libidx];
241 if (f->byname) {
242 ht_snprintf(buffer, sizeof buffer, "; delay import function loader for %s, ordinal %04x", f->name.name, f->ordinal);
243 } else {
244 ht_snprintf(buffer, sizeof buffer, "; delay import function loader for ordinal %04x", f->ordinal);
245 }
246 char *label;
247 label = import_func_name(d->name, f->byname ? f->name.name : NULL, f->ordinal);
248 Address *faddr;
249 if (pe32) {
250 faddr = createAddress32(f->address);
251 } else {
252 faddr = createAddress64(f->address);
253 }
254 addComment(faddr, 0, "");
255 addComment(faddr, 0, ";********************************************************");
256 addComment(faddr, 0, buffer);
257 addComment(faddr, 0, ";********************************************************");
258 assignSymbol(faddr, label, label_func);
259 free(label);
260 delete faddr;
261 }
262 if (entropy) free(entropy);
263
264 addComment(entry, 0, "");
265 addComment(entry, 0, ";****************************");
266 if (pe_shared->coffheader.characteristics & COFF_DLL) {
267 addComment(entry, 0, "; dll entry point");
268 } else {
269 addComment(entry, 0, "; program entry point");
270 }
271 addComment(entry, 0, ";****************************");
272 assignSymbol(entry, "entrypoint", label_func);
273
274 setLocationTreeOptimizeThreshold(1000);
275 setSymbolTreeOptimizeThreshold(1000);
276 delete entry;
277
278 Analyser::beginAnalysis();
279 }
280
281 /*
282 *
283 */
getObjectID() const284 ObjectID PEAnalyser::getObjectID() const
285 {
286 return ATOM_PE_ANALYSER;
287 }
288
289 /*
290 *
291 */
bufPtr(Address * Addr,byte * buf,int size)292 uint PEAnalyser::bufPtr(Address *Addr, byte *buf, int size)
293 {
294 FileOfs ofs = addressToFileofs(Addr);
295 /* if (ofs == INVALID_FILE_OFS) {
296 int as=0;
297 }*/
298 assert(ofs != INVALID_FILE_OFS);
299 file->seek(ofs);
300 return file->read(buf, size);
301 }
302
convertAddressToRVA(Address * addr,RVA * r)303 bool PEAnalyser::convertAddressToRVA(Address *addr, RVA *r)
304 {
305 ObjectID oid = addr->getObjectID();
306 if (oid == ATOM_ADDRESS_FLAT_32) {
307 *r = ((AddressFlat32*)addr)->addr - pe_shared->pe32.header_nt.image_base;
308 return true;
309 } else if (oid == ATOM_ADDRESS_X86_FLAT_32) {
310 *r = ((AddressX86Flat32*)addr)->addr - pe_shared->pe32.header_nt.image_base;
311 return true;
312 } else if (oid == ATOM_ADDRESS_FLAT_64) {
313 uint64 q = ((AddressFlat64*)addr)->addr - pe_shared->pe64.header_nt.image_base;
314 if (q >> 32) return false;
315 *r = q;
316 return true;
317 }
318 return false;
319 }
320
321 /*
322 *
323 */
createAddress32(uint32 addr)324 Address *PEAnalyser::createAddress32(uint32 addr)
325 {
326 switch (pe_shared->coffheader.machine) {
327 case COFF_MACHINE_I386:
328 case COFF_MACHINE_I486:
329 case COFF_MACHINE_I586:
330 return new AddressX86Flat32(addr);
331 }
332 // fallback to standard-addrs
333 return new AddressFlat32(addr);
334 }
335
336 /*
337 *
338 */
createAddress64(uint64 addr)339 Address *PEAnalyser::createAddress64(uint64 addr)
340 {
341 return new AddressFlat64(addr);
342 }
343
createAddress()344 Address *PEAnalyser::createAddress()
345 {
346 switch (pe_shared->coffheader.machine) {
347 case COFF_MACHINE_I386:
348 case COFF_MACHINE_I486:
349 case COFF_MACHINE_I586:
350 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
351 return new AddressFlat64();
352 } else {
353 return new AddressX86Flat32();
354 }
355 }
356 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
357 return new AddressFlat64();
358 }
359 return new AddressFlat32();
360 }
361
362 /*
363 *
364 */
createAssembler()365 Assembler *PEAnalyser::createAssembler()
366 {
367 Assembler *a = NULL;
368 switch (pe_shared->coffheader.machine) {
369 case COFF_MACHINE_I386:
370 case COFF_MACHINE_I486:
371 case COFF_MACHINE_I586:
372 a = new x86asm(X86_OPSIZE32, X86_ADDRSIZE32);
373 a->init();
374 return a;
375 case COFF_MACHINE_AMD64:
376 a = new x86_64asm();
377 a->init();
378 return a;
379 }
380 return a;
381 }
382
383 /*
384 *
385 */
addressToFileofs(Address * Addr)386 FileOfs PEAnalyser::addressToFileofs(Address *Addr)
387 {
388 /* char tbuf[1024];
389 Addr->stringify(tbuf, 1024, 0);
390 printf("ADDR=%s", tbuf);*/
391 if (validAddress(Addr, scinitialized)) {
392 // printf(" v1\n");
393 FileOfs ofs;
394 RVA r;
395 if (!convertAddressToRVA(Addr, &r)) return INVALID_FILE_OFS;
396 if (!pe_rva_to_ofs(&pe_shared->sections, r, &ofs)) return INVALID_FILE_OFS;
397 return ofs;
398 } else {
399 // printf(" IV1\n");
400 return INVALID_FILE_OFS;
401 }
402 }
403
404 // This function checks if a fixup is present on a byte at the given Addr plus offset,
405 // it also stores the last entry found, to speedup the next check.
406
isAddressFixedUp(Address * Addr,int offset)407 bool PEAnalyser::isAddressFixedUp(Address *Addr, int offset)
408 {
409 RVA r, rng_start, rng_end;
410 std::deque<fixup_listentry>::iterator fixupque_lit;
411 unsigned char listmovdir = 0; // 1 down 2 up
412
413 if (!convertAddressToRVA(Addr, &r)) return false;
414 r += offset;
415
416 if (fixupque_git == pe_shared->fixupque.end() ) return false; // exit on empty list
417 fixupque_lit = fixupque_git;
418
419 while (fixupque_lit != pe_shared->fixupque.end() ) {
420
421 rng_start = fixupque_lit->addr;
422 rng_end = rng_start + fixupque_lit->size;
423
424 if (r >= rng_start && r < rng_end) {
425 fixupque_git = fixupque_lit;
426 return true;
427 }
428
429 if (r < rng_start && listmovdir != 2 ) {
430 fixupque_git = fixupque_lit;
431 if (fixupque_lit == pe_shared->fixupque.begin()) return false;
432 fixupque_lit--;
433 listmovdir = 1;
434
435 } else if (r > rng_start && listmovdir != 1){
436 fixupque_git = fixupque_lit;
437 fixupque_lit++;
438 listmovdir = 2;
439
440 } else {
441 return false;
442 }
443 }
444
445 return false;
446 }
447
448
449 /*
450 *
451 */
getSegmentNameByAddress(Address * Addr)452 const char *PEAnalyser::getSegmentNameByAddress(Address *Addr)
453 {
454 static char sectionname[9];
455 pe_section_headers *sections=&pe_shared->sections;
456 int i;
457 RVA r;
458 // Addr-=pe_shared->pe32.header_nt.image_base;
459 if (!convertAddressToRVA(Addr, &r)) return NULL;
460 pe_rva_to_section(sections, r, &i);
461 COFF_SECTION_HEADER *s=sections->sections+i;
462 if (!pe_rva_is_valid(sections, r)) return NULL;
463 memcpy(sectionname, s->name, 8);
464 sectionname[8] = 0;
465 return sectionname;
466 }
467
468 /*
469 *
470 */
getName(String & s)471 String &PEAnalyser::getName(String &s)
472 {
473 return file->getDesc(s);
474 }
475
476 /*
477 *
478 */
getType()479 const char *PEAnalyser::getType()
480 {
481 return "PE/Analyser";
482 }
483
484 /*
485 *
486 */
initCodeAnalyser()487 void PEAnalyser::initCodeAnalyser()
488 {
489 Analyser::initCodeAnalyser();
490 }
491
string_func(uint32 ofs,void * context)492 static char *string_func(uint32 ofs, void *context)
493 {
494 char str[1024];
495 static char str2[1024];
496 ht_pe_shared_data *pe = (ht_pe_shared_data*)context;
497 if (ofs < pe->il->string_pool_size) {
498 uint32 length;
499 uint32 o = ILunpackDword(length, (byte*)&pe->il->string_pool[ofs], 10);
500 wide_char_to_multi_byte(str, (byte*)&pe->il->string_pool[ofs+o], length/2+1);
501 escape_special_str(str2, sizeof str2, str, "\"");
502 return str2;
503 } else {
504 return NULL;
505 }
506 }
507
token_func(uint32 token,void * context)508 static char *token_func(uint32 token, void *context)
509 {
510 static char tokenstr[1024];
511 // ht_pe_shared_data *pe = (ht_pe_shared_data*)context;
512 switch (token & IL_META_TOKEN_MASK) {
513 case IL_META_TOKEN_TYPE_REF:
514 case IL_META_TOKEN_TYPE_DEF: {
515 sprintf(tokenstr, "typedef");
516 break;
517 }
518 case IL_META_TOKEN_FIELD_DEF: {
519 sprintf(tokenstr, "fielddef");
520 break;
521 }
522 case IL_META_TOKEN_METHOD_DEF: {
523 sprintf(tokenstr, "methoddef");
524 break;
525 }
526 case IL_META_TOKEN_MEMBER_REF: {
527 sprintf(tokenstr, "memberref");
528 break;
529 }
530 case IL_META_TOKEN_TYPE_SPEC: {
531 sprintf(tokenstr, "typespec");
532 break;
533 }
534 default:
535 return NULL;
536 }
537 return tokenstr;
538 }
539
540 /*
541 *
542 */
initUnasm()543 void PEAnalyser::initUnasm()
544 {
545 bool pe64 = false;
546 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
547 pe64 = true;
548 }
549 DPRINTF("pe_analy: ");
550 if (pe_shared->il) {
551 analy_disasm = new AnalyILDisassembler();
552 ((AnalyILDisassembler *)analy_disasm)->init(this, string_func, token_func, pe_shared);
553 } else {
554 switch (pe_shared->coffheader.machine) {
555 case COFF_MACHINE_I386: // Intel 386
556 case COFF_MACHINE_I486: // Intel 486
557 case COFF_MACHINE_I586: // Intel 586
558 if (pe64) {
559 errorbox("x86 cant be used in PE64 format.");
560 } else {
561 DPRINTF("initing analy_x86_disassembler\n");
562 analy_disasm = new AnalyX86Disassembler();
563 ((AnalyX86Disassembler *)analy_disasm)->init(this, 0);
564 }
565 break;
566 case COFF_MACHINE_AMD64:
567 if (!pe64) {
568 errorbox("x86_64 cant be used in PE32 format.");
569 } else {
570 analy_disasm = new AnalyX86Disassembler();
571 ((AnalyX86Disassembler *)analy_disasm)->init(this, ANALYX86DISASSEMBLER_FLAGS_AMD64);
572 }
573 break;
574 case COFF_MACHINE_R3000: // MIPS little-endian, 0x160 big-endian
575 DPRINTF("no apropriate disassembler for MIPS\n");
576 warnbox("No disassembler for MIPS!");
577 break;
578 case COFF_MACHINE_R4000: // MIPS little-endian
579 DPRINTF("no apropriate disassembler for MIPS\n");
580 warnbox("No disassembler for MIPS!");
581 break;
582 case COFF_MACHINE_R10000: // MIPS little-endian
583 DPRINTF("no apropriate disassembler for MIPS\n");
584 warnbox("No disassembler for MIPS!");
585 break;
586 case COFF_MACHINE_ALPHA: // Alpha_AXP
587 DPRINTF("initing alpha_axp_disassembler\n");
588 analy_disasm = new AnalyAlphaDisassembler();
589 ((AnalyAlphaDisassembler *)analy_disasm)->init(this);
590 break;
591 case COFF_MACHINE_POWERPC_LE: // IBM PowerPC Little-Endian
592 DPRINTF("no apropriate disassembler for POWER PC\n");
593 warnbox("No disassembler for little endian POWER PC!");
594 break;
595 case COFF_MACHINE_POWERPC_BE:
596 case COFF_MACHINE_POWERPC64_BE:
597 analy_disasm = new AnalyPPCDisassembler();
598 ((AnalyPPCDisassembler*)analy_disasm)->init(this, pe64 ? ANALY_PPC_64 : ANALY_PPC_32);
599 break;
600 case COFF_MACHINE_ARM: // ARM
601 case COFF_MACHINE_THUMB: // Thumb
602 DPRINTF("initing arm_disassembler\n");
603 analy_disasm = new AnalyArmDisassembler();
604 ((AnalyArmDisassembler *)analy_disasm)->init(this);
605 break;
606 case COFF_MACHINE_UNKNOWN:
607 default:
608 DPRINTF("no apropriate disassembler for machine %04x\n", pe_shared->coffheader.machine);
609 warnbox("No disassembler for unknown machine type %04x!", pe_shared->coffheader.machine);
610 }
611 }
612 }
613
614 /*
615 *
616 */
log(const char * msg)617 void PEAnalyser::log(const char *msg)
618 {
619 /*
620 * log() creates to much traffic so dont log
621 * perhaps we reactivate this later
622 *
623 */
624 /* LOG(msg);*/
625 }
626
627 /*
628 *
629 */
nextValid(Address * Addr)630 Address *PEAnalyser::nextValid(Address *Addr)
631 {
632 return (Address *)validarea->findNext(Addr);
633 }
634
635 /*
636 *
637 */
store(ObjectStream & st) const638 void PEAnalyser::store(ObjectStream &st) const
639 {
640 PUT_OBJECT(st, validarea);
641 Analyser::store(st);
642 }
643
644 /*
645 *
646 */
queryConfig(int mode)647 int PEAnalyser::queryConfig(int mode)
648 {
649 switch (mode) {
650 case Q_DO_ANALYSIS:
651 case Q_ENGAGE_CODE_ANALYSER:
652 case Q_ENGAGE_DATA_ANALYSER:
653 return true;
654 default:
655 return 0;
656 }
657 }
658
659 /*
660 *
661 */
fileofsToAddress(FileOfs fileofs)662 Address *PEAnalyser::fileofsToAddress(FileOfs fileofs)
663 {
664 RVA r;
665 if (pe_ofs_to_rva(&pe_shared->sections, fileofs, &r)) {
666 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
667 return createAddress32(r + pe_shared->pe32.header_nt.image_base);
668 } else {
669 return createAddress64(r + pe_shared->pe64.header_nt.image_base);
670 }
671 } else {
672 return new InvalidAddress();
673 }
674 }
675
676 /*
677 *
678 */
validAddress(Address * Addr,tsectype action)679 bool PEAnalyser::validAddress(Address *Addr, tsectype action)
680 {
681 pe_section_headers *sections=&pe_shared->sections;
682 int sec;
683 RVA r;
684 if (!convertAddressToRVA(Addr, &r)) return false;
685 if (!pe_rva_to_section(sections, r, &sec)) return false;
686 COFF_SECTION_HEADER *s=sections->sections+sec;
687 switch (action) {
688 case scvalid:
689 return true;
690 case scread:
691 return s->characteristics & COFF_SCN_MEM_READ;
692 case scwrite:
693 return s->characteristics & COFF_SCN_MEM_WRITE;
694 case screadwrite:
695 return s->characteristics & COFF_SCN_MEM_WRITE;
696 case sccode:
697 // FIXME: EXECUTE vs. CNT_CODE ?
698 if (!pe_rva_is_physical(sections, r)) return false;
699 return (s->characteristics & (COFF_SCN_MEM_EXECUTE | COFF_SCN_CNT_CODE));
700 case scinitialized:
701 if (!pe_rva_is_physical(sections, r)) return false;
702 return true;
703 // !(s->characteristics & COFF_SCN_CNT_UNINITIALIZED_DATA);
704 }
705 return false;
706 }
707
708
709