我在LLVM IR中看到调试段错误的一些非常令人惊讶的行为。考虑一下代码:
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1)
define i32 @main() {
entry:
%cells = alloca i8, i32 9
%offset_cell_ptr = getelementptr i8* %cells, i32 0
call void @llvm.memset.p0i8.i32(i8* %offset_cell_ptr, i8 0, i32 9, i32 1, i1 true)
%cell_index_ptr = alloca i32
store i32 0, i32* %cell_index_ptr
; This is an out-of-bounds memory access.
%target_cell_ptr = getelementptr i8* %cells, i32 -1
%target_cell_val = load i8* %target_cell_ptr
%new_target_val = add i8 %target_cell_val, 11
store i8 %new_target_val, i8* %target_cell_ptr
; This memory access is in bounds.
%cell_index5 = load i32* %cell_index_ptr
%current_cell_ptr6 = getelementptr i8* %cells, i32 %cell_index5
; Removing this line stops lli segfaulting:
store i8 0, i8* %current_cell_ptr6
ret i32 0
}
我正在运行以下代码:
$ lli example.ll
如代码中所述,删除最后一个store
会阻止lli
进行分段。
甚至更奇怪的是用其值替换变量也可以防止段错误。
; Changing this line prevents the segfault, even though it should be equivalent.
%current_cell_ptr6 = getelementptr i8* %cells, i32 0
这是为什么?我原以为lli
会%target_cell_val = load i8* %target_cell_ptr
发生段错误。