vaivaswatha / debugir

DebugIR: Debugging LLVM-IR Files
Apache License 2.0
125 stars 18 forks source link

Breakpoint not working using LLVM-18 #19

Closed Remodor closed 1 month ago

Remodor commented 1 month ago

After building I followed the exact instructions in multiple ways and can't get the desired output.

Prerequisites

Steps to Reproduce

hello.c ```c #include #include int main(int argc, char *argv[]) { if (!strcmp(argv[0], "hello")) { printf("Hello World\n"); } else { printf("No hello\n"); } return 0; } ```

using this command:

clang -emit-llvm -S hello.c

producing hello.ll:

hello.ll ```llvm ; ModuleID = 'hello.c' source_filename = "hello.c" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" @.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @.str.1 = private unnamed_addr constant [13 x i8] c"Hello World\0A\00", align 1 @.str.2 = private unnamed_addr constant [10 x i8] c"No hello\0A\00", align 1 ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main(i32 noundef %0, ptr noundef %1) #0 { %3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca ptr, align 8 store i32 0, ptr %3, align 4 store i32 %0, ptr %4, align 4 store ptr %1, ptr %5, align 8 %6 = load ptr, ptr %5, align 8 %7 = getelementptr inbounds ptr, ptr %6, i64 0 %8 = load ptr, ptr %7, align 8 %9 = call i32 @strcmp(ptr noundef %8, ptr noundef @.str) #3 %10 = icmp ne i32 %9, 0 br i1 %10, label %13, label %11 11: ; preds = %2 %12 = call i32 (ptr, ...) @printf(ptr noundef @.str.1) br label %15 13: ; preds = %2 %14 = call i32 (ptr, ...) @printf(ptr noundef @.str.2) br label %15 15: ; preds = %13, %11 ret i32 0 } ; Function Attrs: nounwind willreturn memory(read) declare i32 @strcmp(ptr noundef, ptr noundef) #1 declare i32 @printf(ptr noundef, ...) #2 attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #1 = { nounwind willreturn memory(read) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #2 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #3 = { nounwind willreturn memory(read) } !llvm.module.flags = !{!0, !1, !2, !3, !4} !llvm.ident = !{!5} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 8, !"PIC Level", i32 2} !2 = !{i32 7, !"PIE Level", i32 2} !3 = !{i32 7, !"uwtable", i32 2} !4 = !{i32 7, !"frame-pointer", i32 2} !5 = !{!"Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144)"} ```

using:

./debugir hello.ll

producing hello.dbg.ll:

hello.ll ```llvm ; ModuleID = 'hello.ll' source_filename = "hello.c" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" @.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @.str.1 = private unnamed_addr constant [13 x i8] c"Hello World\0A\00", align 1 @.str.2 = private unnamed_addr constant [10 x i8] c"No hello\0A\00", align 1 ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main(i32 noundef %0, ptr noundef %1) #0 !dbg !9 { %3 = alloca i32, align 4, !dbg !14 %4 = alloca i32, align 4, !dbg !16 %5 = alloca ptr, align 8, !dbg !17 store i32 0, ptr %3, align 4, !dbg !18 store i32 %0, ptr %4, align 4, !dbg !19 store ptr %1, ptr %5, align 8, !dbg !20 %6 = load ptr, ptr %5, align 8, !dbg !21 %7 = getelementptr inbounds ptr, ptr %6, i64 0, !dbg !22 %8 = load ptr, ptr %7, align 8, !dbg !23 %9 = call i32 @strcmp(ptr noundef %8, ptr noundef @.str) #3, !dbg !24 %10 = icmp ne i32 %9, 0, !dbg !25 br i1 %10, label %13, label %11, !dbg !26 11: ; preds = %2 %12 = call i32 (ptr, ...) @printf(ptr noundef @.str.1), !dbg !27 br label %15, !dbg !29 13: ; preds = %2 %14 = call i32 (ptr, ...) @printf(ptr noundef @.str.2), !dbg !30 br label %15, !dbg !32 15: ; preds = %13, %11 ret i32 0, !dbg !33 } ; Function Attrs: nounwind willreturn memory(read) declare i32 @strcmp(ptr noundef, ptr noundef) #1 declare i32 @printf(ptr noundef, ...) #2 attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #1 = { nounwind willreturn memory(read) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #2 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } attributes #3 = { nounwind willreturn memory(read) } !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} !llvm.ident = !{!6} !llvm.dbg.cu = !{!7} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{i32 8, !"PIC Level", i32 2} !2 = !{i32 7, !"PIE Level", i32 2} !3 = !{i32 7, !"uwtable", i32 2} !4 = !{i32 7, !"frame-pointer", i32 2} !5 = !{i32 2, !"Debug Info Version", i32 3} !6 = !{!"Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144)"} !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !8, producer: "LLVM Version 18.1", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) !8 = !DIFile(filename: "hello.ll", directory: "") !9 = distinct !DISubprogram(name: "main", linkageName: "main", scope: !8, file: !8, line: 10, type: !10, scopeLine: 12, spFlags: DISPFlagDefinition, unit: !7) !10 = !DISubroutineType(types: !11) !11 = !{!12, !12, !13} !12 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_unsigned) !13 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr", baseType: null, size: 64, align: 64) !14 = !DILocation(line: 12, scope: !15) !15 = distinct !DILexicalBlock(scope: !9, file: !8, line: 12) !16 = !DILocation(line: 13, scope: !15) !17 = !DILocation(line: 14, scope: !15) !18 = !DILocation(line: 15, scope: !15) !19 = !DILocation(line: 16, scope: !15) !20 = !DILocation(line: 17, scope: !15) !21 = !DILocation(line: 18, scope: !15) !22 = !DILocation(line: 19, scope: !15) !23 = !DILocation(line: 20, scope: !15) !24 = !DILocation(line: 21, scope: !15) !25 = !DILocation(line: 22, scope: !15) !26 = !DILocation(line: 23, scope: !15) !27 = !DILocation(line: 26, scope: !28) !28 = distinct !DILexicalBlock(scope: !9, file: !8, line: 26) !29 = !DILocation(line: 27, scope: !28) !30 = !DILocation(line: 30, scope: !31) !31 = distinct !DILexicalBlock(scope: !9, file: !8, line: 30) !32 = !DILocation(line: 31, scope: !31) !33 = !DILocation(line: 34, scope: !34) !34 = distinct !DILexicalBlock(scope: !9, file: !8, line: 34) ```

debugging:

lldb lli -- -jit-kind=mcjit hello.dbg.ll
(lldb) target create "lli"
Current executable set to '/lib/llvm-18/bin/lli' (x86_64).
(lldb) settings set -- target.run-args  "-jit-kind=mcjit" "hello.dbg.ll"
(lldb) break set -y hello.ll:25
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) run
Process 37146 launched: '/lib/llvm-18/bin/lli' (x86_64)
1 location added to breakpoint 1
No hello
Process 37146 exited with status = 0 (0x00000000)
vaivaswatha commented 1 month ago

I just tried the same steps, but with GDB, and it worked for me. Can you try GDB once? That way we'll be able to narrow down the problem a bit? I don't have LLDB at the moment but will try with it later on.

Remodor commented 1 month ago

Same problem:

gdb --args lli -jit-kind=mcjit hello.dbg.ll
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from lli...

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) n
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
(No debugging symbols found in lli)
(gdb) break hello.ll:25
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) run
Starting program: /usr/lib/llvm-18/bin/lli -jit-kind=mcjit hello.dbg.ll
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
warning: could not find '.gnu_debugaltlink' file for /lib/x86_64-linux-gnu/libtinfo.so.6
No hello
[Inferior 1 (process 730) exited normally]
vaivaswatha commented 1 month ago

Can you set the breakpoint at line 15 instead of line 25 and let me know what happens?

Remodor commented 1 month ago

That actually worked! Even with lldb. Adjusting the README.md would be a good help imo..

Thanks a lot. Is there a way to read memory/ content of variables?

vaivaswatha commented 1 month ago

That actually worked! Even with lldb. Adjusting the README.md would be a good help imo..

The README already mentions that the line number needs to be valid.

Thanks a lot. Is there a way to read memory/ content of variables?

Yes, but typically LLVM variables names are numbers (and GDB can't recognize them), unless the source specified proper names. To work around this you can specify the -instnamer flag to debugir to attach a valid name to variables. Then you can just print them in GDB.

vaivaswatha commented 1 month ago

Closed by https://github.com/vaivaswatha/debugir/commit/862e5030ed6fe6099c618fad81a5fea5241d30c6