diff options
author | Alan Modra <amodra@gmail.com> | 2001-08-18 14:54:26 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2001-08-18 14:54:26 +0000 |
commit | b3327aadfd3c7e294aa72b5f772326499b8eed9c (patch) | |
tree | 511773070edd3ec4f0ecb629d7a164f84a5e211a /ld | |
parent | ceb160c895751b7115e070d94463067c1667368a (diff) | |
download | binutils-gdb-b3327aadfd3c7e294aa72b5f772326499b8eed9c.tar.gz |
* 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 *.
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 16 | ||||
-rw-r--r-- | ld/ldlang.c | 200 | ||||
-rw-r--r-- | ld/ldlang.h | 2 |
3 files changed, 112 insertions, 106 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index b10f2fd3e3f..b3c069df443 100644 --- a/ld/ChangeLog +++ b/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> * ld.texinfo: Document that fill values now use the four least diff --git a/ld/ldlang.c b/ld/ldlang.c index d9fa38fd347..905d08c1015 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -119,12 +119,12 @@ static void print_statement static void print_statement_list PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *)); static void print_statements PARAMS ((void)); -static bfd_vma insert_pad +static void insert_pad PARAMS ((lang_statement_union_type **, fill_type, unsigned int, asection *, bfd_vma)); static bfd_vma size_input_section 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 ignore_bfd_errors PARAMS ((const char *, ...)); static void lang_check PARAMS ((void)); @@ -2626,87 +2626,94 @@ dprint_statement (s, n) config.map_file = map_save; } -static bfd_vma -insert_pad (this_ptr, fill, power, output_section_statement, dot) - lang_statement_union_type **this_ptr; +static void +insert_pad (ptr, fill, alignment_needed, output_section, dot) + lang_statement_union_type **ptr; fill_type fill; - unsigned int power; - asection *output_section_statement; + unsigned int alignment_needed; + asection *output_section; bfd_vma dot; { - /* Align this section first to the - input sections requirement, then - 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, - ldfile_output_machine); - unsigned int alignment_needed = align_power (dot, power) - dot; - - if (alignment_needed != 0) + lang_statement_union_type *pad; + size_t ptr_off; + + /* ptr_off is zero, but let's not be too fast and loose with + pointers. */ + ptr_off = ((char *) &((lang_statement_union_type *) 0)->header.next + - (char *) 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 = - ((lang_statement_union_type *) - stat_alloc (sizeof (lang_padding_statement_type))); - - /* Link into existing chain. */ - new->header.next = *this_ptr; - *this_ptr = new; - new->header.type = lang_padding_statement_enum; - 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; + /* Use the existing pad statement. The above test on output + section is probably redundant, but it doesn't hurt to check. */ } - - /* Remember the most restrictive alignment. */ - if (power > output_section_statement->alignment_power) + else { - output_section_statement->alignment_power = power; + /* Make a new padding statement, linked into existing chain. */ + pad = ((lang_statement_union_type *) + stat_alloc (sizeof (lang_padding_statement_type))); + pad->header.next = *ptr; + *ptr = pad; + pad->header.type = lang_padding_statement_enum; + pad->padding_statement.output_section = output_section; + pad->padding_statement.fill = fill; } - output_section_statement->_raw_size += alignment_needed * opb; - - return dot + alignment_needed; + pad->padding_statement.output_offset = dot - output_section->vma; + pad->padding_statement.size = alignment_needed; + output_section->_raw_size += alignment_needed; } /* Work out how much this section will move the dot point. */ 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_output_section_statement_type *output_section_statement; fill_type fill; bfd_vma dot; - boolean relax ATTRIBUTE_UNUSED; { lang_input_section_type *is = &((*this_ptr)->input_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) { + unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); + unsigned int alignment_needed; + asection *o; + + /* Align this section first to the input sections requirement, + 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; + 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; - dot = insert_pad (this_ptr, fill, i->alignment_power, - output_section_statement->bfd_section, dot); + 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. */ - 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. */ if (i->_cooked_size != 0) dot += i->_cooked_size / opb; else dot += i->_raw_size / opb; - output_section_statement->bfd_section->_raw_size = - (dot - output_section_statement->bfd_section->vma) * opb; + o->_raw_size = (dot - o->vma) * opb; } 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 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 @@ -2828,7 +2830,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) lang_statement_union_type **prev; fill_type fill; bfd_vma dot; - boolean relax; + boolean *relax; { unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, ldfile_output_machine); @@ -2947,9 +2949,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) os->bfd_section->output_offset = 0; } - (void) lang_size_sections (os->children.head, os, - &os->children.head, - os->fill, dot, relax); + lang_size_sections (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. */ @@ -3020,8 +3021,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) dot = lang_size_sections (constructor_list.head, output_section_statement, &s->wild_statement.children.head, - fill, - dot, relax); + fill, dot, relax); break; 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)) einfo (_("%P%F: can't relax section: %E\n")); if (again) - relax_again = true; + *relax = true; } - dot = size_input_section (prev, - output_section_statement, - output_section_statement->fill, - dot, relax); + dot = size_input_section (prev, output_section_statement, + output_section_statement->fill, dot); } break; case lang_input_statement_enum: @@ -3141,31 +3139,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) if (newdot != dot) { - /* The assignment changed dot. Insert a pad. */ if (output_section_statement == abs_output_section) { /* If we don't have an output section, then just adjust the default memory address. */ lang_memory_region_lookup ("*default*")->current = newdot; } - else if (!relax) + else { - lang_statement_union_type *new = - ((lang_statement_union_type *) - stat_alloc (sizeof (lang_padding_statement_type))); - - /* Link into existing chain. */ - new->header.next = *prev; - *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; + /* Insert a pad after this statement. We can't + put the pad before when relaxing, in case the + assignment references dot. */ + insert_pad (&s->header.next, fill, (newdot - dot) * opb, + output_section_statement->bfd_section, dot); + + /* Don't neuter the pad below when relaxing. */ + s = s->header.next; } dot = newdot; @@ -3174,13 +3163,15 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) break; case lang_padding_statement_enum: - /* If we are relaxing, and this is not the first pass, some - padding statements may have been inserted during previous - passes. We may have to move the padding statement to a new - location if dot has a different value at this point in this - pass than it did at this point in the previous pass. */ - s->padding_statement.output_offset = - dot - output_section_statement->bfd_section->vma; + if (relax) + { + /* If we are relaxing, and this is not the first pass, + we need to allow padding to shrink. If padding is + needed on this pass, it will be added back in. */ + s->padding_statement.size = 0; + break; + } + dot += s->padding_statement.size / opb; output_section_statement->bfd_section->_raw_size += s->padding_statement.size; @@ -3982,6 +3973,7 @@ static void reset_memory_regions () { lang_memory_region_type *p = lang_memory_region_list; + asection *o; for (p = lang_memory_region_list; p != (lang_memory_region_type *) NULL; @@ -3990,6 +3982,9 @@ reset_memory_regions () p->old_length = (bfd_size_type) (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 @@ -4148,16 +4143,17 @@ lang_process () section positions, since they will affect SIZEOF_HEADERS. */ 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. */ 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. */ + boolean relax_again; + do { reset_memory_regions (); @@ -4178,17 +4174,11 @@ lang_process () globals are, so can make better guess. */ lang_size_sections (statement_list.head, abs_output_section, - &(statement_list.head), 0, (bfd_vma) 0, true); + &(statement_list.head), 0, (bfd_vma) 0, + &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 everything is. */ diff --git a/ld/ldlang.h b/ld/ldlang.h index aa05254c87e..28d236c244d 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -441,7 +441,7 @@ 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, boolean relax)); + bfd_vma dot, boolean *relax)); extern void lang_enter_group PARAMS ((void)); extern void lang_leave_group PARAMS ((void)); extern void lang_add_section |