* ldemul.h (ld_emulation_xfer_struct): new hook "recognized_file"
authorDJ Delorie <dj@redhat.com>
Wed, 25 Nov 1998 23:03:47 +0000 (23:03 +0000)
committerDJ Delorie <dj@redhat.com>
Wed, 25 Nov 1998 23:03:47 +0000 (23:03 +0000)
* ldemul.c (ldemul_recognized_file): new function, new hook
* ldint.texinfo: document new hook.
* ldlang.c (load_symbols): call recognized_hook for all objects we
do recognize, in case the emulation needs to handle them
specially.  PE DLLs use this.
* pe-dll.c (pe_dll_generate_def_file): take out hack and debug
printfs
* emultempl/pe.em (gld_i386_recognized_file): new function
(gld_i486_unrecognized_file): take out hack

ld/ChangeLog
ld/ldemul.h [new file with mode: 0644]
ld/ldlang.c

index 9fb68509f12f6be5accd30ec77b080d078844aec..fa41a1de0f1ed8908786d31addc9b4734242d23c 100644 (file)
@@ -1,3 +1,16 @@
+1998-11-25  DJ Delorie  <dj@cygnus.com>
+
+       * ldemul.h (ld_emulation_xfer_struct): new hook "recognized_file"
+       * ldemul.c (ldemul_recognized_file): new function, new hook
+       * ldint.texinfo: document new hook.
+       * ldlang.c (load_symbols): call recognized_hook for all objects we
+       do recognize, in case the emulation needs to handle them
+       specially.  PE DLLs use this.
+       * pe-dll.c (pe_dll_generate_def_file): take out hack and debug
+       printfs
+       * emultempl/pe.em (gld_i386_recognized_file): new function
+       (gld_i486_unrecognized_file): take out hack
+
 start-sanitize-vr4xxx
 1998-11-24  Gavin Romig-Koch  <gavin@cygnus.com>
 
diff --git a/ld/ldemul.h b/ld/ldemul.h
new file mode 100644 (file)
index 0000000..eb34da9
--- /dev/null
@@ -0,0 +1,147 @@
+/* ld-emul.h - Linker emulation header file
+   Copyright 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+
+   This file is part of GLD, the Gnu Linker.
+
+   GLD is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 1, or (at your option)
+   any later version.
+
+   GLD is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.  */
+
+#ifndef LDEMUL_H
+#define LDEMUL_H
+
+#if ANSI_PROTOTYPES
+struct lang_input_statement_struct;
+struct search_dirs;
+#endif
+
+extern void ldemul_hll PARAMS ((char *));
+extern void ldemul_syslib PARAMS ((char *));
+extern void ldemul_after_parse PARAMS ((void));
+extern void ldemul_before_parse PARAMS ((void));
+extern void ldemul_after_open PARAMS ((void));
+extern void ldemul_after_allocation PARAMS ((void));
+extern void ldemul_before_allocation PARAMS ((void));
+extern void ldemul_set_output_arch PARAMS ((void));
+extern char *ldemul_choose_target PARAMS ((void));
+extern void ldemul_choose_mode PARAMS ((char *));
+extern void ldemul_list_emulations PARAMS ((FILE *));
+extern void ldemul_list_emulation_options PARAMS ((FILE *));
+extern char *ldemul_get_script PARAMS ((int *isfile));
+extern void ldemul_finish PARAMS ((void));
+extern void ldemul_set_symbols PARAMS ((void));
+extern void ldemul_create_output_section_statements PARAMS ((void));
+extern boolean ldemul_place_orphan
+  PARAMS ((struct lang_input_statement_struct *, asection *));
+extern int ldemul_parse_args PARAMS ((int, char **));
+extern boolean ldemul_unrecognized_file
+  PARAMS ((struct lang_input_statement_struct *));
+extern boolean ldemul_open_dynamic_archive
+  PARAMS ((const char *, struct search_dirs *,
+          struct lang_input_statement_struct *));
+extern char *ldemul_default_target PARAMS ((void));
+extern void after_parse_default PARAMS ((void));
+extern void after_open_default PARAMS ((void));
+extern void after_allocation_default PARAMS ((void));
+extern void before_allocation_default PARAMS ((void));
+extern void set_output_arch_default PARAMS ((void));
+extern void syslib_default PARAMS ((char*));
+extern void hll_default PARAMS ((char*));
+
+typedef struct ld_emulation_xfer_struct
+{
+  /* Run before parsing the command line and script file.
+     Set the architecture, maybe other things.  */
+  void   (*before_parse) PARAMS ((void));
+
+  /* Handle the SYSLIB (low level library) script command.  */
+  void   (*syslib) PARAMS ((char *));
+
+  /* Handle the HLL (high level library) script command.  */
+  void   (*hll) PARAMS ((char *));
+
+  /* Run after parsing the command line and script file.  */
+  void   (*after_parse) PARAMS ((void));
+
+  /* Run after opening all input files, and loading the symbols.  */
+  void   (*after_open) PARAMS ((void));
+
+  /* Run after allocating output sections.  */
+  void   (*after_allocation) PARAMS ( (void));
+
+  /* Set the output architecture and machine if possible.  */
+  void   (*set_output_arch) PARAMS ((void));
+
+  /* Decide which target name to use.  */
+  char * (*choose_target) PARAMS ((void));
+
+  /* Run before allocating output sections.  */
+  void   (*before_allocation) PARAMS ((void));
+
+  /* Return the appropriate linker script.  */
+  char * (*get_script) PARAMS ((int *isfile));
+
+  /* The name of this emulation.  */
+  char *emulation_name;
+
+  /* The output format.  */
+  char *target_name;
+
+  /* Run after assigning values from the script.  */
+  void (*finish) PARAMS ((void));
+
+  /* Create any output sections needed by the target.  */
+  void (*create_output_section_statements) PARAMS ((void));
+
+  /* Try to open a dynamic library.  ARCH is an architecture name, and
+     is normally the empty string.  ENTRY is the lang_input_statement
+     that should be opened.  */
+  boolean (*open_dynamic_archive)
+    PARAMS ((const char *arch, struct search_dirs *,
+            struct lang_input_statement_struct *entry));
+
+  /* Place an orphan section.  Return true if it was placed, false if
+     the default action should be taken.  This field may be NULL, in
+     which case the default action will always be taken.  */
+  boolean (*place_orphan)
+    PARAMS ((struct lang_input_statement_struct *, asection *));
+
+  /* Run after assigning parsing with the args, but before 
+     reading the script.  Used to initialize symbols used in the script. */
+  void (*set_symbols) PARAMS ((void));
+
+  /* Run to parse args which the base linker doesn't
+     understand. Return non zero on sucess. */
+  int (*parse_args) PARAMS ((int, char **));
+
+  /* Run to handle files which are not recognized as object files or
+     archives.  Return true if the file was handled.  */
+  boolean (*unrecognized_file)
+    PARAMS ((struct lang_input_statement_struct *));
+
+  /* Run to list the command line options which parse_args handles.  */
+  void (* list_options) PARAMS ((FILE *));
+
+  /* Run to specially handle files which *are* recognized as object
+     files or archives.  Return true if the file was handled.  */
+  boolean (*recognized_file)
+    PARAMS ((struct lang_input_statement_struct *));
+
+} ld_emulation_xfer_type;
+
+typedef enum 
+{
+  intel_ic960_ld_mode_enum,
+  default_mode_enum ,
+  intel_gld960_ld_mode_enum
+} lang_emulation_mode_enum_type;
+
+extern ld_emulation_xfer_type *ld_emulations[];
+
+#endif
index 2106b3e90874f82e5ae22570c52e56ca28bac758..f9dbd88fecabba8561958a47cb51aa5642721cf6 100644 (file)
@@ -151,6 +151,7 @@ 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));
+static void lang_do_version_exports_section PARAMS ((void));
                                        
 
 /* EXPORTS */
@@ -1253,6 +1254,9 @@ load_symbols (entry, place)
       return;
     }
 
+  if (ldemul_recognized_file (entry))
+    return;
+
   /* We don't call ldlang_add_file for an archive.  Instead, the
      add_symbols entry point will call ldlang_add_file, via the
      add_archive_element callback, for each element of the archive
@@ -2089,7 +2093,10 @@ print_statement (s, os)
     case lang_constructors_statement_enum:
       if (constructor_list.head != NULL)
        {
-         minfo (" CONSTRUCTORS\n");
+         if (constructors_sorted)
+           minfo (" SORT (CONSTRUCTORS)\n");
+         else
+           minfo (" CONSTRUCTORS\n");
          print_statement_list (constructor_list.head, os);
        }
       break;
@@ -3549,6 +3556,8 @@ lang_gc_sections_1 (s)
        case lang_group_statement_enum:
          lang_gc_sections_1 (s->group_statement.children.head);
          break;
+       default:
+         break;
        }
     }
 }
@@ -3567,7 +3576,7 @@ lang_gc_sections ()
      Handle the entry symbol at the same time.  */
 
   fake_list_start.next = ldlang_undef_chain_list_head;
-  fake_list_start.name = entry_symbol;
+  fake_list_start.name = (char *) entry_symbol;
 
   for (ulist = &fake_list_start; ulist; ulist = ulist->next)
     {
@@ -3612,6 +3621,10 @@ lang_process ()
      link.  */
   lang_check ();
 
+  /* Handle .exports instead of a version script if we're told to do so.  */
+  if (command_line.version_exports_section)
+    lang_do_version_exports_section ();
+
   /* Build all sets based on the information gathered from the input
      files.  */
   ldctor_build_sets ();
@@ -3655,6 +3668,10 @@ lang_process ()
 
          relax_again = false;
 
+         /* Note: pe-dll.c does something like this also.  If you find
+            you need to change this code, you probably need to change
+            pe-dll.c also.  DJ */
+
          /* Do all the assignments with our current guesses as to
             section sizes.  */
          lang_do_assignments (statement_list.head,
@@ -3836,7 +3853,7 @@ lang_add_reloc (reloc, howto, section, name, addend)
   p->output_vma = 0;
 }
 
-void
+lang_assignment_statement_type *
 lang_add_assignment (exp)
      etree_type * exp;
 {
@@ -3844,6 +3861,7 @@ lang_add_assignment (exp)
                                                  stat_ptr);
 
   new->exp = exp;
+  return new;
 }
 
 void
@@ -4476,3 +4494,40 @@ lang_add_vers_depend (list, name)
 
   return ret;
 }
+
+static void
+lang_do_version_exports_section ()
+{
+  struct bfd_elf_version_expr *greg = NULL, *lreg;
+
+  LANG_FOR_EACH_INPUT_STATEMENT (is)
+    {
+      asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports");
+      char *contents, *p;
+      bfd_size_type len;
+
+      if (sec == NULL)
+        continue;
+
+      len = bfd_section_size (is->the_bfd, sec);
+      contents = xmalloc (len);
+      if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
+       einfo (_("%X%P: unable to read .exports section contents"), sec);
+
+      while (p < contents+len)
+       {
+         greg = lang_new_vers_regex (greg, p);
+         p = strchr (p, '\0') + 1;
+       }
+
+      free (contents);
+
+      /* Do not include this section in the link.  */
+      bfd_set_section_flags (is->the_bfd, sec,
+       bfd_get_section_flags (is->the_bfd, sec) | SEC_EXCLUDE);
+    }
+
+  lreg = lang_new_vers_regex (NULL, "*");
+  lang_register_vers_node (command_line.version_exports_section,
+                          lang_new_vers_node (greg, lreg), NULL);
+}