How to make grub not zero initialize a section?

Programming, for all ages and all languages.
Post Reply
User avatar
Nutterts
Member
Member
Posts: 159
Joined: Wed Aug 05, 2015 5:33 pm
Libera.chat IRC: Nutterts
Location: Drenthe, Netherlands

How to make grub not zero initialize a section?

Post 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?
"Always code as if the guy who ends up maintaining it will be a violent psychopath who knows where you live." - John F. Woods

Failed project: GoOS - https://github.com/nutterts/GoOS
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

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

Post 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.
User avatar
Nutterts
Member
Member
Posts: 159
Joined: Wed Aug 05, 2015 5:33 pm
Libera.chat IRC: Nutterts
Location: Drenthe, Netherlands

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

Post 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.
"Always code as if the guy who ends up maintaining it will be a violent psychopath who knows where you live." - John F. Woods

Failed project: GoOS - https://github.com/nutterts/GoOS
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

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

Post 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.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

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

Post 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.
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

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

Post 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).
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
User avatar
Nutterts
Member
Member
Posts: 159
Joined: Wed Aug 05, 2015 5:33 pm
Libera.chat IRC: Nutterts
Location: Drenthe, Netherlands

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

Post 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.
"Always code as if the guy who ends up maintaining it will be a violent psychopath who knows where you live." - John F. Woods

Failed project: GoOS - https://github.com/nutterts/GoOS
Post Reply