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

le_analy.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      le_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_x86.h"
00030 #include "global.h"
00031 #include "htanaly.h"            // FIXME: for ht_aviewer, to call gotoAddress(entrypoint)
00032 #include "le_analy.h"
00033 
00034 #include "htctrl.h"
00035 #include "htdebug.h"
00036 #include "htendian.h"
00037 #include "htiobox.h"
00038 #include "htle.h"
00039 #include "htstring.h"
00040 #include "nestruct.h"
00041 #include "snprintf.h"
00042 #include "x86asm.h"
00043 
00044 /*
00045  *
00046  */
00047 void    LEAnalyser::init(ht_le_shared_data *LE_shared, ht_streamfile *File)
00048 {
00049         le_shared = LE_shared;
00050         file = File;
00051 
00052         validarea = new Area();
00053         validarea->init();
00054 
00055         Analyser::init();
00056 
00058 
00059         setLocationTreeOptimizeThreshold(100);
00060         setSymbolTreeOptimizeThreshold(100);
00061 }
00062 
00063 
00064 /*
00065  *
00066  */
00067 int     LEAnalyser::load(ht_object_stream *f)
00068 {
00069         /*
00070         ht_pe_shared_data       *pe_shared;
00071         ht_stream               *file;
00072         area                            *validarea;
00073         */
00074         GET_OBJECT(f, validarea);
00075         return Analyser::load(f);
00076 }
00077 
00078 /*
00079  *
00080  */
00081 void    LEAnalyser::done()
00082 {
00083         validarea->done();
00084         delete validarea;
00085         Analyser::done();
00086 }
00087 
00088 /*
00089  *
00090  */
00091 void LEAnalyser::beginAnalysis()
00092 {
00093 //      char    buffer[1024];
00094 
00095         /*
00096          *      entrypoint
00097          */
00098 
00099         LEAddress a;
00100         Address *control = NULL;
00101         Address *v86control = NULL;
00102         Address *pmcontrol = NULL;
00103         if (le_shared->is_vxd) {
00104                 LEAddress addr;
00105                 int temp;
00106 
00107                 addr = le_shared->vxd_desc.v86_ctrl_ofs;
00108                 if (LE_addr_to_segment(le_shared, addr, &temp)) {
00109                         a = LE_MAKE_ADDR(le_shared, LE_ADDR_SEG(le_shared, addr),
00110                                 LE_ADDR_OFS(le_shared, addr));
00111                         v86control = createAddressFlat32(a);
00112                         le_shared->best_entrypoint = a;
00113                 }
00114 
00115                 addr = le_shared->vxd_desc.pm_ctrl_ofs;
00116                 if (LE_addr_to_segment(le_shared, addr, &temp)) {
00117                         a = LE_MAKE_ADDR(le_shared, LE_ADDR_SEG(le_shared, addr),
00118                                 LE_ADDR_OFS(le_shared, addr));
00119                         pmcontrol = createAddressFlat32(a);
00120                         le_shared->best_entrypoint = a;
00121                 }
00122                 
00123                 addr = le_shared->vxd_desc.ctrl_ofs;
00124                 if (LE_addr_to_segment(le_shared, addr, &temp)) {
00125                         a = LE_MAKE_ADDR(le_shared, LE_ADDR_SEG(le_shared, addr),
00126                                 LE_ADDR_OFS(le_shared, addr));
00127                         control = createAddressFlat32(a);
00128                         le_shared->best_entrypoint = a;
00129                 }
00130         }
00131 
00132         Address *entry = NULL;
00133         if (le_shared->hdr.startobj != 0) {
00134                 a = LE_MAKE_ADDR(le_shared, le_shared->hdr.startobj-1, le_shared->hdr.eip);
00135                 le_shared->best_entrypoint = a;
00136                 entry = createAddressFlat32(a);
00137         }
00138 
00139         if (v86control) pushAddress(v86control, v86control);
00140 
00141         if (pmcontrol) pushAddress(pmcontrol, pmcontrol);
00142 
00143         if (control) pushAddress(control, control);
00144 
00145         if (entry) pushAddress(entry, entry);
00146 
00147         /*
00148          * give all sections a descriptive comment:
00149          */
00150 
00151         LE_OBJECT *s = le_shared->objmap.header;
00152         char blub[100];
00153         for (UINT i = 0; i < le_shared->objmap.count; i++) {
00154                 LEAddress la = LE_get_seg_addr(le_shared, i);
00155                 Address *secaddr = createAddressFlat32(la);
00156 
00157 //              UINT psize = LE_get_seg_psize(le_shared, i);
00158                 UINT vsize = LE_get_seg_vsize(le_shared, i);
00159 
00160                 sprintf(blub, ";  section %d <%s> USE%d", i+1, getSegmentNameByAddress(secaddr), (le_shared->objmap.header[i].flags & LE_OBJECT_FLAG_USE32) ? 32 : 16);
00161                 addComment(secaddr, 0, "");
00162                 addComment(secaddr, 0, ";******************************************************************");
00163                 addComment(secaddr, 0, blub);
00164                 sprintf(blub, ";  virtual address  %08x  virtual size   %08x", LE_get_seg_addr(le_shared, i), vsize);
00165                 addComment(secaddr, 0, blub);
00166 /*              sprintf(blub, ";  file offset      %08x  file size      %08x", psize);
00167                 addComment(secaddr, 0, blub);*/
00168                 addComment(secaddr, 0, ";******************************************************************");
00169 
00170                 // mark end of sections
00171                 sprintf(blub, ";  end of section <%s>", getSegmentNameByAddress(secaddr));
00172                 Address *secend_addr = (Address *)secaddr->duplicate();
00173                 secend_addr->add(vsize);
00174                 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00175                 addComment(secend_addr, 0, "");
00176                 addComment(secend_addr, 0, ";******************************************************************");
00177                 addComment(secend_addr, 0, blub);
00178                 addComment(secend_addr, 0, ";******************************************************************");
00179 
00180                 validarea->add(secaddr, secend_addr);
00181                 Address *seciniaddr = (Address *)secaddr->duplicate();
00182                 seciniaddr->add(vsize-1);
00183                 if (validAddress(secaddr, scinitialized) && validAddress(seciniaddr, scinitialized)) {
00184                         initialized->add(secaddr, seciniaddr);
00185                 }
00186                 delete secaddr;
00187                 delete secend_addr;
00188                 delete seciniaddr;
00189                 s++;
00190         }
00191 
00192         // entrypoints
00193 /*
00194         int entrypoint_count = le_shared->entrypoints->count();
00195         int *entropy = random_permutation(entrypoint_count);
00196         for (int i=0; i<entrypoint_count; i++) {
00197                 ht_ne_entrypoint *f = (ht_ne_entrypoint*)le_shared->entrypoints->get(*(entropy+i));
00198                 if (f) {
00199                         Address *address = createAddress1616(f->seg, f->offset);
00200                         if (validAddress(address, scvalid)) {
00201                                 char *label;
00202                                 if (f->name) {
00203                                         sprintf(buffer, "; exported function %s, ordinal %04x", f->name, f->ordinal);
00204                                 } else {
00205                                         sprintf(buffer, "; unnamed exported function, ordinal %04x", f->ordinal);
00206                                 }
00207                                 label = export_func_name(f->name, f->ordinal);
00208                                 addComment(address, 0, "");
00209                                 addComment(address, 0, ";********************************************************");
00210                                 addComment(address, 0, buffer);
00211                                 addComment(address, 0, ";********************************************************");
00212                                 pushAddress(address, address);
00213                                 assignSymbol(address, label, label_func);
00214                                 free(label);
00215                         }
00216                         delete address;
00217                 }
00218         }
00219         if (entropy) free(entropy);
00220 */
00221         // imports
00222 /*
00223         if (le_shared->imports) {
00224                 ht_tree *t = le_shared->imports;
00225                 Object *v;
00226                 ne_import_rec *imp = NULL;
00227                 FILEOFS h = le_shared->hdr_ofs + le_shared->hdr.imptab;
00228                 while ((imp = (ne_import_rec*)t->enum_next(&v, imp))) {
00229                         char *name = NULL;
00230                         char *mod = (imp->module-1 < le_shared->modnames_count) ? le_shared->modnames[imp->module-1] : (char*)"invalid!";
00231                         if (imp->byname) {
00232                                 file->seek(h+imp->name_ofs);
00233                                 name = getstrp(file);
00234                         }
00235                         char *label = import_func_name(mod, name, imp->byname ? 0 : imp->ord);
00236                         if (name) free(name);
00237                         Address *addr = createAddress1616(le_shared->fake_segment+1, imp->addr);
00238                         addComment(addr, 0, "");
00239                         assignSymbol(addr, label, label_func);
00240                         data->setIntAddressType(addr, dst_ibyte, 1);
00241                         free(label);
00242                         delete addr;
00243                 }
00244         }
00245 */
00246 
00247 /*      virtual Object *enum_next(Object **value, Object *prevkey);
00248         int import_count = le_shared->imports.funcs->count();
00249         for (int i=0; i<import_count; i++) {
00250                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->imports.funcs->get(*(entropy+i));
00251                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->imports.libs->get(f->libidx);
00252                 char *label;
00253                 label = import_func_name(d->name, (f->byname) ? f->name.name : NULL, f->ordinal);
00254                 addComment(f->address, 0, "");
00255                 assignSymbol(f->address, label, label_func);
00256                 data->set_int_addr_type(f->address, dst_idword, 4);
00257                 free(label);
00258         }*/
00259 
00260         if (le_shared->is_vxd) {
00261                 if (v86control) {
00262                         addComment(v86control, 0, "");
00263                         addComment(v86control, 0, ";****************************");
00264                         addComment(v86control, 0, ";  VxD V86-control procedure");
00265                         addComment(v86control, 0, ";****************************");
00266                         assignSymbol(v86control, "VxD_v86_control", label_func);
00267                 }
00268                 if (pmcontrol) {
00269                         addComment(pmcontrol, 0, "");
00270                         addComment(pmcontrol, 0, ";****************************");
00271                         addComment(pmcontrol, 0, ";  VxD PM-control procedure");
00272                         addComment(pmcontrol, 0, ";****************************");
00273                         assignSymbol(pmcontrol, "VxD_pm_control", label_func);
00274                 }
00275                 if (control) {
00276                         addComment(control, 0, "");
00277                         addComment(control, 0, ";****************************");
00278                         addComment(control, 0, ";  VxD control procedure");
00279                         addComment(control, 0, ";****************************");
00280                         assignSymbol(control, "VxD_control", label_func);
00281                 }
00282         }
00283 
00284         if (entry) {
00285                 addComment(entry, 0, "");
00286                 addComment(entry, 0, ";****************************");
00287                 addComment(entry, 0, ";  program entry point");
00288                 addComment(entry, 0, ";****************************");
00289                 if (validCodeAddress(entry)) {
00290                         assignSymbol(entry, "entrypoint", label_func);
00291                 } else {
00292                         assignSymbol(entry, "entrypoint", label_data);
00293                 }
00294         }
00295 
00296         setLocationTreeOptimizeThreshold(1000);
00297         setSymbolTreeOptimizeThreshold(1000);
00298         delete entry;
00299 
00300         if (le_shared->best_entrypoint != LE_ADDR_INVALID) {
00301                 Address *tmpaddr = createAddressFlat32(le_shared->best_entrypoint);
00302                 ((ht_aviewer*)le_shared->v_image)->gotoAddress(tmpaddr, NULL);
00303                 delete tmpaddr;
00304         }
00305 
00306         Analyser::beginAnalysis();
00307 }
00308 
00309 /*
00310  *
00311  */
00312 OBJECT_ID       LEAnalyser::object_id() const
00313 {
00314         return ATOM_LE_ANALYSER;
00315 }
00316 
00317 /*
00318  *
00319  */
00320 FILEOFS LEAnalyser::addressToFileofs(Address *Addr)
00321 {
00322         if (validAddress(Addr, scinitialized)) {
00323                 FILEOFS ofs;
00324                 LEAddress na;
00325                 if (!convertAddressToLEAddress(Addr, &na)) return INVALID_FILE_OFS;
00326                 if (!LE_addr_to_ofs(le_shared, na, &ofs)) {
00327                         return INVALID_FILE_OFS;
00328                 }
00329                 return ofs;
00330 /*          UINT m;
00331                 FILEOFS oo;
00332                 if (!le_shared->linear_file->map_ofs(ofs, &oo, &m)) {
00333                         le_shared->linear_file->map_ofs(ofs, &oo, &m);
00334                         return INVALID_FILE_OFS;
00335                 }
00336                 return oo;*/
00337         } else {
00338                 return INVALID_FILE_OFS;
00339         }
00340 }
00341 
00342 FILEOFS LEAnalyser::addressToRealFileofs(Address *Addr)
00343 {
00344         if (validAddress(Addr, scinitialized)) {
00345                 FILEOFS ofs;
00346                 LEAddress na;
00347                 if (!convertAddressToLEAddress(Addr, &na)) return INVALID_FILE_OFS;
00348                 if (!LE_addr_to_ofs(le_shared, na, &ofs)) {
00349                         return INVALID_FILE_OFS;
00350                 }
00351                 UINT m;
00352                 FILEOFS oo;
00353                 if (!le_shared->linear_file->map_ofs(ofs, &oo, &m)) {
00354                         return INVALID_FILE_OFS;
00355                 }
00356                 return oo;
00357         } else {
00358                 return INVALID_FILE_OFS;
00359         }
00360 }
00361 
00362 /*
00363  *
00364  */
00365 UINT LEAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00366 {
00367         FILEOFS ofs = addressToFileofs(Addr);
00368 /*     if (ofs == INVALID_FILE_OFS) {
00369                 ht_printf("%y", Addr);
00370                 int as=1;
00371         }*/
00372         assert(ofs != INVALID_FILE_OFS);
00373         file->seek(ofs);
00374         return file->read(buf, size);
00375 }
00376 
00377 bool LEAnalyser::convertAddressToLEAddress(Address *addr, LEAddress *r)
00378 {
00379         if (addr->object_id()==ATOM_ADDRESS_X86_FLAT_32) {
00380 //              *r = LE_MAKE_ADDR(le_shared, ((AddressX86Flat32*)addr)->seg, ((AddressX86_1632*)addr)->addr);
00381                 *r = ((AddressX86Flat32*)addr)->addr;
00382                 return true;
00383         } else {
00384                 return false;
00385         }
00386 }
00387 
00388 Address *LEAnalyser::createAddress()
00389 {
00390         return new AddressX86Flat32(0);
00391 }
00392 
00393 Address *LEAnalyser::createAddressFlat32(uint32 ofs)
00394 {
00395         return new AddressX86Flat32(ofs);
00396 }
00397 
00398 /*
00399  *
00400  */
00401 Assembler *LEAnalyser::createAssembler()
00402 {
00403 /* FIXME: 16/32 */
00404         Assembler *a = new x86asm(X86_OPSIZE32, X86_ADDRSIZE32);
00405         a->init();
00406         return a;
00407 }
00408 
00409 /*
00410  *
00411  */
00412 char *LEAnalyser::getSegmentNameByAddress(Address *Addr)
00413 {
00414         static char segmentname[16];
00415         int i;
00416         LEAddress na;
00417         if (!convertAddressToLEAddress(Addr, &na)) return NULL;
00418         if (!LE_addr_to_segment(le_shared, na, &i)) return NULL;
00419 //      LEAddress temp;
00420 /*      bool init = LE_addr_to_ofs(le_shared, na, &temp);
00421         if (!init)
00422                 return NULL;*/
00423 /*      if (i == (int)le_shared->fake_segment) {
00424                 strcpy(segmentname, "faked names");
00425         } else {*/
00426                 sprintf(segmentname, "seg%d", i+1);
00427 //      }
00428         return segmentname;
00429 }
00430 
00431 /*
00432  *
00433  */
00434 const char *LEAnalyser::getName()
00435 {
00436         return file->get_desc();
00437 }
00438 
00439 /*
00440  *
00441  */
00442 const char *LEAnalyser::getType()
00443 {
00444         return "LE/Analyser";
00445 }
00446 
00447 /*
00448  *
00449  */
00450 void LEAnalyser::initCodeAnalyser()
00451 {
00452         Analyser::initCodeAnalyser();
00453 }
00454 
00455 /*
00456  *
00457  */
00458 void LEAnalyser::initUnasm()
00459 {
00460         DPRINTF("le_analy: ");
00461         DPRINTF("initing analy_x86_disassembler\n");
00462         analy_disasm = new AnalyX86Disassembler();
00463         ((AnalyX86Disassembler*)analy_disasm)->init(this, le_shared->is_vxd ? ANALYX86DISASSEMBLER_FLAGS_VXD_X86DIS : 0);
00464 }
00465 
00466 /*
00467  *
00468  */
00469 void LEAnalyser::log(const char *msg)
00470 {
00471         /*
00472          *      log() creates to much traffic so dont log
00473          *   perhaps we reactivate this later
00474          *
00475          */
00476 /*      LOG(msg);*/
00477 }
00478 
00479 /*
00480  *
00481  */
00482 Address *LEAnalyser::nextValid(Address *Addr)
00483 {
00484         return (Address *)validarea->findNext(Addr);
00485 }
00486 
00487 /*
00488  *
00489  */
00490 void LEAnalyser::store(ht_object_stream *st)
00491 {
00492         PUT_OBJECT(st, validarea);
00493         Analyser::store(st);
00494 }
00495 
00496 /*
00497  *
00498  */
00499 int     LEAnalyser::queryConfig(int mode)
00500 {
00501         switch (mode) {
00502                 case Q_DO_ANALYSIS:
00503                 case Q_ENGAGE_CODE_ANALYSER:
00504                 case Q_ENGAGE_DATA_ANALYSER:
00505                         return true;
00506                 default:
00507                         return 0;
00508         }
00509 }
00510 
00511 /*
00512  *
00513  */
00514 Address *LEAnalyser::fileofsToAddress(FILEOFS fileofs)
00515 {
00516         LEAddress a;
00517         if (LE_ofs_to_addr(le_shared, fileofs, &a)) {
00518                 return createAddressFlat32(a);
00519         } else {
00520                 return new InvalidAddress();
00521         }
00522 }
00523 
00524 /*
00525  *
00526  */
00527 
00528 /* FIXME: fileofs chaos */
00529 Address *LEAnalyser::realFileofsToAddress(FILEOFS fileofs)
00530 {
00531         LEAddress a;
00532         UINT lofs;
00533         if (le_shared->linear_file->unmap_ofs(fileofs, &lofs) &&
00534         LE_ofs_to_addr(le_shared, lofs, &a)) {
00535                 return createAddressFlat32(a);
00536         } else {
00537                 return new InvalidAddress();
00538         }
00539 }
00540 
00541 /*
00542  *
00543  */
00544 bool LEAnalyser::validAddress(Address *Addr, tsectype action)
00545 {
00546         ht_le_objmap *objects = &le_shared->objmap;
00547         int sec;
00548         LEAddress na;
00549         if (!convertAddressToLEAddress(Addr, &na)) return false;
00550         if (!LE_addr_to_segment(le_shared, na, &sec)) return false;
00551         LEAddress temp;
00552         bool init = LE_addr_to_ofs(le_shared, na, &temp);
00553         LE_OBJECT *s = objects->header + sec;
00554 
00555         switch (action) {
00556                 case scvalid:
00557                         return true;
00558                 case scread:
00559                         return (s->flags & LE_OBJECT_FLAG_READABLE);
00560                 case scwrite:
00561                         return (s->flags & LE_OBJECT_FLAG_WRITEABLE);
00562                 case screadwrite:
00563                         return (s->flags & LE_OBJECT_FLAG_READABLE) && (s->flags & LE_OBJECT_FLAG_WRITEABLE);
00564                 case sccode:
00565                         return (s->flags & LE_OBJECT_FLAG_EXECUTABLE) && init;
00566                 case scinitialized:
00567                         return init;
00568         }
00569         return false;
00570 }
00571 

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