【问题标题】:Executing LLVM code results with Segmentation fault执行带有分段错误的 LLVM 代码结果
【发布时间】:2023-03-26 12:11:01
【问题描述】:

我有以下代码:

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

;    >>> 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 代码。

【问题讨论】:

    标签: llvm llvm-ir


    【解决方案1】:

    段错误源于此行

    %register21 = inttoptr i32 %register20 to i32*
    

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

    I've altered the inttptr line

    【讨论】:

    • 感谢您的回答!它确实解决了分段故障,但为什么我需要%register20?我实际上有完整的代码(由教授给出),但由于某种原因,将其更改为 alloca 会导致其他行为。你介意调查一下吗?我在问题中添加了 URL。它应该返回1,但它会返回错误。
    • 我打开了一个单独的主题,这样会更有条理。如果你能帮上忙,请看看。再次感谢:)
    猜你喜欢
    • 1970-01-01
    • 2017-08-29
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    相关资源
    最近更新 更多