Use logging module for better control and configurability
print(
1# GDB Python script to handle Cargo `<exe>.trim-paths.jsonl` files from the trim-paths feature2# - https://github.com/rust-lang/cargo/issues/121373# - https://github.com/rust-lang/rust/issues/11154045import json6import os7import gdb8import sys91011# https://doc.guix.gnu.org/gdb/16.3/en/html_node/Source-Path.html#index-set-substitute_002dpath12def _process_v1_trim_paths(lines, trim_paths_path):13 for idx, line in enumerate(lines[2:], start=3):14 try:15 entry = json.loads(line)16 if "from" in entry and "to" in entry:17 cmd = f'set substitute-path "{entry["from"]}" "{entry["to"]}"'18 gdb.execute(cmd)19 except json.JSONDecodeError:20 print(21 f"(rust-gdb) warning: invalid JSON on line {idx} of {trim_paths_path}",22 file=sys.stderr,23 )242526def _load_trim_paths(filepath):27 trim_paths_path = f"{filepath}.trim-paths.jsonl"2829 # FIXME: It might be worth looking into the debuginfod fetch content if the local file30 # doesn't exists (maybe with `debuginfod-find debuginfo`).31 if not os.path.isfile(trim_paths_path):32 return3334 try:35 # Load all the lines of the trim-paths file36 with open(trim_paths_path, "r", encoding="utf-8") as f:37 lines = [line.strip() for line in f]3839 # Abort if we have less than 3 lines as that means that we cannot have any40 # substitutions (header + metadata is already 2 lines)41 if not lines or len(lines) < 3:42 return4344 # Try loading the header line, which contains the version (v) field45 try:46 header = json.loads(lines[0])47 ver = header["v"]48 except json.JSONDecodeError:49 print(50 f"(rust-gdb) warning: header line 1 of {trim_paths_path} is not valid JSON",51 file=sys.stderr,52 )53 return5455 # We only handle version 156 if ver == 1:57 _process_v1_trim_paths(lines, trim_paths_path)58 else:59 print(60 f"(rust-gdb) warning: unsupported trim-paths version {ver}: {trim_paths_path}",61 file=sys.stderr,62 )63 except Exception as e:64 print(65 f"(rust-gdb) warning: failed to process trim-paths mappings: {e} of {trim_paths_path}",66 file=sys.stderr,67 )686970def _on_objfile(objfile):71 filepath = objfile.filename7273 if not filepath or not objfile.is_valid() or not os.path.isfile(filepath):74 return7576 _load_trim_paths(filepath)777879def _on_progspace(progspace):80 filepath = progspace.filename8182 if not filepath or not os.path.isfile(filepath):83 return8485 _load_trim_paths(filepath)868788def _on_new_objfile(event):89 _on_objfile(event.new_objfile)909192def _on_executable_changed(event):93 _on_progspace(event.progspace)949596# Setup the events for new objfile (so) and new executable97# https://doc.guix.gnu.org/gdb/16.3/en/html_node/Events-In-Python.html98#99# FIXME: should we handle clear/free events?100gdb.events.new_objfile.connect(_on_new_objfile)101gdb.events.executable_changed.connect(_on_executable_changed)102103# Load the trim-paths files for the already loaded objfiles104for objfile in gdb.objfiles():105 _on_objfile(objfile)
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.