问题
I am writing a custom programming language. I am generating LLVM IR as an intermediate (via LLVMlite), and I want to expose variables to GDB. This is an example of the generated 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" }
I removed the previous edits. The generation code can be found here. As you can see, I have a variable $a
that I am trying to declare with llvm.dbg.declare
. However, although objdump --sym
lists debug info (pastebin), gdb gives No locals.
upon running info locals
. What is the correct way to export variables? How could I generate that with LLVMlite?
Here is the compilation code:
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)
Here is the LLVM confirmation code:
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
(After this, the module is written to a file)
EDIT 5 (or 6, idk): As Chirag Patel suggested, I added a new debug statement to the ret
instruction. Then, this happened.
(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)
来源:https://stackoverflow.com/questions/53508969/llvm-ir-expose-variables-to-gdb