-
Notifications
You must be signed in to change notification settings - Fork 59
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
Are statics confined to the size indicated by their type? #259
Comments
It doesn't seem so for as long as you use one of a certain set of linkage types that you can only achieve using https://llvm.org/docs/LangRef.html#global-variables
Yes #![feature(linkage)]
extern "C" {
#[linkage = "weak"]
static mut BEGIN: *mut ();
#[linkage = "weak"]
static mut END: *mut ();
}
pub fn memset() {
unsafe {
std::ptr::write_bytes(BEGIN, 42, (END as *mut _ as usize) - (BEGIN as *mut _ as usize))
}
} define void @_ZN7example6memset17hc68914140fa4fa7bE() unnamed_addr #0 !dbg !6 {
ret void, !dbg !10
} #![feature(linkage)]
extern "C" {
#[linkage = "weak"]
static mut BEGIN: *mut u8;
#[linkage = "weak"]
static mut END: *mut u8;
}
pub fn memset() {
unsafe {
std::ptr::write_bytes(BEGIN, 42, (END as *mut _ as usize) - (BEGIN as *mut _ as usize))
}
} @BEGIN = weak global i8
@END = weak global i8
define void @_ZN7example6memset17hc68914140fa4fa7bE() unnamed_addr #0 !dbg !6 {
start:
tail call void @llvm.memset.p0i8.i64(i8* nonnull align 1 @BEGIN, i8 42, i64 sub (i64 ptrtoint (i8* @END to i64), i64 ptrtoint (i8* @BEGIN to i64)), i1 false) #2, !dbg !10
ret void, !dbg !16
} |
@bjorn3 your first Rust version is wrong, you need to use The 2nd version seems fine, right? When you just paste some code without comments I have no clue what it is you want to demonstrate with that code. :) |
oops
I wanted to demonstrate the difference, but you already found why it behaves different. |
Note that in this pattern, the address of But it seems like any issues with that could be worked around by declaring |
Further, if the range is empty, |
Edit: Bah, after writing this I have noticed your bug report over in cortex-m-rt where you pointed this out already. Original: Your discussion suggests to me that the code found in, e.g., cortex-m-rt's reset routine may be unsound. All the Separately, the way they are made to not exist in their current linker script ensures that they will alias whatever static happens to appear next in link order. (e.g. Making the symbols types ZSTs and eliminating the aliasing seems like a good idea. That would wind up with code like this (slightly simplified from the upstream impl): extern "C" {
// These symbols come from `link.x` and assume that
// data, bss, and uninit appear in exactly that order. Each
// section must begin and end at a 4-byte boundary.
static mut __sdata: ();
static mut __sbss: ();
static mut __suninit: ();
}
// Initialize RAM
r0::zero_bss(&mut __sbss as *mut u32, &mut __suninit as *mut u32);
r0::init_data(&mut __sdata as *mut u32, &mut __sbss as *mut u32, &__sidata as *const u32); Now, a thing to note there: it is entirely possible for Assuming it does not, this routine seems to either need to require that the linker script insert some minimal dummy data in each section to stop aliasing, or export pointer-valued statics it can load from instead of ZST symbols at boundaries.... |
r0 is likely unsound. This replaces the data/bss init with an assembly routine that is guaranteed not to get mangled by the compiler. Context: rust-lang/unsafe-code-guidelines#259
r0 is likely unsound. This replaces the data/bss init with an assembly routine that is guaranteed not to get mangled by the compiler. Context: rust-lang/unsafe-code-guidelines#259
Aliasing is about references pointing to overlapping memory regions. ZST references cannot overlap with anything as they point to 0 bytes, i.e., to no memory at all. let mut x = ((), ());
let ref1 = &mut x.1;
let ref1 = &mut x.2; IOW, aliasing is not a concern with ZST pointers. |
Moving from rust-lang/rust#107975, can the reference be updated regarding the behavior of statics around aliasing and linker scripts? From the above discussion it's clear that extern statics should be declared as ZSTs when used to demarcate sections of memory. |
Just wanted to note that the LangRef wording has since been updated to reflect reality:
That is, accesses past the declared size are not generally UB, but the global must be dereferenceable up to the declared size at least. |
I assume that our semantics follow suit, then. That is, we may, for now, decline to answer the question of "What if you relocate-in a validly initialized instance of something bigger than the static? Can you read past the end of the static then?" but we definitely assert that the originally defined size is dereferenceable (for an immutable static). This much is already implied by our rules regarding extern statics, but we could spell it out with a clue-by-four, for the benefit of the programmers who would prefer to skim rather than closely read the rules regarding sound and unsound behavior. ...wait, does that imply that this also holds for |
Occasionally, people ask about a pattern where a program has
extern
statics likeand the intention is not that these are two integers, but that these indicate an array of integers between the two addresses.
Is that legal, or may the compiler assume that accesses outside of the
u32
are out-of-bounds and thus UB?That boils down to two questions:
The former is something that hopefully the LLVM docs can answer. If the answer is "yes", Rust would have to follow suit or lobby for changing LLVM. If the answer is "no", we can decide either way.
The pattern is also a bit weird in that it promises that there are at least 4 bytes of memory available at
begin
andend
each. If the actual region of memory is smaller than that, I am fairly sure that at least any use of the static is UB --BEGIN
denotes a place of size 4, and it is (currently) UB to create dangling places. If we wanted to change this we again need to start by figuring out what LLVM's rules are.The text was updated successfully, but these errors were encountered: