使用分段错误执行 LLVM 代码结果

Executing LLVM code results with Segmentation fault

我有以下代码:

@.str_specifier = constant [4 x i8] c"%s[=10=]A[=10=]"
@.int_specifier = constant [4 x i8] c"%d[=10=]A[=10=]"
@.string_var1 = constant [2 x i8] c"f[=10=]"
@.string_var2 = constant [6 x i8] c"Error[=10=]"

;    >>> Start Program
declare i32 @printf(i8*, ...)
declare void @exit(i32)
define void @print(i8*) {
    call i32 (i8*, ...) @printf(i8* getelementptr ([4 x i8], [4 x i8]* @.str_specifier, i32 0, i32 0), i8* %0)
    ret void
}
define void @printi(i32) {
    call i32 (i8*, ...) @printf(i8* getelementptr ([4 x i8], [4 x i8]* @.int_specifier, i32 0, i32 0), i32 %0)
    ret void
}
declare i8* @malloc(i32)
declare void @free(i8*)
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1)


define void @main()
{   ; >>> Adding function scope
    %funcArgs1 = alloca [50 x i32]

    ; >>> Adding function arguments allocation

    ; >>> Function body of main
    call void @print(i8* getelementptr ([2 x i8], [2 x i8]* @.string_var1, i32 0, i32 0))
    %register1 = call i8* @malloc(i32 48)
    %register2 = bitcast i8* %register1 to i32*
    %register3 = getelementptr inbounds [50 x i32], [50 x i32]* %funcArgs1, i32 0, i32 0
    %register4 = ptrtoint i32* %register2 to i32
    store i32 %register4, i32* %register3
    %register5 = getelementptr inbounds i32, i32* %register2, i32 0
    %register6 = add i32 0, 12
    store i32 %register6, i32* %register5
    %register7 = getelementptr inbounds i32, i32* %register2, i32 1
    %register8 = add i32 0, 2
    store i32 %register8, i32* %register7
    %register9 = getelementptr inbounds i32, i32* %register2, i32 2
    store i32 0, i32* %register9
    %register10 = getelementptr inbounds i32, i32* %register2, i32 3
    store i32 0, i32* %register10
    %register11 = getelementptr inbounds i32, i32* %register2, i32 4
    store i32 0, i32* %register11
    %register12 = getelementptr inbounds i32, i32* %register2, i32 5
    store i32 0, i32* %register12
    %register13 = getelementptr inbounds i32, i32* %register2, i32 6
    store i32 0, i32* %register13
    %register14 = getelementptr inbounds i32, i32* %register2, i32 7
    store i32 0, i32* %register14
    %register15 = getelementptr inbounds i32, i32* %register2, i32 8
    store i32 0, i32* %register15
    %register16 = getelementptr inbounds i32, i32* %register2, i32 9
    store i32 0, i32* %register16
    %register17 = getelementptr inbounds i32, i32* %register2, i32 10
    store i32 0, i32* %register17
    %register18 = getelementptr inbounds i32, i32* %register2, i32 11
    store i32 0, i32* %register18
    %register19 = load i32, i32* %register3 ; Get variable x
    %register20 = add i32 0, 2
    %register21 = inttoptr i32 %register20 to i32*
    %register22 = getelementptr inbounds i32, i32* %register21, i32 1
    %register23 = load i32, i32* %register22
    %register24 = getelementptr inbounds i32, i32* %register21, i32 0
    %register25 = load i32, i32* %register24
    %register26 = add i32 %register23, %register25
    %register27 = sub i32 %register26, 4
    %register28 = icmp sgt i32 %register20, %register27
    br i1 %register28, label %label1, label %label_cont1
label_cont1:
    br label %label2
label1:
    call void @print(i8* getelementptr ([6 x i8], [6 x i8]* @.string_var2, i32 0, i32 0))
    call void @exit(i32 1)
    %register200 = add i32 0, 2
    br label %label2
label2:
    ret void

}   ; >>> Closing function scope

出于某种原因,当我 运行 它时,它失败并显示 Segmentation fault (core dumped) 而没有打印出可以理解的错误。奇怪的是,如果我在 label1 中注释命令并保留它:

    ;call void @print(i8* getelementptr ([6 x i8], [6 x i8]* @.string_var2, i32 0, i32 0))
    ;call void @exit(i32 1)
    ;%register200 = add i32 0, 2
    br label %label2

它不会导致分段错误。如果我至少注释掉其中一个命令(例如 print 或 sum),它将失败。为什么会这样?

编辑:我想我得到了 same result here. (Here with comments)

我了解“分段错误”意味着我试图访问内存 我无权访问。但为什么我什至不能创建一个具有某些值的新寄存器?

EDIT2:看起来 br i1 %register28, label %label1, label %label_cont1 才是真正的原因。

Edit3:可以找到我试图计算的实际完整代码 here。问题是将其更改为 alloca i32 将导致错误(而不是打印 1)。它还包含我试图复制到 LLVM 的 C 代码。

段错误源于这一行

%register21 = inttoptr i32 %register20 to i32*

转换后,register21 应该指向某个内存位置。但是什么内存位置?它的值是一个不存在的地址,不是通过 alloca instr 或 malloc 调用获得的。 因此所有其他尝试取消引用该指针的寄存器都会失望。

I've altered the inttptr line