Index: ldexp.c =================================================================== RCS file: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldexp.c,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 ldexp.c *** ldexp.c 2001/08/14 02:59:08 1.1.1.3 --- ldexp.c 2002/11/20 06:19:33 *************** *** 452,457 **** --- 452,458 ---- 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); *************** *** 460,465 **** --- 461,473 ---- 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: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldgram.y,v retrieving revision 1.4 diff -c -r1.4 ldgram.y *** ldgram.y 2001/08/14 04:43:12 1.4 --- ldgram.y 2002/11/20 06:19:38 *************** *** 130,136 **** %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 --- 130,136 ---- %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: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldlang.c,v retrieving revision 1.1.1.4 diff -c -r1.1.1.4 ldlang.c *** ldlang.c 2001/08/14 02:59:13 1.1.1.4 --- ldlang.c 2002/11/20 06:19:42 *************** *** 718,723 **** --- 718,725 ---- lookup->subsection_alignment = -1; lookup->section_alignment = -1; lookup->load_base = (union etree_union *) 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: /cvsroot/gnusrc/gnu/dist/toolchain/ld/ldlang.h,v retrieving revision 1.1.1.4 diff -c -r1.1.1.4 ldlang.h *** ldlang.h 2001/08/14 02:59:14 1.1.1.4 --- ldlang.h 2002/11/20 06:19:42 *************** *** 131,136 **** --- 131,139 ---- int section_alignment; /* alignment of start of section */ union etree_union *load_base; + 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: /cvsroot/gnusrc/gnu/dist/toolchain/ld/emultempl/elf32.em,v retrieving revision 1.3 diff -c -r1.3 elf32.em *** emultempl/elf32.em 2002/11/01 16:07:37 1.3 --- emultempl/elf32.em 2002/11/20 06:19:44 *************** *** 1005,1010 **** --- 1005,1011 ---- lang_statement_list_type *old; lang_statement_list_type add; etree_type *address; + etree_type *load_base; const char *secname; const char *outsecname; const char *ps = NULL; *************** *** 1073,1081 **** && (hold_rel.os != NULL || (hold_rel.os = output_rel_find ()) != 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; --- 1074,1086 ---- && (hold_rel.os != NULL || (hold_rel.os = output_rel_find ()) != 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; *************** *** 1133,1143 **** else address = NULL; os = lang_enter_output_section_statement (outsecname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, ! (etree_type *) NULL); wild_doit (&os->children, s, os, file); --- 1138,1164 ---- 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 it for the size of the previous + section. */ + 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 (outsecname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, ! load_base); wild_doit (&os->children, s, os, file); *************** *** 1158,1163 **** --- 1179,1200 ---- sprintf (symname, "__stop_%s", outsecname); 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. */