[U-Boot] arm: add ELF relocation support to rest of cpus

Submitted by Albert ARIBAUD on Nov. 25, 2010, 9:45 p.m.

Details

Message ID 1290721502-410-1-git-send-email-albert.aribaud@free.fr
State Accepted
Commit 3336ca60d412b2e1285c0d5e76b7b6f9b4ff19ef
Headers show

Commit Message

Albert ARIBAUD Nov. 25, 2010, 9:45 p.m.
bulk addition of ELF relocation support to ARM cpus
arm946es, arm720t,arm920t, arm925t, arm_intcm, ixp,
lh7a40x, s3c44b0, and sa1100.

Signed-off-by: Albert Aribaud <albert.aribaud@free.fr>
---
 arch/arm/cpu/arm720t/start.S      |  119 +++++++++++++++++----------------
 arch/arm/cpu/arm720t/u-boot.lds   |   39 +++++++----
 arch/arm/cpu/arm920t/start.S      |  125 ++++++++++++++++++-----------------
 arch/arm/cpu/arm920t/u-boot.lds   |   38 +++++++----
 arch/arm/cpu/arm925t/start.S      |  127 +++++++++++++++++++-----------------
 arch/arm/cpu/arm925t/u-boot.lds   |   38 +++++++----
 arch/arm/cpu/arm946es/start.S     |  123 ++++++++++++++++++-----------------
 arch/arm/cpu/arm946es/u-boot.lds  |   38 +++++++----
 arch/arm/cpu/arm_intcm/start.S    |  127 +++++++++++++++++++----------------
 arch/arm/cpu/arm_intcm/u-boot.lds |   38 +++++++----
 arch/arm/cpu/ixp/start.S          |  118 +++++++++++++++++----------------
 arch/arm/cpu/ixp/u-boot.lds       |   38 +++++++----
 arch/arm/cpu/lh7a40x/start.S      |  119 +++++++++++++++++----------------
 arch/arm/cpu/lh7a40x/u-boot.lds   |   38 +++++++----
 arch/arm/cpu/s3c44b0/start.S      |  131 +++++++++++++++++--------------------
 arch/arm/cpu/s3c44b0/u-boot.lds   |   38 +++++++----
 arch/arm/cpu/sa1100/start.S       |  119 +++++++++++++++++----------------
 arch/arm/cpu/sa1100/u-boot.lds    |   38 +++++++----
 18 files changed, 785 insertions(+), 666 deletions(-)

Comments

Darius Augulis Nov. 26, 2010, 6:04 p.m.
Hi Albert,

On 11/25/2010 11:45 PM, Albert Aribaud wrote:
> bulk addition of ELF relocation support to ARM cpus
> arm946es, arm720t,arm920t, arm925t, arm_intcm, ixp,
> lh7a40x, s3c44b0, and sa1100.
>
> Signed-off-by: Albert Aribaud<albert.aribaud@free.fr>
> ---
>   arch/arm/cpu/arm720t/start.S      |  119 +++++++++++++++++----------------
>   arch/arm/cpu/arm720t/u-boot.lds   |   39 +++++++----
>   arch/arm/cpu/arm920t/start.S      |  125 ++++++++++++++++++-----------------
>   arch/arm/cpu/arm920t/u-boot.lds   |   38 +++++++----
>   arch/arm/cpu/arm925t/start.S      |  127 +++++++++++++++++++-----------------
>   arch/arm/cpu/arm925t/u-boot.lds   |   38 +++++++----
>   arch/arm/cpu/arm946es/start.S     |  123 ++++++++++++++++++-----------------
>   arch/arm/cpu/arm946es/u-boot.lds  |   38 +++++++----
>   arch/arm/cpu/arm_intcm/start.S    |  127 +++++++++++++++++++----------------
>   arch/arm/cpu/arm_intcm/u-boot.lds |   38 +++++++----
>   arch/arm/cpu/ixp/start.S          |  118 +++++++++++++++++----------------
>   arch/arm/cpu/ixp/u-boot.lds       |   38 +++++++----
>   arch/arm/cpu/lh7a40x/start.S      |  119 +++++++++++++++++----------------
>   arch/arm/cpu/lh7a40x/u-boot.lds   |   38 +++++++----
>   arch/arm/cpu/s3c44b0/start.S      |  131 +++++++++++++++++--------------------
>   arch/arm/cpu/s3c44b0/u-boot.lds   |   38 +++++++----
>   arch/arm/cpu/sa1100/start.S       |  119 +++++++++++++++++----------------
>   arch/arm/cpu/sa1100/u-boot.lds    |   38 +++++++----
>   18 files changed, 785 insertions(+), 666 deletions(-)
>

how about arm1136 and arm1176? Perhaps they both have relocation code 
but also they try to use _datarel_* which are not exported by linker 
anymore.
I have my own local patches but I think would be better if you change it 
together with all other cpus.

> diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S
> index 8cd267b..46050da 100644
> --- a/arch/arm/cpu/arm720t/start.S
> +++ b/arch/arm/cpu/arm720t/start.S
> @@ -81,14 +81,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -107,30 +110,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -184,9 +163,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -197,35 +175,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -242,18 +238,25 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
> +
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /*
>    *************************************************************************
> diff --git a/arch/arm/cpu/arm720t/u-boot.lds b/arch/arm/cpu/arm720t/u-boot.lds
> index 4a0bc70..0686e42 100644
> --- a/arch/arm/cpu/arm720t/u-boot.lds
> +++ b/arch/arm/cpu/arm720t/u-boot.lds
> @@ -40,29 +40,38 @@ SECTIONS
>
>   	. = ALIGN(4);
>   	.data : {
> -		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/arm920t/start.S b/arch/arm/cpu/arm920t/start.S
> index d4edde7..01edb9b 100644
> --- a/arch/arm/cpu/arm920t/start.S
> +++ b/arch/arm/cpu/arm920t/start.S
> @@ -77,14 +77,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -103,30 +106,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual start code
>    */
> @@ -230,9 +209,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -243,35 +221,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -289,24 +285,33 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * initialization, now running from RAM.
>    */
>   #ifdef CONFIG_NAND_SPL
> -	ldr     pc, _nand_boot
> +	ldr     r0, _nand_boot_ofs
> +	mov	pc, r0
>
> -_nand_boot: .word nand_boot
> +_nand_boot_ofs:
> +	.word nand_boot
>   #else
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
>   #endif
>
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
> +
>   /*
>    *************************************************************************
>    *
> diff --git a/arch/arm/cpu/arm920t/u-boot.lds b/arch/arm/cpu/arm920t/u-boot.lds
> index 6985434..a6f8b56 100644
> --- a/arch/arm/cpu/arm920t/u-boot.lds
> +++ b/arch/arm/cpu/arm920t/u-boot.lds
> @@ -49,28 +49,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/arm925t/start.S b/arch/arm/cpu/arm925t/start.S
> index 51229c6..ce590a7 100644
> --- a/arch/arm/cpu/arm925t/start.S
> +++ b/arch/arm/cpu/arm925t/start.S
> @@ -87,14 +87,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -113,30 +116,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -221,9 +200,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -234,35 +212,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -271,6 +267,8 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>   	cmp	r0, r1
>   	bne	clbss_l
>
> +	bl coloured_LED_init
> +	bl red_LED_on
>   #endif
>
>   /*
> @@ -278,24 +276,33 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * initialization, now running from RAM.
>    */
>   #ifdef CONFIG_NAND_SPL
> -	ldr     pc, _nand_boot
> +	ldr     r0, _nand_boot_ofs
> +	mov	pc, r0
>
> -_nand_boot: .word nand_boot
> +_nand_boot_ofs:
> +	.word nand_boot
>   #else
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
>   #endif
>
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
> +
>   /*
>    *************************************************************************
>    *
> diff --git a/arch/arm/cpu/arm925t/u-boot.lds b/arch/arm/cpu/arm925t/u-boot.lds
> index 1c4e9bc..7b53edb 100644
> --- a/arch/arm/cpu/arm925t/u-boot.lds
> +++ b/arch/arm/cpu/arm925t/u-boot.lds
> @@ -44,28 +44,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/arm946es/start.S b/arch/arm/cpu/arm946es/start.S
> index cad43ba..f4950f7 100644
> --- a/arch/arm/cpu/arm946es/start.S
> +++ b/arch/arm/cpu/arm946es/start.S
> @@ -10,6 +10,7 @@
>    *  Copyright (c) 2002	Gary Jennejohn<garyj@denx.de>
>    *  Copyright (c) 2003	Richard Woodruff<r-woodruff2@ti.com>
>    *  Copyright (c) 2003	Kshitij<kshitij@ti.com>
> + *  Copyright (c) 2010	Albert Aribaud<albert.aribaud@free.fr>
>    *
>    * See file CREDITS for list of people who contributed to this
>    * project.
> @@ -71,6 +72,7 @@ _fiq:
>
>   	.balignl 16,0xdeadbeef
>
> +_vectors_end:
>
>   /*
>    *************************************************************************
> @@ -91,14 +93,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -117,30 +122,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -190,9 +171,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -203,42 +183,60 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
>   clbss_l:str	r2, [r0]		/* clear loop...		    */
>   	add	r0, r0, #4
>   	cmp	r0, r1
> -	bne	clbss_l
> +	blo	clbss_l
>   #endif
>
>   /*
> @@ -250,20 +248,27 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>
>   _nand_boot: .word nand_boot
>   #else
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
>   #endif
>
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
> +
>   /*
>    *************************************************************************
>    *
> diff --git a/arch/arm/cpu/arm946es/u-boot.lds b/arch/arm/cpu/arm946es/u-boot.lds
> index 6535963..eb91979 100644
> --- a/arch/arm/cpu/arm946es/u-boot.lds
> +++ b/arch/arm/cpu/arm946es/u-boot.lds
> @@ -41,28 +41,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/arm_intcm/start.S b/arch/arm/cpu/arm_intcm/start.S
> index 957ca34..fcaba30 100644
> --- a/arch/arm/cpu/arm_intcm/start.S
> +++ b/arch/arm/cpu/arm_intcm/start.S
> @@ -89,14 +89,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -115,30 +118,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -188,9 +167,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -201,35 +179,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -246,18 +242,33 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +#ifdef CONFIG_NAND_SPL
> +	ldr     r0, _nand_boot_ofs
> +	mov	pc, r0
> +
> +_nand_boot_ofs:
> +	.word nand_boot
> +#else
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
> +#endif
> +
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /*
>    *************************************************************************
> diff --git a/arch/arm/cpu/arm_intcm/u-boot.lds b/arch/arm/cpu/arm_intcm/u-boot.lds
> index 242c7ec..3b5c18d 100644
> --- a/arch/arm/cpu/arm_intcm/u-boot.lds
> +++ b/arch/arm/cpu/arm_intcm/u-boot.lds
> @@ -41,28 +41,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/ixp/start.S b/arch/arm/cpu/ixp/start.S
> index 8d1aebc..d1ab19b 100644
> --- a/arch/arm/cpu/ixp/start.S
> +++ b/arch/arm/cpu/ixp/start.S
> @@ -100,14 +100,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -126,30 +129,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -314,9 +293,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -327,35 +305,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -372,19 +368,25 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
>
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /****************************************************************************/
>   /*									    */
> diff --git a/arch/arm/cpu/ixp/u-boot.lds b/arch/arm/cpu/ixp/u-boot.lds
> index f3d9dc5..a55eb8a 100644
> --- a/arch/arm/cpu/ixp/u-boot.lds
> +++ b/arch/arm/cpu/ixp/u-boot.lds
> @@ -41,28 +41,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/lh7a40x/start.S b/arch/arm/cpu/lh7a40x/start.S
> index fd8a40b..5cf477b 100644
> --- a/arch/arm/cpu/lh7a40x/start.S
> +++ b/arch/arm/cpu/lh7a40x/start.S
> @@ -77,14 +77,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -103,30 +106,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -201,9 +180,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -214,35 +192,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -256,18 +252,25 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
> +
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /*
>    *************************************************************************
> diff --git a/arch/arm/cpu/lh7a40x/u-boot.lds b/arch/arm/cpu/lh7a40x/u-boot.lds
> index cb55b0a..463237d 100644
> --- a/arch/arm/cpu/lh7a40x/u-boot.lds
> +++ b/arch/arm/cpu/lh7a40x/u-boot.lds
> @@ -41,28 +41,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/s3c44b0/start.S b/arch/arm/cpu/s3c44b0/start.S
> index 67b2c6a..8c7100c 100644
> --- a/arch/arm/cpu/s3c44b0/start.S
> +++ b/arch/arm/cpu/s3c44b0/start.S
> @@ -68,14 +68,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -94,30 +97,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -173,9 +152,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -186,47 +164,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
> -/*
> -	now copy to sram the interrupt vector
> -*/
> -	adr	r0, real_vectors
> -	add	r2, r0, #1024
> -	ldr	r1, =0x0c000000
> -	add	r1, r1, #0x08
> -vector_copy_loop:
> -	ldmia	r0!, {r3-r10}
> -	stmia	r1!, {r3-r10}
> -	cmp	r0, r2
> -	blo	vector_copy_loop
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -243,18 +227,25 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
> +
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /*
>    *************************************************************************
> diff --git a/arch/arm/cpu/s3c44b0/u-boot.lds b/arch/arm/cpu/s3c44b0/u-boot.lds
> index bbc8c3a..ac29440 100644
> --- a/arch/arm/cpu/s3c44b0/u-boot.lds
> +++ b/arch/arm/cpu/s3c44b0/u-boot.lds
> @@ -41,28 +41,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
> diff --git a/arch/arm/cpu/sa1100/start.S b/arch/arm/cpu/sa1100/start.S
> index ace0c07..36d44da 100644
> --- a/arch/arm/cpu/sa1100/start.S
> +++ b/arch/arm/cpu/sa1100/start.S
> @@ -78,14 +78,17 @@ _TEXT_BASE:
>
>   /*
>    * These are defined in the board-specific linker script.
> + * Subtracting _start from them lets the linker put their
> + * relative position in the executable instead of leaving
> + * them null.
>    */
> -.globl _bss_start
> -_bss_start:
> -	.word __bss_start
> +.globl _bss_start_ofs
> +_bss_start_ofs:
> +	.word __bss_start - _start
>
> -.globl _bss_end
> -_bss_end:
> -	.word _end
> +.globl _bss_end_ofs
> +_bss_end_ofs:
> +	.word _end - _start
>
>   #ifdef CONFIG_USE_IRQ
>   /* IRQ stack memory (calculated at run-time) */
> @@ -104,30 +107,6 @@ FIQ_STACK_START:
>   IRQ_STACK_START_IN:
>   	.word	0x0badc0de
>
> -.globl _datarel_start
> -_datarel_start:
> -	.word __datarel_start
> -
> -.globl _datarelrolocal_start
> -_datarelrolocal_start:
> -	.word __datarelrolocal_start
> -
> -.globl _datarellocal_start
> -_datarellocal_start:
> -	.word __datarellocal_start
> -
> -.globl _datarelro_start
> -_datarelro_start:
> -	.word __datarelro_start
> -
> -.globl _got_start
> -_got_start:
> -	.word __got_start
> -
> -.globl _got_end
> -_got_end:
> -	.word __got_end
> -
>   /*
>    * the actual reset code
>    */
> @@ -177,9 +156,8 @@ stack_setup:
>
>   	adr	r0, _start
>   	ldr	r2, _TEXT_BASE
> -	ldr	r3, _bss_start
> -	sub	r2, r3, r2		/* r2<- size of armboot	    */
> -	add	r2, r0, r2		/* r2<- source end address	    */
> +	ldr	r3, _bss_start_ofs
> +	add	r2, r0, r3		/* r2<- source end address	    */
>   	cmp	r0, r6
>   	beq	clear_bss
>
> @@ -190,35 +168,53 @@ copy_loop:
>   	blo	copy_loop
>
>   #ifndef CONFIG_PRELOADER
> -	/* fix got entries */
> -	ldr	r1, _TEXT_BASE		/* Text base */
> -	mov	r0, r7			/* reloc addr */
> -	ldr	r2, _got_start		/* addr in Flash */
> -	ldr	r3, _got_end		/* addr in Flash */
> -	sub	r3, r3, r1
> -	add	r3, r3, r0
> -	sub	r2, r2, r1
> -	add	r2, r2, r0
> -
> +	/*
> +	 * fix .rel.dyn relocations
> +	 */
> +	ldr	r0, _TEXT_BASE		/* r0<- Text base */
> +	sub	r9, r7, r0		/* r9<- relocation offset */
> +	ldr	r10, _dynsym_start_ofs	/* r10<- sym table ofs */
> +	add	r10, r10, r0		/* r10<- sym table in FLASH */
> +	ldr	r2, _rel_dyn_start_ofs	/* r2<- rel dyn start ofs */
> +	add	r2, r2, r0		/* r2<- rel dyn start in FLASH */
> +	ldr	r3, _rel_dyn_end_ofs	/* r3<- rel dyn end ofs */
> +	add	r3, r3, r0		/* r3<- rel dyn end in FLASH */
>   fixloop:
> -	ldr	r4, [r2]
> -	sub	r4, r4, r1
> -	add	r4, r4, r0
> -	str	r4, [r2]
> -	add	r2, r2, #4
> +	ldr	r0, [r2]		/* r0<- location to fix up, IN FLASH! */
> +	add	r0, r0, r9		/* r0<- location to fix up in RAM */
> +	ldr	r1, [r2, #4]
> +	and	r8, r1, #0xff
> +	cmp	r8, #23			/* relative fixup? */
> +	beq	fixrel
> +	cmp	r8, #2			/* absolute fixup? */
> +	beq	fixabs
> +	/* ignore unknown type of fixup */
> +	b	fixnext
> +fixabs:
> +	/* absolute fix: set location to (offset) symbol value */
> +	mov	r1, r1, LSR #4		/* r1<- symbol index in .dynsym */
> +	add	r1, r10, r1		/* r1<- address of symbol in table */
> +	ldr	r1, [r1, #4]		/* r1<- symbol value */
> +	add	r1, r9			/* r1<- relocated sym addr */
> +	b	fixnext
> +fixrel:
> +	/* relative fix: increase location by offset */
> +	ldr	r1, [r0]
> +	add	r1, r1, r9
> +fixnext:
> +	str	r1, [r0]
> +	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
>   	cmp	r2, r3
>   	blo	fixloop
>   #endif
>
>   clear_bss:
>   #ifndef CONFIG_PRELOADER
> -	ldr	r0, _bss_start
> -	ldr	r1, _bss_end
> +	ldr	r0, _bss_start_ofs
> +	ldr	r1, _bss_end_ofs
>   	ldr	r3, _TEXT_BASE		/* Text base */
>   	mov	r4, r7			/* reloc addr */
> -	sub	r0, r0, r3
>   	add	r0, r0, r4
> -	sub	r1, r1, r3
>   	add	r1, r1, r4
>   	mov	r2, #0x00000000		/* clear			    */
>
> @@ -232,18 +228,25 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * We are done. Do not return, instead branch to second part of board
>    * initialization, now running from RAM.
>    */
> -	ldr	r0, _TEXT_BASE
> -	ldr	r2, _board_init_r
> -	sub	r2, r2, r0
> -	add	r2, r2, r7	/* position from board_init_r in RAM */
> +	ldr	r0, _board_init_r_ofs
> +	adr	r1, _start
> +	add	lr, r0, r1
> +	add	lr, lr, r9
>   	/* setup parameters for board_init_r */
>   	mov	r0, r5		/* gd_t */
>   	mov	r1, r7		/* dest_addr */
>   	/* jump to it ... */
> -	mov	lr, r2
>   	mov	pc, lr
>
> -_board_init_r: .word board_init_r
> +_board_init_r_ofs:
> +	.word board_init_r - _start
> +
> +_rel_dyn_start_ofs:
> +	.word __rel_dyn_start - _start
> +_rel_dyn_end_ofs:
> +	.word __rel_dyn_end - _start
> +_dynsym_start_ofs:
> +	.word __dynsym_start - _start
>
>   /*
>    *************************************************************************
> diff --git a/arch/arm/cpu/sa1100/u-boot.lds b/arch/arm/cpu/sa1100/u-boot.lds
> index 2e29291..fa6d05c 100644
> --- a/arch/arm/cpu/sa1100/u-boot.lds
> +++ b/arch/arm/cpu/sa1100/u-boot.lds
> @@ -44,28 +44,38 @@ SECTIONS
>   	. = ALIGN(4);
>   	.data : {
>   		*(.data)
> -	__datarel_start = .;
> -		*(.data.rel)
> -	__datarelrolocal_start = .;
> -		*(.data.rel.ro.local)
> -	__datarellocal_start = .;
> -		*(.data.rel.local)
> -	__datarelro_start = .;
> -		*(.data.rel.ro)
>   	}
>
> -	__got_start = .;
>   	. = ALIGN(4);
> -	.got : { *(.got) }
>
> -	__got_end = .;
>   	. = .;
>   	__u_boot_cmd_start = .;
>   	.u_boot_cmd : { *(.u_boot_cmd) }
>   	__u_boot_cmd_end = .;
>
>   	. = ALIGN(4);
> -	__bss_start = .;
> -	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
> -	_end = .;
> +
> +	.rel.dyn : {
> +		__rel_dyn_start = .;
> +		*(.rel*)
> +		__rel_dyn_end = .;
> +	}
> +
> +	.dynsym : {
> +		__dynsym_start = .;
> +		*(.dynsym)
> +	}
> +
> +	.bss __rel_dyn_start (OVERLAY) : {
> +		__bss_start = .;
> +		*(.bss)
> +		 . = ALIGN(4);
> +		_end = .;
> +	}
> +
> +	/DISCARD/ : { *(.dynstr*) }
> +	/DISCARD/ : { *(.dynamic*) }
> +	/DISCARD/ : { *(.plt*) }
> +	/DISCARD/ : { *(.interp*) }
> +	/DISCARD/ : { *(.gnu*) }
>   }
Albert ARIBAUD Nov. 26, 2010, 6:12 p.m.
Hi Darius,

Le 26/11/2010 19:04, Darius Augulis a écrit :

> Hi Albert,

> how about arm1136 and arm1176? Perhaps they both have relocation code
> but also they try to use _datarel_* which are not exported by linker
> anymore.

If I am not mistaken, arm1136 and arm1176 are dealt with in v5 of my 
patch <http://article.gmane.org/gmane.comp.boot-loaders.u-boot/88966>, 
which is already applied to u-boot-arm and will thus be pulled into 
u-boot soon.

> I have my own local patches but I think would be better if you change it
> together with all other cpus.

Please verify my V5 patch and, if your patches are needed above it, 
please post them here to be apllied above mine.

Amicalement,
Darius Augulis Nov. 26, 2010, 6:18 p.m.
Hi,

On 11/26/2010 08:12 PM, Albert ARIBAUD wrote:
> Hi Darius,
>
> Le 26/11/2010 19:04, Darius Augulis a écrit :
>
>> Hi Albert,
>
>> how about arm1136 and arm1176? Perhaps they both have relocation code
>> but also they try to use _datarel_* which are not exported by linker
>> anymore.
>
> If I am not mistaken, arm1136 and arm1176 are dealt with in v5 of my
> patch<http://article.gmane.org/gmane.comp.boot-loaders.u-boot/88966>,
> which is already applied to u-boot-arm and will thus be pulled into
> u-boot soon.

as I can see only u-boot.lds is changed for arm1176 and start.S isn't.
arm1136 got changed both these files.

>
>> I have my own local patches but I think would be better if you change it
>> together with all other cpus.
>
> Please verify my V5 patch and, if your patches are needed above it,
> please post them here to be apllied above mine.

they are very raw and not ready yet. Not sure when will have time to 
finish it.

Darius.

>
> Amicalement,
Albert ARIBAUD Nov. 26, 2010, 6:34 p.m.
Le 26/11/2010 19:18, Darius Augulis a écrit :
> Hi,
>
> On 11/26/2010 08:12 PM, Albert ARIBAUD wrote:
>> Hi Darius,
>>
>> Le 26/11/2010 19:04, Darius Augulis a écrit :
>>
>>> Hi Albert,
>>
>>> how about arm1136 and arm1176? Perhaps they both have relocation code
>>> but also they try to use _datarel_* which are not exported by linker
>>> anymore.
>>
>> If I am not mistaken, arm1136 and arm1176 are dealt with in v5 of my
>> patch<http://article.gmane.org/gmane.comp.boot-loaders.u-boot/88966>,
>> which is already applied to u-boot-arm and will thus be pulled into
>> u-boot soon.
>
> as I can see only u-boot.lds is changed for arm1176 and start.S isn't.
> arm1136 got changed both these files.

Correct, the arm1176 start.S is only half-fixed for ELF relocations. 
I'll post a bugfix right away.

>>> I have my own local patches but I think would be better if you change it
>>> together with all other cpus.
>>
>> Please verify my V5 patch and, if your patches are needed above it,
>> please post them here to be apllied above mine.
>
> they are very raw and not ready yet. Not sure when will have time to
> finish it.

What do they add beside the fix to arm1136/1176 ?

Amicalement,
Darius Augulis Nov. 26, 2010, 6:41 p.m.
On 11/26/2010 08:34 PM, Albert ARIBAUD wrote:
> Le 26/11/2010 19:18, Darius Augulis a écrit :
>> Hi,
>>
>> On 11/26/2010 08:12 PM, Albert ARIBAUD wrote:
>>> Hi Darius,
>>>
>>> Le 26/11/2010 19:04, Darius Augulis a écrit :
>>>
>>>> Hi Albert,
>>>
>>>> how about arm1136 and arm1176? Perhaps they both have relocation code
>>>> but also they try to use _datarel_* which are not exported by linker
>>>> anymore.
>>>
>>> If I am not mistaken, arm1136 and arm1176 are dealt with in v5 of my
>>> patch<http://article.gmane.org/gmane.comp.boot-loaders.u-boot/88966>,
>>> which is already applied to u-boot-arm and will thus be pulled into
>>> u-boot soon.
>>
>> as I can see only u-boot.lds is changed for arm1176 and start.S isn't.
>> arm1136 got changed both these files.
>
> Correct, the arm1176 start.S is only half-fixed for ELF relocations.
> I'll post a bugfix right away.
>
>>>> I have my own local patches but I think would be better if you
>>>> change it
>>>> together with all other cpus.
>>>
>>> Please verify my V5 patch and, if your patches are needed above it,
>>> please post them here to be apllied above mine.
>>
>> they are very raw and not ready yet. Not sure when will have time to
>> finish it.
>
> What do they add beside the fix to arm1136/1176 ?

actually it's not a separate patch but merged into other big patch which 
adds support for mini6410 board. I will resolve my local conflicts after 
pulling your bugfix.

Darius.

>
> Amicalement,
Wolfgang Denk Nov. 26, 2010, 8:22 p.m.
Dear Albert Aribaud,

In message <1290721502-410-1-git-send-email-albert.aribaud@free.fr> you wrote:
> bulk addition of ELF relocation support to ARM cpus
> arm946es, arm720t,arm920t, arm925t, arm_intcm, ixp,
> lh7a40x, s3c44b0, and sa1100.
> 
> Signed-off-by: Albert Aribaud <albert.aribaud@free.fr>
> ---
>  arch/arm/cpu/arm720t/start.S      |  119 +++++++++++++++++----------------
>  arch/arm/cpu/arm720t/u-boot.lds   |   39 +++++++----
>  arch/arm/cpu/arm920t/start.S      |  125 ++++++++++++++++++-----------------
>  arch/arm/cpu/arm920t/u-boot.lds   |   38 +++++++----
>  arch/arm/cpu/arm925t/start.S      |  127 +++++++++++++++++++-----------------
>  arch/arm/cpu/arm925t/u-boot.lds   |   38 +++++++----
>  arch/arm/cpu/arm946es/start.S     |  123 ++++++++++++++++++-----------------
>  arch/arm/cpu/arm946es/u-boot.lds  |   38 +++++++----
>  arch/arm/cpu/arm_intcm/start.S    |  127 +++++++++++++++++++----------------
>  arch/arm/cpu/arm_intcm/u-boot.lds |   38 +++++++----
>  arch/arm/cpu/ixp/start.S          |  118 +++++++++++++++++----------------
>  arch/arm/cpu/ixp/u-boot.lds       |   38 +++++++----
>  arch/arm/cpu/lh7a40x/start.S      |  119 +++++++++++++++++----------------
>  arch/arm/cpu/lh7a40x/u-boot.lds   |   38 +++++++----
>  arch/arm/cpu/s3c44b0/start.S      |  131 +++++++++++++++++--------------------
>  arch/arm/cpu/s3c44b0/u-boot.lds   |   38 +++++++----
>  arch/arm/cpu/sa1100/start.S       |  119 +++++++++++++++++----------------
>  arch/arm/cpu/sa1100/u-boot.lds    |   38 +++++++----
>  18 files changed, 785 insertions(+), 666 deletions(-)

Applied, thanks.

Best regards,

Wolfgang Denk

Patch hide | download patch | download mbox

diff --git a/arch/arm/cpu/arm720t/start.S b/arch/arm/cpu/arm720t/start.S
index 8cd267b..46050da 100644
--- a/arch/arm/cpu/arm720t/start.S
+++ b/arch/arm/cpu/arm720t/start.S
@@ -81,14 +81,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -107,30 +110,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -184,9 +163,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -197,35 +175,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -242,18 +238,25 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
+
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /*
  *************************************************************************
diff --git a/arch/arm/cpu/arm720t/u-boot.lds b/arch/arm/cpu/arm720t/u-boot.lds
index 4a0bc70..0686e42 100644
--- a/arch/arm/cpu/arm720t/u-boot.lds
+++ b/arch/arm/cpu/arm720t/u-boot.lds
@@ -40,29 +40,38 @@  SECTIONS
 
 	. = ALIGN(4);
 	.data : {
-		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/arm920t/start.S b/arch/arm/cpu/arm920t/start.S
index d4edde7..01edb9b 100644
--- a/arch/arm/cpu/arm920t/start.S
+++ b/arch/arm/cpu/arm920t/start.S
@@ -77,14 +77,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -103,30 +106,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual start code
  */
@@ -230,9 +209,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -243,35 +221,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -289,24 +285,33 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * initialization, now running from RAM.
  */
 #ifdef CONFIG_NAND_SPL
-	ldr     pc, _nand_boot
+	ldr     r0, _nand_boot_ofs
+	mov	pc, r0
 
-_nand_boot: .word nand_boot
+_nand_boot_ofs:
+	.word nand_boot
 #else
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
 #endif
 
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
+
 /*
  *************************************************************************
  *
diff --git a/arch/arm/cpu/arm920t/u-boot.lds b/arch/arm/cpu/arm920t/u-boot.lds
index 6985434..a6f8b56 100644
--- a/arch/arm/cpu/arm920t/u-boot.lds
+++ b/arch/arm/cpu/arm920t/u-boot.lds
@@ -49,28 +49,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/arm925t/start.S b/arch/arm/cpu/arm925t/start.S
index 51229c6..ce590a7 100644
--- a/arch/arm/cpu/arm925t/start.S
+++ b/arch/arm/cpu/arm925t/start.S
@@ -87,14 +87,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -113,30 +116,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -221,9 +200,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -234,35 +212,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -271,6 +267,8 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
 	cmp	r0, r1
 	bne	clbss_l
 
+	bl coloured_LED_init
+	bl red_LED_on
 #endif
 
 /*
@@ -278,24 +276,33 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * initialization, now running from RAM.
  */
 #ifdef CONFIG_NAND_SPL
-	ldr     pc, _nand_boot
+	ldr     r0, _nand_boot_ofs
+	mov	pc, r0
 
-_nand_boot: .word nand_boot
+_nand_boot_ofs:
+	.word nand_boot
 #else
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
 #endif
 
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
+
 /*
  *************************************************************************
  *
diff --git a/arch/arm/cpu/arm925t/u-boot.lds b/arch/arm/cpu/arm925t/u-boot.lds
index 1c4e9bc..7b53edb 100644
--- a/arch/arm/cpu/arm925t/u-boot.lds
+++ b/arch/arm/cpu/arm925t/u-boot.lds
@@ -44,28 +44,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/arm946es/start.S b/arch/arm/cpu/arm946es/start.S
index cad43ba..f4950f7 100644
--- a/arch/arm/cpu/arm946es/start.S
+++ b/arch/arm/cpu/arm946es/start.S
@@ -10,6 +10,7 @@ 
  *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
  *  Copyright (c) 2003	Richard Woodruff <r-woodruff2@ti.com>
  *  Copyright (c) 2003	Kshitij <kshitij@ti.com>
+ *  Copyright (c) 2010	Albert Aribaud <albert.aribaud@free.fr>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -71,6 +72,7 @@  _fiq:
 
 	.balignl 16,0xdeadbeef
 
+_vectors_end:
 
 /*
  *************************************************************************
@@ -91,14 +93,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -117,30 +122,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -190,9 +171,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -203,42 +183,60 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
 clbss_l:str	r2, [r0]		/* clear loop...		    */
 	add	r0, r0, #4
 	cmp	r0, r1
-	bne	clbss_l
+	blo	clbss_l
 #endif
 
 /*
@@ -250,20 +248,27 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
 
 _nand_boot: .word nand_boot
 #else
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
 #endif
 
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
+
 /*
  *************************************************************************
  *
diff --git a/arch/arm/cpu/arm946es/u-boot.lds b/arch/arm/cpu/arm946es/u-boot.lds
index 6535963..eb91979 100644
--- a/arch/arm/cpu/arm946es/u-boot.lds
+++ b/arch/arm/cpu/arm946es/u-boot.lds
@@ -41,28 +41,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/arm_intcm/start.S b/arch/arm/cpu/arm_intcm/start.S
index 957ca34..fcaba30 100644
--- a/arch/arm/cpu/arm_intcm/start.S
+++ b/arch/arm/cpu/arm_intcm/start.S
@@ -89,14 +89,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -115,30 +118,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -188,9 +167,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -201,35 +179,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -246,18 +242,33 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+#ifdef CONFIG_NAND_SPL
+	ldr     r0, _nand_boot_ofs
+	mov	pc, r0
+
+_nand_boot_ofs:
+	.word nand_boot
+#else
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
+#endif
+
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /*
  *************************************************************************
diff --git a/arch/arm/cpu/arm_intcm/u-boot.lds b/arch/arm/cpu/arm_intcm/u-boot.lds
index 242c7ec..3b5c18d 100644
--- a/arch/arm/cpu/arm_intcm/u-boot.lds
+++ b/arch/arm/cpu/arm_intcm/u-boot.lds
@@ -41,28 +41,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/ixp/start.S b/arch/arm/cpu/ixp/start.S
index 8d1aebc..d1ab19b 100644
--- a/arch/arm/cpu/ixp/start.S
+++ b/arch/arm/cpu/ixp/start.S
@@ -100,14 +100,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -126,30 +129,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -314,9 +293,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -327,35 +305,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -372,19 +368,25 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
 
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /****************************************************************************/
 /*									    */
diff --git a/arch/arm/cpu/ixp/u-boot.lds b/arch/arm/cpu/ixp/u-boot.lds
index f3d9dc5..a55eb8a 100644
--- a/arch/arm/cpu/ixp/u-boot.lds
+++ b/arch/arm/cpu/ixp/u-boot.lds
@@ -41,28 +41,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/lh7a40x/start.S b/arch/arm/cpu/lh7a40x/start.S
index fd8a40b..5cf477b 100644
--- a/arch/arm/cpu/lh7a40x/start.S
+++ b/arch/arm/cpu/lh7a40x/start.S
@@ -77,14 +77,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -103,30 +106,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -201,9 +180,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -214,35 +192,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -256,18 +252,25 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
+
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /*
  *************************************************************************
diff --git a/arch/arm/cpu/lh7a40x/u-boot.lds b/arch/arm/cpu/lh7a40x/u-boot.lds
index cb55b0a..463237d 100644
--- a/arch/arm/cpu/lh7a40x/u-boot.lds
+++ b/arch/arm/cpu/lh7a40x/u-boot.lds
@@ -41,28 +41,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/s3c44b0/start.S b/arch/arm/cpu/s3c44b0/start.S
index 67b2c6a..8c7100c 100644
--- a/arch/arm/cpu/s3c44b0/start.S
+++ b/arch/arm/cpu/s3c44b0/start.S
@@ -68,14 +68,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -94,30 +97,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -173,9 +152,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -186,47 +164,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
-/*
-	now copy to sram the interrupt vector
-*/
-	adr	r0, real_vectors
-	add	r2, r0, #1024
-	ldr	r1, =0x0c000000
-	add	r1, r1, #0x08
-vector_copy_loop:
-	ldmia	r0!, {r3-r10}
-	stmia	r1!, {r3-r10}
-	cmp	r0, r2
-	blo	vector_copy_loop
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -243,18 +227,25 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
+
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /*
  *************************************************************************
diff --git a/arch/arm/cpu/s3c44b0/u-boot.lds b/arch/arm/cpu/s3c44b0/u-boot.lds
index bbc8c3a..ac29440 100644
--- a/arch/arm/cpu/s3c44b0/u-boot.lds
+++ b/arch/arm/cpu/s3c44b0/u-boot.lds
@@ -41,28 +41,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }
diff --git a/arch/arm/cpu/sa1100/start.S b/arch/arm/cpu/sa1100/start.S
index ace0c07..36d44da 100644
--- a/arch/arm/cpu/sa1100/start.S
+++ b/arch/arm/cpu/sa1100/start.S
@@ -78,14 +78,17 @@  _TEXT_BASE:
 
 /*
  * These are defined in the board-specific linker script.
+ * Subtracting _start from them lets the linker put their
+ * relative position in the executable instead of leaving
+ * them null.
  */
-.globl _bss_start
-_bss_start:
-	.word __bss_start
+.globl _bss_start_ofs
+_bss_start_ofs:
+	.word __bss_start - _start
 
-.globl _bss_end
-_bss_end:
-	.word _end
+.globl _bss_end_ofs
+_bss_end_ofs:
+	.word _end - _start
 
 #ifdef CONFIG_USE_IRQ
 /* IRQ stack memory (calculated at run-time) */
@@ -104,30 +107,6 @@  FIQ_STACK_START:
 IRQ_STACK_START_IN:
 	.word	0x0badc0de
 
-.globl _datarel_start
-_datarel_start:
-	.word __datarel_start
-
-.globl _datarelrolocal_start
-_datarelrolocal_start:
-	.word __datarelrolocal_start
-
-.globl _datarellocal_start
-_datarellocal_start:
-	.word __datarellocal_start
-
-.globl _datarelro_start
-_datarelro_start:
-	.word __datarelro_start
-
-.globl _got_start
-_got_start:
-	.word __got_start
-
-.globl _got_end
-_got_end:
-	.word __got_end
-
 /*
  * the actual reset code
  */
@@ -177,9 +156,8 @@  stack_setup:
 
 	adr	r0, _start
 	ldr	r2, _TEXT_BASE
-	ldr	r3, _bss_start
-	sub	r2, r3, r2		/* r2 <- size of armboot	    */
-	add	r2, r0, r2		/* r2 <- source end address	    */
+	ldr	r3, _bss_start_ofs
+	add	r2, r0, r3		/* r2 <- source end address	    */
 	cmp	r0, r6
 	beq	clear_bss
 
@@ -190,35 +168,53 @@  copy_loop:
 	blo	copy_loop
 
 #ifndef CONFIG_PRELOADER
-	/* fix got entries */
-	ldr	r1, _TEXT_BASE		/* Text base */
-	mov	r0, r7			/* reloc addr */
-	ldr	r2, _got_start		/* addr in Flash */
-	ldr	r3, _got_end		/* addr in Flash */
-	sub	r3, r3, r1
-	add	r3, r3, r0
-	sub	r2, r2, r1
-	add	r2, r2, r0
-
+	/*
+	 * fix .rel.dyn relocations
+	 */
+	ldr	r0, _TEXT_BASE		/* r0 <- Text base */
+	sub	r9, r7, r0		/* r9 <- relocation offset */
+	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */
+	add	r10, r10, r0		/* r10 <- sym table in FLASH */
+	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */
+	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */
+	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */
+	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */
 fixloop:
-	ldr	r4, [r2]
-	sub	r4, r4, r1
-	add	r4, r4, r0
-	str	r4, [r2]
-	add	r2, r2, #4
+	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
+	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
+	ldr	r1, [r2, #4]
+	and	r8, r1, #0xff
+	cmp	r8, #23			/* relative fixup? */
+	beq	fixrel
+	cmp	r8, #2			/* absolute fixup? */
+	beq	fixabs
+	/* ignore unknown type of fixup */
+	b	fixnext
+fixabs:
+	/* absolute fix: set location to (offset) symbol value */
+	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */
+	add	r1, r10, r1		/* r1 <- address of symbol in table */
+	ldr	r1, [r1, #4]		/* r1 <- symbol value */
+	add	r1, r9			/* r1 <- relocated sym addr */
+	b	fixnext
+fixrel:
+	/* relative fix: increase location by offset */
+	ldr	r1, [r0]
+	add	r1, r1, r9
+fixnext:
+	str	r1, [r0]
+	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
 	cmp	r2, r3
 	blo	fixloop
 #endif
 
 clear_bss:
 #ifndef CONFIG_PRELOADER
-	ldr	r0, _bss_start
-	ldr	r1, _bss_end
+	ldr	r0, _bss_start_ofs
+	ldr	r1, _bss_end_ofs
 	ldr	r3, _TEXT_BASE		/* Text base */
 	mov	r4, r7			/* reloc addr */
-	sub	r0, r0, r3
 	add	r0, r0, r4
-	sub	r1, r1, r3
 	add	r1, r1, r4
 	mov	r2, #0x00000000		/* clear			    */
 
@@ -232,18 +228,25 @@  clbss_l:str	r2, [r0]		/* clear loop...		    */
  * We are done. Do not return, instead branch to second part of board
  * initialization, now running from RAM.
  */
-	ldr	r0, _TEXT_BASE
-	ldr	r2, _board_init_r
-	sub	r2, r2, r0
-	add	r2, r2, r7	/* position from board_init_r in RAM */
+	ldr	r0, _board_init_r_ofs
+	adr	r1, _start
+	add	lr, r0, r1
+	add	lr, lr, r9
 	/* setup parameters for board_init_r */
 	mov	r0, r5		/* gd_t */
 	mov	r1, r7		/* dest_addr */
 	/* jump to it ... */
-	mov	lr, r2
 	mov	pc, lr
 
-_board_init_r: .word board_init_r
+_board_init_r_ofs:
+	.word board_init_r - _start
+
+_rel_dyn_start_ofs:
+	.word __rel_dyn_start - _start
+_rel_dyn_end_ofs:
+	.word __rel_dyn_end - _start
+_dynsym_start_ofs:
+	.word __dynsym_start - _start
 
 /*
  *************************************************************************
diff --git a/arch/arm/cpu/sa1100/u-boot.lds b/arch/arm/cpu/sa1100/u-boot.lds
index 2e29291..fa6d05c 100644
--- a/arch/arm/cpu/sa1100/u-boot.lds
+++ b/arch/arm/cpu/sa1100/u-boot.lds
@@ -44,28 +44,38 @@  SECTIONS
 	. = ALIGN(4);
 	.data : {
 		*(.data)
-	__datarel_start = .;
-		*(.data.rel)
-	__datarelrolocal_start = .;
-		*(.data.rel.ro.local)
-	__datarellocal_start = .;
-		*(.data.rel.local)
-	__datarelro_start = .;
-		*(.data.rel.ro)
 	}
 
-	__got_start = .;
 	. = ALIGN(4);
-	.got : { *(.got) }
 
-	__got_end = .;
 	. = .;
 	__u_boot_cmd_start = .;
 	.u_boot_cmd : { *(.u_boot_cmd) }
 	__u_boot_cmd_end = .;
 
 	. = ALIGN(4);
-	__bss_start = .;
-	.bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
-	_end = .;
+
+	.rel.dyn : {
+		__rel_dyn_start = .;
+		*(.rel*)
+		__rel_dyn_end = .;
+	}
+
+	.dynsym : {
+		__dynsym_start = .;
+		*(.dynsym)
+	}
+
+	.bss __rel_dyn_start (OVERLAY) : {
+		__bss_start = .;
+		*(.bss)
+		 . = ALIGN(4);
+		_end = .;
+	}
+
+	/DISCARD/ : { *(.dynstr*) }
+	/DISCARD/ : { *(.dynamic*) }
+	/DISCARD/ : { *(.plt*) }
+	/DISCARD/ : { *(.interp*) }
+	/DISCARD/ : { *(.gnu*) }
 }