AddressSpace.cpp

Go to the documentation of this file.
00001 //===-- AddressSpace.cpp --------------------------------------------------===//
00002 //
00003 //                     The KLEE Symbolic Virtual Machine
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "AddressSpace.h"
00011 #include "CoreStats.h"
00012 #include "Memory.h"
00013 #include "TimingSolver.h"
00014 
00015 #include "klee/Expr.h"
00016 #include "klee/TimerStatIncrementer.h"
00017 
00018 using namespace klee;
00019 
00021 
00022 void AddressSpace::bindObject(const MemoryObject *mo, ObjectState *os) {
00023   assert(os->copyOnWriteOwner==0 && "object already has owner");
00024   os->copyOnWriteOwner = cowKey;
00025   objects = objects.replace(std::make_pair(mo, os));
00026 }
00027 
00028 void AddressSpace::unbindObject(const MemoryObject *mo) {
00029   objects = objects.remove(mo);
00030 }
00031 
00032 const ObjectState *AddressSpace::findObject(const MemoryObject *mo) const {
00033   const MemoryMap::value_type *res = objects.lookup(mo);
00034   
00035   return res ? res->second : 0;
00036 }
00037 
00038 ObjectState *AddressSpace::getWriteable(const MemoryObject *mo,
00039                                         const ObjectState *os) {
00040   assert(!os->readOnly);
00041 
00042   if (cowKey==os->copyOnWriteOwner) {
00043     return const_cast<ObjectState*>(os);
00044   } else {
00045     ObjectState *n = new ObjectState(*os);
00046     n->copyOnWriteOwner = cowKey;
00047     objects = objects.replace(std::make_pair(mo, n));
00048     return n;    
00049   }
00050 }
00051 
00053 
00054 bool AddressSpace::resolveOne(uint64_t addr64, ObjectPair &result) {
00055   unsigned address = (unsigned) addr64;
00056   MemoryObject hack(address);
00057 
00058   if (const MemoryMap::value_type *res = objects.lookup_previous(&hack)) {
00059     const MemoryObject *mo = res->first;
00060     if ((mo->size==0 && address==mo->address) ||
00061         (address - mo->address < mo->size)) {
00062       result = *res;
00063       return true;
00064     }
00065   }
00066 
00067   return false;
00068 }
00069 
00070 bool AddressSpace::resolveOne(ExecutionState &state,
00071                               TimingSolver *solver,
00072                               ref<Expr> address,
00073                               ObjectPair &result,
00074                               bool &success) {
00075   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(address)) {
00076     success = resolveOne(CE->getConstantValue(), result);
00077     return true;
00078   } else {
00079     TimerStatIncrementer timer(stats::resolveTime);
00080 
00081     // try cheap search, will succeed for any inbounds pointer
00082 
00083     ref<ConstantExpr> cex;
00084     if (!solver->getValue(state, address, cex))
00085       return false;
00086     unsigned example = (unsigned) cex->getConstantValue();
00087     MemoryObject hack(example);
00088     const MemoryMap::value_type *res = objects.lookup_previous(&hack);
00089     
00090     if (res) {
00091       const MemoryObject *mo = res->first;
00092       if (example - mo->address < mo->size) {
00093         result = *res;
00094         success = true;
00095         return true;
00096       }
00097     }
00098 
00099     // didn't work, now we have to search
00100        
00101     MemoryMap::iterator oi = objects.upper_bound(&hack);
00102     MemoryMap::iterator begin = objects.begin();
00103     MemoryMap::iterator end = objects.end();
00104       
00105     MemoryMap::iterator start = oi;
00106     while (oi!=begin) {
00107       --oi;
00108       const MemoryObject *mo = oi->first;
00109         
00110       bool mayBeTrue;
00111       if (!solver->mayBeTrue(state, 
00112                              mo->getBoundsCheckPointer(address), mayBeTrue))
00113         return false;
00114       if (mayBeTrue) {
00115         result = *oi;
00116         success = true;
00117         return true;
00118       } else {
00119         bool mustBeTrue;
00120         if (!solver->mustBeTrue(state, 
00121                                 UgeExpr::create(address, mo->getBaseExpr()),
00122                                 mustBeTrue))
00123           return false;
00124         if (mustBeTrue)
00125           break;
00126       }
00127     }
00128 
00129     // search forwards
00130     for (oi=start; oi!=end; ++oi) {
00131       const MemoryObject *mo = oi->first;
00132 
00133       bool mustBeTrue;
00134       if (!solver->mustBeTrue(state, 
00135                               UltExpr::create(address, mo->getBaseExpr()),
00136                               mustBeTrue))
00137         return false;
00138       if (mustBeTrue) {
00139         break;
00140       } else {
00141         bool mayBeTrue;
00142 
00143         if (!solver->mayBeTrue(state, 
00144                                mo->getBoundsCheckPointer(address),
00145                                mayBeTrue))
00146           return false;
00147         if (mayBeTrue) {
00148           result = *oi;
00149           success = true;
00150           return true;
00151         }
00152       }
00153     }
00154 
00155     success = false;
00156     return true;
00157   }
00158 }
00159 
00160 bool AddressSpace::resolve(ExecutionState &state,
00161                            TimingSolver *solver, 
00162                            ref<Expr> p, 
00163                            ResolutionList &rl, 
00164                            unsigned maxResolutions,
00165                            double timeout) {
00166   if (ConstantExpr *CE = dyn_cast<ConstantExpr>(p)) {
00167     ObjectPair res;
00168     if (resolveOne(CE->getConstantValue(), res))
00169       rl.push_back(res);
00170     return false;
00171   } else {
00172     TimerStatIncrementer timer(stats::resolveTime);
00173     uint64_t timeout_us = (uint64_t) (timeout*1000000.);
00174 
00175     // XXX in general this isn't exactly what we want... for
00176     // a multiple resolution case (or for example, a \in {b,c,0})
00177     // we want to find the first object, find a cex assuming
00178     // not the first, find a cex assuming not the second...
00179     // etc.
00180     
00181     // XXX how do we smartly amortize the cost of checking to
00182     // see if we need to keep searching up/down, in bad cases?
00183     // maybe we don't care?
00184     
00185     // XXX we really just need a smart place to start (although
00186     // if its a known solution then the code below is guaranteed
00187     // to hit the fast path with exactly 2 queries). we could also
00188     // just get this by inspection of the expr.
00189     
00190     ref<ConstantExpr> cex;
00191     if (!solver->getValue(state, p, cex))
00192       return true;
00193     unsigned example = (unsigned) cex->getConstantValue();
00194     MemoryObject hack(example);
00195     
00196     MemoryMap::iterator oi = objects.upper_bound(&hack);
00197     MemoryMap::iterator begin = objects.begin();
00198     MemoryMap::iterator end = objects.end();
00199       
00200     MemoryMap::iterator start = oi;
00201       
00202     // XXX in the common case we can save one query if we ask
00203     // mustBeTrue before mayBeTrue for the first result. easy
00204     // to add I just want to have a nice symbolic test case first.
00205       
00206     // search backwards, start with one minus because this
00207     // is the object that p *should* be within, which means we
00208     // get write off the end with 4 queries (XXX can be better,
00209     // no?)
00210     while (oi!=begin) {
00211       --oi;
00212       const MemoryObject *mo = oi->first;
00213       if (timeout_us && timeout_us < timer.check())
00214         return true;
00215 
00216       // XXX I think there is some query wasteage here?
00217       ref<Expr> inBounds = mo->getBoundsCheckPointer(p);
00218       bool mayBeTrue;
00219       if (!solver->mayBeTrue(state, inBounds, mayBeTrue))
00220         return true;
00221       if (mayBeTrue) {
00222         rl.push_back(*oi);
00223         
00224         // fast path check
00225         unsigned size = rl.size();
00226         if (size==1) {
00227           bool mustBeTrue;
00228           if (!solver->mustBeTrue(state, inBounds, mustBeTrue))
00229             return true;
00230           if (mustBeTrue)
00231             return false;
00232         } else if (size==maxResolutions) {
00233           return true;
00234         }
00235       }
00236         
00237       bool mustBeTrue;
00238       if (!solver->mustBeTrue(state, 
00239                               UgeExpr::create(p, mo->getBaseExpr()),
00240                               mustBeTrue))
00241         return true;
00242       if (mustBeTrue)
00243         break;
00244     }
00245     // search forwards
00246     for (oi=start; oi!=end; ++oi) {
00247       const MemoryObject *mo = oi->first;
00248       if (timeout_us && timeout_us < timer.check())
00249         return true;
00250 
00251       bool mustBeTrue;
00252       if (!solver->mustBeTrue(state, 
00253                               UltExpr::create(p, mo->getBaseExpr()),
00254                               mustBeTrue))
00255         return true;
00256       if (mustBeTrue)
00257         break;
00258       
00259       // XXX I think there is some query wasteage here?
00260       ref<Expr> inBounds = mo->getBoundsCheckPointer(p);
00261       bool mayBeTrue;
00262       if (!solver->mayBeTrue(state, inBounds, mayBeTrue))
00263         return true;
00264       if (mayBeTrue) {
00265         rl.push_back(*oi);
00266         
00267         // fast path check
00268         unsigned size = rl.size();
00269         if (size==1) {
00270           bool mustBeTrue;
00271           if (!solver->mustBeTrue(state, inBounds, mustBeTrue))
00272             return true;
00273           if (mustBeTrue)
00274             return false;
00275         } else if (size==maxResolutions) {
00276           return true;
00277         }
00278       }
00279     }
00280   }
00281 
00282   return false;
00283 }
00284 
00285 // These two are pretty big hack so we can sort of pass memory back
00286 // and forth to externals. They work by abusing the concrete cache
00287 // store inside of the object states, which allows them to
00288 // transparently avoid screwing up symbolics (if the byte is symbolic
00289 // then its concrete cache byte isn't being used) but is just a hack.
00290 
00291 void AddressSpace::copyOutConcretes() {
00292   for (MemoryMap::iterator it = objects.begin(), ie = objects.end(); 
00293        it != ie; ++it) {
00294     const MemoryObject *mo = it->first;
00295 
00296     if (!mo->isUserSpecified) {
00297       ObjectState *os = it->second;
00298       uint8_t *address = (uint8_t*) (unsigned long) mo->address;
00299 
00300       if (!os->readOnly)
00301         memcpy(address, os->concreteStore, mo->size);
00302     }
00303   }
00304 }
00305 
00306 bool AddressSpace::copyInConcretes() {
00307   for (MemoryMap::iterator it = objects.begin(), ie = objects.end(); 
00308        it != ie; ++it) {
00309     const MemoryObject *mo = it->first;
00310 
00311     if (!mo->isUserSpecified) {
00312       const ObjectState *os = it->second;
00313       uint8_t *address = (uint8_t*) (unsigned long) mo->address;
00314 
00315       if (memcmp(address, os->concreteStore, mo->size)!=0) {
00316         if (os->readOnly) {
00317           return false;
00318         } else {
00319           ObjectState *wos = getWriteable(mo, os);
00320           memcpy(wos->concreteStore, address, mo->size);
00321         }
00322       }
00323     }
00324   }
00325 
00326   return true;
00327 }
00328 
00329 /***/
00330 
00331 bool MemoryObjectLT::operator()(const MemoryObject *a, const MemoryObject *b) const {
00332   return a->address < b->address;
00333 }
00334 

Generated on Fri Jun 5 03:31:31 2009 for klee by  doxygen 1.5.8