static void gc_section_callback
PARAMS ((lang_wild_statement_type *, struct wildcard_list *, asection *,
lang_input_statement_type *, PTR));
+static void lang_get_regions PARAMS ((struct memory_region_struct **,
+ struct memory_region_struct **,
+ const char *, const char *, int));
static void lang_record_phdrs PARAMS ((void));
static void lang_gc_wild PARAMS ((lang_wild_statement_type *));
static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
{
lang_memory_region_type *p;
+ /* NAME is NULL for LMA memspecs if no region was specified. */
+ if (name == NULL)
+ return NULL;
+
for (p = lang_memory_region_list;
p != (lang_memory_region_type *) NULL;
p = p->next)
lookup->subsection_alignment = -1;
lookup->section_alignment = -1;
lookup->load_base = (union etree_union *) NULL;
+ lookup->update_dot_tree = NULL;
lookup->phdrs = NULL;
lang_statement_append (&lang_output_section_statement,
discard all sections. */
if (entry->just_syms_flag)
{
- sec->output_section = bfd_abs_section_ptr;
- sec->output_offset = sec->vma;
+ bfd_link_just_syms (sec, &link_info);
return;
}
of having link once sections in the first place.
Also, not merging link once sections in a relocatable link
- causes trouble for MIPS ELF, which relies in link once semantics
+ causes trouble for MIPS ELF, which relies on link once semantics
to handle the .reginfo section correctly. */
name = bfd_get_section_name (abfd, sec);
section. */
sec->output_section = bfd_abs_section_ptr;
+ if (flags & SEC_GROUP)
+ bfd_discard_group (abfd, sec);
+
return;
}
}
flags &= ~ (SEC_MERGE | SEC_STRINGS);
}
+ /* For now make .tbss normal section. */
+ if (flags & SEC_THREAD_LOCAL)
+ flags |= SEC_LOAD;
+
section->output_section->flags |= flags;
if (flags & SEC_MERGE)
bfd_error_type err;
lang_statement_list_type *hold;
boolean bad_load = true;
-
+
err = bfd_get_error ();
/* See if the emulation has some special knowledge. */
einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
else
bad_load = false;
-
+
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
case bfd_archive:
if (entry->whole_archive)
{
- bfd * member = NULL;
+ bfd *member = NULL;
boolean loaded = true;
for (;;)
if (member == NULL)
break;
-
+
if (! bfd_check_format (member, bfd_object))
{
einfo (_("%F%B: member %B in archive is not an object\n"),
if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
{
/* Remember the section that common is going to in case we
- later get something which doesn't know where to put it. */
+ later get something which doesn't know where to put it. */
default_common_section = output;
}
}
result = exp_fold_tree (assignment->exp->assign.src, output_section,
lang_final_phase_enum, print_dot, &print_dot);
if (result.valid_p)
- minfo ("0x%V", result.value + result.section->bfd_section->vma);
+ {
+ const char *dst;
+ bfd_vma value;
+
+ value = result.value + result.section->bfd_section->vma;
+ dst = assignment->exp->assign.dst;
+
+ minfo ("0x%V", value);
+ if (dst[0] == '.' && dst[1] == 0)
+ print_dot = value;
+ }
else
{
minfo ("*undef* ");
if ((region->current < region->origin
|| (region->current - region->origin > region->length))
&& ((region->current != region->origin + region->length)
- || base == 0))
+ || 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);
- }
+ {
+ 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);
- }
+ {
+ 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;
}
if (bfd_is_abs_section (os->bfd_section))
ASSERT (after == os->bfd_section->vma);
+ else if ((os->bfd_section->flags & SEC_HAS_CONTENTS) == 0
+ && (os->bfd_section->flags & SEC_THREAD_LOCAL))
+ os->bfd_section->_raw_size = 0;
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;
+ if (os->update_dot_tree != 0)
+ exp_fold_tree (os->update_dot_tree, abs_output_section,
+ lang_allocating_phase_enum, dot, &dot);
+
/* 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
if (os->lma_region == NULL && os->load_base == NULL)
os->lma_region = os->region;
- if (os->lma_region != NULL)
+ if (os->lma_region != NULL && os->lma_region != os->region)
{
- 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);
- }
- }
+ /* 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);
}
}
}
if (value.valid_p == false)
einfo (_("%F%P: invalid data statement\n"));
}
- {
- unsigned int size;
+ {
+ unsigned int size;
switch (s->data_statement.type)
{
default:
h = bfd_link_hash_lookup (link_info.hash, buf, false, false, true);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
- unsigned opb;
+ unsigned opb;
- opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
+ opb = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
h->type = bfd_link_hash_defined;
if (s->_cooked_size != 0)
else if (bfd_count_sections (input_bfd))
{
/* If the input bfd has no contents, it shouldn't set the
- private data of the output bfd. */
+ private data of the output bfd. */
bfd_error_handler_type pfn = NULL;
if (file->just_syms_flag)
{
- /* We are only retrieving symbol values from this
- file. We want the symbols to act as though the
- values in the file are absolute. */
- s->output_section = bfd_abs_section_ptr;
- s->output_offset = s->vma;
+ abort ();
}
else if (strcmp (s->name, "COMMON") == 0)
{
(fill_type *) 0, (bfd_vma) 0);
/* Perform another relax pass - this time we know where the
- globals are, so can make better guess. */
+ globals are, so can make a better guess. */
lang_size_sections (statement_list.head,
abs_output_section,
- &(statement_list.head), 0, (bfd_vma) 0,
+ &statement_list.head, 0, (bfd_vma) 0,
&relax_again);
}
while (relax_again);
lang_float_flag = maybe;
}
+
+/* Work out the load- and run-time regions from a script statement, and
+ store them in *LMA_REGION and *REGION respectively.
+
+ MEMSPEC is the name of the run-time region, or "*default*" if the
+ statement didn't specify one. LMA_MEMSPEC is the name of the
+ load-time region, or null if the statement didn't specify one.
+ HAVE_LMA_P is true if the statement had an explicit load address.
+
+ It is an error to specify both a load region and a load address. */
+
+static void
+lang_get_regions (region, lma_region, memspec, lma_memspec, have_lma_p)
+ struct memory_region_struct **region, **lma_region;
+ const char *memspec, *lma_memspec;
+ int have_lma_p;
+{
+ *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 (lma_memspec != 0 && strcmp (memspec, "*default*") == 0)
+ *region = *lma_region;
+ else
+ *region = lang_memory_region_lookup (memspec);
+
+ if (have_lma_p && lma_memspec != 0)
+ einfo (_("%X%P:%S: section has both a load address and a load region\n"));
+}
+
void
lang_leave_output_section_statement (fill, memspec, phdrs, lma_memspec)
fill_type *fill;
struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{
+ lang_get_regions (¤t_section->region,
+ ¤t_section->lma_region,
+ memspec, lma_memspec,
+ current_section->load_base != 0);
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;
}
/* The overlay virtual address. */
static etree_type *overlay_vma;
-/* The overlay load address. */
-static etree_type *overlay_lma;
-
-/* Whether nocrossrefs is set for this overlay. */
-static int overlay_nocrossrefs;
-
/* An expression for the maximum section size seen so far. */
static etree_type *overlay_max;
/* Start handling an overlay. */
void
-lang_enter_overlay (vma_expr, lma_expr, nocrossrefs)
+lang_enter_overlay (vma_expr)
etree_type *vma_expr;
- etree_type *lma_expr;
- int nocrossrefs;
{
/* The grammar should prevent nested overlays from occurring. */
- ASSERT (overlay_vma == NULL
- && overlay_lma == NULL
- && overlay_list == NULL
- && overlay_max == NULL);
+ ASSERT (overlay_vma == NULL && overlay_max == NULL);
overlay_vma = vma_expr;
- overlay_lma = lma_expr;
- overlay_nocrossrefs = nocrossrefs;
}
/* Start a section in an overlay. We handle this by calling
- lang_enter_output_section_statement with the correct VMA and LMA. */
+ lang_enter_output_section_statement with the correct VMA.
+ lang_leave_overlay sets up the LMA and memory regions. */
void
lang_enter_overlay_section (name)
etree_type *size;
lang_enter_output_section_statement (name, overlay_vma, normal_section,
- 0, 0, 0, overlay_lma);
+ 0, 0, 0, 0);
- /* If this is the first section, then base the VMA and LMA of future
+ /* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is
used in the addresses. */
if (overlay_list == NULL)
- {
- overlay_vma = exp_nameop (ADDR, name);
- overlay_lma = exp_nameop (LOADADDR, name);
- }
+ overlay_vma = exp_nameop (ADDR, name);
/* Remember the section. */
n = (struct overlay_list *) xmalloc (sizeof *n);
size = exp_nameop (SIZEOF, name);
- /* Adjust the LMA for the next section. */
- overlay_lma = exp_binop ('+', overlay_lma, size);
-
/* Arrange to work out the maximum section end address. */
if (overlay_max == NULL)
overlay_max = size;
name = current_section->name;
- lang_leave_output_section_statement (fill, "*default*",
- phdrs, "*default*");
+ /* For now, assume that "*default*" is the run-time memory region and
+ that no load-time region has been specified. It doesn't really
+ matter what we say here, since lang_leave_overlay will override it. */
+ lang_leave_output_section_statement (fill, "*default*", phdrs, 0);
/* Define the magic symbols. */
looks through all the sections in the overlay and sets them. */
void
-lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
+lang_leave_overlay (lma_expr, nocrossrefs, fill, memspec, phdrs, lma_memspec)
+ etree_type *lma_expr;
+ int nocrossrefs;
fill_type *fill;
const char *memspec;
struct lang_output_section_phdr_list *phdrs;
const char *lma_memspec;
{
lang_memory_region_type *region;
- lang_memory_region_type * default_region;
lang_memory_region_type *lma_region;
struct overlay_list *l;
struct lang_nocrossref *nocrossref;
- default_region = lang_memory_region_lookup ("*default*");
-
- if (memspec == NULL)
- region = NULL;
- else
- region = lang_memory_region_lookup (memspec);
-
- if (lma_memspec == NULL)
- lma_region = NULL;
- else
- lma_region = lang_memory_region_lookup (lma_memspec);
+ lang_get_regions (®ion, &lma_region,
+ memspec, lma_memspec,
+ lma_expr != 0);
nocrossref = NULL;
+ /* After setting the size of the last section, set '.' to end of the
+ overlay region. */
+ if (overlay_list != NULL)
+ overlay_list->os->update_dot_tree
+ = exp_assop ('=', ".", exp_binop ('+', overlay_vma, overlay_max));
+
l = overlay_list;
while (l != NULL)
{
if (fill != (fill_type *) 0 && l->os->fill == (fill_type *) 0)
l->os->fill = fill;
- /* Assign a region to the sections, if one has been specified.
- Override the assignment of the default section, but not
- other sections. */
- if (region != NULL &&
- (l->os->region == NULL ||
- l->os->region == default_region))
- l->os->region = region;
-
- /* We only set lma_region for the first overlay section, as
- subsequent overlay sections will have load_base set relative
- to the first section. Also, don't set lma_region if
- load_base is specified. FIXME: There should really be a test
- that `AT ( LDADDR )' doesn't conflict with `AT >LMA_REGION'
- rather than letting LDADDR simply override LMA_REGION. */
- if (lma_region != NULL && l->os->lma_region == NULL
- && l->next == NULL && l->os->load_base == NULL)
- l->os->lma_region = lma_region;
+ l->os->region = region;
+ l->os->lma_region = lma_region;
+
+ /* The first section has the load address specified in the
+ OVERLAY statement. The rest are worked out from that.
+ The base address is not needed (and should be null) if
+ an LMA region was specified. */
+ if (l->next == 0)
+ l->os->load_base = lma_expr;
+ else if (lma_region == 0)
+ l->os->load_base = exp_binop ('+',
+ exp_nameop (LOADADDR, l->next->os->name),
+ exp_nameop (SIZEOF, l->next->os->name));
if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs;
- if (overlay_nocrossrefs)
+ if (nocrossrefs)
{
struct lang_nocrossref *nc;
if (nocrossref != NULL)
lang_add_nocrossref (nocrossref);
- /* Update . for the end of the overlay. */
- lang_add_assignment (exp_assop ('=', ".",
- exp_binop ('+', overlay_vma, overlay_max)));
-
overlay_vma = NULL;
- overlay_lma = NULL;
- overlay_nocrossrefs = 0;
overlay_list = NULL;
overlay_max = NULL;
}
ret->match = lang_vers_match_lang_c;
}
- return ret;
+ return ldemul_new_vers_pattern (ret);
}
/* This is called for each set of variable names and match
bfd_size_type len;
if (sec == NULL)
- continue;
+ continue;
len = bfd_section_size (is->the_bfd, sec);
contents = xmalloc (len);