Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DWARF] Crate Debug Info incomplete? #88521

Closed
ayermolo opened this issue Aug 31, 2021 · 9 comments · Fixed by #92024
Closed

[DWARF] Crate Debug Info incomplete? #88521

ayermolo opened this issue Aug 31, 2021 · 9 comments · Fixed by #92024
Assignees
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@ayermolo
Copy link

Hello.

To preface this. I know nothing about RUST and its compiler. I am coming to this issue on toolchain side BOLT/DWP and dealing with debug information that is produced.

High level summary:

I am seeing multiple Skeleton CUs that have exact same DWO ID. So for example with ThinLTO when Split dwarf is enabled in main binary there are multiple CUs that point to different .dwo files, but have the same DWO ID.

Looking in to those files in to .debug_info.dwo section. They are either exactly the same, or differ by DW_AT_linkage_name.
Although LLVM can be changed to include DW_AT_linkage_name as part of the hashing algorithm, it won't solve the issue fully.

Tools like BOLT (https://github.com/facebookincubator/BOLT), or llvm-dwp rely on DWO ID to be unique.
From DWARF 5 spec (when this was all standardized), but I think also applies to DWARF4

dwo_id (unit ID)
An 8-byte implementation-defined integer constant value, known as the compilation unit ID, that provides unique identification of a skeleton compilation unit and its associated split compilation unit in the object file named in the DW_AT_dwo_name attribute of the skeleton compilation.

Digging a bit in to it:

Looking in to one of the cases where only difference was DW_AT_linkage_name.
There are multiple modules, crates in rust land?, that are created. They define the same templated functions, and import the same functions.

For example looking at LLVM IR of one of the modules and one of the functions:

!74 = distinct !DISubprogram(name: "allocate_in<u8,alloc::alloc::Global>", linkageName: "_RNvMs_NtCsj2IQpe5qjeI_5alloc7raw_vecINtB4_6RawVechE11allocate_inCsg6LRvGNwJvd_41foo_bar", scope: !76, file: !75, line: 180, type: !96, scopeLine: 180, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !43, templateParams: !94, retainedNodes: !98)
!75 = !DIFile(filename: "<>/rust/1.53.0/src/<>/build/rust/library/alloc/src/raw_vec.rs", directory: "", checksumkind: CSK_MD5, checksum: "70792e0964fbcac42a3928c645b54f9d")
!76 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "RawVec<u8, alloc::alloc::Global>", scope: !53, file: !2, size: 128, align: 64, elements: !77, templateParams: !94, identifier: "900af9eff81db06f40b139cda685ab1")

We have a function:
alloc_in that is part of templated raw_vec
https://doc.rust-lang.org/src/alloc/raw_vec.rs.html#188
https://doc.rust-lang.org/src/alloc/raw_vec.rs.html#115

From LinkageName this is relavant?
pub mod bar { pub use foo_bar::*; }

In a different module it will have:

!74 = distinct !DISubprogram(name: "allocate_in<u8,alloc::alloc::Global>", linkageName: "_RNvMs_NtCsj2IQpe5qjeI_5alloc7raw_vecINtB4_6RawVechE11allocate_inCskK341NkcZ13_41foo_bar2", scope: !76, file: !75, line: 180, type: !96, scopeLine: 180, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !43, templateParams: !94, retainedNodes: !98)
!75 = !DIFile(filename: "<>/rust/1.53.0/src/<>/build/rust/library/alloc/src/raw_vec.rs", directory: "", checksumkind: CSK_MD5, checksum: "70792e0964fbcac42a3928c645b54f9d")
!76 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "RawVec<u8, alloc::alloc::Global>", scope: !53, file: !2, size: 128, align: 64, elements: !77, templateParams: !94, identifier: "900af9eff81db06f40b139cda685ab1")

and on rust side:
pub mod bar2 { pub use foo_bar2::*; }

I haven't looked in to cases where debug information is identical, beyond that it didn't have any functions just type information {DW_TAG_namespace , DW_TAG_enumeration_type , DW_TAG_enumerator}.

To me it seems that there is debug information missing on some level that represents what crate this CU belongs.
Any thoughts?

@jyn514 jyn514 added A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 31, 2021
@jyn514
Copy link
Member

jyn514 commented Aug 31, 2021

@ayermolo I'm not familiar with debuginfo generation - you'll probably get a more prompt response if you ask in T-compiler on Zulip: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler

@jyn514
Copy link
Member

jyn514 commented Aug 31, 2021

I'm curious though why this has never come up before? It sounds like a lot of tools depend on this.

@ayermolo
Copy link
Author

Ok, I'll ask there.
No idea. As I said I am not familiar with Rust and just dealing with it's output on tools side of things. So any tips and whatnot are appreciated. Maybe my understanding of what's happening is completely wrong.

@jyn514
Copy link
Member

jyn514 commented Aug 31, 2021

Note that modules, crates, and codegen units are all different. "Modules" in Rust only affect privacy, they don't affect codegen (it sounds like you were treating LLVM modules the same as Rust modules above, and they're not the same). "Crates" are "codegen units for the rust compiler", they're all compiled at once and there's various things you can do within a crate that you can't do outside it (e.g. implement traits for a type). But the rust compiler will often split up crates into multiple LLVM codegen units before passing them to LLVM, so that it can cache them more often: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/collector/index.html

@philipc
Copy link
Contributor

philipc commented Sep 3, 2021

Can you give info on how to reproduce the problem? It sounds like you are using -C split-debuginfo=packed -Zunstable-options which is unstable and probably not widely tested.

As a wild guess, maybe -Z share-generics helps?

To me it seems that there is debug information missing on some level that represents what crate this CU belongs.

That doesn't sound like something that DWARF consumers should ever need to know.

@ayermolo
Copy link
Author

ayermolo commented Sep 3, 2021

@jyn514 Thanks for clarification.
@philipc Let me poke around internally, and read up on rust to see if I can come up with small reproducer.

@philipc
Copy link
Contributor

philipc commented Sep 22, 2021

Here's a reproduction using the xtask crate within rust-analyzer (6b77e32 with lto = true and debug = 2 added to Cargo.toml).

$ rustc +nightly --version
rustc 1.57.0-nightly (ac2d9fc50 2021-09-21)

$ RUSTFLAGS="-C split-debuginfo=packed -Zunstable-options -C save-temps" cargo +nightly build --release

   Compiling xtask v0.1.0 (/home/philipc/code/rust/rust-analyzer/xtask)
error: linking dwarf objects with `rust-llvm-dwp` failed: exit status: 1
  |
  = note: "rust-llvm-dwp" "-e" "/home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec" "-o" "/home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.dwp"
  = note: 
  = note: error: duplicate DWO ID (C6ED43DCB82FE226) in 'xtask/src/main.rs' and 'xtask/src/main.rs'
The executable has 4 skeleton units pointing to the same .dwo:
UNIT<.debug_info+0x00022cfd>: length = 0x24, format = Dwarf32, version = 4, address_size = 8, abbrev_offset = 0x0
< 0><0x0000000b>  DW_TAG_compile_unit
                    DW_AT_stmt_list             <.debug_line+0x0001095b>
                    DW_AT_comp_dir              /home/philipc/code/rust/rust-analyzer
                    DW_AT_GNU_dwo_name          /home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o
                    DW_AT_GNU_dwo_id            0xc6ed43dcb82fe226
                    DW_AT_GNU_ranges_base       <.debug_rnglists+0x00000000>
                    DW_AT_GNU_addr_base         <.debug_addr+0x00000000>

UNIT<.debug_info+0x00023013>: length = 0x34, format = Dwarf32, version = 4, address_size = 8, abbrev_offset = 0x0
< 0><0x0000000b>  DW_TAG_compile_unit
                    DW_AT_stmt_list             <.debug_line+0x00010f9e>
                    DW_AT_comp_dir              /home/philipc/code/rust/rust-analyzer
                    DW_AT_GNU_dwo_name          /home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o
                    DW_AT_GNU_dwo_id            0xc6ed43dcb82fe226
                    DW_AT_GNU_ranges_base       <.debug_rnglists+0x00000000>
                    DW_AT_GNU_addr_base         <.debug_addr+0x00000000>
< 1><0x00000028>    DW_TAG_subprogram
                      DW_AT_name                  new<&str>
< 1><0x0000002d>    DW_TAG_subprogram
                      DW_AT_name                  branch<alloc::string::String, xshell::error::Error>
< 1><0x00000032>    DW_TAG_subprogram
                      DW_AT_name                  from_residual<xtask::dist::Patch, xshell::error::Error, anyhow::Error>
< 1><0x00000037>    DW_TAG_null

UNIT<.debug_info+0x00029acb>: length = 0x2f, format = Dwarf32, version = 4, address_size = 8, abbrev_offset = 0x0
< 0><0x0000000b>  DW_TAG_compile_unit
                    DW_AT_stmt_list             <.debug_line+0x00014b26>
                    DW_AT_comp_dir              /home/philipc/code/rust/rust-analyzer
                    DW_AT_GNU_dwo_name          /home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o
                    DW_AT_GNU_dwo_id            0xc6ed43dcb82fe226
                    DW_AT_GNU_ranges_base       <.debug_rnglists+0x00000000>
                    DW_AT_GNU_addr_base         <.debug_addr+0x00000000>
< 1><0x00000028>    DW_TAG_subprogram
                      DW_AT_name                  from_raw<(dyn std::error::Error + core::marker::Send + core::marker::Sync)>
< 1><0x0000002d>    DW_TAG_subprogram
                      DW_AT_name                  by_ref<anyhow::error::ErrorImpl<()>>
< 1><0x00000032>    DW_TAG_null

UNIT<.debug_info+0x00029b77>: length = 0xb6, format = Dwarf32, version = 4, address_size = 8, abbrev_offset = 0x0
< 0><0x0000000b>  DW_TAG_compile_unit
                    DW_AT_stmt_list             <.debug_line+0x00014b80>
                    DW_AT_comp_dir              /home/philipc/code/rust/rust-analyzer
                    DW_AT_GNU_dwo_name          /home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o
                    DW_AT_GNU_dwo_id            0xc6ed43dcb82fe226
                    DW_AT_GNU_ranges_base       <.debug_rnglists+0x00000000>
                    DW_AT_GNU_addr_base         <.debug_addr+0x00000000>
< 1><0x00000028>    DW_TAG_subprogram
                      DW_AT_name                  from<xshell::error::Error>
< 1><0x0000002d>    DW_TAG_subprogram
                      DW_AT_name                  alloc
< 1><0x00000032>    DW_TAG_subprogram
                      DW_AT_name                  alloc_impl
< 1><0x00000037>    DW_TAG_subprogram
                      DW_AT_name                  allocate
< 1><0x0000003c>    DW_TAG_subprogram
                      DW_AT_name                  exchange_malloc
< 1><0x00000041>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<xshell::error::Error>>
< 1><0x00000046>    DW_TAG_subprogram
                      DW_AT_name                  construct<xshell::error::Error>
< 1><0x0000004b>    DW_TAG_subprogram
                      DW_AT_name                  from_std<xshell::error::Error>
< 1><0x00000050>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<&str>>>
< 1><0x00000055>    DW_TAG_subprogram
                      DW_AT_name                  construct<anyhow::wrapper::MessageError<&str>>
< 1><0x0000005a>    DW_TAG_subprogram
                      DW_AT_name                  from_adhoc<&str>
< 1><0x0000005f>    DW_TAG_subprogram
                      DW_AT_name                  from<xflags::Error>
< 1><0x00000064>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<xflags::Error>>
< 1><0x00000069>    DW_TAG_subprogram
                      DW_AT_name                  construct<xflags::Error>
< 1><0x0000006e>    DW_TAG_subprogram
                      DW_AT_name                  from_std<xflags::Error>
< 1><0x00000073>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<anyhow::error::ContextError<&str, xshell::error::Error>>>
< 1><0x00000078>    DW_TAG_subprogram
                      DW_AT_name                  construct<anyhow::error::ContextError<&str, xshell::error::Error>>
< 1><0x0000007d>    DW_TAG_subprogram
                      DW_AT_name                  from_context<&str, xshell::error::Error>
< 1><0x00000082>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<anyhow::error::ContextError<&str, anyhow::Error>>>
< 1><0x00000087>    DW_TAG_subprogram
                      DW_AT_name                  construct<anyhow::error::ContextError<&str, anyhow::Error>>
< 1><0x0000008c>    DW_TAG_subprogram
                      DW_AT_name                  context<&str>
< 1><0x00000091>    DW_TAG_subprogram
                      DW_AT_name                  ext_context<&str>
< 1><0x00000096>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<anyhow::wrapper::MessageError<alloc::string::String>>>
< 1><0x0000009b>    DW_TAG_subprogram
                      DW_AT_name                  construct<anyhow::wrapper::MessageError<alloc::string::String>>
< 1><0x000000a0>    DW_TAG_subprogram
                      DW_AT_name                  from_adhoc<alloc::string::String>
< 1><0x000000a5>    DW_TAG_subprogram
                      DW_AT_name                  from<std::io::error::Error>
< 1><0x000000aa>    DW_TAG_subprogram
                      DW_AT_name                  new<anyhow::error::ErrorImpl<std::io::error::Error>>
< 1><0x000000af>    DW_TAG_subprogram
                      DW_AT_name                  construct<std::io::error::Error>
< 1><0x000000b4>    DW_TAG_subprogram
                      DW_AT_name                  from_std<std::io::error::Error>
< 1><0x000000b9>    DW_TAG_null

Note that none of these contain any definitions with addresses.

And xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o contains 4 identical DW_TAG_compile_unit with that DW_AT_GNU_dwo_id.

Here's one of them:
UNIT<.debug_info+0x0004bec9>: length = 0xbf, format = Dwarf32, version = 4, address_size = 8, abbrev_offset = 0x0
< 0><0x0000000b>  DW_TAG_compile_unit
                    DW_AT_producer              (indirect string, index 0x39dc): clang LLVM (rustc version 1.57.0-nightly (ac2d9fc50 2021-09-21))
                    DW_AT_language              DW_LANG_Rust
                    DW_AT_name                  (indirect string, index 0x39df): xtask/src/main.rs
                    DW_AT_GNU_dwo_name          (indirect string, index 0x39de): /home/philipc/code/rust/rust-analyzer/target/release/deps/xtask-be398824d5b61cec.write_json-94b9108f588c9a54.write_json.1ae45326-cgu.0.rcgu.o.rcgu.o
                    DW_AT_GNU_dwo_id            0xc6ed43dcb82fe226
< 1><0x0000001c>    DW_TAG_namespace
                      DW_AT_name                  (indirect string, index 0x0): core
< 2><0x0000001e>      DW_TAG_namespace
                        DW_AT_name                  (indirect string, index 0x43): ffi
< 3><0x00000020>        DW_TAG_enumeration_type
                          DW_AT_type                  0x00000031<.debug_info+0x0004befa>
                          DW_AT_enum_class            yes
                          DW_AT_name                  (indirect string, index 0x46): c_void
                          DW_AT_byte_size             0x00000001
                          DW_AT_alignment             0x00000001
< 4><0x00000028>          DW_TAG_enumerator
                            DW_AT_name                  (indirect string, index 0x44): __variant1
                            DW_AT_const_value           0x00000000
< 4><0x0000002b>          DW_TAG_enumerator
                            DW_AT_name                  (indirect string, index 0x45): __variant2
                            DW_AT_const_value           0x00000001
< 4><0x0000002e>          DW_TAG_null
< 3><0x0000002f>        DW_TAG_null
< 2><0x00000030>      DW_TAG_null
< 1><0x00000031>    DW_TAG_base_type
                      DW_AT_name                  (indirect string, index 0x4): u8
                      DW_AT_encoding              DW_ATE_unsigned
                      DW_AT_byte_size             0x00000001
< 1><0x00000035>    DW_TAG_namespace
                      DW_AT_name                  (indirect string, index 0x17): std
< 2><0x00000037>      DW_TAG_namespace
                        DW_AT_name                  (indirect string, index 0x18): io
< 3><0x00000039>        DW_TAG_namespace
                          DW_AT_name                  (indirect string, index 0x19): error
< 4><0x0000003b>          DW_TAG_enumeration_type
                            DW_AT_type                  0x00000031<.debug_info+0x0004befa>
                            DW_AT_enum_class            yes
                            DW_AT_name                  (indirect string, index 0x42): ErrorKind
                            DW_AT_byte_size             0x00000001
                            DW_AT_alignment             0x00000001
< 5><0x00000043>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1a): NotFound
                              DW_AT_const_value           0x00000000
< 5><0x00000046>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1b): PermissionDenied
                              DW_AT_const_value           0x00000001
< 5><0x00000049>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1c): ConnectionRefused
                              DW_AT_const_value           0x00000002
< 5><0x0000004c>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1d): ConnectionReset
                              DW_AT_const_value           0x00000003
< 5><0x0000004f>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1e): HostUnreachable
                              DW_AT_const_value           0x00000004
< 5><0x00000052>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x1f): NetworkUnreachable
                              DW_AT_const_value           0x00000005
< 5><0x00000055>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x20): ConnectionAborted
                              DW_AT_const_value           0x00000006
< 5><0x00000058>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x21): NotConnected
                              DW_AT_const_value           0x00000007
< 5><0x0000005b>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x22): AddrInUse
                              DW_AT_const_value           0x00000008
< 5><0x0000005e>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x23): AddrNotAvailable
                              DW_AT_const_value           0x00000009
< 5><0x00000061>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x24): NetworkDown
                              DW_AT_const_value           0x0000000a
< 5><0x00000064>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x25): BrokenPipe
                              DW_AT_const_value           0x0000000b
< 5><0x00000067>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x26): AlreadyExists
                              DW_AT_const_value           0x0000000c
< 5><0x0000006a>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x27): WouldBlock
                              DW_AT_const_value           0x0000000d
< 5><0x0000006d>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x28): NotADirectory
                              DW_AT_const_value           0x0000000e
< 5><0x00000070>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x29): IsADirectory
                              DW_AT_const_value           0x0000000f
< 5><0x00000073>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2a): DirectoryNotEmpty
                              DW_AT_const_value           0x00000010
< 5><0x00000076>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2b): ReadOnlyFilesystem
                              DW_AT_const_value           0x00000011
< 5><0x00000079>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2c): FilesystemLoop
                              DW_AT_const_value           0x00000012
< 5><0x0000007c>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2d): StaleNetworkFileHandle
                              DW_AT_const_value           0x00000013
< 5><0x0000007f>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2e): InvalidInput
                              DW_AT_const_value           0x00000014
< 5><0x00000082>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x2f): InvalidData
                              DW_AT_const_value           0x00000015
< 5><0x00000085>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x30): TimedOut
                              DW_AT_const_value           0x00000016
< 5><0x00000088>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x31): WriteZero
                              DW_AT_const_value           0x00000017
< 5><0x0000008b>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x32): StorageFull
                              DW_AT_const_value           0x00000018
< 5><0x0000008e>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x33): NotSeekable
                              DW_AT_const_value           0x00000019
< 5><0x00000091>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x34): FilesystemQuotaExceeded
                              DW_AT_const_value           0x0000001a
< 5><0x00000094>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x35): FileTooLarge
                              DW_AT_const_value           0x0000001b
< 5><0x00000097>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x36): ResourceBusy
                              DW_AT_const_value           0x0000001c
< 5><0x0000009a>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x37): ExecutableFileBusy
                              DW_AT_const_value           0x0000001d
< 5><0x0000009d>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x38): Deadlock
                              DW_AT_const_value           0x0000001e
< 5><0x000000a0>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x39): CrossesDevices
                              DW_AT_const_value           0x0000001f
< 5><0x000000a3>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3a): TooManyLinks
                              DW_AT_const_value           0x00000020
< 5><0x000000a6>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3b): FilenameTooLong
                              DW_AT_const_value           0x00000021
< 5><0x000000a9>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3c): ArgumentListTooLong
                              DW_AT_const_value           0x00000022
< 5><0x000000ac>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3d): Interrupted
                              DW_AT_const_value           0x00000023
< 5><0x000000af>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3e): Unsupported
                              DW_AT_const_value           0x00000024
< 5><0x000000b2>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x3f): UnexpectedEof
                              DW_AT_const_value           0x00000025
< 5><0x000000b5>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x40): OutOfMemory
                              DW_AT_const_value           0x00000026
< 5><0x000000b8>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x14): Other
                              DW_AT_const_value           0x00000027
< 5><0x000000bb>            DW_TAG_enumerator
                              DW_AT_name                  (indirect string, index 0x41): Uncategorized
                              DW_AT_const_value           0x00000028
< 5><0x000000be>            DW_TAG_null
< 4><0x000000bf>          DW_TAG_null
< 3><0x000000c0>        DW_TAG_null
< 2><0x000000c1>      DW_TAG_null
< 1><0x000000c2>    DW_TAG_null

I'm guessing those 4 units aren't really meant to be identical, so the duplicate DWO id is causing some to be lost. A reason for that is I think the full units are meant to have entries that correspond to the DW_AT_name in the skeleton units.

Disabling LTO or using thin LTO works okay in this instance.

@philipc
Copy link
Contributor

philipc commented Sep 23, 2021

#89041 (which is a workaround for #66118) also works around this bug when using fat LTO, because now there is only one CU so there can't be duplicates.

It won't affect thin LTO though, and I still don't have a reproduction for that.

@ayermolo
Copy link
Author

Sorry didn't get a chance to get to this before PTO. I asked someone to do it internally, if not I'll priorities once I get back.

@pcwalton pcwalton self-assigned this Oct 4, 2021
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Dec 17, 2021
…davidtwco

rustc_codegen_llvm: Give each codegen unit a unique DWARF name on all platforms, not just Apple ones.

To avoid breaking split DWARF, we need to ensure that each codegen unit has a
unique `DW_AT_name`. This is because there's a remote chance that different
codegen units for the same module will have entirely identical DWARF entries
for the purpose of the DWO ID, which would violate Appendix F ("Split Dwarf
Object Files") of the DWARF 5 specification. LLVM uses the algorithm specified
in section 7.32 "Type Signature Computation" to compute the DWO ID, which does
not include any fields that would distinguish compilation units. So we must
embed the codegen unit name into the `DW_AT_name`.

Closes rust-lang#88521.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Dec 18, 2021
…davidtwco

rustc_codegen_llvm: Give each codegen unit a unique DWARF name on all platforms, not just Apple ones.

To avoid breaking split DWARF, we need to ensure that each codegen unit has a
unique `DW_AT_name`. This is because there's a remote chance that different
codegen units for the same module will have entirely identical DWARF entries
for the purpose of the DWO ID, which would violate Appendix F ("Split Dwarf
Object Files") of the DWARF 5 specification. LLVM uses the algorithm specified
in section 7.32 "Type Signature Computation" to compute the DWO ID, which does
not include any fields that would distinguish compilation units. So we must
embed the codegen unit name into the `DW_AT_name`.

Closes rust-lang#88521.
@bors bors closed this as completed in c41fd76 Dec 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
4 participants