I want to load small 64-bit ELF images using BIOS in boot loader for testing purposes. Obviously the image must be small enough to fit into the first 640K due to BIOS limitation.
I was able to load and run a few testing code, except any code that references static/global variables. The problem is gcc produces ip-relative code with a very large/random offset to reference the global/static data (i.e. variable i). Somehow gcc decides to place variable i at 0x208018 regardless the section addresses specified for ld.
This is a very small image starting at address 0x8000. Ideally variable "i" should be located in .data section near 0xf400 (--section-start .data=0xf400). I don't know how gcc comes up with this 0x208018 address. I cannot create a page mapping ahead of time. This leads to crash.
I don't think this is PIC related, but how to make gcc not to produce this ip-relative code and place the global data at specified location?
In the following example, I'd be able to load and run the ELF image if I remove the "static" keyword. If it's "int i" (instead of "static int i"), gcc references it with standard %rbp notation (e.g. -0x4(%rbp)).
Code: Select all
my: my.o
ld -s --section-start .text=0x8000 --section-start .rodata=0xf000 --section-start .bss=0xf200 --section-start .data=0xf400 --section-start .note.gnu.build-id=0xf800 -o $@ $<
my.o: my.c
gcc -o $@ -fpie -nostdlib -fno-asynchronous-unwind-tables $<
Code: Select all
void _start()
{
static int i;
i++;
}
Code: Select all
> objdump -d my
Disassembly of section .text:
0000000000008000 <.text>:
8000: 55 push %rbp
8001: 48 89 e5 mov %rsp,%rbp
8004: 8b 05 0e 00 20 00 mov 0x20000e(%rip),%eax # 0x208018
800a: 83 c0 01 add $0x1,%eax
800d: 89 05 05 00 20 00 mov %eax,0x200005(%rip) # 0x208018
8013: 90 nop
8014: 5d pop %rbp
8015: c3 retq
Code: Select all
> readelf -S my
There are 6 section headers, starting at offset 0xf890:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000008000 00008000
0000000000000016 0000000000000000 AX 0 0 1
[ 2] .bss NOBITS 000000000000f200 00008016
0000000000000008 0000000000000000 WA 0 0 4
[ 3] .note.gnu.build-i NOTE 000000000000f800 0000f800
0000000000000024 0000000000000000 A 0 0 4
[ 4] .comment PROGBITS 0000000000000000 0000f824
0000000000000034 0000000000000001 MS 0 0 1
[ 5] .shstrtab STRTAB 0000000000000000 0000f858
0000000000000032 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)