Hello List!
I’m trying to add LLDB/DWARF debugging information to the RoboVM opensource fork [1]
Java AOT compiler. RoboVM uses the LLVM 3.6 (pre-release version) debugging format
and I got the basics working, but can’t get the stack variable inspection to work.
The IR is generated by RoboVM’s own implementation, not by the LLVM Cpp API.
The “fr v” command doesn’t show any local variables. Below the generated IR
for a method, the debugging info for this CU and the dwarfdump output.
I can’t see the void* pointer argument %env in lldb. (Metadata Lines !38 - !42)
Any hint what I’m doing wrong would be great, since I ran out of ideas.
Thanks for your time, and sorry if this is the wrong place to ask!
Florian
[1] https://github.com/florianf/robovm/tree/dwarf_debugging_branch
LLDB Version:
lldb-350.0.21.9
CLANG Version & Command:
Apple LLVM version 7.3.0 (clang-703.0.31)
clang++ -o Main -g -arch x86_64 -Wl,-filelist,objects0 -L vm/target/binaries/macosx/x86_64 -ObjC -exported_symbols_list exported_symbols -Wl,-no_implicit_dylibs -Wl,-dead_strip -fPIC -mmacosx-version-min=10.9 -Wl,-no_pie -lrobovm-bc-dbg -force_load vm/target/binaries/macosx/x86_64/librobovm-rt-dbg.a -lrobovm-debug-dbg -lrobovm-core-dbg -lgc-dbg -lpthread -ldl -lm -lz -liconv -lsqlite3 -framework Foundation -framework CoreServices
Generated IR for a method:
define weak i32 @"[J]Main.instanceMethod(I)I"(%Env* %p0, %Object* %p1, i32 %p2) nounwind noinline optsize {
label0:
%__envStack = alloca %Env*
store %Env* %p0, %Env** %__envStack
call void @“llvm.dbg.declare”(metadata %Env** %__envStack, metadata !39), !dbg !57
%r0 = alloca %Object*
%i0 = alloca i32
%r1 = alloca %Object*
%$r2 = alloca %Object*
%$r3 = alloca %Object*
%$i1 = alloca i32
%$i2 = alloca i32
%$i3 = alloca i32
call void @“checkso”()
store %Object* %p1, %Object** %r0, !dbg !58
store i32 %p2, i32* %i0, !dbg !63
%t0 = call %Object* @"[j]str_ndiiiddd_00[ldcstring]"(%Env* %p0), !dbg !51
store %Object* %t0, %Object** %r1, !dbg !56
%t1 = load %Object** %r0, !dbg !52
%t2 = call %Object* @"[j]Main.scAttr(Ltest/sub/SubClass;)[get]"(%Env* %p0, %Object* %t1), !dbg !64
store %Object* %t2, %Object** %$r2, !dbg !45
%t3 = load %Object** %$r2, !dbg !65
%t4 = call i8 @“checknull”(%Env* %p0, %Object* %t3), !dbg !43
call void @"[j]test.sub.SubClass.throwSomething()V[Invokevirtual(Main,test/sub/SubClass)]"(%Env* %p0, %Object* %t3), !dbg !50
%t5 = call %Object* @"[j]str_777_00[ldcstring]"(%Env* %p0), !dbg !49
store %Object* %t5, %Object** %$r3, !dbg !46
%t6 = load %Object** %$r3, !dbg !67
%t7 = call i32 @"[j]java.lang.String.length()I[Invokevirtual(Main,java/lang/String)]"(%Env* %p0, %Object* %t6), !dbg !54
store i32 %t7, i32* %$i1, !dbg !59
%t8 = load %Object** %r1, !dbg !55
%t9 = call i32 @"[j]java.lang.String.length()I[Invokevirtual(Main,java/lang/String)]"(%Env* %p0, %Object* %t8), !dbg !44
store i32 %t9, i32* %$i2, !dbg !60
%t11 = load i32* %$i1, !dbg !53
%t12 = load i32* %$i2, !dbg !61
%t10 = add i32 %t11, %t12, !dbg !47
store i32 %t10, i32* %$i3, !dbg !62
%t13 = load i32* %$i3, !dbg !66
ret i32 %t13, !dbg !48
}
Debugging Metadata:
= !{!7}
!llvm.module.flags = !{!3, !4}
!0 = !{}
!1 = !{!“Main.java”, !"/Users/generalsolutions/Documents/runtime-EclipseApplication/RobovmConsole/src/main/java/"}
!2 = !{!18, !38, !68, !78}
!3 = !{i32 2, !“Dwarf Version”, i32 2}
!4 = !{i32 2, !“Debug Info Version”, i32 2}
!5 = !{!“0x29”, !1} ; [ DW_TAG_file_type ] [ /Users/generalsolutions/Documents/runtime-EclipseApplication/RobovmConsole/src/main/java/Main.java ]
!6 = !{!“0x258”} ; [ DW_TAG_expression ]
!7 = !{!“0x11\0011\00RoboVM 2.2.0-SNAPSHOT\001\00\000\00\001”, !1, !0, !0, !2, !0, !0} ; [ DW_TAG_compile_unit ] [ /Users/generalsolutions/Documents/runtime-EclipseApplication/RobovmConsole/src/main/java/Main.java ] [ DW_LANG_Java ]
!8 = !{!“0x24\00boolean\000\008\008\000\000\002”, null, null} ; [ DW_TAG_base_type ] [ boolean ] [ line 0, size 8, align 8, offset 0, enc DW_ATE_boolean ]
!9 = !{!“0x24\00byte\000\008\008\000\000\006”, null, null} ; [ DW_TAG_base_type ] [ byte ] [ line 0, size 8, align 8, offset 0, enc DW_ATE_signed_char ]
!10 = !{!“0x24\00short\000\0016\0016\000\000\005”, null, null} ; [ DW_TAG_base_type ] [ short ] [ line 0, size 16, align 16, offset 0, enc DW_ATE_signed ]
!11 = !{!“0x24\00char\000\0016\0016\000\000\007”, null, null} ; [ DW_TAG_base_type ] [ char ] [ line 0, size 16, align 16, offset 0, enc DW_ATE_unsigned ]
!12 = !{!“0x24\00int\000\0032\0032\000\000\005”, null, null} ; [ DW_TAG_base_type ] [ int ] [ line 0, size 32, align 32, offset 0, enc DW_ATE_signed ]
!13 = !{!“0x24\00long\000\0064\0064\000\000\005”, null, null} ; [ DW_TAG_base_type ] [ long ] [ line 0, size 64, align 64, offset 0, enc DW_ATE_signed ]
!14 = !{!“0x24\00float\000\0032\0032\000\000\004”, null, null} ; [ DW_TAG_base_type ] [ float ] [ line 0, size 32, align 32, offset 0, enc DW_ATE_float ]
!15 = !{!“0x24\00double\000\0064\0064\000\000\004”, null, null} ; [ DW_TAG_base_type ] [ double ] [ line 0, size 64, align 64, offset 0, enc DW_ATE_float ]
!16 = !{!“0xf\00Env\000\0064\0064\000\000”, null, null, null} ; [ DW_TAG_pointer_type ] [ Env ] [ line 0, size 64, align 64, offset 0 ] [ from ]
!17 = !{!“0xf\00Object\000\0064\0064\000\000”, null, null, null} ; [ DW_TAG_pointer_type ] [ Object ] [ line 0, size 64, align 64, offset 0 ] [ from ]
!18 = !{!“0x2e\00[J]Main.(I)V\00[J]Main.(I)V\00\007\000\001\000\000\00256\000\007”, !1, !5, !22, null, void (%Env*, %Object*, i32)* @"[J]Main.(I)V", null, null, !20} ; [ DW_TAG_subprogram ] [ line 7 ] [ def ] [ [J]Main.(I)V ]
!19 = !{!“0x101\00env\0016777223\000”, !18, !5, !17} ; [ DW_TAG_arg_variable ] [ env ] [ line 7 ]
!20 = !{}
!21 = !{null, !16, !17, !12}
!22 = !{!“0x15\00\000\000\000\000\000\000”, null, null, null, !21, null, null, null} ; [ DW_TAG_subroutine_type ] [ line 0, size 0, align 0, offset 0 ] [ from ]
!23 = !{i32 9, i32 0, !18, null}
!24 = !{i32 7, i32 0, !18, null}
!25 = !{i32 8, i32 0, !18, null}
!26 = !{i32 9, i32 0, !18, null}
!27 = !{i32 10, i32 0, !18, null}
!28 = !{i32 9, i32 0, !18, null}
!29 = !{i32 8, i32 0, !18, null}
!30 = !{i32 7, i32 0, !18, null}
!31 = !{i32 7, i32 0, !18, null}
!32 = !{i32 9, i32 0, !18, null}
!33 = !{i32 7, i32 0, !18, null}
!34 = !{i32 7, i32 0, !18, null}
!35 = !{i32 9, i32 0, !18, null}
!36 = !{i32 9, i32 0, !18, null}
!37 = !{i32 9, i32 0, !18, null}
!38 = !{!“0x2e\00[J]Main.instanceMethod(I)I\00[J]Main.instanceMethod(I)I\00\0013\000\001\000\000\00256\000\0013”, !1, !5, !42, null, i32 (%Env*, %Object*, i32)* @"[J]Main.instanceMethod(I)I", null, null, !40} ; [ DW_TAG_subprogram ] [ line 13 ] [ def ] [ [J]Main.instanceMethod(I)I ]
!39 = !{!“0x101\00env\0016777229\000”, !38, !5, !17} ; [ DW_TAG_arg_variable ] [ env ] [ line 13 ]
!40 = !{}
!41 = !{!12, !16, !17, !12}
!42 = !{!“0x15\00\000\000\000\000\000\000”, null, null, null, !41, null, null, null} ; [ DW_TAG_subroutine_type ] [ line 0, size 0, align 0, offset 0 ] [ from ]
!43 = !{i32 14, i32 0, !38, null}
!44 = !{i32 15, i32 0, !38, null}
!45 = !{i32 14, i32 0, !38, null}
!46 = !{i32 15, i32 0, !38, null}
!47 = !{i32 15, i32 0, !38, null}
!48 = !{i32 15, i32 0, !38, null}
!49 = !{i32 15, i32 0, !38, null}
!50 = !{i32 14, i32 0, !38, null}
!51 = !{i32 13, i32 0, !38, null}
!52 = !{i32 14, i32 0, !38, null}
!53 = !{i32 15, i32 0, !38, null}
!54 = !{i32 15, i32 0, !38, null}
!55 = !{i32 15, i32 0, !38, null}
!56 = !{i32 13, i32 0, !38, null}
!57 = !{i32 13, i32 0, !38, null}
!58 = !{i32 13, i32 0, !38, null}
!59 = !{i32 15, i32 0, !38, null}
!60 = !{i32 15, i32 0, !38, null}
!61 = !{i32 15, i32 0, !38, null}
!62 = !{i32 15, i32 0, !38, null}
!63 = !{i32 13, i32 0, !38, null}
!64 = !{i32 14, i32 0, !38, null}
!65 = !{i32 14, i32 0, !38, null}
!66 = !{i32 15, i32 0, !38, null}
!67 = !{i32 15, i32 0, !38, null}
!68 = !{!“0x2e\00[J]Main.anotherMethod(JJLjava/lang/String;)I\00[J]Main.anotherMethod(JJLjava/lang/String;)I\00\0019\000\001\000\000\00256\000\0019”, !1, !5, !72, null, i32 (%Env*, i64, i64, %Object*)* @"[J]Main.anotherMethod(JJLjava/lang/String;)I", null, null, !70} ; [ DW_TAG_subprogram ] [ line 19 ] [ def ] [ [J]Main.anotherMethod(JJLjava/lang/String;)I ]
!69 = !{!“0x101\00env\0016777235\000”, !68, !5, !17} ; [ DW_TAG_arg_variable ] [ env ] [ line 19 ]
!70 = !{}
!71 = !{!12, !16, !17, !13, !13, !17}
!72 = !{!“0x15\00\000\000\000\000\000\000”, null, null, null, !71, null, null, null} ; [ DW_TAG_subroutine_type ] [ line 0, size 0, align 0, offset 0 ] [ from ]
!73 = !{i32 19, i32 0, !68, null}
!74 = !{i32 19, i32 0, !68, null}
!75 = !{i32 19, i32 0, !68, null}
!76 = !{i32 19, i32 0, !68, null}
!77 = !{i32 19, i32 0, !68, null}
!78 = !{!“0x2e\00[J]Main.main([Ljava/lang/String;)V\00[J]Main.main([Ljava/lang/String;)V\00\0024\000\001\000\000\00256\000\0024”, !1, !5, !82, null, void (%Env*, %Object*)* @"[J]Main.main([Ljava/lang/String;)V", null, null, !80} ; [ DW_TAG_subprogram ] [ line 24 ] [ def ] [ [J]Main.main([Ljava/lang/String;)V ]
!79 = !{!“0x101\00env\0016777240\000”, !78, !5, !17} ; [ DW_TAG_arg_variable ] [ env ] [ line 24 ]
!80 = !{}
!81 = !{null, !16, !17, !17}
!82 = !{!“0x15\00\000\000\000\000\000\000”, null, null, null, !81, null, null, null} ; [ DW_TAG_subroutine_type ] [ line 0, size 0, align 0, offset 0 ] [ from ]
!83 = !{i32 29, i32 0, !78, null}
!84 = !{i32 30, i32 0, !78, null}
!85 = !{i32 45, i32 0, !78, null}
!86 = !{i32 24, i32 0, !78, null}
!87 = !{i32 29, i32 0, !78, null}
!88 = !{i32 30, i32 0, !78, null}
!89 = !{i32 24, i32 0, !78, null}
!90 = !{i32 29, i32 0, !78, null}
!91 = !{i32 29, i32 0, !78, null}
!92 = !{i32 29, i32 0, !78, null}
!93 = !{i32 24, i32 0, !78, null}
!94 = !{i32 30, i32 0, !78, null}
!95 = !{i32 29, i32 0, !78, null}
!96 = !{i32 24, i32 0, !78, null}
LLDB Backtrace:
frame #3 is implemented in assembler, frame #0 is the method whith the %env arg:
- thread #1: tid = 0xc6189, 0x000000010052861f Main`[J]Main.instanceMethod(I)I at Main.java:13, queue = ‘com.apple.main-thread’, stop reason = breakpoint 1.1
- frame #0: 0x000000010052861f Main
[J]Main.instanceMethod(I)I at Main.java:13 frame #1: 0x0000000100528586 Main
[j]Main.instanceMethod(I)I[Invokevirtual(Main,Main)] + 9
frame #2: 0x00000001005287a8 Main[J]Main.main([Ljava/lang/String;)V + 101 at Main.java:30 frame #3: 0x0000000100bd763e Main
_call0 + 142 at call0-darwin-x86_64.s:80
frame #4: 0x0000000100bbb661 MaincallVoidMethod(env=0x0000000101f4afa0, callInfo=0x00007fff5fbff500) + 145 at method.c:640 frame #5: 0x0000000100bc1cc2 Main
rvmCallVoidClassMethodA(env=0x0000000101f4afa0, clazz=0x0000000103885580, method=0x000000010388f550, args=0x0000000103869fa0) + 514 at method.c:1177
frame #6: 0x0000000100bc1d32 MainrvmCallVoidClassMethodV(env=0x0000000101f4afa0, clazz=0x0000000103885580, method=0x000000010388f550, args=0x00007fff5fbff810) + 82 at method.c:1183 frame #7: 0x0000000100bc1ead Main
rvmCallVoidClassMethod(env=0x0000000101f4afa0, clazz=0x0000000103885580, method=0x000000010388f550) + 365 at method.c:1189
frame #8: 0x0000000100bae158 MainrvmRun(env=0x0000000101f4afa0) + 344 at init.c:498 frame #9: 0x0000000100b984a2 Main
bcmain(argc=2, argv=0x00007fff5fbff918) + 178 at bc.c:97
frame #10: 0x0000000100b9d87b Mainmain(argc=2, argv=0x00007fff5fbff918) + 27 at bc.c:103 frame #11: 0x00007fff886005ad libdyld.dylib
start + 1
frame #12: 0x00007fff886005ad libdyld.dylib`start + 1
dwarfdump output: