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

rustc generates invalid DWARF when LTO is enabled #66118

Open
hannobraun opened this issue Nov 5, 2019 · 21 comments
Open

rustc generates invalid DWARF when LTO is enabled #66118

hannobraun opened this issue Nov 5, 2019 · 21 comments
Labels
A-debuginfo Area: Debugging information in compiled programs (DWARF, PDB, etc.) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@hannobraun
Copy link

When combining lto = true with debug = true in Cargo.toml, the compiler generates invalid DWARF, according to Gimli.

I've created a minimal example here: https://github.com/hannobraun/dwarf-test

If you follow the instructions in the example's README, you should see something like this:

DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13d1b to 0x492
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13d30 to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13d4a to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13d59 to 0x5e2
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13d91 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13da6 to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13dce to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13de2 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13dfb to 0x2b31
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e10 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e25 to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e4d to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e61 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e87 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13e9c to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13ec4 to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13ed8 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13ef1 to 0x2b31
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13f06 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13f1b to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13f43 to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13f57 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13fb5 to 0x4ac
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13fca to 0x49f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13fdf to 0x492b
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x13ff4 to 0x523c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14009 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14022 to 0x4893
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1402f to 0x4880
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14049 to 0x4b9
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14056 to 0x5ef
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14063 to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14085 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1409c to 0x5fc
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x140b1 to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x140db to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x140f2 to 0x609
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14107 to 0x616
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1411c to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14146 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1415d to 0x609
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14172 to 0x616
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14187 to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x141b1 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x141c8 to 0x609
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x141dd to 0x616
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x141f7 to 0x4e0
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1420c to 0x62d
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14221 to 0x4d3
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14236 to 0x4945
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1424b to 0x4938
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14279 to 0x492
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1428e to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x142a8 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x142b7 to 0x5e2
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x142c5 to 0x492
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x142da to 0x491e
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x142f4 to 0x522f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14303 to 0x5e2
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14326 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1433b to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14363 to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14377 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14390 to 0x2b31
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x143a5 to 0x4857
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x143ba to 0x536c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x143e2 to 0xf5
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x143f6 to 0xe8
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x144ea to 0x3e22
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14528 to 0x4531
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14551 to 0x4ed
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14582 to 0x453d
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14d39 to 0x4100
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14dcb to 0x3e38
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14e10 to 0x412c
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14e29 to 0x3e4b
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x14e3e to 0x4b11
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x174a6 to 0x6cf
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x17532 to 0x6cf
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x175be to 0x6cf
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x17652 to 0x6cf
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x1770d to 0x7ac
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x178c3 to 0x816
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x178d8 to 0x36f
DWARF error in ../dwarf-test/target/debug/dwarf-test: Invalid intra-unit reference in unit 0x102 from DIE 0x17903 to 0x37c

I've seen this first in a larger project. There, the combination of lto = true and debug = true also causes GDB to freeze when reading the symbols from the binary. I wasn't able to reproduce this in my minimal example, but in the larger project, all binaries that caused GDB to freeze produced these DWARF errors, while I didn't see these errors in the binaries that worked normally.

So while I'm not 100% sure that these DWARF errors are a real problem, I suspect that they're the cause of the GDB freezes I was seeing.

@jonas-schievink jonas-schievink 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 Nov 5, 2019
@jonas-schievink
Copy link
Contributor

Some observations:

  • Setting lto = "thin" makes the errors disappear.
  • Using an alt build of the current master triggers no LLVM assertions, so this might be an issue in LLD.
  • llvm-dwarfdump always outputs a huge list of errors, regardless of whether LTO, ThinLTO, or no LTO is used.

@jonas-schievink jonas-schievink added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Nov 6, 2019
@parched
Copy link
Contributor

parched commented Nov 6, 2019

I saw a similar error in dwarf parsing tool I was working on when LTO did inlining across compilation units which the tool incorrectly assumed wasn't possible. Could it be something similar here @fitzgen ?

@glorv
Copy link
Contributor

glorv commented Nov 8, 2019

I came across this problem recently try to use dwz to make the binary file size smaller. and the dwz will throws Couldn't find DIE referenced by DW_AT_abstract_origin.

here is a piece of info by readelf that shows where dwarf is broken:

<15><4ca073>: Abbrev Number: 16 (DW_TAG_formal_parameter)
  <4ca074>   DW_AT_location    : 0x116476b (location list)
  <4ca078>   DW_AT_abstract_origin: <0x6dc894>
<15><4ca07c>: Abbrev Number: 0
<14><4ca07d>: Abbrev Number: 0
<13><4ca07e>: Abbrev Number: 0
<12><4ca07f>: Abbrev Number: 0
<11>< 4ca080 > : Abbrev Number: 0
<10><4ca081>: Abbrev Number: 0
<9><4ca082>: Abbrev Number: 203 (DW_TAG_inlined_subroutine)
  <4ca084>   DW_AT_abstract_origin: <0x2b06e38>
  <4ca088>   DW_AT_ranges      : 0x632f70
  <4ca08c>   DW_AT_call_file   : 731
  <4ca08e>   DW_AT_call_line   : 162
  <4ca08f>   DW_AT_call_column : 16
<10><4ca090>: Abbrev Number: 26 (DW_TAG_formal_parameter)
  <4ca091>   DW_AT_abstract_origin: <0x2b06e49>
<10><4ca095>: Abbrev Number: 41 (DW_TAG_inlined_subroutine)
---
<14><c5d17d>: Abbrev Number: 16 (DW_TAG_formal_parameter)
  <c5d17e>   DW_AT_location    : 0x34fb8a3 (location list)
  <c5d182>   DW_AT_abstract_origin: <0xc5d019>
<14><c5d186>: Abbrev Number: 211 (DW_TAG_inlined_subroutine)
  <c5d188>   DW_AT_abstract_origin: < 0x4ca080 >
  <c5d18c>   DW_AT_low_pc      : 0xde3990
  <c5d194>   DW_AT_high_pc     : 0x10
  <c5d198>   DW_AT_call_file   : 491
  <c5d19a>   DW_AT_call_line   : 21
  <c5d19b>   DW_AT_call_column : 11
<14><c5d19c>: Abbrev Number: 209 (DW_TAG_inlined_subroutine)
  <c5d19e>   DW_AT_abstract_origin: <0x5642b0>
  <c5d1a2>   DW_AT_ranges      : 0x1340160
  <c5d1a6>   DW_AT_call_file   : 491
  <c5d1a8>   DW_AT_call_line   : 29

the address c5d186 is a DW_TAG_inlined_subroutine and its DW_AT_abstract_origin attr points to address 0x4ca080 with is DW_TAG_padding (Abbrev Number: 0)

According to the dwarf4 specification, two die link by DW_AT_abstract_origin must always be the same type, that to say, in our case, it should be refer to another DW_TAG_inlined_subroutine.

BTW, will config lto = false or lto = "thin", this error would disappear from dwz.

@noonien
Copy link

noonien commented May 13, 2020

Any update on this?

@3v1n0
Copy link

3v1n0 commented Aug 19, 2020

Having this still, only in riscv64 architecture when using rust 1.43.0 when compiling mozjs (part of firefox):

dwz: debian/libmozjs-78-0/usr/lib/riscv64-linux-gnu/libmozjs-78.so.78.1.0: Couldn't find DIE referenced by DW_AT_abstract_origin

Once again, setting RUSTFLAGS = -Clto=thin does the work for it

@sylvestre
Copy link
Contributor

I am starting to experiencing the same thing with rust packages in Debian (grcov & the new version of fd-find)

@sylvestre
Copy link
Contributor

Exporting RUSTFLAGS = -Clto=thin in the Debian build system caused:

error: options `-C embed-bitcode=no` and `-C lto` are incompatible

@jryans
Copy link
Contributor

jryans commented Jan 4, 2021

Exporting RUSTFLAGS = -Clto=thin in the Debian build system caused:

error: options `-C embed-bitcode=no` and `-C lto` are incompatible

@sylvestre: To workaround this option mismatch, you could try using Cargo's env vars to specify the LTO mode, which should prevent Cargo from emitting -C embed-bitcode=no. For example, CARGO_PROFILE_RELEASE_LTO=thin should leave out -C embed-bitcode=no while also setting -C lto=thin, allowing the workaround approach to proceed.

@sylvestre
Copy link
Contributor

Nice to see you here @jryans ;)
I will have a look, for now, I just disable dwz. For example:
https://salsa.debian.org/rust-team/debcargo-conf/-/blob/master/src/fd-find/debian/rules#L15-17

@jryans
Copy link
Contributor

jryans commented Jan 30, 2021

I have attempted to reproduce this issue following the steps in the dwarf-test sample repo, but everything seems to work correctly for me. I tested on Ubuntu 18.04 for x86_64 with both Rust stable (1.49.0) and nightly versions.

Do the original steps still reproduce for you, @hannobraun? Are there additional steps or details I might be missing?

@jryans
Copy link
Contributor

jryans commented Jan 30, 2021

Since the issue seems to focus on lld as a possible cause, and Ubuntu 18.04 uses GCC's cc as the system linker, I also tried installing LLVM 10 and forcing Rust to use lld, but this appears to also work fine as well.

@hannobraun
Copy link
Author

Thanks for looking into this, @jryans. I can confirm that the issue is no longer reproducible using the dwarf-test repo. I don't think there were any additional steps beyond what's documented in the README.

I'm no longer involved in the project where the original issue (freezing GDB, see issue description) occurred, so I'm not set up to verify things there (it was a client project I was working on at the time, and I don't think it remains active). I assume that whatever fixed the DWARF errors fixed the original issue too.

As far as I'm concerned, this issue can be closed, but maybe the others who posted here can confirm that the issue is fixed for them too.

@sticnarf
Copy link
Contributor

sticnarf commented Sep 11, 2021

Hi, all. I create a not so minimized reproducing program:

use tokio::runtime::Builder;
use tonic::client::Grpc;
use tonic::codec::ProstCodec;
use tonic::codegen::http::uri::PathAndQuery;
use tonic::transport::Channel;
use tonic::IntoRequest;

#[derive(::prost::Message)]
pub struct Proto;

fn main() {
    let f = async {
        let client = unsafe { &mut *(0x1usize as *mut Grpc<Channel>) };
        let _: Result<tonic::Response<Proto>, tonic::Status> = client
            .unary(
                Proto.into_request(),
                PathAndQuery::from_static(""),
                ProstCodec::<Proto, Proto>::default(),
            )
            .await;
    };
    let rt = Builder::new_current_thread().build().unwrap();
    rt.block_on(f);
}

Dependency lock file can be found at https://github.com/sticnarf/dwarf-error.

If compiled with codegen-units = 1 and lto = true, the DWARF info is incorrect.

Running gimli's dwarf-validate on the produced binary by Rust 1.55.0 on x86-64 Linux will output:

DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39170 to 0x35bd6
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39185 to 0x64ce
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x391a0 to 0x66ae
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x391be to 0x35bed
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39231 to 0x334c1
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39246 to 0x64ce
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39261 to 0x66ae
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x3927f to 0x35173
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x39291 to 0x64ce
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x392ac to 0x66ae
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x392ca to 0x35197
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x3936b to 0xa0d2
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x3938b to 0xea82
DWARF error in dwarf-error: Invalid intra-unit reference in unit 0x0 from DIE 0x393b3 to 0x3332b

I can also confirm the binary compiled from this repo on Linux ARM is also affected by this issue.

Because the binary uses prost, it includes lots of dependecies. But I cannot reproduce this issue in a simpler program.

@philipc
Copy link
Contributor

philipc commented Sep 12, 2021

Starting to debug this:

RUSTFLAGS="--emit llvm-ir,obj" cargo build --release
../../gimli/target/debug/examples/dwarf-validate target/release/deps/dwarf_error-37590773ac18128b.o

DWARF error in target/release/deps/dwarf_error-37590773ac18128b.o: Invalid intra-unit reference in unit 0x0 from DIE 0x37ea9 to 0x352f3
etc

llc target/release/deps/dwarf_error-37590773ac18128b.ll -filetype=obj -O0 -o fail.o
../../gimli/target/debug/examples/dwarf-validate fail.o

DWARF error in fail.o: Invalid intra-unit reference in unit 0x0 from DIE 0x3bbaf to 0x38812
etc

So I need to work on reducing that LLVM-IR now. I expect that the only relevant parts of it will be the debuginfo, which I don't think bugpoint can help with, so this might take some time.

The original error in https://github.com/hannobraun/dwarf-test can be reproduced using older rust versions (e.g. 1.38) and the DWARF error looks similar.

@philipc
Copy link
Contributor

philipc commented Sep 12, 2021

This seems to be #46346 again. It has all the same symptoms (multiple CUs in the IR, and a function in one CU is being inlined in another CU). That bug occurred for ThinLTO, and we never fixed it in LLVM. Instead, we changed rust's ThinLTO to put all the IR in a single CU ( #46772). But in this issue, we still have multiple CUs, so the bug can still occur.

I'm assuming that it doesn't make sense to try the same workaround again because these really are separate CUs.

Additionally, this doesn't seem to be a problem for C++, so we must be emitting debuginfo differently from C++ to trigger this bug in LLVM. I suspect that part of the problem is that the function definitions are within namespaces, and if I recall correctly, C++ places the declaration in the namespace, but not the definition. The namespace can still be determined because DW_AT_specification links the definition to the declaration. This is also what the examples in the DWARF specification do (e.g. section D.3 in the DWARF 5 standard). So maybe we can change our debuginfo to do the same.

@philipc
Copy link
Contributor

philipc commented Sep 14, 2021

Simplified IR: https://gist.github.com/philipc/59f8c1acf6c55ffdbf917c2c95d80772
fail1.ll is from https://github.com/hannobraun/dwarf-test and fail2.ll is from https://github.com/sticnarf/dwarf-error. These only contain one error from each; there are more errors which may have different forms, but I haven't checked. Both of these still produce invalid DWARF when using llc built from LLVM git. I didn't manage to create a simplified rust reproduction for either of these, but I didn't spend much time on that.

Neither of these have namespaces, so that isn't the problem, but I still think that the declaration vs definition distinction is likely to be significant. See https://reviews.llvm.org/D107076 (which reverts a patch that caused definitions to be shared for C++ and which was causing the same problem we are seeing), and https://reviews.llvm.org/D94976#2508262 (describes a bit about declaration and definitions). So I think this is a problem that upstream LLVM wants to fix too, but it's not easy to fix.

Rust reproduction

lib.rs:

pub struct Xxxxx;

impl Xxxxx {
	#[inline(never)]
	pub fn pppp() {
		// The debuginfo for this inlined function call expects `pppp`
		// to be in the same unit as the declaration of `qqqq`.
		qqqq();
	}
}

#[inline(always)]
fn qqqq() {
	String::from("s");
}

main.rs:

struct Yyyyy {
	// This moves the debuginfo for `Xxxxx` into this unit,
	// including its methods.
	_xxxx: lib::Xxxxx,
}

impl Yyyyy {
	fn rrrr() {
		lib::Xxxxx::pppp();
	}
}

fn main() {
	// Use `Yyyyy` and `Xxxxx::pppp`.
	Yyyyy::rrrr();
}
rustc --crate-name lib lib.rs --crate-type lib --edition=2018 -C codegen-units=1 -C debuginfo=2 --out-dir out
rustc --crate-name main main.rs --crate-type bin --edition=2018 -C lto -C codegen-units=1 -C debuginfo=2 --out-dir out --extern lib=out/liblib.rlib
llvm-dwarfdump -verify out/main

the8472 added a commit to the8472/rust that referenced this issue Sep 22, 2021
…nagisa

Work around invalid DWARF bugs for fat LTO

This PR applies the same workaround in rust-lang#46772 to fat LTO.

It seems to fix the bug reported in rust-lang#66118 (comment).
the8472 added a commit to the8472/rust that referenced this issue Sep 22, 2021
…nagisa

Work around invalid DWARF bugs for fat LTO

This PR applies the same workaround in rust-lang#46772 to fat LTO.

It seems to fix the bug reported in rust-lang#66118 (comment).
@cuviper
Copy link
Member

cuviper commented May 4, 2023

This seems to have been fixed in LLVM 16, as the reproducer has no errors with 1.70-beta or 1.71-nightly.

However, I think that fix is also related to the new errors in #109730 and #109934 -> llvm/llvm-project#61932, which may lead to a revert in LLVM 16. But I have a rustc fix for that in #111167, and I confirmed that this reproducer still look ok with that change too.

So, depending on how that shakes out, we may be almost ready to close this...

@cuviper
Copy link
Member

cuviper commented May 7, 2023

I think this should be done, but it could use a regression test.

@rustbot label +E-needs-test

@rustbot rustbot added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label May 7, 2023
@philipc
Copy link
Contributor

philipc commented May 7, 2023

Maybe #46772 is no longer necessary.

@cuviper
Copy link
Member

cuviper commented May 8, 2023

See #111364 for an attempt to remove that workaround.

@DianQK
Copy link
Member

DianQK commented Aug 3, 2024

I think #114760 is sufficient as a test case.

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.) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests