📄 analy.cc
字号:
/* * HT Editor * analy.cc * * Copyright (C) 1999-2002 Sebastian Biallas (sb@biallas.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <string.h>#include <stdlib.h>#include <stdio.h>#include "analy.h"#include "analy_names.h"#include "analy_register.h"#include "code_analy.h"#include "data_analy.h"#include "io/types.h"#include "atom.h"#include "except.h"#include "htctrl.h"#include "htdebug.h"#include "strtools.h"#include "language.h"#include "snprintf.h"#include "tools.h"#define DPRINTF(msg...)//#undef DPRINTF//#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);}int global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT;int Address::compareDelinear(Address *obj){ return compareTo(obj);}bool Address::isValid(){ return true;}int Address::toString(char *s, int maxlen) const{ return stringify(s, maxlen, global_analyser_address_string_format);}bool InvalidAddress::add(int offset){ return false;}int InvalidAddress::byteSize(){ return 0;}int InvalidAddress::compareTo(const Object *obj) const{ return 0;}void InvalidAddress::putIntoCPUAddress(CPU_ADDR *ca) const{}bool InvalidAddress::difference(int &result, Address *to){ return false;}InvalidAddress *InvalidAddress::clone() const{ return new InvalidAddress(*this);}void InvalidAddress::getFromArray(const byte *array){}void InvalidAddress::getFromCPUAddress(CPU_ADDR *ca){}bool InvalidAddress::getFromUInt64(uint64 u){ return false;}bool InvalidAddress::isValid(){ return false;}int InvalidAddress::parseString(const char *s, int length, Analyser *a){ return 0;}ObjectID InvalidAddress::getObjectID() const{ return ATOM_ADDRESS_INVALID;}void InvalidAddress::putIntoArray(byte *array) const{}bool InvalidAddress::putIntoUInt64(uint64 &u) const{ return false;}int InvalidAddress::stringify(char *s, int max_length, int format) const{ return ht_snprintf(s, max_length, "*INVALID");}int InvalidAddress::stringSize() const{ return 8;}/* * */bool AddressFlat32::add(int offset){ // check for overflow if ((int)offset < 0) { if (addr+offset > addr) return false; } else { if (addr+offset < addr) return false; } addr+=offset; return true;}int AddressFlat32::byteSize(){ return 4;}int AddressFlat32::compareTo(const Object *obj) const{ assert(getObjectID() == obj->getObjectID()); if (addr > ((AddressFlat32 *)obj)->addr) return 1; if (addr < ((AddressFlat32 *)obj)->addr) return -1; return 0;}int AddressFlat32::compareDelinear(Address *to){ assert(getObjectID() == to->getObjectID()); uint32 da = delinearize(addr); uint32 db = delinearize(((AddressFlat32 *)to)->addr); if (da > db) return 1; if (da < db) return -1; return 0;}bool AddressFlat32::difference(int &result, Address *to){ if (getObjectID() == to->getObjectID()) { result = addr - ((AddressFlat32 *)to)->addr; return true; } else { return false; }}AddressFlat32 *AddressFlat32::clone() const{ return new AddressFlat32(*this);}void AddressFlat32::getFromArray(const byte *array){ UNALIGNED_MOVE(addr, *(uint32*)array);}void AddressFlat32::getFromCPUAddress(CPU_ADDR *ca){ addr = ca->addr32.offset;}bool AddressFlat32::getFromUInt64(uint64 u){ if (u <= 0xffffffff) { addr = u; return true; } else { return false; }}void AddressFlat32::load(ObjectStream &st){ GET_INT32X(st, addr);}ObjectID AddressFlat32::getObjectID() const{ return ATOM_ADDRESS_FLAT_32;}int AddressFlat32::parseString(const char *s, int length, Analyser *a){ return false;}void AddressFlat32::putIntoArray(byte *array) const{ UNALIGNED_MOVE(*(uint32*)array, addr);}void AddressFlat32::putIntoCPUAddress(CPU_ADDR *ca) const{ ca->addr32.offset = addr;}bool AddressFlat32::putIntoUInt64(uint64 &u) const{ u = addr; return true;}void AddressFlat32::store(ObjectStream &st) const{ PUT_INT32X(st, addr);}int AddressFlat32::stringify(char *s, int max_length, int format) const{ const char *formats[] = { "%s%x%s", "%s%8x%s", "%s%08x%s", "", "%s%X%s", "%s%8X%s", "%s%08X%s", "", }; return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");}int AddressFlat32::stringSize() const{ return 8;}/* * */bool AddressFlat64::add(int offset){ // check for overflow // FIXME: XXXXXXXXXXXXX addr += sint64(offset); return true;}int AddressFlat64::byteSize(){ return 8;}int AddressFlat64::compareTo(const Object *obj) const{ assert(getObjectID() == obj->getObjectID()); if (addr > ((AddressFlat64 *)obj)->addr) return 1; if (addr < ((AddressFlat64 *)obj)->addr) return -1; return 0;}int AddressFlat64::compareDelinear(Address *to){ assert(getObjectID() == to->getObjectID()); uint64 da1, da2; da1 = delinearize64(addr); da2 = delinearize64(((AddressFlat64 *)to)->addr); if (da1 > da2) return 1; if (da1 < da2) return -1; return 0;}bool AddressFlat64::difference(int &result, Address *to){ if (getObjectID() == to->getObjectID()) { uint64 res = addr - ((AddressFlat64 *)to)->addr; uint32 rh = res >> 32; if (!rh || rh == 0xffffffff) { result = res; return true; } } return false;}AddressFlat64 *AddressFlat64::clone() const{ return new AddressFlat64(*this);}void AddressFlat64::getFromArray(const byte *array){ UNALIGNED_MOVE(addr, *(uint64*)array);}void AddressFlat64::getFromCPUAddress(CPU_ADDR *ca){ addr = ca->flat64.addr;}bool AddressFlat64::getFromUInt64(uint64 u){ addr = u; return true;}void AddressFlat64::load(ObjectStream &st){ GET_INT64X(st, addr);}ObjectID AddressFlat64::getObjectID() const{ return ATOM_ADDRESS_FLAT_64;}int AddressFlat64::parseString(const char *s, int length, Analyser *a){ return false;}void AddressFlat64::putIntoArray(byte *array) const{ UNALIGNED_MOVE(*(uint64*)array, addr);}void AddressFlat64::putIntoCPUAddress(CPU_ADDR *ca) const{ ca->flat64.addr = addr;}bool AddressFlat64::putIntoUInt64(uint64 &u) const{ u = addr; return true;}void AddressFlat64::store(ObjectStream &st) const{ PUT_INT64X(st, addr);}int AddressFlat64::stringify(char *s, int max_length, int format) const{ const char *formats[] = { "%s%qx%s", "%s%16qx%s", "%s%016qx%s", "", "%s%qx%s", "%s%16qx%s", "%s%016qx%s", "", }; return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");}int AddressFlat64::stringSize() const{ return 16;}/* * */ AddrXRef::AddrXRef(Address *a, xref_enum_t Type){ addr = a->clone(); type = Type;}AddrXRef::~AddrXRef(){ delete addr;}void AddrXRef::load(ObjectStream &f){ GET_OBJECT(f, addr); type = (xref_enum_t)GETX_INTX(f, 1, "type");}ObjectID AddrXRef::getObjectID() const{ return ATOM_ADDR_XREF;}void AddrXRef::store(ObjectStream &f) const{ PUT_OBJECT(f, addr); PUT_INTX(f, type, 1);}int AddrXRef::compareTo(const Object *o) const{ Address *a = ((AddrXRef*)o)->addr; return addr->compareTo(a);}/* * */AddressQueueItem::AddressQueueItem(Address *aAddr, Address *aFunc){ addr = aAddr->clone(); func = aFunc->clone();}AddressQueueItem::~AddressQueueItem(){ delete addr; delete func;}ObjectID AddressQueueItem::getObjectID() const{ return ATOM_ADDR_QUEUE_ITEM;}void AddressQueueItem::load(ObjectStream &f){ GET_OBJECT(f, addr); GET_OBJECT(f, func);}void AddressQueueItem::store(ObjectStream &f) const{ PUT_OBJECT(f, addr); PUT_OBJECT(f, func);}/* * */CommentList::CommentList() : Array(true){}void CommentList::appendPreComment(const char *s){ insert(new String(s));}void CommentList::appendPostComment(const char *s){ insert(new String(s));}void CommentList::appendPreComment(int special){ insert(new UInt(special));}void CommentList::appendPostComment(int special){ insert(new UInt(special+0x10000000));}const char *CommentList::getName(uint i){ Object *d = get(findByIdx(i));// return d ? ((d->getObjectID()==OBJID_UINT) ? comment_lookup(((UInt*)d)->value): return d ? ((String*)d)->contentChar() : NULL;}/* * */void Analyser::init(){ active = false; dirty = false; next_address_is_invalid = false; addr = new InvalidAddress(); invalid_addr = new InvalidAddress(); addr_queue = new Queue(true); locations = NULL; symbols = NULL; symbol_count = location_count = 0; cur_addr_ops = cur_label_ops = 1; setLocationTreeOptimizeThreshold(1000); setSymbolTreeOptimizeThreshold(1000); cur_func = NULL; ops_parsed = 0; next_explored = new InvalidAddress(); first_explored = new InvalidAddress(); last_explored = new InvalidAddress(); explored = new Area(); explored->init(); initialized = new Area(); initialized->init(); initCodeAnalyser(); initDataAnalyser(); disasm = NULL; analy_disasm = NULL; max_opcode_length = 1; initUnasm(); mode = ANALY_TRANSLATE_SYMBOLS;}static void loadlocations(ObjectStream &st, Location *&loc, int l, int r){ if (l > r) { loc = NULL; return; } int m = (l+r)/2; loc = new Location; loadlocations(st, loc->left, l, m-1); loc->addr = GETX_OBJECT(st , "addr"); // xrefs loc->xrefs = GETX_OBJECT(st, "xrefs"); // comments loc->comments = GETX_OBJECT(st, "comments"); analyser_get_addrtype(st, &loc->type); // must be resolved later (thisfunc is of type Location not Address) Address *a = GETX_OBJECT(st, "func"); loc->thisfunc = (Location *)a; loc->flags = GETX_INT(st, 1, "flags"); loc->label = NULL; loadlocations(st, loc->right, m+1, r);}static void loadsymbols(Analyser *analy, ObjectStream &st, Symbol *&symbol, int l, int r){ if (l > r) { symbol = NULL; return; } int m = (l+r)/2; symbol = new Symbol; loadsymbols(analy, st, symbol->left, l, m-1); Address *a = GETX_OBJECT(st, "addr"); (symbol->location = analy->newLocation(a))->label = symbol; delete a; symbol->name = st.getString("name"); symbol->type = (labeltype)GETX_INT(st, 1, "type"); loadsymbols(analy, st, symbol->right, m+1, r);}static void resolveaddrs(Analyser *a, Location *loc){ if (loc) { resolveaddrs(a, loc->left); Address *tmp = (Address*)loc->thisfunc; if (tmp->isValid()) { loc->thisfunc = a->getLocationByAddress(tmp); } else { loc->thisfunc = NULL; } delete tmp; resolveaddrs(a, loc->right); }}/* * */void Analyser::load(ObjectStream &st){ cur_addr_ops = 0; cur_label_ops = 0; GET_OBJECT(st, addr); invalid_addr = new InvalidAddress(); GET_OBJECT(st, addr_queue); GET_INT32D(st, ops_parsed); GET_BOOL(st, active); if (active) { some_analyser_active++; } next_address_is_invalid = false; GET_OBJECT(st, next_explored); GET_OBJECT(st, first_explored); GET_OBJECT(st, last_explored); GET_INT32X(st, mode); GET_OBJECT(st, explored); GET_OBJECT(st, initialized); cur_addr_ops = cur_label_ops = 1; setLocationTreeOptimizeThreshold(1000); setSymbolTreeOptimizeThreshold(1000); GET_INT32D(st, location_count); loadlocations(st, locations, 0, location_count-1); resolveaddrs(this, locations); GET_INT32D(st, symbol_count); loadsymbols(this, st, symbols, 0, symbol_count-1); GET_OBJECT(st, analy_disasm); GET_OBJECT(st, disasm); if (analy_disasm) { analy_disasm->analy = this; analy_disasm->disasm = disasm; } GET_OBJECT(st, code); GET_OBJECT(st, data); if (data) { data->analy = this; } GET_INT32D(st, location_threshold); GET_INT32D(st, symbol_threshold); GET_INT32D(st, max_opcode_length); Address *curfuncaddr = GETX_OBJECT(st, "cur_func"); if (curfuncaddr) { cur_func = newLocation(curfuncaddr); delete curfuncaddr; } else { cur_func = NULL; } dirty = false;}/* * */void Analyser::done(){ setActive(false); freeLocations(locations); freeSymbols(symbols); delete addr_queue; if (explored) { explored->done(); delete explored; } if (initialized) { initialized->done(); delete initialized; } if (code) { code->done(); delete code; } if (data) { data->done(); delete data; } if (disasm) { disasm->done(); delete disasm; } if (analy_disasm) { analy_disasm->done(); delete analy_disasm; } delete addr; delete invalid_addr; delete next_explored; delete first_explored; delete last_explored;}/* * addAddressSymbol will never overwrite an existing label (like addlabel) */bool Analyser::addAddressSymbol(Address *address, const char *prefix, labeltype type, Location *infunc){ if (!validAddress(address, scvalid)) return false; char symbol[1024]; global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT; ht_snprintf(symbol, sizeof symbol, "%s_%y", prefix, address); if (addSymbol(address, symbol, type, infunc)) { return true; } else { return false; }}/* * */void Analyser::addComment(Address *Addr, int line, const char *c){ // line 0 meens append (at the moment assume append every time ;-))// if (!validaddr(Addr, scvalid)) return; Location *a = newLocation(Addr); CommentList *com = a->comments; if (!com) { com = new CommentList(); com->init(); a->comments = com;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -