8000 fix getgepoffset and accumulateconstantOffset by bjjwwang · Pull Request #1184 · SVF-tools/SVF · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix getgepoffset and accumulateconstantOffset #1184

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

Merged
merged 3 commits into from
Sep 6, 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
13 changes: 13 additions & 0 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,19 @@ std::vector<const Function *> getCalledFunctions(const Function *F);
std::vector<std::string> getFunAnnotations(const Function* fun);
void removeFunAnnotations(std::vector<Function*>& removedFuncList);

inline u32_t SVFType2ByteSize(const SVFType* type) {
const llvm::Type* llvm_rhs = LLVMModuleSet::getLLVMModuleSet()->getLLVMType(type);
u32_t llvm_rhs_size = LLVMUtil::getTypeSizeInBytes(llvm_rhs->getPointerElementType());
u32_t llvm_elem_size = -1;
if (llvm_rhs->getPointerElementType()->isArrayTy() && llvm_rhs_size > 0) {
size_t array_len = llvm_rhs->getPointerElementType()->getArrayNumElements();
llvm_elem_size = llvm_rhs_size / array_len;
} else {
llvm_elem_size =llvm_rhs_size;
}
return llvm_elem_size;
}

inline void removeUnusedFuncsAndAnnotations(std::vector<Function*> removedFuncList)
{
/// Remove unused function annotations in extapi.bc
Expand Down
14 changes: 14 additions & 0 deletions svf/include/AbstractExecution/SVFIR2ItvExeState.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,23 @@ class SVFIR2ItvExeState
/// Return the field address given a pointer points to a struct object and an offset
VAddrs getGepObjAddress(u32_t pointer, s32_t offset);

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

/// Return the Index offset from one gep param offset
std::pair<s32_t, s32_t> 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<s32_t, s32_t> getGepByteOffset(const GepStmt *gep, s32_t elemBytesize);

/// Return the offset expression of a GepStmt
std::pair<s32_t, s32_t> getGepOffset(const GepStmt *gep);


static z3::context &getContext()
{
return Z3Expr::getContext();
Expand Down
6 changes: 6 additions & 0 deletions svf/include/MemoryModel/AccessPath.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ 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;
/// Return accumulated constant offset given OffsetVarVec
APOffset computeConstantOffset() const;

Expand Down
10 changes: 10 additions & 0 deletions svf/include/SVFIR/SVFStatements.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,16 @@ class GepStmt: public AssignStmt
{
return getAccessPath().isConstantOffset();
}
/// Return accumulated constant offset (when accessing array or struct) if this offset is a constant.
/// 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);
inline APOffset accumulateConstantByteOffset(u32_t elemBytesize) const
{
return getAccessPath().computeConstantByteOffset(elemBytesize);
}

/// Return accumulated constant offset (when accessing array or struct) if this offset is a constant.
inline APOffset accumulateConstantOffset() const
{
Expand Down
225 changes: 142 additions & 83 deletions svf/lib/AbstractExecution/SVFIR2ItvExeState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,108 +173,167 @@ SVFIR2ItvExeState::VAddrs SVFIR2ItvExeState::getGepObjAddress(u32_t pointer, s32
return ret;
}

std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep)
{
std::pair<s32_t, s32_t> SVFIR2ItvExeState::getBytefromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep, s32_t elemBytesize) {
const SVFValue *value = gep_pair.first->getValue();
const SVFType *type = gep_pair.second;
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
s32_t offsetLb = 0;
s32_t offsetUb = 0;
/// set largest byte offset is 0xFFFFFF in case of int32 overflow
s32_t maxFieldLimit = 0xFFFFFF;
/// offset is constant but stored in variable
if (op)
{
offsetLb = offsetUb = op->getSExtValue() >
maxFieldLimit? maxFieldLimit: op->getSExtValue();
} else {
u32_t idx = _svfir->getValueNode(value);
IntervalValue &idxVal = _es[idx];
if (idxVal.isBottom() || idxVal.isTop())
return std::make_pair(0, maxFieldLimit);
// if idxVal is a concrete value
if (idxVal.is_numeral())
{
offsetLb = offsetUb = idxVal.lb().getNumeral()>
maxFieldLimit? maxFieldLimit: idxVal.lb().getNumeral();
} else {
offsetLb = idxVal.lb().getNumeral()> maxFieldLimit? maxFieldLimit:idxVal.lb().getNumeral() * elemBytesize ;
offsetUb = idxVal.ub().getNumeral() > maxFieldLimit? maxFieldLimit:id EDBE xVal.ub().getNumeral() * elemBytesize;
}
}

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};
}


std::pair<s32_t, s32_t> SVFIR2ItvExeState::getIndexfromGepTypePair(const AccessPath::VarAndGepTypePair& gep_pair, const GepStmt *gep) {
const SVFValue *value = gep_pair.first->getValue();
const SVFType *type = gep_pair.second;
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
s32_t offsetLb = 0;
s32_t offsetUb = 0;
s32_t maxFieldLimit = (s32_t)Options::MaxFieldLimit();
/// offset is constant but stored in variable
if (op)
{
offsetLb = offsetUb = op->getSExtValue() >
maxFieldLimit? maxFieldLimit: 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, (s32_t)Options::MaxFieldLimit());
// if idxVal is a concrete value
if (idxVal.is_numeral())
{
offsetLb = offsetUb = idxVal.lb().getNumeral()>
maxFieldLimit? maxFieldLimit: idxVal.lb().getNumeral();
} else {
offsetLb = idxVal.lb().getNumeral() < 0
? 0
: idxVal.lb().getNumeral();
offsetLb = idxVal.lb().getNumeral() > maxFieldLimit
? maxFieldLimit
: offsetLb;
offsetUb = idxVal.ub().getNumeral() < 0
? 0
: idxVal.ub().getNumeral();
offsetUb = idxVal.ub().getNumeral() > maxFieldLimit
? maxFieldLimit
: offsetUb;
}
}

if (type) {
if (const SVFPointerType *pty = SVFUtil::dyn_cast<SVFPointerType>(type)) {
offsetLb = offsetLb * gep->getAccessPath().getElementNum(pty->getPtrElementType());
offsetUb = offsetUb * gep->getAccessPath().getElementNum(pty->getPtrElementType());
}
else {
const std::vector<u32_t>& so = SymbolTableInfo::SymbolInfo()
->getTypeInfo(type)
->getFlattenedElemIdxVec();
if (so.empty() || (u32_t)offsetUb >= so.size() ||
(u32_t)offsetLb >= so.size())
{
offsetLb = 0;
offsetUb = maxFieldLimit;
} else {
offsetLb =
SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(
type, offsetLb);
offsetUb =
SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(
type, offsetUb);
}
}
}
return {offsetLb, offsetUb};
}


std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepByteOffset(const GepStmt *gep, s32_t elemBytesize) {
/// for instant constant index, e.g. gep arr, 1
if (gep->getOffsetVarAndGepTypePairVec().empty())
return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx());

s32_t totalOffsetLb = 0;
s32_t totalOffsetUb = 0;
/// default value of MaxFieldLimit is 512
u32_t maxFieldLimit = Options::MaxFieldLimit() - 1;
/// for variable index and nested indexes, e.g. 1) gep arr, idx 2) gep arr idx0, idx1
u32_t maxFieldLimit = 0xFFFFFF;
for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
{
const SVFValue *value = gep->getOffsetVarAndGepTypePairVec()[i].first->getValue();
const SVFType *type = gep->getOffsetVarAndGepTypePairVec()[i].second;
const SVFConstantInt *op = SVFUtil::dyn_cast<SVFConstantInt>(value);
s32_t offsetLb = 0;
s32_t offsetUb = 0;
/// offset is constant but stored in variable
if (op)
{
offsetLb = offsetUb = op->getSExtValue();
}
/// offset is variable, the concrete value isn't sure util runtime, and maybe not a concrete value.
/// e.g.
std::pair<s32_t, s32_t> offsetIdx = getBytefromGepTypePair(
gep->getOffsetVarAndGepTypePairVec()[i], gep, elemBytesize);
s32_t offsetLb = offsetIdx.first;
s32_t offsetUb = offsetIdx.second;
if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
totalOffsetLb = maxFieldLimit;
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, (s32_t)Options::MaxFieldLimit());
// if idxVal is a concrete value
if (idxVal.is_numeral())
{
offsetLb = offsetUb = idxVal.lb().getNumeral();
}
else
{
// if inxVal is an interval. we should make sure that idxVal.lb>0 && idxVal.ub<MaxFieldLimit
offsetLb = idxVal.lb().getNumeral() < 0 ? 0 : idxVal.lb().getNumeral();
offsetLb = idxVal.lb().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetLb;
offsetUb = idxVal.ub().getNumeral() < 0 ? 0 : idxVal.ub().getNumeral();
offsetUb = idxVal.ub().getNumeral() > maxFieldLimit ? maxFieldLimit : offsetUb;
}
}
if (type == nullptr)
{
if ((long long) (totalOffsetLb + offsetLb) > maxFieldLimit)
{
totalOffsetLb = maxFieldLimit;
}
else
{
totalOffsetLb += offsetLb;
}

if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
{
totalOffsetUb = maxFieldLimit;
}
else
{
totalOffsetUb += offsetUb;
}
continue;
}
totalOffsetLb += offsetLb;
if ((long long) (totalOffsetUb + offsetUb) > maxFieldLimit)
totalOffsetUb = maxFieldLimit;
else
totalOffsetUb += offsetUb ;
}
return {totalOffsetLb, totalOffsetUb};
}

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

}
else
{
const std::vector<u32_t> &so = SymbolTableInfo::SymbolInfo()->getTypeInfo(type)->getFlattenedElemIdxVec();
if (so.empty() || (u32_t) offsetUb >= so.size() || (u32_t) offsetLb >= so.size())
return std::make_pair(-1, -1);
offsetLb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetLb);
offsetUb = SymbolTableInfo::SymbolInfo()->getFlattenedElemIdx(type, offsetUb);
}
std::pair<s32_t, s32_t> SVFIR2ItvExeState::getGepOffset(const GepStmt *gep) {
/// for instant constant index, e.g. gep arr, 1
if (gep->getOffsetVarAndGepTypePairVec().empty())
return std::make_pair(gep->getConstantFieldIdx(), gep->getConstantFieldIdx());
s32_t totalOffsetLb = 0;
s32_t totalOffsetUb = 0;
/// default value of MaxFieldLimit is 512
u32_t maxFieldLimit = Options::MaxFieldLimit() - 1;
for (int i = gep->getOffsetVarAndGepTypePairVec().size() - 1; i >= 0; i--)
{
std::pair<s32_t, s32_t> offsetIdx = getIndexfromGepTypePair(
gep->getOffsetVarAndGepTypePairVec()[i], gep);
s32_t offsetLb = offsetIdx.first;
s32_t 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;
}
totalOffsetUb += offsetUb ;
}
std::pair<s32_t, s32_t> offSetPair;
offSetPair.first = totalOffsetLb;
offSetPair.second = totalOffsetUb;
return offSetPair;
return {totalOffsetLb, totalOffsetUb};
}

/*!
Expand Down
39 changes: 39 additions & 0 deletions svf/lib/MemoryModel/AccessPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,45 @@ u32_t AccessPath::getElementNum(const SVFType* type) const
}
}

/// Return accumulated constant offset
///
/// "value" is the offset variable (must be a constant)
/// "type" is the location where we want to compute offset
/// 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
{
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;
}

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;
}
}
return totalConstOffset;
}

/// Return accumulated constant offset
///
/// "value" is the offset variable (must be a constant)
Expand Down
0