Global/static Variable in Flat Binary

Programming, for all ages and all languages.
Post Reply
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Global/static Variable in Flat Binary

Post by Geometrian »

Hi,

I have a very basic working kernel written in C that can print stuff.

I noticed that I cannot declare global variables without the kernel not running. I find this very odd. I thought this might be related, so I link into an ELF, and then use objcopy. The kernel still works, but as soon as I declare a global variable, it doesn't.

Here's my compilation:

Code: Select all

nasm  -f elf32  MOSS/kernel/jump.asm  -o jump.o
gcc  -c  -Wall -Wextra -Werror  -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -nostdinc -ffreestanding  MOSS/kernel/kernel.c  -o kernel.o
ld  --entry jump  jump.o kernel.o  -o jump_kernel.elf
objcopy  -O binary  jump_kernel.elf  kernel.bin
Minimal sample:

Code: Select all

;jump.asm
[BITS 32]
[global jump]
[extern kernel_main]
jump:
	call  kernel_main

Code: Select all

//kernel.c
//static unsigned char* video = (unsigned char*)(0x00B8000); //uncomment this to see problem
void kernel_main(void) {
	unsigned char* video2 = (unsigned char*)(0x00B8000);
	video2[0] = 'H';
	video2[1] = 0x07;
	video2[2] = 'i';
	video2[3] = 0x07;

	HANG: goto HANG;
}
EDIT: the same occurs with function-scope static variables.

Thanks,
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Global/static Variable in Flat Binary

Post by bluemoon »

Geometrian wrote:The kernel still works, but as soon as I declare a global variable, it doesn't.
How that doesn't work? Do it link successfully? Is grub(or your boot loader) refuse to load it? or it loaded and crash at some point?
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

bluemoon wrote:How that doesn't work? Do it link successfully? Is grub(or your boot loader) refuse to load it? or it loaded and crash at some point?
It basically just sits at the bootloader. As far as I can tell, it doesn't execute anything. Maybe it's jmp-ing to a nop?
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

I think it's modifying the location of the entry point somehow, so that the hardcoded jump in the bootloader doesn't function. How can I explicitly set the linker to compensate for the extra data?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Global/static Variable in Flat Binary

Post by gerryg400 »

Geometrian wrote:I think it's modifying the location of the entry point somehow, so that the hardcoded jump in the bootloader doesn't function. How can I explicitly set the linker to compensate for the extra data?
When you convert the ELF file to a flat binary you are removing all the extra information that an ELF file contains. e.g. the entry point. Once you take that information away there is no way for a loader to know where to enter the binary.
If a trainstation is where trains stop, what is a workstation ?
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

gerryg400 wrote:When you convert the ELF file to a flat binary you are removing all the extra information that an ELF file contains. e.g. the entry point. Once you take that information away there is no way for a loader to know where to enter the binary.
. . . which is why the entry point needs to be at a particular place. I have had improved success with using the linker option "-Ttext 0x1000" or using the linker.ld script given on the C++ Bare Bones page, but the kernel still runs incorrectly when using some things (notably arrays and static variables), and I have a hunch that global int variables working is basically chance.

This is exactly my problem, but no helpful answer.

Thanks,
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Global/static Variable in Flat Binary

Post by gerryg400 »

The best thing to do is to disassemble the binary and see where the linker is putting things. You should be able to identify the text, data and rodata sections by inspection. That way you can quantify your experiments and see what exactly is going on.

Did you write your own loader ? In this case it's probably helpful if you did so that you can understand what it's doing.
If a trainstation is where trains stop, what is a workstation ?
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Global/static Variable in Flat Binary

Post by bluemoon »

This is a sign of relocation error - your code does not agree with where it is loaded, it's probably best to user a debugger to see where exactly the cpu is trying to access for the global variables.
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

After disassembling the kernel, it's clear that the first code point is actually a function that draws a pixel. The actual code for the main function doesn't come until after.

How should I resolve that--when I compile the kernel or when I link it? Or should I resolve it by trying to put the kernel's main function first?

Thanks,
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Global/static Variable in Flat Binary

Post by bewing »

Yes, the third way -- for a flat binary executable, you always want the entrypoint to be at the very beginning. Which means that when you compile and link, the sourcefile that contains the entrypoint has to be first in the list, and the function that is your entrypoint must be the first function in your sourcefile.
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

Okay, I've rearranged the file. I think that helps the problem. The disassembly looks right for sure: the jump starts at 0x1000, and jumps to the kernel's main function at 0x1008.

However, I'm noticing that the data within global arrays appears to be all zero. Locally declared arrays mostly seem to work.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Global/static Variable in Flat Binary

Post by bewing »

There really is no such thing as a globally defined variable in a flat binary. To have the compiler define a shared memory address you need to have symbols, and a flat binary has none -- that's basically the point of a flat binary. You need to allocate all your memory dynamically, or to use only known (hardcoded) memory addresses.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Global/static Variable in Flat Binary

Post by Combuster »

I posted a wall of text back at SO for people's future reference. And the answer still applies to you.

At any rate, putting text at 0x1000 means a custom bootloader. Where does your data, read-only data and bss section end up in the binary? Where do they end up in physical RAM? What addresses are being used to access these sections? This problem is not fixed using guesswork, but you should already know the rough answers to these questions before you even run any assembler or compiler, so you can check that they did what you want them to do - not the other way around.

@bewing: I believe we're still talking about static content here, not dynamically loaded content. The symbols are available up to the linking process.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Geometrian
Member
Member
Posts: 77
Joined: Tue Nov 20, 2012 4:45 pm
Contact:

Re: Global/static Variable in Flat Binary

Post by Geometrian »

The main problem seems to have been that the sector with the data wasn't being loaded by the bootloader--that combined with a number of bugs I have fixed. I am pleased to report that I can now print to the screen with a custom font, and use global variables and classes.

Thanks all!
ranok
Posts: 3
Joined: Fri Dec 07, 2012 3:52 pm

Re: Global/static Variable in Flat Binary

Post by ranok »

I find the best way to arrange the kernel, especially when it gets more complex is to use linker scripts, that way you can define entry points, where you want the various sections placed and linked together in the output flat binary. See http://www.bravegnu.org/gnu-eprog/lds.html or the wiki for more help in this area.
Post Reply