LLVM IR: expose variables to GDB?

你离开我真会死。 提交于 2020-01-05 17:51:38

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!