This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
fix bug with loadaddr and load regions
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: binutils at sources dot redhat dot com
- Date: Fri, 25 Aug 2006 11:52:18 +0100
- Subject: fix bug with loadaddr and load regions
I fell over a problem with using a load region and loadaddr, to create a romable
image. With
.data { data_load = LOADADDR(.data); ... } >ram AT>rom
I found that data_load's value became load address + execution address, because
it was interpreted as a data-relative value. The same problem didn't manifest with
.data : AT(EXPR) { data_load = LOADADDR(.data); ...} >ram
but of course here I have to calculate EXPR myself.
When using an AT> region, ldlang creates an integer expression for the section's
load address. When calculating this later for the map file, it uses
exp_get_abs_int to calculate it in an absolute context (so the map file shows
the correct load address). However, when it's evaluated as part of a LOADADDR,
it's calculated in the current section's context.
This patch fixes things in the simplest way I could find. Namely when
evaluating the LOADADDR expression, check whether it came from a load region,
and if so explicitly put it in the *ABS* section.
ok?
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2006-08-25 Nathan Sidwell <nathan@codesourcery.com>
* ldexp.c (fold_name): Loadaddrs of sections with an lma_region
are absolute.
testsuite/
* ld-elf/loadaddr3.t: New.
* ld-elf/loadaddr3a.d: New.
* ld-elf/loadaddr3b.d: New.
Index: ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.63
diff -c -3 -p -r1.63 ldexp.c
*** ldexp.c 23 Aug 2006 01:35:31 -0000 1.63
--- ldexp.c 25 Aug 2006 10:42:22 -0000
*************** fold_name (etree_type *tree)
*** 579,585 ****
if (os->load_base == NULL)
new_abs (os->bfd_section->lma);
else
! exp_fold_tree_1 (os->load_base);
}
}
break;
--- 579,592 ----
if (os->load_base == NULL)
new_abs (os->bfd_section->lma);
else
! {
! exp_fold_tree_1 (os->load_base);
! /* If this section has a load region, the expression
! will be absolute. */
! if (os->lma_region && expld.result.valid_p)
! expld.result.section = bfd_abs_section_ptr;
! }
!
}
}
break;
Index: testsuite/ld-elf/loadaddr3.t
===================================================================
RCS file: testsuite/ld-elf/loadaddr3.t
diff -N testsuite/ld-elf/loadaddr3.t
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elf/loadaddr3.t 25 Aug 2006 10:42:22 -0000
***************
*** 0 ****
--- 1,16 ----
+
+ MEMORY
+ {
+ rom (rx) : ORIGIN = 0x100, LENGTH = 0x100
+ ram (rwx) : ORIGIN = 0x200, LENGTH = 0x100
+
+ }
+
+ SECTIONS
+ {
+ .text : {*(.text .text.*)} >rom
+ .data : {data_load = LOADADDR (.data);
+ data_start = ADDR (.data);
+ *(.data .data.*)} >ram AT>rom
+ /DISCARD/ : { *(.*) }
+ }
Index: testsuite/ld-elf/loadaddr3a.d
===================================================================
RCS file: testsuite/ld-elf/loadaddr3a.d
diff -N testsuite/ld-elf/loadaddr3a.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elf/loadaddr3a.d 25 Aug 2006 10:42:22 -0000
***************
*** 0 ****
--- 1,9 ----
+ #source: loadaddr.s
+ #ld: -T loadaddr3.t -z max-page-size=0x200000
+ #readelf: -l --wide
+ #target: *-*-elf*
+
+ #...
+ LOAD +0x000000 0x0*00000000 0x0*00000000 0x0*0101 0x0*0101 R E 0x.*
+ LOAD +0x000200 0x0*00000200 0x0*00000101 0x0*0001 0x0*0001 RW 0x.*
+ #pass
Index: testsuite/ld-elf/loadaddr3b.d
===================================================================
RCS file: testsuite/ld-elf/loadaddr3b.d
diff -N testsuite/ld-elf/loadaddr3b.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/ld-elf/loadaddr3b.d 25 Aug 2006 10:42:22 -0000
***************
*** 0 ****
--- 1,13 ----
+ #source: loadaddr.s
+ #ld: -T loadaddr3.t -z max-page-size=0x200000
+ #objdump: -t
+ #target: *-*-elf*
+
+ #...
+ 0+0000100 l d .text 0+0000000 .text
+ 0+0000200 l d .data 0+0000000 .data
+ #...
+ 0+0000101 g \*ABS\* 0+0000000 data_load
+ #...
+ 0+0000200 g .data 0+0000000 data_start
+ #pass