Skip to content

Commit e2828f5

Browse files
authored
Improve the comments about what can be called during relocation. (#147)
It appears the thing that determines which functions in core we can call is `inline(always)`. Update the comments to reflect that. Thanks to @bjorn3 for pointing out that the issue is inlining rather than functions implemented directly in the compiler!
1 parent 9dd97ba commit e2828f5

File tree

1 file changed

+20
-22
lines changed

1 file changed

+20
-22
lines changed

src/relocate.rs

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,8 @@
99
//! relocation memory accesses, so that Rust semantics don't have to be aware
1010
//! of them.
1111
//!
12-
//! However, we need to be careful to avoid making any calls to other crates.
13-
//! This includes functions in `core` that aren't implemented by the compiler,
14-
//! so we can do `ptr == null()` but we can't do `ptr.is_null()` because `null`
15-
//! is implemented by the compiler while `is_null` is not. And, it includes
16-
//! code patterns that the compiler might implement as calls to functions like
17-
//! `memset`.
18-
//!
19-
//! And we have to avoid reading any static variables that contain addresses,
20-
//! including any tables the compiler might implicitly emit.
21-
//!
22-
//! Implicit calls to `memset` etc. could possibly be prevented by using
23-
//! `#![no_builtins]`, however wouldn't fix the other problems, so we'd still
24-
//! need to rely on testing the code to make sure it doesn't segfault in any
25-
//! case. And, `#![no_builtins]` interferes with LTO, so we don't use it.
12+
//! See the comments on the `relocate` function for additional special
13+
//! considerations.
2614
2715
#![allow(clippy::cmp_null)]
2816

@@ -74,17 +62,27 @@ macro_rules! debug_assert_eq {
7462
/// guarantees that this code won't segfault at any moment.
7563
///
7664
/// In practice, things work if we don't make any calls to functions outside
77-
/// of this crate, not counting functions directly implemented by the compiler.
78-
/// So we can do eg. `x == null()` but we can't do `x.is_null()`, because
79-
/// `null` is directly implemented by the compiler, while `is_null` is not 🙃.
65+
/// of this crate, not counting `inline(always)` functions. So we can do eg.
66+
/// `x == null()` but we can't do `x.is_null()`, because `null` is
67+
/// `inline(always)`, while `is_null` is not 🙃. And, it includes code
68+
/// patterns that the compiler might implement as calls to functions like
69+
/// `memset`.
70+
///
71+
/// Implicit calls to `memset` etc. could possibly be prevented by using
72+
/// `#![no_builtins]`, however wouldn't fix the other problems, so we'd still
73+
/// need to rely on testing the code to make sure it doesn't segfault in any
74+
/// case. And, `#![no_builtins]` interferes with LTO, so we don't use it.
75+
///
76+
/// And, we have to avoid reading any static variables that contain addresses,
77+
/// including any tables the compiler might implicitly emit.
8078
///
81-
/// We do all the relocation memory accesses using `asm`, as they happen
79+
/// And, we do all the relocation memory accesses using `asm`, as they happen
8280
/// outside the Rust memory model. They read and write and `mprotect` memory
8381
/// that Rust wouldn't think could be accessed.
8482
///
85-
/// We also need to take care to avoid panics as panicking will segfault due to
86-
/// `core::fmt` making use of statics that need relocation. Even after all
87-
/// relocations are done we still need to avoid panicking as libstd's panic
83+
/// And, we also need to take care to avoid panics as panicking will segfault
84+
/// due to `core::fmt` making use of statics that need relocation. Even after
85+
/// all relocations are done we still need to avoid panicking as libstd's panic
8886
/// handler makes use of TLS, which won't be initialized until much later.
8987
///
9088
/// So yes, there's a reason this code is behind a feature flag.
@@ -375,7 +373,7 @@ unsafe fn compute_auxp(envp: *mut *mut u8) -> *const Elf_auxv_t {
375373
// Locate the AUX records we need. We don't use rustix to do this because
376374
// that would involve calling a function in another crate.
377375
let mut auxp = envp;
378-
// Don't use `is_null` because that's a call.
376+
// Don't use `is_null` because that's not `inline(always)`.
379377
while (*auxp) != null_mut() {
380378
auxp = auxp.add(1);
381379
}

0 commit comments

Comments
 (0)