00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <string.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024
00025 #include "analy.h"
00026 #include "analy_names.h"
00027 #include "analy_register.h"
00028 #include "code_analy.h"
00029 #include "data_analy.h"
00030 #include "global.h"
00031 #include "htatom.h"
00032 #include "htctrl.h"
00033 #include "htdebug.h"
00034 #include "htstring.h"
00035 #include "language.h"
00036 #include "snprintf.h"
00037 #include "tools.h"
00038
00039 #define DPRINTF(msg...)
00040
00041
00042
00043 int global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
00044
00045 int Address::compareDelinear(Address *obj)
00046 {
00047 return compareTo(obj);
00048 }
00049
00050 bool Address::isValid()
00051 {
00052 return true;
00053 }
00054
00055 int Address::toString(char *s, int maxlen)
00056 {
00057 return stringify(s, maxlen, global_analyser_address_string_format);
00058 }
00059
00060 InvalidAddress::InvalidAddress()
00061 {
00062 }
00063
00064 bool InvalidAddress::add(int offset)
00065 {
00066 return false;
00067 }
00068
00069 int InvalidAddress::byteSize()
00070 {
00071 return 0;
00072 }
00073
00074 int InvalidAddress::compareTo(const Object *obj) const
00075 {
00076 return 0;
00077 }
00078
00079 void InvalidAddress::putIntoCPUAddress(CPU_ADDR *ca)
00080 {
00081 }
00082
00083 bool InvalidAddress::difference(int &result, Address *to)
00084 {
00085 return false;
00086 }
00087
00088 Object *InvalidAddress::duplicate()
00089 {
00090 return new InvalidAddress();
00091 }
00092
00093 void InvalidAddress::getFromArray(const byte *array)
00094 {
00095 }
00096
00097 void InvalidAddress::getFromCPUAddress(CPU_ADDR *ca)
00098 {
00099 }
00100
00101 bool InvalidAddress::isValid()
00102 {
00103 return false;
00104 }
00105
00106 int InvalidAddress::parseString(const char *s, int length, Analyser *a)
00107 {
00108 return 0;
00109 }
00110
00111 OBJECT_ID InvalidAddress::object_id() const
00112 {
00113 return ATOM_ADDRESS_INVALID;
00114 }
00115
00116 void InvalidAddress::putIntoArray(byte *array)
00117 {
00118 }
00119
00120 int InvalidAddress::stringify(char *s, int max_length, int format)
00121 {
00122 return ht_snprintf(s, max_length, "*INVALID");
00123 }
00124
00125 int InvalidAddress::stringSize()
00126 {
00127 return 8;
00128 }
00129
00130
00131
00132
00133 AddressFlat32::AddressFlat32()
00134 {
00135 }
00136
00137 AddressFlat32::AddressFlat32(dword a)
00138 {
00139 addr = a;
00140 }
00141
00142 bool AddressFlat32::add(int offset)
00143 {
00144
00145 if ((int)offset < 0) {
00146 if (addr+offset > addr) return false;
00147 } else {
00148 if (addr+offset < addr) return false;
00149 }
00150 addr+=offset;
00151 return true;
00152 }
00153
00154 int AddressFlat32::byteSize()
00155 {
00156 return 4;
00157 }
00158
00159 int AddressFlat32::compareTo(const Object *obj) const
00160 {
00161 assert(object_id() == obj->object_id());
00162 if (addr > ((AddressFlat32 *)obj)->addr) return 1;
00163 if (addr < ((AddressFlat32 *)obj)->addr) return -1;
00164 return 0;
00165 }
00166
00167 int AddressFlat32::compareDelinear(Address *to)
00168 {
00169 assert(object_id() == to->object_id());
00170 dword da = delinearize(addr);
00171 dword db = delinearize(((AddressFlat32 *)to)->addr);
00172 if (da > db) return 1;
00173 if (da < db) return -1;
00174 return 0;
00175 }
00176
00177 bool AddressFlat32::difference(int &result, Address *to)
00178 {
00179 if (object_id() == to->object_id()) {
00180 result = addr - ((AddressFlat32 *)to)->addr;
00181 return true;
00182 } else {
00183 return false;
00184 }
00185 }
00186
00187 Object *AddressFlat32::duplicate()
00188 {
00189 return new AddressFlat32(addr);
00190 }
00191
00192 void AddressFlat32::getFromArray(const byte *array)
00193 {
00194 UNALIGNED_MOVE(addr, *(dword*)array);
00195 }
00196
00197 void AddressFlat32::getFromCPUAddress(CPU_ADDR *ca)
00198 {
00199 addr = ca->addr32.offset;
00200 }
00201
00202 int AddressFlat32::load(ht_object_stream *st)
00203 {
00204 addr = st->getIntHex(4, NULL);
00205 return st->get_error();
00206 }
00207
00208 OBJECT_ID AddressFlat32::object_id() const
00209 {
00210 return ATOM_ADDRESS_FLAT_32;
00211 }
00212
00213 int AddressFlat32::parseString(const char *s, int length, Analyser *a)
00214 {
00215 return false;
00216 }
00217
00218 void AddressFlat32::putIntoArray(byte *array)
00219 {
00220 UNALIGNED_MOVE(*(dword*)array, addr);
00221 }
00222
00223 void AddressFlat32::putIntoCPUAddress(CPU_ADDR *ca)
00224 {
00225 ca->addr32.offset = addr;
00226 }
00227
00228 void AddressFlat32::store(ht_object_stream *st)
00229 {
00230 st->putIntHex(addr, 4, NULL);
00231 }
00232
00233 int AddressFlat32::stringify(char *s, int max_length, int format)
00234 {
00235 char *formats[] = {
00236 "%s%x%s",
00237 "%s%8x%s",
00238 "%s%08x%s",
00239 "",
00240 "%s%X%s",
00241 "%s%8X%s",
00242 "%s%08X%s",
00243 "",
00244 };
00245 return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00246 }
00247
00248 int AddressFlat32::stringSize()
00249 {
00250 return 8;
00251 }
00252
00253
00254
00255
00256 AddressFlat64::AddressFlat64()
00257 {
00258 }
00259
00260 AddressFlat64::AddressFlat64(qword a)
00261 {
00262 addr = a;
00263 }
00264
00265 bool AddressFlat64::add(int offset)
00266 {
00267
00268
00269 if ((int)offset < 0) {
00270 if (addr.lo+offset > addr.lo) {
00271 if (!addr.hi) return false;
00272 addr.hi--;
00273 }
00274 } else {
00275 if (addr.lo+offset < addr.lo) {
00276 if (addr.hi+1==0) return false;
00277 addr.hi++;
00278 }
00279 }
00280 addr.lo+=offset;
00281 return true;
00282 }
00283
00284 int AddressFlat64::byteSize()
00285 {
00286 return 8;
00287 }
00288
00289 int AddressFlat64::compareTo(const Object *obj) const
00290 {
00291 assert(object_id() == obj->object_id());
00292 return qword_cmp(addr, ((AddressFlat64 *)obj)->addr);
00293 }
00294
00295 int AddressFlat64::compareDelinear(Address *to)
00296 {
00297 assert(object_id() == to->object_id());
00298 qword da1, da2;
00299 da1.hi = delinearize(addr.lo);
00300 da1.lo = delinearize(addr.hi);
00301 da2.hi = delinearize(((AddressFlat64 *)to)->addr.lo);
00302 da2.lo = delinearize(((AddressFlat64 *)to)->addr.hi);
00303 return qword_cmp(da1, da2);
00304 }
00305
00306 bool AddressFlat64::difference(int &result, Address *to)
00307 {
00308 if (object_id() == to->object_id()) {
00309 qword res = addr - ((AddressFlat64 *)to)->addr;
00310 if (!res.hi || (res.hi==(dword)-1)) {
00311 result = res.lo;
00312 return true;
00313 }
00314 }
00315 return false;
00316 }
00317
00318 Object *AddressFlat64::duplicate()
00319 {
00320 return new AddressFlat64(addr);
00321 }
00322
00323 void AddressFlat64::getFromArray(const byte *array)
00324 {
00325
00326 UNALIGNED_MOVE(addr.lo, *(dword*)array);
00327 UNALIGNED_MOVE(addr.hi, *(dword*)(array+sizeof addr.lo));
00328 }
00329
00330 void AddressFlat64::getFromCPUAddress(CPU_ADDR *ca)
00331 {
00332 addr = ca->flat64.addr;
00333 }
00334
00335 int AddressFlat64::load(ht_object_stream *st)
00336 {
00337 addr.lo = st->getIntHex(4, NULL);
00338 addr.hi = st->getIntHex(4, NULL);
00339 return st->get_error();
00340 }
00341
00342 OBJECT_ID AddressFlat64::object_id() const
00343 {
00344 return ATOM_ADDRESS_FLAT_64;
00345 }
00346
00347 int AddressFlat64::parseString(const char *s, int length, Analyser *a)
00348 {
00349 return false;
00350 }
00351
00352 void AddressFlat64::putIntoArray(byte *array)
00353 {
00354 UNALIGNED_MOVE(*(dword*)array, addr.lo);
00355 UNALIGNED_MOVE(*(dword*)(array+sizeof addr.lo), addr.hi);
00356 }
00357
00358 void AddressFlat64::putIntoCPUAddress(CPU_ADDR *ca)
00359 {
00360 ca->flat64.addr = addr;
00361 }
00362
00363 void AddressFlat64::store(ht_object_stream *st)
00364 {
00365 st->putIntHex(addr.lo, 4, NULL);
00366 st->putIntHex(addr.hi, 4, NULL);
00367 }
00368
00369 int AddressFlat64::stringify(char *s, int max_length, int format)
00370 {
00371 char *formats[] = {
00372 "%s%qx%s",
00373 "%s%16qx%s",
00374 "%s%016qx%s",
00375 "",
00376 "%s%qx%s",
00377 "%s%16qx%s",
00378 "%s%016qx%s",
00379 "",
00380 };
00381 return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", &addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00382 }
00383
00384 int AddressFlat64::stringSize()
00385 {
00386 return 16;
00387 }
00388
00389
00390
00391
00392
00393
00394 AddrXRef::AddrXRef() {}
00395
00396 AddrXRef::AddrXRef(xref_enum_t Type)
00397 {
00398 type = Type;
00399 }
00400
00401 int AddrXRef::load(ht_object_stream *f)
00402 {
00403 type = (xref_enum_t) f->getIntHex(1, "type");
00404 return f->get_error();
00405 }
00406
00407 OBJECT_ID AddrXRef::object_id() const
00408 {
00409 return ATOM_ADDR_XREF;
00410 }
00411
00412 void AddrXRef::store(ht_object_stream *f)
00413 {
00414 f->putIntHex((UINT)type, 1, "type");
00415 }
00416
00417
00418
00419
00420 AddressQueueItem::AddressQueueItem() {}
00421
00422 AddressQueueItem::AddressQueueItem(Address *Addr, Address *Func)
00423 {
00424 addr = DUP_ADDR(Addr);
00425 func = DUP_ADDR(Func);
00426 }
00427
00428 AddressQueueItem::~AddressQueueItem()
00429 {
00430 delete addr;
00431 delete func;
00432 }
00433
00434 OBJECT_ID AddressQueueItem::object_id() const
00435 {
00436 return ATOM_ADDR_QUEUE_ITEM;
00437 }
00438
00439 int AddressQueueItem::load(ht_object_stream *f)
00440 {
00441 GET_OBJECT(f, addr);
00442 GET_OBJECT(f, func);
00443 return f->get_error();
00444 }
00445
00446 void AddressQueueItem::store(ht_object_stream *f)
00447 {
00448 PUT_OBJECT(f, addr);
00449 PUT_OBJECT(f, func);
00450 }
00451
00452
00453
00454
00455 void CommentList::init()
00456 {
00457 ht_clist::init();
00458 }
00459
00460 void CommentList::appendPreComment(const char *s)
00461 {
00462 append(new ht_data_string(s));
00463 }
00464
00465 void CommentList::appendPostComment(const char *s)
00466 {
00467 append(new ht_data_string(s));
00468 }
00469
00470 void CommentList::appendPreComment(int special)
00471 {
00472 append(new ht_data_uint(special));
00473 }
00474
00475 void CommentList::appendPostComment(int special)
00476 {
00477 append(new ht_data_uint(special+0x10000000));
00478 }
00479
00480 const char *CommentList::getName(UINT i)
00481 {
00482 Object *d = get(i);
00483 return d ? ((d->object_id()==ATOM_HT_DATA_UINT) ? comment_lookup(((ht_data_uint*)d)->value): ((ht_data_string*)d)->value) : NULL;
00484 }
00485
00486
00487
00488
00489 void Analyser::init()
00490 {
00491 active = false;
00492 dirty = false;
00493 next_address_is_invalid = false;
00494 addr = new InvalidAddress();
00495 invalid_addr = new InvalidAddress();
00496 addr_queue = new ht_queue();
00497 addr_queue->init();
00498 locations = NULL;
00499 symbols = NULL;
00500 symbol_count = location_count = 0;
00501 cur_addr_ops = cur_label_ops = 1;
00502 setLocationTreeOptimizeThreshold(1000);
00503 setSymbolTreeOptimizeThreshold(1000);
00504 cur_func = NULL;
00505 ops_parsed = 0;
00506 next_explored = new InvalidAddress();
00507 first_explored = new InvalidAddress();
00508 last_explored = new InvalidAddress();
00509 explored = new Area();
00510 explored->init();
00511 initialized = new Area();
00512 initialized->init();
00513 initCodeAnalyser();
00514 initDataAnalyser();
00515 disasm = NULL;
00516 analy_disasm = NULL;
00517 max_opcode_length = 1;
00518 initUnasm();
00519 mode = ANALY_TRANSLATE_SYMBOLS;
00520 }
00521
00522 static int loadlocations(ht_object_stream *st, Location *&loc, int l, int r)
00523 {
00524 if (l > r) {
00525 loc = NULL;
00526 return st->get_error();
00527 }
00528 int m = (l+r)/2;
00529 loc = (Location *) smalloc0(sizeof(Location));
00530
00531 if (loadlocations(st, loc->left, l, m-1) != 0) {
00532 return st->get_error();
00533 }
00534
00535 loc->addr = (Address *)st->getObject("addr");
00536
00537
00538 loc->xrefs = (ht_tree *)st->getObject("xrefs");
00539
00540
00541 loc->comments = (CommentList*)st->getObject("comments");
00542
00543 if (st->get_error()) {
00544 free(loc);
00545 loc = NULL;
00546 return 1;
00547 }
00548
00549 analyser_get_addrtype(st, &loc->type);
00550
00551
00552 loc->thisfunc = (Location *)st->getObject("func");
00553
00554 loc->flags = st->getIntHex(4, "flags");
00555
00556 if (st->get_error()) {
00557 free(loc);
00558 loc = NULL;
00559 return 1;
00560 }
00561 if (loadlocations(st, loc->right, m+1, r) != 0) {
00562 return st->get_error();
00563 }
00564 return st->get_error();
00565 }
00566
00567 static int loadsymbols(Analyser *analy, ht_object_stream *st, Symbol *&symbol, int l, int r)
00568 {
00569 if (l > r) {
00570 symbol = NULL;
00571 return st->get_error();
00572 }
00573 int m = (l+r)/2;
00574 symbol = (Symbol *) smalloc0(sizeof(Symbol));
00575
00576 if (loadsymbols(analy, st, symbol->left, l, m-1) != 0) {
00577 return st->get_error();
00578 }
00579
00580 Address *a;
00581 a = (Address *)st->getObject("addr");
00582 if (!a) {
00583
00584 return 1;
00585 }
00586 (symbol->location = analy->newLocation(a))->label = symbol;
00587 delete a;
00588
00589 symbol->name = st->getString("name");
00590
00591 symbol->type = (labeltype)st->getIntHex(1, "type");
00592
00593 if (st->get_error()) {
00594 free(symbol);
00595 symbol = NULL;
00596 return st->get_error();
00597 }
00598 if (loadsymbols(analy, st, symbol->right, m+1, r) != 0) {
00599 return st->get_error();
00600 }
00601 return st->get_error();
00602 }
00603
00604 static void resolveaddrs(Analyser *a, Location *loc)
00605 {
00606 if (loc) {
00607 resolveaddrs(a, loc->left);
00608 Address *tmp = (Address*)loc->thisfunc;
00609 if (tmp->isValid()) {
00610 loc->thisfunc = a->getLocationByAddress(tmp);
00611 } else {
00612 loc->thisfunc = NULL;
00613 }
00614 delete tmp;
00615 resolveaddrs(a, loc->right);
00616 }
00617 }
00618
00619
00620
00621
00622 int Analyser::load(ht_object_stream *st)
00623 {
00624 cur_addr_ops = 0;
00625 cur_label_ops = 0;
00626 GET_OBJECT(st, addr);
00627 invalid_addr = new InvalidAddress();
00628 GET_OBJECT(st, addr_queue);
00629 GET_INT_DEC(st, ops_parsed);
00630 GET_BOOL(st, active);
00631 if (active) {
00632 some_analyser_active++;
00633 }
00634 next_address_is_invalid = false;
00635 GET_OBJECT(st, next_explored);
00636 GET_OBJECT(st, first_explored);
00637 GET_OBJECT(st, last_explored);
00638
00639 GET_INT_HEX(st, mode);
00640
00641 GET_OBJECT(st, explored);
00642 GET_OBJECT(st, initialized);
00643
00644 cur_addr_ops = cur_label_ops = 1;
00645 setLocationTreeOptimizeThreshold(1000);
00646 setSymbolTreeOptimizeThreshold(1000);
00647
00648 GET_INT_DEC(st, location_count);
00649 loadlocations(st, locations, 0, location_count-1);
00650
00651 if (st->get_error()) return st->get_error();
00652
00653 resolveaddrs(this, locations);
00654
00655 GET_INT_DEC(st, symbol_count);
00656 loadsymbols(this, st, symbols, 0, symbol_count-1);
00657
00658 if (st->get_error()) return st->get_error();
00659
00660
00661 GET_OBJECT(st, analy_disasm);
00662 GET_OBJECT(st, disasm);
00663 if (analy_disasm) {
00664 analy_disasm->analy = this;
00665 analy_disasm->disasm = disasm;
00666 }
00667 GET_OBJECT(st, code);
00668 GET_OBJECT(st, data);
00669 if (data) {
00670 data->analy = this;
00671 }
00672 GET_INT_DEC(st, location_threshold);
00673 GET_INT_DEC(st, symbol_threshold);
00674
00675 GET_INT_DEC(st, max_opcode_length);
00676
00677 if (st->get_error()) return st->get_error();
00678
00679 Address *curfuncaddr = (Address *)st->getObject("cur_func");
00680 if (curfuncaddr) {
00681 cur_func = newLocation(curfuncaddr);
00682 } else {
00683 cur_func = NULL;
00684 }
00685 delete curfuncaddr;
00686
00687 dirty = false;
00688 return st->get_error();
00689 }
00690
00691
00692
00693
00694 void Analyser::done()
00695 {
00696 setActive(false);
00697 freeLocations(locations);
00698 freeSymbols(symbols);
00699 if (addr_queue) {
00700 addr_queue->destroy();
00701 delete addr_queue;
00702 }
00703 if (explored) {
00704 explored->done();
00705 delete explored;
00706 }
00707 if (initialized) {
00708 initialized->done();
00709 delete initialized;
00710 }
00711 if (code) {
00712 code->done();
00713 delete code;
00714 }
00715 if (data) {
00716 data->done();
00717 delete data;
00718 }
00719 if (disasm) {
00720 disasm->done();
00721 delete disasm;
00722 }
00723 if (analy_disasm) {
00724 analy_disasm->done();
00725 delete analy_disasm;
00726 }
00727 delete addr;
00728 delete invalid_addr;
00729 delete next_explored;
00730 delete first_explored;
00731 delete last_explored;
00732 }
00733
00734
00735
00736
00737 bool Analyser::addAddressSymbol(Address *address, const char *Prefix, labeltype type, Location *infunc)
00738 {
00739 if (!validAddress(address, scvalid)) return false;
00740
00741
00742 char *prefix = label_prefix(Prefix);
00743
00744 char symbol[1024];
00745 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
00746 ht_snprintf(symbol, sizeof symbol, "%s_%y", prefix, address);
00747
00748 if (addSymbol(address, symbol, type, infunc)) {
00749 return true;
00750 } else {
00751 return false;
00752 }
00753 }
00754
00755
00756
00757
00758 void Analyser::addComment(Address *Addr, int line, const char *c)
00759 {
00760
00761
00762
00763
00764 Location *a = newLocation(Addr);
00765
00766 CommentList *com = a->comments;
00767
00768 if (!com) {
00769 com = new CommentList();
00770 com->init();
00771 a->comments = com;
00772 }
00773 com->appendPreComment(c);
00774
00775 DPRINTF("#(%y) comment `%s'\n", Addr, c);
00776 }
00777
00778
00779
00780
00781
00782
00783 bool Analyser::addSymbol(Address *Addr, const char *label, labeltype type, Location *infunc)
00784 {
00785 if (!validAddress(Addr, scvalid)) return false;
00786
00787 Location *a = newLocation(Addr);
00788
00789 if (!a->label) {
00790
00791 Symbol *l = newSymbol(label, a, type, infunc);
00792
00793 if (l->location->addr->compareTo(Addr) != 0) {
00794
00795 return false;
00796 }
00797
00798 a->label = l;
00799 if (a->type.type == dt_unknown || a->type.type == dt_unknown_data) {
00800 if (type == label_func && !validCodeAddress(Addr)) {
00801 type = label_unknown;
00802 }
00803 switch (type) {
00804 case label_unknown:
00805 break;
00806 case label_func:
00807 data->setCodeAddressType(a, dst_function);
00808 break;
00809 case label_loc:
00810 data->setCodeAddressType(a, dst_location);
00811 break;
00812 case label_data:
00813 data->setAddressType(a, dt_unknown_data, 0, 0);
00814 break;
00815 }
00816 }
00817 return true;
00818
00819 } else {
00820
00821
00822 return false;
00823 }
00824 }
00825
00826
00827
00828
00829 bool Analyser::addXRef(Address *from, Address *to, xref_enum_t action)
00830 {
00831 if ((!validAddress(from, scvalid)) || (!validAddress(to, scvalid))) return false;
00832
00833 Location *a = newLocation(from);
00834 ht_tree *x = a->xrefs;
00835
00836 if (x) {
00837 AddrXRef *xref;
00838 if ((xref = (AddrXRef*)x->get(to))) {
00839
00840 return false;
00841 }
00842 } else {
00843 x = new ht_dtree();
00844 ((ht_dtree *)x)->init(compare_keys_ht_data);
00845 }
00846 x->insert(DUP_ADDR(to), new AddrXRef(action));
00847 a->xrefs = x;
00848
00849 DPRINTF("xref %y->%y\n", from, to);
00850 return true;
00851 }
00852
00853
00854
00855
00856 void Analyser::assignComment(Address *Addr, int line, const char *c)
00857 {
00858
00859 addComment(Addr, line, c);
00860 }
00861
00862
00863
00864
00865 bool Analyser::assignSymbol(Address *Addr, const char *label, labeltype type, Location *infunc)
00866 {
00867 if (!validAddress(Addr, scvalid)) return false;
00868
00869 Location *a = newLocation(Addr);
00870
00871 Symbol *l = newSymbol(label, a, type, infunc);
00872 if (l->location->addr->compareTo(Addr) != 0) {
00873
00874 return false;
00875 }
00876
00877 if (l->location->type.type == dt_unknown) {
00878 if (type == label_func && !validCodeAddress(Addr)) {
00879 type = label_unknown;
00880 }
00881 switch (type) {
00882 case label_unknown:
00883 break;
00884 case label_func:
00885 data->setCodeAddressType(a, dst_function);
00886 break;
00887 case label_loc:
00888 data->setCodeAddressType(a, dst_location);
00889 break;
00890 case label_data:
00891 data->setAddressType(a, dt_unknown_data, 0, 0);
00892 break;
00893 }
00894 }
00895
00896 if (a->label) {
00897
00898 if (a->label != l) {
00899
00900 disableSymbol(a->label);
00901 a->label = l;
00902 }
00903 } else {
00904 a->label = l;
00905 }
00906 return true;
00907 }
00908
00909
00910
00911
00912 void Analyser::assignXRef(Address *from, Address *to, xref_enum_t action)
00913 {
00914 if ((!validAddress(from, scvalid)) || (!validAddress(to, scvalid))) return;
00915
00916 Location *a = newLocation(from);
00917 ht_tree *x = a->xrefs;
00918
00919 if (x) {
00920 AddrXRef *xref;
00921 Address *tmp_to = DUP_ADDR(to);
00922 if ((xref = (AddrXRef*)x->get(tmp_to))) {
00923
00924 xref->type = action;
00925 DPRINTF("xref %y->%y updated\n", from, to);
00926 return;
00927 }
00928 delete tmp_to;
00929 } else {
00930 x = new ht_dtree();
00931 ((ht_dtree *)x)->init(compare_keys_ht_data);
00932 }
00933 x->insert(DUP_ADDR(to), new AddrXRef(action));
00934 a->xrefs = x;
00935
00936 DPRINTF("xref %y->%y\n", from, to);
00937 }
00938
00939
00940
00941
00942 void Analyser::beginAnalysis()
00943 {
00944 if (queryConfig(Q_DO_ANALYSIS)) {
00945 DPRINTF("################################\nAnalysis started.\n");
00946 if (analy_disasm && disasm) {
00947 ops_parsed = 0;
00948 if (gotoAddress(invalid_addr, invalid_addr)) setActive(true);
00949 } else {
00950 DPRINTF("Analysis can't be started. No disassembler available.");
00951 }
00952 }
00953 }
00954
00955
00956
00957
00958 bool Analyser::continueAnalysis()
00959 {
00960 byte buf[32];
00961 OPCODE *instr;
00962 int len;
00963 branch_enum_t branch;
00964
00965 assert((UINT)max_opcode_length <= sizeof buf);
00966
00967 if (!active) return false;
00968 do {
00969
00970 int diff;
00971
00972
00973
00974
00975
00976
00977
00978 if ((addr->difference(diff, next_explored) && (diff >= 0)) || !validCodeAddress(addr)) {
00979 if (!gotoAddress(addr, invalid_addr)) {
00980 finish();
00981 return false;
00982 }
00983 }
00984
00985 int bz = bufPtr(addr, buf, max_opcode_length);
00986
00987 instr = disasm->decode(buf, bz, mapAddr(addr));
00988 instr = disasm->duplicateInsn(instr);
00989
00990 ops_parsed++;
00991 num_ops_parsed++;
00992
00993 len = disasm->getSize(instr);
00994 last_explored->add(len);
00995
00996 do {
00997 DPRINTF("opcode @%y [func: %y]: %s\n", addr, (cur_func) ? cur_func->addr : invalid_addr, disasm->str(instr, 0));
00998 if (disasm->validInsn(instr)) {
00999 branch = analy_disasm->isBranch(instr);
01000 if (branch != br_nobranch) {
01001 doBranch(branch, instr, len);
01002 } else {
01003 analy_disasm->examineOpcode(instr);
01004 }
01005 } else {
01006 DPRINTF("invalid opcode @%y\n", addr);
01007
01008 if (!addr->add(len)) {
01009 delete addr;
01010 addr = new InvalidAddress();
01011 } else {
01012 newLocation(addr)->flags |= AF_FUNCTION_END;
01013 next_address_is_invalid = true;
01014 }
01015 }
01016 } while (disasm->selectNext(instr));
01017 if (next_address_is_invalid || !addr->add(len)) {
01018 gotoAddress(invalid_addr, invalid_addr);
01019 next_address_is_invalid = false;
01020 }
01021 free(instr);
01022 } while ((ops_parsed % MAX_OPS_PER_CONTINUE) !=0);
01023 return true;
01024 }
01025
01026
01027
01028
01029 void Analyser::continueAnalysisAt(Address *Addr)
01030 {
01031 if (!validAddress(Addr, sccode)) return;
01032 if (queryConfig(Q_DO_ANALYSIS)) {
01033 DPRINTF("continueing analysis at %y\n", Addr);
01034 if (active || disasm) {
01035 data->setCodeAddressType(Addr, dst_function);
01036 pushAddress(Addr, Addr);
01037 }
01038 if (!active) {
01039 if (disasm) {
01040 Analyser::beginAnalysis();
01041 } else {
01042 DPRINTF("couldn't start analysis: no disasm available\n");
01043 }
01044 }
01045 }
01046 }
01047
01048
01049
01050
01051 Assembler *Analyser::createAssembler()
01052 {
01053 return NULL;
01054 }
01055
01056
01057
01058
01059 void Analyser::dataAccess(Address *Addr, taccess access)
01060 {
01061 if (!validAddress(Addr, scvalid)) {
01062 char msg[100];
01063 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01064 ht_snprintf(msg, sizeof msg, "access of invalid addr %y at addr %y", Addr, addr);
01065 log(msg);
01066 return;
01067 }
01068
01069 DPRINTF("dataaccess of %y\n", Addr);
01070
01071
01072 byte buffer[1024];
01073
01074 if (validAddress(Addr, scinitialized)) {
01075 UINT bz = bufPtr(Addr, buffer, sizeof buffer);
01076 if (bz > 2) {
01077 analy_string *str = string_test(buffer, bz);
01078 if (str) {
01079 char string1[256], string2[31];
01080 str->render_string(string2, sizeof string2);
01081 ht_snprintf(string1, sizeof string1, "%s_%s", str->name(), string2);
01082 make_valid_name(string2, string1);
01083 if (addAddressSymbol(Addr, string2, label_data)) {
01084 addComment(Addr, 0, "");
01085 }
01086 data->setArrayAddressType(Addr, dst_string, str->length());
01087 str->done();
01088 delete str;
01089 return;
01090 }
01091 }
01092 }
01093
01094 if (validCodeAddress(Addr) && access.type == acoffset) {
01095 if (addAddressSymbol(Addr, LPRFX_OFS, label_func)) {
01096 addComment(Addr, 0, "");
01097 }
01098 Location *a = getLocationByAddress(Addr);
01099 assert(a);
01100
01101 if ((a->type.type == dt_unknown) || (a->type.type == dt_code)) {
01102
01103 byte buf[16];
01104 int bz = bufPtr(Addr, buf, sizeof(buf));
01105 OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
01106 if (disasm->validInsn(instr)) {
01107 data->setCodeAddressType(Addr, dst_cunknown);
01108 pushAddress(Addr, Addr);
01109 }
01110 }
01111 } else {
01112 if (access.type != acoffset) {
01113 switch (access.size) {
01114 case 1: data->setIntAddressType(Addr, dst_ibyte, 1); break;
01115 case 2: data->setIntAddressType(Addr, dst_iword, 2); break;
01116 case 4: data->setIntAddressType(Addr, dst_idword, 4); break;
01117 }
01118 }
01119 if (validAddress(Addr, scinitialized)) {
01120 addAddressSymbol(Addr, LPRFX_DTA, label_data);
01121 } else {
01122 addAddressSymbol(Addr, LPRFX_DTU, label_data);
01123 }
01124 }
01125 }
01126
01127
01128
01129
01130 void Analyser::deleteLocation(Address *Addr)
01131 {
01132 Location *a = getLocationByAddress(Addr);
01133 if (a) {
01134 disableSymbol(a->label);
01135 a->label = NULL;
01136 a->flags |= AF_DELETED;
01137 location_count--;
01138 }
01139 }
01140
01141
01142
01143
01144 void Analyser::deleteSymbol(Address *Addr)
01145 {
01146 Location *a = getLocationByAddress(Addr);
01147 if (a) {
01148 disableSymbol(a->label);
01149 a->label = NULL;
01150 symbol_count--;
01151 }
01152 }
01153
01154
01155
01156
01157 bool Analyser::deleteXRef(Address *from, Address *to)
01158 {
01159 if ((!validAddress(from, scvalid)) || (!validAddress(to, scvalid))) return false;
01160
01161 Location *a = getLocationByAddress(from);
01162 if (!a) return false;
01163 ht_tree *x = a->xrefs;
01164 if (!x) return false;
01165
01166 DPRINTF("deleted xref %y->%y\n", from, to);
01167
01168 return x->del(to);
01169 }
01170
01171
01172
01173
01174
01175
01176
01177 void Analyser::disableSymbol(Symbol *label)
01178 {
01179 if (label) {
01180 label->location = NULL;
01181 }
01182 }
01183
01184
01185
01186
01187 void Analyser::doBranch(branch_enum_t branch, OPCODE *opcode, int len)
01188 {
01189 Address *branch_addr = analy_disasm->branchAddr(opcode, branch, true);
01190
01191 if (branch != br_return) {
01192 if (!validCodeAddress(branch_addr)) {
01193 char msg[100];
01194 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
01195 ht_snprintf(msg, sizeof msg, "branch to invalid addr %y from addr %y", branch_addr, addr);
01196 log(msg);
01197 }
01198 }
01199
01200
01201
01202
01203
01204
01205 Address *next_addr = DUP_ADDR(addr);
01206 if (!next_addr->add(len)) {
01207 delete next_addr;
01208 next_addr = new InvalidAddress();
01209 }
01210 switch (branch) {
01211 case br_jump:
01212 if (next_addr->isValid())
01213 newLocation(next_addr)->flags |= AF_FUNCTION_END;
01214
01215 addXRef(branch_addr, addr, xrefjump);
01216 if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) {
01217 addComment(branch_addr, 0, "");
01218 }
01219
01220 pushAddress(branch_addr, invalid_addr);
01221 next_address_is_invalid = true;
01222 break;
01223 case br_return:
01224 if (next_addr->isValid())
01225 newLocation(next_addr)->flags |= AF_FUNCTION_END;
01226
01227 next_address_is_invalid = true;
01228 break;
01229 case br_call: {
01230 addXRef(branch_addr, addr, xrefcall);
01231 bool special_func = false;
01232 char *lprfx = LPRFX_SUB;
01233 if (!getSymbolByAddress(branch_addr) && validCodeAddress(branch_addr)) {
01234
01235 byte buf[16];
01236 int bz = bufPtr(branch_addr, buf, sizeof(buf));
01237 OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(branch_addr));
01238 branch_enum_t bt = analy_disasm->isBranch(instr);
01239
01240 if (bt == br_return) {
01241 lprfx = LPRFX_STUB;
01242 } else if (bt == br_jump) {
01243 char buf[1024], label[1024];
01244 Address *wrap_addr = analy_disasm->branchAddr(instr, bt, false);
01245 if (validAddress(wrap_addr, scvalid)) {
01246 Symbol *l = getSymbolByAddress(wrap_addr);
01247 addComment(branch_addr, 0, "");
01248 addComment(branch_addr, 0, ";----------------------------------------------");
01249 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
01250 if (l && l->name) {
01251 ht_snprintf(buf, sizeof buf, "%s %s", "; W R A P P E R for", l->name);
01252 ht_snprintf(label, sizeof label, "%s_%s_%y", label_prefix(LPRFX_WRAP), l->name, branch_addr);
01253 } else {
01254 ht_snprintf(buf, sizeof buf, "%s %s %y", "; W R A P P E R for", "address", wrap_addr);
01255 ht_snprintf(label, sizeof label, "%s_%y_%y", label_prefix(LPRFX_WRAP), wrap_addr, branch_addr);
01256 }
01257 addComment(branch_addr, 0, buf);
01258 addComment(branch_addr, 0, ";----------------------------------------------");
01259 addSymbol(branch_addr, label, label_func);
01260 special_func = true;
01261 }
01262 delete wrap_addr;
01263 }
01264 }
01265 if (!special_func && addAddressSymbol(branch_addr, lprfx, label_func)) {
01266 addComment(branch_addr, 0, "");
01267 addComment(branch_addr, 0, ";-----------------------");
01268 addComment(branch_addr, 0, "; S U B R O U T I N E");
01269 addComment(branch_addr, 0, ";-----------------------");
01270 if (branch_addr->compareTo(cur_func->addr) == 0) {
01271 addComment(branch_addr, 0, "; (recursive)");
01272 }
01273 }
01274
01275
01276 pushAddress(branch_addr, branch_addr);
01277 break;
01278 }
01279 case br_jXX:
01280 addXRef(branch_addr, addr, xrefjump);
01281 if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) {
01282 addComment(branch_addr, 0, "");
01283 }
01284
01285
01286 pushAddress(branch_addr, invalid_addr);
01287 break;
01288 default:{}
01289
01290 }
01291 delete next_addr;
01292 delete branch_addr;
01293 }
01294
01295
01296
01297
01298 void Analyser::engageCodeanalyser()
01299 {
01300 if (queryConfig(Q_ENGAGE_CODE_ANALYSER)) {
01301 DPRINTF("starting code analyser.\n");
01302 }
01303 }
01304
01305 static void analyserenum_addrs(Location *locs, Address *at, Location *&loc)
01306 {
01307 if ((at->compareTo(locs->addr) < 0) || !at->isValid()) {
01308 loc = locs;
01309 if (locs->left) analyserenum_addrs(locs->left, at, loc);
01310 } else {
01311 if (locs->right) analyserenum_addrs(locs->right, at, loc);
01312 }
01313 }
01314
01315
01316
01317
01318 Location *Analyser::enumLocations(Address *Addr)
01319 {
01320 Location *result = NULL;
01321 if (locations) analyserenum_addrs(locations, Addr, result);
01322 while ((result) && (result->flags & AF_DELETED)) {
01323 Address *a = result->addr;
01324 result = NULL;
01325 analyserenum_addrs(locations, a, result);
01326 }
01327 return result;
01328 }
01329
01330 static void analyserenum_addrs_back(Location *locs, Address *at, Location *&loc)
01331 {
01332 if (at->compareTo(locs->addr) <= 0) {
01333 if (locs->left) analyserenum_addrs_back(locs->left, at, loc);
01334 } else {
01335 loc = locs;
01336 if (locs->right) analyserenum_addrs_back(locs->right, at, loc);
01337 }
01338 }
01339
01340
01341
01342
01343 Location *Analyser::enumLocationsReverse(Address *Addr)
01344 {
01345 Location *result = NULL;
01346 if (locations) analyserenum_addrs_back(locations, Addr, result);
01347 while ((result) && (result->flags & AF_DELETED)) {
01348 Address *a = result->addr;
01349 result = NULL;
01350 analyserenum_addrs_back(locations, a, result);
01351 }
01352 return result;
01353 }
01354
01355 static void analyserenum_labels(Symbol *labels, const char *at, Symbol *&label)
01356 {
01357 int i = strcmp(at, labels->name);
01358 if (i < 0) {
01359 label = labels;
01360 if (labels->left) analyserenum_labels(labels->left, at, label);
01361 } else {
01362 if (labels->right) analyserenum_labels(labels->right, at, label);
01363 }
01364 }
01365
01366
01367
01368
01369
01370
01371
01372 Symbol *Analyser::enumSymbolsByName(const char *at)
01373 {
01374 Symbol *result = NULL;
01375 if (!at) at="";
01376 if (symbols) analyserenum_labels(symbols, at, result);
01377
01378
01379 while ((result) && (!result->location)) {
01380 char *name = result->name;
01381 result = NULL;
01382 analyserenum_labels(symbols, name, result);
01383 }
01384
01385 return result;
01386 }
01387
01388 static void analyserenum_labels_back(Symbol *labels, const char *at, Symbol *&label)
01389 {
01390 int i = strcmp(at, labels->name);
01391 if (i <= 0) {
01392 if (labels->left) analyserenum_labels_back(labels->left, at, label);
01393 } else {
01394 label = labels;
01395 if (labels->right) analyserenum_labels_back(labels->right, at, label);
01396 }
01397 }
01398
01399
01400
01401
01402 Symbol *Analyser::enumSymbolsByNameReverse(const char *at)
01403 {
01404 Symbol *result = NULL;
01405
01406 if (!at) at="\xff\xff\xff";
01407 if (symbols) analyserenum_labels_back(symbols, at, result);
01408
01409
01410 while ((result) && (!result->location)) {
01411 char *name = result->name;
01412 result = NULL;
01413 analyserenum_labels_back(symbols, name, result);
01414 }
01415
01416 return result;
01417 }
01418
01419 Symbol *Analyser::enumSymbols(Symbol *sym)
01420 {
01421 if (sym) {
01422 return enumSymbolsByName(sym->name);
01423 } else {
01424 return enumSymbolsByName(NULL);
01425 }
01426 }
01427
01428 Symbol *Analyser::enumSymbolsReverse(Symbol *sym)
01429 {
01430 if (sym) {
01431 return enumSymbolsByNameReverse(sym->name);
01432 } else {
01433 return enumSymbolsByNameReverse(NULL);
01434 }
01435 }
01436
01437
01438
01439
01440
01441 taddr_typetype Analyser::examineData(Address *Addr)
01442 {
01443 if ((validReadAddress(Addr)) && (validAddress(Addr, scinitialized))) {
01444 DPRINTF("examinating data @%y:\n", Addr);
01445
01446 } else return dt_unknown;
01447 return dt_unknown;
01448 }
01449
01450
01451
01452
01453 static Location *analyserfindaddr(Location *locs, Address *Addr)
01454 {
01455 if (locs) {
01456 if (Addr->compareTo(locs->addr) < 0) return analyserfindaddr(locs->left, Addr);
01457 if (Addr->compareTo(locs->addr) > 0) return analyserfindaddr(locs->right, Addr);
01458 return (locs->flags & AF_DELETED) ? NULL : locs;
01459 }
01460 return NULL;
01461 }
01462
01463
01464
01465
01466 Location *Analyser::getLocationByAddress(Address *Addr)
01467 {
01468 return analyserfindaddr(locations, Addr);
01469 }
01470
01471
01472
01473
01474 Location *Analyser::getLocationContextByAddress(Address *Addr)
01475 {
01476 Location *res = enumLocationsReverse(Addr);
01477 if (res && res->type.type != dt_unknown) {
01478 Address *resaddr = DUP_ADDR(res->addr);
01479 resaddr->add(res->type.length);
01480 if (resaddr->compareTo(Addr) > 0) {
01481 delete resaddr;
01482 return res;
01483 }
01484 delete resaddr;
01485 }
01486 return NULL;
01487 }
01488
01489
01490
01491
01492 Location *Analyser::getFunctionByAddress(Address *Addr)
01493 {
01494 Location *loc = getLocationByAddress(Addr);
01495 if (!loc) loc = enumLocationsReverse(Addr);
01496 while ((loc) && (!(loc->flags & AF_FUNCTION_SET))) {
01497 if (loc->flags & AF_FUNCTION_END) return NULL;
01498 loc = enumLocationsReverse(loc->addr);
01499 }
01500 return (loc) ? loc->thisfunc : NULL;
01501 }
01502
01503
01504
01505
01506 Location *Analyser::getPreviousSymbolByAddress(Address *Addr)
01507 {
01508 Location *loc = getLocationByAddress(Addr);
01509 if (!loc) loc = enumLocationsReverse(Addr);
01510 while ((loc) && (!loc->label)) {
01511 if (loc->flags & AF_FUNCTION_END) return NULL;
01512 loc = enumLocationsReverse(loc->addr);
01513 }
01514 return (loc) ? loc : NULL;
01515 }
01516
01517
01518
01519
01520 static Symbol *analyserfindlabel(Symbol *labels, const char *label)
01521 {
01522 if (labels) {
01523 int i=strcmp(label, labels->name);
01524 if (i < 0) return analyserfindlabel(labels->left, label);
01525 if (i > 0) return analyserfindlabel(labels->right, label);
01526 return labels->location ? labels : NULL;
01527 }
01528 return NULL;
01529 }
01530
01531
01532
01533
01534 Symbol *Analyser::getSymbolByName(const char *label)
01535 {
01536 return analyserfindlabel(symbols, label);
01537 }
01538
01539 const char *Analyser::getSymbolNameByLocation(Location *loc)
01540 {
01541 return (loc) ? ((loc->label) ? loc->label->name : NULL): NULL;
01542 }
01543
01544
01548 Address *Analyser::fileofsToAddress(FILEOFS fileaddr)
01549 {
01550
01551 return DUP_ADDR(invalid_addr);
01552 }
01553
01557 void Analyser::finish()
01558 {
01559 DPRINTF("the analyser finished (for now).\n");
01560 cur_func = NULL;
01561 delete addr;
01562 addr = new InvalidAddress();
01563 setActive(false);
01564 }
01565
01566
01567
01568
01569 void Analyser::freeLocation(Location *loc)
01570 {
01571 if (loc) {
01572
01573 if (loc->xrefs) {
01574 loc->xrefs->destroy();
01575 delete loc->xrefs;
01576 }
01577 freeComments(loc);
01578 delete loc->addr;
01579 free(loc);
01580 }
01581 }
01582
01583
01584
01585
01586 void Analyser::freeLocations(Location *addrs)
01587 {
01588 if (addrs) {
01589 freeLocations(addrs->left);
01590 freeLocations(addrs->right);
01591 freeLocation(addrs);
01592 }
01593 }
01594
01595
01596
01597
01598 void Analyser::freeComments(Location *Addr)
01599 {
01600 CommentList *c = Addr->comments;
01601 if (c) {
01602 c->destroy();
01603 delete c;
01604 }
01605 Addr->comments = NULL;
01606 }
01607
01608
01609
01610
01611 void Analyser::freeSymbol(Symbol *label)
01612 {
01613 if (label) {
01614 if (label->name) free(label->name);
01615 free(label);
01616 }
01617 }
01618
01619
01620
01621
01622
01623 void Analyser::freeSymbols(Symbol *labels)
01624 {
01625 if (labels) {
01626 freeSymbols(labels->left);
01627 freeSymbols(labels->right);
01628 freeSymbol(labels);
01629 }
01630 }
01631
01632
01633
01634
01635 CommentList *Analyser::getComments(Address *Addr)
01636 {
01637 Location *a = getLocationByAddress(Addr);
01638 if (a) {
01639 return a->comments;
01640 }
01641 return NULL;
01642 }
01643
01644 static char *analy_addr_sym_func2(CPU_ADDR Addr, int *symstrlen, void *analy)
01645 {
01646 Address *a = ((Analyser*)analy)->createAddress();
01647 a->getFromCPUAddress(&Addr);
01648 Location *loc = ((Analyser*)analy)->getLocationByAddress(a);
01649 delete a;
01650 if ((loc) && (loc->label)) {
01651 if (symstrlen) *symstrlen = strlen(loc->label->name);
01652 return loc->label->name;
01653 }
01654 return NULL;
01655 }
01656
01657
01658
01659
01660 const char *Analyser::getDisasmStr(Address *Addr, int &length)
01661 {
01662 if (validAddress(Addr, scinitialized)) {
01663 if (disasm) {
01664 addr_sym_func = NULL;
01665 byte buf[16];
01666 int bz = bufPtr(Addr, buf, sizeof(buf));
01667 OPCODE *o = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
01668 length = disasm->getSize(o);
01669 return disasm->strf(o, DIS_STYLE_HEX_NOZEROPAD+DIS_STYLE_HEX_ASMSTYLE, DISASM_STRF_SMALL_FORMAT);
01670 } else {
01671 return "<no disassembler!>";
01672 }
01673 } else {
01674 return "";
01675 }
01676 }
01677
01678
01679
01680
01681 const char *Analyser::getDisasmStrFormatted(Address *Addr)
01682 {
01683 if (disasm) {
01684 addr_sym_func_context = this;
01685 addr_sym_func = &analy_addr_sym_func2;
01686
01687 byte buf[16];
01688 int bz = bufPtr(Addr, buf, sizeof(buf));
01689 OPCODE *o=disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
01690 char *res = disasm->strf(o, DIS_STYLE_HEX_NOZEROPAD+DIS_STYLE_HEX_ASMSTYLE, DISASM_STRF_SMALL_FORMAT);
01691
01692 addr_sym_func_context = NULL;
01693 addr_sym_func = NULL;
01694
01695 return res;
01696 } else {
01697 return "<no disassembler!>";
01698 }
01699 }
01700
01701
01702
01703
01704 int Analyser::getDisplayMode()
01705 {
01706 return mode;
01707 }
01708
01709 static void analysergetlocationcount(Location *addr, int *c)
01710 {
01711 if (addr) {
01712 analysergetlocationcount(addr->left, c);
01713 if (!(addr->flags & AF_DELETED)) (*c)++;
01714 analysergetlocationcount(addr->right, c);
01715 }
01716 }
01717
01718
01719
01720
01721 int Analyser::getLocationCount()
01722 {
01723 int c=0;
01724 analysergetlocationcount(locations, &c);
01725 return c;
01726 }
01727
01728
01729
01730
01731 const char *Analyser::getName()
01732 {
01733 return "generic";
01734 }
01735
01736 static void analysergetsymbolcount(Symbol *l, int *c)
01737 {
01738 if (l) {
01739 analysergetsymbolcount(l->left, c);
01740 if (l->location) (*c)++;
01741 analysergetsymbolcount(l->right, c);
01742 }
01743 }
01744
01745
01746
01747
01748 int Analyser::getSymbolCount()
01749 {
01750 int c=0;
01751 analysergetsymbolcount(symbols, &c);
01752 return c;
01753 }
01754
01755
01756
01757
01758 const char *Analyser::getSegmentNameByAddress(Address *Addr)
01759 {
01760 return NULL;
01761 }
01762
01763
01764
01765
01766 Symbol *Analyser::getSymbolByAddress(Address *Addr)
01767 {
01768 Location *a = getLocationByAddress(Addr);
01769
01770 return (a) ? a->label : NULL;
01771 }
01772
01773
01774
01775
01776 const char *Analyser::getType()
01777 {
01778 return "generic";
01779 }
01780
01781
01782
01783
01784 ht_tree *Analyser::getXRefs(Address *Addr)
01785 {
01786 Location *a = getLocationByAddress(Addr);
01787 if (!a) return NULL;
01788 return a->xrefs;
01789 }
01790
01791
01792
01793
01794 bool Analyser::gotoAddress(Address *Addr, Address *func)
01795 {
01796 DPRINTF("goto(%y, %y)\n", Addr, func);
01797 int diff;
01798
01799 if (first_explored->difference(diff, last_explored) && diff < 0) {
01800 DPRINTF("explored->add(%y - %y)\n", first_explored, last_explored);
01801 explored->add(first_explored, last_explored);
01802 }
01803
01804 delete first_explored;
01805 delete last_explored;
01806 delete next_explored;
01807 func = DUP_ADDR(func);
01808
01809 if (!validCodeAddress(Addr) || explored->contains(Addr)) {
01810 DPRINTF("Address: %y Valid: %d Explored: %d\n", addr, validCodeAddress(addr), explored->contains(addr));
01811 do {
01812 delete addr;
01813 delete func;
01814 if (!popAddress(&addr, &func)) {
01815 first_explored = new InvalidAddress();
01816 last_explored = new InvalidAddress();
01817 next_explored = new InvalidAddress();
01818 addr = new InvalidAddress();
01819 return false;
01820 }
01821
01822 DPRINTF("pop %y (Valid: %d Explored: %d)\n", addr, validCodeAddress(addr), explored->contains(addr));
01823 } while ((explored->contains(addr)) || (!validCodeAddress(addr)));
01824 } else {
01825 if (addr != Addr) {
01826 delete addr;
01827 addr = DUP_ADDR(Addr);
01828 }
01829 }
01830
01831 if (func->isValid()) {
01832 cur_func = newLocation(func);
01833 setLocationFunction(cur_func, cur_func);
01834 }
01835 delete func;
01836 next_explored = (Address *)explored->findNext(addr);
01837 if (!next_explored) {
01838 next_explored = new InvalidAddress();
01839 } else {
01840 next_explored = DUP_ADDR(next_explored);
01841 }
01842 first_explored = DUP_ADDR(addr);
01843 last_explored = DUP_ADDR(addr);
01844 return true;
01845 }
01846
01847
01848
01849
01850 void Analyser::initCodeAnalyser()
01851 {
01852 code = new CodeAnalyser();
01853 code->init(this);
01854 }
01855
01856
01857
01858
01859 void Analyser::initDataAnalyser()
01860 {
01861 data = new DataAnalyser();
01862 data->init(this);
01863 }
01864
01865
01866
01867
01868 bool Analyser::isDirty()
01869 {
01870 return dirty;
01871 }
01872
01873
01874
01875
01876 void Analyser::log(const char *s)
01877 {
01878
01879 }
01880
01881
01882
01883
01884 void Analyser::makeDirty()
01885 {
01886 dirty = true;
01887 }
01888
01889
01890
01891
01892 CPU_ADDR Analyser::mapAddr(Address *Addr)
01893 {
01894
01895
01896
01897
01898
01899
01900 CPU_ADDR a;
01901 Addr->putIntoCPUAddress(&a);
01902 return a;
01903 }
01904
01905 Location *Analyser::newLocation(Location *&locs, Address *Addr)
01906 {
01907 if (locs) {
01908 if (Addr->compareTo(locs->addr) < 0) return newLocation(locs->left, Addr);
01909 if (Addr->compareTo(locs->addr) > 0) return newLocation(locs->right, Addr);
01910 } else {
01911 locs = (Location *) smalloc0(sizeof(Location));
01912 locs->addr = DUP_ADDR(Addr);
01913 location_count++;
01914 }
01915 locs->flags &= ~AF_DELETED;
01916 return locs;
01917 }
01918
01919
01920
01921
01922 Location *Analyser::newLocation(Address *Addr)
01923 {
01924
01925
01926
01927 return newLocation(locations, Addr);
01928 }
01929
01930 Symbol *Analyser::newSymbol(Symbol *&labels, const char *label, Location *loc, labeltype type)
01931 {
01932 if (labels) {
01933 int i = strcmp(label, labels->name);
01934 if (i < 0) return newSymbol(labels->left, label, loc, type);
01935 if (i > 0) return newSymbol(labels->right, label, loc, type);
01936 if (!(labels->location)) {
01937 labels->location = loc;
01938 if (type != label_unknown) labels->type = type;
01939 }
01940 } else {
01941 labels = (Symbol *) smalloc0(sizeof(Symbol));
01942 labels->name = ht_strdup(label);
01943 labels->location = loc;
01944 labels->type = type;
01945 symbol_count++;
01946 }
01947 return labels;
01948 }
01949
01950
01951
01952
01953 Symbol *Analyser::newSymbol(const char *label, Location *loc, labeltype type, Location *infunc)
01954 {
01955
01956
01957
01958 Symbol *result = newSymbol(symbols, label, loc, type);
01959 if ((result) && (result->location==loc) && (infunc)) setLocationFunction(loc, infunc);
01960 return result;
01961 }
01962
01963
01964
01965
01966 void Analyser::optimizeLocationTree()
01967 {
01968 cur_addr_ops = location_threshold;
01969
01970 }
01971
01972
01973
01974
01975 void Analyser::optimizeSymbolTree()
01976 {
01977 cur_label_ops = symbol_threshold;
01978
01979 }
01980
01981
01982
01983
01984 bool Analyser::popAddress(Address **Addr, Address **func)
01985 {
01986 if (addr_queue->count()) {
01987
01988 AddressQueueItem *aqi = (AddressQueueItem *) addr_queue->dequeue();
01989 *Addr = DUP_ADDR(aqi->addr);
01990 *func = DUP_ADDR(aqi->func);
01991 delete aqi;
01992
01993 DPRINTF("addr %y (from sub %y) poped\n", *Addr, *func);
01994 return true;
01995
01996 } else {
01997 DPRINTF("pop failed -> analyser obviously finished\n");
01998 return false;
01999 }
02000 }
02001
02002
02003
02004
02005 void Analyser::pushAddress(Address *Addr, Address *func)
02006 {
02007 if (validCodeAddress(Addr)) {
02008 if (!func->isValid()) {
02009 if (cur_func) {
02010 func = cur_func->addr;
02011 }
02012 }
02013 DPRINTF("addr %y (from func %y) pushed\n", Addr, func);
02014 AddressQueueItem *aqi = new AddressQueueItem(Addr, func);
02015 addr_queue->enqueue(aqi);
02016 }
02017 }
02018
02019
02020
02021
02022 int Analyser::queryConfig(int mode)
02023 {
02024
02025 return 0;
02026 }
02027
02028 static void saveaddrs(ht_object_stream *st, Location *addr)
02029 {
02030 if (addr) {
02031 saveaddrs(st, addr->left);
02032
02033 if (!(addr->flags & AF_DELETED)) {
02034 st->putObject(addr->addr, "addr");
02035
02036 st->putObject(addr->xrefs, "xrefs");
02037 st->putObject(addr->comments, "comments");
02038
02039 analyser_put_addrtype(st, &addr->type);
02040
02041 if (addr->thisfunc) {
02042 st->putObject(addr->thisfunc->addr, "func");
02043 } else {
02044 Address *invalid_addr = new InvalidAddress();
02045 st->putObject(invalid_addr, "func");
02046 delete invalid_addr;
02047 }
02048
02049 st->putIntHex(addr->flags, 4, "flags");
02050 }
02051
02052 saveaddrs(st, addr->right);
02053 }
02054 }
02055
02056 static void savelabels(ht_object_stream *st, Symbol *label)
02057 {
02058 if (label) {
02059 savelabels(st, label->left);
02060
02061 if (label->location) {
02062
02063
02064 st->putObject(label->location->addr, "addr");
02065
02066 st->putString(label->name, "name");
02067
02068 int a = (int)label->type;
02069 st->putIntHex(a, 1, "type");
02070 }
02071
02072 savelabels(st, label->right);
02073 }
02074 }
02075
02076
02077
02078
02079 void Analyser::store(ht_object_stream *st)
02080 {
02081 PUT_OBJECT(st, addr);
02082
02083 PUT_OBJECT(st, addr_queue);
02084 PUT_INT_DEC(st, ops_parsed);
02085 PUT_BOOL(st, active);
02086 PUT_OBJECT(st, next_explored);
02087 PUT_OBJECT(st, first_explored);
02088 PUT_OBJECT(st, last_explored);
02089 PUT_INT_HEX(st, mode);
02090 PUT_OBJECT(st, explored);
02091 PUT_OBJECT(st, initialized);
02092
02093 st->putInfo("locations");
02094 st->putIntDec(getLocationCount(), 4, "location_count");
02095 saveaddrs(st, locations);
02096
02097 st->putInfo("symbols");
02098 st->putIntDec(getSymbolCount(), 4, "symbol_count");
02099 savelabels(st, symbols);
02100
02101 PUT_OBJECT(st, analy_disasm);
02102 PUT_OBJECT(st, disasm);
02103 PUT_OBJECT(st, code);
02104 PUT_OBJECT(st, data);
02105
02106 PUT_INT_DEC(st, location_threshold);
02107 PUT_INT_DEC(st, symbol_threshold);
02108
02109 PUT_INT_DEC(st, max_opcode_length);
02110
02111 if (cur_func) {
02112 st->putObject(cur_func->addr, "cur_func");
02113 } else {
02114 st->putObject(NULL, "cur_func");
02115 }
02116
02117 dirty = false;
02118 }
02119
02120
02121
02122
02123 void Analyser::setActive(bool mode)
02124 {
02125 if (mode) {
02126 if (!active) {
02127 active = true;
02128 some_analyser_active++;
02129 }
02130 } else {
02131 if (active) {
02132 active = false;
02133 some_analyser_active--;
02134 }
02135 }
02136 }
02137
02138
02139
02140
02141 void Analyser::setDisplayMode(int enable, int disable)
02142 {
02143 mode &= ~disable;
02144 mode |= enable;
02145 }
02146
02147
02148
02149
02150 void Analyser::setLocationFunction(Location *a, Location *func)
02151 {
02152 if (a) {
02153 a->thisfunc = func;
02154 a->flags &= !AF_FUNCTION_END;
02155 a->flags |= AF_FUNCTION_SET;
02156 }
02157 }
02158
02159
02160
02161
02162 void Analyser::setDisasm(Disassembler *d)
02163 {
02164 disasm = d;
02165 if (disasm) {
02166 int t;
02167 disasm->getOpcodeMetrics(t, max_opcode_length, t, t, t);
02168 } else {
02169 max_opcode_length = 1;
02170 }
02171 }
02172
02173
02174
02175
02176
02177 void Analyser::setLocationTreeOptimizeThreshold(int threshold)
02178 {
02179 location_threshold = threshold;
02180 if (cur_addr_ops > location_threshold) cur_addr_ops = location_threshold;
02181 }
02182
02183
02184
02185
02186 void Analyser::setSymbolTreeOptimizeThreshold(int threshold)
02187 {
02188 symbol_threshold = threshold;
02189 if (cur_label_ops > symbol_threshold) cur_label_ops = symbol_threshold;
02190 }
02191
02192
02193
02194
02195 void Analyser::toggleDisplayMode(int toggle)
02196 {
02197 mode ^= toggle;
02198 }
02199
02200
02201
02202
02203 bool Analyser::validCodeAddress(Address *Addr)
02204 {
02205 Location *a = getLocationByAddress(Addr);
02206 if (a) {
02207 if ((a->type.type != dt_code) && (a->type.type != dt_unknown)) return false;
02208 }
02209 return validAddress(Addr, sccode);
02210 }
02211
02212
02213
02214
02215 bool Analyser::validReadAddress(Address *Addr)
02216 {
02217 return validAddress(Addr, scread);
02218 }
02219
02220
02221
02222
02223 bool Analyser::validWriteAddress(Address *Addr)
02224 {
02225 return validAddress(Addr, scwrite);
02226 }
02227
02228
02229
02230 AnalyDisassembler::AnalyDisassembler()
02231 {
02232 disasm = NULL;
02233 }
02234
02235
02236
02237
02238 void AnalyDisassembler::init(Analyser *A)
02239 {
02240 analy = A;
02241 initDisasm();
02242 }
02243
02244
02245
02246
02247 int AnalyDisassembler::load(ht_object_stream *st)
02248 {
02249 return st->get_error();
02250 }
02251
02252
02253
02254
02255 void AnalyDisassembler::done()
02256 {
02257 }
02258
02259
02260
02261
02262 void AnalyDisassembler::initDisasm()
02263 {
02264 if (analy) {
02265 analy->setDisasm(disasm);
02266 }
02267 }
02268
02269
02270
02271
02272 void AnalyDisassembler::store(ht_object_stream *f)
02273 {
02274 }
02275