VirtualMachineSemantics.h

Go to the documentation of this file.
00001 #ifndef Rose_VirtualMachineSemantics_H
00002 #define Rose_VirtualMachineSemantics_H
00003 
00004 
00005 #ifndef __STDC_FORMAT_MACROS
00006 #define __STDC_FORMAT_MACROS
00007 #endif
00008 #include <inttypes.h>
00009 
00010 #include <map>
00011 #include <stdint.h>
00012 #include <vector>
00013 
00014 #include "rosePublicConfig.h"
00015 #ifdef ROSE_HAVE_GCRYPT_H
00016 #include <gcrypt.h>
00017 #endif
00018 
00019 #include "x86InstructionSemantics.h"
00020 #include "BaseSemantics.h"
00021 #include "MemoryMap.h"
00022 
00023 namespace BinaryAnalysis {                      // documented elsewhere
00024     namespace InstructionSemantics {            // documented elsewhere
00025 
00026 
00040         namespace VirtualMachineSemantics {
00041 
00042             extern uint64_t name_counter;
00043 
00044             typedef std::map<uint64_t, uint64_t> RenameMap;
00045 
00047             template<size_t nBits>
00048             struct ValueType {
00049                 uint64_t name;                      
00050                 uint64_t offset;                    
00052                 bool negate;                        
00056                 ValueType(): name(++name_counter), offset(0), negate(false) {}
00057 
00059                 template <size_t Len>
00060                 ValueType(const ValueType<Len> &other) {
00061                     name = other.name;
00062                     /*make sure high-order bits are zeroed out*/
00063                     offset = other.offset & IntegerOps::GenMask<uint64_t, nBits>::value;
00064                     negate = other.negate;
00065                 }
00066 
00068                 ValueType(uint64_t n)   /*implicit*/
00069                     : name(0), offset(n), negate(false) {
00070                     this->offset &= IntegerOps::GenMask<uint64_t, nBits>::value;
00071                 }
00072 
00074                 ValueType(uint64_t name, uint64_t offset, bool negate=false)
00075                     : name(name), offset(offset), negate(negate) {
00076                     this->offset &= IntegerOps::GenMask<uint64_t, nBits>::value;
00077                 }
00078 
00080                 bool is_known() const {
00081                     return 0==name;
00082                 }
00083 
00085                 uint64_t known_value() const {
00086                     ROSE_ASSERT(is_known());
00087                     return offset;
00088                 }
00089 
00094                 ValueType<nBits> rename(RenameMap *rmap=NULL) const;
00095 
00098                 void print(std::ostream &o, RenameMap *rmap=NULL) const {
00099                     uint64_t sign_bit = (uint64_t)1 << (nBits-1); /* e.g., 80000000 */
00100                     uint64_t val_mask = sign_bit - 1;             /* e.g., 7fffffff */
00101                     /*magnitude of negative value*/
00102                     uint64_t negative = nBits>1 && (offset & sign_bit) ? (~offset & val_mask) + 1 : 0;
00103 
00104                     if (name!=0) {
00105                         /* This is a named value rather than a constant. */
00106                         uint64_t renamed = name;
00107                         if (rmap) {
00108                             RenameMap::iterator found = rmap->find(name);
00109                             if (found==rmap->end()) {
00110                                 renamed = rmap->size()+1;
00111                                 rmap->insert(std::make_pair(name, renamed));
00112                             } else {
00113                                 renamed = found->second;
00114                             }
00115                         }
00116                         const char *sign = negate ? "-" : "";
00117                         o <<sign <<"v" <<std::dec <<renamed;
00118                         if (negative) {
00119                             o <<"-0x" <<std::hex <<negative;
00120                         } else if (offset) {
00121                             o <<"+0x" <<std::hex <<offset;
00122                         }
00123                     } else {
00124                         /* This is a constant */
00125                         ROSE_ASSERT(!negate);
00126                         o  <<"0x" <<std::hex <<offset;
00127                         if (negative)
00128                             o <<" (-0x" <<std::hex <<negative <<")";
00129                     }
00130                 }
00131                 void print(std::ostream &o, BaseSemantics::SEMANTIC_NO_PRINT_HELPER *unused=NULL) const {
00132                     print(o, (RenameMap*)0);
00133                 }
00134 
00135                 friend bool operator==(const ValueType &a, const ValueType &b) {
00136                     return a.name==b.name && (!a.name || a.negate==b.negate) && a.offset==b.offset;
00137                 }
00138 
00139                 friend bool operator!=(const ValueType &a, const ValueType &b) {
00140                     return !(a==b);
00141                 }
00142 
00143                 friend bool operator<(const ValueType &a, const ValueType &b) {
00144                     if (a.name<b.name) return true;
00145                     if (b.name<a.name) return false;
00146                     if (a.name && a.negate<b.negate) return true;
00147                     if (a.name && b.negate<a.negate) return false;
00148                     return a.offset < b.offset;
00149                 }
00150             };
00151 
00152             template<size_t Len>
00153             std::ostream& operator<<(std::ostream &o, const ValueType<Len> &e) {
00154                 e.print(o, (RenameMap*)0);
00155                 return o;
00156             }
00157 
00160             template <template <size_t> class ValueType=VirtualMachineSemantics::ValueType>
00161             class MemoryCell: public BaseSemantics::MemoryCell<ValueType> {
00162             public:
00163 
00165                 template <size_t Len>
00166                 MemoryCell(const ValueType<32> &address, const ValueType<Len> data, size_t nbytes)
00167                     : BaseSemantics::MemoryCell<ValueType>(address, data, nbytes) {}
00168 
00172                 bool may_alias(const MemoryCell &other) const;
00173 
00176                 bool must_alias(const MemoryCell &other) const;
00177 
00178                 friend bool operator==(const MemoryCell &a, const MemoryCell &b) {
00179                     return (a.get_address()==b.get_address() &&
00180                             a.get_data()==b.get_data() &&
00181                             a.get_nbytes()==b.get_nbytes() &&
00182                             a.get_clobbered()==b.get_clobbered() &&
00183                             a.get_written()==b.get_written());
00184                 }
00185                 friend bool operator!=(const MemoryCell &a, const MemoryCell &b) {
00186                     return !(a==b);
00187                 }
00188                 friend bool operator<(const MemoryCell &a, const MemoryCell &b) {
00189                     return a.get_address() < b.get_address();
00190                 }
00191             };
00192 
00194             template <template <size_t> class ValueType=VirtualMachineSemantics::ValueType>
00195             struct State: public BaseSemantics::StateX86<MemoryCell, ValueType> {
00196                 typedef typename BaseSemantics::StateX86<MemoryCell, ValueType>::Memory Memory;
00197 
00200                 void print_diff_registers(std::ostream &o, const State&, RenameMap *rmap=NULL) const;
00201 
00203                 bool equal_registers(const State&) const;
00204 
00207                 void discard_popped_memory();
00208             };
00209 
00211             template<
00212                 template <template <size_t> class ValueType> class State = VirtualMachineSemantics::State,
00213                 template <size_t nBits> class ValueType = VirtualMachineSemantics::ValueType
00214                 >
00215             class Policy: public BaseSemantics::Policy {
00216             protected:
00217                 SgAsmInstruction *cur_insn;         
00218                 mutable State<ValueType> orig_state;
00229                 mutable State<ValueType> cur_state;
00235                 bool p_discard_popped_memory;       
00240                 size_t ninsns;                      
00243                 MemoryMap *map;                     
00245             public:
00246                 Policy(): cur_insn(NULL), p_discard_popped_memory(false), ninsns(0), map(NULL) {
00247                     /* So that named values are identical in both; reinitialized by first call to startInstruction(). */
00248                     set_register_dictionary(RegisterDictionary::dictionary_pentium4());
00249                     orig_state = cur_state;
00250                 }
00251 
00254                 void set_map(MemoryMap *map) {
00255                     this->map = map;
00256                 }
00257 
00260                 size_t get_ninsns() const {
00261                     return ninsns;
00262                 }
00263 
00266                 void set_ninsns(size_t n) {
00267                     ninsns = n;
00268                 }
00269 
00271                 SgAsmInstruction *get_insn() const {
00272                     return cur_insn;
00273                 }
00274 
00277                 const State<ValueType>& get_state() const { return cur_state; }
00278                 State<ValueType>& get_state() { return cur_state; }
00283                 const State<ValueType>& get_orig_state() const { return orig_state; }
00284                 State<ValueType>& get_orig_state() { return orig_state; }
00285 
00287                 const ValueType<32>& get_ip() const { return cur_state.ip; }
00288 
00290                 const ValueType<32>& get_orig_ip() const { return orig_state.ip; }
00291 
00293                 typename State<ValueType>::Memory memory_for_equality(const State<ValueType>&) const;
00294 
00297                 typename State<ValueType>::Memory memory_for_equality() const { return memory_for_equality(cur_state); }
00298 
00302                 bool equal_states(const State<ValueType>&, const State<ValueType>&) const;
00303 
00306                 void print(std::ostream&, RenameMap *rmap=NULL) const;
00307                 friend std::ostream& operator<<(std::ostream &o, const Policy &p) {
00308                     p.print(o, NULL);
00309                     return o;
00310                 }
00311 
00314                 bool on_stack(const ValueType<32> &value) const;
00315 
00318                 void set_discard_popped_memory(bool b) {
00319                     p_discard_popped_memory = b;
00320                 }
00321 
00324                 bool get_discard_popped_memory() const {
00325                     return p_discard_popped_memory;
00326                 }
00327 
00330                 void print_diff(std::ostream&, const State<ValueType>&, const State<ValueType>&, RenameMap *rmap=NULL) const ;
00331 
00334                 void print_diff(std::ostream &o, const State<ValueType> &state, RenameMap *rmap=NULL) const {
00335                     print_diff(o, orig_state, state, rmap);
00336                 }
00337 
00340                 void print_diff(std::ostream &o, RenameMap *rmap=NULL) const {
00341                     print_diff(o, orig_state, cur_state, rmap);
00342                 }
00343 
00346                 std::string SHA1() const;
00347 
00352                 bool SHA1(unsigned char *digest) const;
00353 
00355                 template <size_t FromLen, size_t ToLen>
00356                 ValueType<ToLen> signExtend(const ValueType<FromLen> &a) const {
00357                     if (ToLen==FromLen) return a;
00358                     if (a.name) return ValueType<ToLen>();
00359                     return IntegerOps::signExtend<FromLen, ToLen>(a.offset);
00360                 }
00361 
00363                 template <size_t BeginAt, size_t EndAt, size_t Len>
00364                 ValueType<EndAt-BeginAt> extract(const ValueType<Len> &a) const {
00365                     if (0==BeginAt) return ValueType<EndAt-BeginAt>(a);
00366                     if (a.name) return ValueType<EndAt-BeginAt>();
00367                     return (a.offset >> BeginAt) & (IntegerOps::SHL1<uint64_t, EndAt-BeginAt>::value - 1);
00368                 }
00369 
00372                 template <size_t FromLen, size_t ToLen>
00373                 ValueType<ToLen> unsignedExtend(const ValueType<FromLen> &a) const {
00374                     return ValueType<ToLen>(a);
00375                 }
00376 
00386                 template <size_t Len> ValueType<Len> mem_read(State<ValueType> &state, const ValueType<32> &addr) const {
00387                     MemoryCell<ValueType> new_cell(addr, ValueType<32>(), Len/8);
00388                     bool aliased = false; /*is new_cell aliased by any existing writes?*/
00389 
00390                     for (typename State<ValueType>::Memory::iterator mi=state.mem.begin(); mi!=state.mem.end(); ++mi) {
00391                         if (new_cell.must_alias(*mi)) {
00392                             if ((*mi).is_clobbered()) {
00393                                 (*mi).set_clobbered(false);
00394                                 (*mi).set_data(new_cell.get_data());
00395                                 return new_cell.get_data();
00396                             } else {
00397                                 return (*mi).get_data();
00398                             }
00399                         } else if (new_cell.may_alias(*mi) && (*mi).is_written()) {
00400                             aliased = true;
00401                         }
00402                     }
00403 
00404                     if (!aliased && &state!=&orig_state) {
00405                         /* We didn't find the memory cell in the specified state and it's not aliased to any writes in that
00406                          * state. Therefore use the value from the initial memory state (creating it if necessary). */
00407                         for (typename State<ValueType>::Memory::iterator mi=orig_state.mem.begin();
00408                              mi!=orig_state.mem.end();
00409                              ++mi) {
00410                             if (new_cell.must_alias(*mi)) {
00411                                 ROSE_ASSERT(!(*mi).is_clobbered());
00412                                 ROSE_ASSERT(!(*mi).is_written());
00413                                 state.mem.push_back(*mi);
00414                                 std::sort(state.mem.begin(), state.mem.end());
00415                                 return (*mi).get_data();
00416                             }
00417                         }
00418 
00419                         /* Not found in initial state. But if we have a known address and a valid memory map then initialize
00420                          * the original state with data from the memory map. */      
00421                         if (map && addr.is_known()) {
00422                             uint8_t buf[sizeof(uint64_t)];
00423                             ROSE_ASSERT(Len/8 < sizeof buf);
00424                             size_t nread = map->read(buf, addr.known_value(), Len/8);
00425                             if (nread==Len/8) {
00426                                 uint64_t n = 0;
00427                                 for (size_t i=0; i<Len/8; i++)
00428                                     n |= buf[i] << (8*i);
00429                                 new_cell.set_data(number<32>(n));
00430                             }
00431                         }
00432 
00433                         orig_state.mem.push_back(new_cell);
00434                         std::sort(orig_state.mem.begin(), orig_state.mem.end());
00435                     }
00436 
00437                     /* Create the cell in the current state. */
00438                     state.mem.push_back(new_cell);
00439                     std::sort(state.mem.begin(), state.mem.end());
00440                     return new_cell.get_data();
00441                 }
00442 
00444                 enum MemRefType { MRT_STACK_PTR, MRT_FRAME_PTR, MRT_OTHER_PTR };
00445 
00450                 MemRefType memory_reference_type(const State<ValueType> &state, const ValueType<32> &addr) const {
00451                     if (addr.name) {
00452                         if (addr.name==state.gpr[x86_gpr_sp].name) return MRT_STACK_PTR;
00453                         if (addr.name==state.gpr[x86_gpr_bp].name) return MRT_FRAME_PTR;
00454                         return MRT_OTHER_PTR;
00455                     }
00456                     if (addr==state.gpr[x86_gpr_sp]) return MRT_STACK_PTR;
00457                     if (addr==state.gpr[x86_gpr_bp]) return MRT_FRAME_PTR;
00458                     return MRT_OTHER_PTR;
00459                 }
00460 
00464                 template <size_t Len> void mem_write(State<ValueType> &state, const ValueType<32> &addr,
00465                                                      const ValueType<Len> &data) {
00466                     ROSE_ASSERT(&state!=&orig_state);
00467                     MemoryCell<ValueType> new_cell(addr, data, Len/8);
00468                     new_cell.set_written();
00469                     bool saved = false; /* has new_cell been saved into memory? */
00470 
00471                     /* Is new memory reference through the stack pointer or frame pointer? */
00472                     MemRefType new_mrt = memory_reference_type(state, addr);
00473 
00474                     /* Overwrite and/or clobber existing memory locations. */
00475                     for (typename State<ValueType>::Memory::iterator mi=state.mem.begin(); mi!=state.mem.end(); ++mi) {
00476                         if (new_cell.must_alias(*mi)) {
00477                             *mi = new_cell;
00478                             saved = true;
00479                         } else if (p_discard_popped_memory && new_mrt!=memory_reference_type(state, (*mi).get_address())) {
00480                             /* Assume that memory referenced through the stack pointer does not alias that which is referenced
00481                              * through the frame pointer, and neither of them alias memory that is referenced other ways. */
00482                         } else if (new_cell.may_alias(*mi)) {
00483                             (*mi).set_clobbered();
00484                         } else {
00485                             /* memory cell *mi is not aliased to cell being written */
00486                         }
00487                     }
00488                     if (!saved) {
00489                         state.mem.push_back(new_cell);
00490                         std::sort(state.mem.begin(), state.mem.end());
00491                     }
00492                 }
00493 
00494                 /*************************************************************************************************************
00495                  * Functions invoked by the X86InstructionSemantics class for every processed instruction or block
00496                  *************************************************************************************************************/
00497 
00499                 void startInstruction(SgAsmInstruction *insn) {
00500                     cur_state.ip = ValueType<32>(insn->get_address());
00501                     if (0==ninsns++)
00502                         orig_state = cur_state;
00503                     cur_insn = insn;
00504                 }
00505 
00507                 void finishInstruction(SgAsmInstruction*) {
00508                     if (p_discard_popped_memory)
00509                         cur_state.discard_popped_memory();
00510                     cur_insn = NULL;
00511                 }
00512 
00513                 /* Called at the beginning of X86InstructionSemantics::processBlock() */
00514                 void startBlock(rose_addr_t addr) {}
00515 
00516                 /* Called at the end of X86InstructionSemantics::processBlock() */
00517                 void finishBlock(rose_addr_t addr) {}
00518 
00519                 /*************************************************************************************************************
00520                  * Functions invoked by the X86InstructionSemantics class to construct values
00521                  *************************************************************************************************************/
00522 
00524                 ValueType<1> true_() const {
00525                     return 1;
00526                 }
00527 
00529                 ValueType<1> false_() const {
00530                     return 0;
00531                 }
00532 
00534                 ValueType<1> undefined_() const {
00535                     return ValueType<1>();
00536                 }
00537 
00539                 template <size_t Len>
00540                 ValueType<Len> number(uint64_t n) const {
00541                     return n;
00542                 }
00543 
00544 
00545 
00546                 /*************************************************************************************************************
00547                  * Functions invoked by the X86InstructionSemantics class for individual instructions
00548                  *************************************************************************************************************/
00549 
00551                 ValueType<32> filterCallTarget(const ValueType<32> &a) const {
00552                     return a;
00553                 }
00554 
00556                 ValueType<32> filterReturnTarget(const ValueType<32> &a) const {
00557                     return a;
00558                 }
00559 
00561                 ValueType<32> filterIndirectJumpTarget(const ValueType<32> &a) const {
00562                     return a;
00563                 }
00564 
00566                 void hlt() {} // FIXME
00567 
00569                 void cpuid() {} // FIXME
00570 
00572                 ValueType<64> rdtsc() {
00573                     return 0;
00574                 }
00575 
00577                 void interrupt(uint8_t num) {
00578                     cur_state = State<ValueType>(); /*reset entire machine state*/
00579                 }
00580 
00582                 void sysenter() {
00583                     cur_state = State<ValueType>(); /*reset entire machine state*/
00584                 }
00585 
00586 
00587 
00588                 /*************************************************************************************************************
00589                  * Functions invoked by the X86InstructionSemantics class for data access operations
00590                  *************************************************************************************************************/
00591 
00592 #include "ReadWriteRegisterFragment.h"
00593 
00595                 template <size_t Len> ValueType<Len>
00596                 readMemory(X86SegmentRegister segreg, const ValueType<32> &addr, const ValueType<1> &cond) const {
00597                     return mem_read<Len>(cur_state, addr);
00598                 }
00599 
00601                 template <size_t Len> void
00602                 writeMemory(X86SegmentRegister segreg, const ValueType<32> &addr, const ValueType<Len> &data,
00603                             const ValueType<1> &cond) {
00604                     mem_write<Len>(cur_state, addr, data);
00605                 }
00606 
00607 
00608 
00609                 /*************************************************************************************************************
00610                  * Functions invoked by the X86InstructionSemantics class for arithmetic operations
00611                  *************************************************************************************************************/
00612 
00614                 template <size_t Len>
00615                 ValueType<Len> add(const ValueType<Len> &a, const ValueType<Len> &b) const {
00616                     if (a.name==b.name && (!a.name || a.negate!=b.negate)) {
00617                         /* [V1+x] + [-V1+y] = [x+y]  or
00618                          * [x] + [y] = [x+y] */
00619                         return a.offset + b.offset;
00620                     } else if (!a.name || !b.name) {
00621                         /* [V1+x] + [y] = [V1+x+y]   or
00622                          * [x] + [V2+y] = [V2+x+y]   or
00623                          * [-V1+x] + [y] = [-V1+x+y] or
00624                          * [x] + [-V2+y] = [-V2+x+y] */
00625                         return ValueType<Len>(a.name+b.name, a.offset+b.offset, a.negate || b.negate);
00626                     } else {
00627                         return ValueType<Len>();
00628                     }
00629                 }
00630 
00632                 template <size_t Len>
00633                 ValueType<Len> addWithCarries(const ValueType<Len> &a, const ValueType<Len> &b, const ValueType<1> &c,
00634                                               ValueType<Len> &carry_out) const {
00635                     int n_unknown = (a.name?1:0) + (b.name?1:0) + (c.name?1:0);
00636                     if (n_unknown <= 1) {
00637                         /* At most, one of the operands is an unknown value. See add() for more details. */
00638                         uint64_t sum = a.offset + b.offset + c.offset;
00639                         carry_out = 0==n_unknown ? ValueType<Len>((a.offset ^ b.offset ^ sum)>>1) : ValueType<Len>();
00640                         return ValueType<Len>(a.name+b.name+c.name, sum, a.negate||b.negate||c.negate);
00641                     } else if (a.name==b.name && !c.name && a.negate!=b.negate) {
00642                         /* A and B are known or have bases that cancel out, and C is known */
00643                         uint64_t sum = a.offset + b.offset + c.offset;
00644                         carry_out = ValueType<Len>((a.offset ^ b.offset ^ sum)>>1);
00645                         return ValueType<Len>(sum);
00646                     } else {
00647                         carry_out = ValueType<Len>();
00648                         return ValueType<Len>();
00649                     }
00650                 }
00651 
00653                 template <size_t Len>
00654                 ValueType<Len> and_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00655                     if ((!a.name && 0==a.offset) || (!b.name && 0==b.offset)) return 0;
00656                     if (a.name || b.name) return ValueType<Len>();
00657                     return a.offset & b.offset;
00658                 }
00659 
00661                 template <size_t Len>
00662                 ValueType<1> equalToZero(const ValueType<Len> &a) const {
00663                     if (a.name) return undefined_();
00664                     return a.offset ? false_() : true_();
00665                 }
00666 
00668                 template <size_t Len>
00669                 ValueType<Len> invert(const ValueType<Len> &a) const {
00670                     if (a.name) return ValueType<Len>(a.name, ~a.offset, !a.negate);
00671                     return ~a.offset;
00672                 }
00673 
00675                 template<size_t Len1, size_t Len2>
00676                 ValueType<Len1+Len2> concat(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00677                     if (a.name || b.name) return ValueType<Len1+Len2>();
00678                     return a.offset | (b.offset << Len1);
00679                 }
00680 
00682                 template <size_t Len>
00683                 ValueType<Len> ite(const ValueType<1> &sel, const ValueType<Len> &ifTrue, const ValueType<Len> &ifFalse) const {
00684                     if (ifTrue==ifFalse) return ifTrue;
00685                     if (sel.name) return ValueType<Len>();
00686                     return sel.offset ? ifTrue : ifFalse;
00687                 }
00688 
00690                 template <size_t Len>
00691                 ValueType<Len> leastSignificantSetBit(const ValueType<Len> &a) const {
00692                     if (a.name) return ValueType<Len>();
00693                     for (size_t i=0; i<Len; ++i) {
00694                         if (a.offset & ((uint64_t)1 << i))
00695                             return i;
00696                     }
00697                     return 0;
00698                 }
00699 
00701                 template <size_t Len>
00702                 ValueType<Len> mostSignificantSetBit(const ValueType<Len> &a) const {
00703                     if (a.name) return ValueType<Len>();
00704                     for (size_t i=Len; i>0; --i) {
00705                         if (a.offset & ((uint64_t)1 << (i-1)))
00706                             return i-1;
00707                     }
00708                     return 0;
00709                 }
00710 
00712                 template <size_t Len>
00713                 ValueType<Len> negate(const ValueType<Len> &a) const {
00714                     if (a.name) return ValueType<Len>(a.name, -a.offset, !a.negate);
00715                     return -a.offset;
00716                 }
00717 
00719                 template <size_t Len>
00720                 ValueType<Len> or_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00721                     if (a==b) return a;
00722                     if (!a.name && !b.name) return a.offset | b.offset;
00723                     if (!a.name && a.offset==IntegerOps::GenMask<uint64_t, Len>::value) return a;
00724                     if (!b.name && b.offset==IntegerOps::GenMask<uint64_t, Len>::value) return b;
00725                     return ValueType<Len>();
00726                 }
00727 
00729                 template <size_t Len, size_t SALen>
00730                 ValueType<Len> rotateLeft(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00731                     if (!a.name && !sa.name) return IntegerOps::rotateLeft<Len>(a.offset, sa.offset);
00732                     if (!sa.name && 0==sa.offset % Len) return a;
00733                     return ValueType<Len>();
00734                 }
00735 
00737                 template <size_t Len, size_t SALen>
00738                 ValueType<Len> rotateRight(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00739                     if (!a.name && !sa.name) return IntegerOps::rotateRight<Len>(a.offset, sa.offset);
00740                     if (!sa.name && 0==sa.offset % Len) return a;
00741                     return ValueType<Len>();
00742                 }
00743 
00745                 template <size_t Len, size_t SALen>
00746                 ValueType<Len> shiftLeft(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00747                     if (!a.name && !sa.name) return IntegerOps::shiftLeft<Len>(a.offset, sa.offset);
00748                     if (!sa.name) {
00749                         if (0==sa.offset) return a;
00750                         if (sa.offset>=Len) return 0;
00751                     }
00752                     return ValueType<Len>();
00753                 }
00754 
00756                 template <size_t Len, size_t SALen>
00757                 ValueType<Len> shiftRight(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00758                     if (!a.name && !sa.name) return IntegerOps::shiftRightLogical<Len>(a.offset, sa.offset);
00759                     if (!sa.name) {
00760                         if (0==sa.offset) return a;
00761                         if (sa.offset>=Len) return 0;
00762                     }
00763                     return ValueType<Len>();
00764                 }
00765 
00767                 template <size_t Len, size_t SALen>
00768                 ValueType<Len> shiftRightArithmetic(const ValueType<Len> &a, const ValueType<SALen> &sa) const {
00769                     if (!a.name && !sa.name) return IntegerOps::shiftRightArithmetic<Len>(a.offset, sa.offset);
00770                     if (!sa.name && 0==sa.offset) return a;
00771                     return ValueType<Len>();
00772                 }
00773 
00775                 template <size_t Len1, size_t Len2>
00776                 ValueType<Len1> signedDivide(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00777                     if (!b.name) {
00778                         if (0==b.offset) throw Exception("division by zero");
00779                         if (!a.name)
00780                             return IntegerOps::signExtend<Len1, 64>(a.offset) / IntegerOps::signExtend<Len2, 64>(b.offset);
00781                         if (1==b.offset) return a;
00782                         if (b.offset==IntegerOps::GenMask<uint64_t,Len2>::value) return negate(a);
00783                         /*FIXME: also possible to return zero if B is large enough. [RPM 2010-05-18]*/
00784                     }
00785                     return ValueType<Len1>();
00786                 }
00787 
00789                 template <size_t Len1, size_t Len2>
00790                 ValueType<Len2> signedModulo(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00791                     if (a.name || b.name) return ValueType<Len2>();
00792                     if (0==b.offset) throw Exception("division by zero");
00793                     return IntegerOps::signExtend<Len1, 64>(a.offset) % IntegerOps::signExtend<Len2, 64>(b.offset);
00794                     /* FIXME: More folding possibilities... if 'b' is a power of two then we can return 'a' with the bitsize of
00795                      * 'b'. */
00796                 }
00797 
00799                 template <size_t Len1, size_t Len2>
00800                 ValueType<Len1+Len2> signedMultiply(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00801                     if (!a.name && !b.name)
00802                         return IntegerOps::signExtend<Len1, 64>(a.offset) * IntegerOps::signExtend<Len2, 64>(b.offset);
00803                     if (!b.name) {
00804                         if (0==b.offset) return 0;
00805                         if (1==b.offset) return signExtend<Len1, Len1+Len2>(a);
00806                         if (b.offset==IntegerOps::GenMask<uint64_t,Len2>::value) return signExtend<Len1, Len1+Len2>(negate(a));
00807                     }
00808                     if (!a.name) {
00809                         if (0==a.offset) return 0;
00810                         if (1==a.offset) return signExtend<Len2, Len1+Len2>(b);
00811                         if (a.offset==IntegerOps::GenMask<uint64_t,Len1>::value) return signExtend<Len2, Len1+Len2>(negate(b));
00812                     }
00813                     return ValueType<Len1+Len2>();
00814                 }
00815 
00817                 template <size_t Len1, size_t Len2>
00818                 ValueType<Len1> unsignedDivide(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00819                     if (!b.name) {
00820                         if (0==b.offset) throw Exception("division by zero");
00821                         if (!a.name) return a.offset / b.offset;
00822                         if (1==b.offset) return a;
00823                         /*FIXME: also possible to return zero if B is large enough. [RPM 2010-05-18]*/
00824                     }
00825                     return ValueType<Len1>();
00826                 }
00827 
00829                 template <size_t Len1, size_t Len2>
00830                 ValueType<Len2> unsignedModulo(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00831                     if (!b.name) {
00832                         if (0==b.offset) throw Exception("division by zero");
00833                         if (!a.name) return a.offset % b.offset;
00834                         /* FIXME: More folding possibilities... if 'b' is a power of two then we can return 'a' with the
00835                          * bitsize of 'b'. */
00836                     }
00837                     if (unsignedExtend<Len1,64>(a)==unsignedExtend<Len2,64>(b)) return b;
00838                     return ValueType<Len2>();
00839                 }
00840 
00842                 template <size_t Len1, size_t Len2>
00843                 ValueType<Len1+Len2> unsignedMultiply(const ValueType<Len1> &a, const ValueType<Len2> &b) const {
00844                     if (!a.name && !b.name)
00845                         return a.offset * b.offset;
00846                     if (!b.name) {
00847                         if (0==b.offset) return 0;
00848                         if (1==b.offset) return unsignedExtend<Len1, Len1+Len2>(a);
00849                     }
00850                     if (!a.name) {
00851                         if (0==a.offset) return 0;
00852                         if (1==a.offset) return unsignedExtend<Len2, Len1+Len2>(b);
00853                     }
00854                     return ValueType<Len1+Len2>();
00855                 }
00856 
00858                 template <size_t Len>
00859                 ValueType<Len> xor_(const ValueType<Len> &a, const ValueType<Len> &b) const {
00860                     if (!a.name && !b.name)
00861                         return a.offset ^ b.offset;
00862                     if (a==b)
00863                         return 0;
00864                     if (!b.name) {
00865                         if (0==b.offset) return a;
00866                         if (b.offset==IntegerOps::GenMask<uint64_t, Len>::value) return invert(a);
00867                     }
00868                     if (!a.name) {
00869                         if (0==a.offset) return b;
00870                         if (a.offset==IntegerOps::GenMask<uint64_t, Len>::value) return invert(b);
00871                     }
00872                     return ValueType<Len>();
00873                 }
00874             };
00875 
00876             /*************************************************************************************************************
00877              *                              ValueType template functions
00878              *************************************************************************************************************/
00879 
00880 
00881             template<size_t Len> ValueType<Len>
00882             ValueType<Len>::rename(RenameMap *rmap) const
00883             {
00884                 ValueType<Len> retval = *this;
00885                 if (rmap && name>0) {
00886                     RenameMap::iterator found = rmap->find(name);
00887                     if (found==rmap->end()) {
00888                         retval.name = rmap->size()+1;
00889                         rmap->insert(std::make_pair(name, retval.name));
00890                     } else {
00891                         retval.name = found->second;
00892                     }
00893                 }
00894                 return retval;
00895             }
00896 
00897 
00898 
00899             /*************************************************************************************************************
00900              *                              MemoryCell template functions
00901              *************************************************************************************************************/
00902 
00903             template<template <size_t> class ValueType>
00904             bool
00905             MemoryCell<ValueType>::may_alias(const MemoryCell &other) const {
00906                 const ValueType<32> &addr1 = this->address;
00907                 const ValueType<32> &addr2 = other.address;
00908                 if (addr1.name != addr2.name) return true;
00909 
00910                 /* Same unknown values but inverses (any offset). */
00911                 if (addr1.name && addr1.negate!=addr2.negate) return true;
00912 
00913                 /* If they have the same base values (or are both constant) then check the offsets. The 32-bit casts are
00914                  * purportedly necessary to wrap propertly, but I'm not sure this will work for addresses (LatticeElements)
00915                  * that have a length other than 32 bits. [FIXME RPM 2009-02-03]. */
00916                 uint32_t offsetDiff = (uint32_t)(addr1.offset - addr2.offset);
00917                 if (offsetDiff < this->nbytes || offsetDiff > (uint32_t)(-other.nbytes))
00918                     return true;
00919                 return false;
00920             }
00921 
00922             template<template<size_t> class ValueType>
00923             bool
00924             MemoryCell<ValueType>::must_alias(const MemoryCell<ValueType> &other) const {
00925                 return this->address == other.address;
00926             }
00927 
00928             /*****************************************************************************************************************
00929              *                              State template functions
00930              *****************************************************************************************************************/
00931 
00932             template<template<size_t> class ValueType>
00933             void
00934             State<ValueType>::print_diff_registers(std::ostream &o, const State &other, RenameMap *rmap/*=NULL*/) const
00935             {
00936 #ifndef CXX_IS_ROSE_ANALYSIS
00937                 // DQ (5/22/2010): This code does not compile using ROSE, it needs to be investigated to be reduced to an bug
00938                 // report.
00939 
00940                 std::string prefix = "    ";
00941 
00942                 for (size_t i=0; i<this->n_gprs; ++i) {
00943                     if (this->gpr[i]!=other.gpr[i]) {
00944                         o <<prefix <<gprToString((X86GeneralPurposeRegister)i) <<": "
00945                           <<this->gpr[i].rename(rmap) <<" -> " <<other.gpr[i].rename(rmap) <<"\n";
00946                     }
00947                 }
00948                 for (size_t i=0; i<this->n_segregs; ++i) {
00949                     if (this->segreg[i]!=other.segreg[i]) {
00950                         o <<prefix <<segregToString((X86SegmentRegister)i) <<": "
00951                           <<this->segreg[i].rename(rmap) <<" -> " <<other.segreg[i].rename(rmap) <<"\n";
00952                     }
00953                 }
00954                 for (size_t i=0; i<this->n_flags; ++i) {
00955                     if (this->flag[i]!=other.flag[i]) {
00956                         o <<prefix <<flagToString((X86Flag)i) <<": "
00957                           <<this->flag[i].rename(rmap) <<" -> " <<other.flag[i].rename(rmap) <<"\n";
00958                     }
00959                 }
00960                 if (this->ip!=other.ip) {
00961                     o <<prefix <<"ip: " <<this->ip.rename(rmap) <<" -> " <<other.ip.rename(rmap) <<"\n";
00962                 }
00963 #endif
00964             }
00965 
00966             template<template<size_t> class ValueType>
00967             bool
00968             State<ValueType>::equal_registers(const State &other) const
00969             {
00970 #ifndef CXX_IS_ROSE_ANALYSIS
00971                 for (size_t i=0; i<this->n_gprs; ++i)
00972                     if (this->gpr[i]!=other.gpr[i]) return false;
00973                 for (size_t i=0; i<this->n_segregs; ++i)
00974                     if (this->segreg[i]!=other.segreg[i]) return false;
00975                 for (size_t i=0; i<this->n_flags; ++i)
00976                     if (this->flag[i]!=other.flag[i]) return false;
00977                 if (this->ip!=other.ip) return false;
00978 #endif
00979                 return true;
00980             }
00981 
00982             template<template<size_t> class ValueType>
00983             void
00984             State<ValueType>::discard_popped_memory()
00985             {
00986                 Memory new_mem;
00987                 const ValueType<32> &sp = this->gpr[x86_gpr_sp];
00988                 for (typename Memory::const_iterator mi=this->mem.begin(); mi!=this->mem.end(); ++mi) {
00989                     const ValueType<32> &addr = (*mi).get_address();
00990                     if (addr.name!=sp.name || addr.negate!=sp.negate || (int32_t)addr.offset>=(int32_t)sp.offset)
00991                         new_mem.push_back(*mi);
00992                 }
00993                 this->mem = new_mem;
00994             }
00995 
00996             /*****************************************************************************************************************
00997              *                              Policy template functions
00998              *****************************************************************************************************************/
00999 
01000             /* Returns memory that needs to be compared by equal_states() */
01001             template<
01002                 template <template <size_t> class ValueType> class State,
01003                 template<size_t> class ValueType>
01004             typename State<ValueType>::Memory
01005             Policy<State, ValueType>::memory_for_equality(const State<ValueType> &state) const
01006             {
01007                 State<ValueType> tmp_state = state;
01008                 typename State<ValueType>::Memory retval;
01009 #ifndef CXX_IS_ROSE_ANALYSIS
01010                 for (typename State<ValueType>::Memory::const_iterator mi=state.mem.begin(); mi!=state.mem.end(); ++mi) {
01011                     if ((*mi).is_written() && (*mi).get_data()!=mem_read<32>(orig_state, (*mi).get_address()))
01012                         retval.push_back(*mi);
01013                 }
01014 #endif
01015                 return retval;
01016             }
01017 
01018             template<
01019                 template <template <size_t> class ValueType> class State,
01020                 template<size_t> class ValueType>
01021             bool
01022             Policy<State, ValueType>::equal_states(const State<ValueType> &s1, const State<ValueType> &s2) const
01023             {
01024 #ifndef CXX_IS_ROSE_ANALYSIS
01025                 if (!s1.equal_registers(s2))
01026                     return false;
01027                 typename State<ValueType>::Memory m1 = memory_for_equality(s1);
01028                 typename State<ValueType>::Memory m2 = memory_for_equality(s2);
01029                 if (m1.size()!=m2.size())
01030                     return false;
01031                 for (size_t i=0; i<m1.size(); ++i) {
01032                     if (m1[i].get_nbytes() != m2[i].get_nbytes() ||
01033                         m1[i].get_address()!= m2[i].get_address() ||
01034                         m1[i].get_data()   != m2[i].get_data())
01035                         return false;
01036                 }
01037 #endif
01038                 return true;
01039             }
01040 
01041             template<
01042                 template <template <size_t> class ValueType> class State,
01043                 template<size_t> class ValueType>
01044             void
01045             Policy<State, ValueType>::print(std::ostream &o, RenameMap *rmap/*=NULL*/) const
01046             {
01047                 cur_state.print(o, "", rmap);
01048             }
01049 
01050             template<
01051                 template <template <size_t> class ValueType> class State,
01052                 template<size_t> class ValueType>
01053             void
01054             Policy<State, ValueType>::print_diff(std::ostream &o, const State<ValueType> &s1,
01055                                                  const State<ValueType> &s2, RenameMap *rmap/*=NULL*/) const
01056             {
01057 #ifndef CXX_IS_ROSE_ANALYSIS
01058                 s1.print_diff_registers(o, s2, rmap);
01059 
01060                 /* Get all addresses that have been written and are not currently clobbered. */
01061                 std::set<ValueType<32> > addresses;
01062                 for (typename State<ValueType>::Memory::const_iterator mi=s1.mem.begin(); mi!=s1.mem.end(); ++mi) {
01063                     if (!(*mi).is_clobbered() && (*mi).is_written())
01064                         addresses.insert((*mi).get_address());
01065                 }
01066                 for (typename State<ValueType>::Memory::const_iterator mi=s2.mem.begin(); mi!=s2.mem.end(); ++mi) {
01067                     if (!(*mi).is_clobbered() && (*mi).is_written())
01068                         addresses.insert((*mi).get_address());
01069                 }
01070 
01071                 State<ValueType> tmp_s1 = s1;
01072                 State<ValueType> tmp_s2 = s2;
01073                 size_t nmemdiff = 0;
01074                 for (typename std::set<ValueType<32> >::const_iterator ai=addresses.begin(); ai!=addresses.end(); ++ai) {
01075                     ValueType<32> v1 = mem_read<32>(tmp_s1, *ai);
01076                     ValueType<32> v2 = mem_read<32>(tmp_s2, *ai);
01077                     if (v1 != v2) {
01078                         if (0==nmemdiff++) o <<"    memory:\n";
01079                         o <<"      " <<(*ai).rename(rmap) <<": " <<v1.rename(rmap) <<" -> " <<v2.rename(rmap) <<"\n";
01080                     }
01081                 }
01082 #endif
01083             }
01084 
01085             template<
01086                 template <template <size_t> class ValueType> class State,
01087                 template<size_t> class ValueType>
01088             bool
01089             Policy<State, ValueType>::on_stack(const ValueType<32> &value) const
01090             {
01091 #ifndef CXX_IS_ROSE_ANALYSIS
01092                 const ValueType<32> sp_inverted = invert(cur_state.gpr[x86_gpr_sp]);
01093                 for (typename State<ValueType>::Memory::const_iterator mi=cur_state.mem.begin(); mi!=cur_state.mem.end(); ++mi) {
01094                     if ((*mi).get_nbytes()!=4 || !((*mi).get_data()==value)) continue;
01095                     const ValueType<32> &addr = (*mi).get_address();
01096 
01097                     /* Is addr >= sp? */
01098                     ValueType<32> carries = 0;
01099                     ValueType<32> diff = addWithCarries(addr, sp_inverted, true_(), carries/*out*/);
01100                     ValueType<1> sf = extract<31,32>(diff);
01101                     ValueType<1> of = xor_(extract<31,32>(carries), extract<30,31>(carries));
01102                     if (sf==of) return true;
01103                 }
01104 #endif
01105                 return false;
01106             }
01107 
01108             template<
01109                 template <template <size_t> class ValueType> class State,
01110                 template<size_t> class ValueType>
01111             bool
01112             Policy<State, ValueType>::SHA1(unsigned char digest[20]) const
01113             {
01114 #ifdef ROSE_HAVE_GCRYPT_H
01115                 /* libgcrypt requires gcry_check_version() to be called "before any other function in the library", but doesn't
01116                  * include an API function for determining if this has already been performed. It also doesn't indicate what
01117                  * happens when it's called more than once, or how expensive the call is.  Therefore, instead of calling it
01118                  * every time through this function, we'll just call it the first time. */
01119                 static bool initialized = false;
01120                 if (!initialized) {
01121                     gcry_check_version(NULL);
01122                     initialized = true;
01123                 }
01124 
01125                 std::stringstream s;
01126                 RenameMap rmap;
01127                 print_diff(s, &rmap);
01128                 ROSE_ASSERT(gcry_md_get_algo_dlen(GCRY_MD_SHA1)==20);
01129                 gcry_md_hash_buffer(GCRY_MD_SHA1, digest, s.str().c_str(), s.str().size());
01130                 return true;
01131 #else
01132                 memset(digest, 0, 20);
01133                 return false;
01134 #endif
01135             }
01136 
01137             template<
01138                 template <template <size_t> class ValueType> class State,
01139                 template<size_t> class ValueType>
01140             std::string
01141             Policy<State, ValueType>::SHA1() const
01142             {
01143                 std::string digest_str;
01144                 unsigned char digest[20];
01145                 if (SHA1(digest)) {
01146                     for (size_t i=sizeof digest; i>0; --i) {
01147                         digest_str += "0123456789abcdef"[(digest[i-1] >> 4) & 0xf];
01148                         digest_str += "0123456789abcdef"[digest[i-1] & 0xf];
01149                     }
01150                 }
01151                 return digest_str;
01152             }
01153     
01154         } /*namespace*/
01155     } /*namespace*/
01156 } /*namespace*/
01157 
01158 
01159 #endif

Generated on Wed May 16 06:18:11 2012 for ROSE by  doxygen 1.4.7