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

Use extapi.bc to replace ExtAPI.json #1150

Closed
wants to merge 5 commits into from
Closed
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
1 change: 1 addition & 0 deletions .config.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
#define CONFIG_H_IN

#define PROJECT_PATH "@CMAKE_CURRENT_SOURCE_DIR@"
#define EXTAPI_PATH PROJECT_PATH "/@CMAKE_BUILD_TYPE@-build/include/Util"

#endif
1 change: 1 addition & 0 deletions .github/workflows/github-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ jobs:
lcov --remove coverage.info '${{github.workspace}}/svf/lib/FastCluster/*' --output-file coverage.info
lcov --remove coverage.info '${{github.workspace}}/svf/include/AbstractExecution/*' --output-file coverage.info
lcov --remove coverage.info '${{github.workspace}}/svf/lib/AbstractExecution/*' --output-file coverage.info
lcov --remove coverage.info '${{github.workspace}}/svf/lib/Util/extapi.c' --output-file coverage.info

- name: upload-coverage
if: runner.os == 'Linux'
Expand Down
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,19 @@ install(
DESTINATION include/svf
FILES_MATCHING
PATTERN "**/*.h")

# Compile extapi.c to extapi.bc
string(REGEX REPLACE "/lib/cmake/llvm$" "" LLVM_DIR "${LLVM_DIR}")
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
COMMAND ${LLVM_DIR}/bin/clang -S -c -Xclang -disable-O0-optnone -fno-discard-value-names -emit-llvm ${PROJECT_SOURCE_DIR}/svf/lib/Util/extapi.c -o ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
DEPENDS ${PROJECT_SOURCE_DIR}/svf/lib/Util/extapi.c
)

add_custom_target(extapi_ir ALL DEPENDS ${PROJECT_BINARY_DIR}/include/Util/extapi.bc)

install(
FILES ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
COMPONENT devel
DESTINATION include/svf/Util
)
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function build_llvm_from_source {
mkdir llvm-build
cd llvm-build
# /*/ is a dirty hack to get llvm-project-llvmorg-version...
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$SVFHOME/$LLVMHome" ../llvm-source/*/llvm
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$SVFHOME/$LLVMHome" -DLLVM_ENABLE_PROJECTS=clang ../llvm-source/*/llvm
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why change it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the previous cmake command doesn't generate clang, it prevents the use of clang to compile extapi.bc later on.

cmake --build . -j ${jobs}
cmake --install .

Expand Down
39 changes: 37 additions & 2 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
#include "SVF-LLVM/BasicTypes.h"
#include "SVF-LLVM/LLVMModule.h"
#include "SVFIR/SVFValue.h"
#include "Util/ExtAPI.h"
#include "Util/ThreadAPI.h"

namespace SVF
Expand Down Expand Up @@ -99,6 +98,42 @@ inline const Function* getProgFunction(const std::string& funName)
return nullptr;
}

inline bool isHeapAllocExtCallViaRet(const Instruction* inst)
{
if (isCallSite(inst))
{
const Function* func = getCallee(getLLVMCallSite(inst));
return func && (func->getName().str().find("_ALLOC_RET") != std::string::npos
|| func->getName().str().find("_REALLOC_RET") != std::string::npos);
}
return false;
}

inline bool isHeapAllocExtCallViaArg(const Instruction* inst)
{
if (isCallSite(inst))
{
const Function* func = getCallee(getLLVMCallSite(inst));
return func && func->getName().str().find("_ALLOC_ARG") != std::string::npos;
}
return false;
}

inline bool isHeapAllocExtCall(const Instruction* inst)
{
return isHeapAllocExtCallViaRet(inst) || isHeapAllocExtCallViaArg(inst);
}

inline bool isStaticExtCall(const Instruction* inst)
{
if (isCallSite(inst))
{
const Function* func = getCallee(getLLVMCallSite(inst));
return func && func->getName().str().find("_STATIC") != std::string::npos;
}
return false;
}

/// Check whether a function is an entry function (i.e., main)
inline bool isProgEntryFunction(const Function* fun)
{
Expand Down Expand Up @@ -145,7 +180,7 @@ inline const PointerType *getRefTypeOfHeapAllocOrStatic(const CallBase* cs)
// Case 2: heap/static object held by return value.
else
{
assert((SVFUtil::isStaticExtCall(svfcs) || SVFUtil::isHeapAllocExtCallViaRet(svfcs))
assert((isStaticExtCall(cs) || isHeapAllocExtCallViaRet(cs))
&& "Must be heap alloc via ret, or static allocation site");
refType = SVFUtil::dyn_cast<PointerType>(cs->getType());
}
Expand Down
19 changes: 5 additions & 14 deletions svf-llvm/include/SVF-LLVM/SVFIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
#define PAGBUILDER_H_

#include "SVFIR/SVFIR.h"
#include "Util/ExtAPI.h"
#include "SVF-LLVM/BasicTypes.h"
#include "SVF-LLVM/ICFGBuilder.h"
#include "SVF-LLVM/LLVMModule.h"
#include "SVF-LLVM/LLVMUtil.h"

namespace SVF
{
Expand Down Expand Up @@ -232,18 +232,9 @@ class SVFIRBuilder: public llvm::InstVisitor<SVFIRBuilder>

/// Handle external call
//@{
virtual SVFCallInst* addSVFExtCallInst(const SVFCallInst* svfInst, SVFBasicBlock* svfBB, const SVFFunction* svfCaller, const SVFFunction* svfCallee);
virtual void addSVFExtRetInst(SVFCallInst* svfCall, SVFBasicBlock* svfBB, SVFFunction* svfCaller);
virtual SVFInstruction* addSVFExtInst(const std::string& instName, const SVFCallInst* svfInst, SVFBasicBlock* svfBB, SVF::ExtAPI::OperationType opType, const SVFType* svfType);
virtual void extFuncAtomaticOperation(ExtAPI::Operand& atomicOp, const SVFCallInst* svfInst);
virtual SVFBasicBlock* extFuncInitialization(const SVFCallInst* svfInst, SVFFunction* svfCaller);
virtual void handleExtCallStat(ExtAPI::ExtFunctionOps &extFunctionOps, const SVFCallInst* svfInst);
virtual NodeID getExtID(ExtAPI::OperationType operationType, const std::string &s, const SVFCallInst* svfCall);
virtual void parseAtomaticOp(SVF::ExtAPI::Operand &atomaticOp, const SVFCallInst* svfCall, std::map<std::string, NodeID> &nodeIDMap);
virtual void parseExtFunctionOps(ExtAPI::ExtFunctionOps &extFunctionOps, const SVFCallInst* svfCall);
virtual void preProcessExtCall(CallBase* cs);
virtual void handleExtCall(const SVFInstruction* svfInst, const SVFFunction* svfCallee);
void addComplexConsForExt(const SVFValue* D, const SVFValue* S, const SVFValue* sz);
virtual const Type *getBaseTypeAndFlattenedFields(const Value *V, std::vector<AccessPath> &fields, const Value* szValue);
virtual void addComplexConsForExt(Value *D, Value *S, const Value* sz);
virtual void handleExtCall(const CallBase* cs, const SVFFunction* svfCallee);
//@}

/// Set current basic block in order to keep track of control flow information
Expand Down Expand Up @@ -287,7 +278,7 @@ class SVFIRBuilder: public llvm::InstVisitor<SVFIRBuilder>
return nullPtr;
}

NodeID getGepValVar(const SVFValue* val, const AccessPath& ap, const SVFType* baseType);
NodeID getGepValVar(const Value* val, const AccessPath& ls, const SVFType* elementType);

void setCurrentBBAndValueForPAGEdge(PAGEdge* edge);

Expand Down
106 changes: 88 additions & 18 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,24 +153,25 @@ void LLVMModuleSet::build()
void LLVMModuleSet::createSVFDataStructure()
{
getSVFType(IntegerType::getInt8Ty(getContext()));
Set<const Function*> candidateDecls;
Set<const Function*> candidateDefs;
// Functions need to be retrieved in the order of insertion
std::vector<const Function*> candidateDecls;
std::vector<const Function*> candidateDefs;

for (Module& mod : modules)
{
std::vector<Function*> removedFuncList;
/// Function
for (Function& func : mod.functions())
{
if (func.isDeclaration())
if (func.isDeclaration() && (FunDefToDeclsMap.find(&func) != FunDefToDeclsMap.end() || mod.getName().str() != Options::ExtAPIInput()))
{
/// if this function is declaration
candidateDecls.insert(&func);
candidateDecls.push_back(&func);
}
else
{
/// if this function is definition
if (mod.getName().str() == Options::ExtAPIInput() && FunDefToDeclsMap[&func].empty() && func.getName().str() != "svf__main")
if (mod.getName().str() == Options::ExtAPIInput() && FunDefToDeclsMap.find(&func) == FunDefToDeclsMap.end() && func.getName().str() != "svf__main")
{
/// if this function func defined in ExtAPI but never used in application code (without any corresponding declared functions).
removedFuncList.push_back(&func);
Expand All @@ -180,13 +181,13 @@ void LLVMModuleSet::createSVFDataStructure()
{
/// if this function is in app bc, any def func should be added.
/// if this function is in ext bc, only functions which have declarations(should be used by app bc) can be inserted.
candidateDefs.insert(&func);
candidateDefs.push_back(&func);
}
}
}
for (Function* func : removedFuncList)
{
mod.getFunctionList().remove(func);
func->eraseFromParent();
}
}
for (const Function* func: candidateDefs)
Expand Down Expand Up @@ -553,8 +554,11 @@ void LLVMModuleSet::loadExtAPIModules()
Err.print("SVFModuleLoader", llvm::errs());
abort();
}
modules.emplace_back(*mod);
owned_modules.emplace_back(std::move(mod));
// The module of ext.bc needs to be imported before other modules.
// Otherwise, when overwriting the app function with SVF extern function,
// the corresponding SVFFunction of the extern function will not be found.
modules.insert(modules.begin(), *mod);
owned_modules.insert(owned_modules.begin(),std::move(mod));
}
}

Expand Down Expand Up @@ -744,25 +748,39 @@ void LLVMModuleSet::addSVFMain()

void LLVMModuleSet::buildFunToFunMap()
{
Set<const Function*> funDecls, funDefs;
Set<const Function*> funDecls, funDefs, extFuncs, overwriteExtFuncs;
OrderedSet<string> declNames, defNames, intersectNames;
typedef Map<string, const Function*> NameToFunDefMapTy;
typedef Map<string, Set<const Function*>> NameToFunDeclsMapTy;
FunDeclToDefMapTy appFunToExtFun;

for (Module& mod : modules)
{
/// Function
for (const Function& fun : mod.functions())
// extapi.bc functions
if (mod.getName().str() == Options::ExtAPIInput())
{
if (fun.isDeclaration())
for (const Function& fun : mod.functions())
{
funDecls.insert(&fun);
declNames.insert(fun.getName().str());
if (fun.getName().str().find("_OVERWRITE") != std::string::npos)
overwriteExtFuncs.insert(&fun);
extFuncs.insert(&fun);
}
else
}
else
{
/// app functions
for (const Function& fun : mod.functions())
{
funDefs.insert(&fun);
defNames.insert(fun.getName().str());
if (fun.isDeclaration())
{
funDecls.insert(&fun);
declNames.insert(fun.getName().str());
}
else
{
funDefs.insert(&fun);
defNames.insert(fun.getName().str());
}
}
}
}
Expand Down Expand Up @@ -827,6 +845,58 @@ void LLVMModuleSet::buildFunToFunMap()
decls.push_back(decl);
}
}

/// App Func decl -> SVF extern Func def
for (const Function* fdecl : funDecls)
{
for (const Function* extfun : extFuncs)
{
std::string declName = fdecl->getName().str();
std::string svfExtName = "svf_";
svfExtName.reserve(svfExtName.size() + declName.size());
svfExtName.append(declName);
std::replace(svfExtName.begin(), svfExtName.end(), '.', '_');
if ((fdecl->arg_size() == extfun->arg_size() || (fdecl->isVarArg() && extfun->isVarArg()))
&& ((extfun->getName().str().length() == svfExtName.length() && extfun->getName().str().compare(svfExtName) == 0) ||
(extfun->getName().str().length() > svfExtName.length() && extfun->getName().str().find(svfExtName + "_") != std::string::npos)))
{
assert(extfun->getName().str().length() > 4 && extfun->getName().str().substr(0, 4).compare("svf_") == 0 && "Function in extapi.bc should be start with 'svf_'");
FunDeclToDefMap[fdecl] = extfun;
std::vector<const Function*>& decls = FunDefToDeclsMap[extfun];
decls.push_back(fdecl);
}
}
}

/// Overwrite
/// App Func def -> SVF extern Func def
for (const Function* appfunc : funDefs)
{
for (const Function* owfunc : overwriteExtFuncs)
{

if (owfunc->getName().str().find("svf_" + appfunc->getName().str() + "_") != std::string::npos &&
(owfunc->arg_size() == appfunc->arg_size() || (owfunc->isVarArg() && appfunc->isVarArg())))
{
assert(owfunc->getName().str().length() > 4 && owfunc->getName().str().substr(0, 4).compare("svf_") == 0 && "Function in extapi.bc should be start with 'svf_'");
appFunToExtFun[appfunc] = owfunc;

Function* fun = const_cast<Function*>(appfunc);
Module* mod = fun->getParent();
FunctionType* funType = fun->getFunctionType();
std::string funName = fun->getName().str();
Function* declaration = Function::Create(funType, GlobalValue::ExternalLinkage, funName, mod);
// Replace app function with svf extern function
fun->replaceAllUsesWith(declaration);
fun->eraseFromParent();
declaration->setName(funName);

FunDeclToDefMap[declaration] = owfunc;
std::vector<const Function*>& decls = FunDefToDeclsMap[owfunc];
decls.push_back(declaration);
}
}
}
}

void LLVMModuleSet::buildGlobalDefToRepMap()
Expand Down
4 changes: 2 additions & 2 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ const std::string structName = "struct.";
*/
bool LLVMUtil::isObject(const Value* ref)
{
if (SVFUtil::isa<Instruction>(ref) && SVFUtil::isStaticExtCall(LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(SVFUtil::cast<Instruction>(ref))) )
if (SVFUtil::isa<Instruction>(ref) && isStaticExtCall(SVFUtil::cast<Instruction>(ref)))
return true;
if (SVFUtil::isa<Instruction>(ref) && SVFUtil::isHeapAllocExtCallViaRet(LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(SVFUtil::cast<Instruction>(ref))))
if (SVFUtil::isa<Instruction>(ref) && isHeapAllocExtCallViaRet(SVFUtil::cast<Instruction>(ref)))
return true;
if (SVFUtil::isa<GlobalVariable>(ref))
return true;
Expand Down
Loading
Loading