Moar comments.
This commit is contained in:
parent
9a71c5c331
commit
d710f8ba1f
7 changed files with 60 additions and 31 deletions
|
@ -65,11 +65,11 @@ pub fn opts() -> TargetOptions {
|
||||||
"-nostdlib".to_string(),
|
"-nostdlib".to_string(),
|
||||||
),
|
),
|
||||||
pre_link_objects_exe: vec!(
|
pre_link_objects_exe: vec!(
|
||||||
"crt2.o".to_string(),
|
"crt2.o".to_string(), // mingw C runtime initialization for executables
|
||||||
"rsbegin.o".to_string(),
|
"rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
|
||||||
),
|
),
|
||||||
pre_link_objects_dll: vec!(
|
pre_link_objects_dll: vec!(
|
||||||
"dllcrt2.o".to_string(),
|
"dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
|
||||||
"rsbegin.o".to_string(),
|
"rsbegin.o".to_string(),
|
||||||
),
|
),
|
||||||
late_link_args: vec!(
|
late_link_args: vec!(
|
||||||
|
|
|
@ -400,15 +400,6 @@ pub mod __rand {
|
||||||
pub use rand::{thread_rng, ThreadRng, Rng};
|
pub use rand::{thread_rng, ThreadRng, Rng};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rust runtime's startup objects depend on these symbols, so they must be public.
|
|
||||||
// Since sys_common isn't public, we have to re-export them here explicitly.
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[unstable(feature = "eh_frame_registry", issue = "0")]
|
|
||||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
|
||||||
pub mod __frame_registry {
|
|
||||||
pub use sys_common::unwind::imp::eh_frame_registry::*;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Include a number of private modules that exist solely to provide
|
// Include a number of private modules that exist solely to provide
|
||||||
// the rustdoc documentation for primitive types. Using `include!`
|
// the rustdoc documentation for primitive types. Using `include!`
|
||||||
// because rustdoc only looks for these modules at the crate level.
|
// because rustdoc only looks for these modules at the crate level.
|
||||||
|
|
|
@ -32,6 +32,11 @@ use thread::{self, Thread};
|
||||||
// Reexport some of our utilities which are expected by other crates.
|
// Reexport some of our utilities which are expected by other crates.
|
||||||
pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt};
|
pub use sys_common::unwind::{begin_unwind, begin_unwind_fmt};
|
||||||
|
|
||||||
|
// Rust runtime's startup objects depend on these symbols, so they must be public.
|
||||||
|
// Since sys_common isn't public, we have to re-export them here.
|
||||||
|
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
||||||
|
pub use sys_common::unwind::imp::eh_frame_registry::*;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
#[lang = "start"]
|
#[lang = "start"]
|
||||||
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
|
fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
|
||||||
|
|
|
@ -232,6 +232,7 @@ pub mod eabi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See docs in the `unwind` module.
|
||||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu", not(test)))]
|
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu", not(test)))]
|
||||||
#[lang = "eh_unwind_resume"]
|
#[lang = "eh_unwind_resume"]
|
||||||
#[unwind]
|
#[unwind]
|
||||||
|
@ -241,6 +242,10 @@ unsafe extern fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! {
|
||||||
|
|
||||||
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
|
||||||
pub mod eh_frame_registry {
|
pub mod eh_frame_registry {
|
||||||
|
// The implementation of stack unwinding is (for now) deferred to libgcc_eh, however Rust
|
||||||
|
// crates use these Rust-specific entry points to avoid potential clashes with GCC runtime.
|
||||||
|
// See also: rtbegin.rs, `unwind` module.
|
||||||
|
|
||||||
#[link(name = "gcc_eh")]
|
#[link(name = "gcc_eh")]
|
||||||
extern {
|
extern {
|
||||||
fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8);
|
fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8);
|
||||||
|
|
|
@ -34,28 +34,35 @@
|
||||||
//! object being thrown, and to decide whether it should be caught at that stack
|
//! object being thrown, and to decide whether it should be caught at that stack
|
||||||
//! frame. Once the handler frame has been identified, cleanup phase begins.
|
//! frame. Once the handler frame has been identified, cleanup phase begins.
|
||||||
//!
|
//!
|
||||||
//! In the cleanup phase, personality routines invoke cleanup code associated
|
//! In the cleanup phase, the unwinder invokes each personality routine again.
|
||||||
//! with their stack frames (i.e. destructors). Once stack has been unwound down
|
//! This time it decides which (if any) cleanup code needs to be run for
|
||||||
//! to the handler frame level, unwinding stops and the last personality routine
|
//! the current stack frame. If so, the control is transferred to a special branch
|
||||||
//! transfers control to its catch block.
|
//! in the function body, the "landing pad", which invokes destructors, frees memory,
|
||||||
|
//! etc. At the end of the landing pad, control is transferred back to the unwinder
|
||||||
|
//! and unwinding resumes.
|
||||||
|
//!
|
||||||
|
//! Once stack has been unwound down to the handler frame level, unwinding stops
|
||||||
|
//! and the last personality routine transfers control to the catch block.
|
||||||
|
//!
|
||||||
|
//! ## `eh_personality` and `eh_unwind_resume`
|
||||||
|
//!
|
||||||
|
//! These language items are used by the compiler when generating unwind info.
|
||||||
|
//! The first one is the personality routine described above. The second one
|
||||||
|
//! allows compilation target to customize the process of resuming unwind at the
|
||||||
|
//! end of the landing pads. `eh_unwind_resume` is used only if `custom_unwind_resume`
|
||||||
|
//! flag in the target options is set.
|
||||||
//!
|
//!
|
||||||
//! ## Frame unwind info registration
|
//! ## Frame unwind info registration
|
||||||
//!
|
//!
|
||||||
//! Each module has its own frame unwind info section (usually ".eh_frame"), and
|
//! Each module's image contains a frame unwind info section (usually ".eh_frame").
|
||||||
//! unwinder needs to know about all of them in order for unwinding to be able to
|
//! When a module is loaded/unloaded into the process, the unwinder must be informed
|
||||||
//! cross module boundaries.
|
//! about the location of this section in memory. The methods of achieving that vary
|
||||||
//!
|
//! by the platform.
|
||||||
//! On some platforms, like Linux, this is achieved by dynamically enumerating
|
//! On some (e.g. Linux), the unwinder can discover unwind info sections on its own
|
||||||
//! currently loaded modules via the dl_iterate_phdr() API and finding all
|
//! (by dynamically enumerating currently loaded modules via the dl_iterate_phdr() API
|
||||||
//! .eh_frame sections.
|
//! and finding their ".eh_frame" sections);
|
||||||
//!
|
|
||||||
//! Others, like Windows, require modules to actively register their unwind info
|
//! Others, like Windows, require modules to actively register their unwind info
|
||||||
//! sections by calling __register_frame_info() API at startup. In the latter
|
//! sections via unwinder API (see `rust_eh_register_frames`/`rust_eh_unregister_frames`).
|
||||||
//! case it is essential that there is only one copy of the unwinder runtime in
|
|
||||||
//! the process. This is usually achieved by linking to the dynamic version of
|
|
||||||
//! the unwind runtime.
|
|
||||||
//!
|
|
||||||
//! Currently Rust uses unwind runtime provided by libgcc.
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
|
@ -8,8 +8,21 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// rsbegin.o and rsend.o are the so called "compiler runtime startup objects".
|
||||||
|
// They contain code needed to correctly initialize the compiler runtime.
|
||||||
|
//
|
||||||
|
// When an executable or dylib image is linked, all user code and libraries are
|
||||||
|
// "sandwiched" between these two object files, so code or data from rsbegin.o
|
||||||
|
// become first in the respective sections of the image, whereas code and data
|
||||||
|
// from rsend.o become the last ones. This effect can be used to place symbols
|
||||||
|
// at the beginning or at the end of a section, as well as to insert any required
|
||||||
|
// headers or footers.
|
||||||
|
//
|
||||||
|
// Note that the actual module entry point is located in the C runtime startup
|
||||||
|
// object (usually called `crtX.o), which then invokes initialization callbacks
|
||||||
|
// of other runtime components (registered via yet another special image section).
|
||||||
|
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
#![feature(linkage)]
|
|
||||||
|
|
||||||
#![crate_type="rlib"]
|
#![crate_type="rlib"]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
@ -20,27 +33,33 @@ pub mod eh_frames
|
||||||
{
|
{
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".eh_frame"]
|
#[link_section = ".eh_frame"]
|
||||||
|
// Marks beginning of the stack frame unwind info section
|
||||||
pub static __EH_FRAME_BEGIN__: [u8; 0] = [];
|
pub static __EH_FRAME_BEGIN__: [u8; 0] = [];
|
||||||
|
|
||||||
// Scratch space for unwinder's internal book-keeping.
|
// Scratch space for unwinder's internal book-keeping.
|
||||||
// This is defined as `struct object` in $GCC/libgcc/unwind-dw2-fde.h.
|
// This is defined as `struct object` in $GCC/libgcc/unwind-dw2-fde.h.
|
||||||
static mut obj: [isize; 6] = [0; 6];
|
static mut obj: [isize; 6] = [0; 6];
|
||||||
|
|
||||||
|
// Unwind info registration/deregistration routines.
|
||||||
|
// See the docs of `unwind` module in libstd.
|
||||||
extern {
|
extern {
|
||||||
fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
|
fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8);
|
||||||
fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
|
fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn init() {
|
unsafe fn init() {
|
||||||
|
// register unwind info on module startup
|
||||||
rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8,
|
rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8,
|
||||||
&mut obj as *mut _ as *mut u8);
|
&mut obj as *mut _ as *mut u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn uninit() {
|
unsafe fn uninit() {
|
||||||
|
// unregister on shutdown
|
||||||
rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8,
|
rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8,
|
||||||
&mut obj as *mut _ as *mut u8);
|
&mut obj as *mut _ as *mut u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MSVC-specific init/uninit routine registration
|
||||||
pub mod ms_init
|
pub mod ms_init
|
||||||
{
|
{
|
||||||
// .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
|
// .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array,
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// See rsbegin.rs for details.
|
||||||
|
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
|
|
||||||
#![crate_type="rlib"]
|
#![crate_type="rlib"]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue