forked from Imagelibrary/binutils-gdb
* ldlang.c (insert_pad): Make use of an existing pad statement if
available. Move code calculating alignment, adjusting section alignment power, and adjusting dot to .. (size_input_section): .. here. Remove unused relax param. (lang_size_sections): Change boolean `relax' param to boolean *. Adjust call to size_input_section. Make use of insert_pad to place pad after the assignment statement. If relaxing, zap padding statements. (reset_memory_regions): Reset output_bfd section sizes too. (relax_again): Move to.. (lang_process): ..here. Adjust call to lang_size_sections, and remove duplicated code. * ldlang.h (lang_size_sections): Change `relax' param to boolean *.
This commit is contained in:
16
ld/ChangeLog
16
ld/ChangeLog
@@ -1,3 +1,19 @@
|
|||||||
|
2001-08-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* ldlang.c (insert_pad): Make use of an existing pad statement if
|
||||||
|
available. Move code calculating alignment, adjusting section
|
||||||
|
alignment power, and adjusting dot to ..
|
||||||
|
(size_input_section): .. here. Remove unused relax param.
|
||||||
|
(lang_size_sections): Change boolean `relax' param to boolean *.
|
||||||
|
Adjust call to size_input_section. Make use of insert_pad to
|
||||||
|
place pad after the assignment statement. If relaxing, zap
|
||||||
|
padding statements.
|
||||||
|
(reset_memory_regions): Reset output_bfd section sizes too.
|
||||||
|
(relax_again): Move to..
|
||||||
|
(lang_process): ..here. Adjust call to lang_size_sections, and
|
||||||
|
remove duplicated code.
|
||||||
|
* ldlang.h (lang_size_sections): Change `relax' param to boolean *.
|
||||||
|
|
||||||
2001-08-17 Alan Modra <amodra@bigpond.net.au>
|
2001-08-17 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* ld.texinfo: Document that fill values now use the four least
|
* ld.texinfo: Document that fill values now use the four least
|
||||||
|
|||||||
198
ld/ldlang.c
198
ld/ldlang.c
@@ -119,12 +119,12 @@ static void print_statement
|
|||||||
static void print_statement_list
|
static void print_statement_list
|
||||||
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
|
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *));
|
||||||
static void print_statements PARAMS ((void));
|
static void print_statements PARAMS ((void));
|
||||||
static bfd_vma insert_pad
|
static void insert_pad
|
||||||
PARAMS ((lang_statement_union_type **, fill_type,
|
PARAMS ((lang_statement_union_type **, fill_type,
|
||||||
unsigned int, asection *, bfd_vma));
|
unsigned int, asection *, bfd_vma));
|
||||||
static bfd_vma size_input_section
|
static bfd_vma size_input_section
|
||||||
PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
|
PARAMS ((lang_statement_union_type **, lang_output_section_statement_type *,
|
||||||
fill_type, bfd_vma, boolean));
|
fill_type, bfd_vma));
|
||||||
static void lang_finish PARAMS ((void));
|
static void lang_finish PARAMS ((void));
|
||||||
static void ignore_bfd_errors PARAMS ((const char *, ...));
|
static void ignore_bfd_errors PARAMS ((const char *, ...));
|
||||||
static void lang_check PARAMS ((void));
|
static void lang_check PARAMS ((void));
|
||||||
@@ -2626,87 +2626,94 @@ dprint_statement (s, n)
|
|||||||
config.map_file = map_save;
|
config.map_file = map_save;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_vma
|
static void
|
||||||
insert_pad (this_ptr, fill, power, output_section_statement, dot)
|
insert_pad (ptr, fill, alignment_needed, output_section, dot)
|
||||||
lang_statement_union_type **this_ptr;
|
lang_statement_union_type **ptr;
|
||||||
fill_type fill;
|
fill_type fill;
|
||||||
unsigned int power;
|
unsigned int alignment_needed;
|
||||||
asection *output_section_statement;
|
asection *output_section;
|
||||||
bfd_vma dot;
|
bfd_vma dot;
|
||||||
{
|
{
|
||||||
/* Align this section first to the
|
lang_statement_union_type *pad;
|
||||||
input sections requirement, then
|
size_t ptr_off;
|
||||||
to the output section's requirement.
|
|
||||||
If this alignment is > than any seen before,
|
|
||||||
then record it too. Perform the alignment by
|
|
||||||
inserting a magic 'padding' statement. */
|
|
||||||
|
|
||||||
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
/* ptr_off is zero, but let's not be too fast and loose with
|
||||||
ldfile_output_machine);
|
pointers. */
|
||||||
unsigned int alignment_needed = align_power (dot, power) - dot;
|
ptr_off = ((char *) &((lang_statement_union_type *) 0)->header.next
|
||||||
|
- (char *) 0);
|
||||||
if (alignment_needed != 0)
|
if (ptr != &statement_list.head
|
||||||
|
&& ((pad = (lang_statement_union_type *) ((char *) ptr - ptr_off))
|
||||||
|
->header.type == lang_padding_statement_enum)
|
||||||
|
&& pad->padding_statement.output_section == output_section)
|
||||||
{
|
{
|
||||||
lang_statement_union_type *new =
|
/* Use the existing pad statement. The above test on output
|
||||||
((lang_statement_union_type *)
|
section is probably redundant, but it doesn't hurt to check. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Make a new padding statement, linked into existing chain. */
|
||||||
|
pad = ((lang_statement_union_type *)
|
||||||
stat_alloc (sizeof (lang_padding_statement_type)));
|
stat_alloc (sizeof (lang_padding_statement_type)));
|
||||||
|
pad->header.next = *ptr;
|
||||||
/* Link into existing chain. */
|
*ptr = pad;
|
||||||
new->header.next = *this_ptr;
|
pad->header.type = lang_padding_statement_enum;
|
||||||
*this_ptr = new;
|
pad->padding_statement.output_section = output_section;
|
||||||
new->header.type = lang_padding_statement_enum;
|
pad->padding_statement.fill = fill;
|
||||||
new->padding_statement.output_section = output_section_statement;
|
|
||||||
new->padding_statement.output_offset =
|
|
||||||
dot - output_section_statement->vma;
|
|
||||||
new->padding_statement.fill = fill;
|
|
||||||
new->padding_statement.size = alignment_needed * opb;
|
|
||||||
}
|
}
|
||||||
|
pad->padding_statement.output_offset = dot - output_section->vma;
|
||||||
/* Remember the most restrictive alignment. */
|
pad->padding_statement.size = alignment_needed;
|
||||||
if (power > output_section_statement->alignment_power)
|
output_section->_raw_size += alignment_needed;
|
||||||
{
|
|
||||||
output_section_statement->alignment_power = power;
|
|
||||||
}
|
|
||||||
output_section_statement->_raw_size += alignment_needed * opb;
|
|
||||||
|
|
||||||
return dot + alignment_needed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Work out how much this section will move the dot point. */
|
/* Work out how much this section will move the dot point. */
|
||||||
|
|
||||||
static bfd_vma
|
static bfd_vma
|
||||||
size_input_section (this_ptr, output_section_statement, fill, dot, relax)
|
size_input_section (this_ptr, output_section_statement, fill, dot)
|
||||||
lang_statement_union_type **this_ptr;
|
lang_statement_union_type **this_ptr;
|
||||||
lang_output_section_statement_type *output_section_statement;
|
lang_output_section_statement_type *output_section_statement;
|
||||||
fill_type fill;
|
fill_type fill;
|
||||||
bfd_vma dot;
|
bfd_vma dot;
|
||||||
boolean relax ATTRIBUTE_UNUSED;
|
|
||||||
{
|
{
|
||||||
lang_input_section_type *is = &((*this_ptr)->input_section);
|
lang_input_section_type *is = &((*this_ptr)->input_section);
|
||||||
asection *i = is->section;
|
asection *i = is->section;
|
||||||
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
|
||||||
ldfile_output_machine);
|
|
||||||
|
|
||||||
if (is->ifile->just_syms_flag == false)
|
if (is->ifile->just_syms_flag == false)
|
||||||
{
|
{
|
||||||
if (output_section_statement->subsection_alignment != -1)
|
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
||||||
i->alignment_power =
|
ldfile_output_machine);
|
||||||
output_section_statement->subsection_alignment;
|
unsigned int alignment_needed;
|
||||||
|
asection *o;
|
||||||
|
|
||||||
dot = insert_pad (this_ptr, fill, i->alignment_power,
|
/* Align this section first to the input sections requirement,
|
||||||
output_section_statement->bfd_section, dot);
|
then to the output section's requirement. If this alignment
|
||||||
|
is greater than any seen before, then record it too. Perform
|
||||||
|
the alignment by inserting a magic 'padding' statement. */
|
||||||
|
|
||||||
|
if (output_section_statement->subsection_alignment != -1)
|
||||||
|
i->alignment_power = output_section_statement->subsection_alignment;
|
||||||
|
|
||||||
|
o = output_section_statement->bfd_section;
|
||||||
|
if (o->alignment_power < i->alignment_power)
|
||||||
|
o->alignment_power = i->alignment_power;
|
||||||
|
|
||||||
|
alignment_needed = align_power (dot, i->alignment_power) - dot;
|
||||||
|
|
||||||
|
if (alignment_needed != 0)
|
||||||
|
{
|
||||||
|
insert_pad (this_ptr, fill, alignment_needed * opb, o, dot);
|
||||||
|
dot += alignment_needed;
|
||||||
|
}
|
||||||
|
|
||||||
/* Remember where in the output section this input section goes. */
|
/* Remember where in the output section this input section goes. */
|
||||||
|
|
||||||
i->output_offset = dot - output_section_statement->bfd_section->vma;
|
i->output_offset = dot - o->vma;
|
||||||
|
|
||||||
/* Mark how big the output section must be to contain this now. */
|
/* Mark how big the output section must be to contain this now. */
|
||||||
if (i->_cooked_size != 0)
|
if (i->_cooked_size != 0)
|
||||||
dot += i->_cooked_size / opb;
|
dot += i->_cooked_size / opb;
|
||||||
else
|
else
|
||||||
dot += i->_raw_size / opb;
|
dot += i->_raw_size / opb;
|
||||||
output_section_statement->bfd_section->_raw_size =
|
o->_raw_size = (dot - o->vma) * opb;
|
||||||
(dot - output_section_statement->bfd_section->vma) * opb;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2777,11 +2784,6 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This variable indicates whether bfd_relax_section should be called
|
|
||||||
again. */
|
|
||||||
|
|
||||||
static boolean relax_again;
|
|
||||||
|
|
||||||
/* Make sure the new address is within the region. We explicitly permit the
|
/* Make sure the new address is within the region. We explicitly permit the
|
||||||
current address to be at the exact end of the region when the address is
|
current address to be at the exact end of the region when the address is
|
||||||
non-zero, in case the region is at the end of addressable memory and the
|
non-zero, in case the region is at the end of addressable memory and the
|
||||||
@@ -2828,7 +2830,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
lang_statement_union_type **prev;
|
lang_statement_union_type **prev;
|
||||||
fill_type fill;
|
fill_type fill;
|
||||||
bfd_vma dot;
|
bfd_vma dot;
|
||||||
boolean relax;
|
boolean *relax;
|
||||||
{
|
{
|
||||||
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
|
||||||
ldfile_output_machine);
|
ldfile_output_machine);
|
||||||
@@ -2947,8 +2949,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
os->bfd_section->output_offset = 0;
|
os->bfd_section->output_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) lang_size_sections (os->children.head, os,
|
lang_size_sections (os->children.head, os, &os->children.head,
|
||||||
&os->children.head,
|
|
||||||
os->fill, dot, relax);
|
os->fill, dot, relax);
|
||||||
|
|
||||||
/* Put the section within the requested block size, or
|
/* Put the section within the requested block size, or
|
||||||
@@ -3020,8 +3021,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
dot = lang_size_sections (constructor_list.head,
|
dot = lang_size_sections (constructor_list.head,
|
||||||
output_section_statement,
|
output_section_statement,
|
||||||
&s->wild_statement.children.head,
|
&s->wild_statement.children.head,
|
||||||
fill,
|
fill, dot, relax);
|
||||||
dot, relax);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case lang_data_statement_enum:
|
case lang_data_statement_enum:
|
||||||
@@ -3113,12 +3113,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
if (! bfd_relax_section (i->owner, i, &link_info, &again))
|
if (! bfd_relax_section (i->owner, i, &link_info, &again))
|
||||||
einfo (_("%P%F: can't relax section: %E\n"));
|
einfo (_("%P%F: can't relax section: %E\n"));
|
||||||
if (again)
|
if (again)
|
||||||
relax_again = true;
|
*relax = true;
|
||||||
}
|
}
|
||||||
dot = size_input_section (prev,
|
dot = size_input_section (prev, output_section_statement,
|
||||||
output_section_statement,
|
output_section_statement->fill, dot);
|
||||||
output_section_statement->fill,
|
|
||||||
dot, relax);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case lang_input_statement_enum:
|
case lang_input_statement_enum:
|
||||||
@@ -3141,31 +3139,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
|
|
||||||
if (newdot != dot)
|
if (newdot != dot)
|
||||||
{
|
{
|
||||||
/* The assignment changed dot. Insert a pad. */
|
|
||||||
if (output_section_statement == abs_output_section)
|
if (output_section_statement == abs_output_section)
|
||||||
{
|
{
|
||||||
/* If we don't have an output section, then just adjust
|
/* If we don't have an output section, then just adjust
|
||||||
the default memory address. */
|
the default memory address. */
|
||||||
lang_memory_region_lookup ("*default*")->current = newdot;
|
lang_memory_region_lookup ("*default*")->current = newdot;
|
||||||
}
|
}
|
||||||
else if (!relax)
|
else
|
||||||
{
|
{
|
||||||
lang_statement_union_type *new =
|
/* Insert a pad after this statement. We can't
|
||||||
((lang_statement_union_type *)
|
put the pad before when relaxing, in case the
|
||||||
stat_alloc (sizeof (lang_padding_statement_type)));
|
assignment references dot. */
|
||||||
|
insert_pad (&s->header.next, fill, (newdot - dot) * opb,
|
||||||
|
output_section_statement->bfd_section, dot);
|
||||||
|
|
||||||
/* Link into existing chain. */
|
/* Don't neuter the pad below when relaxing. */
|
||||||
new->header.next = *prev;
|
s = s->header.next;
|
||||||
*prev = new;
|
|
||||||
new->header.type = lang_padding_statement_enum;
|
|
||||||
new->padding_statement.output_section =
|
|
||||||
output_section_statement->bfd_section;
|
|
||||||
new->padding_statement.output_offset =
|
|
||||||
dot - output_section_statement->bfd_section->vma;
|
|
||||||
new->padding_statement.fill = fill;
|
|
||||||
new->padding_statement.size = (newdot - dot) * opb;
|
|
||||||
output_section_statement->bfd_section->_raw_size +=
|
|
||||||
new->padding_statement.size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dot = newdot;
|
dot = newdot;
|
||||||
@@ -3174,13 +3163,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case lang_padding_statement_enum:
|
case lang_padding_statement_enum:
|
||||||
/* If we are relaxing, and this is not the first pass, some
|
if (relax)
|
||||||
padding statements may have been inserted during previous
|
{
|
||||||
passes. We may have to move the padding statement to a new
|
/* If we are relaxing, and this is not the first pass,
|
||||||
location if dot has a different value at this point in this
|
we need to allow padding to shrink. If padding is
|
||||||
pass than it did at this point in the previous pass. */
|
needed on this pass, it will be added back in. */
|
||||||
s->padding_statement.output_offset =
|
s->padding_statement.size = 0;
|
||||||
dot - output_section_statement->bfd_section->vma;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
dot += s->padding_statement.size / opb;
|
dot += s->padding_statement.size / opb;
|
||||||
output_section_statement->bfd_section->_raw_size +=
|
output_section_statement->bfd_section->_raw_size +=
|
||||||
s->padding_statement.size;
|
s->padding_statement.size;
|
||||||
@@ -3982,6 +3973,7 @@ static void
|
|||||||
reset_memory_regions ()
|
reset_memory_regions ()
|
||||||
{
|
{
|
||||||
lang_memory_region_type *p = lang_memory_region_list;
|
lang_memory_region_type *p = lang_memory_region_list;
|
||||||
|
asection *o;
|
||||||
|
|
||||||
for (p = lang_memory_region_list;
|
for (p = lang_memory_region_list;
|
||||||
p != (lang_memory_region_type *) NULL;
|
p != (lang_memory_region_type *) NULL;
|
||||||
@@ -3990,6 +3982,9 @@ reset_memory_regions ()
|
|||||||
p->old_length = (bfd_size_type) (p->current - p->origin);
|
p->old_length = (bfd_size_type) (p->current - p->origin);
|
||||||
p->current = p->origin;
|
p->current = p->origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (o = output_bfd->sections; o != NULL; o = o->next)
|
||||||
|
o->_raw_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the wild pattern was marked KEEP, the member sections
|
/* If the wild pattern was marked KEEP, the member sections
|
||||||
@@ -4148,16 +4143,17 @@ lang_process ()
|
|||||||
section positions, since they will affect SIZEOF_HEADERS. */
|
section positions, since they will affect SIZEOF_HEADERS. */
|
||||||
lang_record_phdrs ();
|
lang_record_phdrs ();
|
||||||
|
|
||||||
|
/* 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. */
|
/* Now run around and relax if we can. */
|
||||||
if (command_line.relax)
|
if (command_line.relax)
|
||||||
{
|
{
|
||||||
/* First time round is a trial run to get the 'worst case'
|
|
||||||
addresses of the objects if there was no relaxing. */
|
|
||||||
lang_size_sections (statement_list.head,
|
|
||||||
abs_output_section,
|
|
||||||
&(statement_list.head), 0, (bfd_vma) 0, false);
|
|
||||||
|
|
||||||
/* Keep relaxing until bfd_relax_section gives up. */
|
/* Keep relaxing until bfd_relax_section gives up. */
|
||||||
|
boolean relax_again;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
reset_memory_regions ();
|
reset_memory_regions ();
|
||||||
@@ -4178,17 +4174,11 @@ lang_process ()
|
|||||||
globals are, so can make better guess. */
|
globals are, so can make better guess. */
|
||||||
lang_size_sections (statement_list.head,
|
lang_size_sections (statement_list.head,
|
||||||
abs_output_section,
|
abs_output_section,
|
||||||
&(statement_list.head), 0, (bfd_vma) 0, true);
|
&(statement_list.head), 0, (bfd_vma) 0,
|
||||||
|
&relax_again);
|
||||||
}
|
}
|
||||||
while (relax_again);
|
while (relax_again);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Size up the sections. */
|
|
||||||
lang_size_sections (statement_list.head,
|
|
||||||
abs_output_section,
|
|
||||||
&(statement_list.head), 0, (bfd_vma) 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if anything special should be done now we know how big
|
/* See if anything special should be done now we know how big
|
||||||
everything is. */
|
everything is. */
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ extern bfd_vma lang_size_sections
|
|||||||
PARAMS ((lang_statement_union_type *s,
|
PARAMS ((lang_statement_union_type *s,
|
||||||
lang_output_section_statement_type *output_section_statement,
|
lang_output_section_statement_type *output_section_statement,
|
||||||
lang_statement_union_type **prev, fill_type fill,
|
lang_statement_union_type **prev, fill_type fill,
|
||||||
bfd_vma dot, boolean relax));
|
bfd_vma dot, boolean *relax));
|
||||||
extern void lang_enter_group PARAMS ((void));
|
extern void lang_enter_group PARAMS ((void));
|
||||||
extern void lang_leave_group PARAMS ((void));
|
extern void lang_leave_group PARAMS ((void));
|
||||||
extern void lang_add_section
|
extern void lang_add_section
|
||||||
|
|||||||
Reference in New Issue
Block a user