Index: ldexp.c =================================================================== RCS file: /cvs/src/src/ld/ldexp.c,v retrieving revision 1.21 diff -c -r1.21 ldexp.c *** ldexp.c 30 Oct 2002 03:57:38 -0000 1.21 --- ldexp.c 20 Nov 2002 18:51:06 -0000 *************** *** 635,640 **** --- 635,641 ---- break; case SIZEOF: + case SIZEOF_UNADJ: /* not actually allowed in grammar */ if (allocation_done != lang_first_phase_enum) { int opb = bfd_octets_per_byte (output_bfd); *************** *** 643,648 **** --- 644,656 ---- os = lang_output_section_find (tree->name.name); check (os, tree->name.name, "SIZEOF"); result = new_abs (os->bfd_section->_raw_size / opb); + + /* If the output section has a size adjustment, and we've + not been asked for the unadjusted size, apply it. */ + if (os->size_adj && tree->type.node_code != SIZEOF_UNADJ) + result = exp_fold_tree_no_dot + (exp_binop ('+', exp_intop (result.value), os->size_adj), + abs_output_section, allocation_done); } else result = invalid (); Index: ldgram.y =================================================================== RCS file: /cvs/src/src/ld/ldgram.y,v retrieving revision 1.22 diff -c -r1.22 ldgram.y *** ldgram.y 11 Oct 2002 07:39:07 -0000 1.22 --- ldgram.y 20 Nov 2002 18:51:06 -0000 *************** *** 138,144 **** %token NOLOAD DSECT COPY INFO OVERLAY %token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY %token NEXT ! %token SIZEOF ADDR LOADADDR MAX_K MIN_K %token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS %token ORIGIN FILL %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS --- 138,144 ---- %token NOLOAD DSECT COPY INFO OVERLAY %token NAME LNAME DEFINED TARGET_K SEARCH_DIR MAP ENTRY %token NEXT ! %token SIZEOF SIZEOF_UNADJ ADDR LOADADDR MAX_K MIN_K %token STARTUP HLL SYSLIB FLOAT NOFLOAT NOCROSSREFS %token ORIGIN FILL %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS Index: ldlang.c =================================================================== RCS file: /cvs/src/src/ld/ldlang.c,v retrieving revision 1.103 diff -c -r1.103 ldlang.c *** ldlang.c 30 Oct 2002 03:57:38 -0000 1.103 --- ldlang.c 20 Nov 2002 18:51:10 -0000 *************** *** 751,756 **** --- 751,758 ---- lookup->section_alignment = -1; lookup->load_base = (union etree_union *) NULL; lookup->update_dot_tree = NULL; + lookup->size_adj = (union etree_union *) NULL; + lookup->last_orphan = (lang_output_section_statement_type *) NULL; lookup->phdrs = NULL; lang_statement_append (&lang_output_section_statement, Index: ldlang.h =================================================================== RCS file: /cvs/src/src/ld/ldlang.h,v retrieving revision 1.23 diff -c -r1.23 ldlang.h *** ldlang.h 10 Oct 2002 15:59:10 -0000 1.23 --- ldlang.h 20 Nov 2002 18:51:10 -0000 *************** *** 141,146 **** --- 141,155 ---- to move '.' past all the overlaid sections. */ union etree_union *update_dot_tree; + /* These two members are used when sorting orphans after this + section. size_adj contains an expression tree representing + the change in effective size of this section caused by adding + the orphans. last_orphan points to the last orphan section + that was sorted after this section. It is used to compute the + load address of the next orphan sorted after this section. */ + union etree_union *size_adj; + struct lang_output_section_statement_struct *last_orphan; + struct lang_output_section_phdr_list *phdrs; } lang_output_section_statement_type; Index: emultempl/elf32.em =================================================================== RCS file: /cvs/src/src/ld/emultempl/elf32.em,v retrieving revision 1.84 diff -c -r1.84 elf32.em *** emultempl/elf32.em 30 Oct 2002 03:57:39 -0000 1.84 --- emultempl/elf32.em 20 Nov 2002 18:51:12 -0000 *************** *** 1090,1095 **** --- 1090,1096 ---- lang_statement_list_type *old; lang_statement_list_type add; etree_type *address; + etree_type *load_base; const char *secname; const char *ps = NULL; lang_output_section_statement_type *os; *************** *** 1175,1183 **** && (hold_rel.os != NULL || (hold_rel.os = output_rel_find (s)) != NULL)) place = &hold_rel; ! else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY ! && HAVE_SECTION (hold_rodata, ".rodata")) ! place = &hold_rodata; else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY) && hold_text.os != NULL) place = &hold_text; --- 1176,1188 ---- && (hold_rel.os != NULL || (hold_rel.os = output_rel_find (s)) != NULL)) place = &hold_rel; ! else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY) ! { ! /* If we have .rodata, fine. If not, assume we can put read-only ! data into .text. */ ! place = HAVE_SECTION (hold_rodata, ".rodata") ? &hold_rodata ! : &hold_text; ! } else if ((s->flags & (SEC_CODE | SEC_READONLY)) == (SEC_CODE | SEC_READONLY) && hold_text.os != NULL) place = &hold_text; *************** *** 1232,1242 **** else address = NULL; os = lang_enter_output_section_statement (secname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, ! (etree_type *) NULL); lang_add_section (&os->children, s, os, file); --- 1237,1269 ---- else address = NULL; + /* If the output section (or the last orphan that sorted with it) + we're sorting with has an AT expression, then we need to copy + that AT expression, adjusting for the size of the previous + section. + + Note: we need to use the unadjusted size because by the time + the tree can be folded, the original parent section will have + accumulated effective size adjustments for all the orphans, + which will cause the first (and subsequent) orphans to be + mis-placed. */ + if (place != NULL && place->os->load_base != NULL) + { + lang_output_section_statement_type *sort_os; + + sort_os = place->os->last_orphan ? place->os->last_orphan + : place->os; + load_base = exp_binop ('+', sort_os->load_base, + exp_nameop (SIZEOF_UNADJ, sort_os->name)); + } + else + load_base = NULL; + os = lang_enter_output_section_statement (secname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, ! load_base); lang_add_section (&os->children, s, os, file); *************** *** 1257,1262 **** --- 1284,1305 ---- sprintf (symname, "__stop_%s", secname); lang_add_assignment (exp_assop ('=', symname, exp_nameop (NAME, "."))); + } + + if (place != NULL) + { + /* By sorting the orphan after place->os, we effectively changed + the size of that section. Adjust the size of the section to + reflect the additional output. */ + if (place->os->size_adj == NULL) + place->os->size_adj = exp_nameop (SIZEOF, os->name); + else + place->os->size_adj = exp_binop ('+', place->os->size_adj, + exp_nameop (SIZEOF, os->name)); + + /* Record this orphan in case there are any more that are + sorted with this parent. */ + place->os->last_orphan = os; } /* Restore the global list pointer. */ Index: testsuite/ld-scripts/refsec-lma.exp =================================================================== RCS file: testsuite/ld-scripts/refsec-lma.exp diff -N testsuite/ld-scripts/refsec-lma.exp *** /dev/null 1 Jan 1970 00:00:00 -0000 --- testsuite/ld-scripts/refsec-lma.exp 20 Nov 2002 18:51:13 -0000 *************** *** 0 **** --- 1,85 ---- + # Test C-referenceable sections when explicit LMAs are used + # in the linker script. + # + # Written by: Jason Thorpe + # Based on phdrs.exp by Ian Taylor. + # + # Copyright 2002 + # Free Software Foundation, Inc. + # + # This file is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation; either version 2 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + # This tests a feature found in the ELF back-end. + if { ![istarget *-*-sysv4*] \ + && ![istarget *-*-unixware*] \ + && ![istarget *-*-elf*] \ + && ![istarget *-*-eabi*] \ + && ![istarget hppa*64*-*-hpux*] \ + && ![istarget *-*-linux*] \ + && ![istarget *-*-netbsd*] \ + && ![istarget *-*-irix5*] \ + && ![istarget *-*-irix6*] \ + && ![istarget *-*-solaris2*] } { + return + } + + if { [istarget *-*-linux*aout*] \ + || [istarget *-*-linux*oldld*] } { + return + } + + if { ![istarget *-*-netbsdelf*] \ + && [[istarget *-*-netbsd*aout*] \ + || [istarget *-*-netbsdpe*] \ + || [istarget arm*-*-netbsd*] \ + || [istarget sparc-*-netbsd*] \ + || [istarget i*86-*-netbsd*] \ + || [istarget m68*-*-netbsd*] \ + || [istarget vax*-*-netbsd*] \ + || [istarget ns32k-*-netbsd*]] } { + return + } + + set testname "C-referenceable sections with explicit LMA" + + if ![ld_assemble $as $srcdir/$subdir/refsec-lma.s tmpdir/refsec-lma.o] { + unresolved $testname + return + } + + # We don't particularly care about the Program headers. The information we + # want is easily found in the Section headers. + set refsec_regexp \ + ".*Sections:.*\.text.*00000008.*00800000.*10800000.*link_set_1.*00000004.*00800008.*10800008.*link_set_2.*00000004.*0080000c.*1080000c.*\.data.*00000004.*00801000.*10801000.*\.bss.*00000004.*00801004.*00801004.*SYMBOL TABLE:.*0080000c.*g.*__stop_link_set_1.*00800010.*g.*__stop_link_set_2.*00800008.*g.*__start_link_set_1.*0080000c.*g.*__start_link_set_2" + + if ![ld_simple_link $ld tmpdir/refsec-lma "-T $srcdir/$subdir/refsec-lma.t tmpdir/refsec-lma.o"] { + fail $testname + } else { + if {[which $objdump] == 0} { + unresolved $testname + return + } + + verbose -log "$objdump --all-headers tmpdir/refsec-lma" + catch "exec $objdump --all-headers tmpdir/refsec-lma" exec_output + set exec_output [prune_warnings $exec_output] + verbose -log $exec_output + + if [regexp $refsec_regexp $exec_output] { + pass $testname + } else { + fail $testname + } + } Index: testsuite/ld-scripts/refsec-lma.s =================================================================== RCS file: testsuite/ld-scripts/refsec-lma.s diff -N testsuite/ld-scripts/refsec-lma.s *** /dev/null 1 Jan 1970 00:00:00 -0000 --- testsuite/ld-scripts/refsec-lma.s 20 Nov 2002 18:51:13 -0000 *************** *** 0 **** --- 1,17 ---- + .text + .long 1 + + .section .rodata + .long 2 + + .data + .long 3 + + .section .bss + .long 0 + + .section link_set_1,"a" + .long 4 + + .section link_set_2,"a" + .long 5 Index: testsuite/ld-scripts/refsec-lma.t =================================================================== RCS file: testsuite/ld-scripts/refsec-lma.t diff -N testsuite/ld-scripts/refsec-lma.t *** /dev/null 1 Jan 1970 00:00:00 -0000 --- testsuite/ld-scripts/refsec-lma.t 20 Nov 2002 18:51:13 -0000 *************** *** 0 **** --- 1,12 ---- + SECTIONS + { + .text (0x00800000) : + AT (0x10800000) + { *(.text) *(.rodata) } + . = ALIGN(0x1000); + .data : + AT ((LOADADDR(.text) + SIZEOF(.text) + (0x1000 - 1)) & ~(0x1000 - 1)) + { *(.data) } + .bss : { *(.bss) *(COMMON) } + /DISCARD/ : { *(.*) } + }