All of lore.kernel.org
 help / color / mirror / Atom feed
From: Darius Augulis <augulis.darius@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] arm: add ELF relocation support to rest of cpus
Date: Fri, 26 Nov 2010 20:04:02 +0200	[thread overview]
Message-ID: <4CEFF692.7060908@gmail.com> (raw)
In-Reply-To: <1290721502-410-1-git-send-email-albert.aribaud@free.fr>

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*) }
>   }

  reply	other threads:[~2010-11-26 18:04 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-25 21:45 [U-Boot] [PATCH] arm: add ELF relocation support to rest of cpus Albert Aribaud
2010-11-26 18:04 ` Darius Augulis [this message]
2010-11-26 18:12   ` Albert ARIBAUD
2010-11-26 18:18     ` Darius Augulis
2010-11-26 18:34       ` Albert ARIBAUD
2010-11-26 18:41         ` Darius Augulis
2010-11-26 20:22 ` Wolfgang Denk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4CEFF692.7060908@gmail.com \
    --to=augulis.darius@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.