* pe-dll.c (process_def_file): auto-export everything if
[deliverable/binutils-gdb.git] / ld / ldlang.c
index 3721716c355d54c984dce09117a92a2afe5f0862..2106b3e90874f82e5ae22570c52e56ca28bac758 100644 (file)
@@ -141,6 +141,17 @@ static int topower PARAMS ((int));
 static void lang_set_startof PARAMS ((void));
 static void reset_memory_regions PARAMS ((void));
 static void lang_record_phdrs PARAMS ((void));
+static void lang_gc_wild_section
+  PARAMS ((lang_wild_statement_type *, const char *,
+          lang_input_statement_type *));
+static void lang_gc_wild_file
+  PARAMS ((lang_wild_statement_type *, const char *,
+          lang_input_statement_type *));
+static void lang_gc_wild
+  PARAMS ((lang_wild_statement_type *, const char *, const char *));
+static void lang_gc_sections_1 PARAMS ((lang_statement_union_type *));
+static void lang_gc_sections PARAMS ((void));
+                                       
 
 /* EXPORTS */
 lang_output_section_statement_type *abs_output_section;
@@ -982,13 +993,58 @@ wild_sort (wild, file, section)
 
       if (wild->filenames_sorted)
        {
+         const char *fn, *ln;
+         boolean fa, la;
          int i;
 
-         i = strcmp (file->filename, ls->ifile->filename);
-         if (i < 0)
+         /* The PE support for the .idata section as generated by
+             dlltool assumes that files will be sorted by the name of
+             the archive and then the name of the file within the
+             archive.  */
+
+         if (file->the_bfd != NULL
+             && bfd_my_archive (file->the_bfd) != NULL)
+           {
+             fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
+             fa = true;
+           }
+         else
+           {
+             fn = file->filename;
+             fa = false;
+           }
+
+         if (ls->ifile->the_bfd != NULL
+             && bfd_my_archive (ls->ifile->the_bfd) != NULL)
+           {
+             ln = bfd_get_filename (bfd_my_archive (ls->ifile->the_bfd));
+             la = true;
+           }
+         else
+           {
+             ln = ls->ifile->filename;
+             la = false;
+           }
+
+         i = strcmp (fn, ln);
+         if (i > 0)
            continue;
-         else if (i > 0)
+         else if (i < 0)
            break;
+
+         if (fa || la)
+           {
+             if (fa)
+               fn = file->filename;
+             if (la)
+               ln = ls->ifile->filename;
+
+             i = strcmp (fn, ln);
+             if (i > 0)
+               continue;
+             else if (i < 0)
+               break;
+           }
        }
 
       /* Here either the files are not sorted by name, or we are
@@ -999,7 +1055,7 @@ wild_sort (wild, file, section)
          if (strcmp (section_name,
                      bfd_get_section_name (ls->ifile->the_bfd,
                                            ls->section))
-             > 0)
+             < 0)
            break;
        }
     }
@@ -1056,6 +1112,11 @@ wild_section (ptr, section, file, output)
            {
              lang_statement_union_type *before;
 
+             /* If the wild pattern was marked KEEP, the member sections
+                should be as well.  */
+             if (ptr->keep_sections)
+               s->flags |= SEC_KEEP;
+
              before = wild_sort (ptr, file, s);
 
              /* Here BEFORE points to the lang_input_section which
@@ -1072,15 +1133,21 @@ wild_section (ptr, section, file, output)
 
                  lang_list_init (&list);
                  wild_doit (&list, s, output, file);
-                 ASSERT (list.head != NULL && list.head->next == NULL);
 
-                 for (pp = &ptr->children.head;
-                      *pp != before;
-                      pp = &(*pp)->next)
-                   ASSERT (*pp != NULL);
+                 /* If we are discarding the section, LIST.HEAD will
+                     be NULL.  */
+                 if (list.head != NULL)
+                   {
+                     ASSERT (list.head->next == NULL);
 
-                 list.head->next = *pp;
-                 *pp = list.head;
+                     for (pp = &ptr->children.head;
+                          *pp != before;
+                          pp = &(*pp)->next)
+                       ASSERT (*pp != NULL);
+
+                     list.head->next = *pp;
+                     *pp = list.head;
+                   }
                }
            }
        }
@@ -2791,25 +2858,40 @@ lang_finish ()
     }
   else
     {
-      asection *ts;
+      bfd_vma val;
+      CONST char *send;
 
-      /* Can't find the entry symbol.  Use the first address in the
-        text section.  */
-      ts = bfd_get_section_by_name (output_bfd, ".text");
-      if (ts != (asection *) NULL)
+      /* We couldn't find the entry symbol.  Try parsing it as a
+         number.  */
+      val = bfd_scan_vma (entry_symbol, &send, 0);
+      if (*send == '\0')
        {
-         if (warn)
-           einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
-                  entry_symbol, bfd_get_section_vma (output_bfd, ts));
-         if (! bfd_set_start_address (output_bfd,
-                                      bfd_get_section_vma (output_bfd, ts)))
+         if (! bfd_set_start_address (output_bfd, val))
            einfo (_("%P%F: can't set start address\n"));
        }
       else
        {
-         if (warn)
-           einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
-                  entry_symbol);
+         asection *ts;
+
+         /* Can't find the entry symbol, and it's not a number.  Use
+            the first address in the text section.  */
+         ts = bfd_get_section_by_name (output_bfd, ".text");
+         if (ts != (asection *) NULL)
+           {
+             if (warn)
+               einfo (_("%P: warning: cannot find entry symbol %s; defaulting to %V\n"),
+                      entry_symbol, bfd_get_section_vma (output_bfd, ts));
+             if (! bfd_set_start_address (output_bfd,
+                                          bfd_get_section_vma (output_bfd,
+                                                               ts)))
+               einfo (_("%P%F: can't set start address\n"));
+           }
+         else
+           {
+             if (warn)
+               einfo (_("%P: warning: cannot find entry symbol %s; not setting start address\n"),
+                      entry_symbol);
+           }
        }
     }
 }
@@ -3318,6 +3400,192 @@ reset_memory_regions ()
     }
 }
 
+/* ??? At some point this traversal for GC should share code with the
+   traversal for manipulating the output file.  */
+
+/* Expand a wild statement for a particular FILE, marking its sections KEEP
+   as needed.  SECTION may be NULL, in which case it is a wild card.  */
+
+static void
+lang_gc_wild_section (ptr, section, file)
+     lang_wild_statement_type *ptr;
+     const char *section;
+     lang_input_statement_type *file;
+{
+  if (file->just_syms_flag == false)
+    {
+      register asection *s;
+      boolean wildcard;
+
+      if (section == NULL)
+       wildcard = false;
+      else
+       wildcard = wildcardp (section);
+
+      for (s = file->the_bfd->sections; s != NULL; s = s->next)
+       {
+         boolean match;
+
+         if (section == NULL)
+           match = true;
+         else
+           {
+             const char *name;
+
+             name = bfd_get_section_name (file->the_bfd, s);
+             if (wildcard)
+               match = fnmatch (section, name, 0) == 0 ? true : false;
+             else
+               match = strcmp (section, name) == 0 ? true : false;
+           }
+
+         if (match)
+           {
+             /* If the wild pattern was marked KEEP, the member sections
+                should be as well.  */
+             if (ptr->keep_sections)
+               s->flags |= SEC_KEEP;
+           }
+       }
+    }
+}
+
+/* Handle a wild statement for a single file F.  */
+
+static void
+lang_gc_wild_file (s, section, f)
+     lang_wild_statement_type *s;
+     const char *section;
+     lang_input_statement_type *f;
+{
+  if (f->the_bfd == NULL
+      || ! bfd_check_format (f->the_bfd, bfd_archive))
+    lang_gc_wild_section (s, section, f);
+  else
+    {
+      bfd *member;
+
+      /* This is an archive file.  We must map each member of the
+        archive separately.  */
+      member = bfd_openr_next_archived_file (f->the_bfd, (bfd *) NULL);
+      while (member != NULL)
+       {
+         /* When lookup_name is called, it will call the add_symbols
+            entry point for the archive.  For each element of the
+            archive which is included, BFD will call ldlang_add_file,
+            which will set the usrdata field of the member to the
+            lang_input_statement.  */
+         if (member->usrdata != NULL)
+           {
+             lang_gc_wild_section (s, section,
+                           (lang_input_statement_type *) member->usrdata);
+           }
+
+         member = bfd_openr_next_archived_file (f->the_bfd, member);
+       }
+    }
+}
+
+/* Handle a wild statement, marking it against GC.  SECTION or FILE or both
+   may be NULL, indicating that it is a wildcard.  */
+
+static void
+lang_gc_wild (s, section, file)
+     lang_wild_statement_type *s;
+     const char *section;
+     const char *file;
+{
+  lang_input_statement_type *f;
+
+  if (file == (char *) NULL)
+    {
+      /* Perform the iteration over all files in the list */
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         lang_gc_wild_file (s, section, f);
+       }
+    }
+  else if (wildcardp (file))
+    {
+      for (f = (lang_input_statement_type *) file_chain.head;
+          f != (lang_input_statement_type *) NULL;
+          f = (lang_input_statement_type *) f->next)
+       {
+         if (fnmatch (file, f->filename, FNM_FILE_NAME) == 0)
+           lang_gc_wild_file (s, section, f);
+       }
+    }
+  else
+    {
+      /* Perform the iteration over a single file */
+      f = lookup_name (file);
+      lang_gc_wild_file (s, section, f);
+    }
+}
+
+/* Iterate over sections marking them against GC.  */
+
+static void
+lang_gc_sections_1 (s)
+     lang_statement_union_type * s;
+{
+  for (; s != (lang_statement_union_type *) NULL; s = s->next)
+    {
+      switch (s->header.type)
+       {
+       case lang_wild_statement_enum:
+         lang_gc_wild (&s->wild_statement,
+                       s->wild_statement.section_name,
+                       s->wild_statement.filename);
+         break;
+       case lang_constructors_statement_enum:
+         lang_gc_sections_1 (constructor_list.head);
+         break;
+       case lang_output_section_statement_enum:
+         lang_gc_sections_1 (s->output_section_statement.children.head);
+         break;
+       case lang_group_statement_enum:
+         lang_gc_sections_1 (s->group_statement.children.head);
+         break;
+       }
+    }
+}
+
+static void
+lang_gc_sections ()
+{
+  struct bfd_link_hash_entry *h;
+  ldlang_undef_chain_list_type *ulist, fake_list_start;
+
+  /* Keep all sections so marked in the link script.  */
+
+  lang_gc_sections_1 (statement_list.head);
+
+  /* Keep all sections containing symbols undefined on the command-line.
+     Handle the entry symbol at the same time.  */
+
+  fake_list_start.next = ldlang_undef_chain_list_head;
+  fake_list_start.name = entry_symbol;
+
+  for (ulist = &fake_list_start; ulist; ulist = ulist->next)
+    {
+      h = bfd_link_hash_lookup (link_info.hash, ulist->name, 
+                               false, false, false);
+
+      if (h != (struct bfd_link_hash_entry *) NULL
+          && (h->type == bfd_link_hash_defined
+              || h->type == bfd_link_hash_defweak)
+         && ! bfd_is_abs_section (h->u.def.section))
+       {
+         h->u.def.section->flags |= SEC_KEEP;
+       }
+    }
+
+  bfd_gc_sections (output_bfd, &link_info);
+}
+
 void
 lang_process ()
 {
@@ -3348,6 +3616,10 @@ lang_process ()
      files.  */
   ldctor_build_sets ();
 
+  /* Remove unreferenced sections if asked to.  */
+  if (command_line.gc_sections)
+    lang_gc_sections ();
+
   /* Size up the common data */
   lang_common ();
 
@@ -3428,11 +3700,13 @@ lang_process ()
 /* EXPORTED TO YACC */
 
 void
-lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
+lang_add_wild (section_name, sections_sorted, filename, filenames_sorted,
+              keep_sections)
      const char *const section_name;
      boolean sections_sorted;
      const char *const filename;
      boolean filenames_sorted;
+     boolean keep_sections;
 {
   lang_wild_statement_type *new = new_stat (lang_wild_statement,
                                            stat_ptr);
@@ -3449,6 +3723,7 @@ lang_add_wild (section_name, sections_sorted, filename, filenames_sorted)
   new->sections_sorted = sections_sorted;
   new->filename = filename;
   new->filenames_sorted = filenames_sorted;
+  new->keep_sections = keep_sections;
   lang_list_init (&new->children);
 }
 
@@ -3468,21 +3743,6 @@ lang_section_start (name, address)
    called by ENTRY in a linker script.  Command line arguments take
    precedence.  */
 
-/* WINDOWS_NT.  When an entry point has been specified, we will also force
-   this symbol to be defined by calling ldlang_add_undef (equivalent to 
-   having switch -u entry_name on the command line).  The reason we do
-   this is so that the user doesn't have to because they would have to use
-   the -u switch if they were specifying an entry point other than 
-   _mainCRTStartup.  Specifically, if creating a windows application, entry
-   point _WinMainCRTStartup must be specified.
-     What I have found for non console applications (entry not _mainCRTStartup)
-   is that the .obj that contains mainCRTStartup is brought in since it is
-   the first encountered in libc.lib and it has other symbols in it which will
-   be pulled in by the link process.  To avoid this, adding -u with the entry
-   point name specified forces the correct .obj to be used.  We can avoid
-   making the user do this by always adding the entry point name as an
-   undefined symbol.  */
-
 void
 lang_add_entry (name, cmdline)
      CONST char *name;
@@ -3495,14 +3755,6 @@ lang_add_entry (name, cmdline)
       entry_symbol = name;
       entry_from_cmdline = cmdline;
     }
-#if 0 
-  /* don't do this yet.  It seems to work (the executables run), but the 
-     image created is very different from what I was getting before indicating
-     that something else is being pulled in.  When everything else is working,
-     then try to put this back in to see if it will do the right thing for
-     other more complicated applications */
-  ldlang_add_undef (name);
-#endif
 }
 
 void
@@ -3990,7 +4242,7 @@ lang_enter_overlay_section (name)
   if (overlay_max == NULL)
     overlay_max = size;
   else
-    overlay_max = exp_binop (MAX, overlay_max, size);
+    overlay_max = exp_binop (MAX_K, overlay_max, size);
 }
 
 /* Finish a section in an overlay.  There isn't any special to do
This page took 0.029436 seconds and 4 git commands to generate.