Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up#[used] attribute #39987
Conversation
rust-highfive
assigned
arielb1
Feb 20, 2017
This comment has been minimized.
This comment has been minimized.
|
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @arielb1 (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
This comment has been minimized.
This comment has been minimized.
|
cc @frehberg who also wanted this |
This was referenced Feb 20, 2017
japaric
force-pushed the
japaric:used
branch
from
c1cdf3f
to
7fe68d5
Feb 20, 2017
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@japaric: I'm a bit confused after reading the PR description:
|
This comment has been minimized.
This comment has been minimized.
|
The answer to my question is that |
This comment has been minimized.
This comment has been minimized.
|
This seems to be an implementation of a closed RFC, which is weird. Shouldn't we go through the regular procedure for adding features? |
This comment has been minimized.
This comment has been minimized.
|
This also seems related https://internals.rust-lang.org/t/precise-semantics-of-no-mangle/4098 @cbiffle |
This comment has been minimized.
This comment has been minimized.
|
@durka Sorry about the confusion, added the missing attributes to the example. (I opened the pull request from the command line and the interface to write the PR message strips lines that start with @TimNN It used the mechanism described here. The commit message has another example. |
japaric
force-pushed the
japaric:used
branch
from
7fe68d5
to
5d9594a
Feb 20, 2017
This comment has been minimized.
This comment has been minimized.
Life before main is very consciously not supported by Rust. Being able to put arbitrary stuff into arbitrary sections for sure seems useful to me, though in general I feel like it should be more prominently unsafe. |
This comment has been minimized.
This comment has been minimized.
|
I'm happy to someone made an effort to come up with implementation. I understand reluctance to include it, and maybe it should go through formal RFE, but I hope it will at least give a green light to purse it. Lack of mechanism like this makes some embedded (and not only embedded) things impossible in Rust, as compiler keeps removing stuff we want to retain for various reasons. There's a reason why both GCC and LLVM have a method to retain unused symbols.
Some people need it to preserve build ids, or other artefacts, otherwise not directly referenced from the code. I needed it to implement a self-test for embedded OS, where test functions marked with a macro are gather in one section, and called sequentially on "boot" (so not before main, but in similar fashion). The same mechanism is used by Linux kernel (and other kernels) to implement init system or module initialization. |
This comment has been minimized.
This comment has been minimized.
It's not |
This comment has been minimized.
This comment has been minimized.
Oh, of course it is unsafe – it allows putting arbitrary bytes into executable sections. This includes calling unsafe functions without explicit unsafe annotation (as in example above), dereferencing raw pointers without explicit unsafe annotation, or pretty much anything else, really. I feel its more of an oversight that |
This comment has been minimized.
This comment has been minimized.
I guess technically it is However this PR is about adding |
This comment has been minimized.
This comment has been minimized.
|
@japaric from your commit message:
Now I'm confused again. What is the point if this still doesn't defeat the linker? |
This comment has been minimized.
This comment has been minimized.
|
Interesting. I'm confused as well. From "a symbol appears in the @llvm.used list, then the compiler, assembler, and linker are required to treat the symbol as if there is a reference to the symbol that it cannot see(...)" |
This comment has been minimized.
This comment has been minimized.
|
Putting |
This comment has been minimized.
This comment has been minimized.
The point is not to "defeat" the linker but to collaborate with it. That's why you put the
The example in the description is contrived. The proper use case is that you have multiple crates and you want some symbols to make it to the final binary (you mark those as
I can't speak for LLVM's documentation but the current implementation is the same as clang's. clang's __attribute__((used))
static const int USED;
static const int UNUSED;
int main() {}
|
This comment has been minimized.
This comment has been minimized.
|
@dpc are you thinking of gcc's Seems it might not be necessary due to the lack of more aggressive LTO in LLVM vs gcc? Or maybe it's just clang? |
This comment has been minimized.
This comment has been minimized.
Oh. Last time I was using this gathering stuff in section mechanism was C compiled with GCC, and I don't remember the details now. Maybe it was working due to the fact we were not using LTO, so linker was not that aggressive, or we marked it in the linker script. With Rust I never got this to work, as I was blocked on not being able to emit symbols marked with @japaric Is |
This comment has been minimized.
This comment has been minimized.
cbiffle
commented
Feb 21, 2017
|
Remember that the linker deals in sections, not objects. A single
referenced symbol in a section is enough to keep that section alive. With
GCC, -ffunction-sections and -fdata-sections separate each function and
static object into separate sections, and the -gc-sections linker flag
turns on aggressive section collection.
(Those three flags are also a great way to find bugs in your C build/link
configuration.)
Marking something (in C) with attribute((used)) is enough to subvert GCC's
notion of what is used and what is not (mostly relevant for statics). If
the symbol wound up in your binary without special steps in the linker
script, you likely assigned it to a section with other used objects and
didn't have -fdata-sections turned on.
Rust seems to generate each object in a separate section by default, and
will thus be subject to more aggressive link-time garbage collection
whether you like it or not.
So we need #[used] to get past rustc's notion of what is used, and linker
script directives to ensure that the symbol is emitted into the binary. To
answer your question, yes, it would be sufficient, assuming #[used] is
implemented equivalently to Clang __attribute__((used)).
…On Feb 20, 2017 8:39 PM, "Dawid Ciężarkiewicz" ***@***.***> wrote:
I can't speak for LLVM's documentation but the current implementation is
the same as clang's. clang's *attribute((used))*-ed items are not treated
specially by the linker and will be removed if unused / not referenced.
Oh. Last time I was using this gathering stuff in section mechanism was C
compiled with GCC, and I don't remember the details now. Maybe it was
working due to the fact we were not using LTO, so linker was not that
aggressive, or we marked it in the linker script. With Rust I never got
this to work, as I was blocked on not being able to emit symbols marked
with llvm.used. I think it's OK to assume that #[used] by itself does not
solve all the pieces of the puzzle, and might be only one of necessary
steps.
@japaric <https://github.com/japaric> Is KEEP in linker + #[used] enough?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#39987 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AACwv-Aj1QidDhAiXX6ACiUP-Vo71vKXks5remp5gaJpZM4MGn6H>
.
|
This comment has been minimized.
This comment has been minimized.
|
@japaric I have a question about your initial example. Is this Regarding unstable features, I have had thoughts about having such a process, but I never got as far as writing it down. I think the general idea was going to be that one writes an RFC defining your goals and motivation. If we agree that these cannot be achieved out of tree, we would allow you to experiment in tree, but a proper (and full) RFC is required for the final result of that experimentation. i.e., you don't go directly from "experiment" to "stable feature", but rather you go from "experimental" to "unstable, on path to stabilization" and then "stable". In a sense this is always the path, but typically this "experimental" phase takes place out of tree (e.g., in a library). |
This comment has been minimized.
This comment has been minimized.
|
@nikomatsakis |
This comment has been minimized.
This comment has been minimized.
|
@dpc ok =) I thought it must be something like that. |
This comment has been minimized.
This comment has been minimized.
|
Just an array of function pointers. Only as arch-specific as function pointers are. |
This comment has been minimized.
This comment has been minimized.
|
Well no, it is more arch-specific than that because this section's name has
meaning to the executable loader.
…On Tue, Feb 21, 2017 at 3:53 PM, Cody Schafer ***@***.***> wrote:
.init_array: The typical name for the section storing DT_INIT_ARRAY. Part
of SysV ABI, and this piece is very widely used even in cases without
dynamic linking.
Just an array of function pointers. Only as arch-specific as function
pointers are.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#39987 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAC3n5DsWQ_6EHLVhk9sAGzk_SVZahN1ks5re07SgaJpZM4MGn6H>
.
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Apr 7, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
|
Prioritizing the rollup that includes these changes @bors retry |
bors
added a commit
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
|
|
bors
added a commit
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
OSX nm doesn't seem to support demangling, apparently you need to use c++filt directly. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
bors
added a commit
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
bors
added a commit
that referenced
this pull request
Apr 7, 2017
This comment has been minimized.
This comment has been minimized.
|
|
bors
merged commit 98037ca
into
rust-lang:master
Apr 7, 2017
This was referenced Apr 7, 2017
japaric
deleted the
japaric:used
branch
Apr 7, 2017
eddyb
referenced this pull request
Apr 13, 2017
Open
Hide __LOAD_NEON_MODULE by using #[used] on a private static. #204
This comment has been minimized.
This comment has been minimized.
|
Triaging rust-lang/rfcs#1002 - @japaric, what's the status of this wrt. stabilization and an RFC? |
japaric commentedFeb 20, 2017
•
edited by pnkfelix
(For an explanation of what this feature does, read the commit message)
I'd like to propose landing this as an experimental feature (experimental as in:
no clear stabilization path -- like
asm!,#[linkage]) as it's lowmaintenance (I think) and relevant to the "Usage in resource-constrained
environments" exploration area.
The main use case I see is running code before
main. This could be used, forinstance, to cheaply initialize an allocator before
mainwhere the alternativeis to use
lazy_staticto initialize the allocator on its first use which it'smore expensive (atomics) and doesn't work on ARM Cortex-M0 microcontrollers (no
AtomicUsizeon that platform)Here's a
stdexample of that:In general, this pattern could be used to let dependencies run code before
main(which sounds like it could go very wrong in some cases). There areprobably other use cases; I hope that the people I have cc-ed can comment on
those.
Note that I'm personally unsure if the above pattern is something we want to
promote / allow and that's why I'm proposing this feature as experimental. If
this leads to more footguns than benefits then we can just axe the feature.
cc @nikomatsakis ^ I know you have some thoughts on having a process for
experimental features though I'm fine with writing an RFC before landing this.
dead_codelint will have to be updated to special case#[used]symbols.Should we extend
#[used]to work on non-generic functions?cc rust-lang/rfcs#1002
cc rust-lang/rfcs#1459
cc @dpc @JinShil