+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.
[ -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 ]
@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
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
@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
@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
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} )
%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
| 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
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));
}
-
;
{ $$ = exp_unop(ABSOLUTE, $3); }
| ALIGN_K '(' exp ')'
{ $$ = exp_unop(ALIGN_K,$3); }
+ | BLOCK '(' exp ')'
+ { $$ = exp_unop(ALIGN_K,$3); }
| NAME
{ $$ = exp_nameop(NAME,$1); }
;
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);
}
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,
*/
-static void
+void
wild_doit (ptr, section, output, file)
lang_statement_list_type * ptr;
asection * section;
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;
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);
}
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;
}
}
}
+
+
}
break;
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:
}
}
-/* 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;
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));
}
}
default_common_section, file);
}
}
+ else if (ldemul_place_orphan (file, s))
+ ;
else
{
lang_output_section_statement_type *os =