Unexpected value for the linker script variables - c

I am trying to write my own linker script.
The current version is here:
MEMORY
{
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x00004000
RAM (rwx) : ORIGIN = 0x00004000, LENGTH = 0x00004000
}
STACK_SIZE = 0x3000;
BOOT_PC = 0x1000;
/* Section Definitions */
SECTIONS
{
/* Code and constants */
.text :
{
*(.rodata*);
KEEP(*(.vectors .vectors.*));
. = BOOT_PC;
KEEP(*start.o(.text*));
*(.text*);
_etext = . ;
_idata = . ;
} > ROM
/* Unitialized data */
.bss (NOLOAD) :
{
_sbss = . ;
*(.bss*);
*(COMMON);
_ebss = . ;
} > RAM
/* Initialized data */
.data : AT(_idata)
{
_sdata = . ;
*(.data*);
_edata = . ;
} > RAM
/* Stack */
.stack (NOLOAD):
{
. = ALIGN(8);
. = . + STACK_SIZE;
. = ALIGN(8);
_stack = . ;
} > RAM
}
In my C program, I have global variables which are supposed to go in .bss (foo) and .data(init, a1 and a2) sections:
int foo;
int init = 4;
int a1 = 4;
int a2 = 4;
When I use objdump, I have the following result:
elf/noste.elf: file format elf32-littleriscv
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00004000 l d .sbss 00000000 .sbss
00004004 l d .sdata 00000000 .sdata
00004010 l d .stack 00000000 .stack
00000000 l d .comment 00000000 .comment
00000000 l d .riscv.attributes 00000000 .riscv.attributes
00000000 l df *ABS* 00000000 start.o
0000103c l .text 00000000 _end_trigger
00001050 l .text 00000000 _end_loop
00000000 l df *ABS* 00000000 main.c
00000000 l df *ABS* 00000000 reset.c
0000105c g F .text 0000008c reset_handler
00003000 g *ABS* 00000000 STACK_SIZE
000010e8 g .text 00000000 _etext
00004000 g .text 00000000 _sbss
00004008 g O .sdata 00000004 a1
00004004 g .sdata 00000000 _sdata
00004000 g .text 00000000 _ebss
000010e8 g .text 00000000 _idata
00001000 g .text 00000000 _start
0000400c g O .sdata 00000004 init
00001054 g F .text 00000008 main
00004004 g O .sdata 00000004 a2
00004000 g O .sbss 00000004 foo
00004004 g .sdata 00000000 _edata
0000103c g .text 00000000 _end
00007010 g .stack 00000000 _stack
00001000 g *ABS* 00000000 BOOT_PC
As expected, the different C variables are placed in the .sbss and .sdata sections.
However, _ebss and _edata are not incremented and have the same value than _sbss and _sdata.
Instead of _ebss = 00004000 and _edata = 00004004, I expected _ebss = 00004004 and _edata = 00004010.
An idea about my issue here ?
Thanks for the help.

Related

"kernel must be loaded first"

I wrote a mini-boot loader and a simple kernel that print a string. I followed step-by-step this playlist(First 3 videos to be precise!). Anyway, when I boot my virtual machine(with my ISO) I get those messages:
"error: no multiboot header found."
"error: you need to load the kernel first."
I tried to modify some section of the assembly code in the boot file but without success.
Here is the code:
boot.s
.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot
.long MAGIC
.long FLAGS
.long CHECKSUM
.section .text
.extern kernel_main
.extern call_constructors
.global loader
loader:
mov $kernel_stack, %esp
call call_constructors
push %eax
push %ebx
call kernel_main
_stop:
cli
hlt
jmp _stop
.section .bss
.space 2*1024*1024 ;#2 MiB
kernel_stack:
kernel.c
#include <sys/types.h>
void printf(char * str)
{
uint16_t * VideoMemory = (uint16_t *)0xb8000;
for(int32_t i = 0; str[i] != '\0'; i++)
VideoMemory[i] = (VideoMemory[i] & 0xFF00) | str[i];
}
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void call_constructors()
{
for(constructor* i = &start_ctors; i != &end_ctors; i++)
(*i)();
}
extern "C" void kernel_main(const void * multiboot_structure, uint32_t magic_number)
{
printf("Denos - Version: 0.0.1a");
for(;;);
}
NOTE: sys/types.h comes from my lib. which is included as argument in gcc.
linker.ld
ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)
SECTIONS
{
. = 0x0100000;
.text :
{
*(.multiboot)
*(.text*)
*(.rodata)
}
.data :
{
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
end_ctors = .;
*(.data)
}
.bss :
{
*(.bss)
}
/DISCARD/ :
{
*(.fini_array*)
*(.comment)
}
}
Makefile
GPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti -fno-exceptions -fno-leading-underscore -I ../include/
ASPARAMS = --32
objects = boot.o kernel.o
run: denos.iso
(killall VirtualBox && sleep 1) || true
VirtualBox --startvm 'denos' &
%.o: %.c
gcc $(GPPPARAMS) -o $# -c $<
%.o: %.s
as $(ASPARAMS) -o $# $<
kernel.bin : linker.ld $(objects)
ld $(LDPARAMS) -T $< -o $# $(objects)
install: kernel.bin
sudo cp $< ./boot/kernel.bin
denos.iso: kernel.bin
mkdir iso
mkdir iso/boot
mkdir iso/boot/grub
cp kernel.bin iso/boot/kernel.bin
echo 'set timeout=0' > iso/boot/grub/grub.cfg
echo 'set default=0' >> iso/boot/grub/grub.cfg
echo '' >> iso/boot/grub/grub.cfg
echo 'menuentry "Denos" {' >> iso/boot/grub/grub.cfg
echo ' multiboot /boot/kernel.bin' >> iso/boot/grub/grub.cfg
echo ' boot' >> iso/boot/grub/grub.cfg
echo '}' >> iso/boot/grub/grub.cfg
grub-mkrescue --output=denos.iso iso
rm -rf iso
mv -f denos.iso /home/data/libvirt_iso/
objdump -x kernel.bin(Requested)
kernel.bin: file format elf32-i386
kernel.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0010000c
Program Header:
LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**21
filesz 0x001001ac memsz 0x003001ac flags rwx
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
filesz 0x00000000 memsz 0x00000000 flags rwx
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000100 00100000 00100000 00100000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 000000a0 00100100 00100100 00100100 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .got.plt 0000000c 001001a0 001001a0 001001a0 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00200000 001001ac 001001ac 001001ac 2**0
ALLOC
SYMBOL TABLE:
00100000 l d .text 00000000 .text
00100100 l d .eh_frame 00000000 .eh_frame
001001a0 l d .got.plt 00000000 .got.plt
001001ac l d .bss 00000000 .bss
00000000 l df *ABS* 00000000 boot.o
1badb002 l *ABS* 00000000 MAGIC
00000003 l *ABS* 00000000 FLAGS
e4524ffb l *ABS* 00000000 CHECKSUM
003001ac l .bss 00000000 kernel_stack
0010001d l .text 00000000 _stop
00000000 l df *ABS* 00000000 kernel.c
00000000 l df *ABS* 00000000
001001a0 l O .got.plt 00000000 _GLOBAL_OFFSET_TABLE_
001001a0 g .got.plt 00000000 start_ctors
001000e0 g F .text 00000000 .hidden __x86.get_pc_thunk.ax
001000c2 g F .text 0000001e kernel_main
001000e4 g F .text 00000000 .hidden __x86.get_pc_thunk.bx
001001a0 g .got.plt 00000000 end_ctors
00100088 g F .text 0000003a call_constructors
00100021 g F .text 00000067 _Z6printfPc
0010000c g .text 00000000 loader
I'm so sorry I wasted someone times. I checked 'Makefile' file and I figured out that I was missing 'LDPARAMS = -melf_i386'. Now it boot and print
Thanks anyway.

Object file created by objcopy is not compatible

I have created an object file from a binary file using objcopy as below:
objcopy -I binary -O elf32-little --rename-section .data=.text file.bin file.o
In one of the linker script sections I have included the following to place that file into that section:
file.o (.text)
But I get the following error:
skipping incompatible file.o when searching for file.o
error: ld returned 1 exit status
I am developing for a arm microcontroller so I believe the file format "elf32-little" is correct.
Any help is much appreciated.
#####################################################################
UPDATE FOLLOWING THE INCBIN path:
I have tried a new approach and although I have made some progress still not quite yet there.
This is my assembly file:
.section .text.audio_binary
.global audio_start
audio_start:
.incbin "AudioData.bin"
.global audio_start
audio_end:
.byte 0
.global audio_size
audio_size:
.int audio_start - audio_start
This is the object file I get:
raw_audio_binary.o: file format elf32-little
SYMBOL TABLE:
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .text.audio_binary 00000000 .text.audio_binary
00069a78 l .text.audio_binary 00000000 audio_end
00000000 l .text.audio_binary 00000000 $d
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g .text.audio_binary 00000000 audio_start
00069a79 g .text.audio_binary 00000000 audio_size
And this is the section I have in my linker script:
.text_Flash3 : ALIGN(4)
{
FILL(0xff)
*(.text.$Flash3*)
*(.text.$AUDIO*) *(.rodata.$Flash3*)
*(.text.audio_binary*) /* audio binary */
*(.rodata.$AUDIO*) } > AUDIO
For some reason the linker does NOT place the data in this section (or in any).
Any ideas what is wrong?
I apologise in advance if something is very wrong here, I am new to linker scripts so still understanding them...
If you have a sufficiently recent version of GAS, you can use this to create an object file from a binary input file using the .incbin directive:
.section .rodata
.globl input_wav
input_wav:
.incbin "input.wav"
.globl input_wav_size
input_wav_size:
.long . - input_wav

Difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) in linker script

Among other things I am trying to understand the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4).
Assume we have next files (I have used linker script example from here as a basis):
main.c:
int main(void)
{
test_1();
test_2();
return 0;
}
main.lds:
OUTPUT_ARCH(arm)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
test_1.c:
void test_1(void)
{
return;
}
test_2.c:
void test_2(void)
{
return;
}
If we compile it and dump its content we have next:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 200: [APCS-32] [FPA float format] [software FP]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
But if I change OUTPUT_ARCH(arm) to OUTPUT_ARCH(armv4), I get an error from linker:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_1.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_1.o
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: error: test_2.o uses software FP, whereas main.elf uses hardware FP
c:/sysgcc/arm-elf/bin/../lib/gcc/arm-elf/4.6.3/../../../../arm-elf/bin/ld.exe: failed to merge target specific data of file test_2.o
collect2: ld returned 1 exit status
It can be fixed by specifying -mfloat-abi=hard option. In this case there is a difference in private flags comparing with previous output:
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_1.c -c
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -mfloat-abi=hard test_2.c -c
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x test_1.o
test_1.o: file format elf32-littlearm
test_1.o
architecture: arm, flags 0x00000010:
HAS_SYMS
start address 0x00000000
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000014 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000048 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000048 2**0
ALLOC
3 .comment 00000012 00000000 00000000 00000048 2**0
CONTENTS, READONLY
4 .ARM.attributes 00000010 00000000 00000000 0000005a 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 test_1.c
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 g F .text 00000014 test_1
c:\SysGCC\arm-elf\bin>arm-elf-gcc.exe -static -nostartfiles -T main.lds -o main.elf test_1.o test_2.o
c:\SysGCC\arm-elf\bin>arm-elf-objdump.exe -x main.elf
main.elf: file format elf32-littlearm
main.elf
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00010000
Program Header:
LOAD off 0x00008000 vaddr 0x00010000 paddr 0x00010000 align 2**15
filesz 0x00000028 memsz 0x00000028 flags r-x
private flags = 0: [APCS-32] [FPA float format]
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000028 00010000 00010000 00008000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .comment 00000011 00000000 00000000 00008028 2**0
CONTENTS, READONLY
2 .ARM.attributes 00000010 00000000 00000000 00008039 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00010000 l d .text 00000000 .text
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
00000000 l df *ABS* 00000000 test_1.c
00000000 l df *ABS* 00000000 test_2.c
00010014 g F .text 00000014 test_2
00010000 g F .text 00000014 test_1
Does it mean that OUTPUT_ARCH(armv4) causes linker to generate output solely for hard float?
In general, what is the difference between OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4)?
According to ld manual OUTPUT_ARCH() specifies a particular output machine architecture.
The argument is one of the names used by the BFD library.
But I have found no clear information about BFD library except general information.
I use arm-elf toolchain from here (Binutils 2.22, GCC 4.6.3, Newlib 1.2.0, GDB 7.4).
Thank you in advance for help.
UPDATE 1:
This update is a reply for the comment below.
Compiler -v output from old toolchain we use now:
Using built-in specs.
Target: arm-elf
Configured with: ../gcc-4.4.1/configure --target=arm-elf --host=i686-pc-mingw32 --with-cpu=xscale --without-stabs -nfp --prefix=/c/cross-gcc/4.4.1 --disable-nls --disable-shared --disable-__cxa_atexit
--enable-threads --with-gnu-gcc --with-gnu-ld --with-gnu-as --with-dwarf2 --enable-languages=c,c++ --enable-interwork --disable-multilib --with-gmp=/c/cross-gcc/4.4.1 --with-mpfr=/c/cross-gcc/4.4.1 -
-with-newlib --with-headers=../../newlib-1.17.0/newlib-1.17.0/newlib/libc/include --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp -v
Thread model: single
gcc version 4.4.1 (GCC)
Compiler -v output from newer toolchain I used in the examples (SysGCC arm-elf):
Using built-in specs.
COLLECT_GCC=arm-elf-gcc.exe
COLLECT_LTO_WRAPPER=c:/sysgcc/arm-elf/bin/../libexec/gcc/arm-elf/4.6.3/lto-wrapper.exe
Target: arm-elf
Configured with: ../gcc-4.6.3/configure --target arm-elf --enable-win32-registry=SysGCC-arm-elf-4.6.3 --prefix /c/gnu/auto/bu-2.22+gcc-4.6.3+gmp-4.2.4+mpfr-2.4.1+mpc-0.8+newlib-1.20.0-arm-elf/ --enabl
e-languages=c,c++ --disable-nls --with-newlib --with-headers=../newlib-1.20.0/newlib/libc/include --enable-interwork --enable-multilib --with-float=soft
Thread model: single
gcc version 4.6.3 (GCC)
There is no difference between linker output for OUTPUT_ARCH(arm) and OUTPUT_ARCH(armv4) for old compiler. I think I should have checked it before.
Seems that it is an answer to this question.
My goal is to use the combination -mfpu=vfpv3 -mfloat-abi=hard, but according to Debian documentation and GCC 4.4.7 manual this combination is not supported by GCC 4.4.
In fact if I try to compile with -mfpu=vfpv3 -mfloat-abi=hard by old compiler, it returns error:
sorry, unimplemented: -mfloat-abi=hard and VFP
Still and all it is possible to use -mfpu=vfpv3 -mfloat-abi=softfp with old compiler, but according to this comparison it gives big overhead for small routines.

ld ignores size of nobits input section

When working on a small 32-bit kernel for the x86 architecture I discovered something strange with how ld handles nobits sections.
In my kernel I define a .bootstrap_stack section which holds a temporary stack for the initialisation part of the system. I also hold symbols for the beginning and end of the stack. This input section is redirected to the .bss output section. Each output section of my kernel has a symbol for the beginning and end of the section.
The problem is that in the final executable the symbol for the end of the stack is after the end of the .bss section. In the below examples the symbols stack_top and _kernel_ebss (and _kernel_end) have the same value, which isn't what I wanted.
I expected _kernel_ebss to equal stack_bottom.
However once I rename .bootstrap_stack to .bss this does not happen. Removing nobits also works, but the resulting binary is considerably larger.
Here are the stripped files that reproduce my issue:
boot.s
section .bootstrap_stack, nobits ; this does not work
;section .bootstrap_stack ; this works
;section .bss ; this also works
stack_top:
resb 8096
stack_bottom:
section .text
global _start
_start:
hlt
jmp _start
linker.ld
ENTRY(_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000)
{
_kernel_text = .;
*(.multiboot)
*(.text)
_kernel_etext = .;
}
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000)
{
_kernel_bss = .;
*(COMMON)
*(.bss)
*(.bootstrap_stack)
_kernel_ebss = .;
}
_kernel_end = .;
}
Here are the symbols:
$ objdump -t kernel | sort
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .text 00000000 _kernel_bss
c0101000 g .text 00000000 _kernel_ebss
c0101000 g .text 00000000 _kernel_end
c0101000 l .bootstrap_stack, 00000000 stack_top
c0101000 l d .bootstrap_stack, 00000000 .bootstrap_stack,
c0102fa0 l .bootstrap_stack, 00000000 stack_bottom
By renaming .bootstrap_stack to .bss I get what I expected.
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .bss 00000000 _kernel_bss
c0101000 l .bss 00000000 stack_top
c0101000 l d .bss 00000000 .bss
c0102fa0 g .bss 00000000 _kernel_ebss
c0102fa0 g .bss 00000000 _kernel_end
c0102fa0 l .bss 00000000 stack_bottom
My question is whether this is expected behaviour of ld. If yes, what is the problem with my example, because as far as I understand .bss is also a nobits section, but it produces the expected result?
Okay I figured it out.
Apparently you're not supposed to have a comma right after the name of the section. objdump includes the comma in the name of the section so that clearly shows that that is the mistake.
So
section .bootstrap_stack, nobits
should be
section .bootstrap_stack nobits

gnu linker script symbol value got reassigned

I use a linker script to describe the memory map of my os kernel. In the linker script I defined many symbols to record location of section start/end. The linker script is as follow:
OUTPUT_FORMAT(binary)
SECTIONS {
/DISCARD/ : {
*(.comment)
*(.note.GNU-stack)
*(.eh_frame)
}
. = 0x100000;
kernel_load_addr = .;
.text : {
kernel_text_start = .;
*(.boot)
*(.text*)
kernel_text_end = .;
} = 0x90
.data : {
kernel_data_start = .;
*(.rodata*)
*(.data*)
kernel_data_end = .;
} = 0
.bss : {
kernel_bss_start = .;
*(COMMON)
*(.bss)
kernel_bss_end = .;
} = 0
kernel_end = .;
}
But if I print the address of these symbols out, the *_start symbol becomes same as *_end symbol.
I'm printing its value with following code:
extern char kernel_text_start;
extern char kernel_text_end;
extern char kernel_data_start;
extern char kernel_data_end;
extern char kernel_bss_start;
extern char kernel_bss_end;
...
raw_write(u64_to_str((uint64_t) &kernel_text_start, buf, 16), 0x0f, 0);
raw_write(u64_to_str((uint64_t) &kernel_text_end, buf, 16), 0x0f, 40);
raw_write(u64_to_str((uint64_t) &kernel_data_start, buf, 16), 0x0f, 80);
raw_write(u64_to_str((uint64_t) &kernel_data_end, buf, 16), 0x0f, 120);
raw_write(u64_to_str((uint64_t) &kernel_bss_start, buf, 16), 0x0f, 160);
raw_write(u64_to_str((uint64_t) &kernel_bss_end, buf, 16), 0x0f, 200);
and result is
The map file is:
Allocating common symbols
Common symbol size file
buddy_num 0x40 build/memory/page_alloc.c.o
buddy_map 0x40 build/memory/page_alloc.c.o
Discarded input sections
.comment 0x0000000000000000 0x4e build/kernel/main.c.o
.note.GNU-stack
0x0000000000000000 0x0 build/kernel/main.c.o
.eh_frame 0x0000000000000000 0x70 build/kernel/main.c.o
.comment 0x0000000000000000 0x4e build/memory/page_alloc.c.o
.note.GNU-stack
0x0000000000000000 0x0 build/memory/page_alloc.c.o
.eh_frame 0x0000000000000000 0xa8 build/memory/page_alloc.c.o
.comment 0x0000000000000000 0x4e build/memory/virt_alloc.c.o
.note.GNU-stack
0x0000000000000000 0x0 build/memory/virt_alloc.c.o
.comment 0x0000000000000000 0x4e build/library/bitmap.c.o
.note.GNU-stack
0x0000000000000000 0x0 build/library/bitmap.c.o
.eh_frame 0x0000000000000000 0x50 build/library/bitmap.c.o
.comment 0x0000000000000000 0x4e build/library/string.c.o
.note.GNU-stack
0x0000000000000000 0x0 build/library/string.c.o
.eh_frame 0x0000000000000000 0x150 build/library/string.c.o
Memory Configuration
Name Origin Length Attributes
*default* 0x0000000000000000 0xffffffffffffffff
Linker script and memory map
/DISCARD/
*(.comment)
*(.note.GNU-stack)
*(.eh_frame)
*(.comment)
*(.note.GNU-stack)
*(.eh_frame)
0x0000000000100000 . = 0x100000
0x0000000000100000 kernel_load_addr = .
0x0000000000100000 text_start_addr = .
.text 0x0000000000100000 0x262f
0x0000000000100000 kernel_text_start = .
*(.boot)
.boot 0x0000000000100000 0x29 build/boot/boot.asm.o
*(.text*)
*fill* 0x0000000000100029 0x7 90
.text 0x0000000000100030 0x0 build/boot/boot.asm.o
.text 0x0000000000100030 0x14f build/boot/init.asm.o
0x0000000000100030 wheel_init
*fill* 0x000000000010017f 0x1 90
.text 0x0000000000100180 0x73c build/kernel/main.c.o
0x0000000000100180 raw_write
0x0000000000100210 read_info
0x00000000001005e0 wheel_main
*fill* 0x00000000001008bc 0x4 90
.text 0x00000000001008c0 0x974 build/memory/page_alloc.c.o
0x00000000001008c0 page_alloc_init
0x0000000000100cb0 find_free_pages
0x0000000000100ef0 alloc_pages
0x00000000001010c0 free_pages
.text 0x0000000000101234 0x0 build/memory/virt_alloc.c.o
*fill* 0x0000000000101234 0xc 90
.text 0x0000000000101240 0x2ff build/library/bitmap.c.o
0x0000000000101240 bitmap_set
0x00000000001013c0 bitmap_clear
*fill* 0x000000000010153f 0x1 90
.text 0x0000000000101540 0x10ef build/library/string.c.o
0x0000000000101540 strlen
0x0000000000101650 strcpy
0x00000000001016c0 strncpy
0x0000000000101770 memcpy
0x0000000000101960 memset
0x0000000000101b60 u32_to_str
0x0000000000101c90 u64_to_str
0x0000000000101dd0 i32_to_str
0x0000000000101e60 i64_to_str
0x0000000000101ef0 vsprintf
0x00000000001025d0 sprintf
0x000000000010262f kernel_text_end = .
0x000000000010262f kernel_text_start = .
*(.boot)
*(.text*)
0x000000000010262f kernel_text_end = .
.data 0x0000000000102630 0x174
0x0000000000102630 kernel_data_start = .
*(.rodata*)
.rodata 0x0000000000102630 0x8 build/kernel/main.c.o
.rodata.str1.1
0x0000000000102638 0x82 build/kernel/main.c.o
*fill* 0x00000000001026ba 0x6 00000000
.rodata 0x00000000001026c0 0xa5 build/library/string.c.o
*(.data*)
*fill* 0x0000000000102765 0x3 00000000
.data 0x0000000000102768 0x3a build/boot/init.asm.o
*fill* 0x00000000001027a2 0x2 00000000
.data 0x00000000001027a4 0x0 build/kernel/main.c.o
.data 0x00000000001027a4 0x0 build/memory/page_alloc.c.o
.data 0x00000000001027a4 0x0 build/memory/virt_alloc.c.o
.data 0x00000000001027a4 0x0 build/library/bitmap.c.o
.data 0x00000000001027a4 0x0 build/library/string.c.o
0x00000000001027a4 kernel_data_end = .
0x00000000001027a4 kernel_data_start = .
*(.rodata*)
*(.data*)
0x00000000001027a4 kernel_data_end = .
0x00000000001027a4 data_end_addr = .
.bss 0x0000000000103000 0x6000
0x0000000000103000 kernel_bss_start = .
*(COMMON)
COMMON 0x0000000000103000 0x80 build/memory/page_alloc.c.o
0x0000000000103000 buddy_num
0x0000000000103040 buddy_map
*(.bss)
*fill* 0x0000000000103080 0xf80 00000000
.bss 0x0000000000104000 0x5000 build/boot/init.asm.o
0x0000000000104000 kernel_stack
0x0000000000105000 pml4t
.bss 0x0000000000109000 0x0 build/kernel/main.c.o
.bss 0x0000000000109000 0x0 build/memory/page_alloc.c.o
.bss 0x0000000000109000 0x0 build/memory/virt_alloc.c.o
.bss 0x0000000000109000 0x0 build/library/bitmap.c.o
.bss 0x0000000000109000 0x0 build/library/string.c.o
0x0000000000109000 kernel_bss_end = .
0x0000000000109000 kernel_bss_start = .
*(COMMON)
*(.bss)
0x0000000000109000 kernel_bss_end = .
0x0000000000109000 bss_end_addr = .
0x0000000000109000 kernel_end = .
LOAD build/boot/boot.asm.o
LOAD build/boot/init.asm.o
LOAD build/kernel/main.c.o
LOAD build/memory/page_alloc.c.o
LOAD build/memory/virt_alloc.c.o
LOAD build/library/bitmap.c.o
LOAD build/library/string.c.o
LOAD link.lds
0x0000000000100000 . = 0x100000
0x0000000000100000 kernel_load_addr = .
0x0000000000100000 text_start_addr = .
0x0000000000100000 data_end_addr = .
0x0000000000100000 bss_end_addr = .
0x0000000000100000 kernel_end = .
OUTPUT(build/kernel.bin binary)
You can see the value of these symbols got reassigned.
So how can I avoid this and get correct address in my program?

Resources