3

I'm experimenting with programming bare-metal embedded systems in Rust. One of the things that is typically done in C startup code is zero-initializing the BSS segment for any global or static uninitialized variables.

However, in Rust, I can't figure out how to create any global or static uninitialized variables (even using unsafe code). In other words, I can't figure out how to write any Rust code so the compiler will populate the BSS segment with something.

I tried...

static BSS_Data: i32 = unsafe { core::mem::uninitialized() };

....but the compiler rejected it.

Is there any way to write Rust code (unsafe or otherwise) that will result in a populated BSS segment? Is the BSS segment guaranteed to always be empty in any program written entirely in Rust?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Verax
  • 2,409
  • 5
  • 27
  • 42
  • 1
    **zero-initializing** the BSS segment for any global or static **uninitialized** variables — which do you want? If you want it to be zero-initialized, then *initialize it to zero*. That being said, *you* will have to write any code that copies values out of the flash memory and into RAM. That's what bare-metal means. – Shepmaster Nov 07 '16 at 13:38
  • I don't know anything about Rust, but can't you just declare a static variable and initialize it to zero? That should force it to get allocated in .bss. – Lundin Nov 07 '16 at 14:56
  • @Lundin If you initialize it to zero in your code, it will go into the data segment. – Verax Nov 07 '16 at 23:48
  • @Shepmaster If you've done bare-metal programming before, you'll know that you zero the BSS segment not just for your code but for code that others write for your system. Regardless, this question isn't about how or whether to initialize variables, its about whether or not its possible to put data in the BSS segment using Rust. – Verax Nov 07 '16 at 23:48
  • @Verax Then your .bss segment works differently than all other .bss segments in the world. Strange. The very purpose of having a .bss to begin with is to speed up zero-initialization. – Lundin Nov 08 '16 at 07:16
  • @Lundin You are right, I was wrong. Zero-initialized data goes in the .bss segment. If you want to create an answer explaining that .bss is populated with both uninitialized _and_ zero-initialized data, I'll accept it. Thanks. – Verax Nov 08 '16 at 09:34

2 Answers2

0
static mut XYZ: [u8; 0xabc123] = [0; 0xabc123];

fn main() {
    unsafe { println!("{}", XYZ[1000]); }
}
$ rustc bss.rs 
$ readelf -SW bss | grep bss
  [21] .tbss             NOBITS          000000000004b178 04a178 000028 00 WAT  0   0  8
  [28] .bss              NOBITS          000000000004e038 04d038 abc220 00  WA  0   0  8
$ ./bss 
0
hdante
  • 7,685
  • 3
  • 31
  • 36
-1

The purpose of the .bss segment is to speed up initialization of all static storage duration variables with value zero. But also to save NVM, since it doesn't make sense to save x bytes all with the value 0 in flash and then copy them to RAM one by one.

The solution to your problem might be to declare a static variable and explicitly initialize it to zero. Because all variables with static storage duration that are initialized to value zero end up in .bss.

As a side-effect of this, all uninitialized static storage duration variables also end up in .bss too. Because in C (and in languages derived from/inspired by C) there is a requirement that if a variable with static storage duration is not initialized explicitly by the programmer, it must be initialized to value zero.

For example this is formally specified in the C11 standard 6.7.9:

If an object that has static or thread storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;


Pseudo code example of how .data and .bss initialization will differ.

More info of the different memory types and where different kind of variables end up in an embedded system.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • So, what can you show that proves that **in Rust** this happens? – Shepmaster Nov 08 '16 at 13:11
  • 2
    @Shepmaster The behavior of the linker is not specified by any language standard. There is no requirement that a `.bss` segment must be present. Similarly, the manner in which initialization of static storage duration variables is carried out is not specified by a language standard either. – Lundin Nov 08 '16 at 16:08