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

coff_analy.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      coff_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_names.h"
00028 #include "analy_register.h"
00029 #include "analy_ppc.h"
00030 #include "analy_x86.h"
00031 #include "coff_analy.h"
00032 #include "coff_s.h"
00033 #include "global.h"
00034 
00035 #include "htctrl.h"
00036 #include "htdebug.h"
00037 #include "htiobox.h"
00038 #include "htcoff.h"
00039 #include "htstring.h"
00040 #include "snprintf.h"
00041 #include "x86asm.h"
00042 
00043 /*
00044  *
00045  */
00046 void    CoffAnalyser::init(ht_coff_shared_data *Coff_shared, ht_streamfile *File)
00047 {
00048         coff_shared = Coff_shared;
00049         file = File;
00050 
00051         validarea = new Area();
00052         validarea->init();
00053 
00054         Analyser::init();
00055 
00057 
00058         setLocationTreeOptimizeThreshold(100);
00059         setSymbolTreeOptimizeThreshold(100);
00060 }
00061 
00062 
00063 /*
00064  *
00065  */
00066 int     CoffAnalyser::load(ht_object_stream *f)
00067 {
00068         /*
00069         ht_pe_shared_data       *pe_shared;
00070         ht_stream               *file;
00071         area                            *validarea;
00072         */
00073         GET_OBJECT(f, validarea);
00074         return Analyser::load(f);
00075 }
00076 
00077 /*
00078  *
00079  */
00080 void    CoffAnalyser::done()
00081 {
00082         validarea->done();
00083         delete validarea;
00084         Analyser::done();
00085 }
00086 
00087 /*
00088  *
00089  */
00090 void CoffAnalyser::beginAnalysis()
00091 {
00092 //      char    buffer[1024];
00093 
00094         /*
00095          *      entrypoint
00096          */
00097         Address *entry=createAddress32(coff_shared->coff32header.entrypoint_address);
00098         pushAddress(entry, entry);
00099         
00100         /*
00101          * give all sections a descriptive comment:
00102          */
00103 
00104         /*struct PE_SECTION_HEADER {
00105                 byte name[PE_SIZEOF_SHORT_NAME] __attribute__ ((packed));
00106                 dword data_vsize __attribute__ ((packed));
00107                 dword data_address __attribute__ ((packed));
00108                 dword data_size __attribute__   ((packed));
00109                 dword data_offset __attribute__ ((packed));
00110                 dword relocation_offset __attribute__ ((packed));
00111                 dword linenumber_offset __attribute__ ((packed));
00112                 word relocation_count __attribute__ ((packed));
00113                 word linenumber_count __attribute__ ((packed));
00114                 dword characteristics __attribute__ ((packed));
00115         };*/
00116         COFF_SECTION_HEADER *s=coff_shared->sections.sections;
00117         char blub[100];
00118         for (UINT i=0; i<coff_shared->sections.section_count; i++) {
00119                 Address *secaddr = createAddress32(s->data_address);
00120                 sprintf(blub, ";  section %d <%s>", i+1, getSegmentNameByAddress(secaddr));
00121                 addComment(secaddr, 0, "");
00122                 addComment(secaddr, 0, ";******************************************************************");
00123                 addComment(secaddr, 0, blub);
00124                 sprintf(blub, ";  virtual address  %08x  size   %08x", s->data_address, s->data_size);
00125                 addComment(secaddr, 0, blub);
00126                 sprintf(blub, ";  file offset      %08x", s->data_offset+coff_shared->hdr_ofs);
00127                 addComment(secaddr, 0, blub);
00128                 addComment(secaddr, 0, ";******************************************************************");
00129 
00130                 // mark end of sections
00131                 sprintf(blub, ";  end of section <%s>", getSegmentNameByAddress(secaddr));
00132                 Address *secend_addr = (Address*)secaddr->duplicate();
00133                 secend_addr->add(MAX(s->data_size, s->data_vsize));
00134                 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00135                 addComment(secend_addr, 0, "");
00136                 addComment(secend_addr, 0, ";******************************************************************");
00137                 addComment(secend_addr, 0, blub);
00138                 addComment(secend_addr, 0, ";******************************************************************");
00139 
00140                 validarea->add(secaddr, secend_addr);
00141                 Address *secini_addr = (Address *)secaddr->duplicate();
00142                 secini_addr->add(MIN(s->data_size, s->data_vsize));
00143                 if (validAddress(secaddr, scinitialized) && validAddress(secini_addr, scinitialized)) {
00144                         initialized->add(secaddr, secini_addr);
00145                 }
00146                 s++;
00147                 delete secaddr;
00148                 delete secend_addr;
00149                 delete secini_addr;
00150         }
00151 
00152         // exports
00153 
00154 /*      int export_count=coff_shared->exports.funcs->count();
00155         int *entropy = random_permutation(export_count);
00156         for (int i=0; i<export_count; i++) {
00157                 ht_pe_export_function *f=(ht_pe_export_function *)pe_shared->exports.funcs->get(*(entropy+i));
00158                 if (valid_addr(f->address, scvalid)) {
00159                         char *label;
00160                         if (f->byname) {
00161                                 sprintf(buffer, "; exported function %s, ordinal %04x", f->name, f->ordinal);
00162                         } else {
00163                                 sprintf(buffer, "; unnamed exported function, ordinal %04x", f->ordinal);
00164                         }
00165                         label = export_func_name((f->byname) ? f->name : NULL, f->ordinal);
00166                         add_comment(f->address, 0, "");
00167                         add_comment(f->address, 0, ";********************************************************");
00168                         add_comment(f->address, 0, buffer);
00169                         add_comment(f->address, 0, ";********************************************************");
00170                         push_addr(f->address, f->address);
00171                         assign_label(f->address, label, label_func);
00172                         free(label);
00173                 }
00174         }
00175         if (entropy) free(entropy);*/
00176 
00177 /*      int import_count=pe_shared->imports.funcs->count();
00178         entropy = random_permutation(import_count);
00179         for (int i=0; i<import_count; i++) {
00180                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->imports.funcs->get(*(entropy+i));
00181                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->imports.libs->get(f->libidx);
00182                 char *label;
00183                 label = import_func_name(d->name, (f->byname) ? f->name.name : NULL, f->ordinal);
00184                 add_comment(f->address, 0, "");
00185                 assign_label(f->address, label, label_func);
00186                 data->set_int_addr_type(f->address, dst_idword, 4);
00187                 free(label);
00188         }
00189         if (entropy) free(entropy);
00190 
00191         int dimport_count=pe_shared->dimports.funcs->count();
00192         entropy = random_permutation(dimport_count);
00193         for (int i=0; i<dimport_count; i++) {
00194                 // FIXME: delay imports need work (push addr)
00195                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->dimports.funcs->get(*(entropy+i));
00196                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->dimports.libs->get(f->libidx);
00197                 char *label;
00198                 label = import_func_name(d->name, f->byname ? f->name.name : NULL, f->ordinal);
00199                 add_comment(f->address, 0, "");
00200                 assign_label(f->address, label, label_func);
00201 //              data->setintaddrtype(f->address, dstidword, 4);
00202                 free(label);
00203         }
00204         if (entropy) free(entropy);*/
00205 
00206         addComment(entry, 0, "");
00207         addComment(entry, 0, ";****************************");
00208         if (coff_shared->coffheader.characteristics & COFF_DLL) {
00209                 addComment(entry, 0, ";  library entry point");
00210         } else {
00211                 addComment(entry, 0, ";  program entry point");
00212         }
00213         addComment(entry, 0, ";****************************");
00214         assignSymbol(entry, "entrypoint", label_func);
00215 
00216         setLocationTreeOptimizeThreshold(1000);
00217         setSymbolTreeOptimizeThreshold(1000);
00218         delete entry;
00219 
00220         Analyser::beginAnalysis();
00221 }
00222 
00223 /*
00224  *
00225  */
00226 OBJECT_ID       CoffAnalyser::object_id() const
00227 {
00228         return ATOM_COFF_ANALYSER;
00229 }
00230 
00231 /*
00232  *
00233  */
00234 UINT CoffAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00235 {
00236         FILEOFS ofs = addressToFileofs(Addr);
00237         assert(ofs != INVALID_FILE_OFS);
00238         file->seek(ofs);
00239         return file->read(buf, size);
00240 }
00241 
00242 bool CoffAnalyser::convertAddressToRVA(Address *addr, RVA *r)
00243 {
00244         if (addr->object_id()==ATOM_ADDRESS_X86_FLAT_32) {
00245                 *r = ((AddressX86Flat32*)addr)->addr;
00246         } else if (addr->object_id()==ATOM_ADDRESS_FLAT_32) {
00247                 *r = ((AddressFlat32*)addr)->addr;
00248         } else {
00249                 return false;
00250         }
00251         return true;
00252 }
00253 
00254 Address *CoffAnalyser::createAddress()
00255 {
00256         switch (coff_shared->coffheader.machine) {
00257                 case COFF_MACHINE_I386:
00258                 case COFF_MACHINE_I486:
00259                 case COFF_MACHINE_I586:
00260                         return new AddressX86Flat32(0);
00261                 default:
00262                         return new AddressFlat32(0);
00263         }
00264 }
00265 
00266 Address *CoffAnalyser::createAddress32(dword addr)
00267 {
00268         switch (coff_shared->coffheader.machine) {
00269                 case COFF_MACHINE_I386:
00270                 case COFF_MACHINE_I486:
00271                 case COFF_MACHINE_I586:
00272                         return new AddressX86Flat32(addr);
00273                 default:
00274                         return new AddressFlat32(addr);
00275         }
00276 }
00277 
00278 /*
00279  *
00280  */
00281 Assembler *CoffAnalyser::createAssembler()
00282 {
00283         switch (coff_shared->coffheader.machine) {
00284                 case COFF_MACHINE_I386:
00285                 case COFF_MACHINE_I486:
00286                 case COFF_MACHINE_I586:
00287                         Assembler *a = new x86asm(X86_OPSIZE32, X86_ADDRSIZE32);
00288                         a->init();
00289                         return a;
00290         }
00291         return NULL;
00292 }
00293 
00294 
00295 /*
00296  *
00297  */
00298 FILEOFS CoffAnalyser::addressToFileofs(Address *Addr)
00299 {
00300         if (validAddress(Addr, scinitialized)) {
00301                 FILEOFS ofs;
00302 //              Addr-=pe_shared->pe32.header_nt.image_base;
00303                 RVA rva;
00304                 if (!convertAddressToRVA(Addr, &rva)) return INVALID_FILE_OFS;
00305                 if (!coff_rva_to_ofs(&coff_shared->sections, rva, &ofs)) return INVALID_FILE_OFS;
00306                 return ofs;
00307         } else {
00308                 return INVALID_FILE_OFS;
00309         }
00310 }
00311 
00312 /*
00313  *
00314  */
00315 char *CoffAnalyser::getSegmentNameByAddress(Address *Addr)
00316 {
00317         static char sectionname[9];
00318         coff_section_headers *sections=&coff_shared->sections;
00319         int i;
00320         RVA rva;
00321         if (!convertAddressToRVA(Addr, &rva)) return NULL;
00322         coff_rva_to_section(sections, rva, &i);
00323         COFF_SECTION_HEADER *s=sections->sections+i;
00324         if (!coff_rva_is_valid(sections, rva)) return NULL;
00325         memmove(sectionname, s->name, 8);
00326         sectionname[8]=0;
00327         return sectionname;
00328 }
00329 
00330 /*
00331  *
00332  */
00333 const char *CoffAnalyser::getName()
00334 {
00335         return file->get_desc();
00336 }
00337 
00338 /*
00339  *
00340  */
00341 const char *CoffAnalyser::getType()
00342 {
00343         return "COFF/Analyser";
00344 }
00345 
00346 /*
00347  *
00348  */
00349 void CoffAnalyser::initCodeAnalyser()
00350 {
00351         Analyser::initCodeAnalyser();
00352 }
00353 
00354 /*
00355  *
00356  */
00357 void CoffAnalyser::initUnasm()
00358 {
00359         DPRINTF("coff_analy: ");
00360         switch (coff_shared->coffheader.machine) {
00361                 case COFF_MACHINE_I386: // Intel 386
00362                 case COFF_MACHINE_I486: // Intel 486
00363                 case COFF_MACHINE_I586: // Intel 586
00364                         DPRINTF("initing analy_x86_disassembler\n");
00365                         analy_disasm = new AnalyX86Disassembler();
00366                         ((AnalyX86Disassembler*)analy_disasm)->init(this, 0);
00367                         break;
00368                 case COFF_MACHINE_R3000:        // MIPS little-endian, 0x160 big-endian
00369                         DPRINTF("no apropriate disassembler for MIPS\n");
00370                         warnbox("No disassembler for MIPS!");
00371                         break;
00372                 case COFF_MACHINE_R4000:        // MIPS little-endian
00373                         DPRINTF("no apropriate disassembler for MIPS\n");
00374                         warnbox("No disassembler for MIPS!");
00375                         break;
00376                 case COFF_MACHINE_R10000:       // MIPS little-endian
00377                         DPRINTF("no apropriate disassembler for MIPS\n");
00378                         warnbox("No disassembler for MIPS!");
00379                         break;
00380                 case COFF_MACHINE_ALPHA:        // Alpha_AXP
00381                         DPRINTF("initing alpha_axp_disassembler\n");
00382                         analy_disasm = new AnalyAlphaDisassembler();
00383                         ((AnalyAlphaDisassembler *)analy_disasm)->init(this);
00384                         break;
00385                 case COFF_MACHINE_POWERPC_LE:   // IBM PowerPC Little-Endian
00386                         DPRINTF("no apropriate disassembler for POWER PC\n");
00387                         warnbox("No disassembler for POWER PC!");
00388                         break;
00389                 case COFF_MACHINE_POWERPC_BE:
00390                         analy_disasm = new AnalyPPCDisassembler();
00391                         ((AnalyPPCDisassembler*)analy_disasm)->init(this);
00392                         break;          
00393                 case COFF_MACHINE_UNKNOWN:
00394                 default:
00395                         DPRINTF("no apropriate disassembler for machine %04x\n", coff_shared->coffheader.machine);
00396                         warnbox("No disassembler for unknown machine type %04x!", coff_shared->coffheader.machine);
00397         }
00398 }
00399 
00400 /*
00401  *
00402  */
00403 void CoffAnalyser::log(const char *msg)
00404 {
00405         /*
00406          *      log() creates to much traffic so dont log
00407          *   perhaps we reactivate this later
00408          *
00409          */
00410 /*      LOG(msg);*/
00411 }
00412 
00413 /*
00414  *
00415  */
00416 Address *CoffAnalyser::nextValid(Address *Addr)
00417 {
00418         return (Address *)validarea->findNext(Addr);
00419 }
00420 
00421 /*
00422  *
00423  */
00424 void CoffAnalyser::store(ht_object_stream *st)
00425 {
00426         /*
00427         ht_pe_shared_data       *pe_shared;
00428         ht_stream               *file;
00429         area                            *validarea;
00430         */
00431         PUT_OBJECT(st, validarea);
00432         Analyser::store(st);
00433 }
00434 
00435 /*
00436  *
00437  */
00438 int     CoffAnalyser::queryConfig(int mode)
00439 {
00440         switch (mode) {
00441                 case Q_DO_ANALYSIS:
00442                 case Q_ENGAGE_CODE_ANALYSER:
00443                 case Q_ENGAGE_DATA_ANALYSER:
00444                         return true;
00445                 default:
00446                         return 0;
00447         }
00448 }
00449 
00450 /*
00451  *
00452  */
00453 Address *CoffAnalyser::fileofsToAddress(FILEOFS fileofs)
00454 {
00455         RVA a;
00456         if (coff_ofs_to_rva(&coff_shared->sections, fileofs, &a)) {
00457                 return createAddress32(a);
00458         } else {
00459                 return new InvalidAddress();
00460         }
00461 }
00462 
00463 /*
00464  *
00465  */
00466 bool CoffAnalyser::validAddress(Address *Addr, tsectype action)
00467 {
00468         coff_section_headers *sections=&coff_shared->sections;
00469         int sec;
00470         RVA rva;
00471         if (!convertAddressToRVA(Addr, &rva)) return false;
00472         if (!coff_rva_to_section(sections, rva, &sec)) return false;
00473         COFF_SECTION_HEADER *s=sections->sections+sec;
00474         switch (action) {
00475                 case scvalid:
00476                         return true;
00477                 case scread:
00478                         return s->characteristics & COFF_SCN_MEM_READ;
00479                 case scwrite:
00480                         return s->characteristics & COFF_SCN_MEM_WRITE;
00481                 case screadwrite:
00482                         return s->characteristics & COFF_SCN_MEM_WRITE;
00483                 case sccode:
00484                         // FIXME: EXECUTE vs. CNT_CODE ?
00485                         if (!coff_rva_is_physical(sections, rva)) return false;
00486                         return (s->characteristics & (COFF_SCN_MEM_EXECUTE | COFF_SCN_CNT_CODE));
00487                 case scinitialized:
00488                         if (!coff_rva_is_physical(sections, rva)) return false;
00489                         return !(s->characteristics & COFF_SCN_CNT_UNINITIALIZED_DATA);
00490         }
00491         return false;
00492 }
00493 
00494 

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