-bfd_vma
-lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
- 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;
-{
- /* Size up the sections from their constituent parts */
- for (; s != (lang_statement_union_type *) NULL; s = s->next)
- {
- switch (s->header.type)
- {
-
- case lang_output_section_statement_enum:
- {
- bfd_vma after;
- lang_output_section_statement_type *os = &s->output_section_statement;
-
- if (os->bfd_section == NULL)
- {
- /* This section was never actually created. */
- break;
- }
-
- /* If this is a COFF shared library section, use the size and
- address from the input section. FIXME: This is COFF
- specific; it would be cleaner if there were some other way
- to do this, but nothing simple comes to mind. */
- if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
- {
- asection *input;
-
- if (os->children.head == NULL
- || os->children.head->next != NULL
- || os->children.head->header.type != lang_input_section_enum)
- einfo ("%P%X: Internal error on COFF shared library section %s\n",
- os->name);
-
- input = os->children.head->input_section.section;
- bfd_set_section_vma (os->bfd_section->owner,
- os->bfd_section,
- bfd_section_vma (input->owner, input));
- os->bfd_section->_raw_size = input->_raw_size;
- break;
- }
-
- if (bfd_is_abs_section (os->bfd_section))
- {
- /* No matter what happens, an abs section starts at zero */
- ASSERT (os->bfd_section->vma == 0);
- }
- else
- {
- if (os->addr_tree == (etree_type *) NULL)
- {
- /* No address specified for this section, get one
- from the region specification
- */
- if (os->region == (lang_memory_region_type *) NULL)
- {
- os->region = lang_memory_region_lookup ("*default*");
- }
- dot = os->region->current;
- if (os->section_alignment == -1)
- {
- bfd_vma olddot;
-
- olddot = dot;
- dot = align_power (dot, os->bfd_section->alignment_power);
- if (dot != olddot && config.warn_section_align)
- einfo ("%P: warning: changing start of section %s by %u bytes\n",
- os->name, (unsigned int) (dot - olddot));
- }
- }
- else
- {
- etree_value_type r;
-
- r = exp_fold_tree (os->addr_tree,
- abs_output_section,
- lang_allocating_phase_enum,
- dot, &dot);
- if (r.valid == false)
- {
- einfo ("%F%S: non constant address expression for section %s\n",
- os->name);
- }
- dot = r.value + r.section->bfd_section->vma;
- }
- /* The section starts here */
- /* First, align to what the section needs */
-
- if (os->section_alignment != -1)
- dot = align_power (dot, os->section_alignment);
-
- bfd_set_section_vma (0, os->bfd_section, dot);
-
- os->bfd_section->output_offset = 0;
- }
-
- (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,
- /* 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->processed = true;
-
- /* Replace into region ? */
- if (os->region != (lang_memory_region_type *) NULL)
- {
- os->region->current = dot;
- /* Make sure this isn't silly. */
- if (os->region->current < os->region->origin
- || (os->region->current - os->region->origin
- > os->region->length))
- {
- 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;
- }
- }
- }
- break;
-
- case lang_constructors_statement_enum:
- dot = lang_size_sections (constructor_list.head,
- output_section_statement,
- &s->wild_statement.children.head,
- fill,
- dot, relax);
- break;
+bfd_vma
+lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
+ 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;
+{
+ 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)
+ {
+ switch (s->header.type)
+ {
+ case lang_output_section_statement_enum:
+ {
+ bfd_vma after;
+ lang_output_section_statement_type *os = &s->output_section_statement;
+
+ if (os->bfd_section == NULL)
+ /* This section was never actually created. */
+ break;
+
+ /* If this is a COFF shared library section, use the size and
+ address from the input section. FIXME: This is COFF
+ specific; it would be cleaner if there were some other way
+ to do this, but nothing simple comes to mind. */
+ if ((os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
+ {
+ asection * input;
+
+ if (os->children.head == NULL
+ || os->children.head->next != NULL
+ || os->children.head->header.type != lang_input_section_enum)
+ einfo (_("%P%X: Internal error on COFF shared library section %s\n"),
+ os->name);
+
+ input = os->children.head->input_section.section;
+ bfd_set_section_vma (os->bfd_section->owner,
+ os->bfd_section,
+ bfd_section_vma (input->owner, input));
+ os->bfd_section->_raw_size = input->_raw_size;
+ break;
+ }
+
+ if (bfd_is_abs_section (os->bfd_section))
+ {
+ /* No matter what happens, an abs section starts at zero. */
+ ASSERT (os->bfd_section->vma == 0);
+ }
+ else
+ {
+ if (os->addr_tree == (etree_type *) NULL)
+ {
+ /* No address specified for this section, get one
+ from the region specification. */
+ if (os->region == (lang_memory_region_type *) NULL
+ || (((bfd_get_section_flags (output_bfd, os->bfd_section)
+ & (SEC_ALLOC | SEC_LOAD)) != 0)
+ && os->region->name[0] == '*'
+ && strcmp (os->region->name, "*default*") == 0))
+ {
+ os->region = lang_memory_default (os->bfd_section);
+ }
+
+ /* If a loadable section is using the default memory
+ region, and some non default memory regions were
+ defined, issue a warning. */
+ if ((bfd_get_section_flags (output_bfd, os->bfd_section)
+ & (SEC_ALLOC | SEC_LOAD)) != 0
+ && ! link_info.relocateable
+ && strcmp (os->region->name, "*default*") == 0
+ && lang_memory_region_list != NULL
+ && (strcmp (lang_memory_region_list->name, "*default*") != 0
+ || lang_memory_region_list->next != NULL))
+ einfo (_("%P: warning: no memory region specified for section `%s'\n"),
+ bfd_get_section_name (output_bfd, os->bfd_section));
+
+ dot = os->region->current;
+
+ if (os->section_alignment == -1)
+ {
+ bfd_vma olddot;
+
+ olddot = dot;
+ dot = align_power (dot, os->bfd_section->alignment_power);
+
+ if (dot != olddot && config.warn_section_align)
+ einfo (_("%P: warning: changing start of section %s by %u bytes\n"),
+ os->name, (unsigned int) (dot - olddot));
+ }
+ }
+ else
+ {
+ etree_value_type r;
+
+ r = exp_fold_tree (os->addr_tree,
+ abs_output_section,
+ lang_allocating_phase_enum,
+ dot, &dot);
+ if (r.valid_p == false)
+ {
+ einfo (_("%F%S: non constant address expression for section %s\n"),
+ os->name);
+ }
+ dot = r.value + r.section->bfd_section->vma;
+ }
+
+ /* The section starts here.
+ First, align to what the section needs. */
+
+ if (os->section_alignment != -1)
+ dot = align_power (dot, os->section_alignment);
+
+ bfd_set_section_vma (0, os->bfd_section, dot);
+
+ os->bfd_section->output_offset = 0;
+ }
+
+ (void) 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 */
+ 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) * opb;
+ dot = os->bfd_section->vma + os->bfd_section->_raw_size / opb;
+ os->processed = true;
+
+ /* Update dot in the region ?
+ We only do this if the section is going to be allocated,
+ since unallocated sections do not contribute to the region's
+ overall size in memory.
+
+ If the SEC_NEVER_LOAD bit is not set, it will affect the
+ addresses of sections after it. We have to update
+ dot. */
+ if (os->region != (lang_memory_region_type *) NULL
+ && ((bfd_get_section_flags (output_bfd, os->bfd_section)
+ & SEC_NEVER_LOAD) == 0
+ || (bfd_get_section_flags (output_bfd, os->bfd_section)
+ & (SEC_ALLOC | SEC_LOAD))))
+ {
+ os->region->current = dot;
+
+ /* 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;
+
+ case lang_constructors_statement_enum:
+ dot = lang_size_sections (constructor_list.head,
+ output_section_statement,
+ &s->wild_statement.children.head,
+ fill,
+ dot, relax);
+ break;
+
+ case lang_data_statement_enum:
+ {
+ unsigned int size = 0;
+
+ s->data_statement.output_vma = dot - output_section_statement->bfd_section->vma;
+ s->data_statement.output_section =
+ output_section_statement->bfd_section;