rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.65k stars 12.75k forks source link

Debug info is broken on macOS when using --remap-path-prefix #132143

Open csmulhern opened 3 weeks ago

csmulhern commented 3 weeks ago

This can be easily reproduced with a simple program.

// main.rs
fn main() {
    println!("Hello, world!");
}

Without --remap-path-prefix, building with unpacked debug info:

rustc main.rs --codegen=debuginfo=2 --codegen=split-debuginfo=unpacked

Results in a binary that has an OSO entry pointing to the object file containing the debug info:

> nm -pa main | rg OSO
0000000000000000 - 00 0001   OSO /Users/cameron/Desktop/broken/main.main.7c41ea6d61ccd5c8-cgu.0.rcgu.o
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libstd-b0083070c892a1db.rlib(std-b0083070c892a1db.std.1bb08b5702199c76-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libpanic_unwind-8282820217d7b362.rlib(panic_unwind-8282820217d7b362.panic_unwind.edd611859befea2b-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libmemchr-350512940f04084a.rlib(memchr-350512940f04084a.memchr.163a0d7c2b1b5170-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/librustc_demangle-e1d006f163566466.rlib(rustc_demangle-e1d006f163566466.rustc_demangle.763a0c92458f345-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/liballoc-edb678dd3e28691a.rlib(alloc-edb678dd3e28691a.alloc.7c7540ab8626f01a-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcore-2447397acf63b01e.rlib(core-2447397acf63b01e.core.5213bbcd403abe9e-cgu.0.rcgu.o)

With --remap-path-prefix:

rustc main.rs --codegen=debuginfo=2 --codegen=split-debuginfo=unpacked --remap-path-prefix=/Users/cameron/Desktop/broken=

Results in a binary that is missing OSO entries for the remapped object files:

> nm -pa main | rg OSO
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libstd-b0083070c892a1db.rlib(std-b0083070c892a1db.std.1bb08b5702199c76-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libpanic_unwind-8282820217d7b362.rlib(panic_unwind-8282820217d7b362.panic_unwind.edd611859befea2b-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libmemchr-350512940f04084a.rlib(memchr-350512940f04084a.memchr.163a0d7c2b1b5170-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/librustc_demangle-e1d006f163566466.rlib(rustc_demangle-e1d006f163566466.rustc_demangle.763a0c92458f345-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/liballoc-edb678dd3e28691a.rlib(alloc-edb678dd3e28691a.alloc.7c7540ab8626f01a-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcore-2447397acf63b01e.rlib(core-2447397acf63b01e.core.5213bbcd403abe9e-cgu.0.rcgu.o)

Note how the first OSO entry from the first command is missing from the second:

0000000000000000 - 00 0001   OSO /Users/cameron/Desktop/broken/main.main.7c41ea6d61ccd5c8-cgu.0.rcgu.o

I believe the same underlying issue prevents --split-debuginfo=packed from generating a dSYM containing debug info for the object files containing the remapped path prefix, as I believe dsymutil is just using the OSO entries to create a self contained set of DWARF debug info.

Packed debug info without remapping:

rustc main.rs --codegen=debuginfo=2 --codegen=split-debuginfo=packed

Results in a complete dSYM:

> dwarfdump main.dSYM | rg "main.rs" -B 8
main.dSYM/Contents/Resources/DWARF/main:    file format Mach-O arm64

.debug_info contents:
0x00000000: Compile Unit: length = 0x0000091b, format = DWARF32, version = 0x0004, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x0000091f)

0x0000000b: DW_TAG_compile_unit
              DW_AT_producer    ("clang LLVM (rustc version 1.82.0 (f6e511eec 2024-10-15))")
              DW_AT_language    (DW_LANG_Rust)
              DW_AT_name    ("main.rs/@/main.4b21619d1e36c66a-cgu.0")
--
                DW_AT_name  ("main")

0x000008d6:     DW_TAG_subprogram
                  DW_AT_low_pc  (0x0000000100001720)
                  DW_AT_high_pc (0x0000000100001754)
                  DW_AT_frame_base  (DW_OP_reg29 W29)
                  DW_AT_linkage_name    ("_ZN4main4main17h0cc9ac8d6b33b55fE")
                  DW_AT_name    ("main")
                  DW_AT_decl_file   ("/Users/cameron/Desktop/broken/main.rs")

Whereas the remapped version:

rustc main.rs --codegen=debuginfo=2 --codegen=split-debuginfo=packed --remap-path-prefix=/Users/cameron/Desktop/broken=

Does not:

> dwarfdump main.dSYM | rg "main.rs" -B 8

All these issues are reproducible on a recent nightly (rustc version 1.84.0-nightly (a93c1718c 2024-10-24)).

csmulhern commented 3 weeks ago

This is just a guess, but I suspect the issue is to do with the fact that remapped paths become relative paths, whereas OSO paths seem to always be absolute.

For example, if I use the oso_prefix linker argument to do path remapping specifically for the OSO stabs, the path becomes the relative path rooted at /.

rustc main.rs --codegen=debuginfo=2 --codegen=split-debuginfo=unpacked --codegen=link-args=-Wl,-oso_prefix,/Users/cameron/Desktop/broken
> nm -pa main | rg OSO
0000000000000000 - 00 0001   OSO /main.main.4b21619d1e36c66a-cgu.0.rcgu.o
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libstd-0b4a354a5d882f18.rlib(std-0b4a354a5d882f18.std.d8d90c69e022292b-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libpanic_unwind-00e89274fccf37d9.rlib(panic_unwind-00e89274fccf37d9.panic_unwind.ea3026af965941fa-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libmemchr-726032628236814d.rlib(memchr-726032628236814d.memchr.5ae0b6d692968ecf-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/liballoc-a7504b44dda8a2a3.rlib(alloc-a7504b44dda8a2a3.alloc.764fc8c78a1bb3e1-cgu.0.rcgu.o)
0000000000000000 - 00 0001   OSO /Users/cameron/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/aarch64-apple-darwin/lib/libcore-a17e2a568e77fc15.rlib(core-a17e2a568e77fc15.core.fafc87a594706398-cgu.0.rcgu.o)
csmulhern commented 3 weeks ago

After a little more investigation, I'm wondering if the fact that DW_AT_comp_dir is missing when --remap-path-prefix is used is responsible for this. It's possible ld-prime is only emitting OSO stabs when both DW_AT_name and DW_AT_comp_dir are specified in the debug info. I don't have access to an old version of macOS using ld64 to see if the same issue is present there as well.

I will file feedback with Apple and hopefully ld-prime can be updated to support this. A mitigation on the rustc side would be to not remap paths in DWARF debug info on macOS, and rely on the oso_prefix linker option for path remapping instead.