diff options
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 144 |
1 files changed, 75 insertions, 69 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 6b201ec..55714c9 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1,6 +1,6 @@ /* Linker command language support. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003 + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -1799,6 +1799,30 @@ ldlang_open_output (lang_statement_union_type *statement) } } +/* Convert between addresses in bytes and sizes in octets. + For currently supported targets, octets_per_byte is always a power + of two, so we can use shifts. */ +#define TO_ADDR(X) ((X) >> opb_shift) +#define TO_SIZE(X) ((X) << opb_shift) + +/* Support the above. */ +static unsigned int opb_shift = 0; + +static void +init_opb (void) +{ + unsigned x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); + opb_shift = 0; + if (x > 1) + while ((x & 1) == 0) + { + x >>= 1; + ++opb_shift; + } + ASSERT (x == 1); +} + /* Open all the input files. */ static void @@ -2272,8 +2296,8 @@ print_input_section (lang_input_section_type *in) { asection *i = in->section; bfd_size_type size = i->_cooked_size != 0 ? i->_cooked_size : i->_raw_size; - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + + init_opb (); if (size != 0) { print_space (); @@ -2297,7 +2321,7 @@ print_input_section (lang_input_section_type *in) } minfo ("0x%V %W %B\n", - i->output_section->vma + i->output_offset, size / opb, + i->output_section->vma + i->output_offset, TO_ADDR (size), i->owner); if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size) @@ -2319,7 +2343,8 @@ print_input_section (lang_input_section_type *in) bfd_link_hash_traverse (link_info.hash, print_one_symbol, i); - print_dot = i->output_section->vma + i->output_offset + size / opb; + print_dot = (i->output_section->vma + i->output_offset + + TO_ADDR (size)); } } } @@ -2342,9 +2367,8 @@ print_data_statement (lang_data_statement_type *data) bfd_vma addr; bfd_size_type size; const char *name; - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + init_opb (); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -2388,8 +2412,7 @@ print_data_statement (lang_data_statement_type *data) print_nl (); - print_dot = addr + size / opb; - + print_dot = addr + TO_ADDR (size); } /* Print an address statement. These are generated by options like @@ -2411,9 +2434,8 @@ print_reloc_statement (lang_reloc_statement_type *reloc) int i; bfd_vma addr; bfd_size_type size; - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + init_opb (); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -2434,7 +2456,7 @@ print_reloc_statement (lang_reloc_statement_type *reloc) print_nl (); - print_dot = addr + size / opb; + print_dot = addr + TO_ADDR (size); } static void @@ -2442,9 +2464,8 @@ print_padding_statement (lang_padding_statement_type *s) { int len; bfd_vma addr; - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); + init_opb (); minfo (" *fill*"); len = sizeof " *fill*" - 1; @@ -2469,7 +2490,7 @@ print_padding_statement (lang_padding_statement_type *s) print_nl (); - print_dot = addr + s->size / opb; + print_dot = addr + TO_ADDR (s->size); } static void @@ -2698,8 +2719,6 @@ size_input_section (lang_statement_union_type **this_ptr, if (!is->ifile->just_syms_flag) { - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); unsigned int alignment_needed; asection *o; @@ -2719,7 +2738,7 @@ size_input_section (lang_statement_union_type **this_ptr, if (alignment_needed != 0) { - insert_pad (this_ptr, fill, alignment_needed * opb, o, dot); + insert_pad (this_ptr, fill, TO_SIZE (alignment_needed), o, dot); dot += alignment_needed; } @@ -2729,10 +2748,10 @@ size_input_section (lang_statement_union_type **this_ptr, /* Mark how big the output section must be to contain this now. */ if (i->_cooked_size != 0) - dot += i->_cooked_size / opb; + dot += TO_ADDR (i->_cooked_size); else - dot += i->_raw_size / opb; - o->_raw_size = (dot - o->vma) * opb; + dot += TO_ADDR (i->_raw_size); + o->_raw_size = TO_SIZE (dot - o->vma); } else { @@ -2755,7 +2774,6 @@ static void lang_check_section_addresses (void) { asection *s; - unsigned opb = bfd_octets_per_byte (output_bfd); /* Scan all sections in the output list. */ for (s = output_bfd->sections; s != NULL; s = s->next) @@ -2783,10 +2801,10 @@ lang_check_section_addresses (void) /* We must check the sections' LMA addresses not their VMA addresses because overlay sections can have overlapping VMAs but they must have distinct LMAs. */ - s_start = bfd_section_lma (output_bfd, s); + s_start = bfd_section_lma (output_bfd, s); os_start = bfd_section_lma (output_bfd, os); - s_end = s_start + bfd_section_size (output_bfd, s) / opb - 1; - os_end = os_start + bfd_section_size (output_bfd, os) / opb - 1; + s_end = s_start + TO_ADDR (bfd_section_size (output_bfd, s)) - 1; + os_end = os_start + TO_ADDR (bfd_section_size (output_bfd, os)) - 1; /* Look for an overlap. */ if ((s_end < os_start) || (s_start > os_end)) @@ -2851,9 +2869,6 @@ lang_size_sections_1 bfd_boolean *relax, bfd_boolean check_regions) { - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); - /* Size up the sections from their constituent parts. */ for (; s != NULL; s = s->header.next) { @@ -2990,9 +3005,10 @@ lang_size_sections_1 /* Put the section within the requested block size, or align at the block boundary. */ - after = align_n (os->bfd_section->vma - + os->bfd_section->_raw_size / opb, - (bfd_vma) os->block_value); + after = ((os->bfd_section->vma + + TO_ADDR (os->bfd_section->_raw_size) + + os->block_value - 1) + & - (bfd_vma) os->block_value); if (bfd_is_abs_section (os->bfd_section)) ASSERT (after == os->bfd_section->vma); @@ -3001,10 +3017,10 @@ lang_size_sections_1 && ! link_info.relocatable) os->bfd_section->_raw_size = 0; else - os->bfd_section->_raw_size = - (after - os->bfd_section->vma) * opb; + os->bfd_section->_raw_size + = TO_SIZE (after - os->bfd_section->vma); - dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb; + dot = os->bfd_section->vma + TO_ADDR (os->bfd_section->_raw_size); os->processed = TRUE; if (os->update_dot_tree != 0) @@ -3042,7 +3058,7 @@ lang_size_sections_1 /* Set load_base, which will be handled later. */ os->load_base = exp_intop (os->lma_region->current); os->lma_region->current += - os->bfd_section->_raw_size / opb; + TO_ADDR (os->bfd_section->_raw_size); if (check_regions) os_region_check (os, os->lma_region, NULL, os->bfd_section->lma); @@ -3085,9 +3101,9 @@ lang_size_sections_1 size = BYTE_SIZE; break; } - if (size < opb) - size = opb; - dot += size / opb; + if (size < TO_SIZE ((unsigned) 1)) + size = TO_SIZE ((unsigned) 1); + dot += TO_ADDR (size); output_section_statement->bfd_section->_raw_size += size; /* The output section gets contents, and then we inspect for any flags set in the input script which override any ALLOC. */ @@ -3109,7 +3125,7 @@ lang_size_sections_1 s->reloc_statement.output_section = output_section_statement->bfd_section; size = bfd_get_reloc_size (s->reloc_statement.howto); - dot += size / opb; + dot += TO_ADDR (size); output_section_statement->bfd_section->_raw_size += size; } break; @@ -3184,7 +3200,7 @@ lang_size_sections_1 /* 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, + insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot), output_section_statement->bfd_section, dot); /* Don't neuter the pad below when relaxing. */ @@ -3291,9 +3307,6 @@ lang_do_assignments_1 fill_type *fill, bfd_vma dot) { - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); - for (; s != NULL; s = s->header.next) { switch (s->header.type) @@ -3315,7 +3328,8 @@ lang_do_assignments_1 dot = os->bfd_section->vma; (void) lang_do_assignments_1 (os->children.head, os, os->fill, dot); - dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb; + dot = (os->bfd_section->vma + + TO_ADDR (os->bfd_section->_raw_size)); } if (os->load_base) @@ -3377,9 +3391,9 @@ lang_do_assignments_1 size = BYTE_SIZE; break; } - if (size < opb) - size = opb; - dot += size / opb; + if (size < TO_SIZE ((unsigned) 1)) + size = TO_SIZE ((unsigned) 1); + dot += TO_ADDR (size); } break; @@ -3394,7 +3408,7 @@ lang_do_assignments_1 if (!value.valid_p) einfo (_("%F%P: invalid reloc statement\n")); } - dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb; + dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto)); break; case lang_input_section_enum: @@ -3402,9 +3416,9 @@ lang_do_assignments_1 asection *in = s->input_section.section; if (in->_cooked_size != 0) - dot += in->_cooked_size / opb; + dot += TO_ADDR (in->_cooked_size); else - dot += in->_raw_size / opb; + dot += TO_ADDR (in->_raw_size); } break; @@ -3424,7 +3438,7 @@ lang_do_assignments_1 break; case lang_padding_statement_enum: - dot += s->padding_statement.size / opb; + dot += TO_ADDR (s->padding_statement.size); break; case lang_group_statement_enum: @@ -3447,8 +3461,7 @@ lang_do_assignments_1 void lang_do_assignments (lang_statement_union_type *s, - lang_output_section_statement_type - *output_section_statement, + lang_output_section_statement_type *output_section_statement, fill_type *fill, bfd_vma dot) { @@ -3494,15 +3507,11 @@ lang_set_startof (void) h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE); if (h != NULL && h->type == bfd_link_hash_undefined) { - unsigned opb; - - opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); h->type = bfd_link_hash_defined; if (s->_cooked_size != 0) - h->u.def.value = s->_cooked_size / opb; + h->u.def.value = TO_ADDR (s->_cooked_size); else - h->u.def.value = s->_raw_size / opb; + h->u.def.value = TO_ADDR (s->_raw_size); h->u.def.section = bfd_abs_section_ptr; } @@ -3696,8 +3705,6 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) unsigned int power_of_two; bfd_vma size; asection *section; - unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, - ldfile_output_machine); if (h->type != bfd_link_hash_common) return TRUE; @@ -3711,9 +3718,9 @@ lang_one_common (struct bfd_link_hash_entry *h, void *info) section = h->u.c.p->section; - /* Increase the size of the section. */ - section->_cooked_size = align_n ((section->_cooked_size + opb - 1) / opb, - (bfd_vma) 1 << power_of_two) * opb; + /* Increase the size of the section to align the common sym. */ + section->_cooked_size += ((bfd_vma) 1 << (power_of_two + opb_shift)) - 1; + section->_cooked_size &= (- (bfd_vma) 1 << (power_of_two + opb_shift)); /* Adjust the alignment if necessary. */ if (power_of_two > section->alignment_power) @@ -3994,7 +4001,6 @@ lang_output_section_statement_type * lang_enter_output_section_statement (const char *output_section_statement_name, etree_type *address_exp, enum section_type sectype, - bfd_vma block_value, etree_type *align, etree_type *subalign, etree_type *ebase) @@ -4021,7 +4027,7 @@ lang_enter_output_section_statement (const char *output_section_statement_name, os->flags = SEC_NO_FLAGS; else os->flags = SEC_NEVER_LOAD; - os->block_value = block_value ? block_value : 1; + os->block_value = 1; stat_ptr = &os->children; os->subsection_alignment = @@ -4147,6 +4153,7 @@ lang_process (void) /* Open the output file. */ lang_for_each_statement (ldlang_open_output); + init_opb (); ldemul_create_output_section_statements (); @@ -4582,8 +4589,7 @@ lang_abs_symbol_at_end_of (const char *secname, const char *name) h->u.def.value = 0; else h->u.def.value = (bfd_get_section_vma (output_bfd, sec) - + bfd_section_size (output_bfd, sec) / - bfd_octets_per_byte (output_bfd)); + + TO_ADDR (bfd_section_size (output_bfd, sec))); h->u.def.section = bfd_abs_section_ptr; } @@ -4832,7 +4838,7 @@ lang_enter_overlay_section (const char *name) etree_type *size; lang_enter_output_section_statement (name, overlay_vma, normal_section, - 0, 0, overlay_subalign, 0); + 0, overlay_subalign, 0); /* If this is the first section, then base the VMA of future sections on this one. This will work correctly even if `.' is |