2001-05-02 H.J. Lu <hjl@gnu.org>
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 2baf13b85dfb141a0a0e10849020a2b7503f1b1a..a89fcf6d091b0bc19a2586b04217c5bc7f99bef6 100644 (file)
@@ -1,5 +1,6 @@
 /* Linker command language support.
-   Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
+   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001
    Free Software Foundation, Inc.
 
 This file is part of GLD, the Gnu Linker.
@@ -127,6 +128,7 @@ static bfd_vma size_input_section
           fill_type, bfd_vma, boolean));
 static void lang_finish PARAMS ((void));
 static void ignore_bfd_errors PARAMS ((const char *, ...));
+static void record_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));
@@ -621,7 +623,7 @@ lang_memory_region_lookup (name)
     lang_memory_region_type *new =
     (lang_memory_region_type *) stat_alloc (sizeof (lang_memory_region_type));
 
-    new->name = buystring (name);
+    new->name = xstrdup (name);
     new->next = (lang_memory_region_type *) NULL;
 
     *lang_memory_region_list_tail = new;
@@ -1174,8 +1176,22 @@ wild_doit (ptr, section, output, file)
       if (! first && (section->output_section->flags & SEC_READONLY) == 0)
        flags &= ~ SEC_READONLY;
 
+      /* Keep SEC_MERGE and SEC_STRINGS only if they are the same.  */
+      if (! first
+         && ((section->output_section->flags & (SEC_MERGE | SEC_STRINGS))
+             != (flags & (SEC_MERGE | SEC_STRINGS))
+             || ((flags & SEC_MERGE)
+                 && section->output_section->entsize != section->entsize)))
+       {
+         section->output_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
+         flags &= ~ (SEC_MERGE | SEC_STRINGS);
+       }
+
       section->output_section->flags |= flags;
 
+      if (flags & SEC_MERGE)
+       section->output_section->entsize = section->entsize;
+
       /* If SEC_READONLY is not set in the input section, then clear
          it from the output section.  */
       if ((section->flags & SEC_READONLY) == 0)
@@ -1433,6 +1449,11 @@ load_symbols (entry, place)
       lang_statement_list_type *hold;
 
       err = bfd_get_error ();
+
+      /* See if the emulation has some special knowledge.  */
+      if (ldemul_unrecognized_file (entry))
+       return;
+
       if (err == bfd_error_file_ambiguously_recognized)
        {
          char **p;
@@ -1450,13 +1471,7 @@ load_symbols (entry, place)
       bfd_close (entry->the_bfd);
       entry->the_bfd = NULL;
 
-      /* See if the emulation has some special knowledge.  */
-
-      if (ldemul_unrecognized_file (entry))
-       return;
-
       /* Try to interpret the file as a linker script.  */
-
       ldfile_open_command_file (entry->filename);
 
       hold = stat_ptr;
@@ -1894,6 +1909,7 @@ open_input_bfds (s, force)
          if (s->input_statement.real)
            {
              lang_statement_list_type add;
+             bfd_error_handler_type pfn;
 
              s->input_statement.target = current_target;
 
@@ -1908,10 +1924,17 @@ open_input_bfds (s, force)
                                       bfd_archive))
                s->input_statement.loaded = false;
 
-             lang_list_init (&add);
+             lang_list_init (& add);
+
+             /* We need to know if an error occurs whilst loading the 
+                symbols, since this means that a valid executable can
+                not be produced.  */
+             pfn = bfd_set_error_handler (record_bfd_errors);
 
              load_symbols (&s->input_statement, &add);
 
+             bfd_set_error_handler (pfn);
+
              if (add.head != NULL)
                {
                  *add.tail = s->next;
@@ -1971,7 +1994,7 @@ ldlang_add_undef (name)
   new->next = ldlang_undef_chain_list_head;
   ldlang_undef_chain_list_head = new;
 
-  new->name = buystring (name);
+  new->name = xstrdup (name);
 }
 
 /* Run through the list of undefineds created above and place them
@@ -2666,7 +2689,6 @@ size_input_section (this_ptr, output_section_statement, fill, dot, relax)
 #define IGNORE_SECTION(bfd, s) \
   (((bfd_get_section_flags (bfd, s) & (SEC_ALLOC | SEC_LOAD)) != (SEC_ALLOC | SEC_LOAD)) \
    || bfd_section_size (bfd, s) == 0)
-
 /* Check to see if any allocated sections overlap with other allocated
    sections.  This can happen when the linker script specifically specifies
    the output section addresses of the two sections.  */
@@ -2677,6 +2699,7 @@ lang_check_section_addresses ()
   asection *s;
   unsigned opb = bfd_octets_per_byte (output_bfd);
 
+
   /* Scan all sections in the output list.  */
   for (s = output_bfd->sections; s != NULL; s = s->next)
     {
@@ -3435,6 +3458,53 @@ lang_finish ()
     }
 }
 
+
+/* This is the routine to handle BFD error messages.  */
+
+#ifdef ANSI_PROTOTYPES
+
+static void
+record_bfd_errors (const char *s, ...)
+{
+  va_list p;
+
+  einfo ("%P: ");
+
+  va_start (p, s);
+
+  vfprintf (stderr, s, p);
+
+  va_end (p);
+
+  fprintf (stderr, "\n");
+
+  einfo ("%X");
+}
+
+#else /* ! defined (ANSI_PROTOTYPES) */
+
+static void
+record_bfd_errors (va_alist)
+     va_dcl
+{
+  va_list p;
+  const char *s;
+
+  einfo ("%P: ");
+
+  va_start (p);
+
+  s = va_arg (p, const char *);
+  vfprintf (stderr, s, p);
+
+  va_end (p);
+
+  fprintf (stderr, "\n");
+
+  einfo ("%X");
+}
+
+#endif /* ! defined (ANSI_PROTOTYPES) */
 /* This is a small function used when we want to ignore errors from
    BFD.  */
 
@@ -4782,8 +4852,12 @@ lang_leave_overlay (fill, memspec, phdrs, lma_memspec)
        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.  */
-      if (lma_region != NULL && l->os->lma_region == NULL && l->next == NULL)
+        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;
       if (phdrs != NULL && l->os->phdrs == NULL)
        l->os->phdrs = phdrs;
This page took 0.025602 seconds and 4 git commands to generate.