* ldlang.c (load_symbols): Check for archive before object. Use
authorIan Lance Taylor <ian@airs.com>
Tue, 13 Sep 1994 20:42:47 +0000 (20:42 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 13 Sep 1994 20:42:47 +0000 (20:42 +0000)
bfd_check_format_matches, and, if ambiguous, print a list of
matching formats.  If file format is not recognized, treat file as
a linker script.
* ldgram.y (yyerror): If assuming an object file is a script,
mention that.  Tweak the format of the error messages.
* ldlex.l (lex_warn_invalid): If assuming an object is a script,
guess that this is not actually a script, and just report that the
file format was not recognized.
* ld.texinfo (Options): Admit that -( may be used more than once.
Add note that unrecognized object files are now treated as linker
scripts.

* ldfile.c (ldfile_input_filename): Make const.
(ldfile_assumed_script): New variable.
(try_open): Change arguments types to const.
(ldfile_find_command_file): Likewise.
(ldfile_open_command_file): Likewise.  Also, set lineno to 1.
* ldfile.h: Update declarations for ldfile.c changes.
* ldlex.l: Include <ctype.h>.
(file_name_stack): Change to be const char *.
(lineno_stack): New static variable.
(<<EOF>>): Set lineno as well as ldfile_input_filename.
(lex_push_file): Make name argument const.  Initialize
lineno_stack entry.
(lex_redirect): Initialize lineno_stack entry.
(lex_warn_invalid): Handle non printable characters nicely.
* ldlex.h (lex_push_file): Declare second argument as const.

* ldgram.y (ifile_p1): Recognize GROUP.
* ldlex.l: Recognize GROUP.
* ld.texinfo (Option Commands): Document GROUP.

ld/ChangeLog
ld/ld.texinfo
ld/ldgram.y
ld/ldlang.c

index 9db86d04bca8bc413961b818fac29f22fd5caff7..0a95eb262c0d9a83f062a97a31e04a601d324468 100644 (file)
@@ -1,3 +1,38 @@
+Tue Sep 13 16:30:11 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
+
+       * ldlang.c (load_symbols): Check for archive before object.  Use
+       bfd_check_format_matches, and, if ambiguous, print a list of
+       matching formats.  If file format is not recognized, treat file as
+       a linker script.
+       * ldgram.y (yyerror): If assuming an object file is a script,
+       mention that.  Tweak the format of the error messages.
+       * ldlex.l (lex_warn_invalid): If assuming an object is a script,
+       guess that this is not actually a script, and just report that the
+       file format was not recognized.
+       * ld.texinfo (Options): Admit that -( may be used more than once.
+       Add note that unrecognized object files are now treated as linker
+       scripts.
+
+       * ldfile.c (ldfile_input_filename): Make const.
+       (ldfile_assumed_script): New variable.
+       (try_open): Change arguments types to const.
+       (ldfile_find_command_file): Likewise.
+       (ldfile_open_command_file): Likewise.  Also, set lineno to 1.
+       * ldfile.h: Update declarations for ldfile.c changes.
+       * ldlex.l: Include <ctype.h>.
+       (file_name_stack): Change to be const char *.
+       (lineno_stack): New static variable.
+       (<<EOF>>): Set lineno as well as ldfile_input_filename.
+       (lex_push_file): Make name argument const.  Initialize
+       lineno_stack entry.
+       (lex_redirect): Initialize lineno_stack entry.
+       (lex_warn_invalid): Handle non printable characters nicely.
+       * ldlex.h (lex_push_file): Declare second argument as const.
+
+       * ldgram.y (ifile_p1): Recognize GROUP.
+       * ldlex.l: Recognize GROUP.
+       * ld.texinfo (Option Commands): Document GROUP.
+
 Mon Sep 12 17:04:27 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
 
        * config/m68klynx.mh: New file.
index e9a2fb7f3c8dcec5a7648cae85e5def0ee0f8172..b33094a115d48a90803aba9b466f8081cacf2be1 100644 (file)
@@ -177,8 +177,8 @@ ld [ -o @var{output} ]  @var{objfile}@dots{}
   [ -Map @var{mapfile} ]  [ -m @var{emulation} ]  [ -N | -n ]
   [ -noinhibit-exec ]  [ -oformat @var{output-format} ]
   [ -R @var{filename} ]  [ -relax ]  [ -retain-symbols-file @var{filename} ]
-  [ -r | -Ur ]  [ -rpath @var{dir} ] [ -S ]  [ -s ]  [ -sort-common ]
-  [ -stats ] [ -T @var{commandfile} ]
+  [ -r | -Ur ]  [ -rpath @var{dir} ] [ -S ]  [ -s ] [ -soname @var{name} ]
+  [ -sort-common ] [ -stats ] [ -T @var{commandfile} ]
   [ -Ttext @var{org} ]  [ -Tdata @var{org} ]
   [ -Tbss @var{org} ]  [ -t ] [ -traditional-format ]
   [ -u @var{symbol}]  [-V]  [-v]  [ -version ]
@@ -211,11 +211,13 @@ option.
 @ifclear SingleFormat
 The exceptions---which may meaningfully be used more than once---are
 @samp{-A}, @samp{-b} (or its synonym @samp{-format}), @samp{-defsym},
-@samp{-L}, @samp{-l}, @samp{-R}, and @samp{-u}.
+@samp{-L}, @samp{-l}, @samp{-R}, @samp{-u}, and @samp{-(} (or its
+synonym @samp{--start-group})..
 @end ifclear
 @ifset SingleFormat
 The exceptions---which may meaningfully be used more than once---are
-@samp{-A}, @samp{-defsym}, @samp{-L}, @samp{-l}, @samp{-R}, and @samp{-u}.
+@samp{-A}, @samp{-defsym}, @samp{-L}, @samp{-l}, @samp{-R}, @samp{-u},
+and @samp{-(} (or its synonym @samp{--start-group}).
 @end ifset
 
 @cindex object files
@@ -230,6 +232,14 @@ and the script command language.  If @emph{no} binary input files at all
 are specified, the linker does not produce any output, and issues the
 message @samp{No input files}.
 
+If the linker can not recognize the format of an object file, it will
+assume that it is a linker script.  A script specified in this way
+augments the main linker script used for the link (either the default
+linker script or the one specified by using @samp{-T}).  This feature
+permits the linker to link against a file which appears to be an object
+or an archive, but actually merely defines some symbol values, or uses
+@code{INPUT} or @code{GROUP} to load other objects.  @xref{Commands}.
+
 For options whose names are a single letter,
 option arguments must either follow the option letter without intervening
 whitespace, or be given as separate arguments immediately following the
@@ -579,6 +589,17 @@ Omit debugger symbol information (but not all symbols) from the output file.
 @item -s 
 Omit all symbol information from the output file.
 
+@ifset GENERIC
+@item -soname @var{name}
+@cindex runtime library name
+@kindex -soname
+When creating an ELF shared object, set the internal DT_SONAME field to
+the specified name.  When an executable is linked with a shared object
+which has a DT_SONAME field, then when the executable is run the dynamic
+linker will attempt to load the shared object specified by the DT_SONAME
+field rather than the using the file name given to the linker.
+@end ifset
+
 @item -sort-common
 Normally, when @code{ld} places the global common symbols in the
 appropriate output sections, it sorts them by size.  First come all the
@@ -1211,7 +1232,17 @@ SECTIONS @{ @dots{}
 @kindex Non constant expression
 @noindent
 will cause the error message ``@code{Non constant expression for initial
-address}''. 
+address}''.
+
+@cindex provide
+In some cases, it is desirable for a linker script to define a symbol
+only if it is referenced, and only if it is not defined by any object
+included in the link.  For example, traditional linkers defined the
+symbol @samp{etext}.  However, ANSI C requires that the user be able to
+use @samp{etext} as a function name without encountering an error.
+The @code{PROVIDE} keyword may be used to define a symbol, such as
+@samp{etext}, only if it is referenced but not defined.  The syntax is
+@code{PROVIDE(@var{symbol} = @var{expression})}.
 
 @node Arithmetic Functions
 @subsection Arithmetic Functions
@@ -2019,6 +2050,15 @@ search path, just as for files you specify on the command line.
 See the description of @samp{-L} in @ref{Options,,Command Line
 Options}.
 
+@kindex GROUP ( @var{files} )
+@cindex grouping input files
+@item GROUP ( @var{file}, @var{file}, @dots{} )
+@itemx GROUP ( @var{file} @var{file} @dots{} )
+This command is like @code{INPUT}, except that the named files should
+all be archives, and they are searched repeatedly until no new undefined
+references are created.  See the description of @samp{-(} in
+@ref{Options,,Command Line Options}.
+
 @ignore
 @item MAP ( @var{name} )
 @kindex MAP ( @var{name} )
index 3e6ca0aed409fd20e83213357bbcec41c5071c3e..7d139719b6e176074137caf1649d97ee96a6ff99 100644 (file)
@@ -102,8 +102,8 @@ static int error_index;
 %token <integer> SIZEOF NEXT ADDR
 %token STARTUP HLL SYSLIB FLOAT NOFLOAT
 %token ORIGIN FILL
-%token LENGTH CREATE_OBJECT_SYMBOLS INPUT OUTPUT CONSTRUCTORS
-%token ALIGNMOD AT
+%token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS
+%token ALIGNMOD AT PROVIDE
 %type <token> assign_op 
 %type <name>  filename
 %token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD
@@ -249,6 +249,10 @@ ifile_p1:
        |       FORCE_COMMON_ALLOCATION
                { command_line.force_common_definition = true ; }
        |       INPUT '(' input_list ')'
+       |       GROUP
+                 { lang_enter_group (); }
+                   '(' input_list ')'
+                 { lang_leave_group (); }
        |       MAP '(' filename ')'
                { lang_add_map($3); }
        |       INCLUDE filename 
@@ -402,14 +406,20 @@ end:      ';' | ','
 assignment:
                NAME '=' mustbe_exp
                {
-                 lang_add_assignment(exp_assop($2,$1,$3));
+                 lang_add_assignment (exp_assop ($2, $1, $3));
                }
        |       NAME assign_op mustbe_exp
                {
-               
-lang_add_assignment(exp_assop('=',$1,exp_binop($2,exp_nameop(NAME,$1),$3)));
+                 lang_add_assignment (exp_assop ('=', $1,
+                                                 exp_binop ($2,
+                                                            exp_nameop (NAME,
+                                                                        $1),
+                                                            $3)));
+               }
+       |       PROVIDE '(' NAME '=' mustbe_exp ')'
+               {
+                 lang_add_assignment (exp_provide ($3, $5));
                }
-               
        ;
 
 
@@ -564,6 +574,8 @@ exp :
                        { $$ = exp_unop(ABSOLUTE, $3); }
        |       ALIGN_K '(' exp ')'
                        { $$ = exp_unop(ALIGN_K,$3); }
+       |       BLOCK '(' exp ')'
+                       { $$ = exp_unop(ALIGN_K,$3); }
        |       NAME
                        { $$ = exp_nameop(NAME,$1); }
        ;
@@ -618,8 +630,11 @@ void
 yyerror(arg) 
      const char *arg;
 { 
+  if (ldfile_assumed_script)
+    einfo ("%P:%s: file format not recognized; treating as linker script\n",
+          ldfile_input_filename);
   if (error_index > 0 && error_index < ERROR_NAME_MAX)
-     einfo("%P%F: %S %s in %s\n", arg, error_names[error_index-1]);
+     einfo ("%P%F:%S: %s in %s\n", arg, error_names[error_index-1]);
   else
-     einfo("%P%F: %S %s\n", arg);
+     einfo ("%P%F:%S: %s\n", arg);
 }
index be46cbf0c75c9f4b0f9ce4872a10085526a5c60a..da12d8980d60015577a7ac755fba13410df8ef7c 100644 (file)
@@ -72,10 +72,6 @@ static lang_input_statement_type *new_afile
           const char *target, boolean add_to_list));
 static void print_flags PARAMS ((int *ignore_flags));
 static void init_os PARAMS ((lang_output_section_statement_type *s));
-static void wild_doit PARAMS ((lang_statement_list_type *ptr,
-                              asection *section,
-                              lang_output_section_statement_type *output,
-                              lang_input_statement_type *file));
 static void wild_section PARAMS ((lang_wild_statement_type *ptr,
                                  const char *section,
                                  lang_input_statement_type *file,
@@ -628,7 +624,7 @@ init_os (s)
 
 */
 
-static void
+void
 wild_doit (ptr, section, output, file)
      lang_statement_list_type * ptr;
      asection * section;
@@ -752,27 +748,59 @@ static void
 load_symbols (entry)
      lang_input_statement_type *entry;
 {
+  char **matching;
+
   if (entry->loaded)
     return;
 
   ldfile_open_file (entry);
 
-  if (bfd_check_format (entry->the_bfd, bfd_object))
+  if (! bfd_check_format (entry->the_bfd, bfd_archive)
+      && ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
+    {
+      bfd_error_type err;
+
+      err = bfd_get_error ();
+      if (err == bfd_error_file_ambiguously_recognized)
+       {
+         char **p;
+
+         einfo ("%B: file not recognized: %E\n", entry->the_bfd);
+         einfo ("%B: matching formats:", entry->the_bfd);
+         for (p = matching; *p != NULL; p++)
+           einfo (" %s", *p);
+         einfo ("%F\n");
+       }
+      else if (err != bfd_error_file_not_recognized)
+       einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
+
+      /* Try to interpret the file as a linker script.  */
+
+      bfd_close (entry->the_bfd);
+      entry->the_bfd = NULL;
+
+      ldfile_open_command_file (entry->filename);
+
+      ldfile_assumed_script = true;
+      parser_input = input_script;
+      yyparse ();
+      ldfile_assumed_script = false;
+
+      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
+     which is used.  */
+  if (bfd_get_format (entry->the_bfd) == bfd_object)
     {
       ldlang_add_file (entry);
       if (trace_files || trace_file_tries)
        info_msg ("%I\n", entry);
     }
-  else if (bfd_check_format (entry->the_bfd, bfd_archive))
-    {
-      /* There is nothing to do here; the add_symbols routine will
-        call ldlang_add_file (via the add_archive_element callback)
-        for each element of the archive which is used.  */
-    }
-  else
-    einfo ("%F%B: file not recognized: %E\n", entry->the_bfd);
 
-  if (bfd_link_add_symbols (entry->the_bfd, &link_info) == false)
+  if (! bfd_link_add_symbols (entry->the_bfd, &link_info))
     einfo ("%F%B: could not read symbols: %E\n", entry->the_bfd);
 
   entry->loaded = true;
@@ -1155,7 +1183,7 @@ print_output_section_statement (output_section_statement)
   print_nl ();
   if (output_section_statement->load_base)
     {
-      int b = exp_get_value_int(output_section_statement->load_base,
+      int b = exp_get_abs_int(output_section_statement->load_base,
                                0, "output base", lang_final_phase_enum);
       printf("Output address   %08x\n", b);
     }
@@ -1710,11 +1738,6 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
 
         bfd_set_section_vma (0, os->bfd_section, dot);
         
-        if (os->load_base) {
-          os->bfd_section->lma 
-            = exp_get_value_int(os->load_base, 0,"load base", lang_final_phase_enum);
-        }
-
         os->bfd_section->output_offset = 0;
        }
 
@@ -1754,6 +1777,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
           }
 
        }
+
+
      }
 
       break;
@@ -1960,6 +1985,11 @@ lang_do_assignments (s, output_section_statement, fill, dot)
                                            os->fill, dot);
                dot = os->bfd_section->vma + os->bfd_section->_raw_size;
              }
+           if (os->load_base) 
+             {
+               os->bfd_section->lma 
+                 = exp_get_abs_int(os->load_base, 0,"load base", lang_final_phase_enum);
+             }
          }
          break;
        case lang_wild_statement_enum:
@@ -2119,15 +2149,14 @@ lang_finish ()
     }
 }
 
-/* By now we know the target architecture, and we may have an */
-/* ldfile_output_machine_name */
+/* Check that the architecture of all the input files is compatible
+   with the output file.  */
+
 static void
 lang_check ()
 {
   lang_statement_union_type *file;
   bfd *input_bfd;
-  unsigned long input_machine;
-  enum bfd_architecture input_architecture;
   CONST bfd_arch_info_type *compatible;
 
   for (file = file_chain.head;
@@ -2135,36 +2164,12 @@ lang_check ()
        file = file->input_statement.next)
     {
       input_bfd = file->input_statement.the_bfd;
-
-      input_machine = bfd_get_mach (input_bfd);
-      input_architecture = bfd_get_arch (input_bfd);
-
-
-      /* Inspect the architecture and ensure we're linking like with
-         like */
-
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
-      if (compatible)
-       {
-         ldfile_output_machine = compatible->mach;
-         ldfile_output_architecture = compatible->arch;
-       }
-      else
-       {
-
-         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 (! bfd_set_arch_mach (output_bfd,
-                                  input_architecture,
-                                  input_machine))
-           einfo ("%P%F:%s: can't set architecture: %E\n",
-                  bfd_get_filename (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));
     }
 }
 
@@ -2290,6 +2295,8 @@ lang_place_orphans ()
                                 default_common_section, file);
                    }
                }
+             else if (ldemul_place_orphan (file, s))
+               ;
              else
                {
                  lang_output_section_statement_type *os =