00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00071
00072
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
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
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
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
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
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
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
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
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
00286
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
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
00402
00403
00404
00405
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