Page 1 of 1

How to make grub not zero initialize a section?

Posted: Tue Jan 12, 2016 5:32 pm
by Nutterts
Hi, I've probably overlooked something simple because I can't imagine it's not possible.

For the bare metal runtime I'm writing for Go I implemented a memory allocator to bootstrap the language features. The idea is that the kernel written using the runtime will implement it's own memory manager which it can hook into the runtime so it'll use that instead.

I wrote this in my boot.s assembly to specify a section for this purpose:

Code: Select all

.section .runtime_memory, "aw", @nobits
.set RUNTIME_MEMORY_SIZE, 67108864 # 64MB

.global runtime_memory_size
runtime_memory_size:
.long RUNTIME_MEMORY_SIZE

.global runtime_memory_top
runtime_memory_top:

.skip RUNTIME_MEMORY_SIZE

.global runtime_memory_bottom
runtime_memory_bottom:
The section in linker.ld is very straight forward:

Code: Select all

/* Runtime memory for the allocator */
.runtime_memory BLOCK(4K) : ALIGN(4K)
{
	*(.runtime_memory)
}
I picked an insanely large memory size for now until I get a better idea how much a kernel would generally require before being able to replace it. The fact that it's zero initialized annoys me because the compiler already zero's or initializes memory when it's requested from the runtime. So it's a pointless waste of time when loading the kernel.

As you can see I already define the section as @nobits, so it doesn't add anything to the ELF output. But judging from a memory dump it seems to initialize to zero no matter what I do.

I tried naming the section .noinit and the noload output section type. I also tried the .text section but it then just ignores @nobits and adds the bloat to the ELF output.

So I'm scratching my head and wondering what I'm doing wrong...

The reason I'm not using the _end symbol and using that as the start of a fixed size heap is that I thought it would be better if grub was aware of it's size so it can pick a proper place to put it at. But maybe I should rethink that or just accept that it's zero initialized?

Re: How to make grub not zero initialize a section?

Posted: Wed Jan 13, 2016 2:57 am
by linguofreak
Nutterts wrote:I picked an insanely large memory size for now until I get a better idea how much a kernel would generally require before being able to replace it. The fact that it's zero initialized annoys me because the compiler already zero's or initializes memory when it's requested from the runtime. So it's a pointless waste of time when loading the kernel.
It's not entirely pointless if your runtime uses paging and keeps the bottom page of virtual memory unmapped. If it does, then if a free section of the heap gets dereferenced as a pointer due to a bug, you'll get an immediate pagefault on trying to access address zero rather than silently corrupting a random location in memory (if you write through the pointer) or reading invalid data, which might take longer to cause the system to fail in an obvious fashion and would make such bugs harder to find and fix.

Re: How to make grub not zero initialize a section?

Posted: Wed Jan 13, 2016 6:11 am
by Nutterts
Your right, I didn't think of that. The runtime doesn't do it itself but code using it might free or use something it shouldn't as I'm not using a GC like the language normally does. I'll put it back in the .bss section and keep it zero initialized. Thx.

Re: How to make grub not zero initialize a section?

Posted: Fri Jan 15, 2016 8:26 am
by onlyonemac
linguofreak wrote:
Nutterts wrote:I picked an insanely large memory size for now until I get a better idea how much a kernel would generally require before being able to replace it. The fact that it's zero initialized annoys me because the compiler already zero's or initializes memory when it's requested from the runtime. So it's a pointless waste of time when loading the kernel.
It's not entirely pointless if your runtime uses paging and keeps the bottom page of virtual memory unmapped. If it does, then if a free section of the heap gets dereferenced as a pointer due to a bug, you'll get an immediate pagefault on trying to access address zero rather than silently corrupting a random location in memory (if you write through the pointer) or reading invalid data, which might take longer to cause the system to fail in an obvious fashion and would make such bugs harder to find and fix.
Free sections of the heap shouldn't be mapped to random locations in memory; they should be unmapped and trigger a pagefault on access, before address zero even comes into the picture.

Re: How to make grub not zero initialize a section?

Posted: Fri Jan 15, 2016 9:03 am
by iansjack
The whole point of linguofreak's suggestion was to catch bugs due to null pointers. Bugs happen, so it's a useful backstop.

Re: How to make grub not zero initialize a section?

Posted: Fri Jan 15, 2016 2:52 pm
by onlyonemac
iansjack wrote:The whole point of linguofreak's suggestion was to catch bugs due to null pointers. Bugs happen, so it's a useful backstop.
Zero-initialising memory is still not going to help. If an application obtains a pointer from unused heap space, that space should still be unmapped, no matter whether or not the physical memory is zero-initialised. If the application uses a null pointer, it can do that without getting said pointer from unused heap space.

There are two separate bugs to catch:
  • Unused heap memory access
  • Null pointer dereferencing
Unused heap memory access should be caught separately, not by initialising the unused heap to zero (and mapping it) and then waiting for any null pointers obtained from the unused heap space to be dereferenced before the kernel notices anything strange. The unused heap access should be trapped separately, by unmapping the unused heap and catching a page fault on any access to it (how the kernel responds - by returning a zero, mapping a page, or terminating the process, for example - is another matter entirely). And null pointers should be trapped separately too (I believe, although I may be mistaken, that Linux catches them by keeping the bottom page of each process's address space unmapped, and getting a page fault on each null pointer dereference).

Re: How to make grub not zero initialize a section?

Posted: Sun Jan 17, 2016 9:16 pm
by Nutterts
In my case I found out that compiler expects memory that it requests the be zero or else it's behavior doesn't match the language spec because an uninitialized new variable could be of any value. The goal is to have Go programs run unmodified (* milage may vary) on bare metal while providing the tools for somebody who wants to write a kernel using it. It's a runtime, not a kernel, so it doesn't do interrupts, paging etc. They need to implement that themselves and then override that part in the runtime.

<offtopic> It's coming along nicely btw. A simple unmodified hello world program in Go compiles and runs flawlessly with a size of about 12KiB which is amazingly small considering the language. Ported a few standard packages with next to no effort. Can't wait till it's finished enough so I can show a few demo's.</offtopic>

I guess grub simply insists on zero'ing everything and I can't blame him.