-
Notifications
You must be signed in to change notification settings - Fork 13.3k
set subsections_via_symbols for ld64 helper sections #139752
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
Conversation
r? @Nadrieril rustbot has assigned @Nadrieril. Use |
Some changes occurred in compiler/rustc_codegen_ssa |
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the ping!
@rustbot label O-apple O-linkage
if binary_format == BinaryFormat::MachO { | ||
file.set_subsections_via_symbols(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me that this needs to be in create_object_file
? Maybe it would be better to only use it in add_linked_symbol_object
?
Also, MH_SUBSECTIONS_VIA_SYMBOLS
is vastly under-documented, I'd really like to see a comment here explaining why it's safe for us to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object::set_subsections_via_symbols says it should be called before add_section
or add_subsection
, so I feel it better to put it here (not error-prone).
I don't know whether it's safe or not, either. I searched on the Internet and found that this is the only way for Mach-O to implement GC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My problem with having it in create_object_file
is that it may negatively affect the other object files we create (which again is hard to tell for sure, since the docs around it are so limited).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! I didn't notice that this function has multiple callers.
I will add a parameter to control this behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, I'd still have preferred to just change add_linked_symbol_object
, it'd be unexpected if create_object_file
added any sections or subsections, it's literally prefixed "create" as in "only create, do not fill".
But will leave it up to the compiler reviewer to decide, this is a nit anyhow.
unsafe extern "C" { | ||
unsafe static UNDEFINED: usize; | ||
} | ||
|
||
#[unsafe(no_mangle)] | ||
pub fn used() { | ||
println!("UNDEFINED = {}", unsafe { UNDEFINED }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Honestly, I'm kind of surprised that this worked in the past. Could you describe the use-case?
I'd also be interested, does this pattern work on other platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used by https://github.com/pgcentralfoundation/pgrx. It's a framework for developing PostgreSQL extensions. This trick is used for writing hybrid (dylib and SQL generation) code in a library. Code about SQL generation could be compiled to an executable, since dylib-related code are GC-ed.
This should be reasonable usage. Please see #95604 and #95363 (comment).
Yes. It works for Linux, FreeBSD, and Windows, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the answer. Might make sense to leave a comment in the file about this, and perhaps link to #139744, stating that it is a regression test for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, is the expected behaviour for the symbol to still be present, or do we expect the linker to completely strip it out? E.g. would dlsym(RTLD_DEFAULT, "used")
work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The symbol is present in fhe dynamic library. It's GC-ed iff the final artifact is the executable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An idea then would perhaps be to add another test (or use UI-test revisions) with #![crate_type = "dylib"]
and //@ dont-check-compiler-stderr
that expectedly fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's alreay tested in https://github.com/rust-lang/rust/tree/master/tests/run-make/c-link-to-rust-dylib.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I meant having test that fails when trying to link undefined symbols in a dylib
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
cc @bjorn3 @petrochenkov in case this is problematic |
#[unsafe(no_mangle)] | ||
pub unsafe fn used() { | ||
println!("THIS_SYMBOL_SHOULD_BE_UNDEFINED = {}", unsafe { THIS_SYMBOL_SHOULD_BE_UNDEFINED }); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I know that #[no_mangle]
implies it, but could we also add an explicit test for #[used]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[used]
emits errors, while #[no_mangle]
does not, on MacOS.
Don't know why.
Edit: using pr + lld
, nightly + lld
, stable + lld
, stable + ld64
, #[used]
emits errors, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know why now.
On MacOS, #[used]
emits llvm.used
. So #[used(compiler)]
is needed here. Is it expected behavior?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL that #[used]
is an alias for #[used(linker)]
on some platforms:
rust/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Lines 195 to 223 in f836ae4
// Unfortunately, unconditionally using `llvm.used` causes | |
// issues in handling `.init_array` with the gold linker, | |
// but using `llvm.compiler.used` caused a nontrivial amount | |
// of unintentional ecosystem breakage -- particularly on | |
// Mach-O targets. | |
// | |
// As a result, we emit `llvm.compiler.used` only on ELF | |
// targets. This is somewhat ad-hoc, but actually follows | |
// our pre-LLVM 13 behavior (prior to the ecosystem | |
// breakage), and seems to match `clang`'s behavior as well | |
// (both before and after LLVM 13), possibly because they | |
// have similar compatibility concerns to us. See | |
// https://github.com/rust-lang/rust/issues/47384#issuecomment-1019080146 | |
// and following comments for some discussion of this, as | |
// well as the comments in `rustc_codegen_llvm` where these | |
// flags are handled. | |
// | |
// Anyway, to be clear: this is still up in the air | |
// somewhat, and is subject to change in the future (which | |
// is a good thing, because this would ideally be a bit | |
// more firmed up). | |
let is_like_elf = !(tcx.sess.target.is_like_darwin | |
|| tcx.sess.target.is_like_windows | |
|| tcx.sess.target.is_like_wasm); | |
codegen_fn_attrs.flags |= if is_like_elf { | |
CodegenFnAttrFlags::USED | |
} else { | |
CodegenFnAttrFlags::USED_LINKER | |
}; |
#[used]
should be changed to #[used(linker)]
unconditionally anyway. Gold is deprecated upstream and broken with current rustc versions anyway: #139425
6e175fc
to
7d10cf7
Compare
r? codegen |
@@ -221,6 +224,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static | |||
|
|||
file.set_macho_build_version(macho_object_build_version_for_target(sess)) | |||
} | |||
if binary_format == BinaryFormat::MachO { | |||
if set_subsections_via_symbols { | |||
file.set_subsections_via_symbols(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still needs a documentation comment IMO explaining why we do this.
This was discussed in today's compiler triage meeting. The compiler team will revisit this beta backport decision next week after this PR merges. |
set subsections_via_symbols for ld64 helper sections closes rust-lang#139744 cc `@madsmtm`
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
On windows-gnu, the linker removes statics marked with |
Can you add the reason windows-gnu is special for this test to the magic comment? |
@bors r=saethlin,madsmtm |
☀️ Test successful - checks-actions |
What is this?This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.Comparing d7ea436 (parent) -> 847e3ee (this PR) Test differencesShow 6 test diffsStage 1
Stage 2
Job group index
Test dashboardRun cargo run --manifest-path src/ci/citool/Cargo.toml -- \
test-dashboard 847e3ee6b0e614937eee4e6d8f61094411eadcc0 --output-dir test-dashboard And then open Job duration changes
How to interpret the job duration changes?Job durations can vary a lot, based on the actual runner instance |
Finished benchmarking commit (847e3ee): comparison URL. Overall result: ❌✅ regressions and improvements - please read the text belowOur benchmarks found a performance regression caused by this PR. Next Steps:
@rustbot label: +perf-regression Instruction countThis is the most reliable metric that we have; it was used to determine the overall result at the top of this comment. However, even this metric can sometimes exhibit noise.
Max RSS (memory usage)Results (primary -0.4%, secondary -1.7%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResults (primary 0.7%)This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 777.966s -> 776.153s (-0.23%) |
I don't really understand how this change could have the performance impact seen here. Some of the regressions do seem like pure noise (with the next run returning back to the previous baseline), but not all of them. @usamoi @saethlin would you agree that the regressions here are unlikely to be actually caused by this change? |
This should only affect macOS/Apple platforms, and I don't think the benchmarks are run on those? |
That is correct. I'll mark this as triaged @rustbot label: +perf-regression-triaged |
closes #139744
cc @madsmtm