/* Linker command language support.
- Copyright (C) 1991-2015 Free Software Foundation, Inc.
+ Copyright (C) 1991-2016 Free Software Foundation, Inc.
This file is part of the GNU Binutils.
struct unique_sections *unam;
const char *secnam;
- if (link_info.relocatable
+ if (bfd_link_relocatable (&link_info)
&& sec->owner != NULL
&& bfd_is_group_section (sec->owner, sec))
return !(os != NULL
lang_output_section_statement_type *
lang_output_section_find_by_flags (const asection *sec,
+ flagword sec_flags,
lang_output_section_statement_type **exact,
lang_match_sec_type_func match_type)
{
lang_output_section_statement_type *first, *look, *found;
- flagword look_flags, sec_flags, differ;
+ flagword look_flags, differ;
/* We know the first statement on this list is *ABS*. May as well
skip it. */
first = first->next;
/* First try for an exact match. */
- sec_flags = sec->flags;
found = NULL;
for (look = first; look; look = look->next)
{
if (found || !match_type)
return found;
- return lang_output_section_find_by_flags (sec, NULL, NULL);
+ return lang_output_section_find_by_flags (sec, sec_flags, NULL, NULL);
}
/* Find the last output section before given output statement.
{
lang_statement_list_type add;
const char *ps;
+ lang_assignment_statement_type *start_assign;
lang_output_section_statement_type *os;
lang_output_section_statement_type **os_tail;
push_stat_ptr (&add);
}
- if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
+ if (bfd_link_relocatable (&link_info)
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
address = exp_intop (0);
os_tail = ((lang_output_section_statement_type **)
NULL, NULL, NULL, constraint, 0);
ps = NULL;
+ start_assign = NULL;
if (config.build_constructors && *os_tail == os)
{
/* If the name of the section is representable in C, then create
symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
sprintf (symname + (symname[0] != 0), "__start_%s", secname);
- lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
- FALSE));
+ start_assign
+ = lang_add_assignment (exp_provide (symname,
+ exp_nameop (NAME, "."),
+ FALSE));
}
}
lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
NULL);
- if (ps != NULL && *ps == '\0')
+ if (start_assign != NULL)
{
char *symname;
+ lang_assignment_statement_type *stop_assign;
+ bfd_vma dot;
symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
- lang_add_assignment (exp_provide (symname,
- exp_nameop (NAME, "."),
- FALSE));
+ stop_assign
+ = lang_add_assignment (exp_provide (symname,
+ exp_nameop (NAME, "."),
+ FALSE));
+ /* Evaluate the expression to define the symbol if referenced,
+ before sizing dynamic sections. */
+ dot = os->bfd_section->vma;
+ exp_fold_tree (start_assign->exp, os->bfd_section, &dot);
+ dot += s->size;
+ exp_fold_tree (stop_assign->exp, os->bfd_section, &dot);
}
/* Restore the global list pointer. */
format targets, .text$foo sections go into .text and it's odd
to see .text with SEC_LINK_ONCE set. */
- if (!link_info.relocatable)
+ if (!bfd_link_relocatable (&link_info))
flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
switch (output->sectype)
ASSERT (link_info.output_bfd == NULL);
open_output (statement->output_statement.name);
ldemul_set_output_arch ();
- if (config.magic_demand_paged && !link_info.relocatable)
+ if (config.magic_demand_paged
+ && !bfd_link_relocatable (&link_info))
link_info.output_bfd->flags |= D_PAGED;
else
link_info.output_bfd->flags &= ~D_PAGED;
here, in lang_insert_orphan, or in the default linker scripts.
This is covering for coff backend linker bugs. See PR6945. */
if (os->addr_tree == NULL
- && link_info.relocatable
+ && bfd_link_relocatable (&link_info)
&& (bfd_get_flavour (link_info.output_bfd)
== bfd_target_coff_flavour))
os->addr_tree = exp_intop (0);
defined, issue an error message. */
if (!os->ignored
&& !IGNORE_SECTION (os->bfd_section)
- && ! link_info.relocatable
+ && !bfd_link_relocatable (&link_info)
&& check_regions
&& strcmp (os->region->name_list.name,
DEFAULT_MEMORY_REGION) == 0
&& dot >= (r->last_os->output_section_statement
.bfd_section->vma)))
&& os->lma_region == NULL
- && !link_info.relocatable)
+ && !bfd_link_relocatable (&link_info))
r->last_os = s;
/* .tbss sections effectively have zero size. */
if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
- || link_info.relocatable)
+ || bfd_link_relocatable (&link_info))
dotdelta = TO_ADDR (os->bfd_section->size);
else
dotdelta = 0;
/* For sections in the relro segment.. */
for (sec = link_info.output_bfd->section_last; sec; sec = sec->prev)
- if (!IGNORE_SECTION (sec)
+ if ((sec->flags & SEC_ALLOC) != 0
&& sec->vma >= expld.dataseg.base
&& sec->vma < expld.dataseg.relro_end - expld.dataseg.relro_offset)
{
/* Where do we want to put this section so that it ends as
desired? */
- bfd_vma start = sec->vma;
- bfd_vma end = start + sec->size;
- bfd_vma bump = desired_end - end;
+ bfd_vma start, end, bump;
+
+ end = start = sec->vma;
+ if ((sec->flags & SEC_HAS_CONTENTS) != 0
+ || (sec->flags & SEC_THREAD_LOCAL) == 0)
+ end += sec->size;
+ bump = desired_end - end;
/* We'd like to increase START by BUMP, but we must heed
alignment so the increase might be less than optimum. */
- start += bump & ~(((bfd_vma) 1 << sec->alignment_power) - 1);
+ start += bump;
+ start &= ~(((bfd_vma) 1 << sec->alignment_power) - 1);
/* This is now the desired end for the previous section. */
desired_end = start;
}
/* .tbss sections effectively have zero size. */
if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
- || link_info.relocatable)
+ || bfd_link_relocatable (&link_info))
dot += TO_ADDR (os->bfd_section->size);
if (os->update_dot_tree != NULL)
{
asection *s;
- if (link_info.relocatable)
+ if (bfd_link_relocatable (&link_info))
return;
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
struct bfd_link_hash_entry *h;
bfd_boolean warn;
- if ((link_info.relocatable && !link_info.gc_sections)
- || (link_info.shared && !link_info.executable))
+ if ((bfd_link_relocatable (&link_info) && !link_info.gc_sections)
+ || bfd_link_dll (&link_info))
warn = entry_from_cmdline;
else
warn = TRUE;
/* Force the user to specify a root when generating a relocatable with
--gc-sections. */
- if (link_info.gc_sections && link_info.relocatable
+ if (link_info.gc_sections && bfd_link_relocatable (&link_info)
&& !(entry_from_cmdline || undef_from_cmdline))
einfo (_("%P%F: gc-sections requires either an entry or "
"an undefined symbol\n"));
input format may not have equivalent representations in
the output format (and besides BFD does not translate
relocs for other link purposes than a final link). */
- if ((link_info.relocatable || link_info.emitrelocations)
+ if ((bfd_link_relocatable (&link_info)
+ || link_info.emitrelocations)
&& (compatible == NULL
|| (bfd_get_flavour (input_bfd)
!= bfd_get_flavour (link_info.output_bfd)))
{
if (command_line.inhibit_common_definition)
return;
- if (link_info.relocatable
+ if (bfd_link_relocatable (&link_info)
&& ! command_line.force_common_definition)
return;
return TRUE;
}
+/* Handle a single orphan section S, placing the orphan into an appropriate
+ output section. The effects of the --orphan-handling command line
+ option are handled here. */
+
+static void
+ldlang_place_orphan (asection *s)
+{
+ if (config.orphan_handling == orphan_handling_discard)
+ {
+ lang_output_section_statement_type *os;
+ os = lang_output_section_statement_lookup (DISCARD_SECTION_NAME, 0,
+ TRUE);
+ if (os->addr_tree == NULL
+ && (bfd_link_relocatable (&link_info)
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
+ os->addr_tree = exp_intop (0);
+ lang_add_section (&os->children, s, NULL, os);
+ }
+ else
+ {
+ lang_output_section_statement_type *os;
+ const char *name = s->name;
+ int constraint = 0;
+
+ if (config.orphan_handling == orphan_handling_error)
+ einfo ("%X%P: error: unplaced orphan section `%A' from `%B'.\n",
+ s, s->owner);
+
+ if (config.unique_orphan_sections || unique_section_p (s, NULL))
+ constraint = SPECIAL;
+
+ os = ldemul_place_orphan (s, name, constraint);
+ if (os == NULL)
+ {
+ os = lang_output_section_statement_lookup (name, constraint, TRUE);
+ if (os->addr_tree == NULL
+ && (bfd_link_relocatable (&link_info)
+ || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
+ os->addr_tree = exp_intop (0);
+ lang_add_section (&os->children, s, NULL, os);
+ }
+
+ if (config.orphan_handling == orphan_handling_warn)
+ einfo ("%P: warning: orphan section `%A' from `%B' being "
+ "placed in section `%s'.\n",
+ s, s->owner, os->name);
+ }
+}
+
/* Run through the input files and ensure that every input section has
somewhere to go. If one is found without a destination then create
an input request and place it into the statement tree. */
/* This is a lonely common section which must have
come from an archive. We attach to the section
with the wildcard. */
- if (! link_info.relocatable
+ if (!bfd_link_relocatable (&link_info)
|| command_line.force_common_definition)
{
if (default_common_section == NULL)
}
}
else
- {
- const char *name = s->name;
- int constraint = 0;
-
- if (config.unique_orphan_sections
- || unique_section_p (s, NULL))
- constraint = SPECIAL;
-
- if (!ldemul_place_orphan (s, name, constraint))
- {
- lang_output_section_statement_type *os;
- os = lang_output_section_statement_lookup (name,
- constraint,
- TRUE);
- if (os->addr_tree == NULL
- && (link_info.relocatable
- || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
- os->addr_tree = exp_intop (0);
- lang_add_section (&os->children, s, NULL, os);
- }
- }
+ ldlang_place_orphan (s);
}
}
}
/* SEC_EXCLUDE is ignored when doing a relocatable link, except in
the special case of debug info. (See bfd/stabs.c)
Twiddle the flag here, to simplify later linker code. */
- if (link_info.relocatable)
+ if (bfd_link_relocatable (&link_info))
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
/* Find any sections not attached explicitly and handle them. */
lang_place_orphans ();
- if (! link_info.relocatable)
+ if (!bfd_link_relocatable (&link_info))
{
asection *found;
lang_record_phdrs ();
/* Check relro sections. */
- if (link_info.relro && ! link_info.relocatable)
+ if (link_info.relro && !bfd_link_relocatable (&link_info))
lang_find_relro_sections ();
/* Size up the sections. */
ldemul_finish ();
+ /* Convert absolute symbols to section relative. */
+ ldexp_finalize_syms ();
+
/* Make sure that the section addresses make sense. */
if (command_line.check_section_addresses)
lang_check_section_addresses ();