Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix getByteOffsets in GepStmt and SVFIR2ItvExeState #1240

Merged
merged 4 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,15 @@ 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<Type*>(T);
return DL.getTypeAllocSize(mut_T);
}

std::string SVFValue::toString() const
{
std::string str;
Expand Down
40 changes: 40 additions & 0 deletions svf-llvm/tools/Example/svf-ex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
*/

#include "SVF-LLVM/LLVMUtil.h"
#include "AbstractExecution/SVFIR2ItvExeState.h"
#include "Graphs/SVFG.h"
#include "WPA/Andersen.h"
#include "SVF-LLVM/SVFIRBuilder.h"
Expand Down Expand Up @@ -70,6 +71,44 @@ std::string printPts(PointerAnalysis* pta, SVFValue* val)

}

/*!
* An example to query/collect all SVFStmt from a ICFGNode (iNode)
*/
void traverseOnSVFStmt(const ICFGNode* node) {
SVFIR2ItvExeState* svfir2ExeState = new SVFIR2ItvExeState(SVFIR::getPAG());
for (const SVFStmt* stmt: node->getSVFStmts()) {
if (const AddrStmt *addr = SVFUtil::dyn_cast<AddrStmt>(stmt)) {
svfir2ExeState->translateAddr(addr);
} else if (const BinaryOPStmt *binary = SVFUtil::dyn_cast<BinaryOPStmt>(stmt)) {
svfir2ExeState->translateBinary(binary);
} else if (const CmpStmt *cmp = SVFUtil::dyn_cast<CmpStmt>(stmt)) {
svfir2ExeState->translateCmp(cmp);
} else if (const LoadStmt *load = SVFUtil::dyn_cast<LoadStmt>(stmt)) {
svfir2ExeState->translateLoad(load);
} else if (const StoreStmt *store = SVFUtil::dyn_cast<StoreStmt>(stmt)) {
svfir2ExeState->translateStore(store);
} else if (const CopyStmt *copy = SVFUtil::dyn_cast<CopyStmt>(stmt)) {
svfir2ExeState->translateCopy(copy);
} else if (const GepStmt *gep = SVFUtil::dyn_cast<GepStmt>(stmt)) {
if (gep->isConstantOffset()) {
gep->accumulateConstantByteOffset();
gep->accumulateConstantOffset();
}
svfir2ExeState->translateGep(gep);
} else if (const SelectStmt *select = SVFUtil::dyn_cast<SelectStmt>(stmt)) {
svfir2ExeState->translateSelect(select);
} else if (const PhiStmt *phi = SVFUtil::dyn_cast<PhiStmt>(stmt)) {
svfir2ExeState->translatePhi(phi);
} else if (const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt)) {
// To handle Call Edge
svfir2ExeState->translateCall(callPE);
} else if (const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt)) {
svfir2ExeState->translateRet(retPE);
} else
assert(false && "implement this part");
}
}


/*!
* An example to query/collect all successor nodes from a ICFGNode (iNode) along control-flow graph (ICFG)
Expand All @@ -90,6 +129,7 @@ void traverseOnICFG(ICFG* icfg, const SVFInstruction* svfInst)
{
ICFGEdge* edge = *it;
ICFGNode* succNode = edge->getDstNode();
traverseOnSVFStmt(succNode);
if (visited.find(succNode) == visited.end())
{
visited.insert(succNode);
Expand Down
10 changes: 5 additions & 5 deletions svf/include/AbstractExecution/SVFIR2ItvExeState.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ class SVFIR2ItvExeState
VAddrs getGepObjAddress(u32_t pointer, APOffset offset);

/// Return the byte offset from one gep param offset
std::pair<APOffset, APOffset> getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep, APOffset elem_bytesize);
std::pair<APOffset, APOffset> getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep);

/// Return the Index offset from one gep param offset
std::pair<APOffset, APOffset> getIndexfromGepTypePair(const AccessPath::VarAndGepTypePair& 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 = **,
/// s32_t elemBytesize = LLVMUtil::SVFType2ByteSize(gep->getRHSVar()->getValue()->getType());
/// std::pair<s32_t, s32_t> byteOffset = getGepByteOffset(gep, elemBytesize);
std::pair<APOffset, APOffset> getGepByteOffset(const GepStmt *gep, APOffset elemBytesize);
/// e.g. GepStmt* gep = [i32*10], x, and x is [0,3]
/// std::pair<s32_t, s32_t> byteOffset = getGepByteOffset(gep);
/// byteOffset should be [0, 12] since i32 is 4 bytes.
std::pair<APOffset, APOffset> getGepByteOffset(const GepStmt *gep);

/// Return the offset expression of a GepStmt
std::pair<APOffset, APOffset> getGepOffset(const GepStmt *gep);
Expand Down
30 changes: 24 additions & 6 deletions svf/include/MemoryModel/AccessPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,31 @@ class AccessPath
}
//@}

/// Return accumulated constant byte offset given OffsetVarVec and elemByteSize
/// elemBytesize is the element byte size of an static alloc or heap alloc array
/// e.g. GepStmt* gep = **,
/// s32_t elemBytesize = LLVMUtil::SVFType2ByteSize(gep->getRHSVar()->getValue()->getType());
/// APOffset byteOffset = gep->accumulateConstantByteOffset(elemBytesize);
APOffset computeConstantByteOffset(u32_t elemBytesize) const;
/**
* Computes the total constant byte offset of an access path.
* This function iterates over the offset-variable-type pairs in reverse order,
* accumulating the total byte offset for constant offsets. For each pair,
* it retrieves the corresponding SVFValue and determines the type of offset
* (whether it's an array, pointer, or structure). If the offset corresponds
* to a structure, it further resolves the actual element type based on the
* offset value. It then multiplies the offset value by the size of the type
* to compute the byte offset. This is used to handle composite types where
* offsets are derived from the type's internal structure, such as arrays
* or structures with fields of various types and sizes. The function asserts
* that the access path must have a constant offset, and it is intended to be
* used when the offset is known to be constant at compile time.
*
* @return APOffset representing the computed total constant byte offset.
*/
/// e.g. GepStmt* gep = [i32*4], 2
/// APOffset byteOffset = gep->accumulateConstantByteOffset();
/// byteOffset should be 8 since i32 is 4 bytes and index is 2.
APOffset computeConstantByteOffset() const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to explain a bit more about this method since the argument has been removed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the argument is no longer needed.

/// Return accumulated constant offset given OffsetVarVec
/// compard to computeConstantByteOffset, it is field offset rather than byte offset
/// e.g. GepStmt* gep = [i32*4], 2
/// APOffset byteOffset = gep->computeConstantOffset();
/// byteOffset should be 2 since it is field offset.
APOffset computeConstantOffset() const;

/// Return element number of a type.
Expand Down
4 changes: 2 additions & 2 deletions svf/include/SVFIR/SVFStatements.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,9 @@ class GepStmt: public AssignStmt
/// e.g. GepStmt* gep = **,
/// s32_t elemBytesize = LLVMUtil::SVFType2ByteSize(gep->getRHSVar()->getValue()->getType());
/// APOffset byteOffset = gep->accumulateConstantByteOffset(elemBytesize);
inline APOffset accumulateConstantByteOffset(u32_t elemBytesize) const
inline APOffset accumulateConstantByteOffset() const
{
return getAccessPath().computeConstantByteOffset(elemBytesize);
return getAccessPath().computeConstantByteOffset();
}

/// Return accumulated constant offset (when accessing array or struct) if this offset is a constant.
Expand Down
18 changes: 18 additions & 0 deletions svf/include/SVFIR/SVFType.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ class SVFType
return getPointerToTy;
}

u32_t getLLVMByteSize() const;

inline void setTypeInfo(StInfo* ti)
{
typeinfo = ti;
Expand All @@ -321,6 +323,16 @@ class SVFType
return kind == SVFPointerTy;
}

inline bool isArrayTy() const
{
return kind == SVFArrayTy;
}

inline bool isStructTy() const
{
return kind == SVFStructTy;
}

inline bool isSingleValueType() const
{
return isSingleValTy;
Expand Down Expand Up @@ -462,6 +474,10 @@ class SVFArrayType : public SVFType

void print(std::ostream& os) const override;

const SVFType* getTypeOfElement() const {
return typeOfElement;
}

void setTypeOfElement(const SVFType* elemType)
{
typeOfElement = elemType;
Expand All @@ -471,6 +487,8 @@ class SVFArrayType : public SVFType
{
numOfElement = elemNum;
}


};

class SVFOtherType : public SVFType
Expand Down
35 changes: 14 additions & 21 deletions svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,16 @@ SVFIR2ItvExeState::VAddrs SVFIR2ItvExeState::getGepObjAddress(u32_t pointer, APO
return ret;
}

std::pair<APOffset, APOffset> SVFIR2ItvExeState::getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep, APOffset elemBytesize)
std::pair<APOffset, APOffset> SVFIR2ItvExeState::getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep)
{
const SVFValue *value = gep_pair.first->getValue();
const SVFType *type = gep_pair.second;
if (const SVFArrayType* arrType = SVFUtil::dyn_cast<SVFArrayType>(type)) {
type = arrType->getTypeOfElement();
}
else if (const SVFPointerType* ptrType = SVFUtil::dyn_cast<SVFPointerType>(type)) {
type = ptrType->getPtrElementType();
}
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
APOffset offsetLb = 0;
APOffset offsetUb = 0;
Expand All @@ -204,14 +210,15 @@ std::pair<APOffset, APOffset> SVFIR2ItvExeState::getBytefromGepTypePair(const Ac
/// offset is constant but stored in variable
if (op)
{
offsetLb = offsetUb = op->getSExtValue() > maxByteLimit
? maxByteLimit
: op->getSExtValue();
offsetLb = offsetUb =
op->getSExtValue() * type->getLLVMByteSize() > maxByteLimit
? maxByteLimit
: op->getSExtValue() * type->getLLVMByteSize();
}
else
{
u32_t idx = _svfir->getValueNode(value);
IntervalValue &idxVal = _es[idx];
IntervalValue idxVal = _es[idx] * IntervalValue(type->getLLVMByteSize());
if (idxVal.isBottom() || idxVal.isTop())
return std::make_pair(0, maxByteLimit);
// if idxVal is a concrete value
Expand All @@ -225,20 +232,6 @@ std::pair<APOffset, APOffset> SVFIR2ItvExeState::getBytefromGepTypePair(const Ac
offsetUb = valueReshape(idxVal.ub().getNumeral());
}
}

if (type)
{
if (const SVFPointerType *pty = SVFUtil::dyn_cast<SVFPointerType>(type))
{
offsetLb = offsetLb * gep->getAccessPath().getElementNum(pty->getPtrElementType())* elemBytesize;
offsetUb = offsetUb * gep->getAccessPath().getElementNum(pty->getPtrElementType())* elemBytesize;
}
else
{
offsetLb = offsetLb * elemBytesize;
offsetUb = offsetUb * elemBytesize;
}
}
return {offsetLb, offsetUb};
}

Expand Down Expand Up @@ -324,7 +317,7 @@ std::pair<APOffset, APOffset> SVFIR2ItvExeState::getIndexfromGepTypePair(const A
}


std::pair<APOffset, APOffset> SVFIR2ItvExeState::getGepByteOffset(const GepStmt *gep, APOffset elemBytesize)
std::pair<APOffset, APOffset> SVFIR2ItvExeState::getGepByteOffset(const GepStmt *gep)
{
/// for instant constant index, e.g. gep arr, 1
if (gep->getOffsetVarAndGepTypePairVec().empty())
Expand All @@ -336,7 +329,7 @@ std::pair<APOffset, APOffset> SVFIR2ItvExeState::getGepByteOffset(const GepStmt
for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
{
std::pair<APOffset, APOffset> offsetIdx = getBytefromGepTypePair(
gep->getOffsetVarAndGepTypePairVec()[i], gep, elemBytesize);
gep->getOffsetVarAndGepTypePairVec()[i], gep);
APOffset offsetLb = offsetIdx.first;
APOffset offsetUb = offsetIdx.second;
if (totalOffsetLb + offsetLb > maxFieldLimit)
Expand Down
30 changes: 13 additions & 17 deletions svf/lib/MemoryModel/AccessPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,33 +94,29 @@ u32_t AccessPath::getElementNum(const SVFType* type) const
/// Given a vector and elem byte size: [(value1,type1), (value2,type2), (value3,type3)], bytesize
/// totalConstByteOffset = ByteOffset(value1,type1) * ByteOffset(value2,type2) + ByteOffset(value3,type3)
/// For a pointer type (e.g., t1 is PointerType), we will retrieve the pointee type and times the offset, i.e., getElementNum(t1) X off1
APOffset AccessPath::computeConstantByteOffset(u32_t elemBytesize) const
APOffset AccessPath::computeConstantByteOffset() const
{
assert(isConstantOffset() && "not a constant offset");

if(offsetVarAndGepTypePairs.empty())
return getConstantFieldIdx() * elemBytesize;

APOffset totalConstOffset = 0;
for(int i = offsetVarAndGepTypePairs.size() - 1; i >= 0; i--)
{
const SVFValue* value = offsetVarAndGepTypePairs[i].first->getValue();
const SVFType* type = offsetVarAndGepTypePairs[i].second;
const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(value);
assert(op && "not a constant offset?");
if(type==nullptr)
{
totalConstOffset += op->getSExtValue() * elemBytesize;
continue;
const SVFType* type2 = type;
if (const SVFArrayType* arrType = SVFUtil::dyn_cast<SVFArrayType>(type)) {
type2 = arrType->getTypeOfElement();
}
else if (const SVFPointerType* ptrType = SVFUtil::dyn_cast<SVFPointerType>(type)) {
type2 = ptrType->getPtrElementType();
}

if(const SVFPointerType* pty = SVFUtil::dyn_cast<SVFPointerType>(type))
totalConstOffset += op->getSExtValue() * getElementNum(pty->getPtrElementType()) * elemBytesize;
else
{
APOffset offset = op->getSExtValue();
// if getByteOffset is false, it will retrieve flatten idx
totalConstOffset += offset * elemBytesize;
const SVFConstantInt* op = SVFUtil::dyn_cast<SVFConstantInt>(value);
if (const SVFStructType* structType = SVFUtil::dyn_cast<SVFStructType>(type)) {
type2 = structType->getTypeInfo()->getOriginalElemType(op->getSExtValue());
totalConstOffset += type2->getLLVMByteSize();
} else {
totalConstOffset += op->getSExtValue() * type2->getLLVMByteSize();
}
}
return totalConstOffset;
Expand Down
6 changes: 6 additions & 0 deletions svf/lib/SVFIR/SVFType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
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
{
Expand Down
Loading