title: How can I use LD to place ARM reset vectors in a program segment
body: <p>I have an <a href="http://www.atmel.com/devices/SAMA5D35.aspx" rel="nofollow">ARM A5 Microprocessor</a> with 2 major segments of memory.  When it boots up, a <a href="http://www.atmel.com/Images/Atmel-11121-32-bit-Cortex-A5-Microcontroller_SAMA5D3_Datasheet.pdf#page=64" rel="nofollow">hardware bootloader (see page 64)</a> loads a 64k software bootloader that I wrote into sram.  The software bootloader then reads an .elf file from a flash memory chip and loads it into ddram.</p>
  
  <pre><code>these are my mcu's most important memories:
  sram  from 0x0000_0000 - 0x0002_0000
  ddram from 0x2000_0000 - 0x2100_0000
  note: the datasheet I linked to says that on-mcu ROM containing a hardware bootloader is
        mapped to 0x0000.  This is true on startup, but I remap the memory as soon as my
        bootloader starts up. 
  note: This 2 stage bootloading process is necessary because the Atmel hardware bootloader
        can only load programs up to 64k, and it can only load programs to sram.  My 
        firmware is over 64k and needs to be loaded to ddram, so the Atmel hardware
        bootloader loads my own bootloader to sram, and my own bootloader loads my firmware 
        application code to ddram.
  </code></pre>
  
  <p>I want to compile and link my application code into an .elf file so that 2 program segments are created.  One program segment should contain the vector table, placed at 0x0000_0000, and another should contain the .text, .data, and .bss sections and be placed at address 0x2000_0000.</p>
  
  <p>It is important to emphasize the difference between program segments and sections.  Read up <a href="http://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_layout" rel="nofollow">here</a> and <a href="http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf" rel="nofollow">here, page 1-1 (note the difference between "linking view" and "execution view"</a>.</p>
  
  <p>With the linker script that I have right now, .vectors is mapped to an <strong>output section</strong>, but it does NOT appear in a <strong>program segment</strong>.</p>
  
  <p>I thought that adding a PHDRS section like this:</p>
  
  <pre><code>PHDRS
  {
      vectors PT_LOAD; /* at 0x0000_0000 for the vectors*/
      exec PT_LOAD;    /* at 0x2000_0000 for the executable app code*/
  }
  </code></pre>
  
  <p>to my linker script would fix this problem, but it only fixed it halfway: now I have a program segment at 0x0000_0000 like I want, but its length is 0.</p>
  
  <p>How do I get my *(.vectors) section into a program segment at 0x0000_0000?</p>
  
  <p>Thanks.</p>
  
  <p>note: I will edit this question for more clarity when I get into my office and have my linker scripts in front of me.</p>
  
  <p>crt0.S</p>
  
  <pre><code>    .syntax unified
  
      .section .vectors
      .global reset_vector
      .arm
  
  reset_vector:
      ldr pc, =reset_handler
  undef_vector:
      ldr     pc, =undef_vector
  svc_vector:
      ldr     pc, =svc_handler
  prefetch_abort_vector:
      ldr     pc, =prefetch_handler
  data_abort_vector:
      ldr     pc, =data_abort_handler
  reserved_vector:
      ldr     pc, =reserved_vector
  irq_vector:
      ldr     pc, =irq_handler
  
      .section .text
  
  prefetch_handler:
      ldr     sp, =__irq_stack_end__
      mov     r0, lr
      ldr     r1, =prefetch_handler_string
      ldr     r2, =printloop_fatal
      blx     r2
  
  data_abort_handler:
      ldr     sp, =__irq_stack_end__
      mov     r0, lr
      ldr     r1, =data_abort_string
      ldr     r2, =printloop_fatal
      blx     r2
  
  prefetch_handler_string:
      .ascii "prefetch abort\0"
  data_abort_string:
      .ascii "data abort\0"
  
      .align 4  // instructions must be aligned
  
  // Note that we boot in SVC mode (cpsr &amp; 0x1f == 0x12). We will
  // switch to USER mode
  reset_handler:
  
      cpsie   A   // enable abort exceptions
  
      // clear BSS
      ldr r0, =__bss_start__
      ldr r1, =__bss_end__
      mov r2, #0
  1:
      cmp r0, r1
      itt cc
      strcc r2, [r0], #4
      bcc 1b
  
      // sign stack
      ldr r0, =__irq_stack_start__
      ldr r1, =__irq_stack_end__
      ldr r2, =0x5718a9bf    //magic number
  1:
      cmp r0, r1
      it cc
      strcc r2, [r0], #4
      bcc 1b
  
  //................................
  //... lots more init code here ...
  //................................
  
  ldr sp, __sram_end__
  blx main
  
  msr CPSR, #0x1f  // ARM_MODE_USER
  
  svc #0           // invoke scheduler.
  b   .
  
  //...................................................
  //... other handlers are here.  not worth showing ... 
  //...................................................
  </code></pre>
  
  <p>I am using the following linker script:</p>
  
  <p>ddram.ld</p>
  
  <pre><code>OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  OUTPUT_ARCH(arm)
  ENTRY(reset_vector)
  SEARCH_DIR(.)
  
  /* Memory Spaces Definitions */
  MEMORY
  {
      /**
       * The sram is actually 0x20000 long, but we use the top 0x4000 bytes for 
       * the page translation table.
       */
      sram (W!RX) : ORIGIN = 0x000000, LENGTH = 0x1c000
      ddr_ebi1 (W!RX) : ORIGIN = 0x20000000, LENGTH = 8M
      dma_ddr (!RWX) : ORIGIN = 0x21000000, LENGTH = 8M
  }
  
  PHDRS
  {
      vectors PT_LOAD;
      exec PT_LOAD;
  }
  
  /* Section Definitions */
  SECTIONS
  {
      /* vectors go at start of sram.*/
      .vect :
      {
          KEEP(*(.vectors));
          _vector_end = .;
      } &gt; sram AT&gt; sram :vectors
  
      /***/
      .text :
      {
          *(.text*);
          *(.CP15*);
  
          . = ALIGN(4);
          *(.data*);
          *(.rodata*);
          _text_end = .;
      } &gt;ddr_ebi1 AT&gt; ddr_ebi1 :exec
  
      .bss : 
      {
          . = ALIGN(4);
  
          *(.bss*)
          *(COMMON*)
  
          . = ALIGN(4);
          __irq_stack_start__ = .;
          . = . + 4096;
          __irq_stack_end__ = .;
      } &gt; ddr_ebi1 AT&gt; ddr_ebi1
  
      __page_translation_table__ = 0x1c000;
  
      __sram_start__ = ORIGIN(sram);
      __sram_end__ = ORIGIN(sram) + LENGTH(sram);
  
      __bss_start__ = ADDR(.bss);
      __bss_size__ = SIZEOF(.bss);
      __bss_end__ = ADDR(.bss) + SIZEOF(.bss);
  
      __heap_start__ = __bss_end__;
      __heap_end__ = __sram_end__;
  }
  </code></pre>
  
  <p>running arm-none-eabi-objdump -p ./main.out gives</p>
  
  <pre><code>0x70000001 off    0x0001481c vaddr 0x2000c81c paddr 0x2000c81c align 2**2
           filesz 0x00000008 memsz 0x00000008 flags r--
      LOAD off    0x00000094 vaddr 0x00000000 paddr 0x00000000 align 2**15
           filesz 0x00000000 memsz 0x00000000 flags ---
      LOAD off    0x00008000 vaddr 0x20000000 paddr 0x20000000 align 2**15
           filesz 0x0000c824 memsz 0x0000de40 flags rwx
  private flags = 5000000: [Version5 EABI]
  </code></pre>
  
  <p>When I search my .map file for "vect", I get the following</p>
  
  <pre><code>.vect           0x00000000       0x38
   *(.vectors)
   .vectors       0x00000000       0x38 build/crt0.o
                  0x00000000                reset_vector
                  0x00000038                _vector_end = .
  
  .text           0x20000000     0xc81c
   *(.text*)
   .text          0x20000000      0xcb0 build/rtos.o
                  0x20000024                rtos_init
                  0x20000028                rtos_wait
  </code></pre>