-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking issue for the linkage
feature
#29603
Comments
Currently this translates to the various linkage models of LLVM, for example the values of the attribute can be: match name {
"appending" => Some(llvm::AppendingLinkage),
"available_externally" => Some(llvm::AvailableExternallyLinkage),
"common" => Some(llvm::CommonLinkage),
"extern_weak" => Some(llvm::ExternalWeakLinkage),
"external" => Some(llvm::ExternalLinkage),
"internal" => Some(llvm::InternalLinkage),
"linkonce" => Some(llvm::LinkOnceAnyLinkage),
"linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
"private" => Some(llvm::PrivateLinkage),
"weak" => Some(llvm::WeakAnyLinkage),
"weak_odr" => Some(llvm::WeakODRLinkage),
_ => None,
} Some worries about this are:
That being said, it's the only way to do weak symbols on Linux and it's also convenient for exporting a known symbol without worrying about privacy on the Rust side of things. I would personally want to reduce the set of accepted linkage types and then state "well of course linkage is platform-specific!" |
cc #29629 |
This feature is fundamentally broken. Consider the following code: static unsigned long B = 0;
unsigned long *A = &B;
void f(void) { } #![feature(linkage)]
#[link_name = "c_part"]
extern {
#[linkage = "extern_weak"] static A: *const usize;
fn f();
}
fn main() {
unsafe {
f();
println!("{:x} @ {:x} @ {:p}", *(*A as *const usize), *A, A);
}
} Which prints |
This attribute is also used incorrectly here. |
#18804 needs to be resolved before stabilization. |
I think we should at least work on stabilising the To give an example of a use-case for That being said, // crate older version
#[linkage="weak"]
static mut FOO: u32 = !0; // crate newer version
#[linkage="weak"]
static mut FOO: char = 'a'; when linked together, all uses of |
extern_weak is broken in such a dubious way that even though I pointed out two years ago that it was being used incorrectly in the stdlib, the bug still hasn't been fixed.
gcc and clang handle this attribute correctly. PS: The address of __dso_handle isn't actually too significant in __cxa_thread_atexit_impl and &__dso_handle is only a few bytes off. PSS: Wow, looks like I already explained this above (also two years ago). Maybe the NSA is trying to keep this potential remote code execution unfixed. 🤔 |
Ping @alexcrichton @nagisa what's the status here? Is there a bug here that can be solved / mentored? |
@cramertj I personally consider this a perma-unstable issue for now. In general symbol visibility and ABIs are something that historically rustc hasn't done much to specify and has had a lot of freedom over. We relatively regularly tweak ABIs, symbol names, etc. There's a very thin layer at the end (like a C ABI) which is pretty stable but even that gets sketchy sometimes ( I think we've benefitted quite greatly from the symbol visibility flexibility we've had historically in terms of compiler refactorings and heading off regressions. It's hard to introduce a regression when you can't rely on the feature in the first place! Along those lines I think there's definitely some select use cases where using something like (plus that and the whole |
Given that crate owners can't control how many instances of their crate will be included in a given binary, it seems that we really need a mechanism at least for weak linkage in stable Rust. I got bit by the fallout from #29603 (comment), where rust-libloading gained a cc complation step to workaround this missing feature. |
I would love some mechanism to merge statics and variables with the same value (and name, possibly). Consider the following code: // In my actual code, this is a more complicated proc macro.
macro_rules! special_number {
($value: expr) => {
{
// In my actual code, these static variables also have
// the special `export_name` of
// "\x01L_special_number_<unique_id>", where
// `<unique_id>` is a unique identifier to avoid
// symbol conflicts.
#[link_section = ".data,__custom_special_section"]
static SPECIAL_NUMBER: usize = $value;
&SPECIAL_NUMBER
}
};
}
extern {
fn consume_special_number(value: &usize);
}
pub fn main() {
unsafe {
consume_special_number(special_number!(42));
consume_special_number(special_number!(42));
consume_special_number(special_number!(42));
};
} This will generate three different static variables. I would love it if I could get Rust to merge these static variables into one single static variable. Using a There are two ways the merging could be performed:
I would be prefer option 2 (merging by name). Perhaps this is what the The |
I have a couple of ideas that might help stabilize weak linkage. First of all, the syntax. The problem with weak linkage is that its semantics are "the address of this variable might be null" which is not allowed in Rust, so the compiler puts the real symbol inside the first level of indirection, which is confusing. I propose, instead of an attribute, a type extern "C" {
static foo: Weak<fn(usize) -> *const u8>;
} This would be special-cased by the compiler in the same way it is now, where the symbol fn as_ref(&self) -> Option<&'static T>;
unsafe fn as_ref_unchecked(&self) -> &'static T;
unsafe fn as_mut(&mut self) -> Option<&'static mut T>;
unsafe fn as_mut_unchecked(&mut self) -> &'static mut T; Second, the semantics. Instead of "whatever llvm's extern_weak does," I think this is the behavior that people actually want, and is supported on Linux, OSX, and Windows. Getting it to work this way requires providing some flags to the linker ( |
Marking the overall |
Should a separate issue be opened to specifically discuss "weak" linkage (or any other desired linkage attributes), or should discussion of stable linkage attributes continue to be discussed here? |
A small rant about weak linkage: It's really two or maybe three separate features stuffed into one. They have the same syntax in GNU extensions to C (
I find this situation quite confusing. I'm not suggesting we should try to rewrite the terminology that platforms have established, but I think we can at least clearly differentiate between weak references and definitions. For example, in @danielkeller's suggestion, instead of |
Yeah, I think that we should avoid conflating these if we ever decide to expose this as a feature. Weak imports behave quite well on darwin (where they're extremely widely used, usually via the macros like That said, it's not clear what we need to do to make our implementation of them actually work -- Oddly, everything actually works without the if the Rust code is built as a static library and linked into an XCode build. I haven't looked into it but this implies that... there's a workaround in XCode for the linker's behavior? If so, this would be pretty hairy, to be honest, so frankly I hope it is not what's happening? |
Nope! That was wrong. It turns out that the way it works on apple is that the symbol must exist at link time (e.g. on the host system) or you get the undefined symbol error. This is orthogonal to it being weak reference/import, which just indicates whether it's allowed to resolve. I suppose this might be to save people who try to weakly link against XCode does seem to work around this, using some shenanigans with |
For now, can we open up the restrictions of Update: the following now works: extern "C" {
#[linkage = "extern_weak"]
static puts: Option<unsafe extern "C" fn(x: *const u8)>;
}
fn main() {
let str = b"called puts\n\0";
let p = unsafe { puts }.expect("puts isn't linked");
unsafe { (p)(str.as_ptr()) }
} |
I propose that the linkage attributes other than "weak" and "extern_weak" should be disabled, since they have no practical usages, and furthermore, some unsupported attributes are causing ICE, such as #109681. |
Tests crash from inappropriate use of common linkage Follows up my proposal under the [tracking issue for the linkage feature](rust-lang#29603 (comment)). Adds test for [issue 109681](rust-lang#109681).
Rollup merge of rust-lang#113807 - mojingran:master, r=WaffleLapkin Tests crash from inappropriate use of common linkage Follows up my proposal under the [tracking issue for the linkage feature](rust-lang#29603 (comment)). Adds test for [issue 109681](rust-lang#109681).
Tracks stabilization for the
linkage
attribute.The text was updated successfully, but these errors were encountered: