Embed the gdb pretty printers in the .debug_gdb_scripts section of ELF binaries built with -debug, and move the script next to the runtime it reads

This commit is contained in:
gingerBill committed 2026-10-08 11:54:08 +01:00
1 parent 5caf8b7408
commit f689471c90
2 files changed
+44 -3

No files matched your search

@@ -1,7 +1,10 @@
# Pretty printers for Odin types in gdb and lldb
#
# gdb: source <odin>/misc/odin_debugger.py
# lldb: command script import <odin>/misc/odin_debugger.py
# gdb: source <odin>/base/runtime/odin_debugger.py
# lldb: command script import <odin>/base/runtime/odin_debugger.py
#
# gdb also loads it by itself from the `.debug_gdb_scripts` section of an ELF binary built with `-debug`,
# once that binary's directory is trusted, with `add-auto-load-safe-path <directory>`
#
# Shown: `string`, `string16`, slices, dynamic arrays (and fixed capacity ones), maps as their entries,
# and unions as the variant they hold, or `nil`.
@@ -243,7 +246,11 @@ if gdb is not None:
return _GdbArray(val, kind)
return None
gdb.pretty_printers.append(_gdb_lookup)
# NOTE: loaded from a binary's `.debug_gdb_scripts` section, the printers belong to that binary
if gdb.current_objfile() is not None:
gdb.current_objfile().pretty_printers.append(_gdb_lookup)
else:
gdb.pretty_printers.append(_gdb_lookup)
################################################################################
+34
View File
@@ -3864,6 +3864,40 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
}
if (build_context.ODIN_DEBUG) {
// NOTE(bill): gdb runs the pretty printers of `base/runtime/odin_debugger.py` from the `.debug_gdb_scripts` section of an ELF binary,
// once the user trusts its directory; lldb reads no such section.
// The section is written in assembly, as a global cannot be made a section that is never loaded into memory,
// which is what keeps the linker from dropping it, and lets it merge the copies of several objects.
if (build_context.metrics.os != TargetOs_windows && build_context.metrics.os != TargetOs_darwin && !is_arch_wasm()) {
String path = concatenate_strings(temporary_allocator(), odin_root_dir(), str_lit("base/runtime/odin_debugger.py"));
gbFileContents fc = gb_file_read_contents(heap_allocator(), false, alloc_cstring(temporary_allocator(), path));
if (fc.data != nullptr) {
// an entry of kind 4 is the script's name, a newline, then its text
gbString s = gb_string_make(heap_allocator(), ".pushsection \".debug_gdb_scripts\", \"MS\", %progbits, 1\n.byte 4\n.ascii \"odin_debugger.py\\n\"\n.ascii \"");
defer (gb_string_free(s));
for (isize i = 0; i < fc.size; i++) {
u8 c = (cast(u8 *)fc.data)[i];
switch (c) {
case '\r': break;
case '\n': s = gb_string_appendc(s, "\\n\"\n.ascii \""); break;
case '\t': s = gb_string_appendc(s, "\\t"); break;
case '\\': s = gb_string_appendc(s, "\\\\"); break;
case '"': s = gb_string_appendc(s, "\\\""); break;
default:
if (c < 0x20 || c >= 0x7f) {
s = gb_string_append_fmt(s, "\\%03o", c);
} else {
s = gb_string_append_length(s, &c, 1);
}
break;
}
}
s = gb_string_appendc(s, "\"\n.byte 0\n.popsection\n");
gb_file_free_contents(&fc);
LLVMAppendModuleInlineAsm(default_module->mod, s, gb_string_length(s));
}
}
// Custom `.raddbg` section for its debugger
if (build_context.metrics.os == TargetOs_windows) {
lbModule *m = default_module;