This seems an easy question, but I can't confirm on my own: what happens if an outer struct are #[repr(C)], but at least one inner field in not? Is the outer struct not #[repr(C)]?
I think the answer is no. The outer struct is not #[repr(C)] as per
The intention is that if one has a set of C struct declarations and a corresponding set of Rust struct declarations, all of which are tagged with
#[repr(C)], then the layout of those structs will all be identical. Note that this setup implies that none of the structs in question can contain any#[repr(Rust)]structs (or Rust tuples), as those would have no corresponding C struct declaration -- as#[repr(Rust)]types have undefined layout, you cannot safely declare their layout in a C program.
/// Trap Context
#[repr(C)]
pub struct TrapContext {
/// general regs[0..31]
pub x: [usize; 32],
/// CSR sstatus⋅⋅⋅⋅⋅⋅
pub sstatus: Sstatus,
/// CSR sepc
pub sepc: usize,
}
where Sstatus is not tagged with repr(C), it's an implicit repr(Rust) instead: sstatus.rs - source
Is it safe to read a block of memory (34*8 bytes) and treat it as *mut TrapContext? (Not safe if the answer to the above question is no IMO)
// linker.ld
.section .text
.globl __alltraps
.globl __restore
.align 2
__alltraps:
csrrw sp, sscratch, sp
# now sp->kernel stack, sscratch->user stack
# allocate a TrapContext on kernel stack
addi sp, sp, -34*8
# save general-purpose registers
...
# set input argument of trap_handler(cx: &mut TrapContext)
mv a0, sp
call trap_handler
// Rust
#[no_mangle]
/// handle an interrupt, exception, or system call from user space
pub fn trap_handler(cx: &mut TrapContext) -> &mut TrapContext { ... }