Skip to content

Commit

Permalink
Merge pull request #1355 from shuangxiangkan/master
Browse files Browse the repository at this point in the history
Add opaque pointer in extapi
  • Loading branch information
yuleisui authored Feb 1, 2024
2 parents 0e56bc0 + f5437f1 commit 9e94966
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 85 deletions.
6 changes: 5 additions & 1 deletion svf-llvm/include/SVF-LLVM/LLVMModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class LLVMModuleSet
typedef Map<const SVFValue*, const Value*> SVFValue2LLVMValueMap;
typedef Map<const Type*, SVFType*> LLVMType2SVFTypeMap;
typedef Map<const Type*, StInfo*> Type2TypeInfoMap;
typedef Map<const Function*, std::vector<std::string>> Fun2AnnoMap;

private:
static LLVMModuleSet* llvmModuleSet;
Expand All @@ -77,6 +78,8 @@ class LLVMModuleSet
FunDefToDeclsMapTy FunDefToDeclsMap;
/// Record some "sse_" function declarations used in other ext function definition, e.g., svf_ext_foo(), and svf_ext_foo() used in app functions
FunctionSetType ExtFuncsVec;
/// Record annotations of function in extapi.bc
Fun2AnnoMap ExtFun2Annotations;
/// Global definition to a rep definition map
GlobalDefToRepMapTy GlobalDefToRepMap;

Expand Down Expand Up @@ -323,7 +326,6 @@ class LLVMModuleSet
return it->second;
}


Module* getMainLLVMModule() const
{
return getModule(0);
Expand Down Expand Up @@ -377,6 +379,8 @@ class LLVMModuleSet
/// Invoke llvm passes to modify module
void prePassSchedule();
void buildSymbolTable() const;
void collectExtFunAnnotations(const Module* mod);
void removeUnusedExtAPIs();
};

} // End namespace SVF
Expand Down
5 changes: 2 additions & 3 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,11 @@ bool isIntrinsicFun(const Function* func);

/// Get all called funcions in a parent function
std::vector<const Function *> getCalledFunctions(const Function *F);
std::vector<std::string> getFunAnnotations(const Function* fun);
void removeFunAnnotations(std::vector<Function*>& removedFuncList);
void removeFunAnnotations(Set<Function*>& removedFuncList);
bool isUnusedGlobalVariable(const GlobalVariable& global);
void removeUnusedGlobalVariables(Module* module);
/// Delete unused functions, annotations and global variables in extapi.bc
void removeUnusedFuncsAndAnnotationsAndGlobalVariables(std::vector<Function*> removedFuncList);
void removeUnusedFuncsAndAnnotationsAndGlobalVariables(Set<Function*> removedFuncList);

/// Get the corresponding Function based on its name
const SVFFunction* getFunction(const std::string& name);
Expand Down
111 changes: 91 additions & 20 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ void LLVMModuleSet::build()

buildFunToFunMap();
buildGlobalDefToRepMap();
removeUnusedExtAPIs();

if (Options::SVFMain())
addSVFMain();
Expand All @@ -170,17 +171,13 @@ void LLVMModuleSet::createSVFDataStructure()
// candidateDefs is the vector for all used defined functions
// candidateDecls is the vector for all used declared functions
std::vector<const Function*> candidateDefs, candidateDecls;

for (Module& mod : modules)
{
std::vector<Function*> removedFuncList;
/// Function
for (Function& func : mod.functions())
{
if (isCalledExtFunction(&func))
{
removedFuncList.push_back(&func);
}
else if (func.isDeclaration())
if (func.isDeclaration())
{
candidateDecls.push_back(&func);
}
Expand All @@ -189,9 +186,8 @@ void LLVMModuleSet::createSVFDataStructure()
candidateDefs.push_back(&func);
}
}
/// Remove unused functions, annotations and global variables in extapi.bc
LLVMUtil::removeUnusedFuncsAndAnnotationsAndGlobalVariables(removedFuncList);
}

for (const Function* func: candidateDefs)
{
createSVFFunction(func);
Expand Down Expand Up @@ -240,9 +236,11 @@ void LLVMModuleSet::createSVFFunction(const Function* func)
SVFUtil::cast<SVFFunctionType>(
getSVFType(func->getFunctionType())),
func->isDeclaration(), LLVMUtil::isIntrinsicFun(func),
func->hasAddressTaken(), func->isVarArg(), new SVFLoopAndDomInfo, LLVMUtil::getFunAnnotations(func));
func->hasAddressTaken(), func->isVarArg(), new SVFLoopAndDomInfo);
svfFunc->setName(func->getName().str());
svfModule->addFunctionSet(svfFunc);
if (ExtFun2Annotations.find(func) != ExtFun2Annotations.end())
svfFunc->setAnnotations(ExtFun2Annotations[func]);
addFunctionMap(func, svfFunc);

for (const Argument& arg : func->args())
Expand Down Expand Up @@ -790,6 +788,57 @@ void LLVMModuleSet::addSVFMain()
}
}

void LLVMModuleSet::collectExtFunAnnotations(const Module* mod)
{
GlobalVariable *glob = mod->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr || !glob->hasInitializer())
return;

ConstantArray *ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
if (ca == nullptr)
return;

for (unsigned i = 0; i < ca->getNumOperands(); ++i)
{
ConstantStruct *structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr || structAn->getNumOperands() == 0)
continue;

// Check if the annotation is for a function
Function* fun = nullptr;
GlobalVariable *annotateStr = nullptr;
/// Non-opaque pointer
if (ConstantExpr *expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0)))
{
if (expr->getOpcode() == Instruction::BitCast && SVFUtil::isa<Function>(expr->getOperand(0)))
fun = SVFUtil::cast<Function>(expr->getOperand(0));

ConstantExpr *note = SVFUtil::cast<ConstantExpr>(structAn->getOperand(1));
if (note->getOpcode() != Instruction::GetElementPtr)
continue;

annotateStr = SVFUtil::dyn_cast<GlobalVariable>(note->getOperand(0));
}
/// Opaque pointer
else
{
fun = SVFUtil::dyn_cast<Function>(structAn->getOperand(0));
annotateStr = SVFUtil::dyn_cast<GlobalVariable>(structAn->getOperand(1));
}

if (!fun || annotateStr == nullptr || !annotateStr->hasInitializer())
continue;;

ConstantDataSequential *data = SVFUtil::dyn_cast<ConstantDataSequential>(annotateStr->getInitializer());
if (data && data->isString())
{
std::string annotation = data->getAsString().str();
if (!annotation.empty())
ExtFun2Annotations[fun].push_back(annotation);
}
}
}

/*
For a more detailed explanation of the Function declaration and definition mapping relationships and how External APIs are handled,
please refer to the SVF Wiki: https://github.com/SVF-tools/SVF/wiki/Handling-External-APIs-with-extapi.c
Expand Down Expand Up @@ -864,6 +913,7 @@ void LLVMModuleSet::buildFunToFunMap()
// extapi.bc functions
if (mod.getName().str() == ExtAPI::getExtAPI()->getExtBcPath())
{
collectExtFunAnnotations(&mod);
for (const Function& fun : mod.functions())
{
// there is main declaration in ext bc, it should be mapped to
Expand All @@ -885,18 +935,20 @@ void LLVMModuleSet::buildFunToFunMap()
{
extFuncs.insert(&fun);
// Find overwrite functions in extapi.bc
std::vector<std::string> annotations =
LLVMUtil::getFunAnnotations(&fun);
auto it =
std::find_if(annotations.begin(), annotations.end(),
[&](const std::string& annotation)
{
return annotation.find("OVERWRITE") !=
std::string::npos;
});
if (it != annotations.end())
if (ExtFun2Annotations.find(&fun) != ExtFun2Annotations.end())
{
overwriteExtFuncs.insert(&fun);
std::vector<std::string> annotations = ExtFun2Annotations[&fun];
auto it =
std::find_if(annotations.begin(), annotations.end(),
[&](const std::string& annotation)
{
return annotation.find("OVERWRITE") !=
std::string::npos;
});
if (it != annotations.end())
{
overwriteExtFuncs.insert(&fun);
}
}
}
}
Expand Down Expand Up @@ -1115,6 +1167,25 @@ void LLVMModuleSet::buildGlobalDefToRepMap()
}
}

void LLVMModuleSet::removeUnusedExtAPIs()
{
Set<Function*> removedFuncList;
for (Module& mod : modules)
{
if (mod.getName().str() != ExtAPI::getExtAPI()->getExtBcPath())
continue;
for (Function& func : mod.functions())
{
if (isCalledExtFunction(&func))
{
removedFuncList.insert(&func);
ExtFun2Annotations.erase(&func);
}
}
}
LLVMUtil::removeUnusedFuncsAndAnnotationsAndGlobalVariables(removedFuncList);
}

// Dump modules to files
void LLVMModuleSet::dumpModulesToFile(const std::string& suffix)
{
Expand Down
75 changes: 19 additions & 56 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,53 +454,12 @@ void LLVMUtil::processArguments(int argc, char **argv, int &arg_num, char **arg_
}
}

std::vector<std::string> LLVMUtil::getFunAnnotations(const Function* fun)
{
std::vector<std::string> annotations;
// Get annotation variable
GlobalVariable *glob = fun->getParent()->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr || !glob->hasInitializer())
return annotations;

ConstantArray *ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
if (ca == nullptr)
return annotations;

for (unsigned i = 0; i < ca->getNumOperands(); ++i)
{
ConstantStruct *structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr)
continue;

ConstantExpr *expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr || expr->getOpcode() != Instruction::BitCast || expr->getOperand(0) != fun)
continue;

ConstantExpr *note = SVFUtil::cast<ConstantExpr>(structAn->getOperand(1));
if (note->getOpcode() != Instruction::GetElementPtr)
continue;

GlobalVariable *annotateStr = SVFUtil::dyn_cast<GlobalVariable>(note->getOperand(0));
if (annotateStr == nullptr || !annotateStr->hasInitializer())
continue;

ConstantDataSequential *data = SVFUtil::dyn_cast<ConstantDataSequential>(annotateStr->getInitializer());
if (data->isString())
{
std::string annotation = data->getAsString().str();
if (!annotation.empty())
annotations.push_back(annotation);
}
}
return annotations;
}

void LLVMUtil::removeFunAnnotations(std::vector<Function*>& removedFuncList)
void LLVMUtil::removeFunAnnotations(Set<Function*>& removedFuncList)
{
if (removedFuncList.empty())
return; // No functions to remove annotations in extapi.bc module

Module* module = removedFuncList[0]->getParent();
Module* module = (*removedFuncList.begin())->getParent();
GlobalVariable* glob = module->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr || !glob->hasInitializer())
return;
Expand All @@ -516,20 +475,24 @@ void LLVMUtil::removeFunAnnotations(std::vector<Function*>& removedFuncList)
if (structAn == nullptr)
continue;

ConstantExpr* expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr || expr->getOpcode() != Instruction::BitCast)
{
// Keep the annotation if it's not created using BitCast
newAnnotations.push_back(structAn);
continue;
Function* annotatedFunc = nullptr;

// Non-opague pointer, try to cast to ConstantExpr and check for BitCast
if (ConstantExpr* expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0))) {
if (expr->getOpcode() == Instruction::BitCast) {
annotatedFunc = SVFUtil::dyn_cast<Function>(expr->getOperand(0));
}
}

Function* annotatedFunc = SVFUtil::dyn_cast<Function>(expr->getOperand(0));
if (annotatedFunc == nullptr || std::find(removedFuncList.begin(), removedFuncList.end(), annotatedFunc) != removedFuncList.end())
continue;
// Opague pointer, If the above method didn't work, try casting directly to Function
if (!annotatedFunc) {
annotatedFunc = SVFUtil::dyn_cast<Function>(structAn->getOperand(0));
}

// Keep the annotation for all other functions
newAnnotations.push_back(structAn);
// Process the annotated function if it's not in the removed list
if (annotatedFunc && std::find(removedFuncList.begin(), removedFuncList.end(), annotatedFunc) == removedFuncList.end()) {
newAnnotations.push_back(structAn);
}
}

if (newAnnotations.size() == ca->getNumOperands())
Expand Down Expand Up @@ -606,12 +569,12 @@ void LLVMUtil::removeUnusedGlobalVariables(Module* module)
}

/// Delete unused functions, annotations and global variables in extapi.bc
void LLVMUtil::removeUnusedFuncsAndAnnotationsAndGlobalVariables(std::vector<Function*> removedFuncList)
void LLVMUtil::removeUnusedFuncsAndAnnotationsAndGlobalVariables(Set<Function*> removedFuncList)
{
if (removedFuncList.empty())
return;

Module* mod = removedFuncList[0]->getParent();
Module* mod = (*removedFuncList.begin())->getParent();
if (mod->getName().str() != ExtAPI::getExtAPI()->getExtBcPath())
return;

Expand Down
18 changes: 18 additions & 0 deletions svf-llvm/lib/extapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,9 +562,15 @@ int XmbTextPropertyToTextList(void *a, void *b, char ***c, int *d)
__attribute__((annotate("MEMCPY")))
void llvm_memcpy_p0i8_p0i8_i64(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memcpy_p0_p0_i64(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memcpy_p0i8_p0i8_i32(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memcpy_p0_p0_i32(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memcpy(char* dst, char* src, int sz, int flag){}

Expand All @@ -574,9 +580,15 @@ void llvm_memmove(char* dst, char* src, int sz, int flag){}
__attribute__((annotate("MEMCPY")))
void llvm_memmove_p0i8_p0i8_i64(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memmove_p0_p0_i64(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memmove_p0i8_p0i8_i32(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void llvm_memmove_p0_p0_i32(char* dst, char* src, int sz, int flag){}

__attribute__((annotate("MEMCPY")))
void __memcpy_chk(char* dst, char* src, int sz, int flag){}

Expand Down Expand Up @@ -604,9 +616,15 @@ void llvm_memset(char* dst, char elem, int sz, int flag){}
__attribute__((annotate("MEMSET")))
void llvm_memset_p0i8_i32(char* dst, char elem, int sz, int flag){}

__attribute__((annotate("MEMSET")))
void llvm_memset_p0_i32(char* dst, char elem, int sz, int flag){}

__attribute__((annotate("MEMSET")))
void llvm_memset_p0i8_i64(char* dst, char elem, int sz, int flag){}

__attribute__((annotate("MEMSET")))
void llvm_memset_p0_i64(char* dst, char elem, int sz, int flag){}

__attribute__((annotate("MEMSET")))
char *__memset_chk(char * dest, int c, unsigned long destlen, int flag)
{
Expand Down
Loading

0 comments on commit 9e94966

Please sign in to comment.