Skip to content

proposal: add LLGo-aware LLDB integration #2154

Description

@cpunion

Motivation

LLGo emits structurally valid DWARF, but current Apple and upstream LLVM LLDB builds do not maintain a Go language plugin. A compile unit marked DW_LANG_Go therefore loses otherwise valid parameters and locals in stock LLDB.

LLGo will not add or maintain a generic LLDB Go language implementation. Native debug compile units remain DW_LANG_C, which lets stock LLDB consume their standard DWARF locations, scopes, and types. LLGo identity and runtime presentation are provided separately.

Goal

Provide an LLGo-aware LLDB integration that works with stock LLDB and real LLGo binaries:

  • launch LLDB through an installed llgo lldb command;
  • identify LLGo with DW_AT_producer = "LLGo" and a versioned debugger marker;
  • preserve normal LLDB breakpoints, stepping, frames, parameters, locals, globals, and structural types;
  • add marker-selected summaries, synthetic children, commands, and runtime views without replacing LLDB's ordinary variable model;
  • keep the integration testable on macOS Apple LLDB and Linux/Windows LLVM LLDB.

Compatibility contract

  • LLGo debug compile units use DW_LANG_C.
  • DW_AT_producer = "LLGo" remains the compiler identity used by standards-based DWARF validation.
  • __llgo_debugger_marker_v1 identifies an LLGo debugger ABI/runtime schema through LLDB's public API.
  • Targets without the marker remain ordinary C/C++ targets; unsupported marker versions fail LLGo-specific presentation clearly without breaking raw debugging.
  • The adapter must not depend on private LLDB APIs or a patched LLDB build.
  • Native macOS, Linux and Windows builds retain their platform/toolchain DWARF packaging. This proposal does not introduce native artifact repackaging or require a standalone dSYM/debug file.

The language tag is an interoperability choice only. LLGo must still emit correct DWARF types, scopes, locations, line tables, and producer metadata.

Proposed structure

  1. Compiler and artifact contract
    • emit standards-based DWARF consumable as DW_LANG_C;
    • retain the LLGo producer and versioned debugger marker;
    • describe pointer size, endianness, ABI version, and runtime-layout version.
  2. LLDB launcher and adapter
    • install and load the LLGo Python adapter through llgo lldb;
    • use public SB* APIs and preserve direct LLDB use as a raw-debugging fallback;
    • select behavior only after validating the marker/schema version.
  3. Runtime presentation
    • provide summaries and children for strings, slices, maps, channels, interfaces, function values, closures, and goroutines;
    • isolate runtime-version adapters so layout changes do not alter the generic launcher.

Execution flow

llgo lldb <executable>
    |
    +-- stock LLDB reads DW_LANG_C DWARF
    |       |
    |       +-- breakpoints, frames, variables, types, and stepping
    |
    +-- adapter checks __llgo_debugger_marker_v1
            |
            +-- supported schema: install LLGo presentation/runtime views
            +-- missing/unknown schema: keep raw debugging available

Coverage

Tests must use real LLGo binaries rather than only mocked SBValue objects:

  • parameters, named results, locals, shadowing, closures, methods, generics, and globals;
  • every primitive type plus aliases and named/recursive types;
  • arrays, strings, slices, maps, channels, interfaces, pointers, structs, and function values;
  • breakpoints, source lines, stepping, stack frames, and variable lifetimes;
  • optimized builds at O0, O1, O2, O3, Os, and Oz, with explicit expectations for optimized-out values;
  • macOS Apple LLDB and Linux/Windows LLVM LLDB;
  • marker rejection for non-LLGo C/C++ binaries and a clear response for unsupported marker versions;
  • linked executables and LLGo-built libraries where LLDB can load their debug information.

Delivery status and consolidation plan

Status checked on 2026-10-01 against xgo-dev/llgo/main at f06143ba2aac3e1658ddeecdf0ed69e1eebfe1f7. The two contributions below are implemented, validated in the configurations recorded here, and ready for review; they are not merged.

“Implemented”, “merged upstream”, and “validated on a platform” are separate states. The earlier “100% staged” report described the August fork, not delivery on main.

Capability Current main Current contribution
Standards-based DWARF, DW_LANG_C, producer identity and stock LLDB baseline Merged in #2141, with subsequent compiler/debug fixes #2142 implements current C ABI/O0 homes, Darwin line/cache fixes and native default DWARF
Installed llgo lldb, marker validation and raw-debugging fallback Merged in #2211 Preserved and extended by #2712
String and slice presentation Merged in #2240 Revalidated with the advanced views in #2712
Canonical, versioned debugger ABI/runtime schema Basic native marker exists #2712 implements schema v1/runtime layout v2, target pointer size and byte order
Interfaces, function values, closures, bound methods, maps and channels Not integrated #2712 implements and validates the current-runtime adapters and typed map/channel DWARF
Live goroutine enumeration, thread mapping and native backtraces LLDB views not integrated #2712 reuses the existing native traceback registry; no additional scheduler or goroutine registry

Two contributions own this native milestone:

  1. Native DWARF correctness and defaults — debug: consolidate native DWARF correctness and defaults #2142, head 08d0aef2e, directly based on current main. This consolidates debug: preserve O0 variable locations #2235, cabi: preserve debug variable homes #2148, fix(pclntab): preserve Darwin line sites with DWARF #2157 and build: stabilize Darwin DWARF debug maps across cache hits #2202, and relevant native fault/inline-frame acceptance from [Based on #139] debug: validate fault boundaries and final Wasm DWARF cpunion/llgo#140. Current Windows CodeView, proven parameter-home reuse and synthetic debug locations are preserved. Native defaults retain DWARF, with the cmd/link Darwin c-shared exception; ordinary Wasm/embedded defaults remain unchanged. Existing mixed Go/C callback tests provide boundary coverage.
  2. Common debugger ABI and runtime presentation — debug: unify runtime schema and LLDB/GDB views #2712, head 316408b1c, also directly based on current main. This consolidates [Based on #114] debug: define the common debugger ABI cpunion/llgo#120/update ssa.Slice #99/TestTypes #101/closure #103/llvm v0.7.5 #106/build: decodeLinkFile (support *.lla) #130 using the current single C ABI and native runtime layout. The LLDB part completes this focused proposal; GDB and the portable schema also serve umbrella Proposal: cross-platform source-level debugging for native, embedded, WASI, and browser WebAssembly #2164. Native adapters do not depend on typed artifacts or llgo debug.

The two PRs are independent of each other at the branch level. The artifact/session and Wasm frontend chain is #2712 → #2269 → #2713; the old sixteen-PR fork chain is no longer the integration order.

Current validation evidence

These are tests of the new contributions, not historical fork results and not claims of merged-main delivery.

Contribution/configuration Verified in this round
#2142, macOS/arm64, Go 1.27.0, LLVM 22.1.8, Apple LLDB 2100 Full SSA/CL/cltest tests; C ABI home identity/alignment/debug-storage checks; final DWARF at O0/O2; cold/warm Darwin debug maps; runtime Caller/CallersFrames/log line precision; default/explicit DWARF policy
#2142, real LLDB sessions 241 main assertions and 3 mixed Go/C assertions; marker fallbacks; exact panic/divide/nil caller locations; O2 inline frames and step-over
#2712, macOS/arm64, Apple LLDB 2100 276/276 runtime/value/goroutine assertions, 3/3 mixed Go/C assertions, and non-LLGo/unknown-record raw-debugger fallbacks
#2712, Linux/arm64, LLVM 22 and GDB Advanced values, goroutine enumeration and backtraces, selected-thread restoration and unsupported-record fallbacks
Windows Existing complete LLDB qualification passes x64/x86/ARM64 with MSVC and MinGW. The new GDB capability matrix and its upstream unwind limits are recorded below.

Neither local evidence nor a ready-for-review state implies that all platform/optimization combinations have passed. In particular, the O0/O2 checks above do not claim complete O1/O3/Os/Oz qualification, and the remaining broad platform/optimization qualification still needs CI evidence; combined validation is recorded below.

Current review and CI status

Published heads: #2142 08d0aef2e, #2712 316408b1c, #2269 735510143, #2713 b4d3f52dd. All remain contributions, not merged delivery. The four new #2142 and five new #2712 review threads have been addressed and replied to. The previous #2142 and #2712 heads passed all applicable PR checks; fresh CI is running after the review fixes and dependent restack.

The required acceptance distinguishes complete native runtime inspection from narrower, working debugger capabilities:

Target / host LLDB GDB
Native Linux x64 Complete runtime/value/worker-stack CI Values/registry plus strict complete-worker CI
Native Linux arm64 Locally qualified Both acceptance levels locally qualified
Native macOS arm64 Complete runtime acceptance Native process backend unavailable; remote embedded sessions work
Native macOS Intel Complete runtime acceptance Values, three-thread mapping, main stack and fallback checks; blocked-worker unwind remains unavailable
Native Windows x64/x86, MSVC and MinGW Complete runtime acceptance in all four configurations Both levels pass in all four configurations
Native Windows ARM64, MSVC and MinGW Complete runtime acceptance Basic values/registry/main-stack acceptance passes both ABIs; complete-worker unwind remains limited by stock GDB 18 PAC handling
Embedded Cortex-M3, Linux x64/macOS arm64/Windows x64 hosts Real preloaded and reset/download/reset QEMU sessions Same real sessions, including actual image writes

Intel GDB's dyld image-info ABI limit reproduces with a plain C pthread program. Windows ARM64 GDB truncates stacks at PAC-signed system return addresses. The strict complete-worker test is retained and remains required on supported platforms; neither restricted platform is counted as complete GDB runtime support. No patched GDB is bundled. Broader MCU architectures require their own target qualification; no physical-probe execution is claimed.

Evidence: Intel LLDB full / GDB basic, Windows GDB matrix, Linux/Windows embedded matrix, Windows LLDB launcher fix and successful download/session rerun. The last fix configures Python only in LLDB child processes, leaving the host Python debug-server process unchanged.

The four contributions merge without conflicts. After the review fixes, their combined tree passes eight debugger/ABI/browser/SSA Go packages, changed workflow syntax checks, the native panic/inline/O2 mutable-aggregate acceptance, and LLDB runtime acceptance (293 assertions plus 3 mixed Go/C assertions). Native registry retention also passes actual macOS and Linux ARM64 LTO/section-GC checks. The dedicated panic/inline suite remains qualified on Linux/macOS, separately from Windows runtime LLDB and PCLN coverage. Browser/WASI capability limits below are unchanged; native or QEMU passes do not imply Wasm source-debugger or worker-stack support.

Completion criteria

  • Native DWARF and installed LLDB baseline are merged.
  • String/slice presentation is merged.
  • The canonical schema and remaining runtime views are ported to current main and have the current validation evidence above.
  • Native goroutine/thread views are tested against the current traceback registry and pthread model in the recorded Darwin/Linux configurations.
  • debug: consolidate native DWARF correctness and defaults #2142 and debug: unify runtime schema and LLDB/GDB views #2712 are reviewed, integrated together and merged upstream.
  • Real-program acceptance completes the supported compiler/debugger/platform and optimization matrix, including Windows, unknown-schema fallback and optimized-out values.
  • Record the final merged revisions and qualification matrix; old LLVM 19 results must not be presented as current LLVM 22 results.

Do not mark this proposal complete merely because the implementation is ready for review. Wasm worker/goroutine reconstruction and a maintained Go expression evaluator remain outside this native LLDB milestone.

Non-goals

  • Emitting or supporting DW_LANG_Go.
  • Maintaining a generic LLDB Go language plugin or Go expression evaluator.
  • Requiring a patched LLDB build or private LLDB APIs.
  • Changing Go or DWARF semantics to match limitations in a particular LLDB release.
  • Making Python formatting replace standards-based DWARF validation.

Acceptance test layout

Standalone native, runtime-adapter, embedded and hardware acceptance lives under test/debug/{native,runtime,embedded,hardware}. Existing fixture modules are preserved; package-private tests stay with their implementation. User documentation is in doc/debugging.md. Both debuggers use real binaries, strict source/value assertions and explicit capability boundaries. QEMU results do not establish physical-board qualification.

Current-head full PR CI remains in progress. Local and focused integration results above are separate from completion of that matrix; no coverage threshold or assertion has been relaxed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions