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

analy_x86.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      analy_x86.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 
00023 #include "analy_register.h"
00024 #include "analy_x86.h"
00025 #include "htdebug.h"
00026 #include "snprintf.h"
00027 #include "x86dis.h"
00028 
00029 AddressX86Flat32::AddressX86Flat32()
00030 {
00031 }
00032 
00033 AddressX86Flat32::AddressX86Flat32(dword Addr)
00034 {
00035         addr = Addr;
00036 }
00037 
00038 bool AddressX86Flat32::add(int offset)
00039 {
00040         // check for overflow
00041         if ((int)offset < 0) {
00042                 if (addr+offset > addr) return false;
00043         } else {
00044                 if (addr+offset < addr) return false;
00045         }
00046         addr+=offset;
00047         return true;
00048 }
00049 
00050 int AddressX86Flat32::byteSize()
00051 {
00052         return 4;
00053 }
00054 
00055 int AddressX86Flat32::compareTo(const Object *obj) const
00056 {
00057 /*      if (object_id() != to->object_id()) {
00058                 int as=1;
00059         }*/
00060         assert(object_id() == obj->object_id());
00061         if (addr > ((AddressX86Flat32 *)obj)->addr) return 1;
00062         if (addr < ((AddressX86Flat32 *)obj)->addr) return -1;
00063         return 0;
00064 }
00065 
00066 int AddressX86Flat32::compareDelinear(Address *to)
00067 {
00068         assert(object_id() == to->object_id());
00069         dword da = delinearize(addr);
00070         dword db = delinearize(((AddressFlat32 *)to)->addr);
00071         if (da > db) return 1;
00072         if (da < db) return -1;
00073         return 0;
00074 }
00075 
00076 bool AddressX86Flat32::difference(int &result, Address *to)
00077 {
00078         if (object_id() == to->object_id()) {
00079                 result = addr-((AddressX86Flat32 *)to)->addr;
00080                 return true;
00081         } else {
00082                 return false;
00083         }
00084 }
00085 
00086 Object *AddressX86Flat32::duplicate()
00087 {
00088         return new AddressX86Flat32(addr);
00089 }
00090 
00091 void AddressX86Flat32::getFromArray(const byte *array)
00092 {
00093         UNALIGNED_MOVE(addr, *(dword*)array);
00094 }
00095 
00096 void AddressX86Flat32::getFromCPUAddress(CPU_ADDR *ca)
00097 {
00098         addr = ca->addr32.offset;
00099 }
00100 
00101 int AddressX86Flat32::load(ht_object_stream *s)
00102 {
00103         addr = s->getIntHex(4, NULL);
00104         return s->get_error();
00105 }
00106 
00107 OBJECT_ID AddressX86Flat32::object_id() const
00108 {
00109         return ATOM_ADDRESS_X86_FLAT_32;
00110 }
00111 
00112 int AddressX86Flat32::parseString(const char *s, int length, Analyser *a)
00113 {
00114         return 0;
00115 }
00116 
00117 void AddressX86Flat32::putIntoArray(byte *array)
00118 {
00119         UNALIGNED_MOVE(*(dword*)array, addr);
00120 }
00121 
00122 void AddressX86Flat32::putIntoCPUAddress(CPU_ADDR *ca)
00123 {
00124         ca->addr32.offset = addr;
00125 }
00126 
00127 void AddressX86Flat32::store(ht_object_stream *s)
00128 {
00129         s->putIntHex(addr, 4, NULL);
00130 }
00131 
00132 int AddressX86Flat32::stringify(char *s, int max_length, int format)
00133 {
00134         char *formats[] = {
00135                 "%s%x%s",
00136                 "%s%8x%s",
00137                 "%s%08x%s",
00138                 "",
00139                 "%s%X%s",
00140                 "%s%8X%s",
00141                 "%s%08X%s",
00142                 "",
00143         };
00144         return ht_snprintf(s, max_length, formats[format&7], (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00145 }
00146 
00147 int AddressX86Flat32::stringSize()
00148 {
00149         return 8;
00150 }
00151 
00152 
00153 AddressX86_1632::AddressX86_1632()
00154 {
00155 }
00156 
00157 AddressX86_1632::AddressX86_1632(word Seg, dword Addr)
00158 {
00159         seg = Seg;
00160         addr = Addr;
00161 }
00162 
00163 bool AddressX86_1632::add(int offset)
00164 {
00165         // check for overflow
00166         if ((int)offset < 0) {
00167                 if (addr+offset > addr) return false;
00168         } else {
00169                 if (addr+offset < addr) return false;
00170         }
00171         addr+=offset;
00172         return true;
00173 }
00174 
00175 int AddressX86_1632::byteSize()
00176 {
00177         return 6;
00178 }
00179 
00180 int AddressX86_1632::compareTo(const Object *obj) const
00181 {
00182         assert(object_id() == obj->object_id());
00183         if (seg > ((AddressX86_1632 *)obj)->seg) return 1;
00184         if (seg < ((AddressX86_1632 *)obj)->seg) return -1;
00185         if (addr > ((AddressX86_1632 *)obj)->addr) return 1;
00186         if (addr < ((AddressX86_1632 *)obj)->addr) return -1;
00187         return 0;
00188 }
00189 
00190 int AddressX86_1632::compareDelinear(Address *to)
00191 {
00192         assert(object_id() == to->object_id());
00193         dword s1 = delinearize(seg);
00194         dword s2 = delinearize(((AddressX86_1632 *)to)->seg);
00195         if (s1 > s2) return 1;
00196         if (s1 < s2) return -1;
00197         dword a1 = delinearize(addr);
00198         dword a2 = delinearize(((AddressX86_1632 *)to)->addr);
00199         if (a1 > a2) return 1;
00200         if (a1 < a2) return -1;
00201         return 0;
00202 }
00203 
00204 bool AddressX86_1632::difference(int &result, Address *to)
00205 {
00206         if ((object_id() == to->object_id()) && (seg == ((AddressX86_1632 *)to)->seg)) {
00207                 result = addr-((AddressX86_1632 *)to)->addr;
00208                 return true;
00209         } else {
00210                 return false;
00211         }
00212 }
00213 
00214 Object *AddressX86_1632::duplicate()
00215 {
00216         return new AddressX86_1632(seg, addr);
00217 }
00218 
00219 void AddressX86_1632::getFromArray(const byte *array)
00220 {
00221         UNALIGNED_MOVE(addr, *(dword*)array);
00222         UNALIGNED_MOVE(seg, *(word*)(array+sizeof addr));
00223 }
00224 
00225 void AddressX86_1632::getFromCPUAddress(CPU_ADDR *ca)
00226 {
00227         seg = ca->addr32.seg;
00228         addr = ca->addr32.offset;
00229 }
00230 
00231 int AddressX86_1632::load(ht_object_stream *s)
00232 {
00233         seg = s->getIntHex(2, NULL);
00234         addr = s->getIntHex(4, NULL);
00235         return s->get_error();
00236 }
00237 
00238 OBJECT_ID AddressX86_1632::object_id() const
00239 {
00240         return ATOM_ADDRESS_X86_1632;
00241 }
00242 
00243 int AddressX86_1632::parseString(const char *s, int length, Analyser *a)
00244 {
00245         return 0;
00246 }
00247 
00248 void AddressX86_1632::putIntoArray(byte *array)
00249 {
00250         UNALIGNED_MOVE(*(dword*)array, addr);
00251         UNALIGNED_MOVE(*(word*)(array+sizeof addr), seg);
00252 }
00253 
00254 void AddressX86_1632::putIntoCPUAddress(CPU_ADDR *ca)
00255 {
00256         ca->addr32.seg = seg;
00257         ca->addr32.offset = addr;
00258 }
00259 
00260 void AddressX86_1632::store(ht_object_stream *s)
00261 {
00262         s->putIntHex(seg, 2, NULL);
00263         s->putIntHex(addr, 4, NULL);
00264 }
00265 
00266 int AddressX86_1632::stringify(char *s, int max_length, int format)
00267 {
00268         char *formats[] = {
00269                 "%s%x%s:%s%x%s",
00270                 "%s%4x%s:%s%08x%s",
00271                 "%s%04x%s:%s%08x%s",
00272                 "",
00273                 "%s%X%s:%s%X%s",
00274                 "%s%4X%s:%s%08X%s",
00275                 "%s%04X%s:%s%08X%s",
00276                 "",
00277         };
00278         return ht_snprintf(s, max_length, formats[format&7],
00279         (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", seg, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"",
00280         (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00281 }
00282 
00283 int AddressX86_1632::stringSize()
00284 {
00285         return 14;
00286 }
00287 
00288 /*
00289  *
00290  */
00291 AddressX86_1616::AddressX86_1616()
00292 {
00293 }
00294 
00295 AddressX86_1616::AddressX86_1616(word Seg, word Addr)
00296 {
00297         seg = Seg;
00298         addr = Addr;
00299 }
00300 
00301 bool AddressX86_1616::add(int offset)
00302 {
00303         // check for overflow
00304         if ((int)offset < 0) {
00305                 if (addr+offset > addr) return false;
00306         } else {
00307                 if (addr+offset < addr) return false;
00308         }
00309         addr+=offset;
00310         return true;
00311 }
00312 
00313 int AddressX86_1616::byteSize()
00314 {
00315         return 4;
00316 }
00317 
00318 int AddressX86_1616::compareTo(const Object *obj) const
00319 {
00320         assert(object_id() == obj->object_id());
00321         if (seg > ((AddressX86_1616 *)obj)->seg) return 1;
00322         if (seg < ((AddressX86_1616 *)obj)->seg) return -1;
00323         if (addr > ((AddressX86_1616 *)obj)->addr) return 1;
00324         if (addr < ((AddressX86_1616 *)obj)->addr) return -1;
00325         return 0;
00326 }
00327 
00328 int AddressX86_1616::compareDelinear(Address *to)
00329 {
00330         assert(object_id() == to->object_id());
00331         dword s1 = delinearize(seg);
00332         dword s2 = delinearize(((AddressX86_1616 *)to)->seg);
00333         if (s1 > s2) return 1;
00334         if (s1 < s2) return -1;
00335         dword a1 = delinearize(addr);
00336         dword a2 = delinearize(((AddressX86_1616 *)to)->addr);
00337         if (a1 > a2) return 1;
00338         if (a1 < a2) return -1;
00339         return 0;
00340 }
00341 
00342 bool AddressX86_1616::difference(int &result, Address *to)
00343 {
00344         if ((object_id() == to->object_id()) && (seg == ((AddressX86_1616 *)to)->seg)) {
00345                 result = (int)addr-(int)((AddressX86_1616 *)to)->addr;
00346                 return true;
00347         } else {
00348                 return false;
00349         }
00350 }
00351 
00352 Object *AddressX86_1616::duplicate()
00353 {
00354         return new AddressX86_1616(seg, addr);
00355 }
00356 
00357 void AddressX86_1616::getFromArray(const byte *array)
00358 {
00359         UNALIGNED_MOVE(addr, *(word*)array);
00360         UNALIGNED_MOVE(seg, *(word*)(array+sizeof addr));
00361 }
00362 
00363 void AddressX86_1616::getFromCPUAddress(CPU_ADDR *ca)
00364 {
00365         seg = ca->addr32.seg;
00366         addr = ca->addr32.offset;
00367 }
00368 
00369 int AddressX86_1616::load(ht_object_stream *s)
00370 {
00371         seg = s->getIntHex(2, NULL);
00372         addr = s->getIntHex(2, NULL);
00373         return s->get_error();
00374 }
00375 
00376 OBJECT_ID AddressX86_1616::object_id() const
00377 {
00378         return ATOM_ADDRESS_X86_1616;
00379 }
00380 
00381 int AddressX86_1616::parseString(const char *s, int length, Analyser *a)
00382 {
00383         return 0;
00384 }
00385 
00386 void AddressX86_1616::putIntoArray(byte *array)
00387 {
00388         UNALIGNED_MOVE(*(word*)array, addr);
00389         UNALIGNED_MOVE(*(word*)(array+sizeof seg), seg);
00390 }
00391 
00392 void AddressX86_1616::putIntoCPUAddress(CPU_ADDR *ca)
00393 {
00394         ca->addr32.seg = seg;
00395         ca->addr32.offset = addr;
00396 }
00397 
00398 void AddressX86_1616::store(ht_object_stream *s)
00399 {
00400         s->putIntHex(seg, 2, NULL);
00401         s->putIntHex(addr, 2, NULL);
00402 }
00403 
00404 int AddressX86_1616::stringify(char *s, int max_length, int format)
00405 {
00406         char *formats[] = {
00407                 "%s%x%s:%s%04x%s",
00408                 "%s%4x%s:%s%04x%s",
00409                 "%s%04x%s:%s%04x%s",
00410                 "",
00411                 "%s%X%s:%s%04X%s",
00412                 "%s%4X%s:%s%04X%s",
00413                 "%s%04X%s:%s%04X%s",
00414                 "",
00415         };
00416         return ht_snprintf(s, max_length, formats[format&7],
00417         (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", seg, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"",
00418         (format & ADDRESS_STRING_FORMAT_ADD_0X) ? "0x":"", addr, (format & ADDRESS_STRING_FORMAT_ADD_H) ? "h":"");
00419 }
00420 
00421 int AddressX86_1616::stringSize()
00422 {
00423         return 9;
00424 }
00425 
00426 /*
00427  *
00428  */
00429 void AnalyX86Disassembler::init(Analyser *A, int f)
00430 {
00431         flags = f;
00432         createUnasm();
00433         AnalyDisassembler::init(A);
00434 }
00435 
00436 /*
00437  *
00438  */
00439 int  AnalyX86Disassembler::load(ht_object_stream *f)
00440 {
00441         GET_INT_HEX(f, flags);
00442         return AnalyDisassembler::load(f);
00443 }
00444 
00445 /*
00446  *
00447  */
00448 void AnalyX86Disassembler::done()
00449 {
00450         AnalyDisassembler::done();
00451 }
00452 
00453 /*
00454  *
00455  */
00456 OBJECT_ID       AnalyX86Disassembler::object_id() const
00457 {
00458         return ATOM_ANALY_X86;
00459 }
00460 
00461 Address *AnalyX86Disassembler::createAddress(word segment, dword offset)
00462 {
00463         if (flags & ANALYX86DISASSEMBLER_FLAGS_FLAT64) {
00464                 return new AddressFlat64(to_qword(offset));
00465         } else if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00466                 if (offset <= 0xffff) {
00467                         return new AddressX86_1616(segment, offset);
00468                 } else {
00469                         // FIXME
00470 //                      return new AddressX86_1632(segment, offset);
00471                         return new AddressX86_1616(segment, offset);
00472                 }
00473         } else {
00474                 return new AddressX86Flat32(offset);
00475         }
00476 }
00477 
00478 void AnalyX86Disassembler::createUnasm()
00479 {
00480         if (flags & ANALYX86DISASSEMBLER_FLAGS_VXD_X86DIS) {
00481                 if (flags & ANALYX86DISASSEMBLER_FLAGS_16BIT) {
00482                         disasm = new x86dis_vxd(X86_OPSIZE16, X86_ADDRSIZE16);
00483                 } else {
00484                         disasm = new x86dis_vxd(X86_OPSIZE32, X86_ADDRSIZE32);
00485                 }
00486         } else {
00487                 if (flags & ANALYX86DISASSEMBLER_FLAGS_16BIT) {
00488                         disasm = new x86dis(X86_OPSIZE16, X86_ADDRSIZE16);
00489                 } else {
00490                         disasm = new x86dis(X86_OPSIZE32, X86_ADDRSIZE32);
00491                 }
00492         }
00493 }
00494 word AnalyX86Disassembler::getSegment(Address *addr)
00495 {
00496         if (addr->object_id() == ATOM_ADDRESS_X86_1616) {
00497                 return ((AddressX86_1616*)addr)->seg;
00498         } else if (addr->object_id() == ATOM_ADDRESS_X86_1632) {
00499                 return ((AddressX86_1632*)addr)->seg;
00500         } else {
00501                 assert(0);
00502                 return 0;
00503         }
00504 }
00505 
00506 /*
00507  *
00508  */
00509 Address *AnalyX86Disassembler::branchAddr(OPCODE *opcode, branch_enum_t branchtype, bool examine)
00510 {
00511         Address *addr;
00512         x86dis_insn *o = (x86dis_insn*)opcode;
00513         assert(o->op[1].type == X86_OPTYPE_EMPTY);
00514         switch (o->op[0].type) {
00515                 case X86_OPTYPE_IMM: {
00516 /*              if (o->op[0].imm == 0x1012c0f) {
00517                                 int as=0;
00518                         }*/
00519                         
00520                         word seg = 0;
00521                         if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00522                                 seg = getSegment(analy->addr);
00523                         }
00524                         addr = createAddress(seg, o->op[0].imm);
00525                         return addr;
00526                 }
00527                 case X86_OPTYPE_FARPTR:
00528                         if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00529                                 addr = createAddress(o->op[0].farptr.seg, o->op[0].farptr.offset);
00530                         } else {
00531                                 break;
00532                         }
00533                         return addr;
00534                 case X86_OPTYPE_MEM: {
00535                         taccess access;
00536                         addr = NULL;
00537                         if (o->op[0].mem.hasdisp) {
00538                                 addr = createAddress(0, o->op[0].mem.disp);
00539                                 access.type = acread;
00540                                 access.indexed = (o->op[0].mem.base != X86_REG_NO) || (o->op[0].mem.index != X86_REG_NO);
00541                                 access.size = o->op[0].size;
00542                         } else {
00543                                 break;
00544                         }
00545                         if (examine && analy->validAddress(addr, scvalid)) {
00546                                 analy->dataAccess(addr, access);
00547                                 xref_enum_t xref;
00548                                 switch (branchtype) {
00549                                         case br_jXX:
00550                                         case br_jump:
00551                                                 xref = xrefijump;
00552                                                 break;
00553                                         case br_call:
00554                                                 xref = xreficall;
00555                                                 break;
00556                                         default: {assert(0);}
00557                                 }
00558                                 analy->addXRef(addr, analy->addr, xref);
00559                         }
00560                         if (examine) {
00561                                 if (addr) delete addr;
00562                                 break;
00563                         } else {
00564                                 return addr;
00565                         }
00566                 }
00567         }
00568         return new InvalidAddress();
00569 }
00570 
00571 /*
00572  *
00573  */
00574 void    AnalyX86Disassembler::examineOpcode(OPCODE *opcode)
00575 {
00576         x86dis_insn *o = (x86dis_insn*)opcode;
00577         for (int i=0; i<3; i++) {
00578                 x86_insn_op *op = &o->op[i];
00579                 Address *addr = NULL;
00580                 taccess access;
00581                 xref_enum_t xref = xrefoffset;
00582                 switch (op->type) {
00583                         case X86_OPTYPE_IMM:
00584                                 access.type = acoffset;
00585                                 access.indexed = false;
00586                                 addr = createAddress(0, op->imm);
00587                                 break;
00588                         case X86_OPTYPE_FARPTR:
00589                                 if (flags & ANALYX86DISASSEMBLER_FLAGS_SEGMENTED) {
00590                                         addr = createAddress(op->farptr.seg, op->farptr.offset);
00591                                 }
00592                                 access.type = acoffset;
00593                                 access.indexed = false;
00594                                 break;
00595                         case X86_OPTYPE_MEM:
00596                                 if (op->mem.hasdisp) {
00597                                         addr = createAddress(0, op->mem.disp);
00598                                         access.type = acread;
00599                                         access.indexed = (op->mem.base != X86_REG_NO) || (op->mem.index != X86_REG_NO);
00600                                         access.size = op->size;
00601                                         if (strcmp(o->name, "cmp")==0 || strcmp(o->name, "test")==0 || strcmp(o->name, "push")==0) {
00602                                                 xref = xrefread;
00603                                         } else {
00604                                                 xref = (i==0) ? xrefwrite : xrefread;
00605                                         }
00606                                 }
00607                                 break;
00608                 }
00609                 if (addr) {
00610                         if (analy->validAddress(addr, scvalid)) {
00611                                 analy->dataAccess(addr, access);
00612                                 analy->addXRef(addr, analy->addr, xref);
00613                         }
00614                         delete addr;
00615                 }
00616         }
00617 }
00618 
00619 /*
00620  *
00621  */
00622 branch_enum_t AnalyX86Disassembler::isBranch(OPCODE *opcode)
00623 {
00624         x86dis_insn *o = (x86dis_insn*)opcode;
00625         char *opcode_str = o->name;
00626         if (opcode_str[0]=='j') {
00627                 if (opcode_str[1]=='m') return br_jump; else return br_jXX;
00628         } else if ((opcode_str[0]=='l') && (opcode_str[1]=='o')  && (opcode_str[2]=='o')) {
00629                 // loop opcode will be threated like a jXX
00630                 return br_jXX;
00631         } else if ((opcode_str[0]=='c') && (opcode_str[1]=='a')) {
00632                 return br_call;
00633         } else if ((opcode_str[0]=='r') && (opcode_str[1]=='e')) {
00634                 return br_return;
00635         } else return br_nobranch;
00636 }
00637 
00638 /*
00639  *
00640  */
00641 void AnalyX86Disassembler::store(ht_object_stream *f)
00642 {
00643         PUT_INT_HEX(f, flags);
00644         AnalyDisassembler::store(f);
00645 }
00646 
00647 

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