I am new to llvm. I am trying to figure out all store instructions which may change the memory a given pointer points to, using the Basic-aa pass that llvm provides. However, when I run my code, it works well at some input but causes a segmentation fault at some input. I used gdb, and found that it is aa.alias method caused it (aa is an instance of llvm::AliasResult). May anyone could tell me what is the possible reason? Thanks for your help! Here is my code:
// Find all store instruction that may modify the memory location
void findStoresToMemLoc(const llvm::MemoryLocation& memloc, llvm::Function& func, llvm::FunctionAnalysisManager& FAM){
auto& aa = FAM.getResult<llvm::BasicAA>(func);//get the result
for (const auto& bb:func){
for (const auto& instr:bb){//iterate over instructions in func
const llvm::StoreInst* store = llvm::dyn_cast<llvm::StoreInst>(&instr);
if (store == nullptr){//not a store
continue;
}
const auto storeloc = llvm::MemoryLocation::get(store);
//get the memory location of store
auto test = aa.alias(memloc, storeloc);//Clashs!
if (test != llvm::AliasResult::NoAlias){
const auto& dbgloc = store->getDebugLoc();
dbg(llvm::errs()<<"Found store at line:"<<dbgloc.getLine()<<"\n";)
}
}
}
}
//I use this function to test findStoresToMemLoc. In main(), I just call this function.
void testFind(llvm::Function& func, llvm::FunctionAnalysisManager& FAM){
const auto& args = func.getArgumentList();
const auto& firstarg = args.front();//The first argment is a pointer.
const auto memloc = llvm::MemoryLocation(llvm::dyn_cast<llvm::Value>(&firstarg));
findStoresToMemLoc(memloc, func, FAM);
return;
}
I have tried some inputs. When I use this for input:
#include <stdlib.h>
struct Node {
int data;
struct Node* left, *right;
};
void insert(struct Node* h)
{
if (h == NULL){}
h = malloc(sizeof(struct Node));
h->data = 0;//line 12
h->left = h->right = NULL; //line 13
}
It works really well and outputs:
Found store at line:12
Found store at line:13
Found store at line:13
The llvm ir is:
define void @insert(%struct.Node*) #0 !dbg !8 {
%2 = alloca %struct.Node*, align 8
store %struct.Node* %0, %struct.Node** %2, align 8
call void @llvm.dbg.declare(metadata %struct.Node** %2, metadata !18, metadata !19), !dbg !20
%3 = load %struct.Node*, %struct.Node** %2, align 8, !dbg !21
%4 = icmp eq %struct.Node* %3, null, !dbg !23
br i1 %4, label %5, label %8, !dbg !24
; <label>:5: ; preds = %1
%6 = call noalias i8* @malloc(i64 24) #3, !dbg !25
%7 = bitcast i8* %6 to %struct.Node*, !dbg !25
store %struct.Node* %7, %struct.Node** %2, align 8, !dbg !27
br label %8, !dbg !28
; <label>:8: ; preds = %5, %1
%9 = load %struct.Node*, %struct.Node** %2, align 8, !dbg !29
%10 = getelementptr inbounds %struct.Node, %struct.Node* %9, i32 0, i32 0, !dbg !30
store i32 0, i32* %10, align 8, !dbg !31
%11 = load %struct.Node*, %struct.Node** %2, align 8, !dbg !32
%12 = getelementptr inbounds %struct.Node, %struct.Node* %11, i32 0, i32 2, !dbg !33
store %struct.Node* null, %struct.Node** %12, align 8, !dbg !34
%13 = load %struct.Node*, %struct.Node** %2, align 8, !dbg !35
%14 = getelementptr inbounds %struct.Node, %struct.Node* %13, i32 0, i32 1, !dbg !36
store %struct.Node* null, %struct.Node** %14, align 8, !dbg !37
ret void, !dbg !38
}
However, when I use this for input:
#include <stdlib.h>
struct Node {
int data;
struct Node* left, *right;
};
void insert(struct Node* h)
{
struct Node* n = malloc(sizeof(struct Node));
n->data = 0;
n->left = n->right = NULL;
if (h == NULL){
h = n;
}
}
A segmentation fault happends. gdb shows it is aa.alias cause it. The llvm ir is:
; Function Attrs: noinline nounwind uwtable
define void @insert(%struct.Node*) #0 !dbg !8 {
%2 = alloca %struct.Node*, align 8
%3 = alloca %struct.Node*, align 8
store %struct.Node* %0, %struct.Node** %2, align 8
call void @llvm.dbg.declare(metadata %struct.Node** %2, metadata !18, metadata !19), !dbg !20
call void @llvm.dbg.declare(metadata %struct.Node** %3, metadata !21, metadata !19), !dbg !22
%4 = call noalias i8* @malloc(i64 24) #3, !dbg !23
%5 = bitcast i8* %4 to %struct.Node*, !dbg !23
store %struct.Node* %5, %struct.Node** %3, align 8, !dbg !22
%6 = load %struct.Node*, %struct.Node** %3, align 8, !dbg !24
%7 = getelementptr inbounds %struct.Node, %struct.Node* %6, i32 0, i32 0, !dbg !25
store i32 0, i32* %7, align 8, !dbg !26
%8 = load %struct.Node*, %struct.Node** %3, align 8, !dbg !27
%9 = getelementptr inbounds %struct.Node, %struct.Node* %8, i32 0, i32 2, !dbg !28
store %struct.Node* null, %struct.Node** %9, align 8, !dbg !29
%10 = load %struct.Node*, %struct.Node** %3, align 8, !dbg !30
%11 = getelementptr inbounds %struct.Node, %struct.Node* %10, i32 0, i32 1, !dbg !31
store %struct.Node* null, %struct.Node** %11, align 8, !dbg !32
%12 = load %struct.Node*, %struct.Node** %2, align 8, !dbg !33
%13 = icmp eq %struct.Node* %12, null, !dbg !35
br i1 %13, label %14, label %16, !dbg !36
; <label>:14: ; preds = %1
%15 = load %struct.Node*, %struct.Node** %3, align 8, !dbg !37
store %struct.Node* %15, %struct.Node** %2, align 8, !dbg !39
br label %16, !dbg !40
; <label>:16: ; preds = %14, %1
ret void, !dbg !41
}
I compile the ir using clang-4.0.0. The version of llvm I uses is llvm-4.0.0. I am just wondering why it happends.