SVF
SVF copied to clipboard
Segfault in PAGBuilder::build()
I'am experiencing a segfault within the construction of the PAG.
The relevant code snippet, that triggers the error is:
SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(get_module());
assert(svfModule != nullptr && "SVF Module is null");
PAGBuilder builder;
PAG* pag = builder.build(svfModule);
assert(pag != nullptr && "SVF Module is null");
The error itself is:
Thread 1 "python3.7" received signal SIGSEGV, Segmentation fault.
ICFGBuilder::build (this=this@entry=0x7fffffffb8a0, svfModule=0x5555561a4a00) at ../subprojects/svf/lib/SVF-FE/ICFGBuilder.cpp:44
44 const SVFFunction *fun = *iter;
The backtrace is:
#0 ICFGBuilder::build(SVFModule*) (this=this@entry=0x7fffffffb8a0, svfModule=0x5555561a4a00) at ../subprojects/svf/lib/SVF-FE/ICFGBuilder.cpp:44
#1 0x00007fffee1e1e47 in PAG::PAG(bool) (this=0x55555772a6e0, buildFromFile=<optimized out>) at ../subprojects/svf/include/SVF-FE/SymbolTableInfo.h:144
#2 0x00007fffee19b62f in PAG::getPAG(bool) (buildFromFile=false) at ../subprojects/svf/include/Graphs/PAG.h:145
#3 PAGBuilder::PAGBuilder() (this=0x7fffffffb930) at ../subprojects/svf/include/SVF-FE/PAGBuilder.h:53
Here are the relevant code lines (it could be that some line numbers are different due to local asserts etc.):
SymbolTableInfo.h:144 is the return mod; line in
/// Module
inline SVFModule* getModule()
{
return mod;
}
PAG.h:145 is the new PAG(...) line in:
static inline PAG* getPAG(bool buildFromFile = false)
{
if (pag == NULL)
{
pag = new PAG(buildFromFile);
}
return pag;
}
PAGBuilder.h:53 is the constructor:
PAGBuilder(): pag(PAG::getPAG()), svfMod(NULL), curBB(NULL),curVal(NULL)
{
}
Further debugging of frame 0 leads to:
(gdb) print svfModule
$1 = (SVFModule *) 0x5555561a4a00
(gdb) print svfModule->FunctionSet
$2 = {<std::_Vector_base<SVFFunction const*, std::allocator<SVFFunction const*> >> = {_M_impl = {<std::allocator<SVFFunction const*>> = {<__gnu_cxx::new_alloca
tor<SVFFunction const*>> = {<No data fields>}, <No data fields>}, <std::_Vector_base<SVFFunction const*, std::allocator<SVFFunction const*> >::_Vector_impl_dat
a> = {_M_start = 0x9, _M_finish = 0x0, _M_end_of_storage = 0x7fffea8a04c0}, <No data fields>}}, <No data fields>}
Which looks weird.
The SVFModule is filled properly. I have printed the FunctionSet at construction at the vector is filled correctly.
May it be, that the module pointer itself is not correct? I have tried to follow the argument and don't understand the meaning of the module argument in PAGBuilder::build(SVFModule*) function at all.
The thing is, that PAGBuilder initializes its pag member with PAG::getPAG() at its construction (i.e. before build() is called). getPAG() resolves to a singleton and constructs a fresh PAG (This is against my intuition. I have expected that PAGBuilder::build() constructs the PAG). For that it needs an ICFG, which is constructed with an ICFGBuilder in it's build method, which needs an SVFModule. This module is taken from the SymbolTableInfo singleton, which is filled with the module in LLVMModuleSet::buildSVFModule(). Is it possible that this are two different modules?
I have tried the replace the getPAG() call with NULL within the PAGBuilder class but this leads to other problems.
The latest SVFModule has been build with the moduleNameVec, to some degree, it's easier to use the toString() method in dump and print the node content. ''' SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(moduleNameVec); ''' have you updated to the latest version of SVF? As you could briefly check here: (about line 144) https://github.com/SVF-tools/SVF-example/blob/master/src/svf-ex.cpp The building method has been changed.
Yes, I use the latest SVF version (commit: bdc9c6831). I don't get, what you mean. My line in my first commit looks really similar to yours, except that I already have an initialized llvm::Module and give a reference of that into buildSVFModule().
The code lines 144, 152, 153 of your example are quite the same like in my example. However, thanks for the hint. I guess, the error is really that I overgive an llvm::Module& and not a vector a strings.
The problem is, like above explained, that the PAGBuilder needs a vaild SVFModule for construction. This SVFModule is taken from the SymbolTableInfo. However, the SymbolTableInfo is only build within the function buildSVFModule(std::vector<std::string>) and not in the function buildSVFModule(llvm::Module&).
So I guess that this code works:
std::vector<std::string> my_ir_files = get_file_names();
SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(my_ir_files);
PAGBuilder builder;
PAG *pag = builder.build(svfModule);
while this one doesn't:
llvm::Module& module = get_my_module();
SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(module);
PAGBuilder builder;
PAG *pag = builder.build(svfModule)
The obvious workaround would be to initialize a SymbolTableInfo within buildSVFModule(llvm::Module&), too, but I think the cleaner way would be to not require a valid SVFModule for building a PAGBuilder but only for calling PAGBuilder::build().
Maybe also buildSVFModule(std::vector<std::string>) could use buildSVFModule(llvm::Module&) itself. Then the problem of the two paths is solved. When buildSVFModule(std::vector<std::string> also stores the unique_ptr<llvm::Module> that is gets from LLVM somewhere and use only the references later on, #260 is also fixed.
Yes, buildSVFModule accepts the modules' names in the form of strings. It normally works as follows:
std::vector<std::string> moduleNameVec;
SVFUtil::processArguments(argc, argv, arg_num, arg_value, moduleNameVec);
cl::ParseCommandLineOptions(arg_num, arg_value, "XXX Analysis\n");
SVFModule* svfModule = LLVMModuleSet::getLLVMModuleSet()->buildSVFModule(moduleNameVec);
Yes, but I use SVF as library and already have an LLVM module and want to give this diretly to SVF. Therefore I use buildSVFModule(llvm::Module&).