Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

pe_analy.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      pe_analy.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 
00025 #include "analy.h"
00026 #include "analy_alpha.h"
00027 #include "analy_ia64.h"
00028 #include "analy_il.h"
00029 #include "analy_names.h"
00030 #include "analy_register.h"
00031 #include "analy_ppc.h"
00032 #include "analy_x86.h"
00033 #include "global.h"
00034 #include "htctrl.h"
00035 #include "htdebug.h"
00036 #include "htiobox.h"
00037 #include "htpe.h"
00038 #include "htstring.h"
00039 #include "ilopc.h"
00040 #include "pe_analy.h"
00041 #include "pestruct.h"
00042 #include "snprintf.h"
00043 #include "x86asm.h"
00044 
00045 /*
00046  *
00047  */
00048 void    PEAnalyser::init(ht_pe_shared_data *Pe_shared, ht_streamfile *File)
00049 {
00050         pe_shared = Pe_shared;
00051         file = File;
00052 
00053         validarea = new Area();
00054         validarea->init();
00055 
00056         Analyser::init();
00057 }
00058 
00059 
00060 /*
00061  *
00062  */
00063 int     PEAnalyser::load(ht_object_stream *f)
00064 {
00065         /*
00066         ht_pe_shared_data       *pe_shared;
00067         ht_stream               *file;
00068         area                            *validarea;
00069         */
00070         GET_OBJECT(f, validarea);
00071         return Analyser::load(f);
00072 }
00073 
00074 /*
00075  *
00076  */
00077 void    PEAnalyser::done()
00078 {
00079         validarea->done();
00080         delete validarea;
00081         Analyser::done();
00082 }
00083 
00084 /*
00085  *
00086  */
00087 void PEAnalyser::beginAnalysis()
00088 {
00089         char    buffer[1024];
00090 
00091         setLocationTreeOptimizeThreshold(100);
00092         setSymbolTreeOptimizeThreshold(100);
00093 
00094         bool pe32 = (pe_shared->opt_magic == COFF_OPTMAGIC_PE32);
00095         
00096         /*
00097          *      entrypoint
00098          */
00099         Address *entry;
00100         if (pe32) {
00101                 entry = createAddress32(pe_shared->pe32.header.entrypoint_address+pe_shared->pe32.header_nt.image_base);
00102         } else {
00103                 entry = createAddress64(to_qword(pe_shared->pe64.header.entrypoint_address)+pe_shared->pe64.header_nt.image_base);
00104         }
00105         pushAddress(entry, entry);
00106         
00107         /*
00108          * give all sections a descriptive comment:
00109          */
00110 
00111         /*struct PE_SECTION_HEADER {
00112                 byte name[PE_SIZEOF_SHORT_NAME] __attribute__ ((packed));
00113                 dword data_vsize __attribute__ ((packed));
00114                 dword data_address __attribute__ ((packed));
00115                 dword data_size __attribute__   ((packed));
00116                 dword data_offset __attribute__ ((packed));
00117                 dword relocation_offset __attribute__ ((packed));
00118                 dword linenumber_offset __attribute__ ((packed));
00119                 word relocation_count __attribute__ ((packed));
00120                 word linenumber_count __attribute__ ((packed));
00121                 dword characteristics __attribute__ ((packed));
00122         };*/
00123         COFF_SECTION_HEADER *s=pe_shared->sections.sections;
00124         char blub[100];
00125         for (UINT i=0; i<pe_shared->sections.section_count; i++) {
00126                 Address *secaddr;
00127                 if (pe32) {
00128                         secaddr = createAddress32(s->data_address+pe_shared->pe32.header_nt.image_base);
00129                 } else {
00130                         secaddr = createAddress64(to_qword(s->data_address)+pe_shared->pe64.header_nt.image_base);
00131                 }
00132                 ht_snprintf(blub, sizeof blub, ";  section %d <%s>", i+1, getSegmentNameByAddress(secaddr));
00133                 addComment(secaddr, 0, "");
00134                 addComment(secaddr, 0, ";******************************************************************");
00135                 addComment(secaddr, 0, blub);
00136                 ht_snprintf(blub, sizeof blub, ";  virtual address  %08x  virtual size   %08x", s->data_address, s->data_vsize);
00137                 addComment(secaddr, 0, blub);
00138                 ht_snprintf(blub, sizeof blub, ";  file offset      %08x  file size      %08x", s->data_offset, s->data_size);
00139                 addComment(secaddr, 0, blub);
00140                 addComment(secaddr, 0, ";******************************************************************");
00141 
00142                 // mark end of sections
00143                 ht_snprintf(blub, sizeof blub, ";  end of section <%s>", getSegmentNameByAddress(secaddr));
00144                 Address *secend_addr = (Address *)secaddr->duplicate();
00145                 secend_addr->add(MAX(s->data_size, s->data_vsize));
00146                 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00147                 addComment(secend_addr, 0, "");
00148                 addComment(secend_addr, 0, ";******************************************************************");
00149                 addComment(secend_addr, 0, blub);
00150                 addComment(secend_addr, 0, ";******************************************************************");
00151 
00152                 validarea->add(secaddr, secend_addr);
00153                 Address *seciniaddr = (Address *)secaddr->duplicate();
00154                 seciniaddr->add(MIN(s->data_size, s->data_vsize));
00155                 if (validAddress(secaddr, scinitialized) && validAddress(seciniaddr, scinitialized)) {
00156                         initialized->add(secaddr, seciniaddr);
00157                 }
00158                 s++;
00159                 delete secaddr;
00160                 delete secend_addr;
00161                 delete seciniaddr;
00162         }
00163 
00164         // exports
00165 
00166         int export_count=pe_shared->exports.funcs->count();
00167         int *entropy = random_permutation(export_count);
00168         for (int i=0; i<export_count; i++) {
00169                 ht_pe_export_function *f=(ht_pe_export_function *)pe_shared->exports.funcs->get(*(entropy+i));
00170                 Address *faddr;
00171                 if (pe32) {
00172                         faddr = createAddress32(f->address+pe_shared->pe32.header_nt.image_base);
00173                 } else {
00174                         faddr = createAddress64(to_qword(f->address)+pe_shared->pe64.header_nt.image_base);
00175                 }
00176                 if (validAddress(faddr, scvalid)) {
00177                         char *label;
00178                         if (f->byname) {
00179                                 ht_snprintf(buffer, sizeof buffer, "; exported function %s, ordinal %04x", f->name, f->ordinal);
00180                         } else {
00181                                 ht_snprintf(buffer, sizeof buffer, "; unnamed exported function, ordinal %04x", f->ordinal);
00182                         }
00183                         label = export_func_name((f->byname) ? f->name : NULL, f->ordinal);
00184                         addComment(faddr, 0, "");
00185                         addComment(faddr, 0, ";********************************************************");
00186                         addComment(faddr, 0, buffer);
00187                         addComment(faddr, 0, ";********************************************************");
00188                         pushAddress(faddr, faddr);
00189                         assignSymbol(faddr, label, label_func);
00190                         free(label);
00191                 }
00192                 delete faddr;
00193         }
00194         if (entropy) free(entropy);
00195 
00196         int import_count=pe_shared->imports.funcs->count();
00197         entropy = random_permutation(import_count);
00198         for (int i=0; i<import_count; i++) {
00199                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->imports.funcs->get(*(entropy+i));
00200                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->imports.libs->get(f->libidx);
00201                 char *label;
00202                 label = import_func_name(d->name, (f->byname) ? f->name.name : NULL, f->ordinal);
00203                 Address *faddr;
00204                 if (pe32) {
00205                         faddr = createAddress32(f->address+pe_shared->pe32.header_nt.image_base);
00206                 } else {
00207                         faddr = createAddress64(to_qword(f->address)+pe_shared->pe64.header_nt.image_base);
00208                 }
00209                 addComment(faddr, 0, "");
00210                 if (!assignSymbol(faddr, label, label_func)) {
00211                         // multiple import of a function (duplicate labelname)
00212                         // -> mangle name a bit more
00213                         addComment(faddr, 0, "; duplicate import");               
00214                         ht_snprintf(buffer, sizeof buffer, "%s_%x", label, f->address);
00215                         assignSymbol(faddr, buffer, label_func);
00216                 }
00217                 if (pe32) {
00218                         data->setIntAddressType(faddr, dst_idword, 4);
00219                 } else {
00220                         data->setIntAddressType(faddr, dst_iqword, 8);
00221                 }
00222                 free(label);
00223                 delete faddr;
00224         }
00225         if (entropy) free(entropy);
00226 
00227         int dimport_count=pe_shared->dimports.funcs->count();
00228         entropy = random_permutation(dimport_count);
00229         for (int i=0; i<dimport_count; i++) {
00230                 // FIXME: delay imports need work (push addr)
00231                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->dimports.funcs->get(*(entropy+i));
00232                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->dimports.libs->get(f->libidx);
00233                 if (f->byname) {
00234                         ht_snprintf(buffer, sizeof buffer, "; delay import function loader for %s, ordinal %04x", f->name.name, f->ordinal);
00235                 } else {
00236                         ht_snprintf(buffer, sizeof buffer, "; delay import function loader for ordinal %04x", f->ordinal);
00237                 }
00238                 char *label;
00239                 label = import_func_name(d->name, f->byname ? f->name.name : NULL, f->ordinal);
00240                 Address *faddr;
00241                 if (pe32) {
00242                         faddr = createAddress32(f->address);
00243                 } else {
00244                         faddr = createAddress64(to_qword(f->address));
00245                 }
00246                 addComment(faddr, 0, "");
00247                 addComment(faddr, 0, ";********************************************************");
00248                 addComment(faddr, 0, buffer);
00249                 addComment(faddr, 0, ";********************************************************");
00250                 assignSymbol(faddr, label, label_func);
00251                 free(label);
00252                 delete faddr;
00253         }
00254         if (entropy) free(entropy);
00255 
00256         addComment(entry, 0, "");
00257         addComment(entry, 0, ";****************************");
00258         if (pe_shared->coffheader.characteristics & COFF_DLL) {
00259                 addComment(entry, 0, ";  dll entry point");
00260         } else {
00261                 addComment(entry, 0, ";  program entry point");
00262         }
00263         addComment(entry, 0, ";****************************");
00264         assignSymbol(entry, "entrypoint", label_func);
00265 
00266         setLocationTreeOptimizeThreshold(1000);
00267         setSymbolTreeOptimizeThreshold(1000);
00268         delete entry;
00269 
00270         Analyser::beginAnalysis();
00271 }
00272 
00273 /*
00274  *
00275  */
00276 OBJECT_ID       PEAnalyser::object_id() const
00277 {
00278         return ATOM_PE_ANALYSER;
00279 }
00280 
00281 /*
00282  *
00283  */
00284 UINT PEAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00285 {
00286         FILEOFS ofs = addressToFileofs(Addr);
00287 /*      if (ofs == INVALID_FILE_OFS) {
00288                 int as=0;
00289         }*/
00290         assert(ofs != INVALID_FILE_OFS);
00291         file->seek(ofs);
00292         return file->read(buf, size);
00293 }
00294 
00295 bool PEAnalyser::convertAddressToRVA(Address *addr, RVA *r)
00296 {
00297         OBJECT_ID oid = addr->object_id();
00298         if (oid==ATOM_ADDRESS_FLAT_32) {
00299                 *r = ((AddressFlat32*)addr)->addr - pe_shared->pe32.header_nt.image_base;
00300                 return true;
00301         } else if (oid == ATOM_ADDRESS_X86_FLAT_32) {
00302                 *r = ((AddressX86Flat32*)addr)->addr - pe_shared->pe32.header_nt.image_base;
00303                 return true;
00304         } else if (oid == ATOM_ADDRESS_FLAT_64) {
00305                 qword q = ((AddressFlat64*)addr)->addr - pe_shared->pe64.header_nt.image_base;
00306                 if (QWORD_GET_HI(q)) return false;
00307                 *r = QWORD_GET_LO(q);
00308                 return true;
00309         }
00310         return false;
00311 }
00312 
00313 /*
00314  *
00315  */
00316 Address *PEAnalyser::createAddress32(dword addr)
00317 {
00318         switch (pe_shared->coffheader.machine) {
00319                 case COFF_MACHINE_I386:
00320                 case COFF_MACHINE_I486:
00321                 case COFF_MACHINE_I586:
00322                         return new AddressX86Flat32(addr);
00323         }
00324         // fallback to standard-addrs
00325         return new AddressFlat32(addr);
00326 }
00327 
00328 /*
00329  *
00330  */
00331 Address *PEAnalyser::createAddress64(qword addr)
00332 {
00333         return new AddressFlat64(addr);
00334 }
00335 
00336 Address *PEAnalyser::createAddress()
00337 {
00338         switch (pe_shared->coffheader.machine) {
00339                 case COFF_MACHINE_I386:
00340                 case COFF_MACHINE_I486:
00341                 case COFF_MACHINE_I586:
00342                         if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
00343                                 return new AddressFlat64();
00344                         } else {
00345                                 return new AddressX86Flat32();
00346                         }
00347         }
00348         if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
00349                 return new AddressFlat64();
00350         }
00351         return new AddressFlat32();
00352 }
00353 
00354 /*
00355  *
00356  */
00357 Assembler *PEAnalyser::createAssembler()
00358 {
00359         switch (pe_shared->coffheader.machine) {
00360                 case COFF_MACHINE_I386:
00361                 case COFF_MACHINE_I486:
00362                 case COFF_MACHINE_I586:
00363                         Assembler *a = new x86asm(X86_OPSIZE32, X86_ADDRSIZE32);
00364                         a->init();
00365                         return a;
00366         }
00367         return NULL;
00368 }
00369 
00370 /*
00371  *
00372  */
00373 FILEOFS PEAnalyser::addressToFileofs(Address *Addr)
00374 {
00375 /*     char tbuf[1024];
00376         Addr->stringify(tbuf, 1024, 0);
00377         printf("ADDR=%s", tbuf);*/
00378         if (validAddress(Addr, scinitialized)) {
00379 //      printf(" v1\n");
00380                 FILEOFS ofs;
00381                 RVA r;
00382                 if (!convertAddressToRVA(Addr, &r)) return INVALID_FILE_OFS;
00383                 if (!pe_rva_to_ofs(&pe_shared->sections, r, &ofs)) return INVALID_FILE_OFS;
00384                 return ofs;
00385         } else {
00386 //      printf(" IV1\n");
00387                 return INVALID_FILE_OFS;
00388         }
00389 }
00390 
00391 /*
00392  *
00393  */
00394 char *PEAnalyser::getSegmentNameByAddress(Address *Addr)
00395 {
00396         static char sectionname[9];
00397         pe_section_headers *sections=&pe_shared->sections;
00398         int i;
00399         RVA r;
00400 //      Addr-=pe_shared->pe32.header_nt.image_base;
00401         if (!convertAddressToRVA(Addr, &r)) return NULL;
00402         pe_rva_to_section(sections, r, &i);
00403         COFF_SECTION_HEADER *s=sections->sections+i;
00404         if (!pe_rva_is_valid(sections, r)) return NULL;
00405         memmove(sectionname, s->name, 8);
00406         sectionname[8]=0;
00407         return sectionname;
00408 }
00409 
00410 /*
00411  *
00412  */
00413 const char *PEAnalyser::getName()
00414 {
00415         return file->get_desc();
00416 }
00417 
00418 /*
00419  *
00420  */
00421 const char *PEAnalyser::getType()
00422 {
00423         return "PE/Analyser";
00424 }
00425 
00426 /*
00427  *
00428  */
00429 void PEAnalyser::initCodeAnalyser()
00430 {
00431         Analyser::initCodeAnalyser();
00432 }
00433 
00434 static char *string_func(dword ofs, void *context)
00435 {
00436         char str[1024];
00437         static char str2[1024];
00438         ht_pe_shared_data *pe = (ht_pe_shared_data*)context;
00439         if (ofs < pe->il->string_pool_size) {
00440                 dword length;
00441                 dword o = ILunpackDword(length, (byte*)&pe->il->string_pool[ofs], 10);
00442                 wide_char_to_multi_byte(str, (byte*)&pe->il->string_pool[ofs+o], length/2+1);
00443                 escape_special_str(str2, sizeof str2, str, "\"");
00444                 return str2;
00445         } else {
00446                 return NULL;
00447         }
00448 }
00449 
00450 static char *token_func(dword token, void *context)
00451 {
00452         static char tokenstr[1024];
00453 //      ht_pe_shared_data *pe = (ht_pe_shared_data*)context;
00454         switch (token & IL_META_TOKEN_MASK) {
00455                 case IL_META_TOKEN_TYPE_REF:
00456                 case IL_META_TOKEN_TYPE_DEF: {
00457                         sprintf(tokenstr, "typedef");
00458                         break;
00459                 }
00460                 case IL_META_TOKEN_FIELD_DEF: {
00461                         sprintf(tokenstr, "fielddef");
00462                         break;
00463                 }
00464                 case IL_META_TOKEN_METHOD_DEF: {
00465                         sprintf(tokenstr, "methoddef");
00466                         break;
00467                 }
00468                 case IL_META_TOKEN_MEMBER_REF: {
00469                         sprintf(tokenstr, "memberref");
00470                         break;
00471                 }
00472                 case IL_META_TOKEN_TYPE_SPEC: {
00473                         sprintf(tokenstr, "typespec");
00474                         break;
00475                 }
00476                 default:
00477                         return NULL;
00478         }
00479         return tokenstr;
00480 }
00481 
00482 /*
00483  *
00484  */
00485 void PEAnalyser::initUnasm()
00486 {
00487         bool pe64 = false;
00488         if (pe_shared->opt_magic == COFF_OPTMAGIC_PE64) {
00489                 pe64 = true;
00490         }
00491         DPRINTF("pe_analy: ");
00492         if (pe_shared->il) {
00493                 analy_disasm = new AnalyILDisassembler();
00494                 ((AnalyILDisassembler *)analy_disasm)->init(this, string_func, token_func, pe_shared);
00495         } else {
00496         switch (pe_shared->coffheader.machine) {
00497                 case COFF_MACHINE_I386: // Intel 386
00498                 case COFF_MACHINE_I486: // Intel 486
00499                 case COFF_MACHINE_I586: // Intel 586
00500                         if (pe64) {
00501                                 errorbox("x86 cant be used in PE64 format.");
00502                         } else {
00503                                 DPRINTF("initing analy_x86_disassembler\n");
00504                                 analy_disasm = new AnalyX86Disassembler();
00505                                 ((AnalyX86Disassembler *)analy_disasm)->init(this, 0);
00506                         }
00507                         break;
00508                 case COFF_MACHINE_R3000:        // MIPS little-endian, 0x160 big-endian
00509                         DPRINTF("no apropriate disassembler for MIPS\n");
00510                         warnbox("No disassembler for MIPS!");
00511                         break;
00512                 case COFF_MACHINE_R4000:        // MIPS little-endian
00513                         DPRINTF("no apropriate disassembler for MIPS\n");
00514                         warnbox("No disassembler for MIPS!");
00515                         break;
00516                 case COFF_MACHINE_R10000:       // MIPS little-endian
00517                         DPRINTF("no apropriate disassembler for MIPS\n");
00518                         warnbox("No disassembler for MIPS!");
00519                         break;
00520                 case COFF_MACHINE_ALPHA:        // Alpha_AXP
00521                         DPRINTF("initing alpha_axp_disassembler\n");
00522                         analy_disasm = new AnalyAlphaDisassembler();
00523                         ((AnalyAlphaDisassembler *)analy_disasm)->init(this);
00524                         break;
00525                 case COFF_MACHINE_POWERPC_LE:   // IBM PowerPC Little-Endian
00526                         DPRINTF("no apropriate disassembler for POWER PC\n");
00527                         warnbox("No disassembler for POWER PC!");
00528                         break;
00529                 case COFF_MACHINE_POWERPC_BE:
00530                         analy_disasm = new AnalyPPCDisassembler();
00531                         ((AnalyPPCDisassembler*)analy_disasm)->init(this);
00532                         break;          
00533                 case COFF_MACHINE_IA64:
00534                         if (!pe64) {
00535                                 errorbox("Intel IA64 cant be used in PE32 format.");
00536                         } else {
00537                                 analy_disasm = new AnalyIA64Disassembler();
00538                                 ((AnalyIA64Disassembler*)analy_disasm)->init(this);
00539                         }
00540                         break;          
00541                 case COFF_MACHINE_UNKNOWN:
00542                 default:
00543                         DPRINTF("no apropriate disassembler for machine %04x\n", pe_shared->coffheader.machine);
00544                         warnbox("No disassembler for unknown machine type %04x!", pe_shared->coffheader.machine);
00545         }
00546         }
00547 }
00548 
00549 /*
00550  *
00551  */
00552 void PEAnalyser::log(const char *msg)
00553 {
00554         /*
00555          *      log() creates to much traffic so dont log
00556          *   perhaps we reactivate this later
00557          *
00558          */
00559 /*      LOG(msg);*/
00560 }
00561 
00562 /*
00563  *
00564  */
00565 Address *PEAnalyser::nextValid(Address *Addr)
00566 {
00567         return (Address *)validarea->findNext(Addr);
00568 }
00569 
00570 /*
00571  *
00572  */
00573 void PEAnalyser::store(ht_object_stream *st)
00574 {
00575         /*
00576         ht_pe_shared_data       *pe_shared;
00577         ht_stream               *file;
00578         area                            *validarea;
00579         */
00580         PUT_OBJECT(st, validarea);
00581         Analyser::store(st);
00582 }
00583 
00584 /*
00585  *
00586  */
00587 int     PEAnalyser::queryConfig(int mode)
00588 {
00589         switch (mode) {
00590                 case Q_DO_ANALYSIS:
00591                 case Q_ENGAGE_CODE_ANALYSER:
00592                 case Q_ENGAGE_DATA_ANALYSER:
00593                         return true;
00594                 default:
00595                         return 0;
00596         }
00597 }
00598 
00599 /*
00600  *
00601  */
00602 Address *PEAnalyser::fileofsToAddress(FILEOFS fileofs)
00603 {
00604         RVA r;
00605         if (pe_ofs_to_rva(&pe_shared->sections, fileofs, &r)) {
00606                 if (pe_shared->opt_magic == COFF_OPTMAGIC_PE32) {
00607                         return createAddress32(r+pe_shared->pe32.header_nt.image_base);
00608                 } else {
00609                         return createAddress64(to_qword(r)+pe_shared->pe64.header_nt.image_base);
00610                 }
00611         } else {
00612                 return new InvalidAddress();
00613         }
00614 }
00615 
00616 /*
00617  *
00618  */
00619 bool PEAnalyser::validAddress(Address *Addr, tsectype action)
00620 {
00621         pe_section_headers *sections=&pe_shared->sections;
00622         int sec;
00623         RVA r;
00624         if (!convertAddressToRVA(Addr, &r)) return false;
00625         if (!pe_rva_to_section(sections, r, &sec)) return false;
00626         COFF_SECTION_HEADER *s=sections->sections+sec;
00627         switch (action) {
00628                 case scvalid:
00629                         return true;
00630                 case scread:
00631                         return s->characteristics & COFF_SCN_MEM_READ;
00632                 case scwrite:
00633                         return s->characteristics & COFF_SCN_MEM_WRITE;
00634                 case screadwrite:
00635                         return s->characteristics & COFF_SCN_MEM_WRITE;
00636                 case sccode:
00637                         // FIXME: EXECUTE vs. CNT_CODE ?
00638                         if (!pe_rva_is_physical(sections, r)) return false;
00639                         return (s->characteristics & (COFF_SCN_MEM_EXECUTE | COFF_SCN_CNT_CODE));
00640                 case scinitialized:
00641                         if (!pe_rva_is_physical(sections, r)) return false;
00642                         return true;
00643                         // !(s->characteristics & COFF_SCN_CNT_UNINITIALIZED_DATA);
00644         }
00645         return false;
00646 }
00647 
00648 

Generated on Fri May 7 21:15:42 2004 by doxygen 1.3.5