1 /*
2 * HT Editor
3 * analy.cc
4 *
5 * Copyright (C) 1999-2002 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <string.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include "analy.h"
26 #include "analy_names.h"
27 #include "analy_register.h"
28 #include "code_analy.h"
29 #include "data_analy.h"
30 #include "io/types.h"
31 #include "atom.h"
32 #include "except.h"
33 #include "htctrl.h"
34 #include "htdebug.h"
35 #include "strtools.h"
36 #include "language.h"
37 #include "snprintf.h"
38 #include "tools.h"
39
40 #define DPRINTF(msg...)
41 //#undef DPRINTF
42 //#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);}
43
44 int global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
45
compareDelinear(Address * obj)46 int Address::compareDelinear(Address *obj)
47 {
48 return compareTo(obj);
49 }
50
isValid()51 bool Address::isValid()
52 {
53 return true;
54 }
55
toString(char * s,int maxlen) const56 int Address::toString(char *s, int maxlen) const
57 {
58 return stringify(s, maxlen, global_analyser_address_string_format);
59 }
60
add(int offset)61 bool InvalidAddress::add(int offset)
62 {
63 return false;
64 }
65
byteSize()66 int InvalidAddress::byteSize()
67 {
68 return 0;
69 }
70
compareTo(const Object * obj) const71 int InvalidAddress::compareTo(const Object *obj) const
72 {
73 return 0;
74 }
75
putIntoCPUAddress(CPU_ADDR * ca) const76 void InvalidAddress::putIntoCPUAddress(CPU_ADDR *ca) const
77 {
78 }
79
difference(int & result,Address * to)80 bool InvalidAddress::difference(int &result, Address *to)
81 {
82 return false;
83 }
84
clone() const85 InvalidAddress *InvalidAddress::clone() const
86 {
87 return new InvalidAddress(*this);
88 }
89
getFromArray(const byte * array)90 void InvalidAddress::getFromArray(const byte *array)
91 {
92 }
93
getFromCPUAddress(CPU_ADDR * ca)94 void InvalidAddress::getFromCPUAddress(CPU_ADDR *ca)
95 {
96 }
97
getFromUInt64(uint64 u)98 bool InvalidAddress::getFromUInt64(uint64 u)
99 {
100 return false;
101 }
102
isValid()103 bool InvalidAddress::isValid()
104 {
105 return false;
106 }
107
parseString(const char * s,int length,Analyser * a)108 int InvalidAddress::parseString(const char *s, int length, Analyser *a)
109 {
110 return 0;
111 }
112
getObjectID() const113 ObjectID InvalidAddress::getObjectID() const
114 {
115 return ATOM_ADDRESS_INVALID;
116 }
117
putIntoArray(byte * array) const118 void InvalidAddress::putIntoArray(byte *array) const
119 {
120 }
121
putIntoUInt64(uint64 & u) const122 bool InvalidAddress::putIntoUInt64(uint64 &u) const
123 {
124 return false;
125 }
126
stringify(char * s,int max_length,int format) const127 int InvalidAddress::stringify(char *s, int max_length, int format) const
128 {
129 return ht_snprintf(s, max_length, "*INVALID");
130 }
131
stringSize() const132 int InvalidAddress::stringSize() const
133 {
134 return 8;
135 }
136
137 /*
138 *
139 */
add(int offset)140 bool AddressFlat32::add(int offset)
141 {
142 // check for overflow
143 if ((int)offset < 0) {
144 if (addr+offset > addr) return false;
145 } else {
146 if (addr+offset < addr) return false;
147 }
148 addr+=offset;
149 return true;
150 }
151
byteSize()152 int AddressFlat32::byteSize()
153 {
154 return 4;
155 }
156
compareTo(const Object * obj) const157 int AddressFlat32::compareTo(const Object *obj) const
158 {
159 assert(getObjectID() == obj->getObjectID());
160 if (addr > ((AddressFlat32 *)obj)->addr) return 1;
161 if (addr < ((AddressFlat32 *)obj)->addr) return -1;
162 return 0;
163 }
164
compareDelinear(Address * to)165 int AddressFlat32::compareDelinear(Address *to)
166 {
167 assert(getObjectID() == to->getObjectID());
168 uint32 da = delinearize(addr);
169 uint32 db = delinearize(((AddressFlat32 *)to)->addr);
170 if (da > db) return 1;
171 if (da < db) return -1;
172 return 0;
173 }
174
difference(int & result,Address * to)175 bool AddressFlat32::difference(int &result, Address *to)
176 {
177 if (getObjectID() == to->getObjectID()) {
178 result = addr - ((AddressFlat32 *)to)->addr;
179 return true;
180 } else {
181 return false;
182 }
183 }
184
clone() const185 AddressFlat32 *AddressFlat32::clone() const
186 {
187 return new AddressFlat32(*this);
188 }
189
getFromArray(const byte * array)190 void AddressFlat32::getFromArray(const byte *array)
191 {
192 memcpy(&addr, array, sizeof(addr));
193 }
194
getFromCPUAddress(CPU_ADDR * ca)195 void AddressFlat32::getFromCPUAddress(CPU_ADDR *ca)
196 {
197 addr = ca->addr32.offset;
198 }
199
getFromUInt64(uint64 u)200 bool AddressFlat32::getFromUInt64(uint64 u)
201 {
202 if (u <= 0xffffffff) {
203 addr = u;
204 return true;
205 } else {
206 return false;
207 }
208 }
209
load(ObjectStream & st)210 void AddressFlat32::load(ObjectStream &st)
211 {
212 GET_INT32X(st, addr);
213 }
214
getObjectID() const215 ObjectID AddressFlat32::getObjectID() const
216 {
217 return ATOM_ADDRESS_FLAT_32;
218 }
219
parseString(const char * s,int length,Analyser * a)220 int AddressFlat32::parseString(const char *s, int length, Analyser *a)
221 {
222 return false;
223 }
224
putIntoArray(byte * array) const225 void AddressFlat32::putIntoArray(byte *array) const
226 {
227 memcpy(array, &addr, sizeof(addr));
228 }
229
putIntoCPUAddress(CPU_ADDR * ca) const230 void AddressFlat32::putIntoCPUAddress(CPU_ADDR *ca) const
231 {
232 ca->addr32.offset = addr;
233 }
234
putIntoUInt64(uint64 & u) const235 bool AddressFlat32::putIntoUInt64(uint64 &u) const
236 {
237 u = addr;
238 return true;
239 }
240
store(ObjectStream & st) const241 void AddressFlat32::store(ObjectStream &st) const
242 {
243 PUT_INT32X(st, addr);
244 }
245
stringify(char * s,int max_length,int format) const246 int AddressFlat32::stringify(char *s, int max_length, int format) const
247 {
248 const char *formats[] = {
249 "%s%x%s",
250 "%s%8x%s",
251 "%s%08x%s",
252 "",
253 "%s%X%s",
254 "%s%8X%s",
255 "%s%08X%s",
256 "",
257 };
258 return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
259 }
260
stringSize() const261 int AddressFlat32::stringSize() const
262 {
263 return 8;
264 }
265
266 /*
267 *
268 */
add(int offset)269 bool AddressFlat64::add(int offset)
270 {
271 // check for overflow
272 // FIXME: XXXXXXXXXXXXX
273 addr += sint64(offset);
274 return true;
275 }
276
byteSize()277 int AddressFlat64::byteSize()
278 {
279 return 8;
280 }
281
compareTo(const Object * obj) const282 int AddressFlat64::compareTo(const Object *obj) const
283 {
284 assert(getObjectID() == obj->getObjectID());
285 if (addr > ((AddressFlat64 *)obj)->addr) return 1;
286 if (addr < ((AddressFlat64 *)obj)->addr) return -1;
287 return 0;
288 }
289
compareDelinear(Address * to)290 int AddressFlat64::compareDelinear(Address *to)
291 {
292 assert(getObjectID() == to->getObjectID());
293 uint64 da1, da2;
294 da1 = delinearize64(addr);
295 da2 = delinearize64(((AddressFlat64 *)to)->addr);
296 if (da1 > da2) return 1;
297 if (da1 < da2) return -1;
298 return 0;
299 }
300
difference(int & result,Address * to)301 bool AddressFlat64::difference(int &result, Address *to)
302 {
303 if (getObjectID() == to->getObjectID()) {
304 uint64 res = addr - ((AddressFlat64 *)to)->addr;
305 uint32 rh = res >> 32;
306 if (!rh || rh == 0xffffffff) {
307 result = res;
308 return true;
309 }
310 }
311 return false;
312 }
313
clone() const314 AddressFlat64 *AddressFlat64::clone() const
315 {
316 return new AddressFlat64(*this);
317 }
318
getFromArray(const byte * array)319 void AddressFlat64::getFromArray(const byte *array)
320 {
321 memcpy(&addr, array, sizeof(addr));
322 }
323
getFromCPUAddress(CPU_ADDR * ca)324 void AddressFlat64::getFromCPUAddress(CPU_ADDR *ca)
325 {
326 addr = ca->flat64.addr;
327 }
328
getFromUInt64(uint64 u)329 bool AddressFlat64::getFromUInt64(uint64 u)
330 {
331 addr = u;
332 return true;
333 }
334
load(ObjectStream & st)335 void AddressFlat64::load(ObjectStream &st)
336 {
337 GET_INT64X(st, addr);
338 }
339
getObjectID() const340 ObjectID AddressFlat64::getObjectID() const
341 {
342 return ATOM_ADDRESS_FLAT_64;
343 }
344
parseString(const char * s,int length,Analyser * a)345 int AddressFlat64::parseString(const char *s, int length, Analyser *a)
346 {
347 return false;
348 }
349
putIntoArray(byte * array) const350 void AddressFlat64::putIntoArray(byte *array) const
351 {
352 memcpy(array, &addr, sizeof(addr));
353 }
354
putIntoCPUAddress(CPU_ADDR * ca) const355 void AddressFlat64::putIntoCPUAddress(CPU_ADDR *ca) const
356 {
357 ca->flat64.addr = addr;
358 }
359
putIntoUInt64(uint64 & u) const360 bool AddressFlat64::putIntoUInt64(uint64 &u) const
361 {
362 u = addr;
363 return true;
364 }
365
store(ObjectStream & st) const366 void AddressFlat64::store(ObjectStream &st) const
367 {
368 PUT_INT64X(st, addr);
369 }
370
stringify(char * s,int max_length,int format) const371 int AddressFlat64::stringify(char *s, int max_length, int format) const
372 {
373 const char *formats[] = {
374 "%s%qx%s",
375 "%s%16qx%s",
376 "%s%016qx%s",
377 "",
378 "%s%qx%s",
379 "%s%16qx%s",
380 "%s%016qx%s",
381 "",
382 };
383 return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
384 }
385
stringSize() const386 int AddressFlat64::stringSize() const
387 {
388 return 16;
389 }
390
391
392 /*
393 *
394 */
395
AddrXRef(Address * a,xref_enum_t Type)396 AddrXRef::AddrXRef(Address *a, xref_enum_t Type)
397 {
398 addr = a->clone();
399 type = Type;
400 }
401
~AddrXRef()402 AddrXRef::~AddrXRef()
403 {
404 delete addr;
405 }
406
load(ObjectStream & f)407 void AddrXRef::load(ObjectStream &f)
408 {
409 GET_OBJECT(f, addr);
410 type = (xref_enum_t)GETX_INTX(f, 1, "type");
411 }
412
getObjectID() const413 ObjectID AddrXRef::getObjectID() const
414 {
415 return ATOM_ADDR_XREF;
416 }
417
store(ObjectStream & f) const418 void AddrXRef::store(ObjectStream &f) const
419 {
420 PUT_OBJECT(f, addr);
421 PUT_INTX(f, type, 1);
422 }
423
compareTo(const Object * o) const424 int AddrXRef::compareTo(const Object *o) const
425 {
426 Address *a = ((AddrXRef*)o)->addr;
427 return addr->compareTo(a);
428 }
429
430 /*
431 *
432 */
AddressQueueItem(Address * aAddr,Address * aFunc)433 AddressQueueItem::AddressQueueItem(Address *aAddr, Address *aFunc)
434 {
435 addr = aAddr->clone();
436 func = aFunc->clone();
437 }
438
~AddressQueueItem()439 AddressQueueItem::~AddressQueueItem()
440 {
441 delete addr;
442 delete func;
443 }
444
getObjectID() const445 ObjectID AddressQueueItem::getObjectID() const
446 {
447 return ATOM_ADDR_QUEUE_ITEM;
448 }
449
load(ObjectStream & f)450 void AddressQueueItem::load(ObjectStream &f)
451 {
452 GET_OBJECT(f, addr);
453 GET_OBJECT(f, func);
454 }
455
store(ObjectStream & f) const456 void AddressQueueItem::store(ObjectStream &f) const
457 {
458 PUT_OBJECT(f, addr);
459 PUT_OBJECT(f, func);
460 }
461
462 /*
463 *
464 */
CommentList()465 CommentList::CommentList()
466 : Array(true)
467 {
468 }
469
appendPreComment(const char * s)470 void CommentList::appendPreComment(const char *s)
471 {
472 insert(new String(s));
473 }
474
appendPostComment(const char * s)475 void CommentList::appendPostComment(const char *s)
476 {
477 insert(new String(s));
478 }
479
appendPreComment(int special)480 void CommentList::appendPreComment(int special)
481 {
482 insert(new UInt(special));
483 }
484
appendPostComment(int special)485 void CommentList::appendPostComment(int special)
486 {
487 insert(new UInt(special+0x10000000));
488 }
489
getName(uint i)490 const char *CommentList::getName(uint i)
491 {
492 Object *d = get(findByIdx(i));
493 // return d ? ((d->getObjectID()==OBJID_UINT) ? comment_lookup(((UInt*)d)->value):
494 return d ? ((String*)d)->contentChar() : NULL;
495 }
496
497 /*
498 *
499 */
init()500 void Analyser::init()
501 {
502 active = false;
503 dirty = false;
504 next_address_is_invalid = false;
505 addr = new InvalidAddress();
506 invalid_addr = new InvalidAddress();
507 addr_queue = new Queue(true);
508 locations = NULL;
509 symbols = NULL;
510 symbol_count = location_count = 0;
511 cur_addr_ops = cur_label_ops = 1;
512 setLocationTreeOptimizeThreshold(1000);
513 setSymbolTreeOptimizeThreshold(1000);
514 cur_func = NULL;
515 ops_parsed = 0;
516 next_explored = new InvalidAddress();
517 first_explored = new InvalidAddress();
518 last_explored = new InvalidAddress();
519 explored = new Area();
520 explored->init();
521 initialized = new Area();
522 initialized->init();
523 initCodeAnalyser();
524 initDataAnalyser();
525 disasm = NULL;
526 analy_disasm = NULL;
527 max_opcode_length = 1;
528 initUnasm();
529 mode = ANALY_TRANSLATE_SYMBOLS;
530 }
531
loadlocations(ObjectStream & st,Location * & loc,int l,int r)532 static void loadlocations(ObjectStream &st, Location *&loc, int l, int r)
533 {
534 if (l > r) {
535 loc = NULL;
536 return;
537 }
538 int m = (l+r)/2;
539 loc = new Location;
540
541 loadlocations(st, loc->left, l, m-1);
542
543 loc->addr = GETX_OBJECT(st , "addr");
544
545 // xrefs
546 loc->xrefs = GETX_OBJECT(st, "xrefs");
547
548 // comments
549 loc->comments = GETX_OBJECT(st, "comments");
550
551 analyser_get_addrtype(st, &loc->type);
552
553 // must be resolved later (thisfunc is of type Location not Address)
554 Address *a = GETX_OBJECT(st, "func");
555 loc->thisfunc = (Location *)a;
556 loc->flags = GETX_INT(st, 1, "flags");
557 loc->label = NULL;
558
559 loadlocations(st, loc->right, m+1, r);
560 }
561
loadsymbols(Analyser * analy,ObjectStream & st,Symbol * & symbol,int l,int r)562 static void loadsymbols(Analyser *analy, ObjectStream &st, Symbol *&symbol, int l, int r)
563 {
564 if (l > r) {
565 symbol = NULL;
566 return;
567 }
568 int m = (l+r)/2;
569 symbol = new Symbol;
570
571 loadsymbols(analy, st, symbol->left, l, m-1);
572
573 Address *a = GETX_OBJECT(st, "addr");
574
575 (symbol->location = analy->newLocation(a))->label = symbol;
576 delete a;
577
578 symbol->name = st.getString("name");
579
580 symbol->type = (labeltype)GETX_INT(st, 1, "type");
581
582 loadsymbols(analy, st, symbol->right, m+1, r);
583 }
584
resolveaddrs(Analyser * a,Location * loc)585 static void resolveaddrs(Analyser *a, Location *loc)
586 {
587 if (loc) {
588 resolveaddrs(a, loc->left);
589 Address *tmp = (Address*)loc->thisfunc;
590 if (tmp->isValid()) {
591 loc->thisfunc = a->getLocationByAddress(tmp);
592 } else {
593 loc->thisfunc = NULL;
594 }
595 delete tmp;
596 resolveaddrs(a, loc->right);
597 }
598 }
599
600 /*
601 *
602 */
load(ObjectStream & st)603 void Analyser::load(ObjectStream &st)
604 {
605 cur_addr_ops = 0;
606 cur_label_ops = 0;
607 GET_OBJECT(st, addr);
608 invalid_addr = new InvalidAddress();
609 GET_OBJECT(st, addr_queue);
610 GET_INT32D(st, ops_parsed);
611 GET_BOOL(st, active);
612 if (active) {
613 some_analyser_active++;
614 }
615 next_address_is_invalid = false;
616 GET_OBJECT(st, next_explored);
617 GET_OBJECT(st, first_explored);
618 GET_OBJECT(st, last_explored);
619
620 GET_INT32X(st, mode);
621
622 GET_OBJECT(st, explored);
623 GET_OBJECT(st, initialized);
624
625 cur_addr_ops = cur_label_ops = 1;
626 setLocationTreeOptimizeThreshold(1000);
627 setSymbolTreeOptimizeThreshold(1000);
628
629 GET_INT32D(st, location_count);
630 loadlocations(st, locations, 0, location_count-1);
631
632 resolveaddrs(this, locations);
633
634 GET_INT32D(st, symbol_count);
635 loadsymbols(this, st, symbols, 0, symbol_count-1);
636
637 GET_OBJECT(st, analy_disasm);
638 GET_OBJECT(st, disasm);
639 if (analy_disasm) {
640 analy_disasm->analy = this;
641 analy_disasm->disasm = disasm;
642 }
643 GET_OBJECT(st, code);
644 GET_OBJECT(st, data);
645 if (data) {
646 data->analy = this;
647 }
648 GET_INT32D(st, location_threshold);
649 GET_INT32D(st, symbol_threshold);
650
651 GET_INT32D(st, max_opcode_length);
652
653 Address *curfuncaddr = GETX_OBJECT(st, "cur_func");
654 if (curfuncaddr) {
655 cur_func = newLocation(curfuncaddr);
656 delete curfuncaddr;
657 } else {
658 cur_func = NULL;
659 }
660
661 dirty = false;
662 }
663
664 /*
665 *
666 */
done()667 void Analyser::done()
668 {
669 setActive(false);
670 freeLocations(locations);
671 freeSymbols(symbols);
672 delete addr_queue;
673 if (explored) {
674 explored->done();
675 delete explored;
676 }
677 if (initialized) {
678 initialized->done();
679 delete initialized;
680 }
681 if (code) {
682 code->done();
683 delete code;
684 }
685 if (data) {
686 data->done();
687 delete data;
688 }
689 if (disasm) {
690 disasm->done();
691 delete disasm;
692 }
693 if (analy_disasm) {
694 analy_disasm->done();
695 delete analy_disasm;
696 }
697 delete addr;
698 delete invalid_addr;
699 delete next_explored;
700 delete first_explored;
701 delete last_explored;
702 }
703
704 /*
705 * addAddressSymbol will never overwrite an existing label (like addlabel)
706 */
addAddressSymbol(Address * address,const char * prefix,labeltype type,Location * infunc)707 bool Analyser::addAddressSymbol(Address *address, const char *prefix, labeltype type, Location *infunc)
708 {
709 if (!validAddress(address, scvalid)) return false;
710
711 char symbol[1024];
712 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
713 ht_snprintf(symbol, sizeof symbol, "%s_%y", prefix, address);
714
715 if (addSymbol(address, symbol, type, infunc)) {
716 return true;
717 } else {
718 return false;
719 }
720 }
721
722 /*
723 *
724 */
addComment(Address * Addr,int line,const char * c)725 void Analyser::addComment(Address *Addr, int line, const char *c)
726 {
727 // line 0 meens append (at the moment assume append every time ;-))
728
729 // if (!validaddr(Addr, scvalid)) return;
730
731 Location *a = newLocation(Addr);
732
733 CommentList *com = a->comments;
734
735 if (!com) {
736 com = new CommentList();
737 com->init();
738 a->comments = com;
739 }
740 com->appendPreComment(c);
741
742 DPRINTF("#(%y) comment `%s'\n", Addr, c);
743 }
744
745 /*
746 * addlabel: create label if there isnt one
747 * fail if label exist on another address
748 *
749 */
addSymbol(Address * Addr,const char * label,labeltype type,Location * infunc)750 bool Analyser::addSymbol(Address *Addr, const char *label, labeltype type, Location *infunc)
751 {
752 if (!validAddress(Addr, scvalid)) return false;
753
754 Location *a = newLocation(Addr);
755
756 if (!a->label) {
757
758 Symbol *l = newSymbol(label, a, type, infunc);
759
760 if (l->location->addr->compareTo(Addr) != 0) {
761 // this label already exists at a different address
762 return false;
763 }
764
765 a->label = l;
766 if (a->type.type == dt_unknown || a->type.type == dt_unknown_data) {
767 if (type == label_func && !validCodeAddress(Addr)) {
768 type = label_unknown;
769 }
770 switch (type) {
771 case label_unknown:
772 break;
773 case label_func:
774 data->setCodeAddressType(a, dst_function);
775 break;
776 case label_loc:
777 data->setCodeAddressType(a, dst_location);
778 break;
779 case label_data:
780 data->setAddressType(a, dt_unknown_data, 0, 0);
781 break;
782 }
783 }
784 return true;
785
786 } else {
787
788 // adress already has a label
789 return false;
790 }
791 }
792
793 /*
794 *
795 */
addXRef(Address * from,Address * to,xref_enum_t action)796 bool Analyser::addXRef(Address *from, Address *to, xref_enum_t action)
797 {
798 if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return false;
799
800 Location *a = newLocation(from);
801 Container *x = a->xrefs;
802
803 if (x) {
804 AddrXRef tmp(to);
805 if (x->find(&tmp)) return false;
806 } else {
807 x = new AVLTree(true);
808 a->xrefs = x;
809 }
810 x->insert(new AddrXRef(to, action));
811
812 DPRINTF("xref %y->%y\n", from, to);
813 return true;
814 }
815
816 /*
817 *
818 */
assignComment(Address * Addr,int line,const char * c)819 void Analyser::assignComment(Address *Addr, int line, const char *c)
820 {
821 /* not really implemented */
822 addComment(Addr, line, c);
823 }
824
825 /*
826 *
827 */
assignSymbol(Address * Addr,const char * label,labeltype type,Location * infunc)828 bool Analyser::assignSymbol(Address *Addr, const char *label, labeltype type, Location *infunc)
829 {
830 if (!validAddress(Addr, scvalid)) return false;
831
832 Location *a = newLocation(Addr);
833
834 Symbol *l = newSymbol(label, a, type, infunc);
835 if (l->location->addr->compareTo(Addr) != 0) {
836 // label already exists at a different address
837 return false;
838 }
839
840 if (l->location->type.type == dt_unknown) {
841 if (type == label_func && !validCodeAddress(Addr)) {
842 type = label_unknown;
843 }
844 switch (type) {
845 case label_unknown:
846 break;
847 case label_func:
848 data->setCodeAddressType(a, dst_function);
849 break;
850 case label_loc:
851 data->setCodeAddressType(a, dst_location);
852 break;
853 case label_data:
854 data->setAddressType(a, dt_unknown_data, 0, 0);
855 break;
856 }
857 }
858
859 if (a->label) {
860 // overwrite
861 if (a->label != l) {
862 // label has to be renamed
863 disableSymbol(a->label);
864 a->label = l;
865 }
866 } else {
867 a->label = l;
868 }
869 return true;
870 }
871
872 /*
873 *
874 */
assignXRef(Address * from,Address * to,xref_enum_t action)875 void Analyser::assignXRef(Address *from, Address *to, xref_enum_t action)
876 {
877 if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return;
878
879 Location *a = newLocation(from);
880 Container *x = a->xrefs;
881
882 if (x) {
883 AddrXRef *xref;
884 AddrXRef tmp(to);
885 if ((xref = (AddrXRef*)x->get(x->find(&tmp)))) {
886 // update xref
887 xref->type = action;
888 DPRINTF("xref %y->%y updated\n", from, to);
889 return;
890 }
891 } else {
892 x = new AVLTree(true);
893 a->xrefs = x;
894 }
895 x->insert(new AddrXRef(to, action));
896
897 DPRINTF("xref %y->%y\n", from, to);
898 }
899
900 /*
901 *
902 */
beginAnalysis()903 void Analyser::beginAnalysis()
904 {
905 if (queryConfig(Q_DO_ANALYSIS)) {
906 DPRINTF("################################\nAnalysis started.\n");
907 if (analy_disasm && disasm) {
908 ops_parsed = 0;
909 if (gotoAddress(invalid_addr, invalid_addr)) setActive(true);
910 } else {
911 DPRINTF("Analysis can't be started. No disassembler available.");
912 }
913 }
914 }
915
916 /*
917 *
918 */
continueAnalysis()919 bool Analyser::continueAnalysis()
920 {
921 byte buf[32];
922 OPCODE *instr;
923 int len;
924 branch_enum_t branch;
925
926 assert((uint)max_opcode_length <= sizeof buf);
927
928 if (!active) return false;
929 do {
930
931 int diff;
932 // char tbuf[100];
933 // char tbuf2[100];
934 // addr->stringify(tbuf, 100, 0);
935 /* if (strcmp(tbuf, "200970ec") == 0) {
936 int as=0;
937 }*/
938 // printf("*** %s ***\n", tbuf);
939 if ((addr->difference(diff, next_explored) && (diff >= 0)) || !validCodeAddress(addr)) {
940 if (!gotoAddress(addr, invalid_addr)) {
941 finish();
942 return false;
943 }
944 }
945
946 int bz = bufPtr(addr, buf, max_opcode_length);
947
948 instr = disasm->decode(buf, bz, mapAddr(addr));
949 instr = disasm->duplicateInsn(instr);
950
951 ops_parsed++;
952 num_ops_parsed++;
953
954 len = disasm->getSize(instr);
955 last_explored->add(len);
956
957 do {
958 DPRINTF("opcode @%y [func: %y]: %s\n", addr, (cur_func) ? cur_func->addr : invalid_addr, disasm->str(instr, 0));
959 if (disasm->validInsn(instr)) {
960 branch = analy_disasm->isBranch(instr);
961 if (branch != br_nobranch) {
962 doBranch(branch, instr, len);
963 } else {
964 analy_disasm->examineOpcode(instr);
965 }
966 } else {
967 DPRINTF("invalid opcode @%y\n", addr);
968 // log("invalid opcode at address %y\n", addr);
969 if (!addr->add(len)) {
970 delete addr;
971 addr = new InvalidAddress();
972 } else {
973 newLocation(addr)->flags |= AF_FUNCTION_END;
974 next_address_is_invalid = true;
975 }
976 }
977 } while (disasm->selectNext(instr));
978 if (next_address_is_invalid || !addr->add(len)) {
979 gotoAddress(invalid_addr, invalid_addr);
980 next_address_is_invalid = false;
981 }
982 free(instr);
983 } while ((ops_parsed % MAX_OPS_PER_CONTINUE) !=0);
984 return true;
985 }
986
987 /*
988 *
989 */
continueAnalysisAt(Address * Addr)990 void Analyser::continueAnalysisAt(Address *Addr)
991 {
992 if (!validAddress(Addr, sccode)) return;
993 if (queryConfig(Q_DO_ANALYSIS)) {
994 DPRINTF("continueing analysis at %y\n", Addr);
995 if (active || disasm) {
996 data->setCodeAddressType(Addr, dst_function);
997 pushAddress(Addr, Addr);
998 }
999 if (!active) {
1000 if (disasm) {
1001 Analyser::beginAnalysis();
1002 } else {
1003 DPRINTF("couldn't start analysis: no disasm available\n");
1004 }
1005 }
1006 }
1007 }
1008
1009 /*
1010 * should return a new instance of an apropriate assembler
1011 */
createAssembler()1012 Assembler *Analyser::createAssembler()
1013 {
1014 return NULL;
1015 }
1016
1017 /*
1018 *
1019 */
dataAccess(Address * Addr,taccess access)1020 void Analyser::dataAccess(Address *Addr, taccess access)
1021 {
1022 if (!validAddress(Addr, scvalid)) {
1023 char msg[100];
1024 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
1025 ht_snprintf(msg, sizeof msg, "access of invalid addr %y at addr %y", Addr, addr);
1026 log(msg);
1027 return;
1028 }
1029
1030 DPRINTF("dataaccess of %y\n", Addr);
1031
1032 // string test
1033 byte buffer[1024];
1034
1035 if (validAddress(Addr, scinitialized)) {
1036 uint bz = bufPtr(Addr, buffer, sizeof buffer);
1037 if (bz > 2) {
1038 analy_string *str = string_test(buffer, bz);
1039 if (str) {
1040 char string1[128], string2[128];
1041 str->render_string(string2, sizeof string2);
1042 ht_snprintf(string1, sizeof string1, "%s_%s", str->name(), string2);
1043 make_valid_name(string2, string1);
1044 if (addAddressSymbol(Addr, string2, label_data)) {
1045 addComment(Addr, 0, "");
1046 }
1047 data->setArrayAddressType(Addr, dst_string, str->length());
1048 str->done();
1049 delete str;
1050 return;
1051 }
1052 }
1053 }
1054
1055 if (validCodeAddress(Addr) && access.type == acoffset) {
1056 if (addAddressSymbol(Addr, LPRFX_OFS, label_func)) {
1057 addComment(Addr, 0, "");
1058 }
1059 Location *a = getLocationByAddress(Addr);
1060 assert(a);
1061 // test if Addr points to code
1062 if ((a->type.type == dt_unknown) || (a->type.type == dt_code)) {
1063 // test if Addr points to valid code (test not yet complete)
1064 byte buf[16];
1065 int bz = bufPtr(Addr, buf, sizeof(buf));
1066 OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
1067 if (disasm->validInsn(instr)) {
1068 data->setCodeAddressType(Addr, dst_cunknown);
1069 pushAddress(Addr, Addr);
1070 }
1071 }
1072 } else {
1073 if (access.type != acoffset) {
1074 switch (access.size) {
1075 case 1: data->setIntAddressType(Addr, dst_ibyte, 1); break;
1076 case 2: data->setIntAddressType(Addr, dst_iword, 2); break;
1077 case 4: data->setIntAddressType(Addr, dst_idword, 4); break;
1078 }
1079 }
1080 if (validAddress(Addr, scinitialized)) {
1081 addAddressSymbol(Addr, LPRFX_DTA, label_data);
1082 } else {
1083 addAddressSymbol(Addr, LPRFX_DTU, label_data);
1084 }
1085 }
1086 }
1087
1088 /*
1089 * disables address, frees misc
1090 */
deleteLocation(Address * Addr)1091 void Analyser::deleteLocation(Address *Addr)
1092 {
1093 Location *a = getLocationByAddress(Addr);
1094 if (a) {
1095 disableSymbol(a->label);
1096 a->label = NULL;
1097 a->flags |= AF_DELETED;
1098 location_count--;
1099 }
1100 }
1101
1102 /*
1103 * disables label of an address and unassigns address' label
1104 */
deleteSymbol(Address * Addr)1105 void Analyser::deleteSymbol(Address *Addr)
1106 {
1107 Location *a = getLocationByAddress(Addr);
1108 if (a) {
1109 disableSymbol(a->label);
1110 a->label = NULL;
1111 symbol_count--;
1112 }
1113 }
1114
1115 /*
1116 *
1117 */
deleteXRef(Address * from,Address * to)1118 bool Analyser::deleteXRef(Address *from, Address *to)
1119 {
1120 if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return false;
1121
1122 Location *a = getLocationByAddress(from);
1123 if (!a) return false;
1124 Container *x = a->xrefs;
1125 if (!x) return false;
1126
1127 DPRINTF("deleted xref %y->%y\n", from, to);
1128
1129 AddrXRef tmp(to);
1130 return x->delObj(&tmp);
1131 }
1132
1133 /*
1134 * an disabled label will be overwritten as soon as possible,
1135 * and never be returned nor saved.
1136 * performed this way to preserve the labeltrees structure
1137 *
1138 */
disableSymbol(Symbol * label)1139 void Analyser::disableSymbol(Symbol *label)
1140 {
1141 if (label) {
1142 label->location = NULL;
1143 }
1144 }
1145
1146 /*
1147 *
1148 */
doBranch(branch_enum_t branch,OPCODE * opcode,int len)1149 void Analyser::doBranch(branch_enum_t branch, OPCODE *opcode, int len)
1150 {
1151 Address *branch_addr = analy_disasm->branchAddr(opcode, branch, true);
1152
1153 if (branch != br_return) {
1154 if (!validCodeAddress(branch_addr)) {
1155 char msg[100];
1156 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS;
1157 ht_snprintf(msg, sizeof msg, "branch to invalid addr %y from addr %y", branch_addr, addr);
1158 log(msg);
1159 }
1160 }
1161 /* if (branch != brcall) {
1162 taddr *a = new_addr(addr+len);
1163 if (!a->comments) {
1164 add_comment(a->addr, 0, "");
1165 }
1166 }*/
1167 Address *next_addr = addr->clone();
1168 if (!next_addr->add(len)) {
1169 delete next_addr;
1170 next_addr = new InvalidAddress();
1171 }
1172 switch (branch) {
1173 case br_jump:
1174 if (next_addr->isValid())
1175 newLocation(next_addr)->flags |= AF_FUNCTION_END;
1176
1177 addXRef(branch_addr, addr, xrefjump);
1178 if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) {
1179 addComment(branch_addr, 0, "");
1180 }
1181 // gotoAddress(branch_addr, invalid_addr);
1182 pushAddress(branch_addr, invalid_addr);
1183 next_address_is_invalid = true;
1184 break;
1185 case br_return:
1186 if (next_addr->isValid())
1187 newLocation(next_addr)->flags |= AF_FUNCTION_END;
1188
1189 next_address_is_invalid = true;
1190 break;
1191 case br_call: {
1192 addXRef(branch_addr, addr, xrefcall);
1193 bool special_func = false;
1194 const char *lprfx = LPRFX_SUB;
1195 if (!getSymbolByAddress(branch_addr) && validCodeAddress(branch_addr)) {
1196 // should be in code_analy
1197 byte buf[16];
1198 int bz = bufPtr(branch_addr, buf, sizeof(buf));
1199 OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(branch_addr));
1200 branch_enum_t bt = analy_disasm->isBranch(instr);
1201
1202 if (bt == br_return) {
1203 lprfx = LPRFX_STUB;
1204 } else if (bt == br_jump) {
1205 char buf[1024], label[1024];
1206 Address *wrap_addr = analy_disasm->branchAddr(instr, bt, false);
1207 if (validAddress(wrap_addr, scvalid)) {
1208 Symbol *l = getSymbolByAddress(wrap_addr);
1209 addComment(branch_addr, 0, "");
1210 addComment(branch_addr, 0, ";----------------------------------------------");
1211 global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;
1212 if (l && l->name) {
1213 ht_snprintf(buf, sizeof buf, "%s %s", "; W R A P P E R for", l->name);
1214 ht_snprintf(label, sizeof label, "%s_%s_%y", LPRFX_WRAP, l->name, branch_addr);
1215 } else {
1216 ht_snprintf(buf, sizeof buf, "%s %s %y", "; W R A P P E R for", "address", wrap_addr);
1217 ht_snprintf(label, sizeof label, "%s_%y_%y", LPRFX_WRAP, wrap_addr, branch_addr);
1218 }
1219 addComment(branch_addr, 0, buf);
1220 addComment(branch_addr, 0, ";----------------------------------------------");
1221 addSymbol(branch_addr, label, label_func);
1222 special_func = true;
1223 }
1224 delete wrap_addr;
1225 }
1226 }
1227 if (!special_func && addAddressSymbol(branch_addr, lprfx, label_func)) {
1228 addComment(branch_addr, 0, "");
1229 addComment(branch_addr, 0, ";-----------------------");
1230 addComment(branch_addr, 0, "; S U B R O U T I N E");
1231 addComment(branch_addr, 0, ";-----------------------");
1232 if (branch_addr->compareTo(cur_func->addr) == 0) {
1233 addComment(branch_addr, 0, "; (recursive)");
1234 }
1235 }
1236 // pushAddress(next_addr, cur_func->addr);
1237 // gotoAddress(branch_addr, branch_addr);
1238 pushAddress(branch_addr, branch_addr);
1239 break;
1240 }
1241 case br_jXX:
1242 addXRef(branch_addr, addr, xrefjump);
1243 if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) {
1244 addComment(branch_addr, 0, "");
1245 }
1246 // pushAddress(next_addr, cur_func->addr);
1247 // gotoAddress(branch_addr, invalid_addr);
1248 pushAddress(branch_addr, invalid_addr);
1249 break;
1250 default:{}
1251 // stupid but neccessary
1252 }
1253 delete next_addr;
1254 delete branch_addr;
1255 }
1256
1257 /*
1258 *
1259 */
engageCodeanalyser()1260 void Analyser::engageCodeanalyser()
1261 {
1262 if (queryConfig(Q_ENGAGE_CODE_ANALYSER)) {
1263 DPRINTF("starting code analyser.\n");
1264 }
1265 }
1266
analyserenum_addrs(Location * locs,Address * at,Location * & loc)1267 static void analyserenum_addrs(Location *locs, Address *at, Location *&loc)
1268 {
1269 if ((at->compareTo(locs->addr) < 0) || !at->isValid()) {
1270 loc = locs;
1271 if (locs->left) analyserenum_addrs(locs->left, at, loc);
1272 } else /*if (at >= locs->addr)*/ {
1273 if (locs->right) analyserenum_addrs(locs->right, at, loc);
1274 }
1275 }
1276
1277 /*
1278 *
1279 */
enumLocations(Address * Addr)1280 Location *Analyser::enumLocations(Address *Addr)
1281 {
1282 Location *result = NULL;
1283 if (locations) analyserenum_addrs(locations, Addr, result);
1284 while (result && (result->flags & AF_DELETED)) {
1285 Address *a = result->addr;
1286 result = NULL;
1287 analyserenum_addrs(locations, a, result);
1288 }
1289 return result;
1290 }
1291
analyserenum_addrs_back(Location * locs,Address * at,Location * & loc)1292 static void analyserenum_addrs_back(Location *locs, Address *at, Location *&loc)
1293 {
1294 if (at->compareTo(locs->addr) <= 0) {
1295 if (locs->left) analyserenum_addrs_back(locs->left, at, loc);
1296 } else /*if (at > locs->addr)*/ {
1297 loc = locs;
1298 if (locs->right) analyserenum_addrs_back(locs->right, at, loc);
1299 }
1300 }
1301
1302 /*
1303 *
1304 */
enumLocationsReverse(Address * Addr)1305 Location *Analyser::enumLocationsReverse(Address *Addr)
1306 {
1307 Location *result = NULL;
1308 if (locations) analyserenum_addrs_back(locations, Addr, result);
1309 while ((result) && (result->flags & AF_DELETED)) {
1310 Address *a = result->addr;
1311 result = NULL;
1312 analyserenum_addrs_back(locations, a, result);
1313 }
1314 return result;
1315 }
1316
analyserenum_labels(Symbol * labels,const char * at,Symbol * & label)1317 static void analyserenum_labels(Symbol *labels, const char *at, Symbol *&label)
1318 {
1319 int i = strcmp(at, labels->name);
1320 if (i < 0) {
1321 label = labels;
1322 if (labels->left) analyserenum_labels(labels->left, at, label);
1323 } else /*if (i >= 0)*/ {
1324 if (labels->right) analyserenum_labels(labels->right, at, label);
1325 }
1326 }
1327
1328 /*
1329 * returns the (alphanumerically) next label to "at"
1330 * or the first if "at" is NULL
1331 * returns NULL if there is no preceding label
1332 *
1333 */
enumSymbolsByName(const char * at)1334 Symbol *Analyser::enumSymbolsByName(const char *at)
1335 {
1336 Symbol *result = NULL;
1337 if (!at) at="";
1338 if (symbols) analyserenum_labels(symbols, at, result);
1339
1340 // label with !addr mustnt be returned
1341 while ((result) && (!result->location)) {
1342 char *name = result->name;
1343 result = NULL;
1344 analyserenum_labels(symbols, name, result);
1345 }
1346
1347 return result;
1348 }
1349
analyserenum_labels_back(Symbol * labels,const char * at,Symbol * & label)1350 static void analyserenum_labels_back(Symbol *labels, const char *at, Symbol *&label)
1351 {
1352 int i = strcmp(at, labels->name);
1353 if (i <= 0) {
1354 if (labels->left) analyserenum_labels_back(labels->left, at, label);
1355 } else /*if (i >= 0)*/ {
1356 label = labels;
1357 if (labels->right) analyserenum_labels_back(labels->right, at, label);
1358 }
1359 }
1360
1361 /*
1362 *
1363 */
enumSymbolsByNameReverse(const char * at)1364 Symbol *Analyser::enumSymbolsByNameReverse(const char *at)
1365 {
1366 Symbol *result = NULL;
1367 // FIXME:
1368 if (!at) at="\xff\xff\xff";
1369 if (symbols) analyserenum_labels_back(symbols, at, result);
1370
1371 // labels with !addr mustnt be returned
1372 while ((result) && (!result->location)) {
1373 char *name = result->name;
1374 result = NULL;
1375 analyserenum_labels_back(symbols, name, result);
1376 }
1377
1378 return result;
1379 }
1380
enumSymbols(Symbol * sym)1381 Symbol *Analyser::enumSymbols(Symbol *sym)
1382 {
1383 if (sym) {
1384 return enumSymbolsByName(sym->name);
1385 } else {
1386 return enumSymbolsByName(NULL);
1387 }
1388 }
1389
enumSymbolsReverse(Symbol * sym)1390 Symbol *Analyser::enumSymbolsReverse(Symbol *sym)
1391 {
1392 if (sym) {
1393 return enumSymbolsByNameReverse(sym->name);
1394 } else {
1395 return enumSymbolsByNameReverse(NULL);
1396 }
1397 }
1398
1399
1400 /*
1401 *
1402 */
examineData(Address * Addr)1403 taddr_typetype Analyser::examineData(Address *Addr)
1404 {
1405 if ((validReadAddress(Addr)) && (validAddress(Addr, scinitialized))) {
1406 DPRINTF("examinating data @%y:\n", Addr);
1407
1408 } else return dt_unknown;
1409 return dt_unknown;
1410 }
1411
1412 /*
1413 *
1414 */
analyserfindaddr(Location * locs,Address * Addr)1415 static Location *analyserfindaddr(Location *locs, Address *Addr)
1416 {
1417 if (locs) {
1418 if (Addr->compareTo(locs->addr) < 0) return analyserfindaddr(locs->left, Addr);
1419 if (Addr->compareTo(locs->addr) > 0) return analyserfindaddr(locs->right, Addr);
1420 return (locs->flags & AF_DELETED) ? NULL : locs;
1421 }
1422 return NULL;
1423 }
1424
1425 /*
1426 *
1427 */
getLocationByAddress(Address * Addr)1428 Location *Analyser::getLocationByAddress(Address *Addr)
1429 {
1430 return analyserfindaddr(locations, Addr);
1431 }
1432
1433 /*
1434 * finds the address Addr belongs to (if address has size > 1)
1435 */
getLocationContextByAddress(Address * Addr)1436 Location *Analyser::getLocationContextByAddress(Address *Addr)
1437 {
1438 Location *res = enumLocationsReverse(Addr);
1439 if (res && res->type.type != dt_unknown) {
1440 Address *resaddr = res->addr->clone();
1441 resaddr->add(res->type.length);
1442 if (resaddr->compareTo(Addr) > 0) {
1443 delete resaddr;
1444 return res;
1445 }
1446 delete resaddr;
1447 }
1448 return NULL;
1449 }
1450
1451 /*
1452 * finds the function the Addr belongs to (if possible/applicable).
1453 */
getFunctionByAddress(Address * Addr)1454 Location *Analyser::getFunctionByAddress(Address *Addr)
1455 {
1456 Location *loc = getLocationByAddress(Addr);
1457 if (!loc) loc = enumLocationsReverse(Addr);
1458 while (loc && !(loc->flags & AF_FUNCTION_SET)) {
1459 if (loc->flags & AF_FUNCTION_END) return NULL;
1460 loc = enumLocationsReverse(loc->addr);
1461 }
1462 return loc ? loc->thisfunc : NULL;
1463 }
1464
1465 /*
1466 * searches back to the last location
1467 */
getPreviousSymbolByAddress(Address * Addr)1468 Location *Analyser::getPreviousSymbolByAddress(Address *Addr)
1469 {
1470 Location *loc = getLocationByAddress(Addr);
1471 if (!loc) loc = enumLocationsReverse(Addr);
1472 while (loc && !loc->label) {
1473 if (loc->flags & AF_FUNCTION_END) return NULL;
1474 loc = enumLocationsReverse(loc->addr);
1475 }
1476 return loc ? loc : NULL;
1477 }
1478
1479 /*
1480 *
1481 */
analyserfindlabel(Symbol * labels,const char * label)1482 static Symbol *analyserfindlabel(Symbol *labels, const char *label)
1483 {
1484 if (labels) {
1485 int i = strcmp(label, labels->name);
1486 if (i < 0) return analyserfindlabel(labels->left, label);
1487 if (i > 0) return analyserfindlabel(labels->right, label);
1488 return labels->location ? labels : NULL;
1489 }
1490 return NULL;
1491 }
1492
1493 /*
1494 *
1495 */
getSymbolByName(const char * label)1496 Symbol *Analyser::getSymbolByName(const char *label)
1497 {
1498 return analyserfindlabel(symbols, label);
1499 }
1500
getSymbolNameByLocation(Location * loc)1501 const char *Analyser::getSymbolNameByLocation(Location *loc)
1502 {
1503 return loc ? (loc->label ? loc->label->name : NULL): NULL;
1504 }
1505
1506
1507 /**
1508 * converts |FileOfs fileofs| to |Address|
1509 */
fileofsToAddress(FileOfs fileaddr)1510 Address *Analyser::fileofsToAddress(FileOfs fileaddr)
1511 {
1512 // abstract / stub
1513 return new InvalidAddress();
1514 }
1515
1516 /**
1517 * called once every time the analyser has nothing more to do.
1518 */
finish()1519 void Analyser::finish()
1520 {
1521 DPRINTF("the analyser finished (for now).\n");
1522 cur_func = NULL;
1523 delete addr;
1524 addr = new InvalidAddress();
1525 setActive(false);
1526 }
1527
1528 /*
1529 *
1530 */
freeLocation(Location * loc)1531 void Analyser::freeLocation(Location *loc)
1532 {
1533 if (loc) {
1534 // label will be freed separatly
1535 delete loc->xrefs;
1536 freeComments(loc);
1537 delete loc->addr;
1538 delete loc;
1539 }
1540 }
1541
1542 /*
1543 *
1544 */
freeLocations(Location * addrs)1545 void Analyser::freeLocations(Location *addrs)
1546 {
1547 if (addrs) {
1548 freeLocations(addrs->left);
1549 freeLocations(addrs->right);
1550 freeLocation(addrs);
1551 }
1552 }
1553
1554 /*
1555 *
1556 */
freeComments(Location * aAddr)1557 void Analyser::freeComments(Location *aAddr)
1558 {
1559 delete aAddr->comments;
1560 aAddr->comments = NULL;
1561 }
1562
1563 /*
1564 *
1565 */
freeSymbol(Symbol * label)1566 void Analyser::freeSymbol(Symbol *label)
1567 {
1568 if (label) {
1569 free(label->name);
1570 delete label;
1571 }
1572 }
1573
1574
1575 /*
1576 *
1577 */
freeSymbols(Symbol * labels)1578 void Analyser::freeSymbols(Symbol *labels)
1579 {
1580 if (labels) {
1581 freeSymbols(labels->left);
1582 freeSymbols(labels->right);
1583 freeSymbol(labels);
1584 }
1585 }
1586
1587 /*
1588 *
1589 */
getComments(Address * Addr)1590 CommentList *Analyser::getComments(Address *Addr)
1591 {
1592 Location *a = getLocationByAddress(Addr);
1593 if (a) {
1594 return a->comments;
1595 }
1596 return NULL;
1597 }
1598
analy_addr_sym_func2(CPU_ADDR Addr,int * symstrlen,void * analy)1599 static char *analy_addr_sym_func2(CPU_ADDR Addr, int *symstrlen, void *analy)
1600 {
1601 Address *a = ((Analyser*)analy)->createAddress();
1602 a->getFromCPUAddress(&Addr);
1603 Location *loc = ((Analyser*)analy)->getLocationByAddress(a);
1604 delete a;
1605 if (loc && loc->label) {
1606 if (symstrlen) *symstrlen = strlen(loc->label->name);
1607 return loc->label->name;
1608 }
1609 return NULL;
1610 }
1611
1612 /*
1613 *
1614 */
getDisasmStr(Address * Addr,int & length)1615 const char *Analyser::getDisasmStr(Address *Addr, int &length)
1616 {
1617 if (validAddress(Addr, scinitialized)) {
1618 if (disasm) {
1619 addr_sym_func = NULL;
1620 byte buf[16];
1621 int bz = bufPtr(Addr, buf, sizeof(buf));
1622 OPCODE *o = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
1623 length = disasm->getSize(o);
1624 return disasm->strf(o, DIS_STYLE_HEX_NOZEROPAD+DIS_STYLE_HEX_ASMSTYLE, DISASM_STRF_SMALL_FORMAT);
1625 } else {
1626 return "<no disassembler!>";
1627 }
1628 } else {
1629 return "";
1630 }
1631 }
1632
1633 /*
1634 *
1635 */
getDisasmStrFormatted(Address * Addr)1636 const char *Analyser::getDisasmStrFormatted(Address *Addr)
1637 {
1638 if (disasm) {
1639 addr_sym_func_context = this;
1640 addr_sym_func = &analy_addr_sym_func2;
1641
1642 byte buf[16];
1643 int bz = bufPtr(Addr, buf, sizeof(buf));
1644 OPCODE *o=disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr));
1645 const char *res = disasm->strf(o, DIS_STYLE_HEX_NOZEROPAD+DIS_STYLE_HEX_ASMSTYLE, DISASM_STRF_SMALL_FORMAT);
1646
1647 addr_sym_func_context = NULL;
1648 addr_sym_func = NULL;
1649
1650 return res;
1651 } else {
1652 return "<no disassembler!>";
1653 }
1654 }
1655
1656 /*
1657 *
1658 */
getDisplayMode()1659 int Analyser::getDisplayMode()
1660 {
1661 return mode;
1662 }
1663
analysergetlocationcount(Location * addr,int * c)1664 static void analysergetlocationcount(Location *addr, int *c)
1665 {
1666 if (addr) {
1667 analysergetlocationcount(addr->left, c);
1668 if (!(addr->flags & AF_DELETED)) (*c)++;
1669 analysergetlocationcount(addr->right, c);
1670 }
1671 }
1672
1673 /*
1674 *
1675 */
getLocationCount() const1676 int Analyser::getLocationCount() const
1677 {
1678 int c=0;
1679 analysergetlocationcount(locations, &c);
1680 return c;
1681 }
1682
1683 /*
1684 *
1685 */
getName(String & res)1686 String & Analyser::getName(String &res)
1687 {
1688 return res = "generic";
1689 }
1690
analysergetsymbolcount(Symbol * l,int * c)1691 static void analysergetsymbolcount(Symbol *l, int *c)
1692 {
1693 if (l) {
1694 analysergetsymbolcount(l->left, c);
1695 if (l->location) (*c)++;
1696 analysergetsymbolcount(l->right, c);
1697 }
1698 }
1699
1700 /*
1701 *
1702 */
getSymbolCount() const1703 int Analyser::getSymbolCount() const
1704 {
1705 int c=0;
1706 analysergetsymbolcount(symbols, &c);
1707 return c;
1708 }
1709
1710 /*
1711 *
1712 */
getSegmentNameByAddress(Address * Addr)1713 const char *Analyser::getSegmentNameByAddress(Address *Addr)
1714 {
1715 return NULL;
1716 }
1717
1718 /*
1719 *
1720 */
getSymbolByAddress(Address * Addr)1721 Symbol *Analyser::getSymbolByAddress(Address *Addr)
1722 {
1723 Location *a = getLocationByAddress(Addr);
1724
1725 return (a) ? a->label : NULL;
1726 }
1727
1728 /*
1729 *
1730 */
getType()1731 const char *Analyser::getType()
1732 {
1733 return "generic";
1734 }
1735
1736 /*
1737 *
1738 */
getXRefs(Address * Addr)1739 Container *Analyser::getXRefs(Address *Addr)
1740 {
1741 Location *a = getLocationByAddress(Addr);
1742 if (!a) return NULL;
1743 return a->xrefs;
1744 }
1745
1746 /*
1747 *
1748 */
gotoAddress(Address * aAddr,Address * func)1749 bool Analyser::gotoAddress(Address *aAddr, Address *func)
1750 {
1751 DPRINTF("goto(%y, %y)\n", aAddr, func);
1752 int diff;
1753
1754 if (first_explored->difference(diff, last_explored) && diff < 0) {
1755 DPRINTF("explored->add(%y - %y)\n", first_explored, last_explored);
1756 explored->add(first_explored, last_explored);
1757 }
1758
1759 delete first_explored;
1760 delete last_explored;
1761 delete next_explored;
1762 func = func->clone();
1763
1764 if (!validCodeAddress(aAddr) || explored->contains(aAddr)) {
1765 DPRINTF("Address: %y Valid: %d Explored: %d\n", addr, validCodeAddress(addr), explored->contains(addr));
1766 do {
1767 delete addr;
1768 delete func;
1769 if (!popAddress(&addr, &func)) {
1770 first_explored = new InvalidAddress();
1771 last_explored = new InvalidAddress();
1772 next_explored = new InvalidAddress();
1773 addr = new InvalidAddress();
1774 return false;
1775 }
1776
1777 DPRINTF("pop %y (Valid: %d Explored: %d)\n", addr, validCodeAddress(addr), explored->contains(addr));
1778 } while ((explored->contains(addr)) || (!validCodeAddress(addr)));
1779 } else {
1780 if (addr != aAddr) {
1781 delete addr;
1782 addr = aAddr->clone();
1783 }
1784 }
1785
1786 if (func->isValid()) {
1787 cur_func = newLocation(func);
1788 setLocationFunction(cur_func, cur_func);
1789 }
1790 delete func;
1791 next_explored = (Address *)explored->findNext(addr);
1792 if (!next_explored) {
1793 next_explored = new InvalidAddress();
1794 } else {
1795 next_explored = next_explored->clone();
1796 }
1797 first_explored = addr->clone();
1798 last_explored = addr->clone();
1799 return true;
1800 }
1801
1802 /*
1803 *
1804 */
initCodeAnalyser()1805 void Analyser::initCodeAnalyser()
1806 {
1807 code = new CodeAnalyser();
1808 code->init(this);
1809 }
1810
1811 /*
1812 *
1813 */
initDataAnalyser()1814 void Analyser::initDataAnalyser()
1815 {
1816 data = new DataAnalyser();
1817 data->init(this);
1818 }
1819
1820 /*
1821 *
1822 */
isDirty()1823 bool Analyser::isDirty()
1824 {
1825 return dirty;
1826 }
1827
1828 /*
1829 *
1830 */
log(const char * s)1831 void Analyser::log(const char *s)
1832 {
1833 // stub
1834 }
1835
1836 /*
1837 *
1838 */
makeDirty()1839 void Analyser::makeDirty()
1840 {
1841 dirty = true;
1842 }
1843
1844 /*
1845 *
1846 */
mapAddr(Address * aAddr)1847 CPU_ADDR Analyser::mapAddr(Address *aAddr)
1848 {
1849 /*
1850 * this function should map the independent address Addr to a
1851 * processor dependent
1852 * e.g. .23423 --> 00234324 (or something like this)
1853 * it is only used for relativ calls/jumps
1854 */
1855 CPU_ADDR a;
1856 aAddr->putIntoCPUAddress(&a);
1857 return a;
1858 }
1859
newLocation(Location * & locs,Address * aAddr)1860 Location *Analyser::newLocation(Location *&locs, Address *aAddr)
1861 {
1862 if (locs) {
1863 if (aAddr->compareTo(locs->addr) < 0) return newLocation(locs->left, aAddr);
1864 if (aAddr->compareTo(locs->addr) > 0) return newLocation(locs->right, aAddr);
1865 } else {
1866 locs = new Location;
1867 memset(locs, 0, sizeof *locs);
1868 locs->addr = aAddr->clone();
1869 location_count++;
1870 }
1871 locs->flags &= ~AF_DELETED;
1872 return locs;
1873 }
1874
1875 /*
1876 *
1877 */
newLocation(Address * Addr)1878 Location *Analyser::newLocation(Address *Addr)
1879 {
1880 /* if (!(cur_addr_ops--)) {
1881 optimizeLocationTree();
1882 }*/
1883 return newLocation(locations, Addr);
1884 }
1885
newSymbol(Symbol * & labels,const char * label,Location * loc,labeltype type)1886 Symbol *Analyser::newSymbol(Symbol *&labels, const char *label, Location *loc, labeltype type)
1887 {
1888 if (labels) {
1889 int i = strcmp(label, labels->name);
1890 if (i < 0) return newSymbol(labels->left, label, loc, type);
1891 if (i > 0) return newSymbol(labels->right, label, loc, type);
1892 if (!labels->location) {
1893 labels->location = loc;
1894 if (type != label_unknown) labels->type = type;
1895 }
1896 } else {
1897 labels = new Symbol;
1898 labels->name = ht_strdup(label);
1899 labels->location = loc;
1900 labels->type = type;
1901 labels->left = NULL;
1902 labels->right = NULL;
1903 symbol_count++;
1904 }
1905 return labels;
1906 }
1907
1908 /*
1909 *
1910 */
newSymbol(const char * label,Location * loc,labeltype type,Location * infunc)1911 Symbol *Analyser::newSymbol(const char *label, Location *loc, labeltype type, Location *infunc)
1912 {
1913 /* if (!(cur_label_ops--)) {
1914 optimizeSymbolTree();
1915 }*/
1916 Symbol *result = newSymbol(symbols, label, loc, type);
1917 if ((result) && (result->location==loc) && (infunc)) setLocationFunction(loc, infunc);
1918 return result;
1919 }
1920
1921 /*
1922 * optimizes(=balances) addr tree
1923 */
optimizeLocationTree()1924 void Analyser::optimizeLocationTree()
1925 {
1926 cur_addr_ops = location_threshold;
1927 // implement me!
1928 }
1929
1930 /*
1931 * see optimize_addr_tree()
1932 */
optimizeSymbolTree()1933 void Analyser::optimizeSymbolTree()
1934 {
1935 cur_label_ops = symbol_threshold;
1936 // implement me!
1937 }
1938
1939 /*
1940 *
1941 */
popAddress(Address ** Addr,Address ** func)1942 bool Analyser::popAddress(Address **Addr, Address **func)
1943 {
1944 if (!addr_queue->isEmpty()) {
1945 AddressQueueItem *aqi = (AddressQueueItem *) addr_queue->deQueue();
1946 *Addr = aqi->addr->clone();
1947 *func = aqi->func->clone();
1948 delete aqi;
1949
1950 DPRINTF("addr %y (from sub %y) poped\n", *Addr, *func);
1951 return true;
1952
1953 } else {
1954 DPRINTF("pop failed -> analyser obviously finished\n");
1955 return false;
1956 }
1957 }
1958
1959 /*
1960 *
1961 */
pushAddress(Address * Addr,Address * func)1962 void Analyser::pushAddress(Address *Addr, Address *func)
1963 {
1964 if (validCodeAddress(Addr)) {
1965 if (!func->isValid()) {
1966 if (cur_func) {
1967 func = cur_func->addr;
1968 }
1969 }
1970 DPRINTF("addr %y (from func %y) pushed\n", Addr, func);
1971 AddressQueueItem *aqi = new AddressQueueItem(Addr, func);
1972 addr_queue->enQueue(aqi);
1973 }
1974 }
1975
1976 /*
1977 *
1978 */
queryConfig(int mode)1979 int Analyser::queryConfig(int mode)
1980 {
1981 switch (mode) {
1982 case Q_DO_ANALYSIS:
1983 case Q_ENGAGE_CODE_ANALYSER:
1984 case Q_ENGAGE_DATA_ANALYSER:
1985 return true;
1986 default:
1987 return 0;
1988 }
1989 }
1990
saveaddrs(ObjectStream & st,Location * addr)1991 static void saveaddrs(ObjectStream &st, Location *addr)
1992 {
1993 if (addr) {
1994 saveaddrs(st, addr->left);
1995
1996 if (!(addr->flags & AF_DELETED)) {
1997 PUTX_OBJECT(st, addr->addr, "addr");
1998 PUTX_OBJECT(st, addr->xrefs, "xrefs");
1999 PUTX_OBJECT(st, addr->comments, "comments");
2000
2001 analyser_put_addrtype(st, &addr->type);
2002
2003 if (addr->thisfunc) {
2004 PUTX_OBJECT(st, addr->thisfunc->addr, "func");
2005 } else {
2006 Address *invalid_addr = new InvalidAddress();
2007 PUTX_OBJECT(st, invalid_addr, "func");
2008 delete invalid_addr;
2009 }
2010 PUTX_INT8X(st, addr->flags, "flags");
2011 }
2012
2013 saveaddrs(st, addr->right);
2014 }
2015 }
2016
savelabels(ObjectStream & st,Symbol * label)2017 static void savelabels(ObjectStream &st, Symbol *label)
2018 {
2019 if (label) {
2020 savelabels(st, label->left);
2021
2022 if (label->location) {
2023 // label isn't deleted
2024
2025 PUTX_OBJECT(st, label->location->addr, "addr");
2026 PUTX_STRING(st, label->name, "name");
2027
2028 int a = (int)label->type;
2029 PUTX_INTX(st, a, 1, "type");
2030 }
2031
2032 savelabels(st, label->right);
2033 }
2034 }
2035
2036 /*
2037 *
2038 */
store(ObjectStream & st) const2039 void Analyser::store(ObjectStream &st) const
2040 {
2041 PUT_OBJECT(st, addr);
2042
2043 PUT_OBJECT(st, addr_queue);
2044 PUT_INT32D(st, ops_parsed);
2045 PUT_BOOL(st, active);
2046 PUT_OBJECT(st, next_explored);
2047 PUT_OBJECT(st, first_explored);
2048 PUT_OBJECT(st, last_explored);
2049 PUT_INT32X(st, mode);
2050 PUT_OBJECT(st, explored);
2051 PUT_OBJECT(st, initialized);
2052
2053 st.putComment("locations");
2054 PUTX_INT32D(st, getLocationCount(), "location_count");
2055 saveaddrs(st, locations);
2056
2057 st.putComment("symbols");
2058 PUTX_INT32D(st, getSymbolCount(), "symbol_count");
2059 savelabels(st, symbols);
2060
2061 PUT_OBJECT(st, analy_disasm);
2062 PUT_OBJECT(st, disasm);
2063 PUT_OBJECT(st, code);
2064 PUT_OBJECT(st, data);
2065
2066 PUT_INT32D(st, location_threshold);
2067 PUT_INT32D(st, symbol_threshold);
2068
2069 PUT_INT32D(st, max_opcode_length);
2070
2071 if (cur_func) {
2072 PUTX_OBJECT(st, cur_func->addr, "cur_func");
2073 } else {
2074 PUTX_OBJECT(st, NULL, "cur_func");
2075 }
2076
2077 dirty = false;
2078 }
2079
2080 /*
2081 *
2082 */
setActive(bool mode)2083 void Analyser::setActive(bool mode)
2084 {
2085 if (mode) {
2086 if (!active) {
2087 active = true;
2088 some_analyser_active++;
2089 }
2090 } else {
2091 if (active) {
2092 active = false;
2093 some_analyser_active--;
2094 }
2095 }
2096 }
2097
2098 /*
2099 *
2100 */
setDisplayMode(int enable,int disable)2101 void Analyser::setDisplayMode(int enable, int disable)
2102 {
2103 mode &= ~disable;
2104 mode |= enable;
2105 }
2106
2107 /*
2108 *
2109 */
setLocationFunction(Location * a,Location * func)2110 void Analyser::setLocationFunction(Location *a, Location *func)
2111 {
2112 if (a) {
2113 a->thisfunc = func;
2114 a->flags &= !AF_FUNCTION_END;
2115 a->flags |= AF_FUNCTION_SET;
2116 }
2117 }
2118
2119 /*
2120 *
2121 */
setDisasm(Disassembler * d)2122 void Analyser::setDisasm(Disassembler *d)
2123 {
2124 disasm = d;
2125 if (disasm) {
2126 int t;
2127 disasm->getOpcodeMetrics(t, max_opcode_length, t, t, t);
2128 } else {
2129 max_opcode_length = 1;
2130 }
2131 }
2132
2133 /*
2134 * sets addr_threshold. after threshold addr_tree ops the tree will
2135 * be optimized
2136 */
setLocationTreeOptimizeThreshold(int threshold)2137 void Analyser::setLocationTreeOptimizeThreshold(int threshold)
2138 {
2139 location_threshold = threshold;
2140 if (cur_addr_ops > location_threshold) cur_addr_ops = location_threshold;
2141 }
2142
2143 /*
2144 * see set_addr_tree_optimize_threshold
2145 */
setSymbolTreeOptimizeThreshold(int threshold)2146 void Analyser::setSymbolTreeOptimizeThreshold(int threshold)
2147 {
2148 symbol_threshold = threshold;
2149 if (cur_label_ops > symbol_threshold) cur_label_ops = symbol_threshold;
2150 }
2151
2152 /*
2153 *
2154 */
toggleDisplayMode(int toggle)2155 void Analyser::toggleDisplayMode(int toggle)
2156 {
2157 mode ^= toggle;
2158 }
2159
2160 /*
2161 *
2162 */
validCodeAddress(Address * Addr)2163 bool Analyser::validCodeAddress(Address *Addr)
2164 {
2165 Location *a = getLocationByAddress(Addr);
2166 if (a) {
2167 if ((a->type.type != dt_code) && (a->type.type != dt_unknown)) return false;
2168 }
2169 return validAddress(Addr, sccode);
2170 }
2171
2172 /*
2173 *
2174 */
validReadAddress(Address * Addr)2175 bool Analyser::validReadAddress(Address *Addr)
2176 {
2177 return validAddress(Addr, scread);
2178 }
2179
2180 /*
2181 *
2182 */
validWriteAddress(Address * Addr)2183 bool Analyser::validWriteAddress(Address *Addr)
2184 {
2185 return validAddress(Addr, scwrite);
2186 }
2187 /*
2188 * Check if a fixup is present at (Addr + offset)
2189 */
2190
isAddressFixedUp(Address * Addr,int offset)2191 bool Analyser::isAddressFixedUp(Address *Addr, int offset)
2192 {
2193 return false;
2194 }
2195
2196 /****************************************************************************/
2197
AnalyDisassembler()2198 AnalyDisassembler::AnalyDisassembler()
2199 {
2200 disasm = NULL;
2201 }
2202
2203 /*
2204 *
2205 */
init(Analyser * A)2206 void AnalyDisassembler::init(Analyser *A)
2207 {
2208 analy = A;
2209 initDisasm();
2210 }
2211
2212 /*
2213 *
2214 */
initDisasm()2215 void AnalyDisassembler::initDisasm()
2216 {
2217 if (analy) {
2218 analy->setDisasm(disasm);
2219 }
2220 }
2221
2222