-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Remove dependency on libgcc-dw2-1.dll from win32 executables. #29177
Conversation
Rather than injecting a local `_Unwind_Resume` into the current translation unit, just replace `resume` instruction with a direct call the the `eh_unwind_resume` lang item. This is likely to be more robust in the face of future LLVM changes, and also allows us to delegate work back to libgcc's `_Unwind_Resume`.
…our own (for now on for -windows-gnu target only). Since it isn't possible to disable linkage of just GCC startup objects, we now need logic for finding libc installation directory and copying the required startup files (e.g. crt2.o) to rustlib directory. Bonus change: use the `-nodefaultlibs` flag on Windows, thus paving the way to direct linker invocation.
r? @arielb1 (rust_highfive has picked a reviewer for you, use r? to override) |
@vadimcn you never cease to amaze me, fantastic work! I'll try to get around to this tomorrow, and you may be met with a barrage of questions :) |
"rsbegin.o".to_string(), | ||
), | ||
late_link_args: vec!( | ||
"-lmingwex".to_string(), |
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.
Just wondering, what do we rely on mingwex
for anyway?
reverted changes in configure, refactored target.mk
Looks better? |
#[no_mangle] | ||
#[link_section = ".eh_frame"] | ||
// Marks beginning of the stack frame unwind info section | ||
pub static __EH_FRAME_BEGIN__: [u8; 0] = []; |
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.
So just to clarify, this works because:
- The linker will construct the
.eh_frame
section from the list of items contained within it on the command line. This is, however, guarantee to be the first, so&__EH_FRAME_BEGIN__
is guaranteed to be a pointer to the start of the section. - Similarly,
rsend.o
is guarnateed to be at the end, so it's guaranteed that&__EH_FRAME_END__
is at the end of the section.
Does that sound right? Also out of curiosity, what is the __EH_FRAME_END__
symbol used for? It's not explicitly referenced here, so is it referenced or dynamically loaded from the CRT or elsewhere?
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.
Yes, that's my understanding of how this works.
Also out of curiosity, what is the EH_FRAME_END symbol used for?
It's used to support the weight of eh_frame section, thus the extra wide base.
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.
Hm ok, and by "weight" and "extra wide base" do you mean how __EH_FRAME_END__
is a u32 while the start is a [u8; 0]
? (a fact I just realized)
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 other reason is that you can't have a static variable (the zero footer) without a name (at least that I know of).
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.
By extra wide base I meant the underscores :) just kidding :)
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.
Oh dear it looks like my ignorance is leaking, a zero footer makes sense to me!
cc @brson, just wanna give you a heads up about the we-are-building-our-own-object-files strategy. It seems fine to me but figured you may want to know! |
This is basically r+ from me, but I think I'd prefer to hold this off until after the 1.5 beta is released so this lands in 1.6 instead (just so we have some extra time to weed out any problems here). Does that sound ok? |
That's next Thursday, right? Fine by me. |
OK cool, now I just wish I could bors r+ date=2015-... |
⌛ Testing commit afc3046 with merge ccc9ff2... |
💔 Test failed - auto-win-gnu-64-opt |
Uh-oh, that's a stage0 ICE. Crashes in |
Looks like this was my own fault. The tricks I played with injection of the |
Note: for now, this change only affects `-windows-gnu` builds. So why was this `libgcc` dylib dependency needed in the first place? The stack unwinder needs to know about locations of unwind tables of all the modules loaded in the current process. The easiest portable way of achieving this is to have each module register itself with the unwinder when loaded into the process. All modules compiled by GCC do this by calling the __register_frame_info() in their startup code (that's `crtbegin.o` and `crtend.o`, which are automatically linked into any gcc output). Another important piece is that there should be only one copy of the unwinder (and thus unwind tables registry) in the process. This pretty much means that the unwinder must be in a shared library (unless everything is statically linked). Now, Rust compiler tries very hard to make sure that any given Rust crate appears in the final output just once. So if we link the unwinder statically to one of Rust's crates, everything should be fine. Unfortunately, GCC startup objects are built under assumption that `libgcc` is the one true place for the unwind info registry, so I couldn't find any better way than to replace them. So out go `crtbegin`/`crtend`, in come `rsbegin`/`rsend`! A side benefit of this change is that rustc is now more in control of the command line that goes to the linker, so we could stop using `gcc` as the linker driver and just invoke `ld` directly.
Note: for now, this change only affects
-windows-gnu
builds.So why was this
libgcc
dylib dependency needed in the first place?The stack unwinder needs to know about locations of unwind tables of all the modules loaded in the current process. The easiest portable way of achieving this is to have each module register itself with the unwinder when loaded into the process. All modules compiled by GCC do this by calling the __register_frame_info() in their startup code (that's
crtbegin.o
andcrtend.o
, which are automatically linked into any gcc output).Another important piece is that there should be only one copy of the unwinder (and thus unwind tables registry) in the process. This pretty much means that the unwinder must be in a shared library (unless everything is statically linked).
Now, Rust compiler tries very hard to make sure that any given Rust crate appears in the final output just once. So if we link the unwinder statically to one of Rust's crates, everything should be fine.
Unfortunately, GCC startup objects are built under assumption that
libgcc
is the one true place for the unwind info registry, so I couldn't find any better way than to replace them. So out gocrtbegin
/crtend
, in comersbegin
/rsend
!A side benefit of this change is that rustc is now more in control of the command line that goes to the linker, so we could stop using
gcc
as the linker driver and just invokeld
directly.