PATCH: Fix the relax finalize pass
H. J. Lu
hjl@lucon.org
Wed May 14 22:53:00 GMT 2003
On Wed, May 14, 2003 at 12:53:30AM -0700, Richard Henderson wrote:
> On Tue, May 13, 2003 at 04:36:47PM -0700, H. J. Lu wrote:
> > I am not sure if it is the right usage of LTOFF22X
>
> It is. You're allowed to use it with any operand whatsoever.
>
>
The problem is linker keeps changing data segment address after the
relax finalize pass starts. It makes the GP calculation in the relax
finalize pass invalid. This patch tries to avoid it.
H.J.
-------------- next part --------------
2003-05-14 H.J. Lu <hongjiu.lu@intel.com>
* ldlang.c (lang_size_sections_1): Take one more argument to
indicate if the relax finalize pass is needed.
(lang_size_sections): Updated.
(lang_process): Likewise.
* ldlang.h (lang_size_sections_1): Likewise.
* pe-dll.c (pe_dll_fill_sections): Likewise.
(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.
* ldlang.c (lang_size_sections): Don't adjust data segment
address after the relax finalize pass starts.
(lang_process): Perform the relax finalize pass only when
needed. Finalize addresses before the relax finalize pass.
--- ld/emultempl/elf32.em.final 2003-05-09 08:13:31.000000000 -0700
+++ ld/emultempl/elf32.em 2003-05-14 15:21:48.000000000 -0700
@@ -1430,7 +1430,8 @@ gld${EMULATION_NAME}_finish ()
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL,
+ NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
--- ld/emultempl/hppaelf.em.final 2003-02-28 12:53:34.000000000 -0800
+++ ld/emultempl/hppaelf.em 2003-05-14 15:21:57.000000000 -0700
@@ -231,7 +231,8 @@ hppaelf_layout_sections_again ()
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL, NULL,
+ TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
--- ld/emultempl/ppc64elf.em.final 2003-02-28 12:53:38.000000000 -0800
+++ ld/emultempl/ppc64elf.em 2003-05-14 15:22:16.000000000 -0700
@@ -118,7 +118,8 @@ ppc_before_allocation ()
/* 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);
+ &stat_ptr->head, 0, (bfd_vma) 0,
+ NULL, NULL, TRUE);
if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
{
@@ -273,7 +274,8 @@ ppc_layout_sections_again ()
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+ &stat_ptr->head, 0, (bfd_vma) 0,
+ NULL, NULL, TRUE);
/* Recalculate TOC base. */
ldemul_after_allocation ();
--- ld/ldlang.c.final 2003-05-13 08:45:34.000000000 -0700
+++ ld/ldlang.c 2003-05-14 15:36:47.000000000 -0700
@@ -199,9 +199,10 @@ static void os_region_check
PARAMS ((lang_output_section_statement_type *,
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));
+ PARAMS ((lang_statement_union_type *,
+ lang_output_section_statement_type *,
+ lang_statement_union_type **, fill_type *, bfd_vma,
+ bfd_boolean *, bfd_boolean *, bfd_boolean));
typedef void (*callback_t)
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
@@ -2978,14 +2979,15 @@ os_region_check (os, region, tree, base)
/* 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_size_sections_1 (s, output_section_statement, prev, fill, dot,
+ relax, need_finalize_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 *need_finalize_relax;
bfd_boolean check_regions;
{
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
@@ -3123,8 +3125,10 @@ lang_size_sections_1 (s, output_section_
os->bfd_section->output_offset = 0;
}
- lang_size_sections_1 (os->children.head, os, &os->children.head,
- os->fill, dot, relax, check_regions);
+ lang_size_sections_1 (os->children.head, os,
+ &os->children.head, os->fill, dot,
+ relax, need_finalize_relax,
+ check_regions);
/* Put the section within the requested block size, or
align at the block boundary. */
@@ -3193,7 +3197,9 @@ lang_size_sections_1 (s, output_section_
dot = lang_size_sections_1 (constructor_list.head,
output_section_statement,
&s->wild_statement.children.head,
- fill, dot, relax, check_regions);
+ fill, dot, relax,
+ need_finalize_relax,
+ check_regions);
break;
case lang_data_statement_enum:
@@ -3257,7 +3263,9 @@ lang_size_sections_1 (s, output_section_
dot = lang_size_sections_1 (s->wild_statement.children.head,
output_section_statement,
&s->wild_statement.children.head,
- fill, dot, relax, check_regions);
+ fill, dot, relax,
+ need_finalize_relax,
+ check_regions);
break;
@@ -3286,6 +3294,7 @@ lang_size_sections_1 (s, output_section_
einfo (_("%P%F: can't relax section: %E\n"));
if (again)
*relax = TRUE;
+ *need_finalize_relax |= i->need_finalize_relax;
}
dot = size_input_section (prev, output_section_statement,
output_section_statement->fill, dot);
@@ -3355,7 +3364,9 @@ lang_size_sections_1 (s, output_section_
dot = lang_size_sections_1 (s->group_statement.children.head,
output_section_statement,
&s->group_statement.children.head,
- fill, dot, relax, check_regions);
+ fill, dot, relax,
+ need_finalize_relax,
+ check_regions);
break;
default:
@@ -3372,22 +3383,28 @@ lang_size_sections_1 (s, output_section_
}
bfd_vma
-lang_size_sections (s, output_section_statement, prev, fill, dot, relax,
- check_regions)
+lang_size_sections (s, output_section_statement, prev, fill, dot,
+ relax, need_finalize_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 *need_finalize_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)
+ result = lang_size_sections_1 (s, output_section_statement, prev,
+ fill, dot, relax, need_finalize_relax,
+ check_regions);
+
+ /* We can't change addresses after the relax finalize pass starts
+ since the relaxation may assume addresses won't be changes. */
+ if (!link_info.relax_finalizing
+ && exp_data_seg.phase == exp_dataseg_end_seen)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
a page could be saved in the data segment. */
@@ -3401,8 +3418,10 @@ lang_size_sections (s, output_section_st
&& first + last <= exp_data_seg.pagesize)
{
exp_data_seg.phase = exp_dataseg_adjust;
- result = lang_size_sections_1 (s, output_section_statement, prev,
- fill, dot, relax, check_regions);
+ result = lang_size_sections_1 (s, output_section_statement,
+ prev, fill, dot, relax,
+ need_finalize_relax,
+ check_regions);
}
}
@@ -4378,7 +4397,7 @@ lang_process ()
/* Size up the sections. */
lang_size_sections (statement_list.head,
abs_output_section,
- &statement_list.head, 0, (bfd_vma) 0, NULL,
+ &statement_list.head, 0, (bfd_vma) 0, NULL, NULL,
command_line.relax ? FALSE : TRUE);
/* Now run around and relax if we can. */
@@ -4386,6 +4405,7 @@ lang_process ()
{
/* Keep relaxing until bfd_relax_section gives up. */
bfd_boolean relax_again;
+ bfd_boolean need_finalize_relax;
do
{
@@ -4408,14 +4428,29 @@ lang_process ()
lang_size_sections (statement_list.head,
abs_output_section,
&statement_list.head, 0, (bfd_vma) 0,
- &relax_again, FALSE);
+ &relax_again, &need_finalize_relax,
+ FALSE);
/* If the normal relax is done and the relax finalize pass
is not performed yet, we perform another relax pass. */
- if (!relax_again && !link_info.relax_finalizing)
+ if (!relax_again
+ && need_finalize_relax
+ && !link_info.relax_finalizing)
{
link_info.relax_finalizing = TRUE;
relax_again = TRUE;
+ if (exp_data_seg.phase == exp_dataseg_adjust)
+ {
+ /* Make sure addresses are finalized. */
+ 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, NULL, TRUE);
+ }
}
}
while (relax_again);
@@ -4428,7 +4463,7 @@ lang_process ()
lang_size_sections (statement_list.head,
abs_output_section,
& statement_list.head, 0, (bfd_vma) 0,
- NULL, TRUE);
+ NULL, NULL, TRUE);
}
/* See if anything special should be done now we know how big
--- ld/ldlang.h.final 2003-03-04 11:11:00.000000000 -0800
+++ ld/ldlang.h 2003-05-14 15:09:58.000000000 -0700
@@ -482,7 +482,9 @@ extern bfd_vma lang_size_sections
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));
+ bfd_vma dot, bfd_boolean *relax,
+ bfd_boolean *need_finalize_relax,
+ bfd_boolean check_regions));
extern void lang_enter_group
PARAMS ((void));
extern void lang_leave_group
--- ld/pe-dll.c.final 2003-04-02 13:42:02.000000000 -0800
+++ ld/pe-dll.c 2003-05-14 15:10:50.000000000 -0700
@@ -2703,7 +2703,8 @@ pe_dll_fill_sections (abfd, info)
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+ &stat_ptr->head, 0, (bfd_vma) 0,
+ NULL, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
@@ -2738,7 +2739,8 @@ pe_exe_fill_sections (abfd, info)
/* Resize the sections. */
lang_size_sections (stat_ptr->head, abs_output_section,
- &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE);
+ &stat_ptr->head, 0, (bfd_vma) 0,
+ NULL, NULL, TRUE);
/* Redo special stuff. */
ldemul_after_allocation ();
More information about the Gcc
mailing list