我正在编写自定义编程语言。我正在生成LLVM IR作为中间产品(通过LLVMlite),我想向GDB公开变量。这是生成的IR的示例:
; ModuleID = "tests/debuginfo.xan"
source_filename = "debuginfo.xan"
target triple = "x86_64-unknown-linux-gnu"
target datalayout = ""
define void @"main"(i32 %".1", i8** %".2") !dbg !10
{
entry:
%"$argc" = alloca i32
store i32 %".1", i32* %"$argc"
%"$argv" = alloca i8**
store i8** %".2", i8*** %"$argv"
%"$a" = alloca i32
call void @"llvm.dbg.declare"(metadata i32* %"$a", metadata !12, metadata !13), !dbg !14
call void @"llvm.dbg.value"(metadata i32 0, metadata !12, metadata !13), !dbg !15
store i32 0, i32* %"$a"
ret void
}
declare i32 @"printf"(i8* %".1", ...)
declare void @"llvm.dbg.declare"(metadata %".1", metadata %".2", metadata %".3") nounwind readnone
declare void @"llvm.dbg.value"(metadata %".1", metadata %".2", metadata %".3") nounwind readnone
@"NULL" = internal constant i8* inttoptr (i32 0 to i8*)
!llvm.dbg.cu = !{ !2 }
!llvm.module.flags = !{ !3, !4, !5 }
!llvm.ident = !{ !6 }
!gen-by = !{ !16 }
!0 = !DIFile(directory: "/home/proc-daemon/Dropbox/Xanathar/xanathar/tests", filename: "debuginfo.xan")
!1 = !{ }
!2 = distinct !DICompileUnit(emissionKind: FullDebug, enums: !1, file: !0, isOptimized: false, language: DW_LANG_Python, producer: "Xanathar v. a0.0.1", runtimeVersion: 0)
!3 = !{ i32 2, !"Dwarf Version", i32 4 }
!4 = !{ i32 2, !"Debug Info Version", i32 3 }
!5 = !{ i32 1, !"wchar_size", i32 4 }
!6 = !{ !"Xanathar a0.0.1" }
!7 = !DIDerivedType(baseType: null, size: 64, tag: DW_TAG_pointer_type)
!8 = !{ !7 }
!9 = !DISubroutineType(types: !8)
!10 = distinct !DISubprogram(file: !0, isDefinition: true, isLocal: false, isOptimized: false, name: "main", scope: !0, scopeLine: 1, type: !9, unit: !2, variables: !1)
!11 = !DIBasicType(encoding: DW_ATE_signed, name: "int", size: 4)
!12 = !DILocalVariable(file: !0, line: 1, name: "a", scope: !10, type: !11)
!13 = !DIExpression()
!14 = !DILocation(column: 1, line: 1, scope: !10)
!15 = !DILocation(column: 1, line: 2, scope: !10)
!16 = !{ !"Xanathar" }
我删除了之前的修改。可以在here中找到生成代码。如您所见,我有一个变量$a
,我正在尝试用llvm.dbg.declare
进行声明。但是,尽管objdump --sym
列出了调试信息(pastebin),但gdb在运行No locals.
时会给出info locals
。导出变量的正确方法是什么?如何使用LLVMlite生成它?
这是编译代码:
def compile(self, name, so):
sys.stderr.write('---COMPILE---\n')
if not so:
command = 'clang {0} -g -fstandalone-debug -O0 ' + name + '.ll '
else:
command = 'clang {0} -g -fstandalone-debug -O0 -shared -undefined dynamic_lookup ' + name + '.ll '
command = command.format(self.flags)
for i in self.LOADED_MODULES:
if i["type"] == 'LINKED_SO':
command += os.path.abspath(i["FILE"]) + ' '
command = command + '-o ' + name + ('.so' if so else '.o')
# print(command)
os.system(command)
这是LLVM确认代码:
def _compile_ir(self, builder):
"""
Compile the LLVM IR string with the given engine.
The compiled module object is returned.
"""
# Create a LLVM module object from the IR
self.builder = builder
self.builder.ret_void()
self.module.add_named_metadata("gen-by", ["Xanathar"])
llvm_ir = str(self.module)
try:
mod = self.binding.parse_assembly(llvm_ir)
except RuntimeError as e:
sys.stderr.write("[ERR] LLVM parsing error!\n")
sys.stderr.write(str(e))
if "expected instruction opcode" in str(e):
sys.stderr.write("\nDid you forget to return from a function?")
exit(1)
mod = 0 # Otherwise PyCharm complains about mod's usage below
mod.verify()
# Now add the module and make sure it is ready for execution
self.engine.add_module(mod)
self.engine.finalize_object()
self.engine.run_static_constructors()
return mod
(此后,模块将被写入文件)
编辑 5(或6,idk):正如Chirag Patel所建议的那样,我在ret
指令中添加了新的调试语句。然后,这发生了。
(gdb) r
Starting program: /home/proc-daemon/Dropbox/Xanathar/xanathar/tests/debuginfo.xan.o
Breakpoint 1, main () at debuginfo.xan:1
1 declare $a as int32;
(gdb) info locals
Segmentation fault (core dumped)