SVF
SVF copied to clipboard
An intuitive way to convert SVFG node to LLVM Value
Hello,
So this question pertains to this issue a few years back: https://github.com/SVF-tools/SVF/issues/485
I read through the entire discussion quite carefully and tried to reproduce it, but as the SVF changed quite a bit over few years, I came up with something like this (I have commented out the suggested method with #if 0
because it was throwing me errors:
void checkSVFGwithTargetInsts(const SVFG* svfg, SetVector<Instruction*> targetInsts){
for(auto it = svfg->begin(); it != svfg->end(); it++) {
auto targetNode = it->second;
const llvm::Value *llvm_value;
#if 0 // Commented it out because it doesn't seem to work anymore.
const PAGNode* pagnode = svfg->getLHSTopLevPtr(targetNode);
if(pagnode->hasValue())
llvm_value = LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(pagnode->getValue());
#endif
const ICFGNode* icfgNode = targetNode->getICFGNode();
if (!IntraICFGNode::classof(icfgNode))
continue;
llvm::errs() << "IntraICFGNode\n";
auto stmnts = icfgNode->getSVFStmts();
for (auto item : stmnts)
{
auto svfInst = item->getInst();
llvm_value = LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfInst);
for (const llvm::Value* inst : targetInsts)
{
llvm::errs() << *inst << " " << *llvm_value << "\n";
if (inst == llvm_value) // this is the part I'm failing
llvm::errs() << "Found\n";
llvm::errs() << "\n";
}
llvm::errs() << "\n";
}
}
}
Output is as follows:
Current function: main
IntraICFGNode
%a1 = alloca [5 x i32], align 16 %8 = getelementptr inbounds [3 x i8], [3 x i8]* @.str, i64 0, i64 0
0x55708d15d1f0 0x55708d15be00
%a2 = alloca i32, align 4 %8 = getelementptr inbounds [3 x i8], [3 x i8]* @.str, i64 0, i64 0
0x55708d15d260 0x55708d15be00
IntraICFGNode
%a1 = alloca [5 x i32], align 16 %a2 = alloca i32, align 4
0x55708d15d1f0 0x55708d184430
%a2 = alloca i32, align 4 %a2 = alloca i32, align 4
0x55708d15d260 0x55708d184430
The left output is the instructions in targetInsts,
and the right output is as I am iterating through SVFG
; I am checking each stmnt
node to check whether the instruction matches with any in the targetInsts
.
From what I can tell, I am close to getting the desired result but failing the check of if (item == llvm_value)
, because as you can see, I should have been able to pass the if
check of %a2 = alloca i32, align 4 %a2 = alloca i32, align 4
Upon further debugging, I noticed that the address of the llvm_value
pointer is different than the item,
which is why even though they may be pointing at the same "instruction", the if
check is failing.
Therefore my question is as follows:
-
Is there an easier way than the above code to extract
llvm::Value*
from the SVF node? (Admittedly, the above code took a while for me to figure out, and I don't even know whether it is correct, I just tried to get the functionality working). -
My guess is that even though I extract the value from the SVF into LLVM, I cannot just directly compare the LLVM value with the other LLVM value; what would be the proper way to do this? My potential solution I am thinking of right now is just to use
inst->toString()
from the SVF and figure out how to convertllvm::Instruction*
into a string format as well and do a direct comparison of strings. I am hoping to avoid this because I am unsure whether I may get burned later into the project by doing this.
Thank you in advance. I understand that it is against SVF's principle to do what I want to do (as stated in the issue above), but I still wanted to figure this out if possible, if not I'll just do it via string comparison.
Fixed typos
IF anyone wants to use toString()
method to compare, you can do it this way (to save you some time)
std::string str;
llvm::raw_string_ostream ss(str);
...
llvm_value = LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfInst);
for (const llvm::Value* inst : targetInsts)
{
ss.flush();
ss << *inst;
llvm::errs() << strlen(trim(ss.str()).c_str()) << " " << strlen(trim(svfInst->toString()).c_str())<< " " << "\n";
if (strcmp(trim(ss.str()).c_str(),trim(svfInst->toString()).c_str()) == 0)
llvm::errs() << "Found\n";
str.clear();
}
llvm::errs() << "\n";
...
It seems that toString()
provides a string with arbitrary whitespace, so I used trim
function from https://stackoverflow.com/a/17976541/13626080 to ensure no unnecessary whitespace exists.
Works now:
Current function: main
IntraICFGNode
32 67
25 67
IntraICFGNode
32 25
25 25
Found
IF anyone wants to use
toString()
method to compare, you can do it this way (to save you some time)std::string str; llvm::raw_string_ostream ss(str); ... llvm_value = LLVMModuleSet::getLLVMModuleSet()->getLLVMValue(svfInst); for (const llvm::Value* inst : targetInsts) { ss.flush(); ss << *inst; llvm::errs() << strlen(trim(ss.str()).c_str()) << " " << strlen(trim(svfInst->toString()).c_str())<< " " << "\n"; if (strcmp(trim(ss.str()).c_str(),trim(svfInst->toString()).c_str()) == 0) llvm::errs() << "Found\n"; str.clear(); } llvm::errs() << "\n"; ...
It seems that
toString()
provides a string with arbitrary whitespace, so I usedtrim
function from https://stackoverflow.com/a/17976541/13626080 to ensure no unnecessary whitespace exists.Works now:
Current function: main IntraICFGNode 32 67 25 67 IntraICFGNode 32 25 25 25 Found
Thanks and would you be able to make a pull request? @xudon9 could you take a look at whether this trim will affect SVF Json format?