summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/ld/ldlang.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/binutils/ld/ldlang.c')
-rw-r--r--contrib/binutils/ld/ldlang.c289
1 files changed, 217 insertions, 72 deletions
diff --git a/contrib/binutils/ld/ldlang.c b/contrib/binutils/ld/ldlang.c
index 19aedf4..6cdab2b 100644
--- a/contrib/binutils/ld/ldlang.c
+++ b/contrib/binutils/ld/ldlang.c
@@ -1,5 +1,6 @@
/* Linker command language support.
- Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 1998
+ Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
@@ -128,6 +129,7 @@ static bfd_vma size_input_section
lang_output_section_statement_type *output_section_statement,
fill_type fill, bfd_vma dot, boolean relax));
static void lang_finish PARAMS ((void));
+static void ignore_bfd_errors PARAMS ((const char *, ...));
static void lang_check PARAMS ((void));
static void lang_common PARAMS ((void));
static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
@@ -412,8 +414,7 @@ lang_memory_region_type *
lang_memory_region_lookup (name)
CONST char *CONST name;
{
-
- lang_memory_region_type *p = lang_memory_region_list;
+ lang_memory_region_type *p;
for (p = lang_memory_region_list;
p != (lang_memory_region_type *) NULL;
@@ -451,6 +452,8 @@ lang_memory_region_lookup (name)
*lang_memory_region_list_tail = new;
lang_memory_region_list_tail = &new->next;
new->origin = 0;
+ new->flags = 0;
+ new->not_flags = 0;
new->length = ~(bfd_size_type)0;
new->current = 0;
new->had_full_message = false;
@@ -460,6 +463,31 @@ lang_memory_region_lookup (name)
}
+lang_memory_region_type *
+lang_memory_default (section)
+ asection *section;
+{
+ lang_memory_region_type *p;
+
+ flagword sec_flags = section->flags;
+
+ /* Override SEC_DATA to mean a writable section. */
+ if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)
+ sec_flags |= SEC_DATA;
+
+ for (p = lang_memory_region_list;
+ p != (lang_memory_region_type *) NULL;
+ p = p->next)
+ {
+ if ((p->flags & sec_flags) != 0
+ && (p->not_flags & sec_flags) == 0)
+ {
+ return p;
+ }
+ }
+ return lang_memory_region_lookup ("*default*");
+}
+
lang_output_section_statement_type *
lang_output_section_find (name)
CONST char *CONST name;
@@ -518,14 +546,34 @@ lang_output_section_statement_lookup (name)
return lookup;
}
+static void
+lang_map_flags (flag)
+ flagword flag;
+{
+ if (flag & SEC_ALLOC)
+ minfo ("a");
+
+ if (flag & SEC_CODE)
+ minfo ("x");
+
+ if (flag & SEC_READONLY)
+ minfo ("r");
+
+ if (flag & SEC_DATA)
+ minfo ("w");
+
+ if (flag & SEC_LOAD)
+ minfo ("l");
+}
+
void
lang_map ()
{
lang_memory_region_type *m;
minfo ("\nMemory Configuration\n\n");
- fprintf (config.map_file, "%-16s %-18s %-18s\n",
- "Name", "Origin", "Length");
+ fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
+ "Name", "Origin", "Length", "Attributes");
for (m = lang_memory_region_list;
m != (lang_memory_region_type *) NULL;
@@ -545,7 +593,26 @@ lang_map ()
++len;
}
- minfo ("0x%V\n", m->length);
+ minfo ("0x%V", m->length);
+ if (m->flags || m->not_flags)
+ {
+#ifndef BFD64
+ minfo (" ");
+#endif
+ if (m->flags)
+ {
+ print_space ();
+ lang_map_flags (m->flags);
+ }
+
+ if (m->not_flags)
+ {
+ minfo (" !");
+ lang_map_flags (m->not_flags);
+ }
+ }
+
+ print_nl ();
}
fprintf (config.map_file, "\nLinker script and memory map\n\n");
@@ -737,7 +804,11 @@ section_already_linked (abfd, sec, data)
explicit actions, like foo.o(.text), bar.o(.text) and
foo.o(.text, .data). */
-/* Return true if the PATTERN argument is a wildcard pattern. */
+/* Return true if the PATTERN argument is a wildcard pattern.
+ Although backslashes are treated specially if a pattern contains
+ wildcards, we do not consider the mere presence of a backslash to
+ be enough to cause the the pattern to be treated as a wildcard.
+ That lets us handle DOS filenames more naturally. */
static boolean
wildcardp (pattern)
@@ -747,7 +818,6 @@ wildcardp (pattern)
for (s = pattern; *s != '\0'; ++s)
if (*s == '?'
- || *s == '\\'
|| *s == '*'
|| *s == '[')
return true;
@@ -801,10 +871,17 @@ wild_doit (ptr, section, output, file)
if (section->output_section == NULL)
{
+ boolean first;
lang_input_section_type *new;
+ flagword flags;
if (output->bfd_section == NULL)
- init_os (output);
+ {
+ init_os (output);
+ first = true;
+ }
+ else
+ first = false;
/* Add a section reference to the list */
new = new_stat (lang_input_section, ptr);
@@ -813,23 +890,38 @@ wild_doit (ptr, section, output, file)
new->ifile = file;
section->output_section = output->bfd_section;
+ flags = section->flags;
+
/* We don't copy the SEC_NEVER_LOAD flag from an input section
to an output section, because we want to be able to include a
SEC_NEVER_LOAD section in the middle of an otherwise loaded
section (I don't know why we want to do this, but we do).
build_link_order in ldwrite.c handles this case by turning
- the embedded SEC_NEVER_LOAD section into a fill.
+ the embedded SEC_NEVER_LOAD section into a fill. */
+
+ flags &= ~ SEC_NEVER_LOAD;
+
+ /* If final link, don't copy the SEC_LINK_ONCE flags, they've
+ already been processed. One reason to do this is that on pe
+ format targets, .text$foo sections go into .text and it's odd
+ to see .text with SEC_LINK_ONCE set. */
+
+ if (! link_info.relocateable)
+ flags &= ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES);
+
+ /* If this is not the first input section, and the SEC_READONLY
+ flag is not currently set, then don't set it just because the
+ input section has it set. */
+
+ if (! first && (section->output_section->flags & SEC_READONLY) == 0)
+ flags &= ~ SEC_READONLY;
- If final link, don't copy the SEC_LINK_ONCE flags, they've already
- been processed. One reason to do this is that on pe format targets,
- .text$foo sections go into .text and it's odd to see .text with
- SEC_LINK_ONCE set. */
+ section->output_section->flags |= flags;
- section->output_section->flags |=
- section->flags & (flagword) (~ (SEC_NEVER_LOAD
- | (! link_info.relocateable
- ? SEC_LINK_ONCE | SEC_LINK_DUPLICATES
- : 0)));
+ /* If SEC_READONLY is not set in the input section, then clear
+ it from the output section. */
+ if ((section->flags & SEC_READONLY) == 0)
+ section->output_section->flags &= ~SEC_READONLY;
switch (output->sectype)
{
@@ -1367,7 +1459,7 @@ lang_place_undefineds ()
h = bfd_link_hash_lookup (link_info.hash, ptr->name, true, false, true);
if (h == (struct bfd_link_hash_entry *) NULL)
- einfo ("%P%F: bfd_link_hash_lookup failed: %E");
+ einfo ("%P%F: bfd_link_hash_lookup failed: %E\n");
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
@@ -1672,6 +1764,10 @@ print_data_statement (data)
size = QUAD_SIZE;
name = "QUAD";
break;
+ case SQUAD:
+ size = QUAD_SIZE;
+ name = "SQUAD";
+ break;
}
minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
@@ -2047,7 +2143,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
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",
+ einfo ("%P%X: Internal error on COFF shared library section %s\n",
os->name);
input = os->children.head->input_section.section;
@@ -2070,10 +2166,28 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
/* No address specified for this section, get one
from the region specification
*/
- if (os->region == (lang_memory_region_type *) NULL)
+ 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_region_lookup ("*default*");
+ 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)
{
@@ -2177,21 +2291,22 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
output_section_statement->bfd_section;
switch (s->data_statement.type)
- {
- case QUAD:
- size = QUAD_SIZE;
- break;
- case LONG:
- size = LONG_SIZE;
- break;
- case SHORT:
- size = SHORT_SIZE;
- break;
- case BYTE:
- size = BYTE_SIZE;
- break;
+ {
+ 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;
+ }
- }
dot += size;
output_section_statement->bfd_section->_raw_size += size;
/* The output section gets contents, and then we inspect for
@@ -2415,6 +2530,7 @@ lang_do_assignments (s, output_section_statement, fill, dot)
switch (s->data_statement.type)
{
case QUAD:
+ case SQUAD:
dot += QUAD_SIZE;
break;
case LONG:
@@ -2599,6 +2715,20 @@ lang_finish ()
}
}
+/* This is a small function used when we want to ignore errors from
+ BFD. */
+
+static void
+#ifdef ANSI_PROTOTYPES
+ignore_bfd_errors (const char *s, ...)
+#else
+ignore_bfd_errors (s)
+ const char *s;
+#endif
+{
+ /* Don't do anything. */
+}
+
/* Check that the architecture of all the input files is compatible
with the output file. Also call the backend to let it do any
other checking that is needed. */
@@ -2618,12 +2748,32 @@ lang_check ()
compatible = bfd_arch_get_compatible (input_bfd,
output_bfd);
if (compatible == NULL)
- einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
- bfd_printable_name (input_bfd), input_bfd,
- bfd_printable_name (output_bfd));
-
+ {
+ if (command_line.warn_mismatch)
+ einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
+ bfd_printable_name (input_bfd), input_bfd,
+ bfd_printable_name (output_bfd));
+ }
else
- bfd_merge_private_bfd_data (input_bfd, output_bfd);
+ {
+ bfd_error_handler_type pfn = NULL;
+
+ /* If we aren't supposed to warn about mismatched input
+ files, temporarily set the BFD error handler to a
+ function which will do nothing. We still want to call
+ bfd_merge_private_bfd_data, since it may set up
+ information which is needed in the output file. */
+ if (! command_line.warn_mismatch)
+ pfn = bfd_set_error_handler (ignore_bfd_errors);
+ if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+ {
+ if (command_line.warn_mismatch)
+ einfo ("%E%X: failed to merge target specific data of file %B\n",
+ input_bfd);
+ }
+ if (! command_line.warn_mismatch)
+ bfd_set_error_handler (pfn);
+ }
}
}
@@ -2820,36 +2970,41 @@ lang_place_orphans ()
void
lang_set_flags (ptr, flags)
- int *ptr;
+ lang_memory_region_type *ptr;
CONST char *flags;
{
- boolean state = false;
+ flagword *ptr_flags = &ptr->flags;
- *ptr = 0;
+ ptr->flags = ptr->not_flags = 0;
while (*flags)
{
- if (*flags == '!')
- {
- state = false;
- flags++;
- }
- else
- state = true;
switch (*flags)
{
- case 'R':
- /* ptr->flag_read = state; */
+ case '!':
+ ptr_flags = (ptr_flags == &ptr->flags) ? &ptr->not_flags : &ptr->flags;
+ break;
+
+ case 'A': case 'a':
+ *ptr_flags |= SEC_ALLOC;
+ break;
+
+ case 'R': case 'r':
+ *ptr_flags |= SEC_READONLY;
break;
- case 'W':
- /* ptr->flag_write = state; */
+
+ case 'W': case 'w':
+ *ptr_flags |= SEC_DATA;
break;
- case 'X':
- /* ptr->flag_executable= state;*/
+
+ case 'X': case 'x':
+ *ptr_flags |= SEC_CODE;
break;
- case 'L':
- case 'I':
- /* ptr->flag_loadable= state;*/
+
+ case 'L': case 'l':
+ case 'I': case 'i':
+ *ptr_flags |= SEC_LOAD;
break;
+
default:
einfo ("%P%F: invalid syntax in flags\n");
break;
@@ -3757,7 +3912,7 @@ lang_leave_overlay_section (fill, phdrs)
clean = xmalloc (strlen (name) + 1);
s2 = clean;
for (s1 = name; *s1 != '\0'; s1++)
- if (isalnum (*s1) || *s1 == '_')
+ if (isalnum ((unsigned char) *s1) || *s1 == '_')
*s2++ = *s1;
*s2 = '\0';
@@ -3910,11 +4065,6 @@ lang_register_vers_node (name, version, deps)
{
struct bfd_elf_version_expr *e2;
- for (e2 = t->globals; e2 != NULL; e2 = e2->next)
- if (strcmp (e1->match, e2->match) == 0)
- einfo ("%X%P: duplicate expression `%s' in version information\n",
- e1->match);
-
for (e2 = t->locals; e2 != NULL; e2 = e2->next)
if (strcmp (e1->match, e2->match) == 0)
einfo ("%X%P: duplicate expression `%s' in version information\n",
@@ -3932,11 +4082,6 @@ lang_register_vers_node (name, version, deps)
if (strcmp (e1->match, e2->match) == 0)
einfo ("%X%P: duplicate expression `%s' in version information\n",
e1->match);
-
- for (e2 = t->locals; e2 != NULL; e2 = e2->next)
- if (strcmp (e1->match, e2->match) == 0)
- einfo ("%X%P: duplicate expression `%s' in version information\n",
- e1->match);
}
}
OpenPOWER on IntegriCloud