From 914e226a61b67ae9d5d95b8f5f127bb38cb92752 Mon Sep 17 00:00:00 2001 From: Jiawei Wang Date: Tue, 28 Nov 2023 15:59:10 +1100 Subject: [PATCH] 2nd PR. Add SVF's byte size and fix some api use (#1260) * 1. add LLVM Byte size helper functions to AddrStmt 2. add MaxByteLimit Option * 1) remove superfluous apis in AddrStmt, to improve coverage 2) add isStaticDeterminedByteSize and getByteSizeOfObj in ObjTypeInfo (with getter/setter) and MemObj(only getter) 3) fulfill SymbolTableBuilder::initTypeInfo() to init the ByteSize related field * remove MaxByteLimit Option * 1) rename staticDetermined -> ConstantOffset 2) fix a bug in IntervalValue compare Op 3) remove ConstantOffset bool flag. Instead, if byteSize != 0, it is signal of constant offset. If byteSize = 0, it can be zero byte size or non-const offset. 4) add analyzeHeapAllocByteSize(const Value*), which accepts a CallInst like (malloc/calloc/..) and analyze the allocation byte Size of heap function 5) remove the hard code (99999) of maxByteLimit in SVFIR2ItvExeState::getBytefromGepTypePair, and replace it with Options::MaxFieldLimit() * 1) remove getLLVMByteSize 2) add getByteSize and SetByteSize in SVFType * fix CI compile err * fix interval cmp err * imporve the efficiency of function's annotation processing * merge with master * refactor GepStmt's API * remove setByteSize() and move assignments to Constructor * switch the order of SVFOtherType's constructor arguments * rename and refactor some api related to GepStmt --------- Co-authored-by: jiawei.wang --- svf-llvm/lib/LLVMModule.cpp | 20 +- svf-llvm/lib/LLVMUtil.cpp | 9 - svf-llvm/lib/SymbolTableBuilder.cpp | 8 +- svf/include/AbstractExecution/IntervalValue.h | 6 +- .../AbstractExecution/SVFIR2ItvExeState.h | 10 +- svf/include/MemoryModel/AccessPath.h | 11 +- svf/include/SVFIR/SVFStatements.h | 4 +- svf/include/SVFIR/SVFType.h | 28 +- .../AbstractExecution/SVFIR2ItvExeState.cpp | 317 +++++++++--------- svf/lib/MemoryModel/AccessPath.cpp | 19 +- svf/lib/SVFIR/SVFFileSystem.cpp | 10 +- svf/lib/SVFIR/SVFType.cpp | 7 - 12 files changed, 232 insertions(+), 217 deletions(-) diff --git a/svf-llvm/lib/LLVMModule.cpp b/svf-llvm/lib/LLVMModule.cpp index a1870ecb2..91e233b01 100644 --- a/svf-llvm/lib/LLVMModule.cpp +++ b/svf-llvm/lib/LLVMModule.cpp @@ -1256,14 +1256,23 @@ SVFType* LLVMModuleSet::addSVFTypeInfo(const Type* T) assert(LLVMType2SVFType.find(T) == LLVMType2SVFType.end() && "SVFType has been added before"); + // add SVFType's LLVM byte size iff T isSized(), otherwise byteSize is 0(default value) + u32_t byteSize = 0; + if (T->isSized()) { + const llvm::DataLayout &DL = LLVMModuleSet::getLLVMModuleSet()-> + getMainLLVMModule()->getDataLayout(); + Type *mut_T = const_cast(T); + byteSize = DL.getTypeAllocSize(mut_T); + } + SVFType* svftype; if (SVFUtil::isa(T)) { - svftype = new SVFPointerType(); + svftype = new SVFPointerType(byteSize); } else if (const IntegerType* intT = SVFUtil::dyn_cast(T)) { - auto svfIntT = new SVFIntegerType(); + auto svfIntT = new SVFIntegerType(byteSize); unsigned signWidth = intT->getBitWidth(); assert(signWidth < INT16_MAX && "Integer width too big"); svfIntT->setSignAndWidth(intT->getSignBit() ? -signWidth : signWidth); @@ -1273,14 +1282,14 @@ SVFType* LLVMModuleSet::addSVFTypeInfo(const Type* T) svftype = new SVFFunctionType(getSVFType(ft->getReturnType())); else if (const StructType* st = SVFUtil::dyn_cast(T)) { - auto svfst = new SVFStructType(); + auto svfst = new SVFStructType(byteSize); if (st->hasName()) svfst->setName(st->getName().str()); svftype = svfst; } else if (const auto at = SVFUtil::dyn_cast(T)) { - auto svfat = new SVFArrayType(); + auto svfat = new SVFArrayType(byteSize); svfat->setNumOfElement(at->getNumElements()); svfat->setTypeOfElement(getSVFType(at->getElementType())); svftype = svfat; @@ -1288,7 +1297,7 @@ SVFType* LLVMModuleSet::addSVFTypeInfo(const Type* T) else { std::string buffer; - auto ot = new SVFOtherType(T->isSingleValueType()); + auto ot = new SVFOtherType(byteSize, T->isSingleValueType()); llvm::raw_string_ostream(buffer) << *T; ot->setRepr(std::move(buffer)); svftype = ot; @@ -1303,6 +1312,7 @@ SVFType* LLVMModuleSet::addSVFTypeInfo(const Type* T) assert(svfPtrType && "this is not SVFPointerType"); svfPtrType->setPtrElementType(getSVFType(LLVMUtil::getPtrElementType(pt))); } + return svftype; } diff --git a/svf-llvm/lib/LLVMUtil.cpp b/svf-llvm/lib/LLVMUtil.cpp index d063d2b8b..ece420bef 100644 --- a/svf-llvm/lib/LLVMUtil.cpp +++ b/svf-llvm/lib/LLVMUtil.cpp @@ -1268,15 +1268,6 @@ s64_t LLVMUtil::getCaseValue(const SwitchInst &switchInst, SuccBBAndCondValPair namespace SVF { -// getLLVMByteSize -u32_t SVFType::getLLVMByteSize() const -{ - const llvm::DataLayout &DL = LLVMModuleSet::getLLVMModuleSet()-> - getMainLLVMModule()->getDataLayout(); - const Type* T = LLVMModuleSet::getLLVMModuleSet()->getLLVMType(this); - Type* mut_T = const_cast(T); - return DL.getTypeAllocSize(mut_T); -} std::string SVFValue::toString() const { diff --git a/svf-llvm/lib/SymbolTableBuilder.cpp b/svf-llvm/lib/SymbolTableBuilder.cpp index fecbc8c38..a8b2b1cd7 100644 --- a/svf-llvm/lib/SymbolTableBuilder.cpp +++ b/svf-llvm/lib/SymbolTableBuilder.cpp @@ -818,7 +818,7 @@ void SymbolTableBuilder::initTypeInfo(ObjTypeInfo* typeinfo, const Value* val, if(const ConstantInt* sz = SVFUtil::dyn_cast(allocaInst->getArraySize())) { elemNum = sz->getZExtValue() * getNumOfElements(objTy); - byteSize = sz->getZExtValue() * typeinfo->getType()->getLLVMByteSize(); + byteSize = sz->getZExtValue() * typeinfo->getType()->getByteSize(); } /// if ArraySize is not constant, byteSize is not static determined. else @@ -836,7 +836,7 @@ void SymbolTableBuilder::initTypeInfo(ObjTypeInfo* typeinfo, const Value* val, typeinfo->setFlag(ObjTypeInfo::CONST_GLOBAL_OBJ); analyzeObjType(typeinfo,val); elemNum = getNumOfElements(objTy); - byteSize = typeinfo->getType()->getLLVMByteSize(); + byteSize = typeinfo->getType()->getByteSize(); } /// if val is heap alloc else if (SVFUtil::isa(val) && @@ -858,13 +858,13 @@ void SymbolTableBuilder::initTypeInfo(ObjTypeInfo* typeinfo, const Value* val, analyzeStaticObjType(typeinfo,val); // user input data, label its field as infinite here elemNum = typeinfo->getMaxFieldOffsetLimit(); - byteSize = typeinfo->getType()->getLLVMByteSize(); + byteSize = typeinfo->getType()->getByteSize(); } else if(LLVMUtil::isConstDataOrAggData(val)) { typeinfo->setFlag(ObjTypeInfo::CONST_DATA); elemNum = getNumOfFlattenElements(val->getType()); - byteSize = typeinfo->getType()->getLLVMByteSize(); + byteSize = typeinfo->getType()->getByteSize(); } else { diff --git a/svf/include/AbstractExecution/IntervalValue.h b/svf/include/AbstractExecution/IntervalValue.h index 87909dae0..d115f7a61 100644 --- a/svf/include/AbstractExecution/IntervalValue.h +++ b/svf/include/AbstractExecution/IntervalValue.h @@ -661,9 +661,9 @@ inline IntervalValue operator<(const IntervalValue &lhs, const IntervalValue &rh } // Return [0,0] means lhs is totally impossible to be less than rhs // i.e., lhs is totally greater than or equal to rhs - // When lhs.ub >= rhs.lb, e.g., lhs:[3, 4] rhs:[4,5] - // lhs.ub(4) >= rhs.lb(4) - else if (rhs.ub().geq(lhs.lb())) + // When lhs.lb >= rhs.ub, e.g., lhs:[4,5] rhs:[3,4] + // lhs.lb(4) >= rhs.ub(4) + else if (lhs.lb().geq(rhs.ub())) { return IntervalValue(0, 0); } diff --git a/svf/include/AbstractExecution/SVFIR2ItvExeState.h b/svf/include/AbstractExecution/SVFIR2ItvExeState.h index 79dd6988f..f95d77f50 100644 --- a/svf/include/AbstractExecution/SVFIR2ItvExeState.h +++ b/svf/include/AbstractExecution/SVFIR2ItvExeState.h @@ -74,20 +74,20 @@ class SVFIR2ItvExeState VAddrs getGepObjAddress(u32_t pointer, APOffset offset); /// Return the byte offset from one gep param offset - std::pair getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep); + IntervalValue getByteOffsetfromGepTypePair(const AccessPath::IdxVarAndGepTypePair& gep_pair, const GepStmt *gep); /// Return the Index offset from one gep param offset - std::pair getIndexfromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep); + IntervalValue getItvOfFlattenedElemIndexFromGepTypePair(const AccessPath::IdxVarAndGepTypePair& gep_pair, const GepStmt *gep); /// Return the byte offset expression of a GepStmt /// elemBytesize is the element byte size of an static alloc or heap alloc array /// e.g. GepStmt* gep = [i32*10], x, and x is [0,3] - /// std::pair byteOffset = getGepByteOffset(gep); + /// std::pair byteOffset = getByteOffset(gep); /// byteOffset should be [0, 12] since i32 is 4 bytes. - std::pair getGepByteOffset(const GepStmt *gep); + IntervalValue getByteOffset(const GepStmt *gep); /// Return the offset expression of a GepStmt - std::pair getGepOffset(const GepStmt *gep); + IntervalValue getItvOfFlattenedElemIndex(const GepStmt *gep); static z3::context &getContext() diff --git a/svf/include/MemoryModel/AccessPath.h b/svf/include/MemoryModel/AccessPath.h index 2cc06a9b9..6f36fe460 100644 --- a/svf/include/MemoryModel/AccessPath.h +++ b/svf/include/MemoryModel/AccessPath.h @@ -61,8 +61,8 @@ class AccessPath NonOverlap, Overlap, Subset, Superset, Same }; - typedef std::pair VarAndGepTypePair; - typedef std::vector OffsetVarAndGepTypePairs; + typedef std::pair IdxVarAndGepTypePair; + typedef std::vector IdxVarAndGepTypePairs; /// Constructor AccessPath(APOffset o = 0) : fldIdx(o) {} @@ -103,7 +103,7 @@ class AccessPath { fldIdx = idx; } - inline const OffsetVarAndGepTypePairs& getOffsetVarAndGepTypePairVec() const + inline const IdxVarAndGepTypePairs& getOffsetVarAndGepTypePairVec() const { return offsetVarAndGepTypePairs; } @@ -163,7 +163,8 @@ class AccessPath NodeBS computeAllLocations() const; APOffset fldIdx; ///< Accumulated Constant Offsets - OffsetVarAndGepTypePairs offsetVarAndGepTypePairs; ///< a vector of actual offset in the form of s + IdxVarAndGepTypePairs + offsetVarAndGepTypePairs; ///< a vector of actual offset in the form of s }; } // End namespace SVF @@ -173,7 +174,7 @@ template <> struct std::hash size_t operator()(const SVF::AccessPath &ap) const { SVF::Hash> h; - std::hash v; + std::hash v; return h(std::make_pair(ap.getConstantFieldIdx(), v(ap.getOffsetVarAndGepTypePairVec()))); } diff --git a/svf/include/SVFIR/SVFStatements.h b/svf/include/SVFIR/SVFStatements.h index 39c1c4d01..c99c40f1f 100644 --- a/svf/include/SVFIR/SVFStatements.h +++ b/svf/include/SVFIR/SVFStatements.h @@ -342,6 +342,7 @@ class AddrStmt: public AssignStmt AddrStmt(SVFVar* s, SVFVar* d) : AssignStmt(s, d, SVFStmt::Addr) {} virtual const std::string toString() const override; + }; /*! @@ -491,7 +492,8 @@ class GepStmt: public AssignStmt { return ap; } - inline const AccessPath::OffsetVarAndGepTypePairs getOffsetVarAndGepTypePairVec() const + inline const AccessPath::IdxVarAndGepTypePairs + getOffsetVarAndGepTypePairVec() const { return getAccessPath().getOffsetVarAndGepTypePairVec(); } diff --git a/svf/include/SVFIR/SVFType.h b/svf/include/SVFIR/SVFType.h index 56108fe17..fd4825053 100644 --- a/svf/include/SVFIR/SVFType.h +++ b/svf/include/SVFIR/SVFType.h @@ -264,12 +264,13 @@ class SVFType getPointerToTy; /// Return a pointer to the current type StInfo* typeinfo; ///< SVF's TypeInfo bool isSingleValTy; ///< The type represents a single value, not struct or + u32_t byteSize; ///< LLVM Byte Size ///< array protected: - SVFType(bool svt, SVFTyKind k) + SVFType(bool svt, SVFTyKind k, u32_t Sz) : kind(k), getPointerToTy(nullptr), typeinfo(nullptr), - isSingleValTy(svt) + isSingleValTy(svt), byteSize(Sz) { } @@ -299,7 +300,6 @@ class SVFType return getPointerToTy; } - u32_t getLLVMByteSize() const; inline void setTypeInfo(StInfo* ti) { @@ -318,6 +318,12 @@ class SVFType return typeinfo; } + /// if Type is not sized, byteSize is 0 + /// if Type is sized, byteSize is the LLVM Byte Size. + inline u32_t getByteSize() const { + return byteSize; + } + inline bool isPointerTy() const { return kind == SVFPointerTy; @@ -350,8 +356,8 @@ class SVFPointerType : public SVFType const SVFType* ptrElementType; public: - SVFPointerType() - : SVFType(true, SVFPointerTy), ptrElementType(nullptr) + SVFPointerType(u32_t byteSize) + : SVFType(true, SVFPointerTy, byteSize), ptrElementType(nullptr) { } @@ -382,7 +388,7 @@ class SVFIntegerType : public SVFType short signAndWidth; ///< For printing public: - SVFIntegerType() : SVFType(true, SVFIntegerTy) {} + SVFIntegerType(u32_t byteSize) : SVFType(true, SVFIntegerTy, byteSize) {} static inline bool classof(const SVFType* node) { return node->getKind() == SVFIntegerTy; @@ -411,7 +417,7 @@ class SVFFunctionType : public SVFType public: SVFFunctionType(const SVFType* rt) - : SVFType(false, SVFFunctionTy), retTy(rt) + : SVFType(false, SVFFunctionTy, 0), retTy(rt) { } static inline bool classof(const SVFType* node) @@ -436,7 +442,7 @@ class SVFStructType : public SVFType std::string name; public: - SVFStructType() : SVFType(false, SVFStructTy) {} + SVFStructType(u32_t byteSize) : SVFType(false, SVFStructTy, byteSize) {} static inline bool classof(const SVFType* node) { @@ -469,8 +475,8 @@ class SVFArrayType : public SVFType const SVFType* typeOfElement; /// For printing & debugging public: - SVFArrayType() - : SVFType(false, SVFArrayTy), numOfElement(0), typeOfElement(nullptr) + SVFArrayType(u32_t byteSize) + : SVFType(false, SVFArrayTy, byteSize), numOfElement(0), typeOfElement(nullptr) { } @@ -508,7 +514,7 @@ class SVFOtherType : public SVFType std::string repr; /// Field representation for printing public: - SVFOtherType(bool isSingleValueTy) : SVFType(isSingleValueTy, SVFOtherTy) {} + SVFOtherType(u32_t byteSize, bool isSingleValueTy) : SVFType(isSingleValueTy, SVFOtherTy, byteSize) {} static inline bool classof(const SVFType* node) { diff --git a/svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp b/svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp index 9481abc0a..01b897605 100644 --- a/svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp +++ b/svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp @@ -176,113 +176,120 @@ SVFIR2ItvExeState::VAddrs SVFIR2ItvExeState::getGepObjAddress(u32_t pointer, APO return ret; } -std::pair SVFIR2ItvExeState::getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep) +/** + * This function, getByteOffsetfromGepTypePair, calculates the byte interval value + * for a given IdxVarAndGepTypePair and GepStmt. + * + * @param gep_pair The IdxVarAndGepTypePair containing a value and its type. + * @param gep The GepStmt representing the GetElementPtr instruction. + * + * @return The calculated byte interval value. + * + * e.g. %var2 = getelementptr inbounds %struct.OuterStruct, %struct.OuterStruct* %var0, i64 0, i32 2, i32 0, i64 %var1 + * %struct.OuterStruct = type { i32, i32, %struct.InnerStruct } + * %struct.InnerStruct = type { [2 x i32] } + * there are 4 GepTypePairs (<0, %struct.OuterStruct*>, <2, %struct.OuterStruct>, <0, %struct.InnerStruct>, <%var1, [2xi32]>) + * this function can process one GepTypePairs and return byte offset interval value. + * e.g. for 0th pair <0, %struct.OuterStruct*>, it is 0* ptrSize(%struct.OuterStruct*) = 0 bytes + * for 1st pair <2, %struct.OuterStruct>, it is 2nd field in %struct.OuterStruct = 8 bytes + * for 2nd pair <0, %struct.InnerStruct>, it is 0th field in %struct.InnerStruct = 0 bytes + * for 3rd pair <%var1, [2xi32]>, it is %var1'th element in array [2xi32] = 4bytes * %var1 + * ---- + * for 0th/1st/2nd pair, the SVFValue has constant value + * for 3rd pair, the SVFValue is variable, which needs ES table to calculate the interval. + */ +IntervalValue SVFIR2ItvExeState::getByteOffsetfromGepTypePair(const AccessPath::IdxVarAndGepTypePair& gep_pair, const GepStmt *gep) { + IntervalValue res(0); // Initialize the result interval 'res' to 0. + const SVFValue *value = gep_pair.first->getValue(); const SVFType *type = gep_pair.second; + + // Check the type of 'gep_pair.second' and process it accordingly. if (const SVFArrayType* arrType = SVFUtil::dyn_cast(type)) - { type = arrType->getTypeOfElement(); - } else if (const SVFPointerType* ptrType = SVFUtil::dyn_cast(type)) - { type = ptrType->getPtrElementType(); - } - const SVFConstantInt *op = SVFUtil::dyn_cast(value); - APOffset offsetLb = 0; - APOffset offsetUb = 0; - /// set largest byte offset is 0xFFFFFF in case of int32 overflow - APOffset maxByteLimit = 99999; - APOffset minByteLimit = -99999; - auto valueReshape = [&](s64_t offset) - { - if (offset < (s64_t)minByteLimit) - { - return minByteLimit; - } - else if (offset > (s64_t)maxByteLimit) + else if (const SVFStructType* structType = SVFUtil::dyn_cast(type)) { + // If it's a struct type with a constant index, calculate byte sizes. + if (const SVFConstantInt *op = SVFUtil::dyn_cast(value)) { - return maxByteLimit; + for (u32_t structField = 0; structField < (u32_t)op->getSExtValue(); ++structField) + { + u32_t flattenIdx = structType->getTypeInfo()->getFlattenedFieldIdxVec()[structField]; + res = res + IntervalValue(structType->getTypeInfo()->getOriginalElemType(flattenIdx)->getByteSize()); + } + return res; } else - { - return offset; - } - }; - /// offset is constant but stored in variable - if (op) - { - offsetLb = offsetUb = - op->getSExtValue() * type->getLLVMByteSize() > maxByteLimit - ? maxByteLimit - : op->getSExtValue() * type->getLLVMByteSize(); + assert(false && "struct type can only pair with constant idx"); + } else + assert(false && "gep type pair only support arr/ptr/struct"); + + u32_t typeSz = type->getByteSize(); + + // Calculate byte size based on the type and value, considering MaxFieldLimit option. + if (const SVFConstantInt *op = SVFUtil::dyn_cast(value)) { + u32_t lb = (double)Options::MaxFieldLimit() / typeSz >= op->getSExtValue() ? op->getSExtValue() * typeSz: Options::MaxFieldLimit(); + res = IntervalValue(lb, lb); } - else - { + else { u32_t idx = _svfir->getValueNode(value); - IntervalValue idxVal = _es[idx] * IntervalValue(type->getLLVMByteSize()); - if (idxVal.isBottom() || idxVal.isTop()) - return std::make_pair(0, maxByteLimit); - // if idxVal is a concrete value - if (idxVal.is_numeral()) - { - offsetLb = offsetUb = valueReshape(idxVal.lb().getNumeral()); - } - else - { - offsetLb = valueReshape(idxVal.lb().getNumeral()); - offsetUb = valueReshape(idxVal.ub().getNumeral()); + IntervalValue idxVal = _es[idx] * IntervalValue(type->getByteSize()); + if (idxVal.isBottom()) { + res = IntervalValue(0, 0); + } else { + u32_t ub = (double)Options::MaxFieldLimit() / typeSz >= idxVal.ub().getNumeral() ? typeSz * idxVal.ub().getNumeral(): Options::MaxFieldLimit(); + u32_t lb = (idxVal.lb().getNumeral() < 0) ? 0 : + ((double)Options::MaxFieldLimit() / typeSz >= idxVal.lb().getNumeral()) ? (typeSz * idxVal.lb().getNumeral()) : Options::MaxFieldLimit(); + res = IntervalValue(lb, ub); } } - return {offsetLb, offsetUb}; -} + return res; // Return the resulting byte interval value. +} -std::pair SVFIR2ItvExeState::getIndexfromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep) +/** + * This function, getItvOfFlattenedElemIndexFromGepTypePair, calculates the index range as a pair + * of APOffset values for a given IdxVarAndGepTypePair and GepStmt. + * + * @param gep_pair The IdxVarAndGepTypePair containing a value and its type. + * @param gep The GepStmt representing the GetElementPtr instruction. + * + * @return A pair of APOffset values representing the index range. + */ +IntervalValue SVFIR2ItvExeState::getItvOfFlattenedElemIndexFromGepTypePair(const AccessPath::IdxVarAndGepTypePair& gep_pair, const GepStmt *gep) { const SVFValue *value = gep_pair.first->getValue(); const SVFType *type = gep_pair.second; - const SVFConstantInt *op = SVFUtil::dyn_cast(value); APOffset offsetLb = 0; APOffset offsetUb = 0; APOffset maxFieldLimit = (APOffset)Options::MaxFieldLimit(); APOffset minFieldLimit = 0; - auto valueReshape = [&](s64_t offset) - { - if (offset < minFieldLimit) - { - return minFieldLimit; - } - else if (offset > maxFieldLimit) - { - return maxFieldLimit; - } - else - { - return offset; - } - }; - /// offset is constant but stored in variable - if (op) - { - offsetLb = offsetUb = valueReshape(op->getSExtValue()); - } + + /// If the offset is constant but stored in a variable + if (const SVFConstantInt *op = SVFUtil::dyn_cast(value)) + offsetLb = offsetUb = op->getSExtValue(); else { u32_t idx = _svfir->getValueNode(value); - //if (!inVarToIValTable(idx)) return std::make_pair(-1, -1); IntervalValue &idxVal = _es[idx]; if (idxVal.isBottom() || idxVal.isTop()) - return std::make_pair(0, Options::MaxFieldLimit()); - // if idxVal is a concrete value + return IntervalValue((s64_t)0, (s64_t)Options::MaxFieldLimit()); + // If idxVal is a concrete value if (idxVal.is_numeral()) { - offsetLb = offsetUb = valueReshape(idxVal.lb().getNumeral()); + u32_t constIdxVal = idxVal.getNumeral(); + constIdxVal = (constIdxVal < minFieldLimit) ? minFieldLimit : + (constIdxVal > maxFieldLimit) ? maxFieldLimit : constIdxVal; + offsetLb = offsetUb = constIdxVal; } else { - offsetLb = valueReshape(idxVal.lb().getNumeral()); - offsetUb = valueReshape(idxVal.ub().getNumeral()); + offsetLb = (idxVal.lb().getNumeral() < minFieldLimit) ? minFieldLimit : + (idxVal.lb().getNumeral() > maxFieldLimit) ? maxFieldLimit : idxVal.lb().getNumeral(); + offsetUb = (idxVal.ub().getNumeral() < minFieldLimit) ? minFieldLimit : + (idxVal.ub().getNumeral() > maxFieldLimit) ? maxFieldLimit : idxVal.ub().getNumeral(); } } @@ -296,82 +303,107 @@ std::pair SVFIR2ItvExeState::getIndexfromGepTypePair(const A else { const std::vector& so = SymbolTableInfo::SymbolInfo() - ->getTypeInfo(type) - ->getFlattenedElemIdxVec(); + ->getTypeInfo(type) + ->getFlattenedElemIdxVec(); if (so.empty() || offsetUb >= (APOffset)so.size() || - offsetLb >= (APOffset)so.size()) + offsetLb >= (APOffset)so.size()) { offsetLb = 0; offsetUb = maxFieldLimit; } else { - offsetLb = - SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx( - type, offsetLb); - offsetUb = - SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx( - type, offsetUb); + offsetLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetLb); + offsetUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetUb); } } } - return {offsetLb, offsetUb}; + + return IntervalValue(offsetLb, offsetUb); // Return a pair of APOffset values representing the index range. } -std::pair SVFIR2ItvExeState::getGepByteOffset(const GepStmt *gep) +/** + * This function, getByteOffset, calculates the byte offset for a given GepStmt. + * + * @param gep The GepStmt representing the GetElementPtr instruction. + * + * @return The calculated byte offset as an IntervalValue. + * + * If this getelementptr has constant byte offset, directly call accumulateConstantByteOffset(), + * otherwise, if one or more index in getelementptr is variable. + * e.g. %var2 = getelementptr inbounds %struct.OuterStruct, %struct.OuterStruct* %var0, i64 0, i32 2, i32 0, i64 %var1 +* %struct.OuterStruct = type { i32, i32, %struct.InnerStruct } +* %struct.InnerStruct = type { [2 x i32] } +* there are 4 GepTypePairs (<0, %struct.OuterStruct*>, <2, %struct.OuterStruct>, <0, %struct.InnerStruct>, <%var1, [2xi32]>) +* this function calls getByteOffsetfromGepTypePair() to process each pair, and finally accumulate them. +* e.g. for 0th pair <0, %struct.OuterStruct*>, it is 0* ptrSize(%struct.OuterStruct*) = 0 bytes +* for 1st pair <2, %struct.OuterStruct>, it is 2nd field in %struct.OuterStruct = 8 bytes +* for 2nd pair <0, %struct.InnerStruct>, it is 0th field in %struct.InnerStruct = 0 bytes +* for 3rd pair <%var1, [2xi32]>, it is %var1'th element in array [2xi32] = 4bytes * %var1 +* ---- +* Therefore the final byteoffset is [8+4*var1.lb(), 8+4*var1.ub()] + */ +IntervalValue SVFIR2ItvExeState::getByteOffset(const GepStmt *gep) { - /// for instant constant index, e.g. gep arr, 1 - if (gep->getOffsetVarAndGepTypePairVec().empty()) - return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx()); - APOffset totalOffsetLb = 0; - APOffset totalOffsetUb = 0; - /// default value of MaxFieldLimit is 512 - APOffset maxFieldLimit = 0xFFFFFF; + // Check if the GepStmt has a constant offset. + if (gep->isConstantOffset()) { + // If it has a constant offset, return it as an IntervalValue. + return IntervalValue(gep->accumulateConstantByteOffset()); + } + + IntervalValue res(0); // Initialize the result interval 'res' to 0. + + // Loop through the offsetVarAndGepTypePairVec in reverse order. for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--) { - std::pair offsetIdx = getBytefromGepTypePair( - gep->getOffsetVarAndGepTypePairVec()[i], gep); - APOffset offsetLb = offsetIdx.first; - APOffset offsetUb = offsetIdx.second; - if (totalOffsetLb + offsetLb > maxFieldLimit) - totalOffsetLb = maxFieldLimit; - else - totalOffsetLb += offsetLb; - if (totalOffsetUb + offsetUb > maxFieldLimit) - totalOffsetUb = maxFieldLimit; - else - totalOffsetUb += offsetUb ; + // Calculate the byte offset for the current IdxVarAndGepTypePair. + IntervalValue offsetIdx = getByteOffsetfromGepTypePair( + gep->getOffsetVarAndGepTypePairVec()[i], gep); + + // Accumulate the byte offset in the result 'res'. + res = res + offsetIdx; } - return {totalOffsetLb, totalOffsetUb}; -} + return res; // Return the resulting byte offset as an IntervalValue. +} -std::pair SVFIR2ItvExeState::getGepOffset(const GepStmt *gep) +/** + * This function, getItvOfFlattenedElemIndex, calculates the offset range as a pair + * of APOffset values for a given GepStmt. + * + * @param gep The GepStmt representing the GetElementPtr instruction. + * + * @return A pair of APOffset values representing the offset range. + */ +IntervalValue SVFIR2ItvExeState::getItvOfFlattenedElemIndex(const GepStmt *gep) { - /// for instant constant index, e.g. gep arr, 1 - if (gep->getOffsetVarAndGepTypePairVec().empty()) - return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx()); APOffset totalOffsetLb = 0; APOffset totalOffsetUb = 0; - /// default value of MaxFieldLimit is 512 - APOffset maxFieldLimit = Options::MaxFieldLimit() - 1; - for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--) + + /// Default value of Min/MaxFieldLimit is 0/512 + APOffset minFieldLimit = 0; + APOffset maxFieldLimit = Options::MaxFieldLimit(); + + /// For instant constant index, e.g., gep arr, 1 + if (gep->getOffsetVarAndGepTypePairVec().empty() || gep->isConstantOffset()) { + u32_t offsetIdx = gep->getConstantFieldIdx(); + return IntervalValue(offsetIdx, offsetIdx); + } + else { - std::pair offsetIdx = getIndexfromGepTypePair( - gep->getOffsetVarAndGepTypePairVec()[i], gep); - APOffset offsetLb = offsetIdx.first; - APOffset offsetUb = offsetIdx.second; - if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit) - totalOffsetLb = maxFieldLimit; - else - totalOffsetLb += offsetLb; - if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit) - totalOffsetUb = maxFieldLimit; - else - totalOffsetUb += offsetUb ; + for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--) + { + IntervalValue offsetIdx = getItvOfFlattenedElemIndexFromGepTypePair( + gep->getOffsetVarAndGepTypePairVec()[i], gep); + totalOffsetLb += offsetIdx.lb().getNumeral(); + totalOffsetUb += offsetIdx.ub().getNumeral(); + } + totalOffsetLb = (totalOffsetLb < minFieldLimit) ? minFieldLimit : + (totalOffsetLb > maxFieldLimit) ? maxFieldLimit : totalOffsetLb; } - return {totalOffsetLb, totalOffsetUb}; + + return IntervalValue(totalOffsetLb, totalOffsetUb); // Return a pair of APOffset values representing the offset range. } /*! @@ -383,7 +415,6 @@ void SVFIR2ItvExeState::initValVar(const ValVar *valVar, u32_t varId) { SVFIR *svfir = PAG::getPAG(); - if (const SVFType *type = valVar->getType()) { // TODO:miss floatpointerty, voidty, labelty, matadataty @@ -431,35 +462,21 @@ void SVFIR2ItvExeState::initObjVar(const ObjVar *objVar, u32_t varId) IntervalExeState::globalES[varId] = IntervalValue(numeral, numeral); } else if (const SVFConstantFP* consFP = SVFUtil::dyn_cast(obj->getValue())) - { IntervalExeState::globalES[varId] = IntervalValue(consFP->getFPValue(), consFP->getFPValue()); - } else if (SVFUtil::isa(obj->getValue())) - { IntervalExeState::globalES[varId] = IntervalValue(0, 0); - } else if (SVFUtil::isa(obj->getValue())) - { IntervalExeState::globalES.getVAddrs(varId).insert(getVirtualMemAddress(varId)); - } else if (obj->isConstantArray() || obj->isConstantStruct()) - { IntervalExeState::globalES[varId] = IntervalValue::top(); - } else - { IntervalExeState::globalES[varId] = IntervalValue::top(); - } } else - { IntervalExeState::globalES.getVAddrs(varId).insert(getVirtualMemAddress(varId)); - } } else - { IntervalExeState::globalES.getVAddrs(varId).insert(getVirtualMemAddress(varId)); - } } void SVFIR2ItvExeState::initSVFVar(u32_t varId) @@ -856,24 +873,18 @@ void SVFIR2ItvExeState::translateGep(const GepStmt *gep) assert(!getVAddrs(rhs).empty()); VAddrs &rhsVal = getVAddrs(rhs); if (rhsVal.empty()) return; - std::pair offsetPair = getGepOffset(gep); - if (offsetPair.first == -1 && offsetPair.second == -1) return; + IntervalValue offsetPair = getItvOfFlattenedElemIndex(gep); if (!isVirtualMemAddress(*rhsVal.begin())) - { return; - } else { VAddrs gepAddrs; - APOffset ub = offsetPair.second; - if (offsetPair.second > Options::MaxFieldLimit() - 1) - { - ub = Options::MaxFieldLimit() - 1; - } - for (APOffset i = offsetPair.first; i <= ub; i++) - { + APOffset lb = offsetPair.lb().getNumeral() < Options::MaxFieldLimit()? + offsetPair.lb().getNumeral(): Options::MaxFieldLimit(); + APOffset ub = offsetPair.ub().getNumeral() < Options::MaxFieldLimit()? + offsetPair.ub().getNumeral(): Options::MaxFieldLimit(); + for (APOffset i = lb; i <= ub; i++) gepAddrs.join_with(getGepObjAddress(rhs, i)); - } if(gepAddrs.empty()) return; _es.getVAddrs(lhs) = gepAddrs; return; diff --git a/svf/lib/MemoryModel/AccessPath.cpp b/svf/lib/MemoryModel/AccessPath.cpp index 724a792f9..fa1cf9264 100644 --- a/svf/lib/MemoryModel/AccessPath.cpp +++ b/svf/lib/MemoryModel/AccessPath.cpp @@ -140,16 +140,17 @@ APOffset AccessPath::computeConstantByteOffset() const { u32_t flattenIdx = structType->getTypeInfo()->getFlattenedFieldIdxVec()[structField]; type2 = structType->getTypeInfo()->getOriginalElemType(flattenIdx); - totalConstOffset += type2->getLLVMByteSize(); + totalConstOffset += type2->getByteSize(); } } else { /// for (2) i = 0, op: 0, type: [10 x i8]*(Ptr), type2: [10 x i8](Arr) /// i = 1, op: 8, type: [10 x i8](Arr), type2: i8 - totalConstOffset += op->getSExtValue() * type2->getLLVMByteSize(); + totalConstOffset += op->getSExtValue() * type2->getByteSize(); } } + totalConstOffset = Options::MaxFieldLimit() > totalConstOffset? totalConstOffset: Options::MaxFieldLimit(); return totalConstOffset; } @@ -246,14 +247,14 @@ bool AccessPath::operator< (const AccessPath& rhs) const return (fldIdx < rhs.fldIdx); else { - const OffsetVarAndGepTypePairs& pairVec = getOffsetVarAndGepTypePairVec(); - const OffsetVarAndGepTypePairs& rhsPairVec = rhs.getOffsetVarAndGepTypePairVec(); + const IdxVarAndGepTypePairs& pairVec = getOffsetVarAndGepTypePairVec(); + const IdxVarAndGepTypePairs& rhsPairVec = rhs.getOffsetVarAndGepTypePairVec(); if (pairVec.size() != rhsPairVec.size()) return (pairVec.size() < rhsPairVec.size()); else { - OffsetVarAndGepTypePairs::const_iterator it = pairVec.begin(); - OffsetVarAndGepTypePairs::const_iterator rhsIt = rhsPairVec.begin(); + IdxVarAndGepTypePairs::const_iterator it = pairVec.begin(); + IdxVarAndGepTypePairs::const_iterator rhsIt = rhsPairVec.begin(); for (; it != pairVec.end() && rhsIt != rhsPairVec.end(); ++it, ++rhsIt) { return (*it) < (*rhsIt); @@ -293,9 +294,9 @@ std::string AccessPath::dump() const rawstr << "AccessPath\tField_Index: " << getConstantFieldIdx(); rawstr << ",\tNum-Stride: {"; - const OffsetVarAndGepTypePairs& vec = getOffsetVarAndGepTypePairVec(); - OffsetVarAndGepTypePairs::const_iterator it = vec.begin(); - OffsetVarAndGepTypePairs::const_iterator eit = vec.end(); + const IdxVarAndGepTypePairs& vec = getOffsetVarAndGepTypePairVec(); + IdxVarAndGepTypePairs::const_iterator it = vec.begin(); + IdxVarAndGepTypePairs::const_iterator eit = vec.end(); for (; it != eit; ++it) { const SVFType* ty = it->second; diff --git a/svf/lib/SVFIR/SVFFileSystem.cpp b/svf/lib/SVFIR/SVFFileSystem.cpp index e4354942e..6c9a879cd 100644 --- a/svf/lib/SVFIR/SVFFileSystem.cpp +++ b/svf/lib/SVFIR/SVFFileSystem.cpp @@ -24,21 +24,21 @@ SVFType* createSVFType(SVFType::GNodeK kind, bool isSingleValTy) ABORT_MSG("Creation of RAW SVFType isn't allowed"); case SVFType::SVFPointerTy: ABORT_IFNOT(isSingleValTy, "Pointer type must be single-valued"); - return new SVFPointerType(); + return new SVFPointerType(0); case SVFType::SVFIntegerTy: ABORT_IFNOT(isSingleValTy, "Integer type must be single-valued"); - return new SVFIntegerType(); + return new SVFIntegerType(0); case SVFType::SVFFunctionTy: ABORT_IFNOT(!isSingleValTy, "Function type must be multi-valued"); return new SVFFunctionType(nullptr); case SVFType::SVFStructTy: ABORT_IFNOT(!isSingleValTy, "Struct type must be multi-valued"); - return new SVFStructType(); + return new SVFStructType(0); case SVFType::SVFArrayTy: ABORT_IFNOT(!isSingleValTy, "Array type must be multi-valued"); - return new SVFArrayType(); + return new SVFArrayType(0); case SVFType::SVFOtherTy: - return new SVFOtherType(isSingleValTy); + return new SVFOtherType(0, isSingleValTy); } } diff --git a/svf/lib/SVFIR/SVFType.cpp b/svf/lib/SVFIR/SVFType.cpp index bbeece58e..b43d7ca20 100644 --- a/svf/lib/SVFIR/SVFType.cpp +++ b/svf/lib/SVFIR/SVFType.cpp @@ -4,13 +4,6 @@ namespace SVF { -__attribute__((weak)) -u32_t SVFType::getLLVMByteSize() const -{ - assert("SVFType::getLLVMByteSize should be implemented or supported by fronted" && false); - abort(); -} - __attribute__((weak)) std::string SVFType::toString() const {