Skip to content

Commit 287fd69

Browse files
authored
Various cleanups to the self-relocation code (#129)
* Use byte_add where possible * Hardcode relocation entry sizes Glibc only checks the DT_REL*ENT it in a debug assertion and musl ignores them entirely, so we can be pretty sure that they will never change. Hardcoding them makes the produced binaries a tiny bit smaller and faster. * Avoid all uses of with_exposed_provenance in relocate By keeping around the original pointers rather than immediately converting them to addresses. This is safe as none of these pointers, nor their pointed to memory are affected by the relocations we are about to perform. * Ensure self-relocation never panics This is necessary as panicking would crash before relocations are performed. I've manually verified that no panic calls are made in release mode. When debug assertions are enabled there are still a couple of panics inserted by the compiler, but these should be unreachable if there are no bugs in the self-relocation code.
1 parent e585b7e commit 287fd69

7 files changed

Lines changed: 159 additions & 74 deletions

File tree

src/arch/aarch64.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ pub(super) unsafe extern "C" fn _start() -> ! {
4040
)
4141
}
4242

43+
/// Abort the process without involving any panic handling code.
44+
///
45+
/// This is a stable equivalent to `core::intrinsics::abort()`.
46+
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
47+
#[cfg(relocation_model = "pic")]
48+
pub(super) fn abort() -> ! {
49+
unsafe {
50+
asm!("brk #0x1", options(noreturn));
51+
}
52+
}
53+
4354
/// Compute the dynamic address of `_DYNAMIC`.
4455
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
4556
#[cfg(relocation_model = "pic")]
@@ -161,7 +172,11 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
161172
options(nostack, preserves_flags),
162173
);
163174

164-
assert_eq!(r0, 0);
175+
if r0 != 0 {
176+
// Do not panic here as libstd's panic handler needs TLS, which is not
177+
// yet initialized at this point.
178+
abort();
179+
}
165180
}
166181

167182
/// The required alignment for the stack pointer.

src/arch/arm.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ pub(super) unsafe extern "C" fn _start() -> ! {
4040
)
4141
}
4242

43+
/// Abort the process without involving any panic handling code.
44+
///
45+
/// This is a stable equivalent to `core::intrinsics::abort()`.
46+
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
47+
#[cfg(relocation_model = "pic")]
48+
pub(super) fn abort() -> ! {
49+
unsafe {
50+
asm!(".inst 0xe7ffdefe", options(noreturn));
51+
}
52+
}
53+
4354
/// Compute the dynamic address of `_DYNAMIC`.
4455
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
4556
#[cfg(relocation_model = "pic")]
@@ -173,7 +184,11 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
173184
options(nostack, preserves_flags),
174185
);
175186

176-
assert_eq!(r0, 0);
187+
if r0 != 0 {
188+
// Do not panic here as libstd's panic handler needs TLS, which is not
189+
// yet initialized at this point.
190+
abort();
191+
}
177192
}
178193

179194
/// The required alignment for the stack pointer.

src/arch/riscv64.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ pub(super) unsafe extern "C" fn _start() -> ! {
4040
)
4141
}
4242

43+
/// Abort the process without involving any panic handling code.
44+
///
45+
/// This is a stable equivalent to `core::intrinsics::abort()`.
46+
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
47+
#[cfg(relocation_model = "pic")]
48+
pub(super) fn abort() -> ! {
49+
unsafe {
50+
asm!("unimp", options(noreturn));
51+
}
52+
}
53+
4354
/// Compute the dynamic address of `_DYNAMIC`.
4455
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
4556
#[cfg(relocation_model = "pic")]
@@ -158,7 +169,11 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
158169
options(nostack, preserves_flags),
159170
);
160171

161-
assert_eq!(r0, 0);
172+
if r0 != 0 {
173+
// Do not panic here as libstd's panic handler needs TLS, which is not
174+
// yet initialized at this point.
175+
abort();
176+
}
162177
}
163178

164179
/// The required alignment for the stack pointer.

src/arch/x86.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ pub(super) unsafe extern "C" fn _start() -> ! {
4545
)
4646
}
4747

48+
/// Abort the process without involving any panic handling code.
49+
///
50+
/// This is a stable equivalent to `core::intrinsics::abort()`.
51+
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
52+
#[cfg(relocation_model = "pic")]
53+
pub(super) fn abort() -> ! {
54+
unsafe {
55+
asm!("ud2", options(noreturn));
56+
}
57+
}
58+
4859
/// Compute the dynamic address of `_DYNAMIC`.
4960
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
5061
#[cfg(relocation_model = "pic")]
@@ -190,7 +201,11 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
190201
options(nostack, preserves_flags),
191202
);
192203

193-
assert_eq!(r0, 0);
204+
if r0 != 0 {
205+
// Do not panic here as libstd's panic handler needs TLS, which is not
206+
// yet initialized at this point.
207+
abort();
208+
}
194209
}
195210

196211
/// The required alignment for the stack pointer.

src/arch/x86_64.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ pub(super) unsafe extern "C" fn _start() -> ! {
4040
)
4141
}
4242

43+
/// Abort the process without involving any panic handling code.
44+
///
45+
/// This is a stable equivalent to `core::intrinsics::abort()`.
46+
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
47+
#[cfg(relocation_model = "pic")]
48+
pub(super) fn abort() -> ! {
49+
unsafe {
50+
asm!("ud2", options(noreturn));
51+
}
52+
}
53+
4354
/// Compute the dynamic address of `_DYNAMIC`.
4455
#[cfg(all(feature = "experimental-relocate", feature = "origin-start"))]
4556
#[cfg(relocation_model = "pic")]
@@ -162,7 +173,11 @@ pub(super) unsafe fn relocation_mprotect_readonly(ptr: usize, len: usize) {
162173
options(nostack, preserves_flags),
163174
);
164175

165-
assert_eq!(r0, 0);
176+
if r0 != 0 {
177+
// Do not panic here as libstd's panic handler needs TLS, which is not
178+
// yet initialized at this point.
179+
abort();
180+
}
166181
}
167182

168183
/// The required alignment for the stack pointer.

0 commit comments

Comments
 (0)