📄 analy.cc
字号:
} com->appendPreComment(c); DPRINTF("#(%y) comment `%s'\n", Addr, c);}/* * addlabel: create label if there isnt one * fail if label exist on another address * */bool Analyser::addSymbol(Address *Addr, const char *label, labeltype type, Location *infunc){ if (!validAddress(Addr, scvalid)) return false; Location *a = newLocation(Addr); if (!a->label) { Symbol *l = newSymbol(label, a, type, infunc); if (l->location->addr->compareTo(Addr) != 0) { // this label already exists at a different address return false; } a->label = l; if (a->type.type == dt_unknown || a->type.type == dt_unknown_data) { if (type == label_func && !validCodeAddress(Addr)) { type = label_unknown; } switch (type) { case label_unknown: break; case label_func: data->setCodeAddressType(a, dst_function); break; case label_loc: data->setCodeAddressType(a, dst_location); break; case label_data: data->setAddressType(a, dt_unknown_data, 0, 0); break; } } return true; } else { // adress already has a label return false; }}/* * */bool Analyser::addXRef(Address *from, Address *to, xref_enum_t action){ if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return false; Location *a = newLocation(from); Container *x = a->xrefs; if (x) { AddrXRef tmp(to); if (x->find(&tmp)) return false; } else { x = new AVLTree(true); a->xrefs = x; } x->insert(new AddrXRef(to, action)); DPRINTF("xref %y->%y\n", from, to); return true;}/* * */void Analyser::assignComment(Address *Addr, int line, const char *c){ /* not really implemented */ addComment(Addr, line, c);}/* * */bool Analyser::assignSymbol(Address *Addr, const char *label, labeltype type, Location *infunc){ if (!validAddress(Addr, scvalid)) return false; Location *a = newLocation(Addr); Symbol *l = newSymbol(label, a, type, infunc); if (l->location->addr->compareTo(Addr) != 0) { // label already exists at a different address return false; } if (l->location->type.type == dt_unknown) { if (type == label_func && !validCodeAddress(Addr)) { type = label_unknown; } switch (type) { case label_unknown: break; case label_func: data->setCodeAddressType(a, dst_function); break; case label_loc: data->setCodeAddressType(a, dst_location); break; case label_data: data->setAddressType(a, dt_unknown_data, 0, 0); break; } } if (a->label) { // overwrite if (a->label != l) { // label has to be renamed disableSymbol(a->label); a->label = l; } } else { a->label = l; } return true;}/* * */void Analyser::assignXRef(Address *from, Address *to, xref_enum_t action){ if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return; Location *a = newLocation(from); Container *x = a->xrefs; if (x) { AddrXRef *xref; AddrXRef tmp(to); if ((xref = (AddrXRef*)x->get(x->find(&tmp)))) { // update xref xref->type = action; DPRINTF("xref %y->%y updated\n", from, to); return; } } else { x = new AVLTree(true); a->xrefs = x; } x->insert(new AddrXRef(to, action)); DPRINTF("xref %y->%y\n", from, to);}/* * */void Analyser::beginAnalysis(){ if (queryConfig(Q_DO_ANALYSIS)) { DPRINTF("################################\nAnalysis started.\n"); if (analy_disasm && disasm) { ops_parsed = 0; if (gotoAddress(invalid_addr, invalid_addr)) setActive(true); } else { DPRINTF("Analysis can't be started. No disassembler available."); } }}/* * */bool Analyser::continueAnalysis(){ byte buf[32]; OPCODE *instr; int len; branch_enum_t branch; assert((uint)max_opcode_length <= sizeof buf); if (!active) return false; do { int diff;// char tbuf[100];// char tbuf2[100];// addr->stringify(tbuf, 100, 0);/* if (strcmp(tbuf, "200970ec") == 0) { int as=0; }*/// printf("*** %s ***\n", tbuf); if ((addr->difference(diff, next_explored) && (diff >= 0)) || !validCodeAddress(addr)) { if (!gotoAddress(addr, invalid_addr)) { finish(); return false; } } int bz = bufPtr(addr, buf, max_opcode_length); instr = disasm->decode(buf, bz, mapAddr(addr)); instr = disasm->duplicateInsn(instr); ops_parsed++; num_ops_parsed++; len = disasm->getSize(instr); last_explored->add(len); do { DPRINTF("opcode @%y [func: %y]: %s\n", addr, (cur_func) ? cur_func->addr : invalid_addr, disasm->str(instr, 0)); if (disasm->validInsn(instr)) { branch = analy_disasm->isBranch(instr); if (branch != br_nobranch) { doBranch(branch, instr, len); } else { analy_disasm->examineOpcode(instr); } } else { DPRINTF("invalid opcode @%y\n", addr);// log("invalid opcode at address %y\n", addr); if (!addr->add(len)) { delete addr; addr = new InvalidAddress(); } else { newLocation(addr)->flags |= AF_FUNCTION_END; next_address_is_invalid = true; } } } while (disasm->selectNext(instr)); if (next_address_is_invalid || !addr->add(len)) { gotoAddress(invalid_addr, invalid_addr); next_address_is_invalid = false; } free(instr); } while ((ops_parsed % MAX_OPS_PER_CONTINUE) !=0); return true;}/* * */void Analyser::continueAnalysisAt(Address *Addr){ if (!validAddress(Addr, sccode)) return; if (queryConfig(Q_DO_ANALYSIS)) { DPRINTF("continueing analysis at %y\n", Addr); if (active || disasm) { data->setCodeAddressType(Addr, dst_function); pushAddress(Addr, Addr); } if (!active) { if (disasm) { Analyser::beginAnalysis(); } else { DPRINTF("couldn't start analysis: no disasm available\n"); } } }}/* * should return a new instance of an apropriate assembler */Assembler *Analyser::createAssembler(){ return NULL;}/* * */void Analyser::dataAccess(Address *Addr, taccess access){ if (!validAddress(Addr, scvalid)) { char msg[100]; global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS; ht_snprintf(msg, sizeof msg, "access of invalid addr %y at addr %y", Addr, addr); log(msg); return; } DPRINTF("dataaccess of %y\n", Addr); // string test byte buffer[1024]; if (validAddress(Addr, scinitialized)) { uint bz = bufPtr(Addr, buffer, sizeof buffer); if (bz > 2) { analy_string *str = string_test(buffer, bz); if (str) { char string1[128], string2[128]; str->render_string(string2, sizeof string2); ht_snprintf(string1, sizeof string1, "%s_%s", str->name(), string2); make_valid_name(string2, string1); if (addAddressSymbol(Addr, string2, label_data)) { addComment(Addr, 0, ""); } data->setArrayAddressType(Addr, dst_string, str->length()); str->done(); delete str; return; } } } if (validCodeAddress(Addr) && access.type == acoffset) { if (addAddressSymbol(Addr, LPRFX_OFS, label_func)) { addComment(Addr, 0, ""); } Location *a = getLocationByAddress(Addr); assert(a); // test if Addr points to code if ((a->type.type == dt_unknown) || (a->type.type == dt_code)) { // test if Addr points to valid code (test not yet complete) byte buf[16]; int bz = bufPtr(Addr, buf, sizeof(buf)); OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(Addr)); if (disasm->validInsn(instr)) { data->setCodeAddressType(Addr, dst_cunknown); pushAddress(Addr, Addr); } } } else { if (access.type != acoffset) { switch (access.size) { case 1: data->setIntAddressType(Addr, dst_ibyte, 1); break; case 2: data->setIntAddressType(Addr, dst_iword, 2); break; case 4: data->setIntAddressType(Addr, dst_idword, 4); break; } } if (validAddress(Addr, scinitialized)) { addAddressSymbol(Addr, LPRFX_DTA, label_data); } else { addAddressSymbol(Addr, LPRFX_DTU, label_data); } }}/* * disables address, frees misc */void Analyser::deleteLocation(Address *Addr){ Location *a = getLocationByAddress(Addr); if (a) { disableSymbol(a->label); a->label = NULL; a->flags |= AF_DELETED; location_count--; }}/* * disables label of an address and unassigns address' label */void Analyser::deleteSymbol(Address *Addr){ Location *a = getLocationByAddress(Addr); if (a) { disableSymbol(a->label); a->label = NULL; symbol_count--; }}/* * */bool Analyser::deleteXRef(Address *from, Address *to){ if (!validAddress(from, scvalid) || !validAddress(to, scvalid)) return false; Location *a = getLocationByAddress(from); if (!a) return false; Container *x = a->xrefs; if (!x) return false; DPRINTF("deleted xref %y->%y\n", from, to); AddrXRef tmp(to); return x->delObj(&tmp);}/* * an disabled label will be overwritten as soon as possible, * and never be returned nor saved. * performed this way to preserve the labeltrees structure * */void Analyser::disableSymbol(Symbol *label){ if (label) { label->location = NULL; }}/* * */void Analyser::doBranch(branch_enum_t branch, OPCODE *opcode, int len){ Address *branch_addr = analy_disasm->branchAddr(opcode, branch, true); if (branch != br_return) { if (!validCodeAddress(branch_addr)) { char msg[100]; global_analyser_address_string_format = ADDRESS_STRING_FORMAT_LEADING_ZEROS; ht_snprintf(msg, sizeof msg, "branch to invalid addr %y from addr %y", branch_addr, addr); log(msg); } }/* if (branch != brcall) { taddr *a = new_addr(addr+len); if (!a->comments) { add_comment(a->addr, 0, ""); } }*/ Address *next_addr = addr->clone(); if (!next_addr->add(len)) { delete next_addr; next_addr = new InvalidAddress(); } switch (branch) { case br_jump: if (next_addr->isValid()) newLocation(next_addr)->flags |= AF_FUNCTION_END; addXRef(branch_addr, addr, xrefjump); if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) { addComment(branch_addr, 0, ""); }// gotoAddress(branch_addr, invalid_addr); pushAddress(branch_addr, invalid_addr); next_address_is_invalid = true; break; case br_return: if (next_addr->isValid()) newLocation(next_addr)->flags |= AF_FUNCTION_END; next_address_is_invalid = true; break; case br_call: { addXRef(branch_addr, addr, xrefcall); bool special_func = false; const char *lprfx = LPRFX_SUB; if (!getSymbolByAddress(branch_addr) && validCodeAddress(branch_addr)) { // should be in code_analy byte buf[16]; int bz = bufPtr(branch_addr, buf, sizeof(buf)); OPCODE *instr = disasm->decode(buf, MIN(bz, max_opcode_length), mapAddr(branch_addr)); branch_enum_t bt = analy_disasm->isBranch(instr); if (bt == br_return) { lprfx = LPRFX_STUB; } else if (bt == br_jump) { char buf[1024], label[1024]; Address *wrap_addr = analy_disasm->branchAddr(instr, bt, false); if (validAddress(wrap_addr, scvalid)) { Symbol *l = getSymbolByAddress(wrap_addr); addComment(branch_addr, 0, ""); addComment(branch_addr, 0, ";----------------------------------------------"); global_analyser_address_string_format = ADDRESS_STRING_FORMAT_COMPACT; if (l && l->name) { ht_snprintf(buf, sizeof buf, "%s %s", "; W R A P P E R for", l->name); ht_snprintf(label, sizeof label, "%s_%s_%y", LPRFX_WRAP, l->name, branch_addr); } else { ht_snprintf(buf, sizeof buf, "%s %s %y", "; W R A P P E R for", "address", wrap_addr); ht_snprintf(label, sizeof label, "%s_%y_%y", LPRFX_WRAP, wrap_addr, branch_addr); } addComment(branch_addr, 0, buf); addComment(branch_addr, 0, ";----------------------------------------------"); addSymbol(branch_addr, label, label_func); special_func = true; } delete wrap_addr; } } if (!special_func && addAddressSymbol(branch_addr, lprfx, label_func)) { addComment(branch_addr, 0, ""); addComment(branch_addr, 0, ";-----------------------"); addComment(branch_addr, 0, "; S U B R O U T I N E"); addComment(branch_addr, 0, ";-----------------------"); if (branch_addr->compareTo(cur_func->addr) == 0) { addComment(branch_addr, 0, "; (recursive)"); } }// pushAddress(next_addr, cur_func->addr);// gotoAddress(branch_addr, branch_addr); pushAddress(branch_addr, branch_addr); break; } case br_jXX: addXRef(branch_addr, addr, xrefjump); if (addAddressSymbol(branch_addr, LPRFX_LOC, label_loc, cur_func)) { addComment(branch_addr, 0, ""); }// pushAddress(next_addr, cur_func->addr);// gotoAddress(branch_addr, invalid_addr); pushAddress(branch_addr, invalid_addr); break; default:{} // stupid but neccessary } delete next_addr; delete branch_addr;}/* * */void Analyser::engageCodeanalyser(){ if (queryConfig(Q_ENGAGE_CODE_ANALYSER)) { DPRINTF("starting code analyser.\n"); }}static void analyserenum_addrs(Location *locs, Address *at, Location *&loc){ if ((at->compareTo(locs->addr) < 0) || !at->isValid()) { loc = locs; if (locs->left) analyserenum_addrs(locs->left, at, loc); } else /*if (at >= locs->addr)*/ { if (locs->right) analyserenum_addrs(locs->right, at, loc); }}/* * */Location *Analyser::enumLocations(Address *Addr){ Location *result = NULL; if (locations) analyserenum_addrs(locations, Addr, result); while (result && (result->flags & AF_DELETED)) { Address *a = result->addr; result = NULL; analyserenum_addrs(locations, a, result); } return result;}static void analyserenum_addrs_back(Location *locs, Address *at, Location *&loc){ if (at->compareTo(locs->addr) <= 0) { if (locs->left) analyserenum_addrs_back(locs->left, at, loc); } else /*if (at > locs->addr)*/ { loc = locs; if (locs->right) analyserenum_addrs_back(locs->right, at, loc); }}/* * */Location *Analyser::enumLocationsReverse(Address *Addr){ Location *result = NULL; if (locations) analyserenum_addrs_back(locations, Addr, result); while ((result) && (result->flags & AF_DELETED)) { Address *a = result->addr; result = NULL; analyserenum_addrs_back(locations, a, result); } return result;}static void analyserenum_labels(Symbol *labels, const char *at, Symbol *&label){ int i = strcmp(at, labels->name); if (i < 0) { label = labels; if (labels->left) analyserenum_labels(labels->left, at, label); } else /*if (i >= 0)*/ { if (labels->right) analyserenum_labels(labels->right, at, label); }}/* * returns the (alphanumerically) next label to "at" * or the first if "at" is NULL * returns NULL if there is no preceding label * */Symbol *Analyser::enumSymbolsByName(const char *at){ Symbol *result = NULL; if (!at) at=""; if (symbols) analyserenum_labels(symbols, at, result); // label with !addr mustnt be returned while ((result) && (!result->location)) { char *name = result->name; result = NULL; analyserenum_labels(symbols, name, result); } return result;}static void analyserenum_labels_back(Symbol *labels, const char *at, Symbol *&label){ int i = strcmp(at, labels->name); if (i <= 0) { if (labels->left) analyserenum_labels_back(labels->left, at, label); } else /*if (i >= 0)*/ { label = labels; if (labels->right) analyserenum_labels_back(labels->right, at, label); }}/* * */Symbol *Analyser::enumSymbolsByNameReverse(const char *at){ Symbol *result = NULL; // FIXME: if (!at) at="\xff\xff\xff"; if (symbols) analyserenum_labels_back(symbols, at, result); // labels with !addr mustnt be returned while ((result) && (!result->location)) { char *name = result->name; result = NULL; analyserenum_labels_back(symbols, name, result); } return result;}Symbol *Analyser::enumSymbols(Symbol *sym){ if (sym) { return enumSymbolsByName(sym->name); } else { return enumSymbolsByName(NULL); }}Symbol *Analyser::enumSymbolsReverse(Symbol *sym){ if (sym) { return enumSymbolsByNameReverse(sym->name); } else { return enumSymbolsByNameReverse(NULL); }}/* * */taddr_typetype Analyser::examineData(Address *Addr){ if ((validReadAddress(Addr)) && (validAddress(Addr, scinitialized))) { DPRINTF("examinating data @%y:\n", Addr); } else return dt_unknown; return dt_unknown;}/* * */static Location *analyserfindaddr(Location *locs, Address *Addr){ if (locs) { if (Addr->compareTo(locs->addr) < 0) return analyserfindaddr(locs->left, Addr); if (Addr->compareTo(locs->addr) > 0) return analyserfindaddr(locs->right, Addr); return (locs->flags & AF_DELETED) ? NULL : locs; } return NULL;}/* * */Location *Analyser::getLocationByAddress(Address *Addr){ return analyserfindaddr(locations, Addr);}/* * finds the address Addr belongs to (if address has size > 1) */Location *Analyser::getLocationContextByAddress(Address *Addr){ Location *res = enumLocationsReverse(Addr); if (res && res->type.type != dt_unknown) { Address *resaddr = res->addr->clone(); resaddr->add(res->type.length); if (resaddr->compareTo(Addr) > 0) { delete resaddr; return res; } delete resaddr; } return NULL;}/* * finds the function the Addr belongs to (if possible/applicable). */Location *Analyser::getFunctionByAddress(Address *Addr){ Location *loc = getLocationByAddress(Addr); if (!loc) loc = enumLocationsReverse(Addr); while (loc && !(loc->flags & AF_FUNCTION_SET)) { if (loc->flags & AF_FUNCTION_END) return NULL; loc = enumLocationsReverse(loc->addr); } return loc ? loc->thisfunc : NULL;}/* * searches back to the last location */Location *Analyser::getPreviousSymbolByAddress(Address *Addr){ Location *loc = getLocationByAddress(Addr); if (!loc) loc = enumLocationsReverse(Addr); while (loc && !loc->label) { if (loc->flags & AF_FUNCTION_END) return NULL; loc = enumLocationsReverse(loc->addr); } return loc ? loc : NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -