-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Add a freestanding target #106
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| - Start Date: 2014-06-03 | ||
| - RFC PR #: (leave this empty) | ||
| - Rust Issue #: (leave this empty) | ||
|
|
||
| # Summary | ||
|
|
||
| Add support for the "unknown" OS in target triples, and disable split stack | ||
| checking on them by default. | ||
|
|
||
| # Motivation | ||
|
|
||
| One of Rust's important use cases is embedded, OS, or otherwise "bare metal" | ||
| software. At the moment, we still depend on LLVM's split-stack prologue for | ||
| stack safety. In certain situations, it is impossible or undesirable to | ||
| support what LLVM requires to enable this (on x86, a certain thread-local | ||
| storage setup). We also link to some libraries unconditionally, making it | ||
| difficult to produce freestanding binaries. | ||
|
|
||
| # Detailed design | ||
|
|
||
| A target triple consists of three strings separated by a hyphen, with a | ||
| possible fourth string at the end preceded by a hyphen. The first is the | ||
| architecture, the second is the "vendor", the third is the OS type, and the | ||
| optional fourth is environment type. In theory, this specifies precisely what | ||
| platform the generated binary will be able to run on. All of this is | ||
| determined not by us but by LLVM and other tools. When on bare metal or a | ||
| similar environment, there essentially is no OS, and to handle this there is | ||
| the concept of "unknown" in the target triple. When the OS is "unknown" many | ||
| features can be assumed to be missing, such as dynamic linking (which requires | ||
| surprisingly complicated runtime support), thread-local storage (threads are | ||
| inherently an OS concept), presence of any given IO routines, etc. | ||
|
|
||
| When the compiler encounters such a target, it will never attempt to use | ||
| dynamic linking, will disable emitting the split stack prologue, and will not | ||
| link to any support libraries. These targets, of the form `*-unknown-unknown`, | ||
| will never be a valid platform for rustc itself to run on, and can only be | ||
| used for cross-compiling a crate. Statically linking to other crates will | ||
| still be valid. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we could not explicitly deny dynamic linking, but rather let the linker duke it out? If the system linker does in fact support dynamic linking, it seems like we shouldn't prevent you from doing so. It often doesn't make sense in a "freestanding setting", but linker error messages will make that pretty apparent pretty quickly.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not always true. You could be using ELF but it dies at runtime on the dynamic object.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite understand. Each dynamic library has implicit dependencies for various symbols (or so I am led to believe) which are resolved by system libraries. When you you successfully link a dynamic library, and then fail to use it at runtime? I'm basically thinking that this require explicit code in the compiler to reject this situation, when it should naturally be rejected by the linker as it will ultimately have more knowledge than we do.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we support dynamic linkers, we're going to need to provide a way to set the ELF interpeter at the very least... and I don't really want to dig into the nitty-gritty of supporting dynamic executables for All The Things we could support.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still not understanding what you're saying here. What is an ELF interpreter? How are we supporting dynamic linkers? Is a regular linker different from a dynamic linker? How is this digging into the nitty gritty of supporting dynamic executables? I don't understand why specifically blacklisting particular platforms is more nitty-gritty than not doing anything at all.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The dynamic linker being the runtime relocator (I'll just call it rtld to avoid confusion in the future), the interpreter being the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It sounds like things can go wrong very quickly, but I'm still not seeing what we're losing by saying "let the linker duke it out?"
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's something annoying that we could avoid entirely on our end, with a nicer user experience. |
||
|
|
||
| "Support libraries" includes libc, libm, and compiler-rt. libc and libm | ||
| are clearly not available on the unknown OS, and the crate author will need to | ||
| provide compiler-rt or a similar library themselves if they use a feature | ||
| requiring it. The goal is to have 0 dependencies on the environment, at | ||
| compile time and runtime, reducing unnecessary surprises for the freestanding | ||
| author and allowing the use of only rustc to compile the crate, rather than | ||
| manually assembling and linking LLVM bitcode. Providing linker arguments | ||
| manually is probably unavoidable in these cases. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I entirely understand this section. The compiler forcibly links to only two libraries, libmorestack and libcompiler-rt. The morestack library is used to provide the The other library, compiler-rt, is also required by LLVM. This library is not a dependency per-se in that I am unaware of any libc functions it depends on. No matter what your target is, I am under the impression that you want to link compiler-rt. This includes any "freestading platform" it sounds like you're describing here. You mention libc and libm, but the compiler knows nothing about these libraries. They are linked to when you manually link to the Also, when you say "providing linker arguments manually is probably unavoidable", what are you referring to?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whoops, don't know where I thought libc/libm came from. As for compiler-rt, if you need it, you can build it for your platform -- or just avoid the features that require it. As to linker arguments, I'm thinking things like linker scripts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have been compiling zinc.rs without compiler-rt, I'm not exactly sure of what it supports. From memory, many of the Example of linker arguments would be linker scripts
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that LLVM will lower intrinsics and other functionality in your program into calls to functions in libcompiler-rt. From this, it is my understanding that if you do not link compiler-rt you will eventually run into linker errors. With this understanding, why do you not want to link to compiler-rt? Is it difficult to build? |
||
|
|
||
| # Drawbacks | ||
|
|
||
| All function calls become unsafe in such a target, since guards against stack | ||
| overflow are not inserted by the compiler. The crate author must be careful | ||
| not to overflow the stack, or set up their own stack safety mechanism. | ||
|
|
||
| # Alternatives | ||
|
|
||
| We could allow disabling split stacks on a per-crate basis. Then calling | ||
| functions from that crate is then unsafe, and we would need to compensate for | ||
| this somehow. We would still need to add a way to not link to | ||
| libc/libm/copmiler-rt. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spelling. |
||
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 had some comments down below about this last sentence. Do you have examples of this being difficult? The compiler does not unconditionally link to any system library, and the two libraries it does link to should have 0 dependencies.
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.
Tobba claimed to have a bunch of issues with this.
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.
And the build system isn't going to make compiler-rt for these targets, since you wouldn't ever be targetting them with
--targetto configure.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 would prefer to talk concretely about these problems.
When talking about "freestanding support", there is a huge realm of use cases, many of which conflict with each other. I have very frequently run into problems which are already solved or when the solution in mind isn't quite solving the real problem. Talking about concrete use cases is much easier to grapple than a bygone story of a difficult time wrangling with the compiler.