This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH] avoid premature errors when linking with relaxation
- From: Bob Wilson <bwilson at tensilica dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 18 Feb 2003 10:07:59 -0800
- Subject: [PATCH] avoid premature errors when linking with relaxation
- Organization: Tensilica, Inc.
This patch fixes a problem that we have encountered with the linker. The
problem occurs when the original sections from the input files are too big to
fit in the space available in the output section, but when linker relaxation
is enabled, the sections shrink enough so that they fit. This should be OK
but the linker reports it as an error. Even if the final result of the
relaxation is still too big, the linker ends up reporting the error multiple
times, once for each iteration of relaxation.
The root cause is that lang_size_sections() always calls os_region_check().
It seems that os_region_check() should be called only for the last invocation
of lang_size_sections(). The patch adds another argument to
lang_size_sections to indicate whether os_region_check() should be called.
This patch has been tested extensively with the Xtensa port of binutils 2.11
and a fair amount with 2.12. After porting the patch to binutils mainline, I
built it for x86-linux and ran the ld testsuite without any regressions.
2003-02-18 Bob Wilson <bob.wilson@acm.org>
* ldlang.c (lang_size_sections_1): Add CHECK_REGIONS argument and only
call os_region_check when it is set.
(lang_size_sections): Add CHECK_REGIONS argument and pass it through to
lang_size_sections_1.
(lang_process): Change lang_size_sections calls to set CHECK_REGIONS
only for the last call, not on every relaxation iteration.
* ldlang.h (lang_size_sections): Update prototype.
* pe-dll.c (pe_dll_fill_sections): Set CHECK_REGIONS argument in calls
to lang_size_sections.
(pe_exe_fill_sections): Likewise.
* emultempl/elf32.em (gld${EMULATION_NAME}_finish): Likewise.
* emultempl/hppaelf.em (hppaelf_layout_sections_again): Likewise.
* emultempl/ppc64elf.em (ppc_before_allocation): Likewise.
(ppc_layout_sections_again): Likewise.
Index: ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.108
diff -c -3 -r1.108 ldlang.c
*** ldlang.c 2 Jan 2003 03:53:53 -0000 1.108
--- ldlang.c 15 Feb 2003 01:04:15 -0000
***************
*** 201,207 ****
struct memory_region_struct *, etree_type *, bfd_vma));
static bfd_vma lang_size_sections_1
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
! lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *));
typedef void (*callback_t)
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
--- 201,208 ----
struct memory_region_struct *, etree_type *, bfd_vma));
static bfd_vma lang_size_sections_1
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
! lang_statement_union_type **, fill_type *, bfd_vma, bfd_boolean *,
! bfd_boolean));
typedef void (*callback_t)
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
***************
*** 2971,2983 ****
/* Set the sizes for all the output sections. */
static bfd_vma
! lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
bfd_boolean *relax;
{
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
--- 2972,2986 ----
/* Set the sizes for all the output sections. */
static bfd_vma
! lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax,
! check_regions)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
bfd_boolean *relax;
+ bfd_boolean check_regions;
{
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
***************
*** 3046,3051 ****
--- 3049,3055 ----
& (SEC_ALLOC | SEC_LOAD)) != 0
&& (bfd_get_section_flags (output_bfd, os->bfd_section)
& SEC_NEVER_LOAD) == 0
+ && check_regions
&& ! link_info.relocateable
&& strcmp (os->region->name, "*default*") == 0
&& lang_memory_region_list != NULL
***************
*** 3098,3104 ****
}
lang_size_sections_1 (os->children.head, os, &os->children.head,
! os->fill, dot, relax);
/* Put the section within the requested block size, or
align at the block boundary. */
--- 3102,3108 ----
}
lang_size_sections_1 (os->children.head, os, &os->children.head,
! os->fill, dot, relax, check_regions);
/* Put the section within the requested block size, or
align at the block boundary. */
***************
*** 3140,3147 ****
os->region->current = dot;
/* Make sure the new address is within the region. */
! os_region_check (os, os->region, os->addr_tree,
! os->bfd_section->vma);
/* If there's no load address specified, use the run
region as the load region. */
--- 3144,3152 ----
os->region->current = dot;
/* Make sure the new address is within the region. */
! if (check_regions)
! os_region_check (os, os->region, os->addr_tree,
! os->bfd_section->vma);
/* If there's no load address specified, use the run
region as the load region. */
***************
*** 3154,3161 ****
os->load_base = exp_intop (os->lma_region->current);
os->lma_region->current +=
os->bfd_section->_raw_size / opb;
! os_region_check (os, os->lma_region, NULL,
! os->bfd_section->lma);
}
}
}
--- 3159,3167 ----
os->load_base = exp_intop (os->lma_region->current);
os->lma_region->current +=
os->bfd_section->_raw_size / opb;
! if (check_regions)
! os_region_check (os, os->lma_region, NULL,
! os->bfd_section->lma);
}
}
}
***************
*** 3165,3171 ****
dot = lang_size_sections_1 (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
! fill, dot, relax);
break;
case lang_data_statement_enum:
--- 3171,3177 ----
dot = lang_size_sections_1 (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
! fill, dot, relax, check_regions);
break;
case lang_data_statement_enum:
***************
*** 3229,3235 ****
dot = lang_size_sections_1 (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
! fill, dot, relax);
break;
--- 3235,3241 ----
dot = lang_size_sections_1 (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
! fill, dot, relax, check_regions);
break;
***************
*** 3327,3333 ****
dot = lang_size_sections_1 (s->group_statement.children.head,
output_section_statement,
&s->group_statement.children.head,
! fill, dot, relax);
break;
default:
--- 3333,3339 ----
dot = lang_size_sections_1 (s->group_statement.children.head,
output_section_statement,
&s->group_statement.children.head,
! fill, dot, relax, check_regions);
break;
default:
***************
*** 3344,3362 ****
}
bfd_vma
! lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
bfd_boolean *relax;
{
bfd_vma result;
exp_data_seg.phase = exp_dataseg_none;
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
! dot, relax);
if (exp_data_seg.phase == exp_dataseg_end_seen)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
--- 3350,3370 ----
}
bfd_vma
! lang_size_sections (s, output_section_statement, prev, fill, dot, relax,
! check_regions)
lang_statement_union_type *s;
lang_output_section_statement_type *output_section_statement;
lang_statement_union_type **prev;
fill_type *fill;
bfd_vma dot;
bfd_boolean *relax;
+ bfd_boolean check_regions;
{
bfd_vma result;
exp_data_seg.phase = exp_dataseg_none;
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
! dot, relax, check_regions);
if (exp_data_seg.phase == exp_dataseg_end_seen)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
***************
*** 3372,3378 ****
{
exp_data_seg.phase = exp_dataseg_adjust;
result = lang_size_sections_1 (s, output_section_statement, prev,
! fill, dot, relax);
}
}
--- 3380,3386 ----
{
exp_data_seg.phase = exp_dataseg_adjust;
result = lang_size_sections_1 (s, output_section_statement, prev,
! fill, dot, relax, check_regions);
}
}
***************
*** 4348,4354 ****
/* Size up the sections. */
lang_size_sections (statement_list.head,
abs_output_section,
! &statement_list.head, 0, (bfd_vma) 0, NULL);
/* Now run around and relax if we can. */
if (command_line.relax)
--- 4356,4363 ----
/* Size up the sections. */
lang_size_sections (statement_list.head,
abs_output_section,
! &statement_list.head, 0, (bfd_vma) 0, NULL,
! command_line.relax ? FALSE : TRUE);
/* Now run around and relax if we can. */
if (command_line.relax)
***************
*** 4377,4385 ****
lang_size_sections (statement_list.head,
abs_output_section,
&statement_list.head, 0, (bfd_vma) 0,
! &relax_again);
}
while (relax_again);
}
/* See if anything special should be done now we know how big
--- 4386,4404 ----
lang_size_sections (statement_list.head,
abs_output_section,
&statement_list.head, 0, (bfd_vma) 0,
! &relax_again, FALSE);
}
while (relax_again);
+
+ /* Final extra sizing to report errors. */
+ lang_reset_memory_regions ();
+ lang_do_assignments (statement_list.head,
+ abs_output_section,
+ (fill_type *) 0, (bfd_vma) 0);
+ lang_size_sections (statement_list.head,
+ abs_output_section,
+ &statement_list.head, 0, (bfd_vma) 0,
+ NULL, TRUE);
}
/* See if anything special should be done now we know how big
Index: ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.25
diff -c -3 -r1.25 ldlang.h
*** ldlang.h 8 Dec 2002 03:56:04 -0000 1.25
--- ldlang.h 15 Feb 2003 01:04:15 -0000
***************
*** 476,482 ****
PARAMS ((lang_statement_union_type *s,
lang_output_section_statement_type *output_section_statement,
lang_statement_union_type **prev, fill_type *fill,
! bfd_vma dot, bfd_boolean *relax));
extern void lang_enter_group
PARAMS ((void));
extern void lang_leave_group
--- 476,482 ----
PARAMS ((lang_statement_union_type *s,
lang_output_section_statement_type *output_section_statement,
lang_statement_union_type **prev, fill_type *fill,
! bfd_vma dot, bfd_boolean *relax, bfd_boolean check_regions));
extern void lang_enter_group
PARAMS ((void));
extern void lang_leave_group
Index: pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.54
diff -c -3 -r1.54 pe-dll.c
*** pe-dll.c 28 Jan 2003 11:39:43 -0000 1.54
--- pe-dll.c 15 Feb 2003 01:04:15 -0000
***************
*** 2694,2700 ****
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Redo special stuff. */
ldemul_after_allocation ();
--- 2694,2700 ----
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
***************
*** 2728,2734 ****
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Redo special stuff. */
ldemul_after_allocation ();
--- 2728,2734 ----
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
Index: emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.90
diff -c -3 -r1.90 elf32.em
*** emultempl/elf32.em 3 Feb 2003 17:47:23 -0000 1.90
--- emultempl/elf32.em 15 Feb 2003 01:04:15 -0000
***************
*** 1427,1433 ****
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Redo special stuff. */
ldemul_after_allocation ();
--- 1427,1433 ----
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
Index: emultempl/hppaelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/hppaelf.em,v
retrieving revision 1.26
diff -c -3 -r1.26 hppaelf.em
*** emultempl/hppaelf.em 11 Feb 2003 02:20:30 -0000 1.26
--- emultempl/hppaelf.em 15 Feb 2003 01:04:15 -0000
***************
*** 231,237 ****
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Redo special stuff. */
ldemul_after_allocation ();
--- 231,237 ----
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
Index: emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.14
diff -c -3 -r1.14 ppc64elf.em
*** emultempl/ppc64elf.em 17 Feb 2003 22:49:24 -0000 1.14
--- emultempl/ppc64elf.em 18 Feb 2003 17:28:01 -0000
***************
*** 118,124 ****
/* Size the sections. This is premature, but we want to know the
TLS segment layout so that certain optimizations can be done. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
{
--- 118,124 ----
/* Size the sections. This is premature, but we want to know the
TLS segment layout so that certain optimizations can be done. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
{
***************
*** 273,279 ****
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL);
/* Recalculate TOC base. */
ldemul_after_allocation ();
--- 273,279 ----
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
! &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
/* Recalculate TOC base. */
ldemul_after_allocation ();