llvm alias analysis cause a segmentation fault

15 Views Asked by At

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.

0

There are 0 best solutions below