Search code examples
clangllvmlldb

Cannot set breakpoints in LLDB and/or VSCode


I've created a very basic LLVM IR example for myself, to understand how source level debugging works.

Given this made-up source code, in a file called blaha.txt:

extern function puts(str: string): int32;

void main() {
    puts("Hello, World!\n");
}

This is the IR that would be generated if this were to be compiled:

; ModuleID = 'blaha.txt'
source_filename = "blaha.txt"

@0 = private unnamed_addr constant [14 x i8] c"Hello, World!\00", align 1

declare i32 @puts(ptr %0)

define i32 @main() !dbg !4 {
entry:
  %puts = call i32 @puts(ptr @0), !dbg !7
  ret i32 0, !dbg !8
}

!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !{i32 2, !"Dwarf Version", i32 4}
!2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false)
!3 = !DIFile(filename: "blaha.txt", directory: "e:\\slask\\blahllvm")
!4 = distinct !DISubprogram(name: "main", scope: null, file: !3, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !6)
!5 = !DISubroutineType(flags: DIFlagPrototyped, types: !6)
!6 = !{}
!7 = !DILocation(line: 4, column: 1, scope: !4)
!8 = !DILocation(line: 5, column: 1, scope: !4)

However I cannot set breakpoints in LLDB and/or VSCode which I expect to work.

Now this compiles and runs flawlessly with clang -O0 -g file.obj -o file.exe for example. I'm on Windows, so I even get a PDB-file.

However, when I load this into lldb, I cannot set breakpoints. Observe:

E:\slask\blahllvm\bin\Debug\net8.0>set LLDB_USE_NATIVE_PDB_READER=yes

E:\slask\blahllvm\bin\Debug\net8.0>lldb file.exe
(lldb) target create "file.exe"
(lldb) Current executable set to 'E:\slask\blahllvm\bin\Debug\net8.0\file.exe' (x86_64).
(lldb) add-dsym file.pdb
symbol file 'E:\slask\blahllvm\bin\Debug\net8.0\file.pdb' has been added to 'E:\slask\blahllvm\bin\Debug\net8.0\file.exe'
(lldb) breakpoint set -f blaha.txt -l 4
Breakpoint 1: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) breakpoint list
Current breakpoints:
1: file = 'blaha.txt', line = 4, exact_match = 0, locations = 0 (pending)

(lldb) breakpoint set -n main
Breakpoint 2: no locations (pending).
WARNING:  Unable to resolve breakpoint to any actual locations.
(lldb) breakpoint list
Current breakpoints:
1: file = 'blaha.txt', line = 4, exact_match = 0, locations = 0 (pending)

2: name = 'main', locations = 0 (pending)

(lldb) run
(lldb) Process 11344 launched: 'E:\slask\blahllvm\bin\Debug\net8.0\file.exe' (x86_64)
Process 11344 exited with status = 0 (0x00000000)
(lldb)

Does anyone have any idea of what I'm missing?


Solution

  • I figured it out, I needed to add a module flag (CodeView) to make it work with MS debuggers:

    !llvm.module.flags = !{!0, !1, !2}
    !0 = !{i32 2, !"Debug Info Version", i32 3}
    !1 = !{i32 2, !"Dwarf Version", i32 4}
    !2 = !{i32 2, !"CodeView", i32 1}