Linker Scripts

From OSDev.wiki
Revision as of 17:19, 29 November 2014 by Arto (talk | contribs) (→‎External Links: Updated the manual link to refer to the latest GNU ld release.)
Jump to navigation Jump to search
This page is a work in progress.
This page may thus be incomplete. Its content may be changed in the near future.

Introduction

So what exactly is a linker script, and do I really need one? In all basic cases, you can technically do without, as you can specify a lot of options on the GNU ld command line, but how fun is that to type 100 characters over and over? A linker script is basically a nice little file you can create that ld will parse and link according to it.

Keywords

I won't cover all of the keywords here, but I will cover the ones that will most likely be used.

ENTRY

ENTRY(main)
ENTRY(MultibootEntry)

ENTRY takes one argument. That is the symbol name for the entry point of the linked program/kernel. This can be "start" or "__main" or whatever, it's really up to you, but this will be the very first byte of your loaded program(or the first byte of the .text section in ELF and PE binaries).

OUTPUT_FORMAT

OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_FORMAT("pe-i386")

OUTPUT_FORMAT also takes one argument. It specifies what the output format(duh) of your executable will be. To find out what formats your binutils and GCC supports, just use 'objdump -i'. Some of the more common formats are

  • binary --This is just a flat binary with no formatting at all
  • elf32-i386 --This is just the ELF format, usually little endian too.
  • elf64-x86-64 --This is the ELF format for 64bit, usually little endian.
  • pe-i386 --The PE format

STARTUP

STARTUP(Boot.o)
STARTUP(crt0.o)

STARTUP takes on argument. It is which file you want to be linked to the very beginning of the executable. For userland programs, this is usually crt0.o or crtbegin.o. For kernels, it is usually the file that contains your assembly boilerplate that initiates the stack and in some cases GDT and such and then calls your kmain().

SEARCH_DIR

SEARCH_DIR(Directory)

This will add a path to your library search directory. The -nostdlib flag will cause any library found in this path to be effectively ignored. I'm not sure why, it just seems to be how ld works. It treats linker script specified search directories as standard directories, and therefore ignores them with -no-default-libs and such flags

INPUT

INPUT(File1.o File2.o File3.o ...)
INPUT
(
	File1.o
	File2.o
	File3.o
	...
)

INPUT is a 'in-linker script' replacement for adding object files to the command line. Where you would usually specify something like ld File1.o File2.o, the INPUT section can be used to do this inside the linker script instead.

OUTPUT

OUTPUT(Kernel.bin)

OUTPUT specifies the file that has to be output by the linker. This is the name of the executable. For applications on Windows, for example, this is usually .exe.

MEMORY

MEMORY
{
...
}

MEMORY declares one or more memory regions with attributes specifying whether the region can be written to, read from or executed. This is mostly used in embedded systems where different regions of address space may contain different access permissions.

For example:

MEMORY
{
    ROM (rx) : ORIGIN = 0, LENGTH = 256k
    RAM (wx) : org = 0x00100000, len = 1M
}

This script tells the linker that there are two memory regions. a) "ROM" starts at address 0x00000000, is 256kB in length, can be read and executed. b) "RAM" starts at address 0x00100000, is 1MB in length, can be written, read and executed.

SECTIONS

SECTIONS
{
  .text.start (_KERNEL_BASE_) : {
    startup.o( .text )
  }

  .text : ALIGN(0x1000) {
_TEXT_START_ = .;
    *(.text)
_TEXT_END_ = .;
  }

  .data : ALIGN(0x1000) {
_DATA_START_ = .;
    *(.data)
_DATA_END_ = .;
  }

  .bss : ALIGN(0x1000) {
_BSS_START_ = .;
    *(.bss)
_BSS_END_ = .;
  }


}

This script tells the linker to place code from the ".text" section in startup.o at the beginning, starting at logical address _KERNEL_BASE_. This is then followed by page-aligned sections for all ".text", ".data" and ".bss" sections of all the other input files. Linker variables are defined for the start and end address of each section; C(++) code can refer to these using 'extern "C" void <varname>', and taking the address (&<varname>) to use the value.

See Also

External Links