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

analy.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      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 <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 //#undef DPRINTF
00041 //#define DPRINTF(msg...) {global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;char buf[1024]; ht_snprintf(buf, sizeof buf, ##msg); fprintf(stdout, buf);}
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         // check for overflow
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         // check for overflow
00268         // FIXME: reviewme
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         // FIXME: no .lo/.hi
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         // xrefs
00538         loc->xrefs = (ht_tree *)st->getObject("xrefs");
00539         
00540         // comments
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         // must be resolved later (thisfunc is of type Location not Address)
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                 // FIXME: exception bla..
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 //      st->getObject((Object*)analy_disasm, "analy_disasm");
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  *      addaddrlabel will never overwrite an existing label (like addlabel)
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         // line 0 meens append (at the moment assume append every time ;-))
00761 
00762 //      if (!validaddr(Addr, scvalid)) return;
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  * addlabel: create label if there isnt one
00780  *           fail if label exist on another address
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                         // this label already exists at a different address
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                 // adress already has a label
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                         // there's already a xref
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         /* not really implemented */
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                 // label already exists at a different address
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                 // overwrite
00898                 if (a->label != l) {
00899                         // label has to be renamed
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                         // update xref
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 //              char tbuf[100];
00972 //                char tbuf2[100];
00973 //              addr->stringify(tbuf, 100, 0);
00974 /*          if (strcmp(tbuf, "200970ec") == 0) {
00975                         int as=0;
00976                 }*/
00977 //          printf("*** %s ***\n", tbuf);
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 //                              log("invalid opcode at address %y\n", addr);
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  *      should return a new instance of an apropriate assembler
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         // string test
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                 // test if Addr points to code
01101                 if ((a->type.type == dt_unknown) || (a->type.type == dt_code)) {
01102                         // test if Addr points to valid code (test not yet complete)
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  *      disables address, frees misc
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  *      disables label of an address and unassigns address' label
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  *      an disabled label will be overwritten as soon as possible,
01173  *   and never be returned nor saved.
01174  *      performed this way to preserve the labeltrees structure
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 /*      if (branch != brcall) {
01200                 taddr *a = new_addr(addr+len);
01201                 if (!a->comments) {
01202                         add_comment(a->addr, 0, "");
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 //                      gotoAddress(branch_addr, invalid_addr);
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                                 // should be in code_analy
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 //                      pushAddress(next_addr, cur_func->addr);
01275 //                      gotoAddress(branch_addr, branch_addr);
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 //                      pushAddress(next_addr, cur_func->addr);
01285 //                      gotoAddress(branch_addr, invalid_addr);
01286                         pushAddress(branch_addr, invalid_addr);
01287                         break;
01288                 default:{}
01289                         // stupid but neccessary
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 /*if (at >= locs->addr)*/ {
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 /*if (at > locs->addr)*/ {
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 /*if (i >= 0)*/ {
01362                 if (labels->right) analyserenum_labels(labels->right, at, label);
01363         }
01364 }
01365 
01366 /*
01367  *   returns the (alphanumerically) next label to "at"
01368  *      or the first if "at" is NULL
01369  *      returns NULL if there is no preceding label
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         // label with !addr mustnt be returned
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 /*if (i >= 0)*/ {
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         // FIXME:
01406         if (!at) at="\xff\xff\xff";
01407         if (symbols) analyserenum_labels_back(symbols, at, result);
01408 
01409         // labels with !addr mustnt be returned
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  *   finds the address Addr belongs to (if address has size > 1)
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  *      finds the function the Addr belongs to (if possible/applicable).
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  *      searches back to the last location
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         // abstract / stub
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                 // label will be freed separatly
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         // stub
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          *      this function should map the independent address Addr to a
01896          *      processor dependent
01897          *      e.g.    .23423 --> 00234324    (or something like this)
01898          *   it is only used for relativ calls/jumps
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 /*      if (!(cur_addr_ops--)) {
01925                 optimizeLocationTree();
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 /*      if (!(cur_label_ops--)) {
01956                 optimizeSymbolTree();
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  * optimizes(=balances) addr tree
01965  */
01966 void Analyser::optimizeLocationTree()
01967 {
01968         cur_addr_ops = location_threshold;
01969         // implement me!
01970 }
01971 
01972 /*
01973  * see optimize_addr_tree()
01974  */
01975 void Analyser::optimizeSymbolTree()
01976 {
01977         cur_label_ops = symbol_threshold;
01978         // implement me!
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         // stub
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                         // label isn't deleted
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  *      sets addr_threshold. after threshold addr_tree ops the tree will
02175  *   be optimized
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  *      see set_addr_tree_optimize_threshold
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 

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