- 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_default (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 == 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;