X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fldlang.c;h=d40ff07a5b339dcd89422dada5e11e589f84d6f6;hb=5b93d8bb517c1f5715435dcf627a8642f557ddb2;hp=f12fcce616a8a12dfeca69a30703e83179a09b68;hpb=13392b77a79c3512d30ee9d6a547638eeb6fd28a;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldlang.c b/ld/ldlang.c index f12fcce616..d40ff07a5b 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -682,6 +682,7 @@ lang_output_section_statement_lookup (name) lookup = (lang_output_section_statement_type *) new_stat (lang_output_section_statement, stat_ptr); lookup->region = (lang_memory_region_type *) NULL; + lookup->lma_region = (lang_memory_region_type *) NULL; lookup->fill = 0; lookup->block_value = 1; lookup->name = name; @@ -2168,7 +2169,8 @@ print_input_section (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); if (size != 0) { print_space (); @@ -2192,7 +2194,7 @@ print_input_section (in) } minfo ("0x%V %W %B\n", - i->output_section->vma + i->output_offset, size, + i->output_section->vma + i->output_offset, size / opb, i->owner); if (i->_cooked_size != 0 && i->_cooked_size != i->_raw_size) @@ -2214,7 +2216,7 @@ print_input_section (in) bfd_link_hash_traverse (link_info.hash, print_one_symbol, (PTR) i); - print_dot = i->output_section->vma + i->output_offset + size; + print_dot = i->output_section->vma + i->output_offset + size / opb; } } } @@ -2234,6 +2236,8 @@ print_data_statement (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); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -2278,7 +2282,8 @@ print_data_statement (data) print_nl (); - print_dot = addr + size; + print_dot = addr + size / opb; + } /* Print an address statement. These are generated by options like @@ -2302,6 +2307,8 @@ print_reloc_statement (reloc) int i; bfd_vma addr; bfd_size_type size; + unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++) print_space (); @@ -2323,7 +2330,7 @@ print_reloc_statement (reloc) print_nl (); - print_dot = addr + size; + print_dot = addr + size / opb; } static void @@ -2332,6 +2339,8 @@ print_padding_statement (s) { int len; bfd_vma addr; + unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); minfo (" *fill*"); @@ -2352,7 +2361,7 @@ print_padding_statement (s) print_nl (); - print_dot = addr + s->size; + print_dot = addr + s->size / opb; } static void @@ -2547,6 +2556,8 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot) 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) @@ -2563,7 +2574,7 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot) new->padding_statement.output_offset = dot - output_section_statement->vma; new->padding_statement.fill = fill; - new->padding_statement.size = alignment_needed; + new->padding_statement.size = alignment_needed * opb; } @@ -2572,9 +2583,9 @@ insert_pad (this_ptr, fill, power, output_section_statement, dot) { output_section_statement->alignment_power = power; } - output_section_statement->_raw_size += alignment_needed; - return alignment_needed + dot; + output_section_statement->_raw_size += alignment_needed * opb; + return dot + alignment_needed; } /* Work out how much this section will move the dot point */ @@ -2588,6 +2599,8 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax) { 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) { @@ -2605,10 +2618,11 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax) /* Mark how big the output section must be to contain this now */ if (i->_cooked_size != 0) - dot += i->_cooked_size; + dot += i->_cooked_size / opb; else - dot += i->_raw_size; - output_section_statement->bfd_section->_raw_size = dot - output_section_statement->bfd_section->vma; + dot += i->_raw_size / opb; + output_section_statement->bfd_section->_raw_size = + (dot - output_section_statement->bfd_section->vma) * opb; } else { @@ -2629,6 +2643,7 @@ static void lang_check_section_addresses () { 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) @@ -2658,8 +2673,8 @@ lang_check_section_addresses () overlapping VMAs but they must have distinct LMAs. */ 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) - 1; - os_end = os_start + bfd_section_size (output_bfd, os) - 1; + s_end = s_start + bfd_section_size (output_bfd, s) / opb - 1; + os_end = os_start + bfd_section_size (output_bfd, os) / opb - 1; /* Look for an overlap. */ if ((s_end < os_start) || (s_start > os_end)) @@ -2681,6 +2696,43 @@ _("%X%P: section %s [%V -> %V] overlaps section %s [%V -> %V]\n"), 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 + calculation wraps around. */ + +static void +os_region_check (os, region, tree, base) + lang_output_section_statement_type *os; + struct memory_region_struct *region; + etree_type *tree; + bfd_vma base; +{ + if ((region->current < region->origin + || (region->current - region->origin > region->length)) + && ((region->current != region->origin + region->length) + || base == 0)) + { + if (tree != (etree_type *) NULL) + { + einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"), + region->current, + os->bfd_section->owner, + os->bfd_section->name, + region->name); + } + else + { + einfo (_("%X%P: region %s is full (%B section %s)\n"), + region->name, + os->bfd_section->owner, + os->bfd_section->name); + } + /* Reset the region pointer. */ + region->current = region->origin; + } +} + /* Set the sizes for all the output sections. */ bfd_vma @@ -2692,6 +2744,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) bfd_vma dot; boolean relax; { + unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); + /* Size up the sections from their constituent parts. */ for (; s != (lang_statement_union_type *) NULL; s = s->next) { @@ -2805,19 +2860,19 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) (void) lang_size_sections (os->children.head, os, &os->children.head, os->fill, dot, relax); - /* Ignore the size of the input sections, use the vma and size to - align against. */ - - after = ALIGN_N (os->bfd_section->vma + - os->bfd_section->_raw_size, + /* 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, /* The coercion here is important, see ld.h. */ (bfd_vma) os->block_value); if (bfd_is_abs_section (os->bfd_section)) ASSERT (after == os->bfd_section->vma); else - os->bfd_section->_raw_size = after - os->bfd_section->vma; - dot = os->bfd_section->vma + os->bfd_section->_raw_size; + os->bfd_section->_raw_size = + (after - os->bfd_section->vma) * opb; + dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb; os->processed = true; /* Update dot in the region ? @@ -2836,37 +2891,35 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) { os->region->current = dot; - /* 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 VMA is non-zero, - in case the region is at the end of addressable - memory and the calculation wraps around. */ - if ((os->region->current < os->region->origin - || (os->region->current - os->region->origin - > os->region->length)) - && ((os->region->current - != os->region->origin + os->region->length) - || os->bfd_section->vma == 0)) - - { - if (os->addr_tree != (etree_type *) NULL) - { - einfo (_("%X%P: address 0x%v of %B section %s is not within region %s\n"), - os->region->current, - os->bfd_section->owner, - os->bfd_section->name, - os->region->name); - } - else - { - einfo (_("%X%P: region %s is full (%B section %s)\n"), - os->region->name, - os->bfd_section->owner, - os->bfd_section->name); - } - /* Reset the region pointer. */ - os->region->current = os->region->origin; - } + /* 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 */ + if (os->lma_region == NULL && os->load_base == NULL) + os->lma_region = os->region; + + if (os->lma_region != NULL) + { + if (os->load_base != NULL) + { + einfo (_("%X%P: use an absolute load address or a load memory region, not both\n")); + } + else + { + /* don't allocate twice */ + if (os->lma_region != os->region) + { + /* 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; + os_region_check (os, os->lma_region, NULL, + os->bfd_section->lma); + } + } + } } } break; @@ -2889,6 +2942,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) switch (s->data_statement.type) { + default: + abort(); case QUAD: case SQUAD: size = QUAD_SIZE; @@ -2903,8 +2958,9 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) size = BYTE_SIZE; break; } - - dot += size; + if (size < opb) + size = opb; + dot += size / opb; 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. */ @@ -2924,7 +2980,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) s->reloc_statement.output_section = output_section_statement->bfd_section; size = bfd_get_reloc_size (s->reloc_statement.howto); - dot += size; + dot += size / opb; output_section_statement->bfd_section->_raw_size += size; } break; @@ -3012,7 +3068,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) new->padding_statement.output_offset = dot - output_section_statement->bfd_section->vma; new->padding_statement.fill = fill; - new->padding_statement.size = newdot - dot; + new->padding_statement.size = (newdot - dot) * opb; output_section_statement->bfd_section->_raw_size += new->padding_statement.size; } @@ -3030,7 +3086,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) pass than it did at this point in the previous pass. */ s->padding_statement.output_offset = dot - output_section_statement->bfd_section->vma; - dot += s->padding_statement.size; + dot += s->padding_statement.size / opb; output_section_statement->bfd_section->_raw_size += s->padding_statement.size; break; @@ -3063,6 +3119,9 @@ lang_do_assignments (s, output_section_statement, fill, dot) fill_type fill; bfd_vma dot; { + unsigned opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture, + ldfile_output_machine); + for (; s != (lang_statement_union_type *) NULL; s = s->next) { switch (s->header.type) @@ -3084,7 +3143,8 @@ lang_do_assignments (s, output_section_statement, fill, dot) dot = os->bfd_section->vma; (void) lang_do_assignments (os->children.head, os, os->fill, dot); - dot = os->bfd_section->vma + os->bfd_section->_raw_size; + dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb; + } if (os->load_base) { @@ -3124,22 +3184,30 @@ lang_do_assignments (s, output_section_statement, fill, dot) if (value.valid_p == false) einfo (_("%F%P: invalid data statement\n")); } - switch (s->data_statement.type) - { - case QUAD: - case SQUAD: - dot += QUAD_SIZE; - break; - case LONG: - dot += LONG_SIZE; - break; - case SHORT: - dot += SHORT_SIZE; - break; - case BYTE: - dot += BYTE_SIZE; - break; - } + { + unsigned int size; + switch (s->data_statement.type) + { + default: + abort(); + case QUAD: + case SQUAD: + size = QUAD_SIZE; + break; + case LONG: + size = LONG_SIZE; + break; + case SHORT: + size = SHORT_SIZE; + break; + case BYTE: + size = BYTE_SIZE; + break; + } + if (size < opb) + size = opb; + dot += size / opb; + } break; case lang_reloc_statement_enum: @@ -3153,7 +3221,7 @@ lang_do_assignments (s, output_section_statement, fill, dot) if (value.valid_p == false) einfo (_("%F%P: invalid reloc statement\n")); } - dot += bfd_get_reloc_size (s->reloc_statement.howto); + dot += bfd_get_reloc_size (s->reloc_statement.howto) / opb; break; case lang_input_section_enum: @@ -3161,9 +3229,9 @@ lang_do_assignments (s, output_section_statement, fill, dot) asection *in = s->input_section.section; if (in->_cooked_size != 0) - dot += in->_cooked_size; + dot += in->_cooked_size / opb; else - dot += in->_raw_size; + dot += in->_raw_size / opb; } break; @@ -3183,7 +3251,7 @@ lang_do_assignments (s, output_section_statement, fill, dot) break; case lang_padding_statement_enum: - dot += s->padding_statement.size; + dot += s->padding_statement.size / opb; break; case lang_group_statement_enum: @@ -3241,11 +3309,13 @@ lang_set_startof () h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true); if (h != NULL && h->type == bfd_link_hash_undefined) { + unsigned 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; + h->u.def.value = s->_cooked_size / opb; else - h->u.def.value = s->_raw_size; + h->u.def.value = s->_raw_size / opb; h->u.def.section = bfd_abs_section_ptr; } @@ -3422,6 +3492,8 @@ lang_one_common (h, 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; @@ -3436,8 +3508,8 @@ lang_one_common (h, info) section = h->u.c.p->section; /* Increase the size of the section. */ - section->_cooked_size = ALIGN_N (section->_cooked_size, - (bfd_size_type) (1 << power_of_two)); + section->_cooked_size = ALIGN_N ((section->_cooked_size + opb - 1) / opb, + (bfd_size_type) (1 << power_of_two)) * opb; /* Adjust the alignment if necessary. */ if (power_of_two > section->alignment_power) @@ -4223,13 +4295,22 @@ lang_float (maybe) } void -lang_leave_output_section_statement (fill, memspec, phdrs) +lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec) bfd_vma fill; const char *memspec; struct lang_output_section_phdr_list *phdrs; + const char *lma_memspec; { current_section->fill = fill; current_section->region = lang_memory_region_lookup (memspec); + if (strcmp (lma_memspec, "*default*") != 0) + { + current_section->lma_region = lang_memory_region_lookup (lma_memspec); + /* if no runtime region has been given, but the load region has been, + use the load region */ + if (strcmp (memspec, "*default*") == 0) + current_section->region = lang_memory_region_lookup (lma_memspec); + } current_section->phdrs = phdrs; stat_ptr = &statement_list; } @@ -4297,7 +4378,8 @@ lang_abs_symbol_at_end_of (secname, 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_section_size (output_bfd, sec) / + bfd_octets_per_byte (output_bfd)); h->u.def.section = bfd_abs_section_ptr; } @@ -4607,7 +4689,8 @@ lang_leave_overlay_section (fill, phdrs) name = current_section->name; - lang_leave_output_section_statement (fill, "*default*", phdrs); + lang_leave_output_section_statement (fill, "*default*", + phdrs, "*default*"); /* Define the magic symbols. */ @@ -4637,12 +4720,14 @@ lang_leave_overlay_section (fill, phdrs) looks through all the sections in the overlay and sets them. */ void -lang_leave_overlay (fill, memspec, phdrs) +lang_leave_overlay (fill, memspec, phdrs, lma_memspec) bfd_vma fill; const char *memspec; struct lang_output_section_phdr_list *phdrs; + const char *lma_memspec; { lang_memory_region_type *region; + lang_memory_region_type *lma_region; struct overlay_list *l; struct lang_nocrossref *nocrossref; @@ -4651,6 +4736,11 @@ lang_leave_overlay (fill, memspec, phdrs) else region = lang_memory_region_lookup (memspec); + if (lma_memspec == NULL) + lma_region = NULL; + else + lma_region = lang_memory_region_lookup (lma_memspec); + nocrossref = NULL; l = overlay_list; @@ -4662,6 +4752,8 @@ lang_leave_overlay (fill, memspec, phdrs) l->os->fill = fill; if (region != NULL && l->os->region == NULL) l->os->region = region; + if (lma_region != NULL && l->os->lma_region == NULL) + l->os->lma_region = lma_region; if (phdrs != NULL && l->os->phdrs == NULL) l->os->phdrs = phdrs;