Usage of linker LD to produce kernel binary image

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Usage of linker LD to produce kernel binary image

Post by suslik »

I make my kernel as follows:

Code: Select all

kernel: $(KERNEL_OBJECT_FILES)
# kernel_for_debug is EXE or ELF executable depending on OS I use
    ld -T ld.script -Map kernel_for_debug.map $(KERNEL_OBJECT_FILES) -o kernel_for_debug
    nm -n kernel_for_debug > kernel.sym
    objcopy -O binary -j ".text" -j ".data" -j ".rodata" kernel_for_debug kernel.bin
ld.script:

Code: Select all

OUTPUT_ARCH("i386")
ENTRY(kstart)

/* I load kernel at this address */
KERNEL_START_ADDR = 0x100000;
KERNEL_STACK_SIZE_IN_BYTES = 8192;

SECTIONS
{
	. = KERNEL_START_ADDR;
	
	__kdata_beg = .;
	
	.text . : {
		kstart.o(.text)
		*(.text)
		. = ALIGN(4);
	}
	
	.data . : {
		*(.data)
		. = ALIGN(4);
	}
	
	
	.rodata . : {
		*(.rodata)
		*(.rdata)
		. = ALIGN(4);
	}
	
	__kdata_end = .;
	
	KERNEL_SIZE_ON_DISK_IN_BYTES = __kdata_end - __kdata_beg;
	
	__kbss_beg = .;
	
	.bss . : {
		*(.bss)
		. = ALIGN(4);
	}
	
	__kbss_end = .;
	
	KERNEL_BSS_SIZE_IN_DWORDS = ((__kbss_end - __kbss_beg) + 3) / 4;
}
But when I'm using MinGW I get into trouble: in kernel_for_debug.map I see strange section right after the .rodata section: .eh_frame. So, my KERNEL_BSS_SIZE_IN_DWORDS becomes much bigger than I expect.

This is kernel_for_debug.map:

Code: Select all


Memory Configuration

Name             Origin             Length             Attributes
*default*        0x00000000         0xffffffff

Linker script and memory map

                0x00400000                __image_base__ = 0x400000
                0x00000000                __dll__ = 0x0
                0x00400000                ___ImageBase = 0x400000
                0x00001000                __section_alignment__ = 0x1000
                0x00000200                __file_alignment__ = 0x200
                0x00000004                __major_os_version__ = 0x4
                0x00000000                __minor_os_version__ = 0x0
                0x00000001                __major_image_version__ = 0x1
                0x00000000                __minor_image_version__ = 0x0
                0x00000004                __major_subsystem_version__ = 0x4
                0x00000000                __minor_subsystem_version__ = 0x0
                0x00000003                __subsystem__ = 0x3
                0x00200000                __size_of_stack_reserve__ = 0x200000
                0x00001000                __size_of_stack_commit__ = 0x1000
                0x00100000                __size_of_heap_reserve__ = 0x100000
                0x00001000                __size_of_heap_commit__ = 0x1000
                0x00000000                __loader_flags__ = 0x0
                0x00000000                __dll_characteristics__ = 0x0
                0x00100000                KERNEL_START_ADDR = 0x100000
                0x00002000                KERNEL_STACK_SIZE_IN_BYTES = 0x2000
                0x00100000                . = KERNEL_START_ADDR
                0x00100000                __kdata_beg = .

.text           0x00100000      0xa00
 kstart.o(.text)
 .text          0x00100000       0x38 kstart.o
                0x00100014                kstart
 *(.text)
 .text          0x00100038       0x68 kernel.o
                0x00100038                kmain
 .text          0x001000a0      0x1b4 tty.o
                0x001000a0                set_cursor
                0x001000b5                scroll
                0x0010010f                clear
                0x00100152                putc
                0x0010022d                puts
 .text          0x00100254      0x724 lib.o
                0x00100254                memset
                0x00100281                memset16
                0x001002b1                memcpy
                0x00100326                reverse
                0x00100370                itoa
                0x001003e2                atoi
                0x0010045f                ultoh
                0x001004e1                strlen
                0x00100509                strcmp
                0x00100543                memcmp
                0x0010058a                strncpy
                0x001005cb                strcpy
                0x001005fe                vprintf
                0x00100957                printf
                0x00100978                . = ALIGN (0x4)

.data           0x00100978      0x200
 *(.data)
 .data          0x00100978       0x26 kstart.o
 *fill*         0x0010099e        0x2 00
 .data          0x001009a0        0x0 kernel.o
 .data          0x001009a0        0x8 tty.o
 .data          0x001009a8       0x10 lib.o
                0x001009b8                . = ALIGN (0x4)

.rodata         0x001009b8      0x200
 *(.rodata)
 *(.rdata)
 .rdata         0x001009b8       0xe4 kernel.o
 .rdata         0x00100a9c       0xa8 lib.o
                0x00100b44                . = ALIGN (0x4)
                0x00100b44                __kdata_end = .
                0x00000b44                KERNEL_SIZE_ON_DISK_IN_BYTES = (__kdata_end - __kdata_beg)
                0x00100b44                __kbss_beg = .

.eh_frame       0x00101000      0x400
 .eh_frame      0x00101000       0x3c kernel.o
 .eh_frame      0x0010103c       0xb8 tty.o
 .eh_frame      0x001010f4      0x1e0 lib.o

.bss            0x001012d4        0x8
 *(.bss)
 .bss           0x001012d4        0x0 kernel.o
 .bss           0x001012d4        0x8 tty.o
 .bss           0x001012dc        0x0 lib.o
                0x001012dc                . = ALIGN (0x4)
                0x001012dc                __kbss_end = .
                0x000001e6                KERNEL_BSS_SIZE_IN_DWORDS = (((__kbss_end - __kbss_beg) + 0x3) / 0x4)
LOAD kstart.o
LOAD kernel.o
LOAD tty.o
LOAD lib.o
OUTPUT(kernel pei-i386)

.debug_info     0x00000000      0xa00
 .debug_info    0x00000000      0x128 kernel.o
 .debug_info    0x00000128      0x1a9 tty.o
 .debug_info    0x000002d1      0x635 lib.o

.debug_abbrev   0x00000000      0x200
 .debug_abbrev  0x00000000       0x79 kernel.o
 .debug_abbrev  0x00000079       0x7d tty.o
 .debug_abbrev  0x000000f6       0xe5 lib.o

.debug_loc      0x00000000      0x600
 .debug_loc     0x00000000       0x38 kernel.o
 .debug_loc     0x00000038      0x118 tty.o
 .debug_loc     0x00000150      0x310 lib.o

.debug_aranges  0x00000000      0x200
 .debug_aranges
                0x00000000       0x20 kernel.o
 .debug_aranges
                0x00000020       0x20 tty.o
 .debug_aranges
                0x00000040       0x20 lib.o

.debug_line     0x00000000      0x400
 .debug_line    0x00000000       0x53 kernel.o
 .debug_line    0x00000053       0x71 tty.o
 .debug_line    0x000000c4      0x217 lib.o

.debug_str      0x00000000      0x200
 .debug_str     0x00000000        0x7 lib.o
Why the .eh_frame section has been included in the output file by LD?

And I have another question: is "objcopy -O binary -j ".text" -j ".data" -j ".rodata" kernel_for_debug kernel.bin" right method to be sure that objcopy doesn't include .bss section in the result bin file? I know that NOW omitting .bss when producing binary is objcopy's default behaviour, but I want to be sure that the future versions of objcopy will also do the same.
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: Usage of linker LD to produce kernel binary image

Post by Tosi »

1. Google .eh_frame and you get information in the first result explaining what it is.

2. Just use -R .bss to remove the section when calilng objcopy. If you need more information, type objcopy --help or man objcopy.
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Usage of linker LD to produce kernel binary image

Post by suslik »

Google says that .eh_frame is C++ exceptions stuff but my question is why LD copies this section to the output file when in linker script I don't mention .eh_frame.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Usage of linker LD to produce kernel binary image

Post by Owen »

suslik wrote:Google says that .eh_frame is C++ exceptions stuff but my question is why LD copies this section to the output file when in linker script I don't mention .eh_frame.
LD copies all sections not explicitly discarded to the output. You don't specify which architecture you're building for, but for some (e.g. AMD64) inclusion of the exception handling information for all code is a part of the SystemV PSABI. On many platforms it is used to implement e.g. pthread cancellation.
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Usage of linker LD to produce kernel binary image

Post by suslik »

LD copies all sections not explicitly discarded to the output.
I didn't know this. Actually I suspected that LD does this since I read in LD mans about DISCARD section. I've made some experiments and detected that you are absolutely right. But WHY does LD behave this way? I think that linker script must provide the total control on linking process, but how can I know what sections are in the input files to discard unneeded ones? The nice example is .eh_frame section in my case - the size of .bss section is determined incorrectly. I want to make LD behaves like IPTABLES: allow only what is explicity allowed. Is it possible?

May be someone tell me how to fix my linker script to get in the output file only .text, .data. .rodata and .bss sections?
Post Reply