From: Ian Lance Taylor Date: Tue, 13 Sep 1994 20:42:47 +0000 (+0000) Subject: * ldlang.c (load_symbols): Check for archive before object. Use X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0b3499f6721808b2f676a8caf8744002447c00b2;p=binutils-gdb.git * 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 . (file_name_stack): Change to be const char *. (lineno_stack): New static variable. (<>): 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. --- diff --git a/ld/ChangeLog b/ld/ChangeLog index 9db86d04bca..0a95eb262c0 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -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 . + (file_name_stack): Change to be const char *. + (lineno_stack): New static variable. + (<>): 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. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index e9a2fb7f3c8..b33094a115d 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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} ) diff --git a/ld/ldgram.y b/ld/ldgram.y index 3e6ca0aed40..7d139719b6e 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -102,8 +102,8 @@ static int error_index; %token 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 assign_op %type 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); } diff --git a/ld/ldlang.c b/ld/ldlang.c index be46cbf0c75..da12d8980d6 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -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 =