Skip to content

Commit

Permalink
Merge branch 'SVF-tools:master' into fix_rtti_eh_from_llvm
Browse files Browse the repository at this point in the history
  • Loading branch information
Johanmyst authored Dec 20, 2023
2 parents 1fd01be + 6cc6277 commit 6f1f351
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 69 deletions.
12 changes: 7 additions & 5 deletions svf-llvm/include/SVF-LLVM/LLVMModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class LLVMModuleSet
static bool preProcessed;
SymbolTableInfo* symInfo;
SVFModule* svfModule; ///< Borrowed from singleton SVFModule::svfModule
std::unique_ptr<LLVMContext> cxts;
std::unique_ptr<LLVMContext> owned_ctx;
std::vector<std::unique_ptr<Module>> owned_modules;
std::vector<std::reference_wrapper<Module>> modules;

Expand Down Expand Up @@ -111,8 +111,10 @@ class LLVMModuleSet
llvmModuleSet = nullptr;
}

// The parameter of context should be the llvm context of the mod, the llvm context of mod and extapi module should be the same
static SVFModule* buildSVFModule(Module& mod, std::unique_ptr<LLVMContext> context);
// Build an SVF module from a given LLVM Module instance (for use e.g. in a LLVM pass)
static SVFModule* buildSVFModule(Module& mod);

// Build an SVF module from the bitcode files provided in `moduleNameVec`
static SVFModule* buildSVFModule(const std::vector<std::string>& moduleNameVec);

inline SVFModule* getSVFModule()
Expand Down Expand Up @@ -357,8 +359,8 @@ class LLVMModuleSet
std::vector<const Function*> getLLVMGlobalFunctions(const GlobalVariable* global);

void loadModules(const std::vector<std::string>& moduleNameVec);
// The llvm context of app module and extapi module should be the same
void loadExtAPIModules(std::unique_ptr<LLVMContext> context = nullptr);
// Loads ExtAPI bitcode file; uses LLVMContext made while loading module bitcode files or from Module
void loadExtAPIModules();
void addSVFMain();

void createSVFDataStructure();
Expand Down
17 changes: 7 additions & 10 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ const Value* stripAllCasts(const Value* val);
/// Get the type of the heap allocation
const Type* getTypeOfHeapAlloc(const Instruction* inst);

/// Return the bitcast instruction which is val's only use site, otherwise
/// Return the bitcast instruction right next to val, otherwise
/// return nullptr
const Value* getUniqueUseViaCastInst(const Value* val);
const Value* getFirstUseViaCastInst(const Value* val);

/// Return corresponding constant expression, otherwise return nullptr
//@{
Expand Down Expand Up @@ -496,7 +496,7 @@ const Argument* getConstructorThisPtr(const Function* fun);
const Value* getVCallThisPtr(const CallBase* cs);
const Value* getVCallVtblPtr(const CallBase* cs);
s32_t getVCallIdx(const CallBase* cs);
std::string getClassNameFromType(const Type* ty);
std::string getClassNameFromType(const StructType* ty);
std::string getClassNameOfThisPtr(const CallBase* cs);
std::string getFunNameOfVCallSite(const CallBase* cs);
bool VCallInCtorOrDtor(const CallBase* cs);
Expand All @@ -513,13 +513,10 @@ bool VCallInCtorOrDtor(const CallBase* cs);
bool isSameThisPtrInConstructor(const Argument* thisPtr1,
const Value* thisPtr2);

template<typename T>
std::string llvmToString(const T& val)
{
std::string str;
llvm::raw_string_ostream(str) << val;
return str;
}
std::string dumpValue(const Value* val);

std::string dumpType(const Type* type);


/**
* See more: https://github.com/SVF-tools/SVF/pull/1191
Expand Down
2 changes: 1 addition & 1 deletion svf-llvm/include/SVF-LLVM/SymbolTableBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class SymbolTableBuilder
/// Analyse types of all flattened fields of this object
void analyzeObjType(ObjTypeInfo* typeinfo, const Value* val);
/// Analyse types of heap and static objects
void analyzeHeapObjType(ObjTypeInfo* typeinfo, const Value* val);
u32_t analyzeHeapObjType(ObjTypeInfo* typeinfo, const Value* val);
/// Analyse types of heap and static objects
void analyzeStaticObjType(ObjTypeInfo* typeinfo, const Value* val);

Expand Down
54 changes: 37 additions & 17 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,18 @@ bool LLVMModuleSet::preProcessed = false;

LLVMModuleSet::LLVMModuleSet()
: symInfo(SymbolTableInfo::SymbolInfo()),
svfModule(SVFModule::getSVFModule()), cxts(nullptr)
svfModule(SVFModule::getSVFModule())
{
}

SVFModule* LLVMModuleSet::buildSVFModule(Module &mod, std::unique_ptr<LLVMContext> context)
SVFModule* LLVMModuleSet::buildSVFModule(Module &mod)
{
LLVMModuleSet* mset = getLLVMModuleSet();

double startSVFModuleTime = SVFStat::getClk(true);
SVFModule::getSVFModule()->setModuleIdentifier(mod.getModuleIdentifier());
mset->modules.emplace_back(mod);
mset->loadExtAPIModules(std::move(context));

mset->modules.emplace_back(mod); // Populates `modules`; can get context via `this->getContext()`
mset->loadExtAPIModules(); // Uses context from module through `this->getContext()`
mset->build();
double endSVFModuleTime = SVFStat::getClk(true);
SVFStat::timeOfBuildingLLVMModule = (endSVFModuleTime - startSVFModuleTime)/TIMEINTERVAL;
Expand All @@ -101,8 +100,8 @@ SVFModule* LLVMModuleSet::buildSVFModule(const std::vector<std::string> &moduleN

LLVMModuleSet* mset = getLLVMModuleSet();

mset->loadModules(moduleNameVec);
mset->loadExtAPIModules();
mset->loadModules(moduleNameVec); // Populates `modules`; can get context via `this->getContext()`
mset->loadExtAPIModules(); // Uses context from first module through `this->getContext()`

if (!moduleNameVec.empty())
{
Expand Down Expand Up @@ -507,9 +506,11 @@ void LLVMModuleSet::loadModules(const std::vector<std::string> &moduleNameVec)
SVFModule::setPagFromTXT(Options::Graphtxt());

//
// To avoid the following type bugs (t1 != t3) when parsing multiple modules,
// We should use only one LLVMContext object for multiple modules in the same thread.
// No such problem if only one module is processed by SVF.
// LLVMContext objects separate global LLVM settings (from which e.g. types are
// derived); multiple LLVMContext objects can coexist and each context can "own"
// multiple modules (modules can only have one context). Mixing contexts can lead
// to unintended inequalities, such as the following:
//
// ------------------------------------------------------------------
// LLVMContext ctxa,ctxb;
// IntegerType * t1 = IntegerType::get(ctxa,32);
Expand All @@ -521,7 +522,16 @@ void LLVMModuleSet::loadModules(const std::vector<std::string> &moduleNameVec)
// assert(t1 != t3);
// ------------------------------------------------------------------
//
cxts = std::make_unique<LLVMContext>();
// When loading bytecode files, SVF will use the same LLVMContext object for all
// modules (i.e. the context owns all loaded modules). This applies to ExtAPI as
// well, which *must* be loaded using the same LLVMContext object. Hence, when
// loading modules from bitcode files, a new LLVMContext is created (using a
// `std::unique_ptr<LLVMContext>` type to ensure automatic garbage collection).
//
// This garbage collection should be avoided when building an SVF module from an LLVM
// module instance; see the comment(s) in `buildSVFModule` and `loadExtAPIModules()`

owned_ctx = std::make_unique<LLVMContext>();

for (const std::string& moduleName : moduleNameVec)
{
Expand All @@ -532,7 +542,7 @@ void LLVMModuleSet::loadModules(const std::vector<std::string> &moduleNameVec)
}

SMDiagnostic Err;
std::unique_ptr<Module> mod = parseIRFile(moduleName, Err, *cxts);
std::unique_ptr<Module> mod = parseIRFile(moduleName, Err, *owned_ctx);
if (mod == nullptr)
{
SVFUtil::errs() << "load module: " << moduleName << "failed!!\n\n";
Expand All @@ -544,8 +554,21 @@ void LLVMModuleSet::loadModules(const std::vector<std::string> &moduleNameVec)
}
}

void LLVMModuleSet::loadExtAPIModules(std::unique_ptr<LLVMContext> context)
void LLVMModuleSet::loadExtAPIModules()
{
// This function loads the ExtAPI bitcode file as an LLVM module. Note that it is important that
// the same LLVMContext object is used to load this bitcode file as is used by the other modules
// being analysed.
// When the modules are loaded from bitcode files (i.e. passing filenames to files containing
// LLVM IR to `buildSVFModule({file1.bc, file2.bc, ...})) the context is created while loading
// the modules in `loadModules()`, which populates this->modules and this->owned_modules.
// If, however, an LLVM Module object is passed to `buildSVFModule` (e.g. from an LLVM pass),
// the context should be retrieved from the module itself (note that the garbage collection from
// `std::unique_ptr<LLVMContext> LLVMModuleSet::owned_ctx` should be avoided in this case). This
// function populates only this->modules.
// In both cases, fetching the context from the main LLVM module (through `getContext`) works
assert(!empty() && "LLVMModuleSet contains no modules; cannot load ExtAPI module without LLVMContext!");

// Load external API module (extapi.bc)
if (!ExtAPI::getExtAPI()->getExtBcPath().empty())
{
Expand All @@ -556,10 +579,7 @@ void LLVMModuleSet::loadExtAPIModules(std::unique_ptr<LLVMContext> context)
abort();
}
SMDiagnostic Err;
assert(!(cxts == nullptr && context == nullptr) && "Before loading extapi module, at least one LLVMContext should be initialized !!!");
if (context != nullptr)
cxts = std::move(context);
std::unique_ptr<Module> mod = parseIRFile(extModuleName, Err, *cxts);
std::unique_ptr<Module> mod = parseIRFile(extModuleName, Err, getContext());
if (mod == nullptr)
{
SVFUtil::errs() << "load external module: " << extModuleName << "failed!!\n\n";
Expand Down
79 changes: 55 additions & 24 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,17 +346,24 @@ void LLVMUtil::getPrevInsts(const Instruction* curInst, std::vector<const SVFIns
* for example, %4 = call align 16 i8* @malloc(i64 10); %5 = bitcast i8* %4 to i32*
* return %5 whose type is i32* but not %4 whose type is i8*
*/
const Value* LLVMUtil::getUniqueUseViaCastInst(const Value* val)
const Value* LLVMUtil::getFirstUseViaCastInst(const Value* val)
{
const PointerType * type = SVFUtil::dyn_cast<PointerType>(val->getType());
assert(type && "this value should be a pointer type!");
/// If type is void* (i8*) and val is only used at a bitcast instruction
/// If type is void* (i8*) and val is immediately used at a bitcast instruction
if (IntegerType *IT = SVFUtil::dyn_cast<IntegerType>(getPtrElementType(type)))
{
if (IT->getBitWidth() == 8 && val->getNumUses()==1)
if (IT->getBitWidth() == 8)
{
const Use *u = &*val->use_begin();
return SVFUtil::dyn_cast<BitCastInst>(u->getUser());
const Value *latestUse = nullptr;
for (const auto &it : val->uses())
{
if (SVFUtil::isa<BitCastInst>(it.getUser()))
latestUse = it.getUser();
else
latestUse = nullptr;
}
return latestUse;
}
}
return nullptr;
Expand All @@ -371,7 +378,7 @@ const Type* LLVMUtil::getTypeOfHeapAlloc(const Instruction *inst)
const SVFInstruction* svfinst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(inst);
if(SVFUtil::isHeapAllocExtCallViaRet(svfinst))
{
if(const Value* v = getUniqueUseViaCastInst(inst))
if(const Value* v = getFirstUseViaCastInst(inst))
{
if(const PointerType* newTy = SVFUtil::dyn_cast<PointerType>(v->getType()))
type = newTy;
Expand Down Expand Up @@ -923,7 +930,12 @@ bool LLVMUtil::isLoadVtblInst(const LoadInst* loadInst)
if (const FunctionType* functy = SVFUtil::dyn_cast<FunctionType>(elemTy))
{
const Type* paramty = functy->getParamType(0);
std::string className = LLVMUtil::getClassNameFromType(paramty);
std::string className = "";
if(const PointerType* ptrTy = SVFUtil::dyn_cast<PointerType>(paramty))
{
if(const StructType* st = SVFUtil::dyn_cast<StructType>(getPtrElementType(ptrTy)))
className = LLVMUtil::getClassNameFromType(st);
}
if (className.size() > 0)
{
return true;
Expand Down Expand Up @@ -1156,33 +1168,27 @@ bool LLVMUtil::VCallInCtorOrDtor(const CallBase* cs)
return false;
}

std::string LLVMUtil::getClassNameFromType(const Type* ty)
std::string LLVMUtil::getClassNameFromType(const StructType* ty)
{
std::string className = "";
if (const PointerType* ptrType = SVFUtil::dyn_cast<PointerType>(ty))
if (!((SVFUtil::cast<StructType>(ty))->isLiteral()))
{
const Type* elemType = LLVMUtil::getPtrElementType(ptrType);
if (SVFUtil::isa<StructType>(elemType) &&
!((SVFUtil::cast<StructType>(elemType))->isLiteral()))
std::string elemTypeName = ty->getStructName().str();
if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
{
std::string elemTypeName = elemType->getStructName().str();
if (elemTypeName.compare(0, clsName.size(), clsName) == 0)
{
className = elemTypeName.substr(clsName.size());
}
else if (elemTypeName.compare(0, structName.size(), structName) ==
0)
{
className = elemTypeName.substr(structName.size());
}
className = elemTypeName.substr(clsName.size());
}
else if (elemTypeName.compare(0, structName.size(), structName) == 0)
{
className = elemTypeName.substr(structName.size());
}
}
return className;
}

std::string LLVMUtil::getClassNameOfThisPtr(const CallBase* inst)
{
std::string thisPtrClassName;
std::string thisPtrClassName = "";
if (const MDNode* N = inst->getMetadata("VCallPtrType"))
{
const MDString* mdstr = SVFUtil::cast<MDString>(N->getOperand(0).get());
Expand All @@ -1191,7 +1197,9 @@ std::string LLVMUtil::getClassNameOfThisPtr(const CallBase* inst)
if (thisPtrClassName.size() == 0)
{
const Value* thisPtr = LLVMUtil::getVCallThisPtr(inst);
thisPtrClassName = getClassNameFromType(thisPtr->getType());
if(const PointerType* ptrTy = SVFUtil::dyn_cast<PointerType>(thisPtr->getType()))
if(const StructType* st = SVFUtil::dyn_cast<StructType>(getPtrElementType(ptrTy)))
thisPtrClassName = getClassNameFromType(st);
}

size_t found = thisPtrClassName.find_last_not_of("0123456789");
Expand Down Expand Up @@ -1278,6 +1286,29 @@ s64_t LLVMUtil::getCaseValue(const SwitchInst &switchInst, SuccBBAndCondValPair
return val;
}

std::string LLVMUtil::dumpValue(const Value* val)
{
std::string str;
llvm::raw_string_ostream rawstr(str);
if (val)
rawstr << " " << *val << " ";
else
rawstr << " llvm Value is null";
return rawstr.str();
}

std::string LLVMUtil::dumpType(const Type* type)
{
std::string str;
llvm::raw_string_ostream rawstr(str);
if (type)
rawstr << " " << *type << " ";
else
rawstr << " llvm type is null";
return rawstr.str();
}


namespace SVF
{

Expand Down
2 changes: 1 addition & 1 deletion svf-llvm/lib/SVFIRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ const Value* SVFIRBuilder::getBaseValueForExtArg(const Value* V)
const SVFInstruction* svfInst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(cb);
if (SVFUtil::isHeapAllocExtCallViaRet(svfInst))
{
if (const Value* bitCast = getUniqueUseViaCastInst(cb))
if (const Value* bitCast = getFirstUseViaCastInst(cb))
return bitCast;
}
}
Expand Down
Loading

0 comments on commit 6f1f351

Please sign in to comment.