You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
split dwarf doesn't work with crate dependencies #81024
llvm-dwp expects to be able to find all of the dwo files referenced by the linked build_script_build-6f3f48770204354e binary. Using readelf -wi, we can inspect the DW_AT_GNU_dwo_name attributes to find the expected filenames (prepending DW_AT_comp_dir for the complete path). rustc should have kept DWARF object files around at this point in compilation, so "No such file or directory" error suggests a failure in that mechanism. However, there are DWARF object files referenced from previous compilations:
During earlier compilation of autocfg, the DWARF object file referenced would have been created, but then deleted at the end of the compilation. This explains why adding -Csave-temps to the RUSTFLAGS environment variable (as suggested in the initial report) fixes the issue. If we added -Csave-temps to only the failing compiler invocation then that would be insufficient to resolve the issue.
autocfg's compilation does not produce a DWARF package because rustc will only produce one when it is producing an output binary. Even if a DWARF package had been produced, it would have been insufficient to resolve the problem, as llvm-dwp only loads DWARF object files (DWARF package files are only consumed by the debugger, and DW_AT_GNU_dwo_name is never actually modified to point to the package file, debuggers just know to look for sibling .dwp files of binaries):
Therefore, it is necessary that DWARF object files from dependencies still exist during the compilation of dependent crates (in ./target/{debug,release}/deps, the output directory of the dependency's compilation).
I've come up with a some potential approaches which would resolve this issue, and I'd appreciate feedback:
Adding a DWARF object output type
Unlike other output files of the compiler, DWARF objects are not requested with the --emit flag:
Instead, when Split DWARF is enabled: DWARF object files are produced whenever an object file is emitted (we produce DWARF objects alongside object files in the same LLVMRustWriteOutputFile invocation, by providing a buffer as an additional argument to LLVM's addPassesToEmitFile); DWARF package files are created whenever a OutputType::Exe is requested; and DWARF object files are removed whenever we would remove object files.
We could choose to add a OutputType::DwarfObject, which would allow Cargo to pass --emit=dwarf-object,dep-info,metadata,link to the invocation of rustc for dependencies. When --emit=dwarf-object is provided, DWARF object files will not be removed at the end of the compiler invocation. Necessarily when --emit=dwarf-object is requested, object files would have to be created, but these would be removed if only DWARF objects were explicitly requested.
Through this mechanism, we could ensure that the DWARF object files of dependencies continue to exist after the compilation session and thus would be available for dependent compilations.
Adding DWARF objects to rlibs
Alternatively, we could add DWARF object files to rlib files during linking, and then in the dependent compilation, before invoking llvm-dwp, read the DWARF object files from the rlib and write them to the expected location.
Adding DWARF objects to the rlib would require appending the following snippet..
for dwo in codegen_results.modules.iter().filter_map(|m| m.dwarf_object.as_ref()){
ab.add_file(dwo);}
letmut ab = <BasArchiveBuilder>::new(sess, out_filename,None);
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()){
ab.add_file(obj);
}
Reading DWARF objects from the rlib would require similar code to the following function, but with a different value for METADATA_FILENAME (instead, this would be the filename of the DWARF object which should be retrieved):
debug!("didn't find '{}' in the archive",METADATA_FILENAME);
format!("failed to read rlib metadata: '{}'", filename.display())
})
})?;
Ok(rustc_erase_owner!(buf))
}
(The snippet above is from rustc_codegen_llvm, rustc_codegen_cranelift has a similar function)
If we don't already, we would need to record the codegen modules produced for the dependency. This would be required to know which sections to load from the rlib and write out for the llvm-dwp invocation to succeed.
This is quite a bit more complicated than the first solution, but limits the required changes to only rustc.
Always keep DWARF objects for library crates
Similar to "Adding a DWARF object output type" described above, but instead of having Cargo explicitly request that DWARF objects are kept, infer that a crate is a dependency by checking the crate type is a library and that an rlib is also being produced.
I'd appreciate any feedback on which of the above solutions is desirable, or if anyone has any alternatives that I haven't thought of yet.
Alternatively, we could add DWARF object files to rlib files during linking, and then in the dependent compilation, before invoking llvm-dwp, read the DWARF object files from the rlib and write them to the expected location.
I was under the impression that this already happend. At least my FCP proposal for -Csplit-dwarf was made with this assumption.
Alternatively, we could add DWARF object files to rlib files during linking, and then in the dependent compilation, before invoking llvm-dwp, read the DWARF object files from the rlib and write them to the expected location.
I was under the impression that this already happend. At least my FCP proposal for -Csplit-dwarf was made with this assumption.
I assumed that the -Csplit-debuginfo proposal wouldn't enable Split DWARF initially, only -Zrun-dsymutil, since it had only been in nightly for a short time.
Activity
davidtwco commentedon Jan 14, 2021
As of writing, here's what I've figured out - using
backtrace-rsas an example, as that was the crate which was used when reporting the bug:Compiling
backtrace-rswithRUSTFLAGS="-Z split-dwarf=split" cargo +nightly --verbose buildproduces the following output:llvm-dwpexpects to be able to find all of thedwofiles referenced by the linkedbuild_script_build-6f3f48770204354ebinary. Usingreadelf -wi, we can inspect theDW_AT_GNU_dwo_nameattributes to find the expected filenames (prependingDW_AT_comp_dirfor the complete path).rustcshould have kept DWARF object files around at this point in compilation, so "No such file or directory" error suggests a failure in that mechanism. However, there are DWARF object files referenced from previous compilations:During earlier compilation of
autocfg, the DWARF object file referenced would have been created, but then deleted at the end of the compilation. This explains why adding-Csave-tempsto theRUSTFLAGSenvironment variable (as suggested in the initial report) fixes the issue. If we added-Csave-tempsto only the failing compiler invocation then that would be insufficient to resolve the issue.autocfg's compilation does not produce a DWARF package becauserustcwill only produce one when it is producing an output binary. Even if a DWARF package had been produced, it would have been insufficient to resolve the problem, asllvm-dwponly loads DWARF object files (DWARF package files are only consumed by the debugger, andDW_AT_GNU_dwo_nameis never actually modified to point to the package file, debuggers just know to look for sibling.dwpfiles of binaries):https://github.com/llvm/llvm-project/blob/5cf2696317afb0631a4a09414ae40a4e226a905e/llvm/tools/llvm-dwp/llvm-dwp.cpp#L510-L537
Therefore, it is necessary that DWARF object files from dependencies still exist during the compilation of dependent crates (in
./target/{debug,release}/deps, the output directory of the dependency's compilation).I've come up with a some potential approaches which would resolve this issue, and I'd appreciate feedback:
Adding a DWARF object output type
Unlike other output files of the compiler, DWARF objects are not requested with the
--emitflag:rust/compiler/rustc_session/src/config.rs
Lines 241 to 252 in 4275ef6
Instead, when Split DWARF is enabled: DWARF object files are produced whenever an object file is emitted (we produce DWARF objects alongside object files in the same
LLVMRustWriteOutputFileinvocation, by providing a buffer as an additional argument to LLVM'saddPassesToEmitFile); DWARF package files are created whenever aOutputType::Exeis requested; and DWARF object files are removed whenever we would remove object files.We could choose to add a
OutputType::DwarfObject, which would allow Cargo to pass--emit=dwarf-object,dep-info,metadata,linkto the invocation ofrustcfor dependencies. When--emit=dwarf-objectis provided, DWARF object files will not be removed at the end of the compiler invocation. Necessarily when--emit=dwarf-objectis requested, object files would have to be created, but these would be removed if only DWARF objects were explicitly requested.Through this mechanism, we could ensure that the DWARF object files of dependencies continue to exist after the compilation session and thus would be available for dependent compilations.
Adding DWARF objects to rlibs
Alternatively, we could add DWARF object files to rlib files during linking, and then in the dependent compilation, before invoking
llvm-dwp, read the DWARF object files from the rlib and write them to the expected location.Adding DWARF objects to the rlib would require appending the following snippet..
..after this part of the compiler:
rust/compiler/rustc_codegen_ssa/src/back/link.rs
Lines 302 to 314 in 4275ef6
Reading DWARF objects from the rlib would require similar code to the following function, but with a different value for
METADATA_FILENAME(instead, this would be the filename of the DWARF object which should be retrieved):rust/compiler/rustc_codegen_llvm/src/metadata.rs
Lines 21 to 41 in 4275ef6
(The snippet above is from
rustc_codegen_llvm,rustc_codegen_cranelifthas a similar function)If we don't already, we would need to record the codegen modules produced for the dependency. This would be required to know which sections to load from the rlib and write out for the
llvm-dwpinvocation to succeed.This is quite a bit more complicated than the first solution, but limits the required changes to only rustc.
Always keep DWARF objects for library crates
Similar to "Adding a DWARF object output type" described above, but instead of having Cargo explicitly request that DWARF objects are kept, infer that a crate is a dependency by checking the crate type is a library and that an rlib is also being produced.
I'd appreciate any feedback on which of the above solutions is desirable, or if anyone has any alternatives that I haven't thought of yet.
bjorn3 commentedon Jan 14, 2021
I was under the impression that this already happend. At least my FCP proposal for
-Csplit-dwarfwas made with this assumption.davidtwco commentedon Jan 14, 2021
I assumed that the
-Csplit-debuginfoproposal wouldn't enable Split DWARF initially, only-Zrun-dsymutil, since it had only been in nightly for a short time.bjorn3 commentedon Jan 14, 2021
-Csplit-debuginfowill be gated behind-Zunstable-optionsfor all targets other than macOS, but it is supposed to work for both Linux and Windows.apiraino commentedon Jan 21, 2021
Nominated for discussion for next week's compiler meeting (Zulip discussion)