diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/.Sanitize | 2 | ||||
-rw-r--r-- | ld/ChangeLog | 27 | ||||
-rw-r--r-- | ld/Makefile.in | 15 | ||||
-rw-r--r-- | ld/NEWS | 32 | ||||
-rw-r--r-- | ld/fnmatch.c | 214 | ||||
-rw-r--r-- | ld/fnmatch.h | 69 | ||||
-rw-r--r-- | ld/ld.texinfo | 52 | ||||
-rw-r--r-- | ld/ldgram.y | 213 | ||||
-rw-r--r-- | ld/ldlang.c | 271 | ||||
-rw-r--r-- | ld/ldlex.l | 181 |
10 files changed, 903 insertions, 173 deletions
diff --git a/ld/.Sanitize b/ld/.Sanitize index a68cbf9..bf804ae 100644 --- a/ld/.Sanitize +++ b/ld/.Sanitize @@ -39,6 +39,8 @@ configure.tgt dep-in.sed emulparams emultempl +fnmatch.c +fnmatch.h genscripts.sh h8-doc.texi ld.1 diff --git a/ld/ChangeLog b/ld/ChangeLog index 8ec4902..5812270 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,30 @@ +Mon Jul 29 17:23:33 1996 Ian Lance Taylor <ian@cygnus.com> + + * fnmatch.h, fnmatch.c: New files. + * ldlex.l: Remove unused definition of FILENAME. Add definition + of WILDCHAR. In SCRIPT mode, accept any sequence of WILDCHAR as a + NAME. + * ldgram.y (file_NAME_list): Accept '*' and '?' specially. + (input_section_spec): Accept '?' specially. + (statement): Change exp to mustbe_exp in length and FILL cases. + (section): Call ldlex_script before section statements, and call + ldlex_popstate after them. + * ldlang.c: Include "fnmatch.h". + (wildcardp): New static function. + (wild_section): Permit the section name to be a wildcard. + (wild_file): New static function, broken out of wild. + (wild): Call wild_file. Permit the file name to be a wildcard. + (open_input_bfds): Don't call lookup_name for a wildcard pattern. + * Makefile.in: Rebuild dependencies. + (CFILES): Add fnmatch.c. + (HFILES): Add fnmatch.h. + (OFILES): Add fnmatch.o. + * ld.texinfo: Document that file and section names can now be + wildcard patterns. + + * ldlang.c (lang_place_orphans): Correct condition: place a common + section if not relocateable or if common definitions are forced. + start-sanitize-d10v Wed Jul 24 12:16:38 1996 Martin M. Hunt <hunt@pizza.cygnus.com> diff --git a/ld/Makefile.in b/ld/Makefile.in index b83befe..b9cb1f2 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -285,18 +285,18 @@ ALL_EMULATIONS = \ CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \ - mri.c ldcref.c + mri.c ldcref.c fnmatch.c HFILES = config.h ld.h ldctor.h ldemul.h ldexp.h ldfile.h \ ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \ - ldwrite.h mri.h + ldwrite.h mri.h fnmatch.h GENERATED_CFILES = ldgram.c ldlex.c GENERATED_HFILES = ldgram.h ldemul-list.h OFILES = ldgram.o ldlex.o lexsup.o ldlang.o mri.o ldctor.o ldmain.o \ ldwrite.o ldexp.o ldemul.o ldver.o ldmisc.o \ - ldfile.o ldcref.o ${EMULATION_OFILES} + ldfile.o ldcref.o fnmatch.o ${EMULATION_OFILES} LINTSOURCES = $(CFILES) $(GENERATED_CFILES) e*.c @@ -1015,7 +1015,7 @@ ldlang.o: ldlang.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/obstack.h sysdep.h config.h $(INCDIR)/fopen-same.h \ $(INCDIR)/libiberty.h $(INCDIR)/bfdlink.h ld.h ldmain.h \ ldgram.h ldexp.h ldlang.h ldemul.h ldlex.h ldmisc.h \ - ldctor.h ldfile.h + ldctor.h ldfile.h fnmatch.h ldmain.o: ldmain.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/obstack.h sysdep.h config.h $(INCDIR)/fopen-same.h \ $(INCDIR)/libiberty.h $(INCDIR)/progress.h $(INCDIR)/bfdlink.h \ @@ -1034,9 +1034,9 @@ ldwrite.o: ldwrite.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ ldlang.h ldwrite.h ldmisc.h ldgram.h ldmain.h lexsup.o: lexsup.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/obstack.h sysdep.h config.h $(INCDIR)/fopen-same.h \ - $(INCDIR)/getopt.h $(INCDIR)/bfdlink.h ld.h ldmain.h \ - ldmisc.h ldexp.h ldlang.h ldgram.h ldlex.h ldfile.h \ - ldver.h ldemul.h + $(INCDIR)/libiberty.h $(INCDIR)/getopt.h $(INCDIR)/bfdlink.h \ + ld.h ldmain.h ldmisc.h ldexp.h ldlang.h ldgram.h ldlex.h \ + ldfile.h ldver.h ldemul.h mri.o: mri.c ../bfd/bfd.h $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h \ sysdep.h config.h $(INCDIR)/fopen-same.h ld.h ldexp.h \ ldlang.h ldmisc.h mri.h ldgram.h @@ -1044,6 +1044,7 @@ ldcref.o: ldcref.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/obstack.h sysdep.h config.h $(INCDIR)/fopen-same.h \ $(INCDIR)/bfdlink.h $(INCDIR)/libiberty.h ld.h ldmain.h \ ldmisc.h +fnmatch.o: fnmatch.c ldgram.o: ldgram.c ../bfd/bfd.h $(INCDIR)/ansidecl.h \ $(INCDIR)/obstack.h sysdep.h config.h $(INCDIR)/fopen-same.h \ $(INCDIR)/bfdlink.h ld.h ldexp.h ldver.h ldlang.h ldemul.h \ @@ -1,5 +1,25 @@ -*- text -*- +Changes since version 2.7: + +* Linker scripts may now contain shell wildcard characters for file and section + names. + +Changes since version 2.6: + +* New option --cref to print out a cross reference table. + +* New option --wrap SYMBOL. + +* New option --no-whole-archive, to turn off the effect of --whole-archive. + +* Input sections assigned to the output section /DISCARD/ in the linker script + are not included in the output file. + +* The SunOS and ELF linkers now merge stabs debugging information which uses + the N_BINCL and N_EINCL stab types. This reduces the amount of debugging + information generated. + Changes since version 2.5: * When an ELF section name is representable as a C identifier (this is not true @@ -20,11 +40,13 @@ glibc. * New options -split-by-reloc and -split-by-file. * The linker now supports linking PIC compiled code on SPARC SunOS. It can -also create SPARC SunOS shared libraries. The native SunOS linker will do this -when linking code which has an undefined symbol, but the GNU linker requires -the -shared option. For convenience when used with gcc -shared, the GNU linker -will also create a shared library when given the -assert pure-text option, -although this is not really what -assert pure-text should mean. +also create SPARC SunOS shared libraries, and, like the native SunOS linker, +will do so whenever there is an undefined symbol in the link and neither the -e +nor the -r option was used. + +* The -rpath option may be used on SunOS to set the list of directories to be +searched at run time. This overrides the default of building the list from the +-L options. * The COFF linker now combines debugging information for structs, unions, and enums, so that even if the same type is defined in multiple input files it will diff --git a/ld/fnmatch.c b/ld/fnmatch.c new file mode 100644 index 0000000..11f896f --- /dev/null +++ b/ld/fnmatch.c @@ -0,0 +1,214 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +This program 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 2, or (at your option) any +later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include <errno.h> +#include <fnmatch.h> +#include <ctype.h> + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS) +extern int errno; +#endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int +fnmatch (pattern, string, flags) + const char *pattern; + const char *string; + int flags; +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evalutes C many times. */ +#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + c = FOLD (c); + } + if (FOLD (*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) + if (((flags & FNM_FILE_NAME) && *n == '/') || + (c == '?' && *n == '\0')) + return FNM_NOMATCH; + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + c1 = FOLD (c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD (*n) == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + cstart = cend = *p++; + + cstart = cend = FOLD (cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD (c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD (cend); + + c = *p++; + } + + if (FOLD (*n) >= cstart && FOLD (*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD (*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/ld/fnmatch.h b/ld/fnmatch.h new file mode 100644 index 0000000..1a653ab --- /dev/null +++ b/ld/fnmatch.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + +NOTE: The canonical source of this file is maintained with the GNU C Library. +Bugs can be reported to bug-glibc@prep.ai.mit.edu. + +This program 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 2, or (at your option) any +later version. + +This program 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _FNMATCH_H + +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#undef __P +#define __P(args) args +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(args) () +/* We can get away without defining `const' here only because in this file + it is used only inside the prototype for `fnmatch', which is elided in + non-ANSI C where `const' is problematical. */ +#endif /* C++ or ANSI C. */ + + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in <unistd.h>. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined (_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 2 || defined (_GNU_SOURCE) +#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* Match STRING against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch __P ((const char *__pattern, const char *__string, + int __flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/ld/ld.texinfo b/ld/ld.texinfo index bdb7644..73057c4 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -642,6 +642,19 @@ for a program linked against a shared library to override the definition within the shared library. This option is only meaningful on ELF platforms which support shared libraries. +@cindex cross reference table +@kindex --cref +@item --cref +Output a cross reference table. If a linker map file is being +generated, the cross reference table is printed to the map file. +Otherwise, it is printed on the standard output. + +The format of the table is intentionally simple, so that it may be +easily processed by a script if necessary. The symbols are printed out, +sorted by name. For each symbol, a list of file names is given. If the +symbol is defined, the first file listed is the location of the +definition. The remaining files contain references to the symbol. + @cindex symbols, from command line @kindex --defsym @var{symbol}=@var{exp} @item --defsym @var{symbol}=@var{expression} @@ -1864,7 +1877,7 @@ beginning of the section. The @var{contents} of a section definition may include any of the following kinds of statement. You can include as many of these as you like in a single section definition, separated from one another by -whitespace. +whitespace. @table @code @kindex @var{filename} @@ -1949,8 +1962,23 @@ were in an input-file section named @code{COMMON}, regardless of the input file's format. @end table -For example, the following command script arranges the output file into -three consecutive sections, named @code{.text}, @code{.data}, and +In any place where you may use a specific file or section name, you may +also use a wildcard pattern. The wildcard handling is similar to that +used by the Unix shell. A @samp{*} character matches any number of +characters. A @samp{?} character matches any single character. The +sequence @samp{[@var{chars}]} will match a single instance of any of the +@var{chars}; the @samp{-} character may be used to specify a range of +characters, as in @samp{[a-z]} to match any lower case letter. A +@samp{\} character may be used to quote the following character. + +When using a wildcard to match a file name, the wildcard characters will +not match a @samp{/} character (used to separate directory names on +Unix). A pattern consisting of a single @samp{*} character is an +exception; it will always match any file name. The wildcard characters +will match a @samp{/} character in a section name. + +In the following example, the command script arranges the output file +into three consecutive sections, named @code{.text}, @code{.data}, and @code{.bss}, taking the input for each from the correspondingly named sections of all the input files: @@ -1995,6 +2023,24 @@ SECTIONS @{ @end group @end smallexample +This example shows how wildcard patterns might be used to partition +files. All @code{.text} sections are placed in @code{.text}, and all +@code{.bss} sections are placed in @code{.bss}. For all files beginning +with an upper case character, the @code{.data} section is placed into +@code{.DATA}; for all other files, the @code{.data} section is placed +into @code{.data}. + +@smallexample +@group +SECTIONS @{ + .text : @{ *(.text) @} + .DATA : @{ [A-Z]*(.data) @} + .data : @{ *(.data) @} + .bss : @{ *(.bss) @} +@} +@end group +@end smallexample + @node Section Data Expressions @subsection Section Data Expressions diff --git a/ld/ldgram.y b/ld/ldgram.y index 7e6f1e8..92ba5bc 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -1,5 +1,5 @@ /* A YACC grammer to parse a superset of the AT&T linker scripting languaue. - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support (steve@cygnus.com). This file is part of GNU ld. @@ -43,7 +43,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define YYDEBUG 1 #endif -static int typebits; +static enum section_type sectype; lang_memory_region_type *region; @@ -68,14 +68,22 @@ static int error_index; char *name; int token; union etree_union *etree; + struct phdr_info + { + boolean filehdr; + boolean phdrs; + union etree_union *at; + union etree_union *flags; + } phdr; } -%type <etree> exp opt_exp_with_type mustbe_exp opt_at +%type <etree> exp opt_exp_with_type mustbe_exp opt_at phdr_type phdr_val %type <integer> fill_opt %type <name> memspec_opt casesymlist %token <integer> INT %token <name> NAME LNAME %type <integer> length +%type <phdr> phdr_qualifiers %right <token> PLUSEQ MINUSEQ MULTEQ DIVEQ '=' LSHIFTEQ RSHIFTEQ ANDEQ OREQ %right <token> '?' ':' @@ -94,8 +102,8 @@ static int error_index; %right UNARY %token END %left <token> '(' -%token <token> ALIGN_K BLOCK QUAD LONG SHORT BYTE -%token SECTIONS +%token <token> ALIGN_K BLOCK BIND QUAD LONG SHORT BYTE +%token SECTIONS PHDRS %token '{' '}' %token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH %token SIZEOF_HEADERS @@ -108,7 +116,7 @@ static int error_index; %token ORIGIN FILL %token LENGTH CREATE_OBJECT_SYMBOLS INPUT GROUP OUTPUT CONSTRUCTORS %token ALIGNMOD AT PROVIDE -%type <token> assign_op +%type <token> assign_op atype %type <name> filename %token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL @@ -136,12 +144,15 @@ defsym_expr: /* SYNTAX WITHIN AN MRI SCRIPT FILE */ mri_script_file: - { ldlex_mri_script(); - PUSH_ERROR("MRI style script"); + { + ldlex_mri_script (); + PUSH_ERROR ("MRI style script"); } mri_script_lines - { ldlex_popstate(); - POP_ERROR(); + { + ldlex_popstate (); + mri_draw_tree (); + POP_ERROR (); } ; @@ -177,8 +188,12 @@ mri_script_command: { mri_output_section($2, $4);} | ALIGN_K NAME '=' exp { mri_align($2,$4); } + | ALIGN_K NAME ',' exp + { mri_align($2,$4); } | ALIGNMOD NAME '=' exp { mri_alignmod($2,$4); } + | ALIGNMOD NAME ',' exp + { mri_alignmod($2,$4); } | ABSOLUTE mri_abs_name_list | LOAD mri_load_name_list | NAMEWORD NAME @@ -196,7 +211,7 @@ mri_script_command: | INCLUDE filename { ldfile_open_command_file ($2); } mri_script_lines END | START NAME - { lang_add_entry ($2, 0); } + { lang_add_entry ($2, false); } | ; @@ -253,6 +268,7 @@ ifile_list: ifile_p1: memory | sections + | phdrs | startup | high_level_library | low_level_library @@ -318,15 +334,25 @@ sec_or_group_p1: statement_anywhere: ENTRY '(' NAME ')' - { lang_add_entry ($3, 0); } + { lang_add_entry ($3, false); } | assignment end ; +/* The '*' and '?' cases are there because the lexer returns them as + separate tokens rather than as NAME. */ file_NAME_list: NAME - { lang_add_wild($1, current_file); } + { lang_add_wild ($1, current_file); } + | '*' + { lang_add_wild ("*", current_file); } + | '?' + { lang_add_wild ("?", current_file); } | file_NAME_list opt_comma NAME - { lang_add_wild($3, current_file); } + { lang_add_wild ($3, current_file); } + | file_NAME_list opt_comma '*' + { lang_add_wild ("*", current_file); } + | file_NAME_list opt_comma '?' + { lang_add_wild ("?", current_file); } ; input_section_spec: @@ -342,7 +368,14 @@ input_section_spec: ']' | NAME { - current_file =$1; + current_file = $1; + } + '(' file_NAME_list ')' + | '?' + /* This case is needed because the lexer returns a + single question mark as '?' rather than NAME. */ + { + current_file = "?"; } '(' file_NAME_list ')' | '*' @@ -365,12 +398,12 @@ statement: lang_add_attribute(lang_constructors_statement_enum); } | input_section_spec - | length '(' exp ')' + | length '(' mustbe_exp ')' { lang_add_data((int) $1,$3); } - | FILL '(' exp ')' + | FILL '(' mustbe_exp ')' { lang_add_fill (exp_get_value_int($3, @@ -623,36 +656,57 @@ opt_at: section: NAME { ldlex_expression(); } opt_exp_with_type - opt_at { ldlex_popstate(); } + opt_at { ldlex_popstate (); ldlex_script (); } '{' { - lang_enter_output_section_statement($1,$3,typebits,0,0,0,$4); + lang_enter_output_section_statement($1, $3, + sectype, + 0, 0, 0, $4); } statement_list_opt - '}' {ldlex_expression();} memspec_opt fill_opt + '}' { ldlex_popstate (); ldlex_expression (); } + memspec_opt phdr_opt fill_opt { ldlex_popstate(); - lang_leave_output_section_statement($12, $11); + lang_leave_output_section_statement($13, $11); } -opt_comma - + opt_comma + | /* The GROUP case is just enough to support the gcc + svr3.ifile script. It is not intended to be full + support. I'm not even sure what GROUP is supposed + to mean. */ + GROUP { ldlex_expression (); } + opt_exp_with_type + { + ldlex_popstate (); + lang_add_assignment (exp_assop ('=', ".", $3)); + } + '{' sec_or_group_p1 '}' ; type: - NOLOAD { typebits = SEC_NEVER_LOAD; } - | DSECT { typebits = 0; } - | COPY { typebits = 0; } - | INFO { typebits = 0; } - | OVERLAY { typebits = 0; } - | { typebits = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; } + NOLOAD { sectype = noload_section; } + | DSECT { sectype = dsect_section; } + | COPY { sectype = copy_section; } + | INFO { sectype = info_section; } + | OVERLAY { sectype = overlay_section; } ; +atype: + '(' type ')' + | /* EMPTY */ { sectype = normal_section; } + ; opt_exp_with_type: - exp ':' { $$ = $1; typebits =0;} - | exp '(' type ')' ':' { $$ = $1; } - | ':' { $$= (etree_type *)NULL; typebits = 0; } - | '(' type ')' ':' { $$= (etree_type *)NULL; } + exp atype ':' { $$ = $1; } + | atype ':' { $$ = (etree_type *)NULL; } + | /* The BIND cases are to support the gcc svr3.ifile + script. They aren't intended to implement full + support for the BIND keyword. I'm not even sure + what BIND is supposed to mean. */ + BIND '(' exp ')' atype ':' { $$ = $3; } + | BIND '(' exp ')' BLOCK '(' exp ')' atype ':' + { $$ = $3; } ; memspec_opt: @@ -660,6 +714,99 @@ memspec_opt: { $$ = $2; } | { $$ = "*default*"; } ; + +phdr_opt: + /* empty */ + | phdr_opt ':' NAME + { + lang_section_in_phdr ($3); + } + ; + +phdrs: + PHDRS '{' phdr_list '}' + ; + +phdr_list: + /* empty */ + | phdr_list phdr + ; + +phdr: + NAME { ldlex_expression (); } + phdr_type phdr_qualifiers { ldlex_popstate (); } + ';' + { + lang_new_phdr ($1, $3, $4.filehdr, $4.phdrs, $4.at, + $4.flags); + } + ; + +phdr_type: + exp + { + $$ = $1; + + if ($1->type.node_class == etree_name + && $1->type.node_code == NAME) + { + const char *s; + unsigned int i; + static const char * const phdr_types[] = + { + "PT_NULL", "PT_LOAD", "PT_DYNAMIC", + "PT_INTERP", "PT_NOTE", "PT_SHLIB", + "PT_PHDR" + }; + + s = $1->name.name; + for (i = 0; + i < sizeof phdr_types / sizeof phdr_types[0]; + i++) + if (strcmp (s, phdr_types[i]) == 0) + { + $$ = exp_intop (i); + break; + } + } + } + ; + +phdr_qualifiers: + /* empty */ + { + memset (&$$, 0, sizeof (struct phdr_info)); + } + | NAME phdr_val phdr_qualifiers + { + $$ = $3; + if (strcmp ($1, "FILEHDR") == 0 && $2 == NULL) + $$.filehdr = true; + else if (strcmp ($1, "PHDRS") == 0 && $2 == NULL) + $$.phdrs = true; + else if (strcmp ($1, "FLAGS") == 0 && $2 != NULL) + $$.flags = $2; + else + einfo ("%X%P:%S: PHDRS syntax error at `%s'\n", $1); + } + | AT '(' exp ')' phdr_qualifiers + { + $$ = $5; + $$.at = $3; + } + ; + +phdr_val: + /* empty */ + { + $$ = NULL; + } + | '(' exp ')' + { + $$ = $2; + } + ; + %% void yyerror(arg) diff --git a/ld/ldlang.c b/ld/ldlang.c index d3924a0..94f58f9 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -32,6 +32,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 #include "ldmisc.h" #include "ldctor.h" #include "ldfile.h" +#include "fnmatch.h" /* FORWARDS */ static lang_statement_union_type *new_statement PARAMS ((enum statement_enum, @@ -64,7 +65,9 @@ static lang_input_statement_type *new_afile PARAMS ((const char *name, lang_input_file_enum_type file_type, const char *target, boolean add_to_list)); static void init_os PARAMS ((lang_output_section_statement_type *s)); +static void exp_init_os PARAMS ((etree_type *)); static void section_already_linked PARAMS ((bfd *, asection *, PTR)); +static boolean wildcardp PARAMS ((const char *)); static void wild_section PARAMS ((lang_wild_statement_type *ptr, const char *section, lang_input_statement_type *file, @@ -72,6 +75,9 @@ static void wild_section PARAMS ((lang_wild_statement_type *ptr, static lang_input_statement_type *lookup_name PARAMS ((const char *name)); static void load_symbols PARAMS ((lang_input_statement_type *entry, lang_statement_list_type *)); +static void wild_file PARAMS ((lang_wild_statement_type *, const char *, + lang_input_statement_type *, + lang_output_section_statement_type *)); static void wild PARAMS ((lang_wild_statement_type *s, const char *section, const char *file, const char *target, @@ -283,7 +289,6 @@ new_afile (name, file_type, target, add_to_list) lang_has_input_file = true; p->target = target; - p->complained = false; switch (file_type) { case lang_input_file_is_symbols_only_enum: @@ -342,7 +347,6 @@ new_afile (name, file_type, target, add_to_list) p->next_real_file = (lang_statement_union_type *) NULL; p->next = (lang_statement_union_type *) NULL; p->symbol_count = 0; - p->common_output_section = (asection *) NULL; p->dynamic = config.dynamic_link; p->whole_archive = whole_archive; p->loaded = false; @@ -490,7 +494,7 @@ lang_output_section_statement_lookup (name) lookup->next = (lang_statement_union_type *) NULL; lookup->bfd_section = (asection *) NULL; lookup->processed = false; - lookup->loadable = 1; + lookup->sectype = normal_section; lookup->addr_tree = (etree_type *) NULL; lang_list_init (&lookup->children); @@ -543,15 +547,17 @@ lang_map () print_statements (); } -/* - * - */ +/* Initialize an output section. */ + static void init_os (s) - lang_output_section_statement_type * s; + lang_output_section_statement_type *s; { section_userdata_type *new; + if (s->bfd_section != NULL) + return; + if (strcmp (s->name, DISCARD_SECTION_NAME) == 0) einfo ("%P%F: Illegal use of `%s' section", DISCARD_SECTION_NAME); @@ -572,6 +578,59 @@ init_os (s) /* vma to allow us to output a section through itself */ s->bfd_section->output_offset = 0; get_userdata (s->bfd_section) = (PTR) new; + + /* If there is a base address, make sure that any sections it might + mention are initialized. */ + if (s->addr_tree != NULL) + exp_init_os (s->addr_tree); +} + +/* Make sure that all output sections mentioned in an expression are + initialized. */ + +static void +exp_init_os (exp) + etree_type *exp; +{ + switch (exp->type.node_class) + { + case etree_assign: + exp_init_os (exp->assign.src); + break; + + case etree_binary: + exp_init_os (exp->binary.lhs); + exp_init_os (exp->binary.rhs); + break; + + case etree_trinary: + exp_init_os (exp->trinary.cond); + exp_init_os (exp->trinary.lhs); + exp_init_os (exp->trinary.rhs); + break; + + case etree_unary: + exp_init_os (exp->unary.child); + break; + + case etree_name: + switch (exp->type.node_code) + { + case ADDR: + case SIZEOF: + { + lang_output_section_statement_type *os; + + os = lang_output_section_find (exp->name.name); + if (os != NULL && os->bfd_section == NULL) + init_os (os); + } + } + break; + + default: + break; + } } /* Sections marked with the SEC_LINK_ONCE flag should only be linked @@ -661,6 +720,23 @@ section_already_linked (abfd, sec, ignore) explicit actions, like foo.o(.text), bar.o(.text) and foo.o(.text, .data). */ +/* Return true if the PATTERN argument is a wildcard pattern. */ + +static boolean +wildcardp (pattern) + const char *pattern; +{ + const char *s; + + for (s = pattern; *s != '\0'; ++s) + if (*s == '?' + || *s == '\\' + || *s == '*' + || *s == '[') + return true; + return false; +} + /* Add SECTION to the output section OUTPUT. Do this by creating a lang_input_section statement which is placed at PTR. FILE is the input file which holds SECTION. */ @@ -725,15 +801,33 @@ wild_doit (ptr, section, output, file) SEC_NEVER_LOAD section in the middle of an otherwise loaded section (I don't know why we want to do this, but we do). build_link_order in ldwrite.c handles this case by turning - the embedded SEC_NEVER_LOAD section into a fill. */ + the embedded SEC_NEVER_LOAD section into a fill. + + If final link, don't copy the SEC_LINK_ONCE flags, they've already + been processed. One reason to do this is that on pe format targets, + .text$foo sections go into .text and it's odd to see .text with + SEC_LINK_ONCE set. */ + section->output_section->flags |= - section->flags & (flagword) (~ SEC_NEVER_LOAD); + section->flags & (flagword) (~ (SEC_NEVER_LOAD + | (! link_info.relocateable + ? SEC_LINK_ONCE | SEC_LINK_DUPLICATES + : 0))); - if (! output->loadable) + switch (output->sectype) { - /* Turn off load flag */ + case normal_section: + break; + case dsect_section: + case copy_section: + case info_section: + case overlay_section: + output->bfd_section->flags &= ~SEC_ALLOC; + break; + case noload_section: output->bfd_section->flags &= ~SEC_LOAD; output->bfd_section->flags |= SEC_NEVER_LOAD; + break; } if (section->alignment_power > output->bfd_section->alignment_power) @@ -758,9 +852,17 @@ wild_section (ptr, section, file, output) 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; + /* Attach all sections named SECTION. If SECTION is NULL, then attach all sections. @@ -769,9 +871,19 @@ wild_section (ptr, section, file, output) section. I did not understand that, and I took it out. --ian@cygnus.com. */ - if (section == NULL - || strcmp (bfd_get_section_name (file->the_bfd, s), - section) == 0) + 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) wild_doit (&ptr->children, s, output, file); } } @@ -922,6 +1034,44 @@ load_symbols (entry, place) entry->loaded = true; } +/* Handle a wild statement for a single file F. */ + +static void +wild_file (s, section, f, output) + lang_wild_statement_type *s; + const char *section; + lang_input_statement_type *f; + lang_output_section_statement_type *output; +{ + if (f->the_bfd == NULL + || ! bfd_check_format (f->the_bfd, bfd_archive)) + wild_section (s, section, f, output); + 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) + { + wild_section (s, section, + (lang_input_statement_type *) member->usrdata, + output); + } + + member = bfd_openr_next_archived_file (f->the_bfd, member); + } + } +} + /* Handle a wild statement. SECTION or FILE or both may be NULL, indicating that it is a wildcard. Separate lang_input_section statements are created for each part of the expansion; they are @@ -944,40 +1094,24 @@ wild (s, section, file, target, output) f != (lang_input_statement_type *) NULL; f = (lang_input_statement_type *) f->next) { - wild_section (s, section, f, output); + wild_file (s, section, f, output); + } + } + 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) + wild_file (s, section, f, output); } } else { /* Perform the iteration over a single file */ f = lookup_name (file); - if (f->the_bfd == NULL - || ! bfd_check_format (f->the_bfd, bfd_archive)) - wild_section (s, section, f, output); - 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) - { - wild_section (s, section, - (lang_input_statement_type *) member->usrdata, - output); - } - - member = bfd_openr_next_archived_file (f->the_bfd, member); - } - } + wild_file (s, section, f, output); } if (section != (char *) NULL @@ -1016,7 +1150,7 @@ open_output (name) einfo ("%P%F: cannot open output file %s: %E\n", name); } - delete_output_file_on_failure = 1; + delete_output_file_on_failure = true; /* output->flags |= D_PAGED;*/ @@ -1089,7 +1223,8 @@ open_input_bfds (s, force) break; case lang_wild_statement_enum: /* Maybe we should load the file's symbols */ - if (s->wild_statement.filename) + if (s->wild_statement.filename + && ! wildcardp (s->wild_statement.filename)) (void) lookup_name (s->wild_statement.filename); open_input_bfds (s->wild_statement.children.head, force); break; @@ -1269,13 +1404,21 @@ map_input_to_output_sections (s, target, output_section_statement) case lang_object_symbols_statement_enum: case lang_data_statement_enum: case lang_reloc_statement_enum: - case lang_assignment_statement_enum: case lang_padding_statement_enum: case lang_input_statement_enum: if (output_section_statement != NULL && output_section_statement->bfd_section == NULL) init_os (output_section_statement); break; + case lang_assignment_statement_enum: + if (output_section_statement != NULL + && output_section_statement->bfd_section == NULL) + init_os (output_section_statement); + + /* Make sure that any sections mentioned in the assignment + are initialized. */ + exp_init_os (s->assignment_statement.exp); + break; case lang_afile_asection_pair_statement_enum: FAIL (); break; @@ -1594,7 +1737,7 @@ print_padding_statement (s) minfo ("0x%V %W", addr, s->size); if (s->fill != 0) - minfo (" 0x%x", s->fill); + minfo (" %u", s->fill); print_nl (); @@ -1746,7 +1889,7 @@ dprint_statement (s, n) print_statement_list (s, abs_output_section); else { - while (--n >= 0) + while (s && --n >= 0) { print_statement (s, abs_output_section); s = s->next; @@ -2609,19 +2752,22 @@ lang_place_orphans () s->output_section = bfd_abs_section_ptr; s->output_offset = s->vma; } - else if (file->common_section == s) + else if (strcmp (s->name, "COMMON") == 0) { - /* This is a lonely common section which must - have come from an archive. We attatch to the - section with the wildcard */ + /* This is a lonely common section which must have + come from an archive. We attach to the section + with the wildcard. */ if (! link_info.relocateable - && ! command_line.force_common_definition) + || command_line.force_common_definition) { - if (default_common_section == - (lang_output_section_statement_type *) NULL) + if (default_common_section == NULL) { +#if 0 + /* This message happens when using the + svr3.ifile linker script, so I have + disabled it. */ info_msg ("%P: no [COMMON] command, defaulting to .bss\n"); - +#endif default_common_section = lang_output_section_statement_lookup (".bss"); @@ -2815,13 +2961,14 @@ topower (x) return 0; } + void lang_enter_output_section_statement (output_section_statement_name, - address_exp, flags, block_value, + address_exp, sectype, block_value, align, subalign, ebase) const char *output_section_statement_name; etree_type * address_exp; - int flags; + enum section_type sectype; bfd_vma block_value; etree_type *align; etree_type *subalign; @@ -2846,11 +2993,11 @@ lang_enter_output_section_statement (output_section_statement_name, os->addr_tree = address_exp; } - os->flags = flags; - if (flags & SEC_NEVER_LOAD) - os->loadable = 0; + os->sectype = sectype; + if (sectype != noload_section) + os->flags = SEC_NO_FLAGS; else - os->loadable = 1; + os->flags = SEC_NEVER_LOAD; os->block_value = block_value ? block_value : 1; stat_ptr = &os->children; @@ -3404,7 +3551,7 @@ lang_record_phdrs () last = pl; else { - if (! os->loadable + if (os->sectype == noload_section || os->bfd_section == NULL || (os->bfd_section->flags & SEC_ALLOC) == 0) continue; @@ -1,6 +1,6 @@ %{ -/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. +/* Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GLD; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This was written by steve chamberlain @@ -26,12 +26,13 @@ This was written by steve chamberlain #include <ansidecl.h> #include <stdio.h> -/* start-sanitize-mpw */ +#include <ctype.h> + #ifdef MPW /* Prevent enum redefinition problems. */ #define TRUE_FALSE_ALREADY_DEFINED #endif /* MPW */ -/* end-sanitize-mpw */ + #include "bfd.h" #include "sysdep.h" #include "ld.h" @@ -54,9 +55,14 @@ int hex_mode; (FIXME Actually, it doesn't appear to get reset for each file?) */ unsigned int lineno = 1; +/* The string we are currently lexing, or NULL if we are reading a + file. */ +const char *lex_string = NULL; + /* Support for flex reading from more than one input file (stream). `include_stack' is flex's input state for each open file; - `file_name_stack' is the file names. + `file_name_stack' is the file names. `lineno_stack' is the current + line numbers. If `include_stack_ptr' is 0, we haven't started reading anything yet. Otherwise, stack elements 0 through `include_stack_ptr - 1' are valid. */ @@ -66,7 +72,8 @@ unsigned int lineno = 1; #define MAX_INCLUDE_DEPTH 10 static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; -static char *file_name_stack[MAX_INCLUDE_DEPTH]; +static const char *file_name_stack[MAX_INCLUDE_DEPTH]; +static unsigned int lineno_stack[MAX_INCLUDE_DEPTH]; static unsigned int include_stack_ptr = 0; static YY_BUFFER_STATE yy_create_string_buffer PARAMS ((const char *string, @@ -99,7 +106,7 @@ CMDFILENAMECHAR1 [_a-zA-Z0-9\/\.\\_\+\$\:\[\]\\\,\=\&\!\<\>\~] FILENAMECHAR1 [_a-zA-Z\/\.\\\$\_\~] SYMBOLCHARN [_a-zA-Z\/\.\\0-9] FILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\=\$\:\[\]\\\,\~] -FILENAME {FILENAMECHAR}+ +WILDCHAR [_a-zA-Z0-9\/\.\-\_\+\=\$\:\[\]\\\,\~\?\*] WHITE [ \t\n\r]+ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] @@ -139,23 +146,27 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] return INT; } -<MRI,EXPRESSION>([0-9A-Fa-f])+(H|X|B|O|D) { +<MRI,EXPRESSION>([0-9A-Fa-f])+(H|h|X|x|B|b|O|o|D|d) { int ibase ; switch (yytext[yyleng-1]) { case 'X': + case 'x': case 'H': + case 'h': ibase = 16; break; case 'O': + case 'o': ibase = 8; break; case 'B': + case 'b': ibase = 2; break; default: ibase = 10; } - yylval.integer = bfd_scan_vma (yytext+1, 0, + yylval.integer = bfd_scan_vma (yytext, 0, ibase); return INT; } @@ -172,47 +183,48 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] } return INT; } -<BOTH,SCRIPT,EXPRESSION>"]" { RTOKEN(']');} -<BOTH,SCRIPT,EXPRESSION>"[" { RTOKEN('[');} -<BOTH,SCRIPT,EXPRESSION>"<<=" { RTOKEN(LSHIFTEQ);} -<BOTH,SCRIPT,EXPRESSION>">>=" { RTOKEN(RSHIFTEQ);} -<BOTH,SCRIPT,EXPRESSION>"||" { RTOKEN(OROR);} -<BOTH,SCRIPT,EXPRESSION>"==" { RTOKEN(EQ);} -<BOTH,SCRIPT,EXPRESSION>"!=" { RTOKEN(NE);} -<BOTH,SCRIPT,EXPRESSION>">=" { RTOKEN(GE);} -<BOTH,SCRIPT,EXPRESSION>"<=" { RTOKEN(LE);} -<BOTH,SCRIPT,EXPRESSION>"<<" { RTOKEN(LSHIFT);} -<BOTH,SCRIPT,EXPRESSION>">>" { RTOKEN(RSHIFT);} -<BOTH,SCRIPT,EXPRESSION>"+=" { RTOKEN(PLUSEQ);} -<BOTH,SCRIPT,EXPRESSION>"-=" { RTOKEN(MINUSEQ);} -<BOTH,SCRIPT,EXPRESSION>"*=" { RTOKEN(MULTEQ);} -<BOTH,SCRIPT,EXPRESSION>"/=" { RTOKEN(DIVEQ);} -<BOTH,SCRIPT,EXPRESSION>"&=" { RTOKEN(ANDEQ);} -<BOTH,SCRIPT,EXPRESSION>"|=" { RTOKEN(OREQ);} -<BOTH,SCRIPT,EXPRESSION>"&&" { RTOKEN(ANDAND);} -<BOTH,SCRIPT,EXPRESSION>">" { RTOKEN('>');} -<MRI,BOTH,SCRIPT,EXPRESSION>"," { RTOKEN(',');} -<BOTH,SCRIPT,EXPRESSION>"&" { RTOKEN('&');} -<BOTH,SCRIPT,EXPRESSION>"|" { RTOKEN('|');} -<BOTH,SCRIPT,EXPRESSION>"~" { RTOKEN('~');} -<BOTH,SCRIPT,EXPRESSION>"!" { RTOKEN('!');} -<BOTH,SCRIPT,EXPRESSION>"?" { RTOKEN('?');} -<BOTH,SCRIPT,EXPRESSION>"*" { RTOKEN('*');} -<BOTH,SCRIPT,EXPRESSION>"+" { RTOKEN('+');} -<BOTH,SCRIPT,EXPRESSION>"-" { RTOKEN('-');} -<BOTH,SCRIPT,EXPRESSION>"/" { RTOKEN('/');} -<BOTH,SCRIPT,EXPRESSION>"%" { RTOKEN('%');} -<BOTH,SCRIPT,EXPRESSION>"<" { RTOKEN('<');} -<MRI,BOTH,SCRIPT,EXPRESSION>"=" { RTOKEN('=');} -<BOTH,SCRIPT,EXPRESSION>"}" { RTOKEN('}') ; } -<BOTH,SCRIPT,EXPRESSION>"{" { RTOKEN('{'); } -<BOTH,SCRIPT,EXPRESSION>")" { RTOKEN(')');} -<BOTH,SCRIPT,EXPRESSION>"(" { RTOKEN('(');} -<BOTH,SCRIPT,EXPRESSION>":" { RTOKEN(':'); } -<BOTH,SCRIPT,EXPRESSION>";" { RTOKEN(';');} +<BOTH,SCRIPT,EXPRESSION,MRI>"]" { RTOKEN(']');} +<BOTH,SCRIPT,EXPRESSION,MRI>"[" { RTOKEN('[');} +<BOTH,SCRIPT,EXPRESSION,MRI>"<<=" { RTOKEN(LSHIFTEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>">>=" { RTOKEN(RSHIFTEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"||" { RTOKEN(OROR);} +<BOTH,SCRIPT,EXPRESSION,MRI>"==" { RTOKEN(EQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"!=" { RTOKEN(NE);} +<BOTH,SCRIPT,EXPRESSION,MRI>">=" { RTOKEN(GE);} +<BOTH,SCRIPT,EXPRESSION,MRI>"<=" { RTOKEN(LE);} +<BOTH,SCRIPT,EXPRESSION,MRI>"<<" { RTOKEN(LSHIFT);} +<BOTH,SCRIPT,EXPRESSION,MRI>">>" { RTOKEN(RSHIFT);} +<BOTH,SCRIPT,EXPRESSION,MRI>"+=" { RTOKEN(PLUSEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"-=" { RTOKEN(MINUSEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"*=" { RTOKEN(MULTEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"/=" { RTOKEN(DIVEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"&=" { RTOKEN(ANDEQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"|=" { RTOKEN(OREQ);} +<BOTH,SCRIPT,EXPRESSION,MRI>"&&" { RTOKEN(ANDAND);} +<BOTH,SCRIPT,EXPRESSION,MRI>">" { RTOKEN('>');} +<BOTH,SCRIPT,EXPRESSION,MRI>"," { RTOKEN(',');} +<BOTH,SCRIPT,EXPRESSION,MRI>"&" { RTOKEN('&');} +<BOTH,SCRIPT,EXPRESSION,MRI>"|" { RTOKEN('|');} +<BOTH,SCRIPT,EXPRESSION,MRI>"~" { RTOKEN('~');} +<BOTH,SCRIPT,EXPRESSION,MRI>"!" { RTOKEN('!');} +<BOTH,SCRIPT,EXPRESSION,MRI>"?" { RTOKEN('?');} +<BOTH,SCRIPT,EXPRESSION,MRI>"*" { RTOKEN('*');} +<BOTH,SCRIPT,EXPRESSION,MRI>"+" { RTOKEN('+');} +<BOTH,SCRIPT,EXPRESSION,MRI>"-" { RTOKEN('-');} +<BOTH,SCRIPT,EXPRESSION,MRI>"/" { RTOKEN('/');} +<BOTH,SCRIPT,EXPRESSION,MRI>"%" { RTOKEN('%');} +<BOTH,SCRIPT,EXPRESSION,MRI>"<" { RTOKEN('<');} +<BOTH,SCRIPT,EXPRESSION,MRI>"=" { RTOKEN('=');} +<BOTH,SCRIPT,EXPRESSION,MRI>"}" { RTOKEN('}') ; } +<BOTH,SCRIPT,EXPRESSION,MRI>"{" { RTOKEN('{'); } +<BOTH,SCRIPT,EXPRESSION,MRI>")" { RTOKEN(')');} +<BOTH,SCRIPT,EXPRESSION,MRI>"(" { RTOKEN('(');} +<BOTH,SCRIPT,EXPRESSION,MRI>":" { RTOKEN(':'); } +<BOTH,SCRIPT,EXPRESSION,MRI>";" { RTOKEN(';');} <BOTH,SCRIPT>"MEMORY" { RTOKEN(MEMORY);} <BOTH,SCRIPT>"ORIGIN" { RTOKEN(ORIGIN);} -<BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);} +<EXPRESSION,BOTH,SCRIPT>"BLOCK" { RTOKEN(BLOCK);} +<EXPRESSION,BOTH,SCRIPT>"BIND" { RTOKEN(BIND);} <BOTH,SCRIPT>"LENGTH" { RTOKEN(LENGTH);} <EXPRESSION,BOTH,SCRIPT>"ALIGN" { RTOKEN(ALIGN_K);} <EXPRESSION,BOTH,SCRIPT>"ADDR" { RTOKEN(ADDR);} @@ -226,6 +238,7 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] <BOTH,SCRIPT>"SEARCH_DIR" { RTOKEN(SEARCH_DIR);} <BOTH,SCRIPT>"OUTPUT" { RTOKEN(OUTPUT);} <BOTH,SCRIPT>"INPUT" { RTOKEN(INPUT);} +<EXPRESSION,BOTH,SCRIPT>"GROUP" { RTOKEN(GROUP);} <EXPRESSION,BOTH,SCRIPT>"DEFINED" { RTOKEN(DEFINED);} <BOTH,SCRIPT>"CREATE_OBJECT_SYMBOLS" { RTOKEN(CREATE_OBJECT_SYMBOLS);} <BOTH,SCRIPT>"CONSTRUCTORS" { RTOKEN( CONSTRUCTORS);} @@ -243,25 +256,27 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] <BOTH,SCRIPT>"SHORT" { RTOKEN( SHORT);} <BOTH,SCRIPT>"BYTE" { RTOKEN( BYTE);} <BOTH,SCRIPT>"NOFLOAT" { RTOKEN(NOFLOAT);} -<EXPRESSION,BOTH,SCRIPT>"NOLOAD" { RTOKEN(NOLOAD);} -<BOTH,SCRIPT>"DSECT" { RTOKEN(DSECT);} -<BOTH,SCRIPT>"COPY" { RTOKEN(COPY);} -<BOTH,SCRIPT>"INFO" { RTOKEN(INFO);} -<BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY);} +<EXPRESSION,BOTH,SCRIPT>"NOLOAD" { RTOKEN(NOLOAD);} +<EXPRESSION,BOTH,SCRIPT>"DSECT" { RTOKEN(DSECT);} +<EXPRESSION,BOTH,SCRIPT>"COPY" { RTOKEN(COPY);} +<EXPRESSION,BOTH,SCRIPT>"INFO" { RTOKEN(INFO);} +<EXPRESSION,BOTH,SCRIPT>"OVERLAY" { RTOKEN(OVERLAY);} <BOTH,SCRIPT>"o" { RTOKEN(ORIGIN);} <BOTH,SCRIPT>"org" { RTOKEN(ORIGIN);} <BOTH,SCRIPT>"l" { RTOKEN( LENGTH);} <BOTH,SCRIPT>"len" { RTOKEN( LENGTH);} <BOTH,SCRIPT>"INCLUDE" { RTOKEN(INCLUDE);} +<BOTH,SCRIPT>"PHDRS" { RTOKEN (PHDRS); } <EXPRESSION,BOTH,SCRIPT>"AT" { RTOKEN(AT);} -<BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); } +<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); } +<MRI>"#".*\n?\r? { ++ lineno; } <MRI>"\n" { ++ lineno; RTOKEN(NEWLINE); } <MRI>"\r" { ++ lineno; RTOKEN(NEWLINE); } <MRI>"*".* { /* Mri comment line */ } +<MRI>";".* { /* Mri comment line */ } <MRI>"END" { RTOKEN(ENDWORD); } <MRI>"ALIGNMOD" { RTOKEN(ALIGNMOD);} <MRI>"ALIGN" { RTOKEN(ALIGN_K);} - <MRI>"CHIP" { RTOKEN(CHIP); } <MRI>"BASE" { RTOKEN(BASE); } <MRI>"ALIAS" { RTOKEN(ALIAS); } @@ -271,15 +286,27 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] <MRI>"ORDER" { RTOKEN(ORDER); } <MRI>"NAME" { RTOKEN(NAMEWORD); } <MRI>"FORMAT" { RTOKEN(FORMAT); } +<MRI>"CASE" { RTOKEN(CASE); } +<MRI>"EXTERN" { RTOKEN(EXTERN); } +<MRI>"START" { RTOKEN(START); } <MRI>"LIST".* { RTOKEN(LIST); /* LIST and ignore to end of line */ } <MRI>"SECT" { RTOKEN(SECT); } <EXPRESSION,BOTH,SCRIPT,MRI>"ABSOLUTE" { RTOKEN(ABSOLUTE); } <MRI>"end" { RTOKEN(ENDWORD); } +<MRI>"alignmod" { RTOKEN(ALIGNMOD);} +<MRI>"align" { RTOKEN(ALIGN_K);} <MRI>"chip" { RTOKEN(CHIP); } +<MRI>"base" { RTOKEN(BASE); } +<MRI>"alias" { RTOKEN(ALIAS); } +<MRI>"truncate" { RTOKEN(TRUNCATE); } <MRI>"load" { RTOKEN(LOAD); } +<MRI>"public" { RTOKEN(PUBLIC); } <MRI>"order" { RTOKEN(ORDER); } <MRI>"name" { RTOKEN(NAMEWORD); } <MRI>"format" { RTOKEN(FORMAT); } +<MRI>"case" { RTOKEN(CASE); } +<MRI>"extern" { RTOKEN(EXTERN); } +<MRI>"start" { RTOKEN(START); } <MRI>"list".* { RTOKEN(LIST); /* LIST and ignore to end of line */ } <MRI>"sect" { RTOKEN(SECT); } <EXPRESSION,BOTH,SCRIPT,MRI>"absolute" { RTOKEN(ABSOLUTE); } @@ -295,9 +322,11 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] yylval.name = buystring(yytext); return NAME; } -<SCRIPT>{FILENAMECHAR}* { yylval.name = buystring(yytext); - return NAME; +<BOTH,EXPRESSION>"-l"{FILENAMECHAR}+ { + yylval.name = buystring (yytext + 2); + return LNAME; } +<SCRIPT>{WILDCHAR}* { yylval.name = buystring(yytext); return NAME; } <EXPRESSION,BOTH,SCRIPT>"\""[^\"]*"\"" { /* No matter the state, quotes @@ -323,7 +352,8 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] } BEGIN(SCRIPT); - ldfile_input_filename = file_name_stack[include_stack_ptr-1]; + ldfile_input_filename = file_name_stack[include_stack_ptr - 1]; + lineno = lineno_stack[include_stack_ptr - 1]; return END; } @@ -340,13 +370,14 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~] void lex_push_file (file, name) FILE *file; - char *name; + const char *name; { if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { einfo("%F:includes nested too deeply\n"); } file_name_stack[include_stack_ptr] = name; + lineno_stack[include_stack_ptr] = 1; include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; include_stack_ptr++; @@ -372,7 +403,7 @@ yy_create_string_buffer (string, size) /* yy_ch_buf has to be 2 characters longer than the size given because we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (YY_CHAR *) malloc ((unsigned) (b->yy_buf_size + 3)); + b->yy_ch_buf = (char *) malloc ((unsigned) (b->yy_buf_size + 3)); b->yy_ch_buf[0] = '\n'; strcpy (b->yy_ch_buf+1, string); @@ -380,7 +411,14 @@ yy_create_string_buffer (string, size) b->yy_ch_buf[size+2] = YY_END_OF_BUFFER_CHAR; b->yy_n_chars = size+1; b->yy_buf_pos = &b->yy_ch_buf[1]; + + /* flex 2.4.7 changed the interface. FIXME: We should not be using + a flex internal interface in the first place! */ +#ifdef YY_BUFFER_NEW + b->yy_buffer_status = YY_BUFFER_NEW; +#else b->yy_eof_status = EOF_NOT_SEEN; +#endif return b; } @@ -400,6 +438,7 @@ lex_redirect (string) einfo("%F: macros nested too deeply\n"); } file_name_stack[include_stack_ptr] = "redirect"; + lineno_stack[include_stack_ptr] = 0; include_stack[include_stack_ptr] = YY_CURRENT_BUFFER; include_stack_ptr++; tmp = yy_create_string_buffer (string, strlen (string)); @@ -520,7 +559,23 @@ static void lex_warn_invalid (where, what) char *where, *what; { - fprintf(stderr, - "%s: ignoring invalid character `%s'%s\n", - program_name, what, where); + char buf[5]; + + /* If we have found an input file whose format we do not recognize, + and we are therefore treating it as a linker script, and we find + an invalid character, then most likely this is a real object file + of some different format. Treat it as such. */ + if (ldfile_assumed_script) + { + bfd_set_error (bfd_error_file_not_recognized); + einfo ("%F%s: file not recognized: %E\n", ldfile_input_filename); + } + + if (! isprint ((unsigned char) *what)) + { + sprintf (buf, "\\%03o", (unsigned int) *what); + what = buf; + } + + einfo ("%P:%S: ignoring invalid character `%s'%s\n", what, where); } |