nuclear@0: /* Linker Script v1.3 by Jeff Frohwein */ nuclear@0: /* v1.0 - Original release */ nuclear@0: /* v1.1 - Added proper .data section support */ nuclear@0: /* v1.2 - Added support for c++ & iwram overlays */ nuclear@0: /* - Major contributions by Jason Wilkins. */ nuclear@0: /* v1.3 - .ewram section now can be used when */ nuclear@0: /* compiling for MULTIBOOT mode. This fixes */ nuclear@0: /* malloc() in DevKitAdvance which depends */ nuclear@0: /* on __eheap_start instead of end to define*/ nuclear@0: /* the starting location of heap space. */ nuclear@0: /* External global variable __gba_iwram_heap*/ nuclear@0: /* support added to allow labels end, _end, */ nuclear@0: /* & __end__ to point to end of iwram or */ nuclear@0: /* the end of ewram. */ nuclear@0: nuclear@0: /* This file is released into the public domain */ nuclear@0: /* for commercial or non-commercial use with no */ nuclear@0: /* restrictions placed upon it. */ nuclear@0: nuclear@0: /* NOTE!!!: This linker script defines the RAM & */ nuclear@0: /* ROM start addresses. In order for it to work */ nuclear@0: /* properly, remove -Ttext and -Tbss linker */ nuclear@0: /* options from your makefile if they are */ nuclear@0: /* present. */ nuclear@0: nuclear@0: /* You can use the following to view section */ nuclear@0: /* addresses in your .elf file: */ nuclear@0: /* objdump -h file.elf */ nuclear@0: /* Please note that empty sections may incorrectly*/ nuclear@0: /* list the lma address as the vma address for */ nuclear@0: /* some versions of objdump. */ nuclear@0: nuclear@0: OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") nuclear@0: OUTPUT_ARCH(arm) nuclear@0: ENTRY(_start) nuclear@0: /* SEARCH_DIR(/bin/arm); */ nuclear@0: nuclear@0: /* By default this linker script will generate code */ nuclear@0: /* for flash carts located at 0x8000000. In order to */ nuclear@0: /* generate code that is compiled at 0x2000000 that */ nuclear@0: /* will run on flash carts or in multiboot mode then */ nuclear@0: /* you need to add the following variable to your main */ nuclear@0: /* project file. It's value is NOT important but */ nuclear@0: /* IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK: */ nuclear@0: nuclear@0: /* #define MULTIBOOT int __gba_multiboot; */ nuclear@0: /* Then use it like this: MULTIBOOT */ nuclear@0: nuclear@0: /* By default this linker script will set the labels */ nuclear@0: /* end, _end, & __end__ at the end of ewram. To force */ nuclear@0: /* them to be set to the end of iwram then you need to */ nuclear@0: /* add the following variable to your main */ nuclear@0: /* project file. It's value is NOT important but */ nuclear@0: /* IT MUST BE A GLOBAL VARIABLE OR IT WILL NOT WORK: */ nuclear@0: nuclear@0: /* #define IWRAMHEAP int __gba_iwram_heap; */ nuclear@0: /* Then use it like this: IWRAMHEAP */ nuclear@0: nuclear@0: /* The linker script function "var1 += var2;" sometimes */ nuclear@0: /* reports incorrect values in the *.map file but the */ nuclear@0: /* actual value it calculates is usually, if not always, */ nuclear@0: /* correct. If you leave out the ". = ALIGN(4);" at the */ nuclear@0: /* end of each section then the return value of SIZEOF() */ nuclear@0: /* is sometimes incorrect and "var1 += var2;" appears to */ nuclear@0: /* not work as well. "var1 += var2" style functions are */ nuclear@0: /* avoided below as a result. */ nuclear@0: nuclear@0: /* The linker script MEMORY directive is not used here due */ nuclear@0: /* to the fact that __text_start is not always a fixed value. */ nuclear@0: nuclear@0: __text_start = DEFINED (__gba_multiboot) ? 0x2000000 : 0x8000000; nuclear@0: /* __ewram_start = 0x2000000; */ /* Removed in v1.3 */ nuclear@0: __eheap_end = 0x2040000; nuclear@0: __iwram_start = 0x3000000; nuclear@0: __iheap_end = 0x3008000 - 0x400; nuclear@0: __sp_usr = 0x3008000 - 0x100; nuclear@0: __sp_irq = 0x3008000 - 0x60; nuclear@0: __intr_vector_buf = 0x3008000 - 4; nuclear@0: __sp_usr_offset = __sp_usr - __iwram_start; nuclear@0: __intr_vect_offset = __intr_vector_buf - __sp_usr; nuclear@0: nuclear@0: SECTIONS nuclear@0: { nuclear@0: .text __text_start : /* ALIGN (4): */ nuclear@0: { nuclear@0: *(EXCLUDE_FILE (*text.iwram*) .text) nuclear@0: *(.text.*) nuclear@0: *(.stub) nuclear@0: /* .gnu.warning sections are handled specially by elf32.em. */ nuclear@0: *(.gnu.warning) nuclear@0: *(.gnu.linkonce.t*) nuclear@0: *(.glue_7) nuclear@0: *(.glue_7t) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0xff nuclear@0: /* laddr = ADDR(.text) + SIZEOF(.text); */ nuclear@0: __text_end = .; nuclear@0: nuclear@0: .rodata : nuclear@0: { nuclear@0: *(.rodata) nuclear@0: *all.rodata*(*) nuclear@0: *(.roda) nuclear@0: *(.rodata.*) nuclear@0: *(.gnu.linkonce.r*) nuclear@0: SORT(CONSTRUCTORS) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0xff nuclear@0: /* laddr += SIZEOF(.rodata); */ nuclear@0: nuclear@0: .ctors : nuclear@0: { nuclear@0: /* gcc uses crtbegin.o to find the start of the constructors, so nuclear@0: we make sure it is first. Because this is a wildcard, it nuclear@0: doesn't matter if the user does not actually link against nuclear@0: crtbegin.o; the linker won't look for a file to match a nuclear@0: wildcard. The wildcard also means that it doesn't matter which nuclear@0: directory crtbegin.o is in. */ nuclear@0: KEEP (*crtbegin.o(.ctors)) nuclear@0: KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) nuclear@0: KEEP (*(SORT(.ctors.*))) nuclear@0: KEEP (*(.ctors)) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0 nuclear@0: /* laddr += SIZEOF(.ctors); */ nuclear@0: laddr = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors); nuclear@0: nuclear@0: .dtors : nuclear@0: { nuclear@0: KEEP (*crtbegin.o(.dtors)) nuclear@0: KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) nuclear@0: KEEP (*(SORT(.dtors.*))) nuclear@0: KEEP (*(.dtors)) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0 nuclear@0: /* laddr += SIZEOF(.dtors); */ nuclear@0: laddr = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors); nuclear@0: nuclear@0: .eh_frame : nuclear@0: { nuclear@0: KEEP (*(.eh_frame)) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0 nuclear@0: /* laddr += SIZEOF(.eh_frame); */ nuclear@0: nuclear@0: .gcc_except_table : nuclear@0: { nuclear@0: *(.gcc_except_table) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0 nuclear@0: /* laddr += (SIZEOF(.gcc_except_table) + 3) & ~ 3; */ nuclear@0: /* __iwram_lma = laddr; */ nuclear@0: __iwram_lma = (ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + 3) & ~ 3; nuclear@0: nuclear@0: .iwram __iwram_start : AT (__iwram_lma) nuclear@0: { nuclear@0: __iwram_start = ABSOLUTE(.) ; nuclear@0: *(.iwram) nuclear@0: *iwram.*(.text) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0xff nuclear@0: /* laddr += SIZEOF(.iwram); */ nuclear@0: /* __data_lma = laddr; */ nuclear@0: __data_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram); nuclear@0: nuclear@0: __iwram_end = . ; nuclear@0: nuclear@0: .bss ALIGN(4) : nuclear@0: { nuclear@0: __bss_start = ABSOLUTE(.); nuclear@0: __bss_start__ = ABSOLUTE(.); nuclear@0: *(.dynbss) nuclear@0: *(.gnu.linkonce.b*) nuclear@0: *(COMMON) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } nuclear@0: nuclear@0: __bss_end = . ; nuclear@0: __bss_end__ = . ; nuclear@0: nuclear@0: .data ALIGN(4) : AT (__data_lma) nuclear@0: { nuclear@0: __data_start = ABSOLUTE(.); nuclear@0: *(.data) nuclear@0: *(.data.*) nuclear@0: *(.gnu.linkonce.d*) nuclear@0: CONSTRUCTORS nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0xff nuclear@0: /* laddr += SIZEOF(.data); */ nuclear@0: /* __iwram_overlay_lma = laddr; */ nuclear@0: __iwram_overlay_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data); nuclear@0: nuclear@0: __data_end = .; nuclear@0: PROVIDE (edata = .); nuclear@0: /* __data_lma = LOADADDR(.data); */ nuclear@0: __iwram_overlay_start = . ; nuclear@0: nuclear@0: OVERLAY : NOCROSSREFS AT (__iwram_overlay_lma) nuclear@0: { nuclear@0: .iwram0 { *(.iwram0) . = ALIGN(4);} nuclear@0: .iwram1 { *(.iwram1) . = ALIGN(4);} nuclear@0: .iwram2 { *(.iwram2) . = ALIGN(4);} nuclear@0: .iwram3 { *(.iwram3) . = ALIGN(4);} nuclear@0: .iwram4 { *(.iwram4) . = ALIGN(4);} nuclear@0: .iwram5 { *(.iwram5) . = ALIGN(4);} nuclear@0: .iwram6 { *(.iwram6) . = ALIGN(4);} nuclear@0: .iwram7 { *(.iwram7) . = ALIGN(4);} nuclear@0: .iwram8 { *(.iwram8) . = ALIGN(4);} nuclear@0: .iwram9 { *(.iwram9) . = ALIGN(4);} nuclear@0: } = 0xff nuclear@0: /* laddr += (SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9)); */ nuclear@0: /* __ewram_lma = laddr; */ nuclear@0: __ewram_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9); nuclear@0: nuclear@0: /* __iwram_overlay_lma = LOADADDR (.iwram0); */ nuclear@0: __iwram_overlay_end = . ; nuclear@0: /* _end = . ; */ nuclear@0: /* __end__ = . ; */ nuclear@0: /* PROVIDE (end = .); */ nuclear@0: __iheap_start = . ; nuclear@0: nuclear@0: /* v1.3 */ nuclear@0: __ewram_start = DEFINED (__gba_multiboot) ? __ewram_lma : 0x2000000; nuclear@0: nuclear@0: .ewram __ewram_start : AT (__ewram_lma) nuclear@0: { nuclear@0: /* __ewram_start = ABSOLUTE(.); */ nuclear@0: *(.ewram) nuclear@0: . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ nuclear@0: } = 0xff nuclear@0: /* laddr += SIZEOF(.ewram); */ nuclear@0: /* __ewram_overlay_lma = laddr; */ nuclear@0: __ewram_overlay_lma = ADDR(.text) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ctors) + SIZEOF(.dtors) + SIZEOF(.eh_frame) + SIZEOF(.gcc_except_table) + SIZEOF(.iwram) + SIZEOF(.data) + SIZEOF(.iwram0)+SIZEOF(.iwram1)+SIZEOF(.iwram2)+SIZEOF(.iwram3)+SIZEOF(.iwram4)+SIZEOF(.iwram5)+SIZEOF(.iwram6)+SIZEOF(.iwram7)+SIZEOF(.iwram8)+SIZEOF(.iwram9) + SIZEOF(.ewram); nuclear@0: nuclear@0: /* __ewram_lma = LOADADDR(.ewram); */ nuclear@0: __ewram_end = . ; nuclear@0: __ewram_overlay_start = . ; nuclear@0: nuclear@0: OVERLAY ALIGN(4): NOCROSSREFS AT (__ewram_overlay_lma) nuclear@0: { nuclear@0: .ewram0 { *(.ewram0) . = ALIGN(4);} nuclear@0: .ewram1 { *(.ewram1) . = ALIGN(4);} nuclear@0: .ewram2 { *(.ewram2) . = ALIGN(4);} nuclear@0: .ewram3 { *(.ewram3) . = ALIGN(4);} nuclear@0: .ewram4 { *(.ewram4) . = ALIGN(4);} nuclear@0: .ewram5 { *(.ewram5) . = ALIGN(4);} nuclear@0: .ewram6 { *(.ewram6) . = ALIGN(4);} nuclear@0: .ewram7 { *(.ewram7) . = ALIGN(4);} nuclear@0: .ewram8 { *(.ewram8) . = ALIGN(4);} nuclear@0: .ewram9 { *(.ewram9) . = ALIGN(4);} nuclear@0: } = 0xff nuclear@0: nuclear@0: __ewram_overlay_end = . ; nuclear@0: nuclear@0: __eheap_start = . ; nuclear@0: nuclear@0: _end = DEFINED (__gba_iwram_heap) ? __iheap_start : .; /* v1.3 */ nuclear@0: __end__ = _end ; /* v1.3 */ nuclear@0: PROVIDE (end = _end); /* v1.3 */ nuclear@0: nuclear@0: /* Stabs debugging sections. */ nuclear@0: .stab 0 : { *(.stab) } nuclear@0: .stabstr 0 : { *(.stabstr) } nuclear@0: .stab.excl 0 : { *(.stab.excl) } nuclear@0: .stab.exclstr 0 : { *(.stab.exclstr) } nuclear@0: .stab.index 0 : { *(.stab.index) } nuclear@0: .stab.indexstr 0 : { *(.stab.indexstr) } nuclear@0: .comment 0 : { *(.comment) } nuclear@0: /* DWARF debug sections. nuclear@0: Symbols in the DWARF debugging sections are relative to the beginning nuclear@0: of the section so we begin them at 0. */ nuclear@0: /* DWARF 1 */ nuclear@0: .debug 0 : { *(.debug) } nuclear@0: .line 0 : { *(.line) } nuclear@0: /* GNU DWARF 1 extensions */ nuclear@0: .debug_srcinfo 0 : { *(.debug_srcinfo) } nuclear@0: .debug_sfnames 0 : { *(.debug_sfnames) } nuclear@0: /* DWARF 1.1 and DWARF 2 */ nuclear@0: .debug_aranges 0 : { *(.debug_aranges) } nuclear@0: .debug_pubnames 0 : { *(.debug_pubnames) } nuclear@0: /* DWARF 2 */ nuclear@0: .debug_info 0 : { *(.debug_info) } nuclear@0: .debug_abbrev 0 : { *(.debug_abbrev) } nuclear@0: .debug_line 0 : { *(.debug_line) } nuclear@0: .debug_frame 0 : { *(.debug_frame) } nuclear@0: .debug_str 0 : { *(.debug_str) } nuclear@0: .debug_loc 0 : { *(.debug_loc) } nuclear@0: .debug_macinfo 0 : { *(.debug_macinfo) } nuclear@0: /* SGI/MIPS DWARF 2 extensions */ nuclear@0: .debug_weaknames 0 : { *(.debug_weaknames) } nuclear@0: .debug_funcnames 0 : { *(.debug_funcnames) } nuclear@0: .debug_typenames 0 : { *(.debug_typenames) } nuclear@0: .debug_varnames 0 : { *(.debug_varnames) } nuclear@0: .stack 0x80000 : { _stack = .; *(.stack) } nuclear@0: /* These must appear regardless of . */ nuclear@0: }