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

ne_analy.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      ne_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 "ne_analy.h"
00032 
00033 #include "htctrl.h"
00034 #include "htdebug.h"
00035 #include "htendian.h"
00036 #include "htiobox.h"
00037 #include "htne.h"
00038 #include "htneent.h"
00039 #include "htstring.h"
00040 #include "nestruct.h"
00041 #include "snprintf.h"
00042 #include "x86asm.h"
00043 
00044 /*
00045  *
00046  */
00047 void    NEAnalyser::init(ht_ne_shared_data *NE_shared, ht_streamfile *File)
00048 {
00049         ne_shared = NE_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     NEAnalyser::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    NEAnalyser::done()
00082 {
00083         validarea->done();
00084         delete validarea;
00085         Analyser::done();
00086 }
00087 
00088 /*
00089  *
00090  */
00091 void NEAnalyser::beginAnalysis()
00092 {
00093         char    buffer[1024];
00094 
00095         /*
00096          *      entrypoint
00097          */
00098          
00099         Address *entry = createAddress1616(NE_ADDR_SEG(ne_shared->hdr.csip), NE_ADDR_OFS(ne_shared->hdr.csip));
00100         
00101         if (ne_shared->hdr.flags & NE_FLAGS_SELFLOAD) {
00102                 // bound as family app (needs loader)
00103                 struct bla {
00104                     NEAddress a;
00105                     char *b;
00106                     char *c;
00107                 };
00108                 bla blabla[] = {
00109                         { NE_MAKE_ADDR(0x0001, 0x0004), "loader_ptr_1", "loader_entry_1"},
00110                         { NE_MAKE_ADDR(0x0001, 0x0008), "loader_ptr_2", "loader_entry_2"},
00111                         { NE_MAKE_ADDR(0x0001, 0x0018), "loader_ptr_3", "loader_entry_3"},
00112                         { 0, 0, 0 },
00113                 };
00114                 bla *blla = blabla;
00115                 while (blla->b) {
00116                         Address *bllaa = createAddress1616(NE_ADDR_SEG(blla->a), NE_ADDR_OFS(blla->a));
00117                         addComment(bllaa, 0, "");
00118                         assignSymbol(bllaa, blla->b, label_data);
00119                         data->setIntAddressType(bllaa, dst_idword, 4);
00120                         NEAddress addr;
00121                         byte buf[4];
00122                         if (validAddress(bllaa, scinitialized) && bufPtr(bllaa, buf, 4)==4) {
00123                                 sprintf(buffer, "; pointer to %s", blla->c);
00124                                 addComment(bllaa, 0, buffer);
00125                                 addr = create_host_int(buf, 4, little_endian);
00126                                 Address *a = createAddress1616(NE_ADDR_SEG(addr), NE_ADDR_OFS(addr));
00127                                 addComment(a, 0, "");
00128                                 assignSymbol(a, blla->c, label_func);
00129                                 pushAddress(a, a);
00130                                 delete a;
00131                         }
00132                         blla++;
00133                         delete bllaa;
00134                 }
00135         } else {
00136                 pushAddress(entry, entry);
00137         }
00138         
00139         /*
00140          * give all sections a descriptive comment:
00141          */
00142 
00143         NE_SEGMENT *s = ne_shared->segments.segments;
00144         char blub[100];
00145         for (UINT i = 0; i < ne_shared->segments.segment_count; i++) {
00146                 Address *secaddr = createAddress1616(NE_ADDR_SEG(NE_get_seg_addr(ne_shared, i)), NE_ADDR_OFS(NE_get_seg_addr(ne_shared, i)));
00147 
00148                 UINT epsize = MIN(NE_get_seg_vsize(ne_shared, i), NE_get_seg_psize(ne_shared, i));
00149                 UINT evsize = MAX(NE_get_seg_vsize(ne_shared, i), NE_get_seg_psize(ne_shared, i));
00150 
00151                 sprintf(blub, ";  section %d <%s>", i+1, getSegmentNameByAddress(secaddr));
00152                 addComment(secaddr, 0, "");
00153                 addComment(secaddr, 0, ";******************************************************************");
00154                 addComment(secaddr, 0, blub);
00155                 sprintf(blub, ";  virtual address  %08x  virtual size   %08x", NE_get_seg_addr(ne_shared, i), evsize);
00156                 addComment(secaddr, 0, blub);
00157                 sprintf(blub, ";  file offset      %08x  file size      %08x", NE_get_seg_ofs(ne_shared, i), epsize);
00158                 addComment(secaddr, 0, blub);
00159                 addComment(secaddr, 0, ";******************************************************************");
00160 
00161                 // mark end of sections
00162                 sprintf(blub, ";  end of section <%s>", getSegmentNameByAddress(secaddr));
00163                 Address *secend_addr = (Address *)secaddr->duplicate();
00164                 secend_addr->add(evsize);
00165                 newLocation(secend_addr)->flags |= AF_FUNCTION_END;
00166                 addComment(secend_addr, 0, "");
00167                 addComment(secend_addr, 0, ";******************************************************************");
00168                 addComment(secend_addr, 0, blub);
00169                 addComment(secend_addr, 0, ";******************************************************************");
00170 
00171                 validarea->add(secaddr, secend_addr);
00172                 Address *seciniaddr = (Address *)secaddr->duplicate();
00173                 seciniaddr->add(epsize);
00174                 if (validAddress(secaddr, scinitialized) && validAddress(seciniaddr, scinitialized)) {
00175                         initialized->add(secaddr, seciniaddr);
00176                 }
00177                 delete secaddr;
00178                 delete secend_addr;
00179                 delete seciniaddr;
00180                 s++;
00181         }
00182 
00183         // entrypoints
00184 
00185         int entrypoint_count = ne_shared->entrypoints->count();
00186         int *entropy = random_permutation(entrypoint_count);
00187         for (int i=0; i<entrypoint_count; i++) {
00188                 ht_ne_entrypoint *f = (ht_ne_entrypoint*)ne_shared->entrypoints->get(*(entropy+i));
00189                 if (f) {
00190                         Address *address = createAddress1616(f->seg, f->offset);
00191                         if (validAddress(address, scvalid)) {
00192                                 char *label;
00193                                 if (f->name) {
00194                                         sprintf(buffer, "; exported function %s, ordinal %04x", f->name, f->ordinal);
00195                                 } else {
00196                                         sprintf(buffer, "; unnamed exported function, ordinal %04x", f->ordinal);
00197                                 }
00198                                 label = export_func_name(f->name, f->ordinal);
00199                                 addComment(address, 0, "");
00200                                 addComment(address, 0, ";********************************************************");
00201                                 addComment(address, 0, buffer);
00202                                 addComment(address, 0, ";********************************************************");
00203                                 pushAddress(address, address);
00204                                 assignSymbol(address, label, label_func);
00205                                 free(label);
00206                         }
00207                         delete address;
00208                 }
00209         }
00210         if (entropy) free(entropy);
00211 
00212         // imports
00213 
00214         if (ne_shared->imports) {
00215                 ht_tree *t = ne_shared->imports;
00216                 Object *v;
00217                 ne_import_rec *imp = NULL;
00218                 FILEOFS h = ne_shared->hdr_ofs + ne_shared->hdr.imptab;
00219                 while ((imp = (ne_import_rec*)t->enum_next(&v, imp))) {
00220                         char *name = NULL;
00221                         char *mod = (imp->module-1 < ne_shared->modnames_count) ? ne_shared->modnames[imp->module-1] : (char*)"invalid!";
00222                         if (imp->byname) {
00223                                 file->seek(h+imp->name_ofs);
00224                                 name = getstrp(file);
00225                         }
00226                         char *label = import_func_name(mod, name, imp->byname ? 0 : imp->ord);
00227                         if (name) free(name);
00228                         Address *addr = createAddress1616(ne_shared->fake_segment+1, imp->addr);
00229                         addComment(addr, 0, "");
00230                         assignSymbol(addr, label, label_func);
00231                         data->setIntAddressType(addr, dst_ibyte, 1);
00232                         free(label);
00233                         delete addr;
00234                 }
00235         }
00236 
00237 /*      virtual Object *enum_next(Object **value, Object *prevkey);
00238         int import_count = ne_shared->imports.funcs->count();
00239         for (int i=0; i<import_count; i++) {
00240                 ht_pe_import_function *f=(ht_pe_import_function *)pe_shared->imports.funcs->get(*(entropy+i));
00241                 ht_pe_import_library *d=(ht_pe_import_library *)pe_shared->imports.libs->get(f->libidx);
00242                 char *label;
00243                 label = import_func_name(d->name, (f->byname) ? f->name.name : NULL, f->ordinal);
00244                 addComment(f->address, 0, "");
00245                 assignSymbol(f->address, label, label_func);
00246                 data->set_int_addr_type(f->address, dst_idword, 4);
00247                 free(label);
00248         }*/
00249 
00250         addComment(entry, 0, "");
00251         addComment(entry, 0, ";****************************");
00252         if (ne_shared->hdr.flags & NE_FLAGS_NOTAPROCESS) {
00253                 addComment(entry, 0, ";  library entry point");
00254         } else {
00255                 addComment(entry, 0, ";  program entry point");
00256         }
00257         addComment(entry, 0, ";****************************");
00258         if (validCodeAddress(entry)) {
00259                 assignSymbol(entry, "entrypoint", label_func);
00260         } else {
00261                 assignSymbol(entry, "entrypoint", label_data);
00262         }
00263 
00264         setLocationTreeOptimizeThreshold(1000);
00265         setSymbolTreeOptimizeThreshold(1000);
00266         delete entry;
00267         
00268         Analyser::beginAnalysis();
00269 }
00270 
00271 /*
00272  *
00273  */
00274 OBJECT_ID       NEAnalyser::object_id() const
00275 {
00276         return ATOM_NE_ANALYSER;
00277 }
00278 
00279 /*
00280  *
00281  */
00282 UINT NEAnalyser::bufPtr(Address *Addr, byte *buf, int size)
00283 {
00284         FILEOFS ofs = addressToFileofs(Addr);
00285 /*     if (ofs == INVALID_FILE_OFS) {
00286                 int as=1;
00287         }*/
00288         assert(ofs != INVALID_FILE_OFS);
00289         file->seek(ofs);
00290         return file->read(buf, size);
00291 }
00292 
00293 bool NEAnalyser::convertAddressToNEAddress(Address *addr, NEAddress *r)
00294 {
00295         if (addr->object_id()==ATOM_ADDRESS_X86_1616) {
00296                 *r = NE_MAKE_ADDR(((AddressX86_1616*)addr)->seg, ((AddressX86_1616*)addr)->addr);
00297                 return true;
00298         } else {
00299                 return false;
00300         }
00301 }
00302 
00303 Address *NEAnalyser::createAddress()
00304 {
00305         return new AddressX86_1616(0, 0);
00306 }
00307 
00308 Address *NEAnalyser::createAddress1616(word seg, word ofs)
00309 {
00310         return new AddressX86_1616(seg, ofs);
00311 }
00312 
00313 /*
00314  *
00315  */
00316 Assembler *NEAnalyser::createAssembler()
00317 {
00318 /* FIXME: 16/32 */
00319         Assembler *a = new x86asm(X86_OPSIZE16, X86_ADDRSIZE16);
00320         a->init();
00321         return a;
00322 }
00323 
00324 /*
00325  *
00326  */
00327 FILEOFS NEAnalyser::addressToFileofs(Address *Addr)
00328 {
00329         if (validAddress(Addr, scinitialized)) {
00330                 FILEOFS ofs;
00331                 NEAddress na;
00332                 if (!convertAddressToNEAddress(Addr, &na)) return INVALID_FILE_OFS;
00333                 if (!NE_addr_to_ofs(ne_shared, na, &ofs)) {
00334                         return INVALID_FILE_OFS;
00335                 }
00336                 return ofs;
00337         } else {
00338                 return INVALID_FILE_OFS;
00339         }
00340 }
00341 
00342 /*
00343  *
00344  */
00345 char *NEAnalyser::getSegmentNameByAddress(Address *Addr)
00346 {
00347         static char segmentname[16];
00348         int i;
00349         NEAddress na;
00350         if (!convertAddressToNEAddress(Addr, &na)) return NULL;
00351         if (!NE_addr_to_segment(ne_shared, na, &i)) return NULL;
00352         if (i == (int)ne_shared->fake_segment) {
00353                 strcpy(segmentname, "faked names");
00354         } else {
00355                 sprintf(segmentname, "seg%d", i+1);
00356         }
00357         return segmentname;
00358 }
00359 
00360 /*
00361  *
00362  */
00363 const char *NEAnalyser::getName()
00364 {
00365         return file->get_desc();
00366 }
00367 
00368 /*
00369  *
00370  */
00371 const char *NEAnalyser::getType()
00372 {
00373         return "NE/Analyser";
00374 }
00375 
00376 /*
00377  *
00378  */
00379 void NEAnalyser::initCodeAnalyser()
00380 {
00381         Analyser::initCodeAnalyser();
00382 }
00383 
00384 /*
00385  *
00386  */
00387 void NEAnalyser::initUnasm()
00388 {
00389         DPRINTF("ne_analy: ");
00390         DPRINTF("initing analy_x86_disassembler\n");
00391         analy_disasm = new AnalyX86Disassembler();
00392         ((AnalyX86Disassembler*)analy_disasm)->init(this, ANALYX86DISASSEMBLER_FLAGS_16BIT | ANALYX86DISASSEMBLER_FLAGS_SEGMENTED);
00393 }
00394 
00395 /*
00396  *
00397  */
00398 void NEAnalyser::log(const char *msg)
00399 {
00400         /*
00401          *      log() creates to much traffic so dont log
00402          *   perhaps we reactivate this later
00403          *
00404          */
00405 /*      LOG(msg);*/
00406 }
00407 
00408 /*
00409  *
00410  */
00411 Address *NEAnalyser::nextValid(Address *Addr)
00412 {
00413         return (Address *)validarea->findNext(Addr);
00414 }
00415 
00416 /*
00417  *
00418  */
00419 void NEAnalyser::store(ht_object_stream *st)
00420 {
00421         PUT_OBJECT(st, validarea);
00422         Analyser::store(st);
00423 }
00424 
00425 /*
00426  *
00427  */
00428 int     NEAnalyser::queryConfig(int mode)
00429 {
00430         switch (mode) {
00431                 case Q_DO_ANALYSIS:
00432                 case Q_ENGAGE_CODE_ANALYSER:
00433                 case Q_ENGAGE_DATA_ANALYSER:
00434                         return true;
00435                 default:
00436                         return 0;
00437         }
00438 }
00439 
00440 /*
00441  *
00442  */
00443 Address *NEAnalyser::fileofsToAddress(FILEOFS fileofs)
00444 {
00445         NEAddress a;
00446         if (NE_ofs_to_addr(ne_shared, fileofs, &a)) {
00447                 return createAddress1616(NE_ADDR_SEG(a), NE_ADDR_OFS(a));
00448         } else {
00449                 return new InvalidAddress();
00450         }
00451 }
00452 
00453 /*
00454  *
00455  */
00456 bool NEAnalyser::validAddress(Address *Addr, tsectype action)
00457 {
00458         ne_segment_headers *segments = &ne_shared->segments;
00459         int sec;
00460         NEAddress na;
00461         if (!convertAddressToNEAddress(Addr, &na)) return false;
00462         if (!NE_addr_to_segment(ne_shared, na, &sec)) return false;
00463         NE_SEGMENT *s = segments->segments + sec;
00464         switch (action) {
00465                 case scvalid:
00466                         return true;
00467                 case scread:
00468                         return !(s->flags & NE_READONLY) || (s->flags & NE_DATA);
00469                 case scwrite:
00470                         return !(s->flags & NE_READONLY) && (s->flags & NE_DATA);
00471                 case screadwrite:
00472                         return !(s->flags & NE_READONLY) && (s->flags & NE_DATA);
00473                 case sccode:
00474                         return (!(s->flags & NE_DATA)) && NE_addr_is_physical(ne_shared, na);
00475                 case scinitialized:
00476                         return NE_addr_is_physical(ne_shared, na);
00477         }
00478         return false;
00479 }
00480 

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