Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5197 → Rev 5199

/contrib/toolchain/binutils/Makefile
15,7 → 15,7
LDFLAGS = -nostdlib -shared -s --image-base 0 -T ../newlib/dll.lds -e _DllStartup
LDFLAGS+= --out-implib
 
SUBDIRS = libiberty bfd
SUBDIRS = libiberty bfd ld
 
# targets
 
/contrib/toolchain/binutils/bfd/Makefile
8,6 → 8,8
 
DEFINES= -DHAVE_CONFIG_H -DHAVE_i386pe_vec -DHAVE_i386pei_vec -DHAVE_bfd_elf32_i386_vec -DHAVE_bfd_elf32_little_generic_vec
DEFINES+= -DHAVE_bfd_elf32_big_generic_vec -DBINDIR="/home/autobuild/tools/win32/bin"
TDEFS= -DDEFAULT_VECTOR=i386pe_vec "-DSELECT_VECS=&i386pe_vec,&i386pei_vec,&bfd_elf32_i386_vec,&bfd_elf32_little_generic_vec,&bfd_elf32_big_generic_vec"
TDEFS+= "-DSELECT_ARCHITECTURES=&bfd_i386_arch"
 
SRCS = \
archive.c archures.c bfd.c bfdio.c \
19,9 → 21,9
elf-nacl.c elf-strtab.c elf-vxworks.c \
format.c hash.c ihex.c init.c libbfd.c \
linker.c merge.c opncls.c pe-i386.c \
peigen.c reloc.c section.c simple.c \
srec.c stabs.c stab-syms.c syms.c \
targets.c tekhex.c verilog.c
peigen.c pei-i386.c reloc.c section.c \
simple.c srec.c stabs.c stab-syms.c \
syms.c targets.c tekhex.c verilog.c
 
 
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
32,13 → 34,18
 
libbfd.a : $(OBJS) MAkefile
$(AR) crs libbfd.a $(OBJS)
# mv -f libbfd.a $(SDK_DIR)/lib
mv -f libbfd.a $(SDK_DIR)/lib
 
%.o : %.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
 
dwarf2.o : dwarf2.c Makefile
$(CC) $(CFLAGS) $(DEFINES) -DDEBUGDIR=\"/home/autobuild/tools/win32/lib/debug\" $(INCLUDES) -o $@ $<
$(CC) $(CFLAGS) $(DEFINES) -DDEBUGDIR='"/home/autobuild/tools/win32/lib/debug\"' $(INCLUDES) -o $@ $<
 
 
targets.o : targets.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(TDEFS) $(INCLUDES) -o $@ $<
 
archures.o : archures.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(TDEFS) $(INCLUDES) -o $@ $<
/contrib/toolchain/binutils/bfd/bfdio.c
69,15 → 69,6
static FILE *
close_on_exec (FILE *file)
{
#if defined (HAVE_FILENO) && defined (F_GETFD)
if (file)
{
int fd = fileno (file);
int old = fcntl (fd, F_GETFD, 0);
if (old >= 0)
fcntl (fd, F_SETFD, old | FD_CLOEXEC);
}
#endif
return file;
}
 
/contrib/toolchain/binutils/bfd/cache.c
76,24 → 76,9
static int
bfd_cache_max_open (void)
{
if (max_open_files == 0)
{
int max;
#ifdef HAVE_GETRLIMIT
struct rlimit rlim;
if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
&& rlim.rlim_cur != RLIM_INFINITY)
max = rlim.rlim_cur / 8;
else
#endif /* HAVE_GETRLIMIT */
#ifdef _SC_OPEN_MAX
max = sysconf (_SC_OPEN_MAX) / 8;
#else
max = 10;
#endif /* _SC_OPEN_MAX */
max_open_files = max < 10 ? 10 : max;
}
 
max_open_files = 16;
 
return max_open_files;
}
 
/contrib/toolchain/binutils/bfd/opncls.c
673,6 → 673,7
which run tests with "ld [...] -o /dev/null". */
&& S_ISREG(buf.st_mode))
{
/*
unsigned int mask = umask (0);
 
umask (mask);
679,6 → 680,7
chmod (abfd->filename,
(0777
& (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
*/
}
}
}
/contrib/toolchain/binutils/bfd/pei-i386.c
0,0 → 1,46
/* BFD back-end for Intel 386 PE IMAGE COFF files.
Copyright 1995, 1996, 1999, 2002, 2004, 2005, 2006, 2007, 2009
Free Software Foundation, Inc.
 
This file is part of BFD, the Binary File Descriptor library.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
 
#define TARGET_SYM i386pei_vec
#define TARGET_NAME "pei-i386"
#define COFF_IMAGE_WITH_PE
#define COFF_WITH_PE
#define PCRELOFFSET TRUE
#define TARGET_UNDERSCORE '_'
/* Long section names not allowed in executable images, only object files. */
#define COFF_LONG_SECTION_NAMES 0
#define COFF_SUPPORT_GNU_LINKONCE
#define COFF_LONG_FILENAMES
 
#define COFF_SECTION_ALIGNMENT_ENTRIES \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
 
#include "coff-i386.c"
/contrib/toolchain/binutils/bfd/sysdep.h
27,6 → 27,8
#error sysdep.h must be included in lieu of config.h
#endif
 
#include <stdarg.h>
 
#include "config.h"
 
#include "ansidecl.h"
/contrib/toolchain/binutils/ld/Makefile
0,0 → 1,55
NAME= ld-new
 
LIB_DIR:= $(SDK_DIR)/lib
 
CFLAGS_OPT = -U_Win32 -U_WIN32 -U__MINGW32__ -UWIN32 -U_MSC_VER -O2
CFLAGS_OPT+= -fomit-frame-pointer -fno-ident -mno-ms-bitfields
CFLAGS_OPT+= -W -Wall -Wmissing-prototypes -Wno-format -Werror
CFLAGS = -c $(CFLAGS_OPT)
 
INCLUDES= -I. -I../bfd -I../include -I$(SDK_DIR)/sources/newlib/libc/include
 
DEFINES= -DHAVE_CONFIG_H -DLOCALEDIR='"/home/autobuild/tools/win32/share/locale"'
FDEFS= -DSCRIPTDIR='"/home/autobuild/tools/win32/mingw32/lib"' -DBINDIR='"/home/autobuild/tools/win32/bin"'
FDEFS+= -DTOOLBINDIR='"/home/autobuild/tools/win32/mingw32/bin"'
MDEFS= -DDEFAULT_EMULATION='"i386pe"' -DBINDIR='"/home/autobuild/tools/win32/bin"'
MDEFS+= -DTOOLBINDIR='"/home/autobuild/tools/win32/mingw32/bin"' -DTARGET='"i686-pc-mingw32"'
MDEFS+= -DTARGET_SYSTEM_ROOT='"/home/autobuild/tools/win32"' -DTARGET_SYSTEM_ROOT_RELOCATABLE
 
LIBS= -lbfd -liberty -lz -lgcc -lc.dll -lapp
 
LIBPATH:= -L$(LIB_DIR) -L/home/autobuild/tools/win32/mingw32/lib
 
LDFLAGS = -static -nostdlib --stack 0x200000 -T$(SDK_DIR)/sources/newlib/app.lds --image-base 0
 
 
SRCS = \
deffilep.c ei386pe.c \
ldcref.c ldctor.c ldemul.c \
ldexp.c ldfile.c ldgram.c \
ldlang.c ldlex-wrapper.c \
ldmain.c ldmisc.c ldver.c \
ldwrite.c lexsup.c mri.c \
pe-dll.c
 
 
 
OBJS = $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))
 
# targets
 
all: $(NAME)
 
$(NAME): $(OBJS) Makefile
$(LD) $(LDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LIBS)
kos32-objcopy $@ -O binary
 
%.o : %.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
 
ldfile.o : ldfile.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(FDEFS) $(INCLUDES) -o $@ $<
 
ldmain.o : ldmain.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(MDEFS) $(INCLUDES) -o $@ $<
/contrib/toolchain/binutils/ld/config.h
0,0 → 1,238
/* config.h. Generated from config.in by configure. */
/* config.in. Generated from configure.in by autoheader. */
 
/* Check that config.h is #included before system headers
(this works only for glibc, but that should be enough). */
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__CONFIG_H__)
# error config.h must be #included before system headers
#endif
#define __CONFIG_H__ 1
 
/* Define to 1 if translation of program messages to the user's native
language is requested. */
/* #undef ENABLE_NLS */
 
/* Additional extension a shared object might have. */
/* #undef EXTRA_SHLIB_EXTENSION */
 
/* Define to choose default GOT handling scheme */
#define GOT_HANDLING_DEFAULT GOT_HANDLING_TARGET_DEFAULT
 
/* Define to 1 if you have the `close' function. */
#define HAVE_CLOSE 1
 
/* Define to 1 if you have the declaration of `environ', and to 0 if you
don't. */
#define HAVE_DECL_ENVIRON 1
 
/* Define to 1 if you have the declaration of `free', and to 0 if you don't.
*/
#define HAVE_DECL_FREE 1
 
/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't.
*/
#define HAVE_DECL_GETENV 1
 
/* Is the prototype for getopt in <unistd.h> in the expected format? */
#define HAVE_DECL_GETOPT 1
 
/* Define to 1 if you have the declaration of `sbrk', and to 0 if you don't.
*/
#define HAVE_DECL_SBRK 0
 
/* Define to 1 if you have the declaration of `strstr', and to 0 if you don't.
*/
#define HAVE_DECL_STRSTR 1
 
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
*/
#define HAVE_DIRENT_H 1
 
/* Define to 1 if you have the `dlclose' function. */
/* #undef HAVE_DLCLOSE */
 
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
 
/* Define to 1 if you have the `dlopen' function. */
/* #undef HAVE_DLOPEN */
 
/* Define to 1 if you have the `dlsym' function. */
/* #undef HAVE_DLSYM */
 
/* Define to 1 if you have the <elf-hints.h> header file. */
/* #undef HAVE_ELF_HINTS_H */
 
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
 
/* Define to 1 if you have the `glob' function. */
/* #undef HAVE_GLOB */
 
/* Define .init_array/.fini_array sections are available and working. */
#define HAVE_INITFINI_ARRAY 1
 
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
 
/* Define if your <locale.h> file defines LC_MESSAGES. */
/* #undef HAVE_LC_MESSAGES */
 
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
 
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
 
/* Define to 1 if you have the `lseek' function. */
#define HAVE_LSEEK 1
 
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
 
/* Define to 1 if you have the `mkstemp' function. */
/* #undef HAVE_MKSTEMP */
 
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
 
/* Define to 1 if you have the `open' function. */
#define HAVE_OPEN 1
 
/* Define to 1 if you have the `realpath' function. */
/* #undef HAVE_REALPATH */
 
/* Define to 1 if you have the `sbrk' function. */
/* #undef HAVE_SBRK */
 
/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1
 
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
 
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
 
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
 
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
 
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_DIR_H */
 
/* Define to 1 if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
 
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
*/
/* #undef HAVE_SYS_NDIR_H */
 
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
 
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
 
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
 
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
 
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
 
/* Define to 1 if you have the `waitpid' function. */
/* #undef HAVE_WAITPID */
 
/* Define to 1 if you have the <windows.h> header file. */
//#define HAVE_WINDOWS_H 1
 
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
 
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
 
/* Name of package */
#define PACKAGE "ld"
 
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
 
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
 
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
 
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
 
/* Define to the home page for this package. */
#define PACKAGE_URL ""
 
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
 
/* The size of `void *', as computed by sizeof. */
#define SIZEOF_VOID_P 4
 
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
 
/* Define if you can safely include both <string.h> and <strings.h>. */
#define STRING_WITH_STRINGS 1
 
/* Use b modifier when opening binary files? */
#define USE_BINARY_FOPEN 1
 
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# define _POSIX_PTHREAD_SEMANTICS 1
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# define _TANDEM_SOURCE 1
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# define __EXTENSIONS__ 1
#endif
 
 
/* Version number of package */
#define VERSION "2.24"
 
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
/* #undef YYTEXT_POINTER */
 
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
 
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
 
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
 
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
/* #undef _POSIX_1_SOURCE */
 
/* Define to 1 if you need to in order for `stat' and other things to work. */
/* #undef _POSIX_SOURCE */
/contrib/toolchain/binutils/ld/deffile.h
0,0 → 1,118
/* deffile.h - header for .DEF file parser
Copyright 1998, 1999, 2000, 2002, 2003, 2005, 2006, 2007, 2009
Free Software Foundation, Inc.
Written by DJ Delorie dj@cygnus.com
 
This file is part of the GNU Binutils.
 
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 3, or (at your option)
any later version.
 
The 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 GLD; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
02110-1301, USA. */
 
#ifndef DEFFILE_H
#define DEFFILE_H
 
/* DEF storage definitions. Note that any ordinal may be zero, and
any pointer may be NULL, if not defined by the DEF file. */
 
typedef struct def_file_section {
char *name; /* always set */
char *class; /* may be NULL */
char flag_read, flag_write, flag_execute, flag_shared;
} def_file_section;
 
typedef struct def_file_export {
char *name; /* always set */
char *internal_name; /* always set, may == name */
char *its_name; /* optional export table name refered to. */
int ordinal; /* -1 if not specified */
int hint;
char flag_private, flag_constant, flag_noname, flag_data, flag_forward;
} def_file_export;
 
typedef struct def_file_module {
struct def_file_module *next;
void *user_data;
char name[1]; /* extended via malloc */
} def_file_module;
 
typedef struct def_file_import {
char *internal_name; /* always set */
def_file_module *module; /* always set */
char *name; /* may be NULL; either this or ordinal will be set */
char *its_name; /* optional import table name refered to. */
int ordinal; /* may be -1 */
int data; /* = 1 if data */
} def_file_import;
 
typedef struct def_file_aligncomm {
struct def_file_aligncomm *next; /* Chain pointer. */
char *symbol_name; /* Name of common symbol. */
unsigned int alignment; /* log-2 alignment. */
} def_file_aligncomm;
 
typedef struct def_file {
/* From the NAME or LIBRARY command. */
char *name;
int is_dll; /* -1 if NAME/LIBRARY not given */
bfd_vma base_address; /* (bfd_vma)(-1) if unspecified */
 
/* From the DESCRIPTION command. */
char *description;
 
/* From the STACK/HEAP command, -1 if unspecified. */
int stack_reserve, stack_commit;
int heap_reserve, heap_commit;
 
/* From the SECTION/SEGMENT commands. */
int num_section_defs;
def_file_section *section_defs;
 
/* From the EXPORTS commands. */
int num_exports;
def_file_export *exports;
 
/* Used by imports for module names. */
def_file_module *modules;
 
/* From the IMPORTS commands. */
int num_imports;
def_file_import *imports;
 
/* From the VERSION command, -1 if not specified. */
int version_major, version_minor;
 
/* Only expected from .drectve sections, not .DEF files. */
def_file_aligncomm *aligncomms;
 
} def_file;
 
extern def_file *def_file_empty (void);
 
/* The second arg may be NULL. If not, this .def is appended to it. */
extern def_file *def_file_parse (const char *, def_file *);
extern void def_file_free (def_file *);
extern def_file_export *def_file_add_export (def_file *, const char *,
const char *, int,
const char *, int *);
extern def_file_import *def_file_add_import (def_file *, const char *,
const char *, int, const char *,
const char *, int *);
extern void def_file_add_directive (def_file *, const char *, int);
extern def_file_module *def_get_module (def_file *, const char *);
#ifdef DEF_FILE_PRINT
extern void def_file_print (FILE *, def_file *);
#endif
 
#endif /* DEFFILE_H */
/contrib/toolchain/binutils/ld/deffilep.c
0,0 → 1,3426
/* A Bison parser, made by GNU Bison 2.3. */
 
/* Skeleton implementation for Bison's Yacc-like parsers in C
 
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
 
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, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
 
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
 
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
 
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
 
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
There are some unavoidable exceptions within include files to
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
 
/* Identify Bison output. */
#define YYBISON 1
 
/* Bison version. */
#define YYBISON_VERSION "2.3"
 
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
 
/* Pure parsers. */
#define YYPURE 0
 
/* Using locations. */
#define YYLSP_NEEDED 0
 
 
 
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
NAME = 258,
LIBRARY = 259,
DESCRIPTION = 260,
STACKSIZE_K = 261,
HEAPSIZE = 262,
CODE = 263,
DATAU = 264,
DATAL = 265,
SECTIONS = 266,
EXPORTS = 267,
IMPORTS = 268,
VERSIONK = 269,
BASE = 270,
CONSTANTU = 271,
CONSTANTL = 272,
PRIVATEU = 273,
PRIVATEL = 274,
ALIGNCOMM = 275,
READ = 276,
WRITE = 277,
EXECUTE = 278,
SHARED = 279,
NONAMEU = 280,
NONAMEL = 281,
DIRECTIVE = 282,
EQUAL = 283,
ID = 284,
DIGITS = 285
};
#endif
/* Tokens. */
#define NAME 258
#define LIBRARY 259
#define DESCRIPTION 260
#define STACKSIZE_K 261
#define HEAPSIZE 262
#define CODE 263
#define DATAU 264
#define DATAL 265
#define SECTIONS 266
#define EXPORTS 267
#define IMPORTS 268
#define VERSIONK 269
#define BASE 270
#define CONSTANTU 271
#define CONSTANTL 272
#define PRIVATEU 273
#define PRIVATEL 274
#define ALIGNCOMM 275
#define READ 276
#define WRITE 277
#define EXECUTE 278
#define SHARED 279
#define NONAMEU 280
#define NONAMEL 281
#define DIRECTIVE 282
#define EQUAL 283
#define ID 284
#define DIGITS 285
 
 
 
 
/* Copy the first part of user declarations. */
#line 1 "deffilep.y"
/* deffilep.y - parser for .def files */
 
/* Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006,
2007, 2009 Free Software Foundation, Inc.
 
This file is part of GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "libiberty.h"
#include "safe-ctype.h"
#include "bfd.h"
#include "ld.h"
#include "ldmisc.h"
#include "deffile.h"
 
#define TRACE 0
 
#define ROUND_UP(a, b) (((a)+((b)-1))&~((b)-1))
 
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
yacc generated parsers in ld. Note that these are only the variables
produced by yacc. If other parser generators (bison, byacc, etc) produce
additional global names that conflict at link time, then those parser
generators need to be fixed instead of adding those names to this list. */
 
#define yymaxdepth def_maxdepth
#define yyparse def_parse
#define yylex def_lex
#define yyerror def_error
#define yylval def_lval
#define yychar def_char
#define yydebug def_debug
#define yypact def_pact
#define yyr1 def_r1
#define yyr2 def_r2
#define yydef def_def
#define yychk def_chk
#define yypgo def_pgo
#define yyact def_act
#define yyexca def_exca
#define yyerrflag def_errflag
#define yynerrs def_nerrs
#define yyps def_ps
#define yypv def_pv
#define yys def_s
#define yy_yys def_yys
#define yystate def_state
#define yytmp def_tmp
#define yyv def_v
#define yy_yyv def_yyv
#define yyval def_val
#define yylloc def_lloc
#define yyreds def_reds /* With YYDEBUG defined. */
#define yytoks def_toks /* With YYDEBUG defined. */
#define yylhs def_yylhs
#define yylen def_yylen
#define yydefred def_yydefred
#define yydgoto def_yydgoto
#define yysindex def_yysindex
#define yyrindex def_yyrindex
#define yygindex def_yygindex
#define yytable def_yytable
#define yycheck def_yycheck
 
typedef struct def_pool_str {
struct def_pool_str *next;
char data[1];
} def_pool_str;
 
static def_pool_str *pool_strs = NULL;
 
static char *def_pool_alloc (size_t sz);
static char *def_pool_strdup (const char *str);
static void def_pool_free (void);
 
static void def_description (const char *);
static void def_exports (const char *, const char *, int, int, const char *);
static void def_heapsize (int, int);
static void def_import (const char *, const char *, const char *, const char *,
int, const char *);
static void def_image_name (const char *, bfd_vma, int);
static void def_section (const char *, int);
static void def_section_alt (const char *, const char *);
static void def_stacksize (int, int);
static void def_version (int, int);
static void def_directive (char *);
static void def_aligncomm (char *str, int align);
static int def_parse (void);
static int def_error (const char *);
static int def_lex (void);
 
static int lex_forced_token = 0;
static const char *lex_parse_string = 0;
static const char *lex_parse_string_end = 0;
 
 
 
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
 
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
# define YYERROR_VERBOSE 0
#endif
 
/* Enabling the token table. */
#ifndef YYTOKEN_TABLE
# define YYTOKEN_TABLE 0
#endif
 
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 114 "deffilep.y"
{
char *id;
const char *id_const;
int number;
bfd_vma vma;
char *digits;
}
/* Line 193 of yacc.c. */
#line 277 "deffilep.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
 
 
 
/* Copy the second part of user declarations. */
 
 
/* Line 216 of yacc.c. */
#line 290 "deffilep.c"
 
#ifdef short
# undef short
#endif
 
#ifdef YYTYPE_UINT8
typedef YYTYPE_UINT8 yytype_uint8;
#else
typedef unsigned char yytype_uint8;
#endif
 
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
#elif (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
typedef signed char yytype_int8;
#else
typedef short int yytype_int8;
#endif
 
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
typedef unsigned short int yytype_uint16;
#endif
 
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
typedef short int yytype_int16;
#endif
 
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned int
# endif
#endif
 
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
# endif
# endif
# ifndef YY_
# define YY_(msgid) msgid
# endif
#endif
 
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(e) ((void) (e))
#else
# define YYUSE(e) /* empty */
#endif
 
/* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint
# define YYID(n) (n)
#else
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
YYID (int i)
#else
static int
YYID (i)
int i;
#endif
{
return i;
}
#endif
 
#if ! defined yyoverflow || YYERROR_VERBOSE
 
/* The parser invokes alloca or malloc; define the necessary symbols. */
 
# ifdef YYSTACK_USE_ALLOCA
# if YYSTACK_USE_ALLOCA
# ifdef __GNUC__
# define YYSTACK_ALLOC __builtin_alloca
# elif defined __BUILTIN_VA_ARG_INCR
# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
# elif defined _AIX
# define YYSTACK_ALLOC __alloca
# elif defined _MSC_VER
# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
# endif
# endif
# endif
# endif
# endif
 
# ifdef YYSTACK_ALLOC
/* Pacify GCC's `empty if-body' warning. */
# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
to allow for a few compiler-allocated temporary stack slots. */
# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
# endif
# else
# define YYSTACK_ALLOC YYMALLOC
# define YYSTACK_FREE YYFREE
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
# if (defined __cplusplus && ! defined _STDLIB_H \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
 
 
#if (! defined yyoverflow \
&& (! defined __cplusplus \
|| (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
/* A type that is properly aligned for any stack member. */
union yyalloc
{
yytype_int16 yyss;
YYSTYPE yyvs;
};
 
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
 
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
 
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
# define YYCOPY(To, From, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
while (YYID (0))
# endif
# endif
 
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
# define YYSTACK_RELOCATE(Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
YYCOPY (&yyptr->Stack, Stack, yysize); \
Stack = &yyptr->Stack; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
while (YYID (0))
 
#endif
 
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 69
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 149
 
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 35
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 27
/* YYNRULES -- Number of rules. */
#define YYNRULES 99
/* YYNRULES -- Number of states. */
#define YYNSTATES 146
 
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 285
 
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 32, 2, 31, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 33, 2, 2, 34, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30
};
 
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 6, 8, 12, 16, 19, 23, 27,
30, 33, 36, 39, 42, 45, 50, 53, 58, 59,
61, 64, 72, 76, 77, 79, 81, 83, 85, 87,
89, 91, 93, 96, 98, 107, 116, 123, 130, 137,
142, 145, 147, 150, 153, 157, 159, 161, 162, 165,
166, 168, 170, 172, 174, 176, 178, 180, 182, 184,
186, 188, 190, 192, 194, 196, 198, 200, 202, 204,
206, 208, 210, 212, 214, 216, 218, 220, 223, 226,
230, 234, 236, 237, 240, 241, 244, 245, 248, 249,
253, 254, 256, 259, 264, 266, 267, 269, 270, 272
};
 
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
36, 0, -1, 36, 37, -1, 37, -1, 3, 52,
56, -1, 4, 52, 56, -1, 5, 29, -1, 6,
60, 48, -1, 7, 60, 48, -1, 8, 46, -1,
9, 46, -1, 11, 44, -1, 12, 38, -1, 13,
42, -1, 14, 60, -1, 14, 60, 31, 60, -1,
27, 29, -1, 20, 57, 32, 60, -1, -1, 39,
-1, 38, 39, -1, 51, 55, 54, 47, 40, 47,
53, -1, 41, 47, 40, -1, -1, 25, -1, 26,
-1, 16, -1, 17, -1, 9, -1, 10, -1, 18,
-1, 19, -1, 42, 43, -1, 43, -1, 29, 33,
29, 31, 29, 31, 29, 53, -1, 29, 33, 29,
31, 29, 31, 60, 53, -1, 29, 33, 29, 31,
29, 53, -1, 29, 33, 29, 31, 60, 53, -1,
29, 31, 29, 31, 29, 53, -1, 29, 31, 29,
53, -1, 44, 45, -1, 45, -1, 29, 46, -1,
29, 29, -1, 46, 47, 49, -1, 49, -1, 32,
-1, -1, 32, 60, -1, -1, 21, -1, 22, -1,
23, -1, 24, -1, 15, -1, 8, -1, 16, -1,
17, -1, 9, -1, 10, -1, 5, -1, 27, -1,
23, -1, 12, -1, 7, -1, 13, -1, 3, -1,
25, -1, 26, -1, 18, -1, 19, -1, 21, -1,
24, -1, 6, -1, 14, -1, 22, -1, 29, -1,
31, 50, -1, 31, 51, -1, 50, 31, 51, -1,
29, 31, 51, -1, 51, -1, -1, 28, 29, -1,
-1, 34, 60, -1, -1, 33, 51, -1, -1, 15,
33, 61, -1, -1, 29, -1, 31, 29, -1, 57,
31, 58, 59, -1, 30, -1, -1, 29, -1, -1,
30, -1, 30, -1
};
 
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 139, 139, 140, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 161, 163,
164, 171, 178, 179, 182, 183, 184, 185, 186, 187,
188, 189, 192, 193, 197, 199, 201, 203, 205, 207,
212, 213, 217, 218, 222, 223, 227, 228, 230, 231,
235, 236, 237, 238, 242, 243, 244, 245, 246, 247,
248, 249, 250, 251, 252, 253, 260, 261, 262, 263,
264, 265, 266, 267, 268, 269, 272, 273, 279, 285,
291, 299, 300, 303, 304, 308, 309, 313, 314, 317,
318, 321, 322, 328, 336, 337, 340, 341, 344, 346
};
#endif
 
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "NAME", "LIBRARY", "DESCRIPTION",
"STACKSIZE_K", "HEAPSIZE", "CODE", "DATAU", "DATAL", "SECTIONS",
"EXPORTS", "IMPORTS", "VERSIONK", "BASE", "CONSTANTU", "CONSTANTL",
"PRIVATEU", "PRIVATEL", "ALIGNCOMM", "READ", "WRITE", "EXECUTE",
"SHARED", "NONAMEU", "NONAMEL", "DIRECTIVE", "EQUAL", "ID", "DIGITS",
"'.'", "','", "'='", "'@'", "$accept", "start", "command", "explist",
"expline", "exp_opt_list", "exp_opt", "implist", "impline", "seclist",
"secline", "attr_list", "opt_comma", "opt_number", "attr",
"keyword_as_name", "opt_name2", "opt_name", "opt_equalequal_name",
"opt_ordinal", "opt_equal_name", "opt_base", "anylang_id", "opt_digits",
"opt_id", "NUMBER", "VMA", 0
};
#endif
 
# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
token YYLEX-NUM. */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 46, 44, 61, 64
};
# endif
 
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
0, 35, 36, 36, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 38, 38,
38, 39, 40, 40, 41, 41, 41, 41, 41, 41,
41, 41, 42, 42, 43, 43, 43, 43, 43, 43,
44, 44, 45, 45, 46, 46, 47, 47, 48, 48,
49, 49, 49, 49, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 51, 51, 51, 51,
51, 52, 52, 53, 53, 54, 54, 55, 55, 56,
56, 57, 57, 57, 58, 58, 59, 59, 60, 61
};
 
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 2, 1, 3, 3, 2, 3, 3, 2,
2, 2, 2, 2, 2, 4, 2, 4, 0, 1,
2, 7, 3, 0, 1, 1, 1, 1, 1, 1,
1, 1, 2, 1, 8, 8, 6, 6, 6, 4,
2, 1, 2, 2, 3, 1, 1, 0, 2, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2, 2, 3,
3, 1, 0, 2, 0, 2, 0, 2, 0, 3,
0, 1, 2, 4, 1, 0, 1, 0, 1, 1
};
 
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
0, 82, 82, 0, 0, 0, 0, 0, 0, 18,
0, 0, 0, 0, 0, 3, 66, 60, 73, 64,
55, 58, 59, 63, 65, 74, 54, 56, 57, 69,
70, 71, 75, 62, 72, 67, 68, 61, 76, 0,
0, 81, 90, 90, 6, 98, 49, 49, 50, 51,
52, 53, 9, 45, 10, 0, 11, 41, 12, 19,
88, 0, 13, 33, 14, 91, 0, 0, 16, 1,
2, 0, 77, 78, 0, 0, 4, 5, 0, 7,
8, 46, 0, 43, 42, 40, 20, 0, 86, 0,
0, 32, 0, 92, 95, 0, 80, 79, 0, 48,
44, 87, 0, 47, 84, 0, 15, 94, 97, 17,
99, 89, 85, 23, 0, 0, 39, 0, 96, 93,
28, 29, 26, 27, 30, 31, 24, 25, 47, 47,
83, 84, 84, 84, 84, 23, 38, 0, 36, 37,
21, 22, 84, 84, 34, 35
};
 
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
-1, 14, 15, 58, 59, 128, 129, 62, 63, 56,
57, 52, 82, 79, 53, 40, 41, 42, 116, 103,
88, 76, 67, 108, 119, 46, 111
};
 
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
#define YYPACT_NINF -82
static const yytype_int8 yypact[] =
{
122, 11, 11, -25, 9, 9, 53, 53, -17, 11,
14, 9, -18, 20, 95, -82, -82, -82, -82, -82,
-82, -82, -82, -82, -82, -82, -82, -82, -82, -82,
-82, -82, -82, -82, -82, -82, -82, -82, 29, 11,
47, -82, 67, 67, -82, -82, 54, 54, -82, -82,
-82, -82, 48, -82, 48, -14, -17, -82, 11, -82,
58, 50, 14, -82, 61, -82, 64, 33, -82, -82,
-82, 11, 47, -82, 11, 63, -82, -82, 9, -82,
-82, -82, 53, -82, 48, -82, -82, 11, 60, 76,
81, -82, 9, -82, 83, 9, -82, -82, 84, -82,
-82, -82, 9, 79, -26, 85, -82, -82, 88, -82,
-82, -82, -82, 36, 89, 90, -82, 55, -82, -82,
-82, -82, -82, -82, -82, -82, -82, -82, 79, 79,
-82, 92, 13, 92, 92, 36, -82, 59, -82, -82,
-82, -82, 92, 92, -82, -82
};
 
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
-82, -82, 107, -82, 65, -11, -82, -82, 75, -82,
82, -4, -81, 93, 57, 102, -8, 141, -75, -82,
-82, 101, -82, -82, -82, -5, -82
};
 
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -48
static const yytype_int16 yytable[] =
{
47, 60, 114, 54, 44, 115, 64, 48, 49, 50,
51, 65, 55, 66, 16, 83, 17, 18, 19, 20,
21, 22, 113, 23, 24, 25, 26, 27, 28, 29,
30, 73, 31, 32, 33, 34, 35, 36, 37, 45,
38, 114, 39, 61, 137, 120, 121, 134, 135, 68,
60, 84, 122, 123, 124, 125, 136, 138, 139, 140,
71, 126, 127, 96, 94, 95, 97, 144, 145, -47,
-47, -47, -47, 99, 48, 49, 50, 51, 74, 101,
81, 89, 75, 90, 132, 45, 78, 106, 142, 45,
109, 87, 92, 93, 102, 69, 98, 112, 1, 2,
3, 4, 5, 6, 7, 104, 8, 9, 10, 11,
105, 81, 133, 107, 110, 12, 117, 118, 130, 131,
114, 70, 13, 86, 141, 1, 2, 3, 4, 5,
6, 7, 143, 8, 9, 10, 11, 91, 85, 100,
80, 72, 12, 43, 77, 0, 0, 0, 0, 13
};
 
static const yytype_int16 yycheck[] =
{
5, 9, 28, 7, 29, 31, 11, 21, 22, 23,
24, 29, 29, 31, 3, 29, 5, 6, 7, 8,
9, 10, 103, 12, 13, 14, 15, 16, 17, 18,
19, 39, 21, 22, 23, 24, 25, 26, 27, 30,
29, 28, 31, 29, 31, 9, 10, 128, 129, 29,
58, 55, 16, 17, 18, 19, 131, 132, 133, 134,
31, 25, 26, 71, 31, 32, 74, 142, 143, 21,
22, 23, 24, 78, 21, 22, 23, 24, 31, 87,
32, 31, 15, 33, 29, 30, 32, 92, 29, 30,
95, 33, 31, 29, 34, 0, 33, 102, 3, 4,
5, 6, 7, 8, 9, 29, 11, 12, 13, 14,
29, 32, 117, 30, 30, 20, 31, 29, 29, 29,
28, 14, 27, 58, 135, 3, 4, 5, 6, 7,
8, 9, 137, 11, 12, 13, 14, 62, 56, 82,
47, 39, 20, 2, 43, -1, -1, -1, -1, 27
};
 
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
0, 3, 4, 5, 6, 7, 8, 9, 11, 12,
13, 14, 20, 27, 36, 37, 3, 5, 6, 7,
8, 9, 10, 12, 13, 14, 15, 16, 17, 18,
19, 21, 22, 23, 24, 25, 26, 27, 29, 31,
50, 51, 52, 52, 29, 30, 60, 60, 21, 22,
23, 24, 46, 49, 46, 29, 44, 45, 38, 39,
51, 29, 42, 43, 60, 29, 31, 57, 29, 0,
37, 31, 50, 51, 31, 15, 56, 56, 32, 48,
48, 32, 47, 29, 46, 45, 39, 33, 55, 31,
33, 43, 31, 29, 31, 32, 51, 51, 33, 60,
49, 51, 34, 54, 29, 29, 60, 30, 58, 60,
30, 61, 60, 47, 28, 31, 53, 31, 29, 59,
9, 10, 16, 17, 18, 19, 25, 26, 40, 41,
29, 29, 29, 60, 47, 47, 53, 31, 53, 53,
53, 40, 29, 60, 53, 53
};
 
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY (-2)
#define YYEOF 0
 
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
 
 
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
 
#define YYFAIL goto yyerrlab
 
#define YYRECOVERING() (!!yyerrstatus)
 
#define YYBACKUP(Token, Value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
{ \
yychar = (Token); \
yylval = (Value); \
yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK (1); \
goto yybackup; \
} \
else \
{ \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
while (YYID (0))
 
 
#define YYTERROR 1
#define YYERRCODE 256
 
 
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
the previous symbol: RHS[0] (always defined). */
 
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
if (YYID (N)) \
{ \
(Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC (Rhs, N).last_line; \
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \
} \
else \
{ \
(Current).first_line = (Current).last_line = \
YYRHSLOC (Rhs, 0).last_line; \
(Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \
} \
while (YYID (0))
#endif
 
 
/* YY_LOCATION_PRINT -- Print the location on the stream.
This macro was not mandated originally: define only if we know
we won't break user code: when these are the locations we know. */
 
#ifndef YY_LOCATION_PRINT
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
(Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
#endif
 
 
/* YYLEX -- calling `yylex' with the right arguments. */
 
#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
# define YYLEX yylex ()
#endif
 
/* Enable debugging if requested. */
#if YYDEBUG
 
# ifndef YYFPRINTF
# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
# define YYFPRINTF fprintf
# endif
 
# define YYDPRINTF(Args) \
do { \
if (yydebug) \
YYFPRINTF Args; \
} while (YYID (0))
 
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
Type, Value); \
YYFPRINTF (stderr, "\n"); \
} \
} while (YYID (0))
 
 
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
 
/*ARGSUSED*/
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
static void
yy_symbol_value_print (yyoutput, yytype, yyvaluep)
FILE *yyoutput;
int yytype;
YYSTYPE const * const yyvaluep;
#endif
{
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# else
YYUSE (yyoutput);
# endif
switch (yytype)
{
default:
break;
}
}
 
 
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
static void
yy_symbol_print (yyoutput, yytype, yyvaluep)
FILE *yyoutput;
int yytype;
YYSTYPE const * const yyvaluep;
#endif
{
if (yytype < YYNTOKENS)
YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
else
YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
yy_symbol_value_print (yyoutput, yytype, yyvaluep);
YYFPRINTF (yyoutput, ")");
}
 
/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included). |
`------------------------------------------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
yy_stack_print (bottom, top)
yytype_int16 *bottom;
yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
for (; bottom <= top; ++bottom)
YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
 
# define YY_STACK_PRINT(Bottom, Top) \
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
} while (YYID (0))
 
 
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
#else
static void
yy_reduce_print (yyvsp, yyrule)
YYSTYPE *yyvsp;
int yyrule;
#endif
{
int yynrhs = yyr2[yyrule];
int yyi;
unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
fprintf (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
);
fprintf (stderr, "\n");
}
}
 
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
yy_reduce_print (yyvsp, Rule); \
} while (YYID (0))
 
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
 
 
/* YYINITDEPTH -- initial size of the parser's stacks. */
#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif
 
/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
if the built-in stack extension method is used).
 
Do not make this value too large; the results are undefined if
YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
evaluated with infinite-precision integer arithmetic. */
 
#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif
 
 
#if YYERROR_VERBOSE
 
# ifndef yystrlen
# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
#else
static YYSIZE_T
yystrlen (yystr)
const char *yystr;
#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
# endif
# endif
 
# ifndef yystpcpy
# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
#else
static char *
yystpcpy (yydest, yysrc)
char *yydest;
const char *yysrc;
#endif
{
char *yyd = yydest;
const char *yys = yysrc;
 
while ((*yyd++ = *yys++) != '\0')
continue;
 
return yyd - 1;
}
# endif
# endif
 
# ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
contains an apostrophe, a comma, or backslash (other than
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
static YYSIZE_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
YYSIZE_T yyn = 0;
char const *yyp = yystr;
 
for (;;)
switch (*++yyp)
{
case '\'':
case ',':
goto do_not_strip_quotes;
 
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
/* Fall through. */
default:
if (yyres)
yyres[yyn] = *yyp;
yyn++;
break;
 
case '"':
if (yyres)
yyres[yyn] = '\0';
return yyn;
}
do_not_strip_quotes: ;
}
 
if (! yyres)
return yystrlen (yystr);
 
return yystpcpy (yyres, yystr) - yyres;
}
# endif
 
/* Copy into YYRESULT an error message about the unexpected token
YYCHAR while in state YYSTATE. Return the number of bytes copied,
including the terminating null byte. If YYRESULT is null, do not
copy anything; just return the number of bytes that would be
copied. As a special case, return 0 if an ordinary "syntax error"
message will do. Return YYSIZE_MAXIMUM if overflow occurs during
size calculation. */
static YYSIZE_T
yysyntax_error (char *yyresult, int yystate, int yychar)
{
int yyn = yypact[yystate];
 
if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
return 0;
else
{
int yytype = YYTRANSLATE (yychar);
YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
int yysize_overflow = 0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
int yyx;
 
# if 0
/* This is so xgettext sees the translatable formats that are
constructed on the fly. */
YY_("syntax error, unexpected %s");
YY_("syntax error, unexpected %s, expecting %s");
YY_("syntax error, unexpected %s, expecting %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
# endif
char *yyfmt;
char const *yyf;
static char const yyunexpected[] = "syntax error, unexpected %s";
static char const yyexpecting[] = ", expecting %s";
static char const yyor[] = " or %s";
char yyformat[sizeof yyunexpected
+ sizeof yyexpecting - 1
+ ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
* (sizeof yyor - 1))];
char const *yyprefix = yyexpecting;
 
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
int yyxbegin = yyn < 0 ? -yyn : 0;
 
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1;
 
yyarg[0] = yytname[yytype];
yyfmt = yystpcpy (yyformat, yyunexpected);
 
for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
{
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{
yycount = 1;
yysize = yysize0;
yyformat[sizeof yyunexpected - 1] = '\0';
break;
}
yyarg[yycount++] = yytname[yyx];
yysize1 = yysize + yytnamerr (0, yytname[yyx]);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
yyfmt = yystpcpy (yyfmt, yyprefix);
yyprefix = yyor;
}
 
yyf = YY_(yyformat);
yysize1 = yysize + yystrlen (yyf);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
 
if (yysize_overflow)
return YYSIZE_MAXIMUM;
 
if (yyresult)
{
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
char *yyp = yyresult;
int yyi = 0;
while ((*yyp = *yyf) != '\0')
{
if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyf += 2;
}
else
{
yyp++;
yyf++;
}
}
}
return yysize;
}
}
#endif /* YYERROR_VERBOSE */
 
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
 
/*ARGSUSED*/
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
#else
static void
yydestruct (yymsg, yytype, yyvaluep)
const char *yymsg;
int yytype;
YYSTYPE *yyvaluep;
#endif
{
YYUSE (yyvaluep);
 
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
switch (yytype)
{
 
default:
break;
}
}
 
/* Prevent warnings from -Wmissing-prototypes. */
 
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
 
 
 
/* The look-ahead symbol. */
int yychar;
 
/* The semantic value of the look-ahead symbol. */
YYSTYPE yylval;
 
/* Number of syntax errors so far. */
int yynerrs;
 
 
 
/*----------.
| yyparse. |
`----------*/
 
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
int
yyparse (void *YYPARSE_PARAM)
#else
int
yyparse (YYPARSE_PARAM)
void *YYPARSE_PARAM;
#endif
#else /* ! YYPARSE_PARAM */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
#else
int
yyparse ()
 
#endif
#endif
{
 
int yystate;
int yyn;
int yyresult;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
#endif
 
/* Three stacks and their tools:
`yyss': related to states,
`yyvs': related to semantic values,
`yyls': related to locations.
 
Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
 
/* The state stack. */
yytype_int16 yyssa[YYINITDEPTH];
yytype_int16 *yyss = yyssa;
yytype_int16 *yyssp;
 
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
YYSTYPE *yyvsp;
 
 
 
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
 
YYSIZE_T yystacksize = YYINITDEPTH;
 
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
 
 
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
 
YYDPRINTF ((stderr, "Starting parse\n"));
 
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
 
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
 
yyssp = yyss;
yyvsp = yyvs;
 
goto yysetstate;
 
/*------------------------------------------------------------.
| yynewstate -- Push a new state, which is found in yystate. |
`------------------------------------------------------------*/
yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
 
yysetstate:
*yyssp = yystate;
 
if (yyss + yystacksize - 1 <= yyssp)
{
/* Get the current used size of the three stacks, in elements. */
YYSIZE_T yysize = yyssp - yyss + 1;
 
#ifdef yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;
 
 
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
 
&yystacksize);
 
yyss = yyss1;
yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
goto yyexhaustedlab;
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
 
{
yytype_int16 *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss);
YYSTACK_RELOCATE (yyvs);
 
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
 
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
 
 
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
 
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
 
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
goto yybackup;
 
/*-----------.
| yybackup. |
`-----------*/
yybackup:
 
/* Do appropriate processing given the current state. Read a
look-ahead token if we need one and don't already have one. */
 
/* First try to decide what to do without reference to look-ahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
 
/* Not known => get a look-ahead token if don't already have one. */
 
/* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX;
}
 
if (yychar <= YYEOF)
{
yychar = yytoken = YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
else
{
yytoken = YYTRANSLATE (yychar);
YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
}
 
/* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */
yyn += yytoken;
if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
goto yydefault;
yyn = yytable[yyn];
if (yyn <= 0)
{
if (yyn == 0 || yyn == YYTABLE_NINF)
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
 
if (yyn == YYFINAL)
YYACCEPT;
 
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
 
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
/* Discard the shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
 
yystate = yyn;
*++yyvsp = yylval;
 
goto yynewstate;
 
 
/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state. |
`-----------------------------------------------------------*/
yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
goto yyreduce;
 
 
/*-----------------------------.
| yyreduce -- Do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
yylen = yyr2[yyn];
 
/* If YYLEN is nonzero, implement the default value of the action:
`$$ = $1'.
 
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
users should not rely upon it. Assigning to YYVAL
unconditionally makes the parser a bit smaller, and it avoids a
GCC warning that YYVAL may be used uninitialized. */
yyval = yyvsp[1-yylen];
 
 
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 4:
#line 144 "deffilep.y"
{ def_image_name ((yyvsp[(2) - (3)].id), (yyvsp[(3) - (3)].vma), 0); }
break;
 
case 5:
#line 145 "deffilep.y"
{ def_image_name ((yyvsp[(2) - (3)].id), (yyvsp[(3) - (3)].vma), 1); }
break;
 
case 6:
#line 146 "deffilep.y"
{ def_description ((yyvsp[(2) - (2)].id));}
break;
 
case 7:
#line 147 "deffilep.y"
{ def_stacksize ((yyvsp[(2) - (3)].number), (yyvsp[(3) - (3)].number));}
break;
 
case 8:
#line 148 "deffilep.y"
{ def_heapsize ((yyvsp[(2) - (3)].number), (yyvsp[(3) - (3)].number));}
break;
 
case 9:
#line 149 "deffilep.y"
{ def_section ("CODE", (yyvsp[(2) - (2)].number));}
break;
 
case 10:
#line 150 "deffilep.y"
{ def_section ("DATA", (yyvsp[(2) - (2)].number));}
break;
 
case 14:
#line 154 "deffilep.y"
{ def_version ((yyvsp[(2) - (2)].number), 0);}
break;
 
case 15:
#line 155 "deffilep.y"
{ def_version ((yyvsp[(2) - (4)].number), (yyvsp[(4) - (4)].number));}
break;
 
case 16:
#line 156 "deffilep.y"
{ def_directive ((yyvsp[(2) - (2)].id));}
break;
 
case 17:
#line 157 "deffilep.y"
{ def_aligncomm ((yyvsp[(2) - (4)].id), (yyvsp[(4) - (4)].number));}
break;
 
case 21:
#line 172 "deffilep.y"
{ def_exports ((yyvsp[(1) - (7)].id), (yyvsp[(2) - (7)].id), (yyvsp[(3) - (7)].number), (yyvsp[(5) - (7)].number), (yyvsp[(7) - (7)].id)); }
break;
 
case 22:
#line 178 "deffilep.y"
{ (yyval.number) = (yyvsp[(1) - (3)].number) | (yyvsp[(3) - (3)].number); }
break;
 
case 23:
#line 179 "deffilep.y"
{ (yyval.number) = 0; }
break;
 
case 24:
#line 182 "deffilep.y"
{ (yyval.number) = 1; }
break;
 
case 25:
#line 183 "deffilep.y"
{ (yyval.number) = 1; }
break;
 
case 26:
#line 184 "deffilep.y"
{ (yyval.number) = 2; }
break;
 
case 27:
#line 185 "deffilep.y"
{ (yyval.number) = 2; }
break;
 
case 28:
#line 186 "deffilep.y"
{ (yyval.number) = 4; }
break;
 
case 29:
#line 187 "deffilep.y"
{ (yyval.number) = 4; }
break;
 
case 30:
#line 188 "deffilep.y"
{ (yyval.number) = 8; }
break;
 
case 31:
#line 189 "deffilep.y"
{ (yyval.number) = 8; }
break;
 
case 34:
#line 198 "deffilep.y"
{ def_import ((yyvsp[(1) - (8)].id), (yyvsp[(3) - (8)].id), (yyvsp[(5) - (8)].id), (yyvsp[(7) - (8)].id), -1, (yyvsp[(8) - (8)].id)); }
break;
 
case 35:
#line 200 "deffilep.y"
{ def_import ((yyvsp[(1) - (8)].id), (yyvsp[(3) - (8)].id), (yyvsp[(5) - (8)].id), 0, (yyvsp[(7) - (8)].number), (yyvsp[(8) - (8)].id)); }
break;
 
case 36:
#line 202 "deffilep.y"
{ def_import ((yyvsp[(1) - (6)].id), (yyvsp[(3) - (6)].id), 0, (yyvsp[(5) - (6)].id), -1, (yyvsp[(6) - (6)].id)); }
break;
 
case 37:
#line 204 "deffilep.y"
{ def_import ((yyvsp[(1) - (6)].id), (yyvsp[(3) - (6)].id), 0, 0, (yyvsp[(5) - (6)].number), (yyvsp[(6) - (6)].id)); }
break;
 
case 38:
#line 206 "deffilep.y"
{ def_import( 0, (yyvsp[(1) - (6)].id), (yyvsp[(3) - (6)].id), (yyvsp[(5) - (6)].id), -1, (yyvsp[(6) - (6)].id)); }
break;
 
case 39:
#line 208 "deffilep.y"
{ def_import ( 0, (yyvsp[(1) - (4)].id), 0, (yyvsp[(3) - (4)].id), -1, (yyvsp[(4) - (4)].id)); }
break;
 
case 42:
#line 217 "deffilep.y"
{ def_section ((yyvsp[(1) - (2)].id), (yyvsp[(2) - (2)].number));}
break;
 
case 43:
#line 218 "deffilep.y"
{ def_section_alt ((yyvsp[(1) - (2)].id), (yyvsp[(2) - (2)].id));}
break;
 
case 44:
#line 222 "deffilep.y"
{ (yyval.number) = (yyvsp[(1) - (3)].number) | (yyvsp[(3) - (3)].number); }
break;
 
case 45:
#line 223 "deffilep.y"
{ (yyval.number) = (yyvsp[(1) - (1)].number); }
break;
 
case 48:
#line 230 "deffilep.y"
{ (yyval.number)=(yyvsp[(2) - (2)].number);}
break;
 
case 49:
#line 231 "deffilep.y"
{ (yyval.number)=-1;}
break;
 
case 50:
#line 235 "deffilep.y"
{ (yyval.number) = 1;}
break;
 
case 51:
#line 236 "deffilep.y"
{ (yyval.number) = 2;}
break;
 
case 52:
#line 237 "deffilep.y"
{ (yyval.number)=4;}
break;
 
case 53:
#line 238 "deffilep.y"
{ (yyval.number)=8;}
break;
 
case 54:
#line 242 "deffilep.y"
{ (yyval.id_const) = "BASE"; }
break;
 
case 55:
#line 243 "deffilep.y"
{ (yyval.id_const) = "CODE"; }
break;
 
case 56:
#line 244 "deffilep.y"
{ (yyval.id_const) = "CONSTANT"; }
break;
 
case 57:
#line 245 "deffilep.y"
{ (yyval.id_const) = "constant"; }
break;
 
case 58:
#line 246 "deffilep.y"
{ (yyval.id_const) = "DATA"; }
break;
 
case 59:
#line 247 "deffilep.y"
{ (yyval.id_const) = "data"; }
break;
 
case 60:
#line 248 "deffilep.y"
{ (yyval.id_const) = "DESCRIPTION"; }
break;
 
case 61:
#line 249 "deffilep.y"
{ (yyval.id_const) = "DIRECTIVE"; }
break;
 
case 62:
#line 250 "deffilep.y"
{ (yyval.id_const) = "EXECUTE"; }
break;
 
case 63:
#line 251 "deffilep.y"
{ (yyval.id_const) = "EXPORTS"; }
break;
 
case 64:
#line 252 "deffilep.y"
{ (yyval.id_const) = "HEAPSIZE"; }
break;
 
case 65:
#line 253 "deffilep.y"
{ (yyval.id_const) = "IMPORTS"; }
break;
 
case 66:
#line 260 "deffilep.y"
{ (yyval.id_const) = "NAME"; }
break;
 
case 67:
#line 261 "deffilep.y"
{ (yyval.id_const) = "NONAME"; }
break;
 
case 68:
#line 262 "deffilep.y"
{ (yyval.id_const) = "noname"; }
break;
 
case 69:
#line 263 "deffilep.y"
{ (yyval.id_const) = "PRIVATE"; }
break;
 
case 70:
#line 264 "deffilep.y"
{ (yyval.id_const) = "private"; }
break;
 
case 71:
#line 265 "deffilep.y"
{ (yyval.id_const) = "READ"; }
break;
 
case 72:
#line 266 "deffilep.y"
{ (yyval.id_const) = "SHARED"; }
break;
 
case 73:
#line 267 "deffilep.y"
{ (yyval.id_const) = "STACKSIZE"; }
break;
 
case 74:
#line 268 "deffilep.y"
{ (yyval.id_const) = "VERSION"; }
break;
 
case 75:
#line 269 "deffilep.y"
{ (yyval.id_const) = "WRITE"; }
break;
 
case 76:
#line 272 "deffilep.y"
{ (yyval.id) = (yyvsp[(1) - (1)].id); }
break;
 
case 77:
#line 274 "deffilep.y"
{
char *name = xmalloc (strlen ((yyvsp[(2) - (2)].id_const)) + 2);
sprintf (name, ".%s", (yyvsp[(2) - (2)].id_const));
(yyval.id) = name;
}
break;
 
case 78:
#line 280 "deffilep.y"
{
char *name = def_pool_alloc (strlen ((yyvsp[(2) - (2)].id)) + 2);
sprintf (name, ".%s", (yyvsp[(2) - (2)].id));
(yyval.id) = name;
}
break;
 
case 79:
#line 286 "deffilep.y"
{
char *name = def_pool_alloc (strlen ((yyvsp[(1) - (3)].id_const)) + 1 + strlen ((yyvsp[(3) - (3)].id)) + 1);
sprintf (name, "%s.%s", (yyvsp[(1) - (3)].id_const), (yyvsp[(3) - (3)].id));
(yyval.id) = name;
}
break;
 
case 80:
#line 292 "deffilep.y"
{
char *name = def_pool_alloc (strlen ((yyvsp[(1) - (3)].id)) + 1 + strlen ((yyvsp[(3) - (3)].id)) + 1);
sprintf (name, "%s.%s", (yyvsp[(1) - (3)].id), (yyvsp[(3) - (3)].id));
(yyval.id) = name;
}
break;
 
case 81:
#line 299 "deffilep.y"
{ (yyval.id) = (yyvsp[(1) - (1)].id); }
break;
 
case 82:
#line 300 "deffilep.y"
{ (yyval.id) = ""; }
break;
 
case 83:
#line 303 "deffilep.y"
{ (yyval.id) = (yyvsp[(2) - (2)].id); }
break;
 
case 84:
#line 304 "deffilep.y"
{ (yyval.id) = 0; }
break;
 
case 85:
#line 308 "deffilep.y"
{ (yyval.number) = (yyvsp[(2) - (2)].number);}
break;
 
case 86:
#line 309 "deffilep.y"
{ (yyval.number) = -1;}
break;
 
case 87:
#line 313 "deffilep.y"
{ (yyval.id) = (yyvsp[(2) - (2)].id); }
break;
 
case 88:
#line 314 "deffilep.y"
{ (yyval.id) = 0; }
break;
 
case 89:
#line 317 "deffilep.y"
{ (yyval.vma) = (yyvsp[(3) - (3)].vma);}
break;
 
case 90:
#line 318 "deffilep.y"
{ (yyval.vma) = (bfd_vma) -1;}
break;
 
case 91:
#line 321 "deffilep.y"
{ (yyval.id) = (yyvsp[(1) - (1)].id); }
break;
 
case 92:
#line 323 "deffilep.y"
{
char *id = def_pool_alloc (strlen ((yyvsp[(2) - (2)].id)) + 2);
sprintf (id, ".%s", (yyvsp[(2) - (2)].id));
(yyval.id) = id;
}
break;
 
case 93:
#line 329 "deffilep.y"
{
char *id = def_pool_alloc (strlen ((yyvsp[(1) - (4)].id)) + 1 + strlen ((yyvsp[(3) - (4)].digits)) + strlen ((yyvsp[(4) - (4)].id)) + 1);
sprintf (id, "%s.%s%s", (yyvsp[(1) - (4)].id), (yyvsp[(3) - (4)].digits), (yyvsp[(4) - (4)].id));
(yyval.id) = id;
}
break;
 
case 94:
#line 336 "deffilep.y"
{ (yyval.digits) = (yyvsp[(1) - (1)].digits); }
break;
 
case 95:
#line 337 "deffilep.y"
{ (yyval.digits) = ""; }
break;
 
case 96:
#line 340 "deffilep.y"
{ (yyval.id) = (yyvsp[(1) - (1)].id); }
break;
 
case 97:
#line 341 "deffilep.y"
{ (yyval.id) = ""; }
break;
 
case 98:
#line 344 "deffilep.y"
{ (yyval.number) = strtoul ((yyvsp[(1) - (1)].digits), 0, 0); }
break;
 
case 99:
#line 346 "deffilep.y"
{ (yyval.vma) = (bfd_vma) strtoull ((yyvsp[(1) - (1)].digits), 0, 0); }
break;
 
 
/* Line 1267 of yacc.c. */
#line 2065 "deffilep.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
 
*++yyvsp = yyval;
 
 
/* Now `shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
 
yyn = yyr1[yyn];
 
yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
yystate = yydefgoto[yyn - YYNTOKENS];
 
goto yynewstate;
 
 
/*------------------------------------.
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
{
YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
{
YYSIZE_T yyalloc = 2 * yysize;
if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
yyalloc = YYSTACK_ALLOC_MAXIMUM;
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yyalloc);
if (yymsg)
yymsg_alloc = yyalloc;
else
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
}
}
 
if (0 < yysize && yysize <= yymsg_alloc)
{
(void) yysyntax_error (yymsg, yystate, yychar);
yyerror (yymsg);
}
else
{
yyerror (YY_("syntax error"));
if (yysize != 0)
goto yyexhaustedlab;
}
}
#endif
}
 
 
 
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse look-ahead token after an
error, discard it. */
 
if (yychar <= YYEOF)
{
/* Return failure if at end of input. */
if (yychar == YYEOF)
YYABORT;
}
else
{
yydestruct ("Error: discarding",
yytoken, &yylval);
yychar = YYEMPTY;
}
}
 
/* Else will try to reuse look-ahead token after shifting the error
token. */
goto yyerrlab1;
 
 
/*---------------------------------------------------.
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
 
/* Pacify compilers like GCC when the user code never invokes
YYERROR and the label yyerrorlab therefore never appears in user
code. */
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
 
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
goto yyerrlab1;
 
 
/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
yyerrstatus = 3; /* Each real token shifted decrements this. */
 
for (;;)
{
yyn = yypact[yystate];
if (yyn != YYPACT_NINF)
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
{
yyn = yytable[yyn];
if (0 < yyn)
break;
}
}
 
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
YYABORT;
 
 
yydestruct ("Error: popping",
yystos[yystate], yyvsp);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
 
if (yyn == YYFINAL)
YYACCEPT;
 
*++yyvsp = yylval;
 
 
/* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
 
yystate = yyn;
goto yynewstate;
 
 
/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here. |
`-------------------------------------*/
yyacceptlab:
yyresult = 0;
goto yyreturn;
 
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
yyabortlab:
yyresult = 1;
goto yyreturn;
 
#ifndef yyoverflow
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
 
yyreturn:
if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
yystos[*yyssp], yyvsp);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
/* Make sure YYID is used. */
return YYID (yyresult);
}
 
 
#line 348 "deffilep.y"
 
 
/*****************************************************************************
API
*****************************************************************************/
 
static FILE *the_file;
static const char *def_filename;
static int linenumber;
static def_file *def;
static int saw_newline;
 
struct directive
{
struct directive *next;
char *name;
int len;
};
 
static struct directive *directives = 0;
 
def_file *
def_file_empty (void)
{
def_file *rv = xmalloc (sizeof (def_file));
memset (rv, 0, sizeof (def_file));
rv->is_dll = -1;
rv->base_address = (bfd_vma) -1;
rv->stack_reserve = rv->stack_commit = -1;
rv->heap_reserve = rv->heap_commit = -1;
rv->version_major = rv->version_minor = -1;
return rv;
}
 
def_file *
def_file_parse (const char *filename, def_file *add_to)
{
struct directive *d;
 
the_file = fopen (filename, "r");
def_filename = filename;
linenumber = 1;
if (!the_file)
{
//perror (filename);
printf("Error %s\n", filename);
return 0;
}
if (add_to)
{
def = add_to;
}
else
{
def = def_file_empty ();
}
 
saw_newline = 1;
if (def_parse ())
{
def_file_free (def);
fclose (the_file);
def_pool_free ();
return 0;
}
 
fclose (the_file);
 
while ((d = directives) != NULL)
{
#if TRACE
printf ("Adding directive %08x `%s'\n", d->name, d->name);
#endif
def_file_add_directive (def, d->name, d->len);
directives = d->next;
free (d->name);
free (d);
}
def_pool_free ();
 
return def;
}
 
void
def_file_free (def_file *fdef)
{
int i;
 
if (!fdef)
return;
if (fdef->name)
free (fdef->name);
if (fdef->description)
free (fdef->description);
 
if (fdef->section_defs)
{
for (i = 0; i < fdef->num_section_defs; i++)
{
if (fdef->section_defs[i].name)
free (fdef->section_defs[i].name);
if (fdef->section_defs[i].class)
free (fdef->section_defs[i].class);
}
free (fdef->section_defs);
}
 
if (fdef->exports)
{
for (i = 0; i < fdef->num_exports; i++)
{
if (fdef->exports[i].internal_name
&& fdef->exports[i].internal_name != fdef->exports[i].name)
free (fdef->exports[i].internal_name);
if (fdef->exports[i].name)
free (fdef->exports[i].name);
if (fdef->exports[i].its_name)
free (fdef->exports[i].its_name);
}
free (fdef->exports);
}
 
if (fdef->imports)
{
for (i = 0; i < fdef->num_imports; i++)
{
if (fdef->imports[i].internal_name
&& fdef->imports[i].internal_name != fdef->imports[i].name)
free (fdef->imports[i].internal_name);
if (fdef->imports[i].name)
free (fdef->imports[i].name);
if (fdef->imports[i].its_name)
free (fdef->imports[i].its_name);
}
free (fdef->imports);
}
 
while (fdef->modules)
{
def_file_module *m = fdef->modules;
 
fdef->modules = fdef->modules->next;
free (m);
}
 
while (fdef->aligncomms)
{
def_file_aligncomm *c = fdef->aligncomms;
 
fdef->aligncomms = fdef->aligncomms->next;
free (c->symbol_name);
free (c);
}
 
free (fdef);
}
 
#ifdef DEF_FILE_PRINT
void
def_file_print (FILE *file, def_file *fdef)
{
int i;
 
fprintf (file, ">>>> def_file at 0x%08x\n", fdef);
if (fdef->name)
fprintf (file, " name: %s\n", fdef->name ? fdef->name : "(unspecified)");
if (fdef->is_dll != -1)
fprintf (file, " is dll: %s\n", fdef->is_dll ? "yes" : "no");
if (fdef->base_address != (bfd_vma) -1)
{
fprintf (file, " base address: 0x");
fprintf_vma (file, fdef->base_address);
fprintf (file, "\n");
}
if (fdef->description)
fprintf (file, " description: `%s'\n", fdef->description);
if (fdef->stack_reserve != -1)
fprintf (file, " stack reserve: 0x%08x\n", fdef->stack_reserve);
if (fdef->stack_commit != -1)
fprintf (file, " stack commit: 0x%08x\n", fdef->stack_commit);
if (fdef->heap_reserve != -1)
fprintf (file, " heap reserve: 0x%08x\n", fdef->heap_reserve);
if (fdef->heap_commit != -1)
fprintf (file, " heap commit: 0x%08x\n", fdef->heap_commit);
 
if (fdef->num_section_defs > 0)
{
fprintf (file, " section defs:\n");
 
for (i = 0; i < fdef->num_section_defs; i++)
{
fprintf (file, " name: `%s', class: `%s', flags:",
fdef->section_defs[i].name, fdef->section_defs[i].class);
if (fdef->section_defs[i].flag_read)
fprintf (file, " R");
if (fdef->section_defs[i].flag_write)
fprintf (file, " W");
if (fdef->section_defs[i].flag_execute)
fprintf (file, " X");
if (fdef->section_defs[i].flag_shared)
fprintf (file, " S");
fprintf (file, "\n");
}
}
 
if (fdef->num_exports > 0)
{
fprintf (file, " exports:\n");
 
for (i = 0; i < fdef->num_exports; i++)
{
fprintf (file, " name: `%s', int: `%s', ordinal: %d, flags:",
fdef->exports[i].name, fdef->exports[i].internal_name,
fdef->exports[i].ordinal);
if (fdef->exports[i].flag_private)
fprintf (file, " P");
if (fdef->exports[i].flag_constant)
fprintf (file, " C");
if (fdef->exports[i].flag_noname)
fprintf (file, " N");
if (fdef->exports[i].flag_data)
fprintf (file, " D");
fprintf (file, "\n");
}
}
 
if (fdef->num_imports > 0)
{
fprintf (file, " imports:\n");
 
for (i = 0; i < fdef->num_imports; i++)
{
fprintf (file, " int: %s, from: `%s', name: `%s', ordinal: %d\n",
fdef->imports[i].internal_name,
fdef->imports[i].module,
fdef->imports[i].name,
fdef->imports[i].ordinal);
}
}
 
if (fdef->version_major != -1)
fprintf (file, " version: %d.%d\n", fdef->version_major, fdef->version_minor);
 
fprintf (file, "<<<< def_file at 0x%08x\n", fdef);
}
#endif
 
/* Helper routine to check for identity of string pointers,
which might be NULL. */
 
static int
are_names_equal (const char *s1, const char *s2)
{
if (!s1 && !s2)
return 0;
if (!s1 || !s2)
return (!s1 ? -1 : 1);
return strcmp (s1, s2);
}
 
static int
cmp_export_elem (const def_file_export *e, const char *ex_name,
const char *in_name, const char *its_name,
int ord)
{
int r;
 
if ((r = are_names_equal (ex_name, e->name)) != 0)
return r;
if ((r = are_names_equal (in_name, e->internal_name)) != 0)
return r;
if ((r = are_names_equal (its_name, e->its_name)) != 0)
return r;
return (ord - e->ordinal);
}
 
/* Search the position of the identical element, or returns the position
of the next higher element. If last valid element is smaller, then MAX
is returned. */
 
static int
find_export_in_list (def_file_export *b, int max,
const char *ex_name, const char *in_name,
const char *its_name, int ord, int *is_ident)
{
int e, l, r, p;
 
*is_ident = 0;
if (!max)
return 0;
if ((e = cmp_export_elem (b, ex_name, in_name, its_name, ord)) <= 0)
{
if (!e)
*is_ident = 1;
return 0;
}
if (max == 1)
return 1;
if ((e = cmp_export_elem (b + (max - 1), ex_name, in_name, its_name, ord)) > 0)
return max;
else if (!e || max == 2)
{
if (!e)
*is_ident = 1;
return max - 1;
}
l = 0; r = max - 1;
while (l < r)
{
p = (l + r) / 2;
e = cmp_export_elem (b + p, ex_name, in_name, its_name, ord);
if (!e)
{
*is_ident = 1;
return p;
}
else if (e < 0)
r = p - 1;
else if (e > 0)
l = p + 1;
}
if ((e = cmp_export_elem (b + l, ex_name, in_name, its_name, ord)) > 0)
++l;
else if (!e)
*is_ident = 1;
return l;
}
 
def_file_export *
def_file_add_export (def_file *fdef,
const char *external_name,
const char *internal_name,
int ordinal,
const char *its_name,
int *is_dup)
{
def_file_export *e;
int pos;
int max_exports = ROUND_UP(fdef->num_exports, 32);
 
if (internal_name && !external_name)
external_name = internal_name;
if (external_name && !internal_name)
internal_name = external_name;
 
/* We need to avoid duplicates. */
*is_dup = 0;
pos = find_export_in_list (fdef->exports, fdef->num_exports,
external_name, internal_name,
its_name, ordinal, is_dup);
 
if (*is_dup != 0)
return (fdef->exports + pos);
 
if (fdef->num_exports >= max_exports)
{
max_exports = ROUND_UP(fdef->num_exports + 1, 32);
if (fdef->exports)
fdef->exports = xrealloc (fdef->exports,
max_exports * sizeof (def_file_export));
else
fdef->exports = xmalloc (max_exports * sizeof (def_file_export));
}
 
e = fdef->exports + pos;
if (pos != fdef->num_exports)
memmove (&e[1], e, (sizeof (def_file_export) * (fdef->num_exports - pos)));
memset (e, 0, sizeof (def_file_export));
e->name = xstrdup (external_name);
e->internal_name = xstrdup (internal_name);
e->its_name = (its_name ? xstrdup (its_name) : NULL);
e->ordinal = ordinal;
fdef->num_exports++;
return e;
}
 
def_file_module *
def_get_module (def_file *fdef, const char *name)
{
def_file_module *s;
 
for (s = fdef->modules; s; s = s->next)
if (strcmp (s->name, name) == 0)
return s;
 
return NULL;
}
 
static def_file_module *
def_stash_module (def_file *fdef, const char *name)
{
def_file_module *s;
 
if ((s = def_get_module (fdef, name)) != NULL)
return s;
s = xmalloc (sizeof (def_file_module) + strlen (name));
s->next = fdef->modules;
fdef->modules = s;
s->user_data = 0;
strcpy (s->name, name);
return s;
}
 
static int
cmp_import_elem (const def_file_import *e, const char *ex_name,
const char *in_name, const char *module,
int ord)
{
int r;
 
if ((r = are_names_equal (module, (e->module ? e->module->name : NULL))))
return r;
if ((r = are_names_equal (ex_name, e->name)) != 0)
return r;
if ((r = are_names_equal (in_name, e->internal_name)) != 0)
return r;
if (ord != e->ordinal)
return (ord < e->ordinal ? -1 : 1);
return 0;
}
 
/* Search the position of the identical element, or returns the position
of the next higher element. If last valid element is smaller, then MAX
is returned. */
 
static int
find_import_in_list (def_file_import *b, int max,
const char *ex_name, const char *in_name,
const char *module, int ord, int *is_ident)
{
int e, l, r, p;
 
*is_ident = 0;
if (!max)
return 0;
if ((e = cmp_import_elem (b, ex_name, in_name, module, ord)) <= 0)
{
if (!e)
*is_ident = 1;
return 0;
}
if (max == 1)
return 1;
if ((e = cmp_import_elem (b + (max - 1), ex_name, in_name, module, ord)) > 0)
return max;
else if (!e || max == 2)
{
if (!e)
*is_ident = 1;
return max - 1;
}
l = 0; r = max - 1;
while (l < r)
{
p = (l + r) / 2;
e = cmp_import_elem (b + p, ex_name, in_name, module, ord);
if (!e)
{
*is_ident = 1;
return p;
}
else if (e < 0)
r = p - 1;
else if (e > 0)
l = p + 1;
}
if ((e = cmp_import_elem (b + l, ex_name, in_name, module, ord)) > 0)
++l;
else if (!e)
*is_ident = 1;
return l;
}
 
def_file_import *
def_file_add_import (def_file *fdef,
const char *name,
const char *module,
int ordinal,
const char *internal_name,
const char *its_name,
int *is_dup)
{
def_file_import *i;
int pos;
int max_imports = ROUND_UP (fdef->num_imports, 16);
 
/* We need to avoid here duplicates. */
*is_dup = 0;
pos = find_import_in_list (fdef->imports, fdef->num_imports,
name,
(!internal_name ? name : internal_name),
module, ordinal, is_dup);
if (*is_dup != 0)
return fdef->imports + pos;
 
if (fdef->num_imports >= max_imports)
{
max_imports = ROUND_UP (fdef->num_imports+1, 16);
 
if (fdef->imports)
fdef->imports = xrealloc (fdef->imports,
max_imports * sizeof (def_file_import));
else
fdef->imports = xmalloc (max_imports * sizeof (def_file_import));
}
i = fdef->imports + pos;
if (pos != fdef->num_imports)
memmove (&i[1], i, (sizeof (def_file_import) * (fdef->num_imports - pos)));
memset (i, 0, sizeof (def_file_import));
if (name)
i->name = xstrdup (name);
if (module)
i->module = def_stash_module (fdef, module);
i->ordinal = ordinal;
if (internal_name)
i->internal_name = xstrdup (internal_name);
else
i->internal_name = i->name;
i->its_name = (its_name ? xstrdup (its_name) : NULL);
fdef->num_imports++;
 
return i;
}
 
struct
{
char *param;
int token;
}
diropts[] =
{
{ "-heap", HEAPSIZE },
{ "-stack", STACKSIZE_K },
{ "-attr", SECTIONS },
{ "-export", EXPORTS },
{ "-aligncomm", ALIGNCOMM },
{ 0, 0 }
};
 
void
def_file_add_directive (def_file *my_def, const char *param, int len)
{
def_file *save_def = def;
const char *pend = param + len;
char * tend = (char *) param;
int i;
 
def = my_def;
 
while (param < pend)
{
while (param < pend
&& (ISSPACE (*param) || *param == '\n' || *param == 0))
param++;
 
if (param == pend)
break;
 
/* Scan forward until we encounter any of:
- the end of the buffer
- the start of a new option
- a newline seperating options
- a NUL seperating options. */
for (tend = (char *) (param + 1);
(tend < pend
&& !(ISSPACE (tend[-1]) && *tend == '-')
&& *tend != '\n' && *tend != 0);
tend++)
;
 
for (i = 0; diropts[i].param; i++)
{
len = strlen (diropts[i].param);
 
if (tend - param >= len
&& strncmp (param, diropts[i].param, len) == 0
&& (param[len] == ':' || param[len] == ' '))
{
lex_parse_string_end = tend;
lex_parse_string = param + len + 1;
lex_forced_token = diropts[i].token;
saw_newline = 0;
if (def_parse ())
continue;
break;
}
}
 
if (!diropts[i].param)
{
if (tend < pend)
{
char saved;
 
saved = * tend;
* tend = 0;
/* xgettext:c-format */
einfo (_("Warning: .drectve `%s' unrecognized\n"), param);
* tend = saved;
}
else
{
einfo (_("Warning: corrupt .drectve at end of def file\n"));
}
}
 
lex_parse_string = 0;
param = tend;
}
 
def = save_def;
def_pool_free ();
}
 
/* Parser Callbacks. */
 
static void
def_image_name (const char *name, bfd_vma base, int is_dll)
{
/* If a LIBRARY or NAME statement is specified without a name, there is nothing
to do here. We retain the output filename specified on command line. */
if (*name)
{
const char* image_name = lbasename (name);
 
if (image_name != name)
einfo ("%s:%d: Warning: path components stripped from %s, '%s'\n",
def_filename, linenumber, is_dll ? "LIBRARY" : "NAME",
name);
if (def->name)
free (def->name);
/* Append the default suffix, if none specified. */
if (strchr (image_name, '.') == 0)
{
const char * suffix = is_dll ? ".dll" : ".exe";
 
def->name = xmalloc (strlen (image_name) + strlen (suffix) + 1);
sprintf (def->name, "%s%s", image_name, suffix);
}
else
def->name = xstrdup (image_name);
}
 
/* Honor a BASE address statement, even if LIBRARY string is empty. */
def->base_address = base;
def->is_dll = is_dll;
}
 
static void
def_description (const char *text)
{
int len = def->description ? strlen (def->description) : 0;
 
len += strlen (text) + 1;
if (def->description)
{
def->description = xrealloc (def->description, len);
strcat (def->description, text);
}
else
{
def->description = xmalloc (len);
strcpy (def->description, text);
}
}
 
static void
def_stacksize (int reserve, int commit)
{
def->stack_reserve = reserve;
def->stack_commit = commit;
}
 
static void
def_heapsize (int reserve, int commit)
{
def->heap_reserve = reserve;
def->heap_commit = commit;
}
 
static void
def_section (const char *name, int attr)
{
def_file_section *s;
int max_sections = ROUND_UP (def->num_section_defs, 4);
 
if (def->num_section_defs >= max_sections)
{
max_sections = ROUND_UP (def->num_section_defs+1, 4);
 
if (def->section_defs)
def->section_defs = xrealloc (def->section_defs,
max_sections * sizeof (def_file_import));
else
def->section_defs = xmalloc (max_sections * sizeof (def_file_import));
}
s = def->section_defs + def->num_section_defs;
memset (s, 0, sizeof (def_file_section));
s->name = xstrdup (name);
if (attr & 1)
s->flag_read = 1;
if (attr & 2)
s->flag_write = 1;
if (attr & 4)
s->flag_execute = 1;
if (attr & 8)
s->flag_shared = 1;
 
def->num_section_defs++;
}
 
static void
def_section_alt (const char *name, const char *attr)
{
int aval = 0;
 
for (; *attr; attr++)
{
switch (*attr)
{
case 'R':
case 'r':
aval |= 1;
break;
case 'W':
case 'w':
aval |= 2;
break;
case 'X':
case 'x':
aval |= 4;
break;
case 'S':
case 's':
aval |= 8;
break;
}
}
def_section (name, aval);
}
 
static void
def_exports (const char *external_name,
const char *internal_name,
int ordinal,
int flags,
const char *its_name)
{
def_file_export *dfe;
int is_dup = 0;
 
if (!internal_name && external_name)
internal_name = external_name;
#if TRACE
printf ("def_exports, ext=%s int=%s\n", external_name, internal_name);
#endif
 
dfe = def_file_add_export (def, external_name, internal_name, ordinal,
its_name, &is_dup);
 
/* We might check here for flag redefinition and warn. For now we
ignore duplicates silently. */
if (is_dup)
return;
 
if (flags & 1)
dfe->flag_noname = 1;
if (flags & 2)
dfe->flag_constant = 1;
if (flags & 4)
dfe->flag_data = 1;
if (flags & 8)
dfe->flag_private = 1;
}
 
static void
def_import (const char *internal_name,
const char *module,
const char *dllext,
const char *name,
int ordinal,
const char *its_name)
{
char *buf = 0;
const char *ext = dllext ? dllext : "dll";
int is_dup = 0;
 
buf = xmalloc (strlen (module) + strlen (ext) + 2);
sprintf (buf, "%s.%s", module, ext);
module = buf;
 
def_file_add_import (def, name, module, ordinal, internal_name, its_name,
&is_dup);
free (buf);
}
 
static void
def_version (int major, int minor)
{
def->version_major = major;
def->version_minor = minor;
}
 
static void
def_directive (char *str)
{
struct directive *d = xmalloc (sizeof (struct directive));
 
d->next = directives;
directives = d;
d->name = xstrdup (str);
d->len = strlen (str);
}
 
static void
def_aligncomm (char *str, int align)
{
def_file_aligncomm *c, *p;
 
p = NULL;
c = def->aligncomms;
while (c != NULL)
{
int e = strcmp (c->symbol_name, str);
if (!e)
{
/* Not sure if we want to allow here duplicates with
different alignments, but for now we keep them. */
e = (int) c->alignment - align;
if (!e)
return;
}
if (e > 0)
break;
c = (p = c)->next;
}
 
c = xmalloc (sizeof (def_file_aligncomm));
c->symbol_name = xstrdup (str);
c->alignment = (unsigned int) align;
if (!p)
{
c->next = def->aligncomms;
def->aligncomms = c;
}
else
{
c->next = p->next;
p->next = c;
}
}
 
static int
def_error (const char *err)
{
einfo ("%P: %s:%d: %s\n",
def_filename ? def_filename : "<unknown-file>", linenumber, err);
return 0;
}
 
 
/* Lexical Scanner. */
 
#undef TRACE
#define TRACE 0
 
/* Never freed, but always reused as needed, so no real leak. */
static char *buffer = 0;
static int buflen = 0;
static int bufptr = 0;
 
static void
put_buf (char c)
{
if (bufptr == buflen)
{
buflen += 50; /* overly reasonable, eh? */
if (buffer)
buffer = xrealloc (buffer, buflen + 1);
else
buffer = xmalloc (buflen + 1);
}
buffer[bufptr++] = c;
buffer[bufptr] = 0; /* not optimal, but very convenient. */
}
 
static struct
{
char *name;
int token;
}
tokens[] =
{
{ "BASE", BASE },
{ "CODE", CODE },
{ "CONSTANT", CONSTANTU },
{ "constant", CONSTANTL },
{ "DATA", DATAU },
{ "data", DATAL },
{ "DESCRIPTION", DESCRIPTION },
{ "DIRECTIVE", DIRECTIVE },
{ "EXECUTE", EXECUTE },
{ "EXPORTS", EXPORTS },
{ "HEAPSIZE", HEAPSIZE },
{ "IMPORTS", IMPORTS },
{ "LIBRARY", LIBRARY },
{ "NAME", NAME },
{ "NONAME", NONAMEU },
{ "noname", NONAMEL },
{ "PRIVATE", PRIVATEU },
{ "private", PRIVATEL },
{ "READ", READ },
{ "SECTIONS", SECTIONS },
{ "SEGMENTS", SECTIONS },
{ "SHARED", SHARED },
{ "STACKSIZE", STACKSIZE_K },
{ "VERSION", VERSIONK },
{ "WRITE", WRITE },
{ 0, 0 }
};
 
static int
def_getc (void)
{
int rv;
 
if (lex_parse_string)
{
if (lex_parse_string >= lex_parse_string_end)
rv = EOF;
else
rv = *lex_parse_string++;
}
else
{
rv = fgetc (the_file);
}
if (rv == '\n')
saw_newline = 1;
return rv;
}
 
static int
def_ungetc (int c)
{
if (lex_parse_string)
{
lex_parse_string--;
return c;
}
else
return ungetc (c, the_file);
}
 
static int
def_lex (void)
{
int c, i, q;
 
if (lex_forced_token)
{
i = lex_forced_token;
lex_forced_token = 0;
#if TRACE
printf ("lex: forcing token %d\n", i);
#endif
return i;
}
 
c = def_getc ();
 
/* Trim leading whitespace. */
while (c != EOF && (c == ' ' || c == '\t') && saw_newline)
c = def_getc ();
 
if (c == EOF)
{
#if TRACE
printf ("lex: EOF\n");
#endif
return 0;
}
 
if (saw_newline && c == ';')
{
do
{
c = def_getc ();
}
while (c != EOF && c != '\n');
if (c == '\n')
return def_lex ();
return 0;
}
 
/* Must be something else. */
saw_newline = 0;
 
if (ISDIGIT (c))
{
bufptr = 0;
while (c != EOF && (ISXDIGIT (c) || (c == 'x')))
{
put_buf (c);
c = def_getc ();
}
if (c != EOF)
def_ungetc (c);
yylval.digits = def_pool_strdup (buffer);
#if TRACE
printf ("lex: `%s' returns DIGITS\n", buffer);
#endif
return DIGITS;
}
 
if (ISALPHA (c) || strchr ("$:-_?@", c))
{
bufptr = 0;
q = c;
put_buf (c);
c = def_getc ();
 
if (q == '@')
{
if (ISBLANK (c) ) /* '@' followed by whitespace. */
return (q);
else if (ISDIGIT (c)) /* '@' followed by digit. */
{
def_ungetc (c);
return (q);
}
#if TRACE
printf ("lex: @ returns itself\n");
#endif
}
 
while (c != EOF && (ISALNUM (c) || strchr ("$:-_?/@<>", c)))
{
put_buf (c);
c = def_getc ();
}
if (c != EOF)
def_ungetc (c);
if (ISALPHA (q)) /* Check for tokens. */
{
for (i = 0; tokens[i].name; i++)
if (strcmp (tokens[i].name, buffer) == 0)
{
#if TRACE
printf ("lex: `%s' is a string token\n", buffer);
#endif
return tokens[i].token;
}
}
#if TRACE
printf ("lex: `%s' returns ID\n", buffer);
#endif
yylval.id = def_pool_strdup (buffer);
return ID;
}
 
if (c == '\'' || c == '"')
{
q = c;
c = def_getc ();
bufptr = 0;
 
while (c != EOF && c != q)
{
put_buf (c);
c = def_getc ();
}
yylval.id = def_pool_strdup (buffer);
#if TRACE
printf ("lex: `%s' returns ID\n", buffer);
#endif
return ID;
}
 
if ( c == '=')
{
c = def_getc ();
if (c == '=')
{
#if TRACE
printf ("lex: `==' returns EQUAL\n");
#endif
return EQUAL;
}
def_ungetc (c);
#if TRACE
printf ("lex: `=' returns itself\n");
#endif
return '=';
}
if (c == '.' || c == ',')
{
#if TRACE
printf ("lex: `%c' returns itself\n", c);
#endif
return c;
}
 
if (c == '\n')
{
linenumber++;
saw_newline = 1;
}
 
/*printf ("lex: 0x%02x ignored\n", c); */
return def_lex ();
}
 
static char *
def_pool_alloc (size_t sz)
{
def_pool_str *e;
 
e = (def_pool_str *) xmalloc (sizeof (def_pool_str) + sz);
e->next = pool_strs;
pool_strs = e;
return e->data;
}
 
static char *
def_pool_strdup (const char *str)
{
char *s;
size_t len;
if (!str)
return NULL;
len = strlen (str) + 1;
s = def_pool_alloc (len);
memcpy (s, str, len);
return s;
}
 
static void
def_pool_free (void)
{
def_pool_str *p;
while ((p = pool_strs) != NULL)
{
pool_strs = p->next;
free (p);
}
}
 
/contrib/toolchain/binutils/ld/ei386pe.c
0,0 → 1,3832
 
 
 
 
 
/* Copyright 1995-2013 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
 
/* For WINDOWS_NT */
/* The original file generated returned different default scripts depending
on whether certain switches were set, but these switches pertain to the
Linux system and that particular version of coff. In the NT case, we
only determine if the subsystem is console or windows in order to select
the correct entry point by default. */
 
#define TARGET_IS_i386pe
 
/* Do this before including bfd.h, so we prototype the right functions. */
 
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
#define bfd_arm_allocate_interworking_sections bfd_i386pe_allocate_interworking_sections
#define bfd_arm_get_bfd_for_interworking bfd_i386pe_get_bfd_for_interworking
#define bfd_arm_process_before_allocation bfd_i386pe_process_before_allocation
#endif
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "getopt.h"
#include "libiberty.h"
#include "filenames.h"
#include "ld.h"
#include "ldmain.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldmisc.h"
#include "ldctor.h"
#include "coff/internal.h"
 
/* FIXME: See bfd/peXXigen.c for why we include an architecture specific
header in generic PE code. */
#include "coff/i386.h"
#include "coff/pe.h"
 
/* FIXME: This is a BFD internal header file, and we should not be
using it here. */
#include "../bfd/libcoff.h"
 
#include "deffile.h"
#include "pe-dll.h"
#include "safe-ctype.h"
 
/* Permit the emulation parameters to override the default section
alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes
it seem that include/coff/internal.h should not define
PE_DEF_SECTION_ALIGNMENT. */
#if PE_DEF_SECTION_ALIGNMENT != PE_DEF_SECTION_ALIGNMENT
#undef PE_DEF_SECTION_ALIGNMENT
#define PE_DEF_SECTION_ALIGNMENT
#endif
 
#if defined(TARGET_IS_i386pe) || defined(TARGET_IS_shpe) || defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
#define DLL_SUPPORT
#endif
 
#if defined(TARGET_IS_i386pe)
#define DEFAULT_PSEUDO_RELOC_VERSION 2
#else
#define DEFAULT_PSEUDO_RELOC_VERSION 1
#endif
 
#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
#define PE_DEF_SUBSYSTEM 3
#else
#undef NT_EXE_IMAGE_BASE
#undef PE_DEF_SECTION_ALIGNMENT
#undef PE_DEF_FILE_ALIGNMENT
#define NT_EXE_IMAGE_BASE 0x00010000
 
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe)
#define PE_DEF_SECTION_ALIGNMENT 0x00001000
#define PE_DEF_SUBSYSTEM 9
#else
#define PE_DEF_SECTION_ALIGNMENT 0x00000400
#define PE_DEF_SUBSYSTEM 2
#endif
#define PE_DEF_FILE_ALIGNMENT 0x00000200
#endif
 
static struct internal_extra_pe_aouthdr pe;
static int dll;
static int pe_subsystem = PE_DEF_SUBSYSTEM;
static flagword real_flags = 0;
static int support_old_code = 0;
static char * thumb_entry_symbol = NULL;
static lang_assignment_statement_type *image_base_statement = 0;
static unsigned short pe_dll_characteristics = 0;
static bfd_boolean insert_timestamp = FALSE;
 
#ifdef DLL_SUPPORT
static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable. */
static char *pe_out_def_filename = NULL;
static char *pe_implib_filename = NULL;
static int pe_enable_auto_image_base = 0;
static char *pe_dll_search_prefix = NULL;
#endif
 
extern const char *output_filename;
 
static int is_underscoring (void)
{
int u = 0;
if (pe_leading_underscore != -1)
return pe_leading_underscore;
if (!bfd_get_target_info ("pei-i386", NULL, NULL, &u, NULL))
bfd_get_target_info ("pe-i386", NULL, NULL, &u, NULL);
 
if (u == -1)
abort ();
pe_leading_underscore = (u != 0 ? 1 : 0);
return pe_leading_underscore;
}
 
static void
gld_i386pe_before_parse (void)
{
is_underscoring ();
ldfile_set_output_arch ("i386", bfd_arch_i386);
output_filename = "a.exe";
#ifdef DLL_SUPPORT
input_flags.dynamic = TRUE;
config.has_shared = 1;
link_info.pei386_auto_import = 1;
/* Use by default version. */
link_info.pei386_runtime_pseudo_reloc = DEFAULT_PSEUDO_RELOC_VERSION;
#endif
}
/* Indicates if RDATA shall be merged into DATA when pseudo-relocation
version 2 is used and auto-import is enabled. */
#define MERGE_RDATA_V2 0
 
/* PE format extra command line options. */
 
/* Used for setting flags in the PE header. */
#define OPTION_BASE_FILE (300 + 1)
#define OPTION_DLL (OPTION_BASE_FILE + 1)
#define OPTION_FILE_ALIGNMENT (OPTION_DLL + 1)
#define OPTION_IMAGE_BASE (OPTION_FILE_ALIGNMENT + 1)
#define OPTION_MAJOR_IMAGE_VERSION (OPTION_IMAGE_BASE + 1)
#define OPTION_MAJOR_OS_VERSION (OPTION_MAJOR_IMAGE_VERSION + 1)
#define OPTION_MAJOR_SUBSYSTEM_VERSION (OPTION_MAJOR_OS_VERSION + 1)
#define OPTION_MINOR_IMAGE_VERSION (OPTION_MAJOR_SUBSYSTEM_VERSION + 1)
#define OPTION_MINOR_OS_VERSION (OPTION_MINOR_IMAGE_VERSION + 1)
#define OPTION_MINOR_SUBSYSTEM_VERSION (OPTION_MINOR_OS_VERSION + 1)
#define OPTION_SECTION_ALIGNMENT (OPTION_MINOR_SUBSYSTEM_VERSION + 1)
#define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1)
#define OPTION_SUBSYSTEM (OPTION_STACK + 1)
#define OPTION_HEAP (OPTION_SUBSYSTEM + 1)
#define OPTION_SUPPORT_OLD_CODE (OPTION_HEAP + 1)
#define OPTION_OUT_DEF (OPTION_SUPPORT_OLD_CODE + 1)
#define OPTION_EXPORT_ALL (OPTION_OUT_DEF + 1)
#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1)
#define OPTION_EXCLUDE_ALL_SYMBOLS (OPTION_EXCLUDE_SYMBOLS + 1)
#define OPTION_KILL_ATS (OPTION_EXCLUDE_ALL_SYMBOLS + 1)
#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1)
#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1)
#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1)
#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1)
#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1)
#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1)
#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1)
#define OPTION_ENABLE_AUTO_IMAGE_BASE (OPTION_IMP_COMPAT + 1)
#define OPTION_DISABLE_AUTO_IMAGE_BASE (OPTION_ENABLE_AUTO_IMAGE_BASE + 1)
#define OPTION_DLL_SEARCH_PREFIX (OPTION_DISABLE_AUTO_IMAGE_BASE + 1)
#define OPTION_NO_DEFAULT_EXCLUDES (OPTION_DLL_SEARCH_PREFIX + 1)
#define OPTION_DLL_ENABLE_AUTO_IMPORT (OPTION_NO_DEFAULT_EXCLUDES + 1)
#define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
#define OPTION_ENABLE_EXTRA_PE_DEBUG (OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
#define OPTION_EXCLUDE_LIBS (OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC (OPTION_EXCLUDE_LIBS + 1)
#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
#define OPTION_LARGE_ADDRESS_AWARE (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1)
#define OPTION_DISABLE_LARGE_ADDRESS_AWARE (OPTION_LARGE_ADDRESS_AWARE + 1)
#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 (OPTION_DISABLE_LARGE_ADDRESS_AWARE + 1)
#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 + 1)
#define OPTION_EXCLUDE_MODULES_FOR_IMPLIB (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 + 1)
#define OPTION_USE_NUL_PREFIXED_IMPORT_TABLES (OPTION_EXCLUDE_MODULES_FOR_IMPLIB + 1)
#define OPTION_NO_LEADING_UNDERSCORE (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES + 1)
#define OPTION_LEADING_UNDERSCORE (OPTION_NO_LEADING_UNDERSCORE + 1)
#define OPTION_ENABLE_LONG_SECTION_NAMES (OPTION_LEADING_UNDERSCORE + 1)
#define OPTION_DISABLE_LONG_SECTION_NAMES (OPTION_ENABLE_LONG_SECTION_NAMES + 1)
/* DLLCharacteristics flags. */
#define OPTION_DYNAMIC_BASE (OPTION_DISABLE_LONG_SECTION_NAMES + 1)
#define OPTION_FORCE_INTEGRITY (OPTION_DYNAMIC_BASE + 1)
#define OPTION_NX_COMPAT (OPTION_FORCE_INTEGRITY + 1)
#define OPTION_NO_ISOLATION (OPTION_NX_COMPAT + 1)
#define OPTION_NO_SEH (OPTION_NO_ISOLATION + 1)
#define OPTION_NO_BIND (OPTION_NO_SEH + 1)
#define OPTION_WDM_DRIVER (OPTION_NO_BIND + 1)
#define OPTION_TERMINAL_SERVER_AWARE (OPTION_WDM_DRIVER + 1)
/* Determinism. */
#define OPTION_INSERT_TIMESTAMP (OPTION_TERMINAL_SERVER_AWARE + 1)
 
static void
gldi386pe_add_options
(int ns ATTRIBUTE_UNUSED,
char **shortopts ATTRIBUTE_UNUSED,
int nl,
struct option **longopts,
int nrl ATTRIBUTE_UNUSED,
struct option **really_longopts ATTRIBUTE_UNUSED)
{
static const struct option xtra_long[] =
{
/* PE options. */
{"base-file", required_argument, NULL, OPTION_BASE_FILE},
{"dll", no_argument, NULL, OPTION_DLL},
{"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT},
{"heap", required_argument, NULL, OPTION_HEAP},
{"image-base", required_argument, NULL, OPTION_IMAGE_BASE},
{"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION},
{"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION},
{"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION},
{"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION},
{"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION},
{"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION},
{"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT},
{"stack", required_argument, NULL, OPTION_STACK},
{"subsystem", required_argument, NULL, OPTION_SUBSYSTEM},
{"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE},
{"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
{"use-nul-prefixed-import-tables", no_argument, NULL,
OPTION_USE_NUL_PREFIXED_IMPORT_TABLES},
{"no-leading-underscore", no_argument, NULL, OPTION_NO_LEADING_UNDERSCORE},
{"leading-underscore", no_argument, NULL, OPTION_LEADING_UNDERSCORE},
{"insert-timestamp", no_argument, NULL, OPTION_INSERT_TIMESTAMP},
#ifdef DLL_SUPPORT
/* getopt allows abbreviations, so we do this to stop it
from treating -o as an abbreviation for this option. */
{"output-def", required_argument, NULL, OPTION_OUT_DEF},
{"output-def", required_argument, NULL, OPTION_OUT_DEF},
{"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL},
{"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS},
{"exclude-all-symbols", no_argument, NULL, OPTION_EXCLUDE_ALL_SYMBOLS},
{"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
{"exclude-modules-for-implib", required_argument, NULL, OPTION_EXCLUDE_MODULES_FOR_IMPLIB},
{"kill-at", no_argument, NULL, OPTION_KILL_ATS},
{"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES},
{"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP},
{"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP},
{"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME},
{"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS},
/* getopt() allows abbreviations, so we do this to stop it from
treating -c as an abbreviation for these --compat-implib. */
{"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
{"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT},
{"enable-auto-image-base", no_argument, NULL, OPTION_ENABLE_AUTO_IMAGE_BASE},
{"disable-auto-image-base", no_argument, NULL, OPTION_DISABLE_AUTO_IMAGE_BASE},
{"dll-search-prefix", required_argument, NULL, OPTION_DLL_SEARCH_PREFIX},
{"no-default-excludes", no_argument, NULL, OPTION_NO_DEFAULT_EXCLUDES},
{"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
{"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
{"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
{"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
{"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
{"enable-runtime-pseudo-reloc-v1", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1},
{"enable-runtime-pseudo-reloc-v2", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2},
#endif
{"large-address-aware", no_argument, NULL, OPTION_LARGE_ADDRESS_AWARE},
{"disable-large-address-aware", no_argument, NULL, OPTION_DISABLE_LARGE_ADDRESS_AWARE},
{"enable-long-section-names", no_argument, NULL, OPTION_ENABLE_LONG_SECTION_NAMES},
{"disable-long-section-names", no_argument, NULL, OPTION_DISABLE_LONG_SECTION_NAMES},
{"dynamicbase",no_argument, NULL, OPTION_DYNAMIC_BASE},
{"forceinteg", no_argument, NULL, OPTION_FORCE_INTEGRITY},
{"nxcompat", no_argument, NULL, OPTION_NX_COMPAT},
{"no-isolation", no_argument, NULL, OPTION_NO_ISOLATION},
{"no-seh", no_argument, NULL, OPTION_NO_SEH},
{"no-bind", no_argument, NULL, OPTION_NO_BIND},
{"wdmdriver", no_argument, NULL, OPTION_WDM_DRIVER},
{"tsaware", no_argument, NULL, OPTION_TERMINAL_SERVER_AWARE},
{NULL, no_argument, NULL, 0}
};
 
*longopts
= xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
}
 
/* PE/WIN32; added routines to get the subsystem type, heap and/or stack
parameters which may be input from the command line. */
 
typedef struct
{
void *ptr;
int size;
int value;
char *symbol;
int inited;
/* FALSE for an assembly level symbol and TRUE for a C visible symbol.
C visible symbols can be prefixed by underscore dependent to target's
settings. */
bfd_boolean is_c_symbol;
} definfo;
 
/* Get symbol name dependent to kind and C visible state of
underscore. */
#define GET_INIT_SYMBOL_NAME(IDX) (init[(IDX)].symbol + ((init[(IDX)].is_c_symbol == FALSE || (is_underscoring () != 0)) ? 0 : 1))
 
/* Decorates the C visible symbol by underscore, if target requires. */
#define U(CSTR) ((is_underscoring () == 0) ? CSTR : "_" CSTR)
 
/* Get size of constant string for a possible underscore prefixed
C visible symbol. */
#define U_SIZE(CSTR) (sizeof (CSTR) + (is_underscoring () == 0 ? 0 : 1))
 
#define D(field,symbol,def,usc) {&pe.field,sizeof(pe.field), def, symbol, 0, usc}
 
static definfo init[] =
{
/* imagebase must be first */
#define IMAGEBASEOFF 0
D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE, FALSE),
#define DLLOFF 1
{&dll, sizeof(dll), 0, "__dll__", 0, FALSE},
#define MSIMAGEBASEOFF 2
D(ImageBase, "___ImageBase", NT_EXE_IMAGE_BASE, TRUE),
D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT, FALSE),
D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT, FALSE),
D(MajorOperatingSystemVersion,"__major_os_version__", 4, FALSE),
D(MinorOperatingSystemVersion,"__minor_os_version__", 0, FALSE),
D(MajorImageVersion,"__major_image_version__", 1, FALSE),
D(MinorImageVersion,"__minor_image_version__", 0, FALSE),
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_wince_pe)
D(MajorSubsystemVersion,"__major_subsystem_version__", 3, FALSE),
#else
D(MajorSubsystemVersion,"__major_subsystem_version__", 4, FALSE),
#endif
D(MinorSubsystemVersion,"__minor_subsystem_version__", 0, FALSE),
D(Subsystem,"__subsystem__", PE_DEF_SUBSYSTEM, FALSE),
D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x200000, FALSE),
D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000, FALSE),
D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000, FALSE),
D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000, FALSE),
D(LoaderFlags,"__loader_flags__", 0x0, FALSE),
D(DllCharacteristics, "__dll_characteristics__", 0x0, FALSE),
{ NULL, 0, 0, NULL, 0 , FALSE}
};
 
 
static void
gld_i386pe_list_options (FILE *file)
{
fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n"));
fprintf (file, _(" --dll Set image base to the default for DLLs\n"));
fprintf (file, _(" --file-alignment <size> Set file alignment\n"));
fprintf (file, _(" --heap <size> Set initial size of the heap\n"));
fprintf (file, _(" --image-base <address> Set start address of the executable\n"));
fprintf (file, _(" --major-image-version <number> Set version number of the executable\n"));
fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n"));
fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n"));
fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n"));
fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n"));
fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n"));
fprintf (file, _(" --section-alignment <size> Set section alignment\n"));
fprintf (file, _(" --stack <size> Set size of the initial stack\n"));
fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n"));
fprintf (file, _(" --support-old-code Support interworking with old code\n"));
fprintf (file, _(" --[no-]leading-underscore Set explicit symbol underscore prefix mode\n"));
fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n"));
fprintf (file, _(" --insert-timestamp Use a real timestamp rather than zero.\n"));
fprintf (file, _(" This makes binaries non-deterministic\n"));
#ifdef DLL_SUPPORT
fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n"));
fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n"));
fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n"));
fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n"));
fprintf (file, _(" --exclude-all-symbols Exclude all symbols from automatic export\n"));
fprintf (file, _(" --exclude-libs lib,lib,... Exclude libraries from automatic export\n"));
fprintf (file, _(" --exclude-modules-for-implib mod,mod,...\n"));
fprintf (file, _(" Exclude objects, archive members from auto\n"));
fprintf (file, _(" export, place into import library instead.\n"));
fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n"));
fprintf (file, _(" --kill-at Remove @nn from exported symbols\n"));
fprintf (file, _(" --out-implib <file> Generate import library\n"));
fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n"));
fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n"));
fprintf (file, _(" --compat-implib Create backward compatible import libs;\n create __imp_<SYMBOL> as well.\n"));
fprintf (file, _(" --enable-auto-image-base Automatically choose image base for DLLs\n unless user specifies one\n"));
fprintf (file, _(" --disable-auto-image-base Do not auto-choose image base. (default)\n"));
fprintf (file, _(" --dll-search-prefix=<string> When linking dynamically to a dll without\n an importlib, use <string><basename>.dll\n in preference to lib<basename>.dll \n"));
fprintf (file, _(" --enable-auto-import Do sophisticated linking of _sym to\n __imp_sym for DATA references\n"));
fprintf (file, _(" --disable-auto-import Do not auto-import DATA items from DLLs\n"));
fprintf (file, _(" --enable-runtime-pseudo-reloc Work around auto-import limitations by\n adding pseudo-relocations resolved at\n runtime.\n"));
fprintf (file, _(" --disable-runtime-pseudo-reloc Do not add runtime pseudo-relocations for\n auto-imported DATA.\n"));
fprintf (file, _(" --enable-extra-pe-debug Enable verbose debug output when building\n or linking to DLLs (esp. auto-import)\n"));
#endif
fprintf (file, _(" --large-address-aware Executable supports virtual addresses\n greater than 2 gigabytes\n"));
fprintf (file, _(" --disable-large-address-aware Executable does not support virtual\n addresses greater than 2 gigabytes\n"));
fprintf (file, _(" --enable-long-section-names Use long COFF section names even in\n executable image files\n"));
fprintf (file, _(" --disable-long-section-names Never use long COFF section names, even\n in object files\n"));
fprintf (file, _(" --dynamicbase Image base address may be relocated using\n address space layout randomization (ASLR)\n"));
fprintf (file, _(" --forceinteg Code integrity checks are enforced\n"));
fprintf (file, _(" --nxcompat Image is compatible with data execution prevention\n"));
fprintf (file, _(" --no-isolation Image understands isolation but do not isolate the image\n"));
fprintf (file, _(" --no-seh Image does not use SEH. No SE handler may\n be called in this image\n"));
fprintf (file, _(" --no-bind Do not bind this image\n"));
fprintf (file, _(" --wdmdriver Driver uses the WDM model\n"));
fprintf (file, _(" --tsaware Image is Terminal Server aware\n"));
}
 
 
static void
set_pe_name (char *name, long val)
{
int i;
is_underscoring ();
 
/* Find the name and set it. */
for (i = 0; init[i].ptr; i++)
{
if (strcmp (name, GET_INIT_SYMBOL_NAME (i)) == 0)
{
init[i].value = val;
init[i].inited = 1;
if (strcmp (name,"__image_base__") == 0)
set_pe_name (U ("__ImageBase"), val);
return;
}
}
abort ();
}
 
static void
set_entry_point (void)
{
const char *entry;
const char *initial_symbol_char;
int i;
 
static const struct
{
const int value;
const char *entry;
}
v[] =
{
{ 1, "NtProcessStartup" },
{ 2, "WinMainCRTStartup" },
{ 3, "mainCRTStartup" },
{ 7, "__PosixProcessStartup"},
{ 9, "WinMainCRTStartup" },
{14, "mainCRTStartup" },
{ 0, NULL }
};
 
/* Entry point name for arbitrary subsystem numbers. */
static const char default_entry[] = "mainCRTStartup";
 
if (link_info.shared || dll)
{
#if defined (TARGET_IS_i386pe)
entry = "DllMainCRTStartup@12";
#else
entry = "DllMainCRTStartup";
#endif
}
else
{
 
for (i = 0; v[i].entry; i++)
if (v[i].value == pe_subsystem)
break;
 
/* If no match, use the default. */
if (v[i].entry != NULL)
entry = v[i].entry;
else
entry = default_entry;
}
 
initial_symbol_char = (is_underscoring () != 0 ? "_" : "");
 
if (*initial_symbol_char != '\0')
{
char *alc_entry;
 
/* lang_default_entry expects its argument to be permanently
allocated, so we don't free this string. */
alc_entry = xmalloc (strlen (initial_symbol_char)
+ strlen (entry)
+ 1);
strcpy (alc_entry, initial_symbol_char);
strcat (alc_entry, entry);
entry = alc_entry;
}
 
lang_default_entry (entry);
}
 
static void
set_pe_subsystem (void)
{
const char *sver;
char *end;
int len;
int i;
unsigned long temp_subsystem;
static const struct
{
const char *name;
const int value;
}
v[] =
{
{ "native", 1},
{ "windows", 2},
{ "console", 3},
{ "posix", 7},
{ "wince", 9},
{ "xbox", 14},
{ NULL, 0 }
};
 
/* Check for the presence of a version number. */
sver = strchr (optarg, ':');
if (sver == NULL)
len = strlen (optarg);
else
{
len = sver - optarg;
set_pe_name ("__major_subsystem_version__",
strtoul (sver + 1, &end, 0));
if (*end == '.')
set_pe_name ("__minor_subsystem_version__",
strtoul (end + 1, &end, 0));
if (*end != '\0')
einfo (_("%P: warning: bad version number in -subsystem option\n"));
}
 
/* Check for numeric subsystem. */
temp_subsystem = strtoul (optarg, & end, 0);
if ((*end == ':' || *end == '\0') && (temp_subsystem < 65536))
{
/* Search list for a numeric match to use its entry point. */
for (i = 0; v[i].name; i++)
if (v[i].value == (int) temp_subsystem)
break;
 
/* Use this subsystem. */
pe_subsystem = (int) temp_subsystem;
}
else
{
/* Search for subsystem by name. */
for (i = 0; v[i].name; i++)
if (strncmp (optarg, v[i].name, len) == 0
&& v[i].name[len] == '\0')
break;
 
if (v[i].name == NULL)
{
einfo (_("%P%F: invalid subsystem type %s\n"), optarg);
return;
}
 
pe_subsystem = v[i].value;
}
 
set_pe_name ("__subsystem__", pe_subsystem);
 
return;
}
 
 
static void
set_pe_value (char *name)
{
char *end;
 
set_pe_name (name, strtoul (optarg, &end, 0));
 
if (end == optarg)
einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg);
 
optarg = end;
}
 
 
static void
set_pe_stack_heap (char *resname, char *comname)
{
set_pe_value (resname);
 
if (*optarg == ',')
{
optarg++;
set_pe_value (comname);
}
else if (*optarg)
einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg);
}
 
 
static bfd_boolean
gldi386pe_handle_option (int optc)
{
switch (optc)
{
default:
return FALSE;
 
case OPTION_BASE_FILE:
link_info.base_file = fopen (optarg, FOPEN_WB);
if (link_info.base_file == NULL)
einfo (_("%F%P: cannot open base file %s\n"), optarg);
break;
 
/* PE options. */
case OPTION_HEAP:
set_pe_stack_heap ("__size_of_heap_reserve__", "__size_of_heap_commit__");
break;
case OPTION_STACK:
set_pe_stack_heap ("__size_of_stack_reserve__", "__size_of_stack_commit__");
break;
case OPTION_SUBSYSTEM:
set_pe_subsystem ();
break;
case OPTION_MAJOR_OS_VERSION:
set_pe_value ("__major_os_version__");
break;
case OPTION_MINOR_OS_VERSION:
set_pe_value ("__minor_os_version__");
break;
case OPTION_MAJOR_SUBSYSTEM_VERSION:
set_pe_value ("__major_subsystem_version__");
break;
case OPTION_MINOR_SUBSYSTEM_VERSION:
set_pe_value ("__minor_subsystem_version__");
break;
case OPTION_MAJOR_IMAGE_VERSION:
set_pe_value ("__major_image_version__");
break;
case OPTION_MINOR_IMAGE_VERSION:
set_pe_value ("__minor_image_version__");
break;
case OPTION_FILE_ALIGNMENT:
set_pe_value ("__file_alignment__");
break;
case OPTION_SECTION_ALIGNMENT:
set_pe_value ("__section_alignment__");
break;
case OPTION_DLL:
set_pe_name ("__dll__", 1);
break;
case OPTION_IMAGE_BASE:
set_pe_value ("__image_base__");
break;
case OPTION_SUPPORT_OLD_CODE:
support_old_code = 1;
break;
case OPTION_THUMB_ENTRY:
thumb_entry_symbol = optarg;
break;
case OPTION_USE_NUL_PREFIXED_IMPORT_TABLES:
pe_use_nul_prefixed_import_tables = TRUE;
break;
case OPTION_NO_LEADING_UNDERSCORE:
pe_leading_underscore = 0;
break;
case OPTION_LEADING_UNDERSCORE:
pe_leading_underscore = 1;
break;
case OPTION_INSERT_TIMESTAMP:
insert_timestamp = TRUE;
break;
#ifdef DLL_SUPPORT
case OPTION_OUT_DEF:
pe_out_def_filename = xstrdup (optarg);
break;
case OPTION_EXPORT_ALL:
pe_dll_export_everything = 1;
break;
case OPTION_EXCLUDE_SYMBOLS:
pe_dll_add_excludes (optarg, EXCLUDESYMS);
break;
case OPTION_EXCLUDE_ALL_SYMBOLS:
pe_dll_exclude_all_symbols = 1;
break;
case OPTION_EXCLUDE_LIBS:
pe_dll_add_excludes (optarg, EXCLUDELIBS);
break;
case OPTION_EXCLUDE_MODULES_FOR_IMPLIB:
pe_dll_add_excludes (optarg, EXCLUDEFORIMPLIB);
break;
case OPTION_KILL_ATS:
pe_dll_kill_ats = 1;
break;
case OPTION_STDCALL_ALIASES:
pe_dll_stdcall_aliases = 1;
break;
case OPTION_ENABLE_STDCALL_FIXUP:
pe_enable_stdcall_fixup = 1;
break;
case OPTION_DISABLE_STDCALL_FIXUP:
pe_enable_stdcall_fixup = 0;
break;
case OPTION_IMPLIB_FILENAME:
pe_implib_filename = xstrdup (optarg);
break;
case OPTION_WARN_DUPLICATE_EXPORTS:
pe_dll_warn_dup_exports = 1;
break;
case OPTION_IMP_COMPAT:
pe_dll_compat_implib = 1;
break;
case OPTION_ENABLE_AUTO_IMAGE_BASE:
pe_enable_auto_image_base = 1;
break;
case OPTION_DISABLE_AUTO_IMAGE_BASE:
pe_enable_auto_image_base = 0;
break;
case OPTION_DLL_SEARCH_PREFIX:
pe_dll_search_prefix = xstrdup (optarg);
break;
case OPTION_NO_DEFAULT_EXCLUDES:
pe_dll_do_default_excludes = 0;
break;
case OPTION_DLL_ENABLE_AUTO_IMPORT:
link_info.pei386_auto_import = 1;
break;
case OPTION_DLL_DISABLE_AUTO_IMPORT:
link_info.pei386_auto_import = 0;
break;
case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
link_info.pei386_runtime_pseudo_reloc =
DEFAULT_PSEUDO_RELOC_VERSION;
break;
case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1:
link_info.pei386_runtime_pseudo_reloc = 1;
break;
case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2:
link_info.pei386_runtime_pseudo_reloc = 2;
break;
case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
link_info.pei386_runtime_pseudo_reloc = 0;
break;
case OPTION_ENABLE_EXTRA_PE_DEBUG:
pe_dll_extra_pe_debug = 1;
break;
#endif
case OPTION_LARGE_ADDRESS_AWARE:
real_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
break;
case OPTION_DISABLE_LARGE_ADDRESS_AWARE:
real_flags &= ~ IMAGE_FILE_LARGE_ADDRESS_AWARE;
break;
case OPTION_ENABLE_LONG_SECTION_NAMES:
pe_use_coff_long_section_names = 1;
break;
case OPTION_DISABLE_LONG_SECTION_NAMES:
pe_use_coff_long_section_names = 0;
break;
/* Get DLLCharacteristics bits */
case OPTION_DYNAMIC_BASE:
pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
break;
case OPTION_FORCE_INTEGRITY:
pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
break;
case OPTION_NX_COMPAT:
pe_dll_characteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
break;
case OPTION_NO_ISOLATION:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_ISOLATION;
break;
case OPTION_NO_SEH:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH;
break;
case OPTION_NO_BIND:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_NO_BIND;
break;
case OPTION_WDM_DRIVER:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_WDM_DRIVER;
break;
case OPTION_TERMINAL_SERVER_AWARE:
pe_dll_characteristics |= IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE;
break;
}
 
/* Set DLLCharacteristics bits */
set_pe_name ("__dll_characteristics__", pe_dll_characteristics);
 
return TRUE;
}
 
#ifdef DLL_SUPPORT
static unsigned long
strhash (const char *str)
{
const unsigned char *s;
unsigned long hash;
unsigned int c;
unsigned int len;
 
hash = 0;
len = 0;
s = (const unsigned char *) str;
while ((c = *s++) != '\0')
{
hash += c + (c << 17);
hash ^= hash >> 2;
++len;
}
hash += len + (len << 17);
hash ^= hash >> 2;
 
return hash;
}
 
/* Use the output file to create a image base for relocatable DLLs. */
 
static unsigned long
compute_dll_image_base (const char *ofile)
{
unsigned long hash = strhash (ofile);
return 0x61300000 + ((hash << 16) & 0x0FFC0000);
}
#endif
 
/* Assign values to the special symbols before the linker script is
read. */
 
static void
gld_i386pe_set_symbols (void)
{
/* Run through and invent symbols for all the
names and insert the defaults. */
int j;
 
is_underscoring ();
 
if (!init[IMAGEBASEOFF].inited)
{
if (link_info.relocatable)
init[IMAGEBASEOFF].value = 0;
else if (init[DLLOFF].value || (link_info.shared && !link_info.pie))
{
#ifdef DLL_SUPPORT
init[IMAGEBASEOFF].value = (pe_enable_auto_image_base
? compute_dll_image_base (output_filename)
: NT_DLL_IMAGE_BASE);
#else
init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE;
#endif
}
else
init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE;
init[MSIMAGEBASEOFF].value = init[IMAGEBASEOFF].value;
}
 
/* Don't do any symbol assignments if this is a relocatable link. */
if (link_info.relocatable)
return;
 
/* Glue the assignments into the abs section. */
push_stat_ptr (&abs_output_section->children);
 
for (j = 0; init[j].ptr; j++)
{
long val = init[j].value;
lang_assignment_statement_type *rv;
 
rv = lang_add_assignment (exp_assign (GET_INIT_SYMBOL_NAME (j),
exp_intop (val), FALSE));
if (init[j].size == sizeof (short))
*(short *) init[j].ptr = val;
else if (init[j].size == sizeof (int))
*(int *) init[j].ptr = val;
else if (init[j].size == sizeof (long))
*(long *) init[j].ptr = val;
/* This might be a long long or other special type. */
else if (init[j].size == sizeof (bfd_vma))
*(bfd_vma *) init[j].ptr = val;
else abort ();
if (j == IMAGEBASEOFF)
image_base_statement = rv;
}
/* Restore the pointer. */
pop_stat_ptr ();
 
if (pe.FileAlignment > pe.SectionAlignment)
{
einfo (_("%P: warning, file alignment > section alignment.\n"));
}
}
 
/* This is called after the linker script and the command line options
have been read. */
 
static void
gld_i386pe_after_parse (void)
{
/* PR ld/6744: Warn the user if they have used an ELF-only
option hoping it will work on PE. */
if (link_info.export_dynamic)
einfo (_("%P: warning: --export-dynamic is not supported for PE "
"targets, did you mean --export-all-symbols?\n"));
 
set_entry_point ();
 
after_parse_default ();
}
 
/* pe-dll.c directly accesses pe_data_import_dll,
so it must be defined outside of #ifdef DLL_SUPPORT.
Note - this variable is deliberately not initialised.
This allows it to be treated as a common varaible, and only
exist in one incarnation in a multiple target enabled linker. */
char * pe_data_import_dll;
 
#ifdef DLL_SUPPORT
static struct bfd_link_hash_entry *pe_undef_found_sym;
 
static bfd_boolean
pe_undef_cdecl_match (struct bfd_link_hash_entry *h, void *inf)
{
int sl;
char *string = inf;
const char *hs = h->root.string;
 
sl = strlen (string);
if (h->type == bfd_link_hash_defined
&& ((*hs == '@' && *string == '_'
&& strncmp (hs + 1, string + 1, sl - 1) == 0)
|| strncmp (hs, string, sl) == 0)
&& h->root.string[sl] == '@')
{
pe_undef_found_sym = h;
return FALSE;
}
return TRUE;
}
 
static void
pe_fixup_stdcalls (void)
{
static int gave_warning_message = 0;
struct bfd_link_hash_entry *undef, *sym;
 
if (pe_dll_extra_pe_debug)
printf ("%s\n", __FUNCTION__);
 
for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
if (undef->type == bfd_link_hash_undefined)
{
char* at = strchr (undef->root.string, '@');
int lead_at = (*undef->root.string == '@');
if (lead_at)
at = strchr (undef->root.string + 1, '@');
 
if (at || lead_at)
{
/* The symbol is a stdcall symbol, so let's look for a
cdecl symbol with the same name and resolve to that. */
char *cname = xstrdup (undef->root.string);
 
if (lead_at)
*cname = '_';
at = strchr (cname, '@');
if (at)
*at = 0;
sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1);
 
if (sym && sym->type == bfd_link_hash_defined)
{
undef->type = bfd_link_hash_defined;
undef->u.def.value = sym->u.def.value;
undef->u.def.section = sym->u.def.section;
 
if (pe_enable_stdcall_fixup == -1)
{
einfo (_("Warning: resolving %s by linking to %s\n"),
undef->root.string, cname);
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
}
}
else
{
/* The symbol is a cdecl symbol, so we look for stdcall
symbols - which means scanning the whole symbol table. */
pe_undef_found_sym = 0;
bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match,
(char *) undef->root.string);
sym = pe_undef_found_sym;
if (sym)
{
undef->type = bfd_link_hash_defined;
undef->u.def.value = sym->u.def.value;
undef->u.def.section = sym->u.def.section;
 
if (pe_enable_stdcall_fixup == -1)
{
einfo (_("Warning: resolving %s by linking to %s\n"),
undef->root.string, sym->root.string);
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
}
}
}
}
 
static int
make_import_fixup (arelent *rel, asection *s)
{
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
char addend[4];
 
if (pe_dll_extra_pe_debug)
printf ("arelent: %s@%#lx: add=%li\n", sym->name,
(unsigned long) rel->address, (long) rel->addend);
 
if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend)))
einfo (_("%C: Cannot get section contents - auto-import exception\n"),
s->owner, s, rel->address);
 
pe_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend));
 
return 1;
}
 
static void
pe_find_data_imports (void)
{
struct bfd_link_hash_entry *undef, *sym;
 
if (link_info.pei386_auto_import == 0)
return;
 
for (undef = link_info.hash->undefs; undef; undef=undef->u.undef.next)
{
if (undef->type == bfd_link_hash_undefined)
{
/* C++ symbols are *long*. */
char buf[4096];
 
if (pe_dll_extra_pe_debug)
printf ("%s:%s\n", __FUNCTION__, undef->root.string);
 
sprintf (buf, "__imp_%s", undef->root.string);
 
sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
 
if (sym && sym->type == bfd_link_hash_defined)
{
bfd *b = sym->u.def.section->owner;
asymbol **symbols;
int nsyms, i;
 
if (link_info.pei386_auto_import == -1)
{
static bfd_boolean warned = FALSE;
 
info_msg (_("Info: resolving %s by linking to %s (auto-import)\n"),
undef->root.string, buf);
 
/* PR linker/4844. */
if (! warned)
{
warned = TRUE;
einfo (_("%P: warning: auto-importing has been activated without --enable-auto-import specified on the command line.\nThis should work unless it involves constant data structures referencing symbols from auto-imported DLLs.\n"));
}
}
 
if (!bfd_generic_link_read_symbols (b))
{
einfo (_("%B%F: could not read symbols: %E\n"), b);
return;
}
 
symbols = bfd_get_outsymbols (b);
nsyms = bfd_get_symcount (b);
 
for (i = 0; i < nsyms; i++)
{
if (! CONST_STRNEQ (symbols[i]->name,
U ("_head_")))
continue;
 
if (pe_dll_extra_pe_debug)
printf ("->%s\n", symbols[i]->name);
 
pe_data_import_dll = (char *) (symbols[i]->name
+ U_SIZE ("_head_") - 1);
break;
}
 
pe_walk_relocs_of_symbol (&link_info, undef->root.string,
make_import_fixup);
 
/* Let's differentiate it somehow from defined. */
undef->type = bfd_link_hash_defweak;
/* We replace original name with __imp_ prefixed, this
1) may trash memory 2) leads to duplicate symbol generation.
Still, IMHO it's better than having name poluted. */
undef->root.string = sym->root.string;
undef->u.def.value = sym->u.def.value;
undef->u.def.section = sym->u.def.section;
}
}
}
}
 
static bfd_boolean
pr_sym (struct bfd_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
printf ("+%s\n", h->string);
 
return TRUE;
}
#endif /* DLL_SUPPORT */
 
static void
debug_section_p (bfd *abfd ATTRIBUTE_UNUSED, asection *sect, void *obj)
{
int *found = (int *) obj;
if (strncmp (".debug_", sect->name, sizeof (".debug_") - 1) == 0)
*found = 1;
}
 
static void
gld_i386pe_after_open (void)
{
after_open_default ();
 
#ifdef DLL_SUPPORT
if (pe_dll_extra_pe_debug)
{
bfd *a;
struct bfd_link_hash_entry *sym;
 
printf ("%s()\n", __FUNCTION__);
 
for (sym = link_info.hash->undefs; sym; sym=sym->u.undef.next)
printf ("-%s\n", sym->root.string);
bfd_hash_traverse (&link_info.hash->table, pr_sym, NULL);
 
for (a = link_info.input_bfds; a; a = a->link_next)
printf ("*%s\n",a->filename);
}
#endif
 
/* Pass the wacky PE command line options into the output bfd.
FIXME: This should be done via a function, rather than by
including an internal BFD header. */
 
if (coff_data (link_info.output_bfd) == NULL
|| coff_data (link_info.output_bfd)->pe == 0)
einfo (_("%F%P: cannot perform PE operations on non PE output file '%B'.\n"),
link_info.output_bfd);
 
pe_data (link_info.output_bfd)->pe_opthdr = pe;
pe_data (link_info.output_bfd)->dll = init[DLLOFF].value;
pe_data (link_info.output_bfd)->real_flags |= real_flags;
pe_data (link_info.output_bfd)->insert_timestamp = insert_timestamp;
 
/* At this point we must decide whether to use long section names
in the output or not. If the user hasn't explicitly specified
on the command line, we leave it to the default for the format
(object files yes, image files no), except if there is debug
information present; GDB relies on the long section names to
find it, so enable it in that case. */
if (pe_use_coff_long_section_names < 0 && link_info.strip == strip_none)
{
/* Iterate over all sections of all input BFDs, checking
for any that begin 'debug_' and are long names. */
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
int found_debug = 0;
bfd_map_over_sections (is->the_bfd, debug_section_p, &found_debug);
if (found_debug)
{
pe_use_coff_long_section_names = 1;
break;
}
}
}
 
pe_output_file_set_long_section_names (link_info.output_bfd);
 
#ifdef DLL_SUPPORT
if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
pe_fixup_stdcalls ();
 
pe_process_import_defs (link_info.output_bfd, &link_info);
 
pe_find_data_imports ();
 
/* As possibly new symbols are added by imports, we rerun
stdcall/fastcall fixup here. */
if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
pe_fixup_stdcalls ();
 
#if defined (TARGET_IS_i386pe) || defined (TARGET_IS_armpe) || defined (TARGET_IS_arm_epoc_pe) || defined (TARGET_IS_arm_wince_pe)
if (!link_info.relocatable)
pe_dll_build_sections (link_info.output_bfd, &link_info);
#else
if (link_info.shared)
pe_dll_build_sections (link_info.output_bfd, &link_info);
else
pe_exe_build_sections (link_info.output_bfd, &link_info);
#endif
#endif /* DLL_SUPPORT */
 
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
{
/* The arm backend needs special fields in the output hash structure.
These will only be created if the output format is an arm format,
hence we do not support linking and changing output formats at the
same time. Use a link followed by objcopy to change output formats. */
einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
return;
}
{
/* Find a BFD that can hold the interworking stubs. */
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (bfd_arm_get_bfd_for_interworking (is->the_bfd, & link_info))
break;
}
}
#endif
 
{
/* This next chunk of code tries to detect the case where you have
two import libraries for the same DLL (specifically,
symbolically linking libm.a and libc.a in cygwin to
libcygwin.a). In those cases, it's possible for function
thunks from the second implib to be used but without the
head/tail objects, causing an improper import table. We detect
those cases and rename the "other" import libraries to match
the one the head/tail come from, so that the linker will sort
things nicely and produce a valid import table. */
 
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (is->the_bfd->my_archive)
{
int idata2 = 0, reloc_count=0, is_imp = 0;
asection *sec;
 
/* See if this is an import library thunk. */
for (sec = is->the_bfd->sections; sec; sec = sec->next)
{
if (strcmp (sec->name, ".idata$2") == 0)
idata2 = 1;
if (CONST_STRNEQ (sec->name, ".idata$"))
is_imp = 1;
reloc_count += sec->reloc_count;
}
 
if (is_imp && !idata2 && reloc_count)
{
/* It is, look for the reference to head and see if it's
from our own library. */
for (sec = is->the_bfd->sections; sec; sec = sec->next)
{
int i;
long relsize;
asymbol **symbols;
arelent **relocs;
int nrelocs;
 
relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
if (relsize < 1)
break;
 
if (!bfd_generic_link_read_symbols (is->the_bfd))
{
einfo (_("%B%F: could not read symbols: %E\n"),
is->the_bfd);
return;
}
symbols = bfd_get_outsymbols (is->the_bfd);
 
relocs = xmalloc ((size_t) relsize);
nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
relocs, symbols);
if (nrelocs < 0)
{
free (relocs);
einfo ("%X%P: unable to process relocs: %E\n");
return;
}
 
for (i = 0; i < nrelocs; i++)
{
struct bfd_symbol *s;
struct bfd_link_hash_entry * blhe;
char *other_bfd_filename;
char *n;
 
s = (relocs[i]->sym_ptr_ptr)[0];
 
if (s->flags & BSF_LOCAL)
continue;
 
/* Thunk section with reloc to another bfd. */
blhe = bfd_link_hash_lookup (link_info.hash,
s->name,
FALSE, FALSE, TRUE);
 
if (blhe == NULL
|| blhe->type != bfd_link_hash_defined)
continue;
 
other_bfd_filename
= blhe->u.def.section->owner->my_archive
? bfd_get_filename (blhe->u.def.section->owner->my_archive)
: bfd_get_filename (blhe->u.def.section->owner);
 
if (filename_cmp (bfd_get_filename
(is->the_bfd->my_archive),
other_bfd_filename) == 0)
continue;
 
/* Rename this implib to match the other one. */
n = xmalloc (strlen (other_bfd_filename) + 1);
strcpy (n, other_bfd_filename);
is->the_bfd->my_archive->filename = n;
}
 
free (relocs);
/* Note - we do not free the symbols,
they are now cached in the BFD. */
}
}
}
}
}
 
{
int is_ms_arch = 0;
bfd *cur_arch = 0;
lang_input_statement_type *is2;
lang_input_statement_type *is3;
 
/* Careful - this is a shell script. Watch those dollar signs! */
/* Microsoft import libraries have every member named the same,
and not in the right order for us to link them correctly. We
must detect these and rename the members so that they'll link
correctly. There are three types of objects: the head, the
thunks, and the sentinel(s). The head is easy; it's the one
with idata2. We assume that the sentinels won't have relocs,
and the thunks will. It's easier than checking the symbol
table for external references. */
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (is->the_bfd->my_archive)
{
char *pnt;
bfd *arch = is->the_bfd->my_archive;
 
if (cur_arch != arch)
{
cur_arch = arch;
is_ms_arch = 1;
 
for (is3 = is;
is3 && is3->the_bfd->my_archive == arch;
is3 = (lang_input_statement_type *) is3->next)
{
/* A MS dynamic import library can also contain static
members, so look for the first element with a .dll
extension, and use that for the remainder of the
comparisons. */
pnt = strrchr (is3->the_bfd->filename, '.');
if (pnt != NULL && filename_cmp (pnt, ".dll") == 0)
break;
}
 
if (is3 == NULL)
is_ms_arch = 0;
else
{
/* OK, found one. Now look to see if the remaining
(dynamic import) members use the same name. */
for (is2 = is;
is2 && is2->the_bfd->my_archive == arch;
is2 = (lang_input_statement_type *) is2->next)
{
/* Skip static members, ie anything with a .obj
extension. */
pnt = strrchr (is2->the_bfd->filename, '.');
if (pnt != NULL && filename_cmp (pnt, ".obj") == 0)
continue;
 
if (filename_cmp (is3->the_bfd->filename,
is2->the_bfd->filename))
{
is_ms_arch = 0;
break;
}
}
}
}
 
/* This fragment might have come from an .obj file in a Microsoft
import, and not an actual import record. If this is the case,
then leave the filename alone. */
pnt = strrchr (is->the_bfd->filename, '.');
 
if (is_ms_arch && (filename_cmp (pnt, ".dll") == 0))
{
int idata2 = 0, reloc_count=0;
asection *sec;
char *new_name, seq;
 
for (sec = is->the_bfd->sections; sec; sec = sec->next)
{
if (strcmp (sec->name, ".idata$2") == 0)
idata2 = 1;
reloc_count += sec->reloc_count;
}
 
if (idata2) /* .idata2 is the TOC */
seq = 'a';
else if (reloc_count > 0) /* thunks */
seq = 'b';
else /* sentinel */
seq = 'c';
 
new_name = xmalloc (strlen (is->the_bfd->filename) + 3);
sprintf (new_name, "%s.%c", is->the_bfd->filename, seq);
is->the_bfd->filename = new_name;
 
new_name = xmalloc (strlen (is->filename) + 3);
sprintf (new_name, "%s.%c", is->filename, seq);
is->filename = new_name;
}
}
}
}
 
{
/* The following chunk of code tries to identify jump stubs in
import libraries which are dead code and eliminates them
from the final link. For each exported symbol <sym>, there
is a object file in the import library with a .text section
and several .idata$* sections. The .text section contains the
symbol definition for <sym> which is a jump stub of the form
jmp *__imp_<sym>. The .idata$5 contains the symbol definition
for __imp_<sym> which is the address of the slot for <sym> in
the import address table. When a symbol is imported explicitly
using __declspec(dllimport) declaration, the compiler generates
a reference to __imp_<sym> which directly resolves to the
symbol in .idata$5, in which case the jump stub code is not
needed. The following code tries to identify jump stub sections
in import libraries which are not referred to by anyone and
marks them for exclusion from the final link. */
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (is->the_bfd->my_archive)
{
int is_imp = 0;
asection *sec, *stub_sec = NULL;
 
/* See if this is an import library thunk. */
for (sec = is->the_bfd->sections; sec; sec = sec->next)
{
if (strncmp (sec->name, ".idata$", 7) == 0)
is_imp = 1;
/* The section containing the jmp stub has code
and has a reloc. */
if ((sec->flags & SEC_CODE) && sec->reloc_count)
stub_sec = sec;
}
 
if (is_imp && stub_sec)
{
asymbol **symbols;
long nsyms, src_count;
struct bfd_link_hash_entry * blhe;
 
if (!bfd_generic_link_read_symbols (is->the_bfd))
{
einfo (_("%B%F: could not read symbols: %E\n"),
is->the_bfd);
return;
}
symbols = bfd_get_outsymbols (is->the_bfd);
nsyms = bfd_get_symcount (is->the_bfd);
 
for (src_count = 0; src_count < nsyms; src_count++)
{
if (symbols[src_count]->section->id == stub_sec->id)
{
/* This symbol belongs to the section containing
the stub. */
blhe = bfd_link_hash_lookup (link_info.hash,
symbols[src_count]->name,
FALSE, FALSE, TRUE);
/* If the symbol in the stub section has no other
undefined references, exclude the stub section
from the final link. */
if (blhe != NULL
&& blhe->type == bfd_link_hash_defined
&& blhe->u.undef.next == NULL
&& blhe != link_info.hash->undefs_tail)
stub_sec->flags |= SEC_EXCLUDE;
}
}
}
}
}
}
}
static void
gld_i386pe_before_allocation (void)
{
#ifdef TARGET_IS_ppcpe
/* Here we rummage through the found bfds to collect toc information. */
{
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (!ppc_process_before_allocation (is->the_bfd, &link_info))
{
/* xgettext:c-format */
einfo (_("Errors encountered processing file %s\n"), is->filename);
}
}
}
 
/* We have seen it all. Allocate it, and carry on. */
ppc_allocate_toc_section (&link_info);
#endif /* TARGET_IS_ppcpe */
 
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
/* FIXME: we should be able to set the size of the interworking stub
section.
 
Here we rummage through the found bfds to collect glue
information. FIXME: should this be based on a command line
option? krk@cygnus.com. */
{
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
if (! bfd_arm_process_before_allocation
(is->the_bfd, & link_info, support_old_code))
{
/* xgettext:c-format */
einfo (_("Errors encountered processing file %s for interworking\n"),
is->filename);
}
}
}
 
/* We have seen it all. Allocate it, and carry on. */
bfd_arm_allocate_interworking_sections (& link_info);
#endif /* TARGET_IS_armpe || TARGET_IS_arm_epoc_pe || TARGET_IS_arm_wince_pe */
 
before_allocation_default ();
}
#ifdef DLL_SUPPORT
/* This is called when an input file isn't recognized as a BFD. We
check here for .DEF files and pull them in automatically. */
 
static int
saw_option (char *option)
{
int i;
 
for (i = 0; init[i].ptr; i++)
if (strcmp (GET_INIT_SYMBOL_NAME (i), option) == 0)
return init[i].inited;
return 0;
}
#endif /* DLL_SUPPORT */
 
static bfd_boolean
gld_i386pe_unrecognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
{
#ifdef DLL_SUPPORT
const char *ext = entry->filename + strlen (entry->filename) - 4;
 
if (filename_cmp (ext, ".def") == 0 || filename_cmp (ext, ".DEF") == 0)
{
pe_def_file = def_file_parse (entry->filename, pe_def_file);
 
if (pe_def_file)
{
int i, buflen=0, len;
char *buf;
 
for (i = 0; i < pe_def_file->num_exports; i++)
{
len = strlen (pe_def_file->exports[i].internal_name);
if (buflen < len + 2)
buflen = len + 2;
}
 
buf = xmalloc (buflen);
 
for (i = 0; i < pe_def_file->num_exports; i++)
{
struct bfd_link_hash_entry *h;
 
sprintf (buf, "%s%s", U (""),
pe_def_file->exports[i].internal_name);
 
h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
bfd_link_add_undef (link_info.hash, h);
}
}
free (buf);
 
/* def_file_print (stdout, pe_def_file); */
if (pe_def_file->is_dll == 1)
link_info.shared = 1;
 
if (pe_def_file->base_address != (bfd_vma)(-1))
{
pe.ImageBase
= pe_data (link_info.output_bfd)->pe_opthdr.ImageBase
= init[IMAGEBASEOFF].value
= pe_def_file->base_address;
init[IMAGEBASEOFF].inited = 1;
if (image_base_statement)
image_base_statement->exp
= exp_assign ("__image_base__", exp_intop (pe.ImageBase),
FALSE);
}
 
if (pe_def_file->stack_reserve != -1
&& ! saw_option ("__size_of_stack_reserve__"))
{
pe.SizeOfStackReserve = pe_def_file->stack_reserve;
if (pe_def_file->stack_commit != -1)
pe.SizeOfStackCommit = pe_def_file->stack_commit;
}
if (pe_def_file->heap_reserve != -1
&& ! saw_option ("__size_of_heap_reserve__"))
{
pe.SizeOfHeapReserve = pe_def_file->heap_reserve;
if (pe_def_file->heap_commit != -1)
pe.SizeOfHeapCommit = pe_def_file->heap_commit;
}
return TRUE;
}
}
#endif
return FALSE;
}
 
static bfd_boolean
gld_i386pe_recognized_file (lang_input_statement_type *entry ATTRIBUTE_UNUSED)
{
#ifdef DLL_SUPPORT
#ifdef TARGET_IS_i386pe
pe_dll_id_target ("pei-i386");
#endif
#ifdef TARGET_IS_shpe
pe_dll_id_target ("pei-shl");
#endif
#ifdef TARGET_IS_armpe
pe_dll_id_target ("pei-arm-little");
#endif
#ifdef TARGET_IS_arm_epoc_pe
pe_dll_id_target ("epoc-pei-arm-little");
#endif
#ifdef TARGET_IS_arm_wince_pe
pe_dll_id_target ("pei-arm-wince-little");
#endif
if (pe_bfd_is_dll (entry->the_bfd))
return pe_implied_import_dll (entry->filename);
#endif
return FALSE;
}
 
static void
gld_i386pe_finish (void)
{
#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe)
struct bfd_link_hash_entry * h;
 
if (thumb_entry_symbol != NULL)
{
h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
FALSE, FALSE, TRUE);
 
if (h != (struct bfd_link_hash_entry *) NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
&& h->u.def.section->output_section != NULL)
{
static char buffer[32];
bfd_vma val;
 
/* Special procesing is required for a Thumb entry symbol. The
bottom bit of its address must be set. */
val = (h->u.def.value
+ bfd_get_section_vma (link_info.output_bfd,
h->u.def.section->output_section)
+ h->u.def.section->output_offset);
 
val |= 1;
 
/* Now convert this value into a string and store it in entry_symbol
where the lang_finish() function will pick it up. */
buffer[0] = '0';
buffer[1] = 'x';
 
sprintf_vma (buffer + 2, val);
 
if (entry_symbol.name != NULL && entry_from_cmdline)
einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
thumb_entry_symbol, entry_symbol.name);
entry_symbol.name = buffer;
}
else
einfo (_("%P: warning: cannot find thumb start symbol %s\n"), thumb_entry_symbol);
}
#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) || defined(TARGET_IS_arm_wince_pe) */
 
finish_default ();
 
#ifdef DLL_SUPPORT
if (link_info.shared
#if !defined(TARGET_IS_shpe)
|| (!link_info.relocatable && pe_def_file->num_exports != 0)
#endif
)
{
pe_dll_fill_sections (link_info.output_bfd, &link_info);
if (pe_implib_filename)
pe_dll_generate_implib (pe_def_file, pe_implib_filename, &link_info);
}
#if defined(TARGET_IS_shpe)
/* ARM doesn't need relocs. */
else
{
pe_exe_fill_sections (link_info.output_bfd, &link_info);
}
#endif
 
if (pe_out_def_filename)
pe_dll_generate_def_file (pe_out_def_filename);
#endif /* DLL_SUPPORT */
 
/* I don't know where .idata gets set as code, but it shouldn't be. */
{
asection *asec = bfd_get_section_by_name (link_info.output_bfd, ".idata");
 
if (asec)
{
asec->flags &= ~SEC_CODE;
asec->flags |= SEC_DATA;
}
}
}
 
/* Place an orphan section.
 
We use this to put sections in a reasonable place in the file, and
to ensure that they are aligned as required.
 
We handle grouped sections here as well. A section named .foo$nn
goes into the output section .foo. All grouped sections are sorted
by name.
 
Grouped sections for the default sections are handled by the
default linker script using wildcards, and are sorted by
sort_sections. */
 
static lang_output_section_statement_type *
gld_i386pe_place_orphan (asection *s,
const char *secname,
int constraint)
{
const char *orig_secname = secname;
char *dollar = NULL;
lang_output_section_statement_type *os;
lang_statement_list_type add_child;
lang_output_section_statement_type *match_by_name = NULL;
lang_statement_union_type **pl;
 
/* Look through the script to see where to place this section. */
if (!link_info.relocatable
&& (dollar = strchr (secname, '$')) != NULL)
{
size_t len = dollar - secname;
char *newname = xmalloc (len + 1);
memcpy (newname, secname, len);
newname[len] = '\0';
secname = newname;
}
 
lang_list_init (&add_child);
 
os = NULL;
if (constraint == 0)
for (os = lang_output_section_find (secname);
os != NULL;
os = next_matching_output_section_statement (os, 0))
{
/* If we don't match an existing output section, tell
lang_insert_orphan to create a new output section. */
constraint = SPECIAL;
 
if (os->bfd_section != NULL
&& (os->bfd_section->flags == 0
|| ((s->flags ^ os->bfd_section->flags)
& (SEC_LOAD | SEC_ALLOC)) == 0))
{
/* We already have an output section statement with this
name, and its bfd section has compatible flags.
If the section already exists but does not have any flags set,
then it has been created by the linker, probably as a result of
a --section-start command line switch. */
lang_add_section (&add_child, s, NULL, os);
break;
}
 
/* Save unused output sections in case we can match them
against orphans later. */
if (os->bfd_section == NULL)
match_by_name = os;
}
 
/* If we didn't match an active output section, see if we matched an
unused one and use that. */
if (os == NULL && match_by_name)
{
lang_add_section (&match_by_name->children, s, NULL, match_by_name);
return match_by_name;
}
 
if (os == NULL)
{
static struct orphan_save hold[] =
{
{ ".text",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
0, 0, 0, 0 },
{ ".idata",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
0, 0, 0, 0 },
{ ".rdata",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
0, 0, 0, 0 },
{ ".data",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
0, 0, 0, 0 },
{ ".bss",
SEC_ALLOC,
0, 0, 0, 0 }
};
enum orphan_save_index
{
orphan_text = 0,
orphan_idata,
orphan_rodata,
orphan_data,
orphan_bss
};
static int orphan_init_done = 0;
struct orphan_save *place;
lang_output_section_statement_type *after;
etree_type *address;
 
if (!orphan_init_done)
{
struct orphan_save *ho;
for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
if (ho->name != NULL)
{
ho->os = lang_output_section_find (ho->name);
if (ho->os != NULL && ho->os->flags == 0)
ho->os->flags = ho->flags;
}
orphan_init_done = 1;
}
 
/* Try to put the new output section in a reasonable place based
on the section name and section flags. */
 
place = NULL;
if ((s->flags & SEC_ALLOC) == 0)
;
else if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
place = &hold[orphan_bss];
else if ((s->flags & SEC_READONLY) == 0)
place = &hold[orphan_data];
else if ((s->flags & SEC_CODE) == 0)
{
place = (!strncmp (secname, ".idata$", 7) ? &hold[orphan_idata]
: &hold[orphan_rodata]);
}
else
place = &hold[orphan_text];
 
after = NULL;
if (place != NULL)
{
if (place->os == NULL)
place->os = lang_output_section_find (place->name);
after = place->os;
if (after == NULL)
after = lang_output_section_find_by_flags (s, &place->os, NULL);
if (after == NULL)
/* *ABS* is always the first output section statement. */
after = (&lang_output_section_statement.head
->output_section_statement);
}
 
/* All sections in an executable must be aligned to a page boundary.
In a relocatable link, just preserve the incoming alignment; the
address is discarded by lang_insert_orphan in that case, anyway. */
address = exp_unop (ALIGN_K, exp_nameop (NAME, "__section_alignment__"));
os = lang_insert_orphan (s, secname, constraint, after, place, address,
&add_child);
if (link_info.relocatable)
{
os->section_alignment = s->alignment_power;
os->bfd_section->alignment_power = s->alignment_power;
}
}
 
/* If the section name has a '$', sort it with the other '$'
sections. */
for (pl = &os->children.head; *pl != NULL; pl = &(*pl)->header.next)
{
lang_input_section_type *ls;
const char *lname;
 
if ((*pl)->header.type != lang_input_section_enum)
continue;
 
ls = &(*pl)->input_section;
 
lname = bfd_get_section_name (ls->section->owner, ls->section);
if (strchr (lname, '$') != NULL
&& (dollar == NULL || strcmp (orig_secname, lname) < 0))
break;
}
 
if (add_child.head != NULL)
{
*add_child.tail = *pl;
*pl = add_child.head;
}
 
return os;
}
 
static bfd_boolean
gld_i386pe_open_dynamic_archive
(const char *arch ATTRIBUTE_UNUSED,
search_dirs_type *search,
lang_input_statement_type *entry)
{
static const struct
{
const char * format;
bfd_boolean use_prefix;
}
libname_fmt [] =
{
/* Preferred explicit import library for dll's. */
{ "lib%s.dll.a", FALSE },
/* Alternate explicit import library for dll's. */
{ "%s.dll.a", FALSE },
/* "libfoo.a" could be either an import lib or a static lib.
For backwards compatibility, libfoo.a needs to precede
libfoo.dll and foo.dll in the search. */
{ "lib%s.a", FALSE },
/* The 'native' spelling of an import lib name is "foo.lib". */
{ "%s.lib", FALSE },
#ifdef DLL_SUPPORT
/* Try "<prefix>foo.dll" (preferred dll name, if specified). */
{ "%s%s.dll", TRUE },
#endif
/* Try "libfoo.dll" (default preferred dll name). */
{ "lib%s.dll", FALSE },
/* Finally try 'native' dll name "foo.dll". */
{ "%s.dll", FALSE },
/* Note: If adding more formats to this table, make sure to check to
see if their length is longer than libname_fmt[0].format, and if
so, update the call to xmalloc() below. */
{ NULL, FALSE }
};
static unsigned int format_max_len = 0;
const char * filename;
char * full_string;
char * base_string;
unsigned int i;
 
 
if (! entry->flags.maybe_archive)
return FALSE;
 
filename = entry->filename;
 
if (format_max_len == 0)
/* We need to allow space in the memory that we are going to allocate
for the characters in the format string. Since the format array is
static we only need to calculate this information once. In theory
this value could also be computed statically, but this introduces
the possibility for a discrepancy and hence a possible memory
corruption. The lengths we compute here will be too long because
they will include any formating characters (%s) in the strings, but
this will not matter. */
for (i = 0; libname_fmt[i].format; i++)
if (format_max_len < strlen (libname_fmt[i].format))
format_max_len = strlen (libname_fmt[i].format);
 
full_string = xmalloc (strlen (search->name)
+ strlen (filename)
+ format_max_len
#ifdef DLL_SUPPORT
+ (pe_dll_search_prefix
? strlen (pe_dll_search_prefix) : 0)
#endif
/* Allow for the terminating NUL and for the path
separator character that is inserted between
search->name and the start of the format string. */
+ 2);
 
sprintf (full_string, "%s/", search->name);
base_string = full_string + strlen (full_string);
 
for (i = 0; libname_fmt[i].format; i++)
{
#ifdef DLL_SUPPORT
if (libname_fmt[i].use_prefix)
{
if (!pe_dll_search_prefix)
continue;
sprintf (base_string, libname_fmt[i].format, pe_dll_search_prefix, filename);
}
else
#endif
sprintf (base_string, libname_fmt[i].format, filename);
 
if (ldfile_try_open_bfd (full_string, entry))
break;
}
 
if (!libname_fmt[i].format)
{
free (full_string);
return FALSE;
}
 
entry->filename = full_string;
 
return TRUE;
}
 
static int
gld_i386pe_find_potential_libraries
(char *name, lang_input_statement_type *entry)
{
return ldfile_open_file_search (name, entry, "", ".lib");
}
static char *
gld_i386pe_get_script (int *isfile)
{
*isfile = 0;
 
if (link_info.relocatable && config.build_constructors)
return
"/* Script for ld -Ur: link w/out relocation, do create constructors */\n\
OUTPUT_FORMAT(pe-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
.text :\n\
{\n\
*(.text)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;\n\
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);\n\
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;\n\
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);\n\
/* ??? Why is .gcc_exc here? */\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data :\n\
{\n\
*(.data)\n\
*(.data2)\n"
" *(.jcr)\n\
}\n\
.rdata :\n\
{\n\
*(.rdata)\n\
*(.rdata_runtime_pseudo_reloc)\n\
}\n\
.eh_frame :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata :\n\
{\n\
*(.pdata)\n\
}\n\
.bss :\n\
{\n\
*(.bss)\n\
*(COMMON)\n\
}\n\
.edata :\n\
{\n\
*(.edata)\n\
}\n\
/DISCARD/ :\n"
" {\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n\
*(.drectve)\n\
}\n\
.idata :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
}\n\
.CRT :\n\
{\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls :\n\
{\n\
}\n\
.endjunk :\n\
{\n\
/* end is deprecated, don't use it */\n"
" }\n\
.rsrc :\n\
{\n\
*(.rsrc)\n\
}\n\
.reloc :\n\
{\n\
*(.reloc)\n\
}\n\
.stab :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges :\n\
{\n\
*(.debug_aranges)\n"
" }\n\
.zdebug_aranges :\n\
{\n\
*(.zdebug_aranges)\n\
}\n\
.debug_pubnames :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info :\n\
{\n\
*(.debug_info)\n\
}\n\
.zdebug_info :\n\
{\n\
*(.zdebug_info)\n\
}\n\
.debug_abbrev :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types :\n\
{\n\
*(.debug_types)\n\
}\n\
.zdebug_types :\n\
{\n\
*(.zdebug_types)\n\
}\n\
}\n\n"
; else if (link_info.relocatable) return
"/* Script for ld -r: link without relocation */\n\
OUTPUT_FORMAT(pe-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
.text :\n\
{\n\
*(.text)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
/* ??? Why is .gcc_exc here? */\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data :\n\
{\n\
*(.data)\n\
*(.data2)\n\
*(.jcr)\n\
}\n\
.rdata :\n\
{\n"
" *(.rdata)\n\
*(.rdata_runtime_pseudo_reloc)\n\
}\n\
.eh_frame :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata :\n\
{\n\
*(.pdata)\n\
}\n\
.bss :\n\
{\n\
*(.bss)\n\
*(COMMON)\n\
}\n\
.edata :\n\
{\n\
*(.edata)\n\
}\n\
/DISCARD/ :\n\
{\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n"
" *(.drectve)\n\
}\n\
.idata :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
}\n\
.CRT :\n\
{\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls :\n\
{\n\
}\n\
.endjunk :\n\
{\n\
/* end is deprecated, don't use it */\n\
}\n\
.rsrc :\n\
{\n\
*(.rsrc)\n"
" }\n\
.reloc :\n\
{\n\
*(.reloc)\n\
}\n\
.stab :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges :\n\
{\n\
*(.debug_aranges)\n\
}\n\
.zdebug_aranges :\n\
{\n\
*(.zdebug_aranges)\n"
" }\n\
.debug_pubnames :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info :\n\
{\n\
*(.debug_info)\n\
}\n\
.zdebug_info :\n\
{\n\
*(.zdebug_info)\n\
}\n\
.debug_abbrev :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types :\n\
{\n\
*(.debug_types)\n\
}\n\
.zdebug_types :\n\
{\n\
*(.zdebug_types)\n\
}\n\
}\n\n"
; else if (!config.text_read_only) return
"/* Script for -N: mix text and data on same page; don't align data */\n\
OUTPUT_FORMAT(pei-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
/* Make the virtual address and file offset synced if the alignment is\n\
lower than the target page size. */\n\
. = SIZEOF_HEADERS;\n\
. = ALIGN(__section_alignment__);\n\
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :\n\
{\n\
*(.init)\n\
*(.text)\n\
*(SORT(.text$*))\n\
*(.text.*)\n\
*(.gnu.linkonce.t.*)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;\n\
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);\n\
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;\n\
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);\n\
*(.fini)\n\
/* ??? Why is .gcc_exc here? */\n\
*(.gcc_exc)\n"
" PROVIDE (etext = .);\n\
PROVIDE (_etext = .);\n\
*(.gcc_except_table)\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data BLOCK(__section_alignment__) :\n\
{\n\
__data_start__ = . ;\n\
*(.data)\n\
*(.data2)\n\
*(SORT(.data$*))\n\
*(.jcr)\n\
__data_end__ = . ;\n\
*(.data_cygwin_nocopy)\n\
}\n\
.rdata BLOCK(__section_alignment__) :\n\
{\n\
*(.rdata)\n\
*(SORT(.rdata$*))\n\
__rt_psrelocs_start = .;\n\
*(.rdata_runtime_pseudo_reloc)\n"
" __rt_psrelocs_end = .;\n\
}\n\
__rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start;\n\
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
__RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
.eh_frame BLOCK(__section_alignment__) :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata BLOCK(__section_alignment__) :\n\
{\n\
*(.pdata)\n\
}\n\
.bss BLOCK(__section_alignment__) :\n\
{\n\
__bss_start__ = . ;\n\
*(.bss)\n\
*(COMMON)\n\
__bss_end__ = . ;\n\
}\n\
.edata BLOCK(__section_alignment__) :\n\
{\n\
*(.edata)\n"
" }\n\
/DISCARD/ :\n\
{\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n\
*(.drectve)\n\
*(.note.GNU-stack)\n\
*(.gnu.lto_*)\n\
}\n\
.idata BLOCK(__section_alignment__) :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
SORT(*)(.idata$2)\n\
SORT(*)(.idata$3)\n\
/* These zeroes mark the end of the import list. */\n\
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);\n\
SORT(*)(.idata$4)\n\
__IAT_start__ = .;\n\
SORT(*)(.idata$5)\n\
__IAT_end__ = .;\n\
SORT(*)(.idata$6)\n\
SORT(*)(.idata$7)\n\
}\n"
" .CRT BLOCK(__section_alignment__) :\n\
{\n\
___crt_xc_start__ = . ;\n\
*(SORT(.CRT$XC*)) /* C initialization */\n\
___crt_xc_end__ = . ;\n\
___crt_xi_start__ = . ;\n\
*(SORT(.CRT$XI*)) /* C++ initialization */\n\
___crt_xi_end__ = . ;\n\
___crt_xl_start__ = . ;\n\
*(SORT(.CRT$XL*)) /* TLS callbacks */\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
___crt_xp_start__ = . ;\n\
*(SORT(.CRT$XP*)) /* Pre-termination */\n\
___crt_xp_end__ = . ;\n\
___crt_xt_start__ = . ;\n\
*(SORT(.CRT$XT*)) /* Termination */\n\
___crt_xt_end__ = . ;\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls BLOCK(__section_alignment__) :\n\
{\n\
___tls_start__ = . ;\n\
*(.tls$AAA)\n\
*(.tls)\n\
*(.tls$)\n\
*(SORT(.tls$*))\n\
*(.tls$ZZZ)\n\
___tls_end__ = . ;\n\
}\n\
.endjunk BLOCK(__section_alignment__) :\n\
{\n\
/* end is deprecated, don't use it */\n\
PROVIDE (end = .);\n\
PROVIDE ( _end = .);\n\
__end__ = .;\n\
}\n\
.rsrc BLOCK(__section_alignment__) :\n\
{\n\
*(.rsrc)\n\
*(SORT(.rsrc$*))\n\
}\n\
.reloc BLOCK(__section_alignment__) :\n\
{\n\
*(.reloc)\n\
}\n\
.stab BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_aranges)\n\
}\n\
.zdebug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_aranges)\n\
}\n\
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_info .gnu.linkonce.wi.*)\n\
}\n\
.zdebug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_info .zdebug.gnu.linkonce.wi.*)\n\
}\n\
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_types .gnu.linkonce.wt.*)\n\
}\n\
.zdebug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_types .gnu.linkonce.wt.*)\n\
}\n\
}\n\n"
; else if (!config.magic_demand_paged) return
"/* Script for -n: mix text and data on same page */\n\
OUTPUT_FORMAT(pei-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
/* Make the virtual address and file offset synced if the alignment is\n\
lower than the target page size. */\n\
. = SIZEOF_HEADERS;\n\
. = ALIGN(__section_alignment__);\n\
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :\n\
{\n\
*(.init)\n\
*(.text)\n\
*(SORT(.text$*))\n\
*(.text.*)\n\
*(.gnu.linkonce.t.*)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;\n\
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);\n\
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;\n\
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);\n\
*(.fini)\n\
/* ??? Why is .gcc_exc here? */\n\
*(.gcc_exc)\n"
" PROVIDE (etext = .);\n\
PROVIDE (_etext = .);\n\
*(.gcc_except_table)\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data BLOCK(__section_alignment__) :\n\
{\n\
__data_start__ = . ;\n\
*(.data)\n\
*(.data2)\n\
*(SORT(.data$*))\n\
*(.jcr)\n\
__data_end__ = . ;\n\
*(.data_cygwin_nocopy)\n\
}\n\
.rdata BLOCK(__section_alignment__) :\n\
{\n\
*(.rdata)\n\
*(SORT(.rdata$*))\n\
__rt_psrelocs_start = .;\n\
*(.rdata_runtime_pseudo_reloc)\n"
" __rt_psrelocs_end = .;\n\
}\n\
__rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start;\n\
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
__RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
.eh_frame BLOCK(__section_alignment__) :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata BLOCK(__section_alignment__) :\n\
{\n\
*(.pdata)\n\
}\n\
.bss BLOCK(__section_alignment__) :\n\
{\n\
__bss_start__ = . ;\n\
*(.bss)\n\
*(COMMON)\n\
__bss_end__ = . ;\n\
}\n\
.edata BLOCK(__section_alignment__) :\n\
{\n\
*(.edata)\n"
" }\n\
/DISCARD/ :\n\
{\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n\
*(.drectve)\n\
*(.note.GNU-stack)\n\
*(.gnu.lto_*)\n\
}\n\
.idata BLOCK(__section_alignment__) :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
SORT(*)(.idata$2)\n\
SORT(*)(.idata$3)\n\
/* These zeroes mark the end of the import list. */\n\
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);\n\
SORT(*)(.idata$4)\n\
__IAT_start__ = .;\n\
SORT(*)(.idata$5)\n\
__IAT_end__ = .;\n\
SORT(*)(.idata$6)\n\
SORT(*)(.idata$7)\n\
}\n"
" .CRT BLOCK(__section_alignment__) :\n\
{\n\
___crt_xc_start__ = . ;\n\
*(SORT(.CRT$XC*)) /* C initialization */\n\
___crt_xc_end__ = . ;\n\
___crt_xi_start__ = . ;\n\
*(SORT(.CRT$XI*)) /* C++ initialization */\n\
___crt_xi_end__ = . ;\n\
___crt_xl_start__ = . ;\n\
*(SORT(.CRT$XL*)) /* TLS callbacks */\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
___crt_xp_start__ = . ;\n\
*(SORT(.CRT$XP*)) /* Pre-termination */\n\
___crt_xp_end__ = . ;\n\
___crt_xt_start__ = . ;\n\
*(SORT(.CRT$XT*)) /* Termination */\n\
___crt_xt_end__ = . ;\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls BLOCK(__section_alignment__) :\n\
{\n\
___tls_start__ = . ;\n\
*(.tls$AAA)\n\
*(.tls)\n\
*(.tls$)\n\
*(SORT(.tls$*))\n\
*(.tls$ZZZ)\n\
___tls_end__ = . ;\n\
}\n\
.endjunk BLOCK(__section_alignment__) :\n\
{\n\
/* end is deprecated, don't use it */\n\
PROVIDE (end = .);\n\
PROVIDE ( _end = .);\n\
__end__ = .;\n\
}\n\
.rsrc BLOCK(__section_alignment__) :\n\
{\n\
*(.rsrc)\n\
*(SORT(.rsrc$*))\n\
}\n\
.reloc BLOCK(__section_alignment__) :\n\
{\n\
*(.reloc)\n\
}\n\
.stab BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_aranges)\n\
}\n\
.zdebug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_aranges)\n\
}\n\
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_info .gnu.linkonce.wi.*)\n\
}\n\
.zdebug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_info .zdebug.gnu.linkonce.wi.*)\n\
}\n\
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_types .gnu.linkonce.wt.*)\n\
}\n\
.zdebug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_types .gnu.linkonce.wt.*)\n\
}\n\
}\n\n"
; else if (link_info.pei386_auto_import == 1 && (MERGE_RDATA_V2 || link_info.pei386_runtime_pseudo_reloc != 2)) return
"/* Script for ld --enable-auto-import: Like the default script except read only data is placed into .data */\n\
OUTPUT_FORMAT(pei-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
/* Make the virtual address and file offset synced if the alignment is\n\
lower than the target page size. */\n\
. = SIZEOF_HEADERS;\n\
. = ALIGN(__section_alignment__);\n\
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :\n\
{\n\
*(.init)\n\
*(.text)\n\
*(SORT(.text$*))\n\
*(.text.*)\n\
*(.gnu.linkonce.t.*)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;\n\
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);\n\
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;\n\
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);\n\
*(.fini)\n\
/* ??? Why is .gcc_exc here? */\n\
*(.gcc_exc)\n"
" PROVIDE (etext = .);\n\
PROVIDE (_etext = .);\n\
*(.gcc_except_table)\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data BLOCK(__section_alignment__) :\n\
{\n\
__data_start__ = . ;\n\
*(.data)\n\
*(.data2)\n\
*(SORT(.data$*))\n\
*(.rdata)\n\
*(SORT(.rdata$*))\n\
*(.jcr)\n\
__data_end__ = . ;\n\
*(.data_cygwin_nocopy)\n\
}\n\
.rdata BLOCK(__section_alignment__) :\n\
{\n\
__rt_psrelocs_start = .;\n\
*(.rdata_runtime_pseudo_reloc)\n"
" __rt_psrelocs_end = .;\n\
}\n\
__rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start;\n\
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
__RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
.eh_frame BLOCK(__section_alignment__) :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata BLOCK(__section_alignment__) :\n\
{\n\
*(.pdata)\n\
}\n\
.bss BLOCK(__section_alignment__) :\n\
{\n\
__bss_start__ = . ;\n\
*(.bss)\n\
*(COMMON)\n\
__bss_end__ = . ;\n\
}\n\
.edata BLOCK(__section_alignment__) :\n\
{\n\
*(.edata)\n"
" }\n\
/DISCARD/ :\n\
{\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n\
*(.drectve)\n\
*(.note.GNU-stack)\n\
*(.gnu.lto_*)\n\
}\n\
.idata BLOCK(__section_alignment__) :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
SORT(*)(.idata$2)\n\
SORT(*)(.idata$3)\n\
/* These zeroes mark the end of the import list. */\n\
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);\n\
SORT(*)(.idata$4)\n\
__IAT_start__ = .;\n\
SORT(*)(.idata$5)\n\
__IAT_end__ = .;\n\
SORT(*)(.idata$6)\n\
SORT(*)(.idata$7)\n\
}\n"
" .CRT BLOCK(__section_alignment__) :\n\
{\n\
___crt_xc_start__ = . ;\n\
*(SORT(.CRT$XC*)) /* C initialization */\n\
___crt_xc_end__ = . ;\n\
___crt_xi_start__ = . ;\n\
*(SORT(.CRT$XI*)) /* C++ initialization */\n\
___crt_xi_end__ = . ;\n\
___crt_xl_start__ = . ;\n\
*(SORT(.CRT$XL*)) /* TLS callbacks */\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
___crt_xp_start__ = . ;\n\
*(SORT(.CRT$XP*)) /* Pre-termination */\n\
___crt_xp_end__ = . ;\n\
___crt_xt_start__ = . ;\n\
*(SORT(.CRT$XT*)) /* Termination */\n\
___crt_xt_end__ = . ;\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls BLOCK(__section_alignment__) :\n\
{\n\
___tls_start__ = . ;\n\
*(.tls$AAA)\n\
*(.tls)\n\
*(.tls$)\n\
*(SORT(.tls$*))\n\
*(.tls$ZZZ)\n\
___tls_end__ = . ;\n\
}\n\
.endjunk BLOCK(__section_alignment__) :\n\
{\n\
/* end is deprecated, don't use it */\n\
PROVIDE (end = .);\n\
PROVIDE ( _end = .);\n\
__end__ = .;\n\
}\n\
.rsrc BLOCK(__section_alignment__) :\n\
{\n\
*(.rsrc)\n\
*(SORT(.rsrc$*))\n\
}\n\
.reloc BLOCK(__section_alignment__) :\n\
{\n\
*(.reloc)\n\
}\n\
.stab BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_aranges)\n\
}\n\
.zdebug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_aranges)\n\
}\n\
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_info .gnu.linkonce.wi.*)\n\
}\n\
.zdebug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_info .zdebug.gnu.linkonce.wi.*)\n\
}\n\
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_types .gnu.linkonce.wt.*)\n\
}\n\
.zdebug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_types .gnu.linkonce.wt.*)\n\
}\n\
}\n\n"
; else return
"/* Default linker script, for normal executables */\n\
OUTPUT_FORMAT(pei-i386)\n\
SEARCH_DIR(\"=/usr/local/lib\"); SEARCH_DIR(\"=/lib\"); SEARCH_DIR(\"=/usr/lib\");\n\
SECTIONS\n\
{\n\
/* Make the virtual address and file offset synced if the alignment is\n\
lower than the target page size. */\n\
. = SIZEOF_HEADERS;\n\
. = ALIGN(__section_alignment__);\n\
.text __image_base__ + ( __section_alignment__ < 0x1000 ? . : __section_alignment__ ) :\n\
{\n\
*(.init)\n\
*(.text)\n\
*(SORT(.text$*))\n\
*(.text.*)\n\
*(.gnu.linkonce.t.*)\n\
*(.glue_7t)\n\
*(.glue_7)\n\
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;\n\
LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);\n\
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;\n\
LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);\n\
*(.fini)\n\
/* ??? Why is .gcc_exc here? */\n\
*(.gcc_exc)\n"
" PROVIDE (etext = .);\n\
PROVIDE (_etext = .);\n\
*(.gcc_except_table)\n\
}\n\
/* The Cygwin32 library uses a section to avoid copying certain data\n\
on fork. This used to be named \".data\". The linker used\n\
to include this between __data_start__ and __data_end__, but that\n\
breaks building the cygwin32 dll. Instead, we name the section\n\
\".data_cygwin_nocopy\" and explicitly include it after __data_end__. */\n\
.data BLOCK(__section_alignment__) :\n\
{\n\
__data_start__ = . ;\n\
*(.data)\n\
*(.data2)\n\
*(SORT(.data$*))\n\
*(.jcr)\n\
__data_end__ = . ;\n\
*(.data_cygwin_nocopy)\n\
}\n\
.rdata BLOCK(__section_alignment__) :\n\
{\n\
*(.rdata)\n\
*(SORT(.rdata$*))\n\
__rt_psrelocs_start = .;\n\
*(.rdata_runtime_pseudo_reloc)\n"
" __rt_psrelocs_end = .;\n\
}\n\
__rt_psrelocs_size = __rt_psrelocs_end - __rt_psrelocs_start;\n\
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;\n\
___RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
__RUNTIME_PSEUDO_RELOC_LIST__ = . - __rt_psrelocs_size;\n\
.eh_frame BLOCK(__section_alignment__) :\n\
{\n\
*(.eh_frame*)\n\
}\n\
.pdata BLOCK(__section_alignment__) :\n\
{\n\
*(.pdata)\n\
}\n\
.bss BLOCK(__section_alignment__) :\n\
{\n\
__bss_start__ = . ;\n\
*(.bss)\n\
*(COMMON)\n\
__bss_end__ = . ;\n\
}\n\
.edata BLOCK(__section_alignment__) :\n\
{\n\
*(.edata)\n"
" }\n\
/DISCARD/ :\n\
{\n\
*(.debug$S)\n\
*(.debug$T)\n\
*(.debug$F)\n\
*(.drectve)\n\
*(.note.GNU-stack)\n\
*(.gnu.lto_*)\n\
}\n\
.idata BLOCK(__section_alignment__) :\n\
{\n\
/* This cannot currently be handled with grouped sections.\n\
See pe.em:sort_sections. */\n\
SORT(*)(.idata$2)\n\
SORT(*)(.idata$3)\n\
/* These zeroes mark the end of the import list. */\n\
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);\n\
SORT(*)(.idata$4)\n\
__IAT_start__ = .;\n\
SORT(*)(.idata$5)\n\
__IAT_end__ = .;\n\
SORT(*)(.idata$6)\n\
SORT(*)(.idata$7)\n\
}\n"
" .CRT BLOCK(__section_alignment__) :\n\
{\n\
___crt_xc_start__ = . ;\n\
*(SORT(.CRT$XC*)) /* C initialization */\n\
___crt_xc_end__ = . ;\n\
___crt_xi_start__ = . ;\n\
*(SORT(.CRT$XI*)) /* C++ initialization */\n\
___crt_xi_end__ = . ;\n\
___crt_xl_start__ = . ;\n\
*(SORT(.CRT$XL*)) /* TLS callbacks */\n\
/* ___crt_xl_end__ is defined in the TLS Directory support code */\n\
___crt_xp_start__ = . ;\n\
*(SORT(.CRT$XP*)) /* Pre-termination */\n\
___crt_xp_end__ = . ;\n\
___crt_xt_start__ = . ;\n\
*(SORT(.CRT$XT*)) /* Termination */\n\
___crt_xt_end__ = . ;\n\
}\n\
/* Windows TLS expects .tls$AAA to be at the start and .tls$ZZZ to be\n\
at the end of section. This is important because _tls_start MUST\n\
be at the beginning of the section to enable SECREL32 relocations with TLS\n\
data. */\n\
.tls BLOCK(__section_alignment__) :\n\
{\n\
___tls_start__ = . ;\n\
*(.tls$AAA)\n\
*(.tls)\n\
*(.tls$)\n\
*(SORT(.tls$*))\n\
*(.tls$ZZZ)\n\
___tls_end__ = . ;\n\
}\n\
.endjunk BLOCK(__section_alignment__) :\n\
{\n\
/* end is deprecated, don't use it */\n\
PROVIDE (end = .);\n\
PROVIDE ( _end = .);\n\
__end__ = .;\n\
}\n\
.rsrc BLOCK(__section_alignment__) :\n\
{\n\
*(.rsrc)\n\
*(SORT(.rsrc$*))\n\
}\n\
.reloc BLOCK(__section_alignment__) :\n\
{\n\
*(.reloc)\n\
}\n\
.stab BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stab)\n\
}\n\
.stabstr BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.stabstr)\n\
}\n\
/* DWARF debug sections.\n\
Symbols in the DWARF debugging sections are relative to the beginning\n\
of the section. Unlike other targets that fake this by putting the\n\
section VMA at 0, the PE format will not allow it. */\n\
/* DWARF 1.1 and DWARF 2. */\n\
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_aranges)\n\
}\n\
.zdebug_aranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_aranges)\n\
}\n\
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubnames)\n\
}\n\
.zdebug_pubnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubnames)\n\
}\n\
.debug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_pubtypes)\n\
}\n\
.zdebug_pubtypes BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_pubtypes)\n\
}\n\
/* DWARF 2. */\n\
.debug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_info .gnu.linkonce.wi.*)\n\
}\n\
.zdebug_info BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_info .zdebug.gnu.linkonce.wi.*)\n\
}\n\
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_abbrev)\n\
}\n\
.zdebug_abbrev BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_abbrev)\n\
}\n\
.debug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_line)\n\
}\n\
.zdebug_line BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_line)\n\
}\n\
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_frame*)\n\
}\n\
.zdebug_frame BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_frame*)\n\
}\n\
.debug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_str)\n\
}\n\
.zdebug_str BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_str)\n\
}\n\
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_loc)\n\
}\n\
.zdebug_loc BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_loc)\n\
}\n\
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macinfo)\n\
}\n\
.zdebug_macinfo BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macinfo)\n\
}\n\
/* SGI/MIPS DWARF 2 extensions. */\n\
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_weaknames)\n\
}\n\
.zdebug_weaknames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_weaknames)\n\
}\n\
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_funcnames)\n\
}\n\
.zdebug_funcnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_funcnames)\n\
}\n\
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_typenames)\n\
}\n\
.zdebug_typenames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_typenames)\n\
}\n\
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_varnames)\n\
}\n\
.zdebug_varnames BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_varnames)\n\
}\n\
.debug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_macro)\n\
}\n\
.zdebug_macro BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_macro)\n\
}\n\
/* DWARF 3. */\n\
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_ranges)\n\
}\n\
.zdebug_ranges BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_ranges)\n\
}\n\
/* DWARF 4. */\n\
.debug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.debug_types .gnu.linkonce.wt.*)\n\
}\n\
.zdebug_types BLOCK(__section_alignment__) (NOLOAD) :\n\
{\n\
*(.zdebug_types .gnu.linkonce.wt.*)\n\
}\n\
}\n\n"
; }
 
 
struct ld_emulation_xfer_struct ld_i386pe_emulation =
{
gld_i386pe_before_parse,
syslib_default,
hll_default,
gld_i386pe_after_parse,
gld_i386pe_after_open,
after_allocation_default,
set_output_arch_default,
ldemul_default_target,
gld_i386pe_before_allocation,
gld_i386pe_get_script,
"i386pe",
"pei-i386",
gld_i386pe_finish,
NULL, /* Create output section statements. */
gld_i386pe_open_dynamic_archive,
gld_i386pe_place_orphan,
gld_i386pe_set_symbols,
NULL, /* parse_args */
gldi386pe_add_options,
gldi386pe_handle_option,
gld_i386pe_unrecognized_file,
gld_i386pe_list_options,
gld_i386pe_recognized_file,
gld_i386pe_find_potential_libraries,
NULL /* new_vers_pattern. */
};
/contrib/toolchain/binutils/ld/ld.h
0,0 → 1,321
/* ld.h -- general linker header file
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LD_H
#define LD_H
 
#ifdef HAVE_LOCALE_H
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
 
#ifdef HAVE_LOCALE_H
# ifndef ENABLE_NLS
/* The Solaris version of locale.h always includes libintl.h. If we have
been configured with --disable-nls then ENABLE_NLS will not be defined
and the dummy definitions of bindtextdomain (et al) below will conflict
with the defintions in libintl.h. So we define these values to prevent
the bogus inclusion of libintl.h. */
# define _LIBINTL_H
# define _LIBGETTEXT_H
# endif
# include <locale.h>
#endif
 
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) gettext (String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define gettext(Msgid) (Msgid)
# define dgettext(Domainname, Msgid) (Msgid)
# define dcgettext(Domainname, Msgid, Category) (Msgid)
# define textdomain(Domainname) while (0) /* nothing */
# define bindtextdomain(Domainname, Dirname) while (0) /* nothing */
# define _(String) (String)
# define N_(String) (String)
#endif
 
/* Look in this environment name for the linker to pretend to be */
#define EMULATION_ENVIRON "LDEMULATION"
/* If in there look for the strings: */
 
/* Look in this variable for a target format */
#define TARGET_ENVIRON "GNUTARGET"
 
/* Input sections which are put in a section of this name are actually
discarded. */
#define DISCARD_SECTION_NAME "/DISCARD/"
 
/* A file name list */
typedef struct name_list {
const char *name;
struct name_list *next;
}
name_list;
 
typedef enum {sort_none, sort_ascending, sort_descending} sort_order;
 
/* A wildcard specification. */
 
typedef enum {
none, by_name, by_alignment, by_name_alignment, by_alignment_name,
by_none, by_init_priority
} sort_type;
 
extern sort_type sort_section;
 
struct wildcard_spec {
const char *name;
struct name_list *exclude_name_list;
sort_type sorted;
struct flag_info *section_flag_list;
};
 
struct wildcard_list {
struct wildcard_list *next;
struct wildcard_spec spec;
};
 
struct map_symbol_def {
struct bfd_link_hash_entry *entry;
struct map_symbol_def *next;
};
 
/* The initial part of fat_user_section_struct has to be idential with
lean_user_section_struct. */
typedef struct fat_user_section_struct {
/* For input sections, when writing a map file: head / tail of a linked
list of hash table entries for symbols defined in this section. */
struct map_symbol_def *map_symbol_def_head;
struct map_symbol_def **map_symbol_def_tail;
unsigned long map_symbol_def_count;
} fat_section_userdata_type;
 
#define get_userdata(x) ((x)->userdata)
 
#define BYTE_SIZE (1)
#define SHORT_SIZE (2)
#define LONG_SIZE (4)
#define QUAD_SIZE (8)
 
enum endian_enum { ENDIAN_UNSET = 0, ENDIAN_BIG, ENDIAN_LITTLE };
 
enum symbolic_enum
{
symbolic_unset = 0,
symbolic,
symbolic_functions,
};
 
enum dynamic_list_enum
{
dynamic_list_unset = 0,
dynamic_list_data,
dynamic_list
};
 
typedef struct {
/* 1 => assign space to common symbols even if `relocatable_output'. */
bfd_boolean force_common_definition;
 
/* 1 => do not assign addresses to common symbols. */
bfd_boolean inhibit_common_definition;
 
/* If TRUE, build MIPS embedded PIC relocation tables in the output
file. */
bfd_boolean embedded_relocs;
 
/* If TRUE, force generation of a file with a .exe file. */
bfd_boolean force_exe_suffix;
 
/* If TRUE, generate a cross reference report. */
bfd_boolean cref;
 
/* If TRUE (which is the default), warn about mismatched input
files. */
bfd_boolean warn_mismatch;
 
/* Warn on attempting to open an incompatible library during a library
search. */
bfd_boolean warn_search_mismatch;
 
/* If non-zero check section addresses, once computed,
for overlaps. Relocatable links only check when this is > 0. */
signed char check_section_addresses;
 
/* If TRUE allow the linking of input files in an unknown architecture
assuming that the user knows what they are doing. This was the old
behaviour of the linker. The new default behaviour is to reject such
input files. */
bfd_boolean accept_unknown_input_arch;
 
/* If TRUE we'll just print the default output on stdout. */
bfd_boolean print_output_format;
 
/* Big or little endian as set on command line. */
enum endian_enum endian;
 
/* -Bsymbolic and -Bsymbolic-functions, as set on command line. */
enum symbolic_enum symbolic;
 
/* --dynamic-list, --dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo
and --dynamic-list FILE, as set on command line. */
enum dynamic_list_enum dynamic_list;
 
/* Name of runtime interpreter to invoke. */
char *interpreter;
 
/* Name to give runtime libary from the -soname argument. */
char *soname;
 
/* Runtime library search path from the -rpath argument. */
char *rpath;
 
/* Link time runtime library search path from the -rpath-link
argument. */
char *rpath_link;
 
/* Name of shared object whose symbol table should be filtered with
this shared object. From the --filter option. */
char *filter_shlib;
 
/* Name of shared object for whose symbol table this shared object
is an auxiliary filter. From the --auxiliary option. */
char **auxiliary_filters;
 
/* A version symbol to be applied to the symbol names found in the
.exports sections. */
char *version_exports_section;
 
/* Default linker script. */
char *default_script;
} args_type;
 
extern args_type command_line;
 
typedef int token_code_type;
 
typedef struct {
bfd_boolean magic_demand_paged;
bfd_boolean make_executable;
 
/* If TRUE, -shared is supported. */
/* ??? A better way to do this is perhaps to define this in the
ld_emulation_xfer_struct since this is really a target dependent
parameter. */
bfd_boolean has_shared;
 
/* If TRUE, build constructors. */
bfd_boolean build_constructors;
 
/* If TRUE, warn about any constructors. */
bfd_boolean warn_constructors;
 
/* If TRUE, warn about merging common symbols with others. */
bfd_boolean warn_common;
 
/* If TRUE, only warn once about a particular undefined symbol. */
bfd_boolean warn_once;
 
/* If TRUE, warn if multiple global-pointers are needed (Alpha
only). */
bfd_boolean warn_multiple_gp;
 
/* If TRUE, warn if the starting address of an output section
changes due to the alignment of an input section. */
bfd_boolean warn_section_align;
 
/* If TRUE, warning messages are fatal */
bfd_boolean fatal_warnings;
 
sort_order sort_common;
 
bfd_boolean text_read_only;
 
bfd_boolean stats;
 
/* If set, orphan input sections will be mapped to separate output
sections. */
bfd_boolean unique_orphan_sections;
 
/* If set, only search library directories explicitly selected
on the command line. */
bfd_boolean only_cmd_line_lib_dirs;
 
/* If set, numbers and absolute symbols are simply treated as
numbers everywhere. */
bfd_boolean sane_expr;
 
/* If set, code and non-code sections should never be in one segment. */
bfd_boolean separate_code;
 
/* The rpath separation character. Usually ':'. */
char rpath_separator;
 
char *map_filename;
FILE *map_file;
 
unsigned int split_by_reloc;
bfd_size_type split_by_file;
 
bfd_size_type specified_data_size;
 
/* The size of the hash table to use. */
unsigned long hash_table_size;
 
/* The maximum page size for ELF. */
bfd_vma maxpagesize;
 
/* The common page size for ELF. */
bfd_vma commonpagesize;
} ld_config_type;
 
extern ld_config_type config;
 
extern FILE * saved_script_handle;
extern bfd_boolean force_make_executable;
 
extern int yyparse (void);
extern void add_cref (const char *, bfd *, asection *, bfd_vma);
extern bfd_boolean handle_asneeded_cref (bfd *, enum notice_asneeded_action);
extern void output_cref (FILE *);
extern void check_nocrossrefs (void);
extern void ld_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 
/* If gcc >= 2.6, we can give a function name, too. */
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
#define __PRETTY_FUNCTION__ NULL
#endif
 
#undef abort
#define abort() ld_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
 
#endif
/contrib/toolchain/binutils/ld/ld.lnk
0,0 → 1,4
-static -nostdlib --stack 0x200000 -T/kolibrios/contrib/sdk/sources/newlib/app.lds
--image-base 0 -L/kolibrios/contrib/sdk/lib -o ld-new deffilep.o ei386pe.o ldcref.o ldctor.o ldemul.o ldexp.o ldfile.o ldgram.o
ldlang.o ldlex-wrapper.o ldmain.o ldmisc.o ldver.o ldwrite.o lexsup.o mri.o pe-dll.o
-lbfd -liberty -lz -lgcc -lc.dll -lapp
/contrib/toolchain/binutils/ld/ldcref.c
0,0 → 1,704
/* ldcref.c -- output a cross reference table
Copyright 1996-2013 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@cygnus.com>
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
 
/* This file holds routines that manage the cross reference table.
The table is used to generate cross reference reports. It is also
used to implement the NOCROSSREFS command in the linker script. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libiberty.h"
#include "demangle.h"
#include "objalloc.h"
 
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
 
/* We keep an instance of this structure for each reference to a
symbol from a given object. */
 
struct cref_ref {
/* The next reference. */
struct cref_ref *next;
/* The object. */
bfd *abfd;
/* True if the symbol is defined. */
unsigned int def : 1;
/* True if the symbol is common. */
unsigned int common : 1;
/* True if the symbol is undefined. */
unsigned int undef : 1;
};
 
/* We keep a hash table of symbols. Each entry looks like this. */
 
struct cref_hash_entry {
struct bfd_hash_entry root;
/* The demangled name. */
const char *demangled;
/* References to and definitions of this symbol. */
struct cref_ref *refs;
};
 
/* This is what the hash table looks like. */
 
struct cref_hash_table {
struct bfd_hash_table root;
};
 
/* Forward declarations. */
 
static void output_one_cref (FILE *, struct cref_hash_entry *);
static void check_local_sym_xref (lang_input_statement_type *);
static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *);
static void check_refs (const char *, bfd_boolean, asection *, bfd *,
struct lang_nocrossrefs *);
static void check_reloc_refs (bfd *, asection *, void *);
 
/* Look up an entry in the cref hash table. */
 
#define cref_hash_lookup(table, string, create, copy) \
((struct cref_hash_entry *) \
bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
 
/* Traverse the cref hash table. */
 
#define cref_hash_traverse(table, func, info) \
(bfd_hash_traverse \
(&(table)->root, \
(bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \
(info)))
 
/* The cref hash table. */
 
static struct cref_hash_table cref_table;
 
/* Whether the cref hash table has been initialized. */
 
static bfd_boolean cref_initialized;
 
/* The number of symbols seen so far. */
 
static size_t cref_symcount;
 
/* Used to take a snapshot of the cref hash table when starting to
add syms from an as-needed library. */
static struct bfd_hash_entry **old_table;
static unsigned int old_size;
static unsigned int old_count;
static void *old_tab;
static void *alloc_mark;
static size_t tabsize, entsize, refsize;
static size_t old_symcount;
 
/* Create an entry in a cref hash table. */
 
static struct bfd_hash_entry *
cref_hash_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string)
{
struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
 
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (ret == NULL)
ret = ((struct cref_hash_entry *)
bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
if (ret == NULL)
return NULL;
 
/* Call the allocation method of the superclass. */
ret = ((struct cref_hash_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
if (ret != NULL)
{
/* Set local fields. */
ret->demangled = NULL;
ret->refs = NULL;
 
/* Keep a count of the number of entries created in the hash
table. */
++cref_symcount;
}
 
return &ret->root;
}
 
/* Add a symbol to the cref hash table. This is called for every
global symbol that is seen during the link. */
 
void
add_cref (const char *name,
bfd *abfd,
asection *section,
bfd_vma value ATTRIBUTE_UNUSED)
{
struct cref_hash_entry *h;
struct cref_ref *r;
 
if (! cref_initialized)
{
if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc,
sizeof (struct cref_hash_entry)))
einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n"));
cref_initialized = TRUE;
}
 
h = cref_hash_lookup (&cref_table, name, TRUE, FALSE);
if (h == NULL)
einfo (_("%X%P: cref_hash_lookup failed: %E\n"));
 
for (r = h->refs; r != NULL; r = r->next)
if (r->abfd == abfd)
break;
 
if (r == NULL)
{
r = (struct cref_ref *) bfd_hash_allocate (&cref_table.root, sizeof *r);
if (r == NULL)
einfo (_("%X%P: cref alloc failed: %E\n"));
r->next = h->refs;
h->refs = r;
r->abfd = abfd;
r->def = FALSE;
r->common = FALSE;
r->undef = FALSE;
}
 
if (bfd_is_und_section (section))
r->undef = TRUE;
else if (bfd_is_com_section (section))
r->common = TRUE;
else
r->def = TRUE;
}
 
/* Called before loading an as-needed library to take a snapshot of
the cref hash table, and after we have loaded or found that the
library was not needed. */
 
bfd_boolean
handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
enum notice_asneeded_action act)
{
unsigned int i;
 
if (!cref_initialized)
return TRUE;
 
if (act == notice_as_needed)
{
char *old_ent, *old_ref;
 
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
 
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
entsize += cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
refsize += sizeof (struct cref_ref);
}
}
 
tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
old_tab = xmalloc (tabsize + entsize + refsize);
 
alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
if (alloc_mark == NULL)
return FALSE;
 
memcpy (old_tab, cref_table.root.table, tabsize);
old_ent = (char *) old_tab + tabsize;
old_ref = (char *) old_ent + entsize;
old_table = cref_table.root.table;
old_size = cref_table.root.size;
old_count = cref_table.root.count;
old_symcount = cref_symcount;
 
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
 
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
memcpy (old_ent, p, cref_table.root.entsize);
old_ent = (char *) old_ent + cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
{
memcpy (old_ref, r, sizeof (struct cref_ref));
old_ref = (char *) old_ref + sizeof (struct cref_ref);
}
}
}
return TRUE;
}
 
if (act == notice_not_needed)
{
char *old_ent, *old_ref;
 
if (old_tab == NULL)
{
/* The only way old_tab can be NULL is if the cref hash table
had not been initialised when notice_as_needed. */
bfd_hash_table_free (&cref_table.root);
cref_initialized = FALSE;
return TRUE;
}
 
old_ent = (char *) old_tab + tabsize;
old_ref = (char *) old_ent + entsize;
cref_table.root.table = old_table;
cref_table.root.size = old_size;
cref_table.root.count = old_count;
memcpy (cref_table.root.table, old_tab, tabsize);
cref_symcount = old_symcount;
 
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
 
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
memcpy (p, old_ent, cref_table.root.entsize);
old_ent = (char *) old_ent + cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
{
memcpy (r, old_ref, sizeof (struct cref_ref));
old_ref = (char *) old_ref + sizeof (struct cref_ref);
}
}
}
 
objalloc_free_block ((struct objalloc *) cref_table.root.memory,
alloc_mark);
}
else if (act != notice_needed)
return FALSE;
 
free (old_tab);
old_tab = NULL;
return TRUE;
}
 
/* Copy the addresses of the hash table entries into an array. This
is called via cref_hash_traverse. We also fill in the demangled
name. */
 
static bfd_boolean
cref_fill_array (struct cref_hash_entry *h, void *data)
{
struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data;
 
ASSERT (h->demangled == NULL);
h->demangled = bfd_demangle (link_info.output_bfd, h->root.string,
DMGL_ANSI | DMGL_PARAMS);
if (h->demangled == NULL)
h->demangled = h->root.string;
 
**pph = h;
 
++*pph;
 
return TRUE;
}
 
/* Sort an array of cref hash table entries by name. */
 
static int
cref_sort_array (const void *a1, const void *a2)
{
const struct cref_hash_entry * const *p1 =
(const struct cref_hash_entry * const *) a1;
const struct cref_hash_entry * const *p2 =
(const struct cref_hash_entry * const *) a2;
 
return strcmp ((*p1)->demangled, (*p2)->demangled);
}
 
/* Write out the cref table. */
 
#define FILECOL (50)
 
void
output_cref (FILE *fp)
{
int len;
struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
const char *msg;
 
fprintf (fp, _("\nCross Reference Table\n\n"));
msg = _("Symbol");
fprintf (fp, "%s", msg);
len = strlen (msg);
while (len < FILECOL)
{
putc (' ', fp);
++len;
}
fprintf (fp, _("File\n"));
 
if (! cref_initialized)
{
fprintf (fp, _("No symbols\n"));
return;
}
 
csyms = (struct cref_hash_entry **) xmalloc (cref_symcount * sizeof (*csyms));
 
csym_fill = csyms;
cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
ASSERT ((size_t) (csym_fill - csyms) == cref_symcount);
 
qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
 
csym_end = csyms + cref_symcount;
for (csym = csyms; csym < csym_end; csym++)
output_one_cref (fp, *csym);
}
 
/* Output one entry in the cross reference table. */
 
static void
output_one_cref (FILE *fp, struct cref_hash_entry *h)
{
int len;
struct bfd_link_hash_entry *hl;
struct cref_ref *r;
 
hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
FALSE, TRUE);
if (hl == NULL)
einfo ("%P: symbol `%T' missing from main hash table\n",
h->root.string);
else
{
/* If this symbol is defined in a dynamic object but never
referenced by a normal object, then don't print it. */
if (hl->type == bfd_link_hash_defined)
{
if (hl->u.def.section->output_section == NULL)
return;
if (hl->u.def.section->owner != NULL
&& (hl->u.def.section->owner->flags & DYNAMIC) != 0)
{
for (r = h->refs; r != NULL; r = r->next)
if ((r->abfd->flags & DYNAMIC) == 0)
break;
if (r == NULL)
return;
}
}
}
 
fprintf (fp, "%s ", h->demangled);
len = strlen (h->demangled) + 1;
 
for (r = h->refs; r != NULL; r = r->next)
{
if (r->def)
{
while (len < FILECOL)
{
putc (' ', fp);
++len;
}
lfinfo (fp, "%B\n", r->abfd);
len = 0;
}
}
 
for (r = h->refs; r != NULL; r = r->next)
{
if (r->common)
{
while (len < FILECOL)
{
putc (' ', fp);
++len;
}
lfinfo (fp, "%B\n", r->abfd);
len = 0;
}
}
 
for (r = h->refs; r != NULL; r = r->next)
{
if (! r->def && ! r->common)
{
while (len < FILECOL)
{
putc (' ', fp);
++len;
}
lfinfo (fp, "%B\n", r->abfd);
len = 0;
}
}
 
ASSERT (len == 0);
}
 
/* Check for prohibited cross references. */
 
void
check_nocrossrefs (void)
{
if (! cref_initialized)
return;
 
cref_hash_traverse (&cref_table, check_nocrossref, NULL);
 
lang_for_each_file (check_local_sym_xref);
}
 
/* Check for prohibited cross references to local and section symbols. */
 
static void
check_local_sym_xref (lang_input_statement_type *statement)
{
bfd *abfd;
asymbol **syms;
 
abfd = statement->the_bfd;
if (abfd == NULL)
return;
 
if (!bfd_generic_link_read_symbols (abfd))
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
 
for (syms = bfd_get_outsymbols (abfd); *syms; ++syms)
{
asymbol *sym = *syms;
if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE))
continue;
if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0
&& sym->section->output_section != NULL)
{
const char *outsecname, *symname;
struct lang_nocrossrefs *ncrs;
struct lang_nocrossref *ncr;
 
outsecname = sym->section->output_section->name;
symname = NULL;
if ((sym->flags & BSF_SECTION_SYM) == 0)
symname = sym->name;
for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
if (strcmp (ncr->name, outsecname) == 0)
check_refs (symname, FALSE, sym->section, abfd, ncrs);
}
}
}
 
/* Check one symbol to see if it is a prohibited cross reference. */
 
static bfd_boolean
check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED)
{
struct bfd_link_hash_entry *hl;
asection *defsec;
const char *defsecname;
struct lang_nocrossrefs *ncrs;
struct lang_nocrossref *ncr;
struct cref_ref *ref;
 
hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE,
FALSE, TRUE);
if (hl == NULL)
{
einfo (_("%P: symbol `%T' missing from main hash table\n"),
h->root.string);
return TRUE;
}
 
if (hl->type != bfd_link_hash_defined
&& hl->type != bfd_link_hash_defweak)
return TRUE;
 
defsec = hl->u.def.section->output_section;
if (defsec == NULL)
return TRUE;
defsecname = bfd_get_section_name (defsec->owner, defsec);
 
for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next)
for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next)
if (strcmp (ncr->name, defsecname) == 0)
for (ref = h->refs; ref != NULL; ref = ref->next)
check_refs (hl->root.string, TRUE, hl->u.def.section,
ref->abfd, ncrs);
 
return TRUE;
}
 
/* The struct is used to pass information from check_refs to
check_reloc_refs through bfd_map_over_sections. */
 
struct check_refs_info {
const char *sym_name;
asection *defsec;
struct lang_nocrossrefs *ncrs;
asymbol **asymbols;
bfd_boolean global;
};
 
/* This function is called for each symbol defined in a section which
prohibits cross references. We need to look through all references
to this symbol, and ensure that the references are not from
prohibited sections. */
 
static void
check_refs (const char *name,
bfd_boolean global,
asection *sec,
bfd *abfd,
struct lang_nocrossrefs *ncrs)
{
struct check_refs_info info;
 
/* We need to look through the relocations for this BFD, to see
if any of the relocations which refer to this symbol are from
a prohibited section. Note that we need to do this even for
the BFD in which the symbol is defined, since even a single
BFD might contain a prohibited cross reference. */
 
if (!bfd_generic_link_read_symbols (abfd))
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
 
info.sym_name = name;
info.global = global;
info.defsec = sec;
info.ncrs = ncrs;
info.asymbols = bfd_get_outsymbols (abfd);
bfd_map_over_sections (abfd, check_reloc_refs, &info);
}
 
/* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol
defined in INFO->DEFSECNAME. If this section maps into any of the
sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we
look through the relocations. If any of the relocations are to
INFO->SYM_NAME, then we report a prohibited cross reference error. */
 
static void
check_reloc_refs (bfd *abfd, asection *sec, void *iarg)
{
struct check_refs_info *info = (struct check_refs_info *) iarg;
asection *outsec;
const char *outsecname;
asection *outdefsec;
const char *outdefsecname;
struct lang_nocrossref *ncr;
const char *symname;
bfd_boolean global;
long relsize;
arelent **relpp;
long relcount;
arelent **p, **pend;
 
outsec = sec->output_section;
outsecname = bfd_get_section_name (outsec->owner, outsec);
 
outdefsec = info->defsec->output_section;
outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec);
 
/* The section where the symbol is defined is permitted. */
if (strcmp (outsecname, outdefsecname) == 0)
return;
 
for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next)
if (strcmp (outsecname, ncr->name) == 0)
break;
 
if (ncr == NULL)
return;
 
/* This section is one for which cross references are prohibited.
Look through the relocations, and see if any of them are to
INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations
against the section symbol. If INFO->GLOBAL is TRUE, the
definition is global, check for relocations against the global
symbols. Otherwise check for relocations against the local and
section symbols. */
 
symname = info->sym_name;
global = info->global;
 
relsize = bfd_get_reloc_upper_bound (abfd, sec);
if (relsize < 0)
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
if (relsize == 0)
return;
 
relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
if (relcount < 0)
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
 
p = relpp;
pend = p + relcount;
for (; p < pend && *p != NULL; p++)
{
arelent *q = *p;
 
if (q->sym_ptr_ptr != NULL
&& *q->sym_ptr_ptr != NULL
&& ((global
&& (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr))
|| bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr))
|| ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL
| BSF_WEAK)) != 0))
|| (!global
&& ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL
| BSF_SECTION_SYM)) != 0
&& bfd_get_section (*q->sym_ptr_ptr) == info->defsec))
&& (symname != NULL
? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0
: ((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0))
{
/* We found a reloc for the symbol. The symbol is defined
in OUTSECNAME. This reloc is from a section which is
mapped into a section from which references to OUTSECNAME
are prohibited. We must report an error. */
einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"),
abfd, sec, q->address, outsecname,
bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname);
}
}
 
free (relpp);
}
/contrib/toolchain/binutils/ld/ldctor.c
0,0 → 1,378
/* ldctor.c -- constructor support routines
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011
Free Software Foundation, Inc.
By Steve Chamberlain <sac@cygnus.com>
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "safe-ctype.h"
 
#include "ld.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldmisc.h"
#include <ldgram.h>
#include "ldmain.h"
#include "ldctor.h"
 
/* The list of statements needed to handle constructors. These are
invoked by the command CONSTRUCTORS in the linker script. */
lang_statement_list_type constructor_list;
 
/* Whether the constructors should be sorted. Note that this is
global for the entire link; we assume that there is only a single
CONSTRUCTORS command in the linker script. */
bfd_boolean constructors_sorted;
 
/* The sets we have seen. */
struct set_info *sets;
 
/* Add an entry to a set. H is the entry in the linker hash table.
RELOC is the relocation to use for an entry in the set. SECTION
and VALUE are the value to add. This is called during the first
phase of the link, when we are still gathering symbols together.
We just record the information now. The ldctor_build_sets
function will construct the sets. */
 
void
ldctor_add_set_entry (struct bfd_link_hash_entry *h,
bfd_reloc_code_real_type reloc,
const char *name,
asection *section,
bfd_vma value)
{
struct set_info *p;
struct set_element *e;
struct set_element **epp;
 
for (p = sets; p != NULL; p = p->next)
if (p->h == h)
break;
 
if (p == NULL)
{
p = (struct set_info *) xmalloc (sizeof (struct set_info));
p->next = sets;
sets = p;
p->h = h;
p->reloc = reloc;
p->count = 0;
p->elements = NULL;
}
else
{
if (p->reloc != reloc)
{
einfo (_("%P%X: Different relocs used in set %s\n"),
h->root.string);
return;
}
 
/* Don't permit a set to be constructed from different object
file formats. The same reloc may have different results. We
actually could sometimes handle this, but the case is
unlikely to ever arise. Sometimes constructor symbols are in
unusual sections, such as the absolute section--this appears
to be the case in Linux a.out--and in such cases we just
assume everything is OK. */
if (p->elements != NULL
&& section->owner != NULL
&& p->elements->section->owner != NULL
&& strcmp (bfd_get_target (section->owner),
bfd_get_target (p->elements->section->owner)) != 0)
{
einfo (_("%P%X: Different object file formats composing set %s\n"),
h->root.string);
return;
}
}
 
e = (struct set_element *) xmalloc (sizeof (struct set_element));
e->next = NULL;
e->name = name;
e->section = section;
e->value = value;
 
for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
;
*epp = e;
 
++p->count;
}
 
/* Get the priority of a g++ global constructor or destructor from the
symbol name. */
 
static int
ctor_prio (const char *name)
{
/* The name will look something like _GLOBAL_$I$65535$test02__Fv.
There might be extra leading underscores, and the $ characters
might be something else. The I might be a D. */
 
while (*name == '_')
++name;
 
if (! CONST_STRNEQ (name, "GLOBAL_"))
return -1;
 
name += sizeof "GLOBAL_" - 1;
 
if (name[0] != name[2])
return -1;
if (name[1] != 'I' && name[1] != 'D')
return -1;
if (! ISDIGIT (name[3]))
return -1;
 
return atoi (name + 3);
}
 
/* This function is used to sort constructor elements by priority. It
is called via qsort. */
 
static int
ctor_cmp (const void *p1, const void *p2)
{
const struct set_element * const *pe1 =
(const struct set_element * const *) p1;
const struct set_element * const *pe2 =
(const struct set_element * const *) p2;
const char *n1;
const char *n2;
int prio1;
int prio2;
 
n1 = (*pe1)->name;
if (n1 == NULL)
n1 = "";
n2 = (*pe2)->name;
if (n2 == NULL)
n2 = "";
 
/* We need to sort in reverse order by priority. When two
constructors have the same priority, we should maintain their
current relative position. */
 
prio1 = ctor_prio (n1);
prio2 = ctor_prio (n2);
 
/* We sort in reverse order because that is what g++ expects. */
if (prio1 < prio2)
return 1;
else if (prio1 > prio2)
return -1;
 
/* Force a stable sort. */
 
if (pe1 < pe2)
return -1;
else if (pe1 > pe2)
return 1;
else
return 0;
}
 
/* This function is called after the first phase of the link and
before the second phase. At this point all set information has
been gathered. We now put the statements to build the sets
themselves into constructor_list. */
 
void
ldctor_build_sets (void)
{
static bfd_boolean called;
bfd_boolean header_printed;
struct set_info *p;
 
/* The emulation code may call us directly, but we only want to do
this once. */
if (called)
return;
called = TRUE;
 
if (constructors_sorted)
{
for (p = sets; p != NULL; p = p->next)
{
int c, i;
struct set_element *e;
struct set_element **array;
 
if (p->elements == NULL)
continue;
 
c = 0;
for (e = p->elements; e != NULL; e = e->next)
++c;
 
array = (struct set_element **) xmalloc (c * sizeof *array);
 
i = 0;
for (e = p->elements; e != NULL; e = e->next)
{
array[i] = e;
++i;
}
 
qsort (array, c, sizeof *array, ctor_cmp);
 
e = array[0];
p->elements = e;
for (i = 0; i < c - 1; i++)
array[i]->next = array[i + 1];
array[i]->next = NULL;
 
free (array);
}
}
 
lang_list_init (&constructor_list);
push_stat_ptr (&constructor_list);
 
header_printed = FALSE;
for (p = sets; p != NULL; p = p->next)
{
struct set_element *e;
reloc_howto_type *howto;
int reloc_size, size;
 
/* If the symbol is defined, we may have been invoked from
collect, and the sets may already have been built, so we do
not do anything. */
if (p->h->type == bfd_link_hash_defined
|| p->h->type == bfd_link_hash_defweak)
continue;
 
/* For each set we build:
set:
.long number_of_elements
.long element0
...
.long elementN
.long 0
except that we use the right size instead of .long. When
generating relocatable output, we generate relocs instead of
addresses. */
howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc);
if (howto == NULL)
{
if (link_info.relocatable)
{
einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
bfd_get_target (link_info.output_bfd),
bfd_get_reloc_code_name (p->reloc),
p->h->root.string);
continue;
}
 
/* If this is not a relocatable link, all we need is the
size, which we can get from the input BFD. */
if (p->elements->section->owner != NULL)
howto = bfd_reloc_type_lookup (p->elements->section->owner,
p->reloc);
if (howto == NULL)
{
einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
bfd_get_target (p->elements->section->owner),
bfd_get_reloc_code_name (p->reloc),
p->h->root.string);
continue;
}
}
 
reloc_size = bfd_get_reloc_size (howto);
switch (reloc_size)
{
case 1: size = BYTE; break;
case 2: size = SHORT; break;
case 4: size = LONG; break;
case 8:
if (howto->complain_on_overflow == complain_overflow_signed)
size = SQUAD;
else
size = QUAD;
break;
default:
einfo (_("%P%X: Unsupported size %d for set %s\n"),
bfd_get_reloc_size (howto), p->h->root.string);
size = LONG;
break;
}
 
lang_add_assignment (exp_assign (".",
exp_unop (ALIGN_K,
exp_intop (reloc_size)),
FALSE));
lang_add_assignment (exp_assign (p->h->root.string,
exp_nameop (NAME, "."),
FALSE));
lang_add_data (size, exp_intop (p->count));
 
for (e = p->elements; e != NULL; e = e->next)
{
if (config.map_file != NULL)
{
int len;
 
if (! header_printed)
{
minfo (_("\nSet Symbol\n\n"));
header_printed = TRUE;
}
 
minfo ("%s", p->h->root.string);
len = strlen (p->h->root.string);
 
if (len >= 19)
{
print_nl ();
len = 0;
}
while (len < 20)
{
print_space ();
++len;
}
 
if (e->name != NULL)
minfo ("%T\n", e->name);
else
minfo ("%G\n", e->section->owner, e->section, e->value);
}
 
/* Need SEC_KEEP for --gc-sections. */
if (! bfd_is_abs_section (e->section))
e->section->flags |= SEC_KEEP;
 
if (link_info.relocatable)
lang_add_reloc (p->reloc, howto, e->section, e->name,
exp_intop (e->value));
else
lang_add_data (size, exp_relop (e->section, e->value));
}
 
lang_add_data (size, exp_intop (0));
}
 
pop_stat_ptr ();
}
/contrib/toolchain/binutils/ld/ldctor.h
0,0 → 1,60
/* ldctor.h - linker constructor support
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2002, 2003, 2005,
2007, 2008 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDCTOR_H
#define LDCTOR_H
 
/* List of statements needed to handle constructors */
extern lang_statement_list_type constructor_list;
 
/* Whether the constructors should be sorted. Note that this is
global for the entire link; we assume that there is only a single
CONSTRUCTORS command in the linker script. */
extern bfd_boolean constructors_sorted;
 
/* We keep a list of these structures for each set we build. */
 
struct set_info {
struct set_info *next; /* Next set. */
struct bfd_link_hash_entry *h; /* Hash table entry. */
bfd_reloc_code_real_type reloc; /* Reloc to use for an entry. */
size_t count; /* Number of elements. */
struct set_element *elements; /* Elements in set. */
};
 
struct set_element {
struct set_element *next; /* Next element. */
const char *name; /* Name in set (may be NULL). */
asection *section; /* Section of value in set. */
bfd_vma value; /* Value in set. */
};
 
/* The sets we have seen. */
 
extern struct set_info *sets;
 
extern void ldctor_add_set_entry
(struct bfd_link_hash_entry *, bfd_reloc_code_real_type, const char *,
asection *, bfd_vma);
extern void ldctor_build_sets
(void);
 
#endif
/contrib/toolchain/binutils/ld/ldemul-list.h
0,0 → 1,6
/* This file is automatically generated. DO NOT EDIT! */
extern ld_emulation_xfer_type ld_i386pe_emulation;
 
#define EMULATION_LIST \
&ld_i386pe_emulation, \
0
/contrib/toolchain/binutils/ld/ldemul.c
0,0 → 1,352
/* ldemul.c -- clearing house for ld emulation states
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "getopt.h"
#include "bfdlink.h"
 
#include "ld.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
#include "ldmain.h"
#include "ldemul-list.h"
 
static ld_emulation_xfer_type *ld_emulation;
 
void
ldemul_hll (char *name)
{
ld_emulation->hll (name);
}
 
void
ldemul_syslib (char *name)
{
ld_emulation->syslib (name);
}
 
void
ldemul_after_parse (void)
{
ld_emulation->after_parse ();
}
 
void
ldemul_before_parse (void)
{
ld_emulation->before_parse ();
}
 
void
ldemul_after_open (void)
{
ld_emulation->after_open ();
}
 
void
ldemul_after_allocation (void)
{
ld_emulation->after_allocation ();
}
 
void
ldemul_before_allocation (void)
{
ld_emulation->before_allocation ();
}
 
void
ldemul_set_output_arch (void)
{
ld_emulation->set_output_arch ();
}
 
void
ldemul_finish (void)
{
ld_emulation->finish ();
}
 
void
ldemul_set_symbols (void)
{
if (ld_emulation->set_symbols)
ld_emulation->set_symbols ();
}
 
void
ldemul_create_output_section_statements (void)
{
if (ld_emulation->create_output_section_statements)
ld_emulation->create_output_section_statements ();
}
 
char *
ldemul_get_script (int *isfile)
{
return ld_emulation->get_script (isfile);
}
 
bfd_boolean
ldemul_open_dynamic_archive (const char *arch, search_dirs_type *search,
lang_input_statement_type *entry)
{
if (ld_emulation->open_dynamic_archive)
return (*ld_emulation->open_dynamic_archive) (arch, search, entry);
return FALSE;
}
 
lang_output_section_statement_type *
ldemul_place_orphan (asection *s, const char *name, int constraint)
{
if (ld_emulation->place_orphan)
return (*ld_emulation->place_orphan) (s, name, constraint);
return NULL;
}
 
void
ldemul_add_options (int ns, char **shortopts, int nl,
struct option **longopts, int nrl,
struct option **really_longopts)
{
if (ld_emulation->add_options)
(*ld_emulation->add_options) (ns, shortopts, nl, longopts,
nrl, really_longopts);
}
 
bfd_boolean
ldemul_handle_option (int optc)
{
if (ld_emulation->handle_option)
return (*ld_emulation->handle_option) (optc);
return FALSE;
}
 
bfd_boolean
ldemul_parse_args (int argc, char **argv)
{
/* Try and use the emulation parser if there is one. */
if (ld_emulation->parse_args)
return (*ld_emulation->parse_args) (argc, argv);
return FALSE;
}
 
/* Let the emulation code handle an unrecognized file. */
 
bfd_boolean
ldemul_unrecognized_file (lang_input_statement_type *entry)
{
if (ld_emulation->unrecognized_file)
return (*ld_emulation->unrecognized_file) (entry);
return FALSE;
}
 
/* Let the emulation code handle a recognized file. */
 
bfd_boolean
ldemul_recognized_file (lang_input_statement_type *entry)
{
if (ld_emulation->recognized_file)
return (*ld_emulation->recognized_file) (entry);
return FALSE;
}
 
char *
ldemul_choose_target (int argc, char **argv)
{
return ld_emulation->choose_target (argc, argv);
}
 
 
/* The default choose_target function. */
 
char *
ldemul_default_target (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
{
char *from_outside = getenv (TARGET_ENVIRON);
if (from_outside != (char *) NULL)
return from_outside;
return ld_emulation->target_name;
}
 
/* If the entry point was not specified as an address, then add the
symbol as undefined. This will cause ld to extract an archive
element defining the entry if ld is linking against such an archive.
 
We don't do this when generating shared libraries unless given -e
on the command line, because most shared libs are not designed to
be run as an executable. However, some are, eg. glibc ld.so and
may rely on the default linker script supplying ENTRY. So we can't
remove the ENTRY from the script, but would rather not insert
undefined _start syms. */
 
void
after_parse_default (void)
{
if (entry_symbol.name != NULL
&& (link_info.executable || entry_from_cmdline))
{
bfd_boolean is_vma = FALSE;
 
if (entry_from_cmdline)
{
const char *send;
 
bfd_scan_vma (entry_symbol.name, &send, 0);
is_vma = *send == '\0';
}
if (!is_vma)
ldlang_add_undef (entry_symbol.name, entry_from_cmdline);
}
}
 
void
after_open_default (void)
{
}
 
void
after_allocation_default (void)
{
lang_relax_sections (FALSE);
}
 
void
before_allocation_default (void)
{
if (!link_info.relocatable)
strip_excluded_output_sections ();
}
 
void
finish_default (void)
{
if (!link_info.relocatable)
_bfd_fix_excluded_sec_syms (link_info.output_bfd, &link_info);
}
 
void
set_output_arch_default (void)
{
/* Set the output architecture and machine if possible. */
bfd_set_arch_mach (link_info.output_bfd,
ldfile_output_architecture, ldfile_output_machine);
 
bfd_emul_set_maxpagesize (output_target, config.maxpagesize);
bfd_emul_set_commonpagesize (output_target, config.commonpagesize);
}
 
void
syslib_default (char *ignore ATTRIBUTE_UNUSED)
{
info_msg (_("%S SYSLIB ignored\n"), NULL);
}
 
void
hll_default (char *ignore ATTRIBUTE_UNUSED)
{
info_msg (_("%S HLL ignored\n"), NULL);
}
 
ld_emulation_xfer_type *ld_emulations[] = { EMULATION_LIST };
 
void
ldemul_choose_mode (char *target)
{
ld_emulation_xfer_type **eptr = ld_emulations;
/* Ignore "gld" prefix. */
if (target[0] == 'g' && target[1] == 'l' && target[2] == 'd')
target += 3;
for (; *eptr; eptr++)
{
if (strcmp (target, (*eptr)->emulation_name) == 0)
{
ld_emulation = *eptr;
return;
}
}
einfo (_("%P: unrecognised emulation mode: %s\n"), target);
einfo (_("Supported emulations: "));
ldemul_list_emulations (stderr);
einfo ("%F\n");
}
 
void
ldemul_list_emulations (FILE *f)
{
ld_emulation_xfer_type **eptr = ld_emulations;
bfd_boolean first = TRUE;
 
for (; *eptr; eptr++)
{
if (first)
first = FALSE;
else
fprintf (f, " ");
fprintf (f, "%s", (*eptr)->emulation_name);
}
}
 
void
ldemul_list_emulation_options (FILE *f)
{
ld_emulation_xfer_type **eptr;
int options_found = 0;
 
for (eptr = ld_emulations; *eptr; eptr++)
{
ld_emulation_xfer_type *emul = *eptr;
 
if (emul->list_options)
{
fprintf (f, "%s: \n", emul->emulation_name);
 
emul->list_options (f);
 
options_found = 1;
}
}
 
if (! options_found)
fprintf (f, _(" no emulation specific options.\n"));
}
 
int
ldemul_find_potential_libraries (char *name, lang_input_statement_type *entry)
{
if (ld_emulation->find_potential_libraries)
return ld_emulation->find_potential_libraries (name, entry);
 
return 0;
}
 
struct bfd_elf_version_expr *
ldemul_new_vers_pattern (struct bfd_elf_version_expr *entry)
{
if (ld_emulation->new_vers_pattern)
entry = (*ld_emulation->new_vers_pattern) (entry);
return entry;
}
/contrib/toolchain/binutils/ld/ldemul.h
0,0 → 1,209
/* ld-emul.h - Linker emulation header file
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001,
2002, 2003, 2004, 2005, 2007, 2008
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDEMUL_H
#define LDEMUL_H
 
/* Forward declaration for ldemul_add_options() and others. */
struct option;
 
extern void ldemul_hll
(char *);
extern void ldemul_syslib
(char *);
extern void ldemul_after_parse
(void);
extern void ldemul_before_parse
(void);
extern void ldemul_after_open
(void);
extern void ldemul_after_allocation
(void);
extern void ldemul_before_allocation
(void);
extern void ldemul_set_output_arch
(void);
extern char *ldemul_choose_target
(int, char**);
extern void ldemul_choose_mode
(char *);
extern void ldemul_list_emulations
(FILE *);
extern void ldemul_list_emulation_options
(FILE *);
extern char *ldemul_get_script
(int *isfile);
extern void ldemul_finish
(void);
extern void ldemul_set_symbols
(void);
extern void ldemul_create_output_section_statements
(void);
extern lang_output_section_statement_type *ldemul_place_orphan
(asection *, const char *, int);
extern bfd_boolean ldemul_parse_args
(int, char **);
extern void ldemul_add_options
(int, char **, int, struct option **, int, struct option **);
extern bfd_boolean ldemul_handle_option
(int);
extern bfd_boolean ldemul_unrecognized_file
(struct lang_input_statement_struct *);
extern bfd_boolean ldemul_recognized_file
(struct lang_input_statement_struct *);
extern bfd_boolean ldemul_open_dynamic_archive
(const char *, struct search_dirs *, struct lang_input_statement_struct *);
extern char *ldemul_default_target
(int, char**);
extern void after_parse_default
(void);
extern void after_open_default
(void);
extern void after_allocation_default
(void);
extern void before_allocation_default
(void);
extern void finish_default
(void);
extern void finish_default
(void);
extern void set_output_arch_default
(void);
extern void syslib_default
(char*);
extern void hll_default
(char*);
extern int ldemul_find_potential_libraries
(char *, struct lang_input_statement_struct *);
extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
(struct bfd_elf_version_expr *);
 
typedef struct ld_emulation_xfer_struct {
/* Run before parsing the command line and script file.
Set the architecture, maybe other things. */
void (*before_parse) (void);
 
/* Handle the SYSLIB (low level library) script command. */
void (*syslib) (char *);
 
/* Handle the HLL (high level library) script command. */
void (*hll) (char *);
 
/* Run after parsing the command line and script file. */
void (*after_parse) (void);
 
/* Run after opening all input files, and loading the symbols. */
void (*after_open) (void);
 
/* Run after allocating output sections. */
void (*after_allocation) (void);
 
/* Set the output architecture and machine if possible. */
void (*set_output_arch) (void);
 
/* Decide which target name to use. */
char * (*choose_target) (int, char**);
 
/* Run before allocating output sections. */
void (*before_allocation) (void);
 
/* Return the appropriate linker script. */
char * (*get_script) (int *isfile);
 
/* The name of this emulation. */
char *emulation_name;
 
/* The output format. */
char *target_name;
 
/* Run after assigning values from the script. */
void (*finish) (void);
 
/* Create any output sections needed by the target. */
void (*create_output_section_statements) (void);
 
/* Try to open a dynamic library. ARCH is an architecture name, and
is normally the empty string. ENTRY is the lang_input_statement
that should be opened. */
bfd_boolean (*open_dynamic_archive)
(const char *arch, struct search_dirs *,
struct lang_input_statement_struct *entry);
 
/* Place an orphan section. Return TRUE if it was placed, FALSE if
the default action should be taken. This field may be NULL, in
which case the default action will always be taken. */
lang_output_section_statement_type *(*place_orphan)
(asection *, const char *, int);
 
/* Run after assigning parsing with the args, but before
reading the script. Used to initialize symbols used in the script. */
void (*set_symbols) (void);
 
/* Parse args which the base linker doesn't understand.
Return TRUE if the arg needs no further processing. */
bfd_boolean (*parse_args) (int, char **);
 
/* Hook to add options to parameters passed by the base linker to
getopt_long and getopt_long_only calls. */
void (*add_options)
(int, char **, int, struct option **, int, struct option **);
 
/* Companion to the above to handle an option. Returns TRUE if it is
one of our options. */
bfd_boolean (*handle_option) (int);
 
/* Run to handle files which are not recognized as object files or
archives. Return TRUE if the file was handled. */
bfd_boolean (*unrecognized_file)
(struct lang_input_statement_struct *);
 
/* Run to list the command line options which parse_args handles. */
void (* list_options) (FILE *);
 
/* Run to specially handle files which *are* recognized as object
files or archives. Return TRUE if the file was handled. */
bfd_boolean (*recognized_file)
(struct lang_input_statement_struct *);
 
/* Called when looking for libraries in a directory specified
via a linker command line option or linker script option.
Files that match the pattern "lib*.a" have already been scanned.
(For VMS files matching ":lib*.a" have also been scanned). */
int (* find_potential_libraries)
(char *, struct lang_input_statement_struct *);
 
/* Called when adding a new version pattern. PowerPC64-ELF uses
this hook to add a pattern matching ".foo" for every "foo". */
struct bfd_elf_version_expr * (*new_vers_pattern)
(struct bfd_elf_version_expr *);
 
} ld_emulation_xfer_type;
 
typedef enum {
intel_ic960_ld_mode_enum,
default_mode_enum,
intel_gld960_ld_mode_enum
} lang_emulation_mode_enum_type;
 
extern ld_emulation_xfer_type *ld_emulations[];
 
#endif
/contrib/toolchain/binutils/ld/ldexp.c
0,0 → 1,1357
/* This module handles expression trees.
Copyright 1991-2013 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
 
/* This module is in charge of working out the contents of expressions.
 
It has to keep track of the relative/absness of a symbol etc. This
is done by keeping all values in a struct (an etree_value_type)
which contains a value, a section to which it is relative and a
valid bit. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
 
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlex.h"
#include <ldgram.h>
#include "ldlang.h"
#include "libiberty.h"
#include "safe-ctype.h"
 
static void exp_fold_tree_1 (etree_type *);
static bfd_vma align_n (bfd_vma, bfd_vma);
 
segment_type *segments;
 
struct ldexp_control expld;
 
/* Print the string representation of the given token. Surround it
with spaces if INFIX_P is TRUE. */
 
static void
exp_print_token (token_code_type code, int infix_p)
{
static const struct
{
token_code_type code;
const char * name;
}
table[] =
{
{ INT, "int" },
{ NAME, "NAME" },
{ PLUSEQ, "+=" },
{ MINUSEQ, "-=" },
{ MULTEQ, "*=" },
{ DIVEQ, "/=" },
{ LSHIFTEQ, "<<=" },
{ RSHIFTEQ, ">>=" },
{ ANDEQ, "&=" },
{ OREQ, "|=" },
{ OROR, "||" },
{ ANDAND, "&&" },
{ EQ, "==" },
{ NE, "!=" },
{ LE, "<=" },
{ GE, ">=" },
{ LSHIFT, "<<" },
{ RSHIFT, ">>" },
{ LOG2CEIL, "LOG2CEIL" },
{ ALIGN_K, "ALIGN" },
{ BLOCK, "BLOCK" },
{ QUAD, "QUAD" },
{ SQUAD, "SQUAD" },
{ LONG, "LONG" },
{ SHORT, "SHORT" },
{ BYTE, "BYTE" },
{ SECTIONS, "SECTIONS" },
{ SIZEOF_HEADERS, "SIZEOF_HEADERS" },
{ MEMORY, "MEMORY" },
{ DEFINED, "DEFINED" },
{ TARGET_K, "TARGET" },
{ SEARCH_DIR, "SEARCH_DIR" },
{ MAP, "MAP" },
{ ENTRY, "ENTRY" },
{ NEXT, "NEXT" },
{ ALIGNOF, "ALIGNOF" },
{ SIZEOF, "SIZEOF" },
{ ADDR, "ADDR" },
{ LOADADDR, "LOADADDR" },
{ CONSTANT, "CONSTANT" },
{ ABSOLUTE, "ABSOLUTE" },
{ MAX_K, "MAX" },
{ MIN_K, "MIN" },
{ ASSERT_K, "ASSERT" },
{ REL, "relocatable" },
{ DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
{ DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
{ DATA_SEGMENT_END, "DATA_SEGMENT_END" },
{ ORIGIN, "ORIGIN" },
{ LENGTH, "LENGTH" },
{ SEGMENT_START, "SEGMENT_START" }
};
unsigned int idx;
 
for (idx = 0; idx < ARRAY_SIZE (table); idx++)
if (table[idx].code == code)
break;
 
if (infix_p)
fputc (' ', config.map_file);
 
if (idx < ARRAY_SIZE (table))
fputs (table[idx].name, config.map_file);
else if (code < 127)
fputc (code, config.map_file);
else
fprintf (config.map_file, "<code %d>", code);
 
if (infix_p)
fputc (' ', config.map_file);
}
 
static void
make_log2ceil (void)
{
bfd_vma value = expld.result.value;
bfd_vma result = -1;
bfd_boolean round_up = FALSE;
 
do
{
result++;
/* If more than one bit is set in the value we will need to round up. */
if ((value > 1) && (value & 1))
round_up = TRUE;
}
while (value >>= 1);
 
if (round_up)
result += 1;
expld.result.section = NULL;
expld.result.value = result;
}
 
static void
make_abs (void)
{
if (expld.result.section != NULL)
expld.result.value += expld.result.section->vma;
expld.result.section = bfd_abs_section_ptr;
}
 
static void
new_abs (bfd_vma value)
{
expld.result.valid_p = TRUE;
expld.result.section = bfd_abs_section_ptr;
expld.result.value = value;
expld.result.str = NULL;
}
 
etree_type *
exp_intop (bfd_vma value)
{
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
new_e->type.node_code = INT;
new_e->type.filename = ldlex_filename ();
new_e->type.lineno = lineno;
new_e->value.value = value;
new_e->value.str = NULL;
new_e->type.node_class = etree_value;
return new_e;
}
 
etree_type *
exp_bigintop (bfd_vma value, char *str)
{
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
new_e->type.node_code = INT;
new_e->type.filename = ldlex_filename ();
new_e->type.lineno = lineno;
new_e->value.value = value;
new_e->value.str = str;
new_e->type.node_class = etree_value;
return new_e;
}
 
/* Build an expression representing an unnamed relocatable value. */
 
etree_type *
exp_relop (asection *section, bfd_vma value)
{
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->rel));
new_e->type.node_code = REL;
new_e->type.filename = ldlex_filename ();
new_e->type.lineno = lineno;
new_e->type.node_class = etree_rel;
new_e->rel.section = section;
new_e->rel.value = value;
return new_e;
}
 
static void
new_number (bfd_vma value)
{
expld.result.valid_p = TRUE;
expld.result.value = value;
expld.result.str = NULL;
expld.result.section = NULL;
}
 
static void
new_rel (bfd_vma value, asection *section)
{
expld.result.valid_p = TRUE;
expld.result.value = value;
expld.result.str = NULL;
expld.result.section = section;
}
 
static void
new_rel_from_abs (bfd_vma value)
{
asection *s = expld.section;
 
if (s == bfd_abs_section_ptr && expld.phase == lang_final_phase_enum)
s = section_for_dot ();
expld.result.valid_p = TRUE;
expld.result.value = value - s->vma;
expld.result.str = NULL;
expld.result.section = s;
}
 
static void
fold_unary (etree_type *tree)
{
exp_fold_tree_1 (tree->unary.child);
if (expld.result.valid_p)
{
switch (tree->type.node_code)
{
case ALIGN_K:
if (expld.phase != lang_first_phase_enum)
new_rel_from_abs (align_n (expld.dot, expld.result.value));
else
expld.result.valid_p = FALSE;
break;
 
case ABSOLUTE:
make_abs ();
break;
 
case LOG2CEIL:
make_log2ceil ();
break;
 
case '~':
expld.result.value = ~expld.result.value;
break;
 
case '!':
expld.result.value = !expld.result.value;
break;
 
case '-':
expld.result.value = -expld.result.value;
break;
 
case NEXT:
/* Return next place aligned to value. */
if (expld.phase != lang_first_phase_enum)
{
make_abs ();
expld.result.value = align_n (expld.dot, expld.result.value);
}
else
expld.result.valid_p = FALSE;
break;
 
case DATA_SEGMENT_END:
if (expld.phase == lang_first_phase_enum
|| expld.section != bfd_abs_section_ptr)
{
expld.result.valid_p = FALSE;
}
else if (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_relro_seen)
{
expld.dataseg.phase = exp_dataseg_end_seen;
expld.dataseg.end = expld.result.value;
}
else if (expld.dataseg.phase == exp_dataseg_done
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust)
{
/* OK. */
}
else
expld.result.valid_p = FALSE;
break;
 
default:
FAIL ();
break;
}
}
}
 
static void
fold_binary (etree_type *tree)
{
etree_value_type lhs;
exp_fold_tree_1 (tree->binary.lhs);
 
/* The SEGMENT_START operator is special because its first
operand is a string, not the name of a symbol. Note that the
operands have been swapped, so binary.lhs is second (default)
operand, binary.rhs is first operand. */
if (expld.result.valid_p && tree->type.node_code == SEGMENT_START)
{
const char *segment_name;
segment_type *seg;
 
/* Check to see if the user has overridden the default
value. */
segment_name = tree->binary.rhs->name.name;
for (seg = segments; seg; seg = seg->next)
if (strcmp (seg->name, segment_name) == 0)
{
if (!seg->used
&& config.magic_demand_paged
&& (seg->value % config.maxpagesize) != 0)
einfo (_("%P: warning: address of `%s' isn't multiple of maximum page size\n"),
segment_name);
seg->used = TRUE;
new_rel_from_abs (seg->value);
break;
}
return;
}
 
lhs = expld.result;
exp_fold_tree_1 (tree->binary.rhs);
expld.result.valid_p &= lhs.valid_p;
 
if (expld.result.valid_p)
{
if (lhs.section != expld.result.section)
{
/* If the values are from different sections, and neither is
just a number, make both the source arguments absolute. */
if (expld.result.section != NULL
&& lhs.section != NULL)
{
make_abs ();
lhs.value += lhs.section->vma;
lhs.section = bfd_abs_section_ptr;
}
 
/* If the rhs is just a number, keep the lhs section. */
else if (expld.result.section == NULL)
{
expld.result.section = lhs.section;
/* Make this NULL so that we know one of the operands
was just a number, for later tests. */
lhs.section = NULL;
}
}
/* At this point we know that both operands have the same
section, or at least one of them is a plain number. */
 
switch (tree->type.node_code)
{
/* Arithmetic operators, bitwise AND, bitwise OR and XOR
keep the section of one of their operands only when the
other operand is a plain number. Losing the section when
operating on two symbols, ie. a result of a plain number,
is required for subtraction and XOR. It's justifiable
for the other operations on the grounds that adding,
multiplying etc. two section relative values does not
really make sense unless they are just treated as
numbers.
The same argument could be made for many expressions
involving one symbol and a number. For example,
"1 << x" and "100 / x" probably should not be given the
section of x. The trouble is that if we fuss about such
things the rules become complex and it is onerous to
document ld expression evaluation. */
#define BOP(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
if (expld.result.section == lhs.section) \
expld.result.section = NULL; \
break;
 
/* Comparison operators, logical AND, and logical OR always
return a plain number. */
#define BOPN(x, y) \
case x: \
expld.result.value = lhs.value y expld.result.value; \
expld.result.section = NULL; \
break;
 
BOP ('+', +);
BOP ('*', *);
BOP ('-', -);
BOP (LSHIFT, <<);
BOP (RSHIFT, >>);
BOP ('&', &);
BOP ('^', ^);
BOP ('|', |);
BOPN (EQ, ==);
BOPN (NE, !=);
BOPN ('<', <);
BOPN ('>', >);
BOPN (LE, <=);
BOPN (GE, >=);
BOPN (ANDAND, &&);
BOPN (OROR, ||);
 
case '%':
if (expld.result.value != 0)
expld.result.value = ((bfd_signed_vma) lhs.value
% (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S %% by zero\n"), tree->binary.rhs);
if (expld.result.section == lhs.section)
expld.result.section = NULL;
break;
 
case '/':
if (expld.result.value != 0)
expld.result.value = ((bfd_signed_vma) lhs.value
/ (bfd_signed_vma) expld.result.value);
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S / by zero\n"), tree->binary.rhs);
if (expld.result.section == lhs.section)
expld.result.section = NULL;
break;
 
case MAX_K:
if (lhs.value > expld.result.value)
expld.result.value = lhs.value;
break;
 
case MIN_K:
if (lhs.value < expld.result.value)
expld.result.value = lhs.value;
break;
 
case ALIGN_K:
expld.result.value = align_n (lhs.value, expld.result.value);
break;
 
case DATA_SEGMENT_ALIGN:
expld.dataseg.relro = exp_dataseg_relro_start;
if (expld.phase == lang_first_phase_enum
|| expld.section != bfd_abs_section_ptr)
expld.result.valid_p = FALSE;
else
{
bfd_vma maxpage = lhs.value;
bfd_vma commonpage = expld.result.value;
 
expld.result.value = align_n (expld.dot, maxpage);
if (expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.result.value = expld.dataseg.base;
else if (expld.dataseg.phase == exp_dataseg_adjust)
{
if (commonpage < maxpage)
expld.result.value += ((expld.dot + commonpage - 1)
& (maxpage - commonpage));
}
else
{
expld.result.value += expld.dot & (maxpage - 1);
if (expld.dataseg.phase == exp_dataseg_done)
{
/* OK. */
}
else if (expld.dataseg.phase == exp_dataseg_none)
{
expld.dataseg.phase = exp_dataseg_align_seen;
expld.dataseg.min_base = expld.dot;
expld.dataseg.base = expld.result.value;
expld.dataseg.pagesize = commonpage;
expld.dataseg.maxpagesize = maxpage;
expld.dataseg.relro_end = 0;
}
else
expld.result.valid_p = FALSE;
}
}
break;
 
case DATA_SEGMENT_RELRO_END:
expld.dataseg.relro = exp_dataseg_relro_end;
if (expld.phase == lang_first_phase_enum
|| expld.section != bfd_abs_section_ptr)
expld.result.valid_p = FALSE;
else if (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_adjust
|| expld.dataseg.phase == exp_dataseg_relro_adjust
|| expld.dataseg.phase == exp_dataseg_done)
{
if (expld.dataseg.phase == exp_dataseg_align_seen
|| expld.dataseg.phase == exp_dataseg_relro_adjust)
expld.dataseg.relro_end = lhs.value + expld.result.value;
 
if (expld.dataseg.phase == exp_dataseg_relro_adjust
&& (expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1)))
{
expld.dataseg.relro_end += expld.dataseg.pagesize - 1;
expld.dataseg.relro_end &= ~(expld.dataseg.pagesize - 1);
expld.result.value = (expld.dataseg.relro_end
- expld.result.value);
}
else
expld.result.value = lhs.value;
 
if (expld.dataseg.phase == exp_dataseg_align_seen)
expld.dataseg.phase = exp_dataseg_relro_seen;
}
else
expld.result.valid_p = FALSE;
break;
 
default:
FAIL ();
}
}
}
 
static void
fold_trinary (etree_type *tree)
{
exp_fold_tree_1 (tree->trinary.cond);
if (expld.result.valid_p)
exp_fold_tree_1 (expld.result.value
? tree->trinary.lhs
: tree->trinary.rhs);
}
 
static void
fold_name (etree_type *tree)
{
memset (&expld.result, 0, sizeof (expld.result));
 
switch (tree->type.node_code)
{
case SIZEOF_HEADERS:
if (expld.phase != lang_first_phase_enum)
{
bfd_vma hdr_size = 0;
/* Don't find the real header size if only marking sections;
The bfd function may cache incorrect data. */
if (expld.phase != lang_mark_phase_enum)
hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info);
new_number (hdr_size);
}
break;
 
case DEFINED:
if (expld.phase == lang_first_phase_enum)
lang_track_definedness (tree->name.name);
else
{
struct bfd_link_hash_entry *h;
int def_iteration
= lang_symbol_definition_iteration (tree->name.name);
 
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info,
tree->name.name,
FALSE, FALSE, TRUE);
new_number (h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_common)
&& (def_iteration == lang_statement_iteration
|| def_iteration == -1));
}
break;
 
case NAME:
if (expld.assign_name != NULL
&& strcmp (expld.assign_name, tree->name.name) == 0)
expld.assign_name = NULL;
if (expld.phase == lang_first_phase_enum)
;
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
new_rel_from_abs (expld.dot);
else
{
struct bfd_link_hash_entry *h;
 
h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
&link_info,
tree->name.name,
TRUE, FALSE, TRUE);
if (!h)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
else if (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
{
asection *output_section;
 
output_section = h->u.def.section->output_section;
if (output_section == NULL)
{
if (expld.phase == lang_mark_phase_enum)
new_rel (h->u.def.value, h->u.def.section);
else
einfo (_("%X%S: unresolvable symbol `%s'"
" referenced in expression\n"),
tree, tree->name.name);
}
else if (output_section == bfd_abs_section_ptr
&& (expld.section != bfd_abs_section_ptr
|| config.sane_expr))
new_number (h->u.def.value + h->u.def.section->output_offset);
else
new_rel (h->u.def.value + h->u.def.section->output_offset,
output_section);
}
else if (expld.phase == lang_final_phase_enum
|| (expld.phase != lang_mark_phase_enum
&& expld.assigning_to_dot))
einfo (_("%F%S: undefined symbol `%s'"
" referenced in expression\n"),
tree, tree->name.name);
else if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
bfd_link_add_undef (link_info.hash, h);
}
}
break;
 
case ADDR:
if (expld.phase != lang_first_phase_enum)
{
lang_output_section_statement_type *os;
 
os = lang_output_section_find (tree->name.name);
if (os == NULL)
{
if (expld.phase == lang_final_phase_enum)
einfo (_("%F%S: undefined section `%s'"
" referenced in expression\n"),
tree, tree->name.name);
}
else if (os->processed_vma)
new_rel (0, os->bfd_section);
}
break;
 
case LOADADDR:
if (expld.phase != lang_first_phase_enum)
{
lang_output_section_statement_type *os;
 
os = lang_output_section_find (tree->name.name);
if (os == NULL)
{
if (expld.phase == lang_final_phase_enum)
einfo (_("%F%S: undefined section `%s'"
" referenced in expression\n"),
tree, tree->name.name);
}
else if (os->processed_lma)
{
if (os->load_base == NULL)
new_abs (os->bfd_section->lma);
else
{
exp_fold_tree_1 (os->load_base);
if (expld.result.valid_p)
make_abs ();
}
}
}
break;
 
case SIZEOF:
case ALIGNOF:
if (expld.phase != lang_first_phase_enum)
{
lang_output_section_statement_type *os;
 
os = lang_output_section_find (tree->name.name);
if (os == NULL)
{
if (expld.phase == lang_final_phase_enum)
einfo (_("%F%S: undefined section `%s'"
" referenced in expression\n"),
tree, tree->name.name);
new_number (0);
}
else if (os->bfd_section != NULL)
{
bfd_vma val;
 
if (tree->type.node_code == SIZEOF)
val = (os->bfd_section->size
/ bfd_octets_per_byte (link_info.output_bfd));
else
val = (bfd_vma)1 << os->bfd_section->alignment_power;
 
new_number (val);
}
else
new_number (0);
}
break;
 
case LENGTH:
{
lang_memory_region_type *mem;
 
mem = lang_memory_region_lookup (tree->name.name, FALSE);
if (mem != NULL)
new_number (mem->length);
else
einfo (_("%F%S: undefined MEMORY region `%s'"
" referenced in expression\n"),
tree, tree->name.name);
}
break;
 
case ORIGIN:
if (expld.phase != lang_first_phase_enum)
{
lang_memory_region_type *mem;
 
mem = lang_memory_region_lookup (tree->name.name, FALSE);
if (mem != NULL)
new_rel_from_abs (mem->origin);
else
einfo (_("%F%S: undefined MEMORY region `%s'"
" referenced in expression\n"),
tree, tree->name.name);
}
break;
 
case CONSTANT:
if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
new_number (config.maxpagesize);
else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
new_number (config.commonpagesize);
else
einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
tree, tree->name.name);
break;
 
default:
FAIL ();
break;
}
}
 
static void
exp_fold_tree_1 (etree_type *tree)
{
if (tree == NULL)
{
memset (&expld.result, 0, sizeof (expld.result));
return;
}
 
switch (tree->type.node_class)
{
case etree_value:
if (expld.section == bfd_abs_section_ptr
&& !config.sane_expr)
new_abs (tree->value.value);
else
new_number (tree->value.value);
expld.result.str = tree->value.str;
break;
 
case etree_rel:
if (expld.phase != lang_first_phase_enum)
{
asection *output_section = tree->rel.section->output_section;
new_rel (tree->rel.value + tree->rel.section->output_offset,
output_section);
}
else
memset (&expld.result, 0, sizeof (expld.result));
break;
 
case etree_assert:
exp_fold_tree_1 (tree->assert_s.child);
if (expld.phase == lang_final_phase_enum && !expld.result.value)
einfo ("%X%P: %s\n", tree->assert_s.message);
break;
 
case etree_unary:
fold_unary (tree);
break;
 
case etree_binary:
fold_binary (tree);
break;
 
case etree_trinary:
fold_trinary (tree);
break;
 
case etree_assign:
case etree_provide:
case etree_provided:
if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
{
if (tree->type.node_class != etree_assign)
einfo (_("%F%S can not PROVIDE assignment to"
" location counter\n"), tree);
if (expld.phase != lang_first_phase_enum)
{
/* Notify the folder that this is an assignment to dot. */
expld.assigning_to_dot = TRUE;
exp_fold_tree_1 (tree->assign.src);
expld.assigning_to_dot = FALSE;
 
if (!expld.result.valid_p)
{
if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S invalid assignment to"
" location counter\n"), tree);
}
else if (expld.dotp == NULL)
einfo (_("%F%S assignment to location counter"
" invalid outside of SECTIONS\n"), tree);
 
/* After allocation, assignment to dot should not be
done inside an output section since allocation adds a
padding statement that effectively duplicates the
assignment. */
else if (expld.phase <= lang_allocating_phase_enum
|| expld.section == bfd_abs_section_ptr)
{
bfd_vma nextdot;
 
nextdot = expld.result.value;
if (expld.result.section != NULL)
nextdot += expld.result.section->vma;
else
nextdot += expld.section->vma;
if (nextdot < expld.dot
&& expld.section != bfd_abs_section_ptr)
einfo (_("%F%S cannot move location counter backwards"
" (from %V to %V)\n"),
tree, expld.dot, nextdot);
else
{
expld.dot = nextdot;
*expld.dotp = nextdot;
}
}
}
else
memset (&expld.result, 0, sizeof (expld.result));
}
else
{
struct bfd_link_hash_entry *h = NULL;
 
if (tree->type.node_class == etree_provide)
{
h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
FALSE, FALSE, TRUE);
if (h == NULL
|| (h->type != bfd_link_hash_new
&& h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common))
{
/* Do nothing. The symbol was never referenced, or was
defined by some object. */
break;
}
}
 
expld.assign_name = tree->assign.dst;
exp_fold_tree_1 (tree->assign.src);
/* expld.assign_name remaining equal to tree->assign.dst
below indicates the evaluation of tree->assign.src did
not use the value of tree->assign.dst. We don't allow
self assignment until the final phase for two reasons:
1) Expressions are evaluated multiple times. With
relaxation, the number of times may vary.
2) Section relative symbol values cannot be correctly
converted to absolute values, as is required by many
expressions, until final section sizing is complete. */
if ((expld.result.valid_p
&& (expld.phase == lang_final_phase_enum
|| expld.assign_name != NULL))
|| (expld.phase <= lang_mark_phase_enum
&& tree->type.node_class == etree_assign
&& tree->assign.defsym))
{
if (h == NULL)
{
h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
TRUE, FALSE, TRUE);
if (h == NULL)
einfo (_("%P%F:%s: hash creation failed\n"),
tree->assign.dst);
}
 
/* FIXME: Should we worry if the symbol is already
defined? */
lang_update_definedness (tree->assign.dst, h);
h->type = bfd_link_hash_defined;
h->u.def.value = expld.result.value;
if (expld.result.section == NULL)
expld.result.section = expld.section;
h->u.def.section = expld.result.section;
if (tree->type.node_class == etree_provide)
tree->type.node_class = etree_provided;
 
/* Copy the symbol type if this is a simple assignment of
one symbol to another. This could be more general
(e.g. a ?: operator with NAMEs in each branch). */
if (tree->assign.src->type.node_class == etree_name)
{
struct bfd_link_hash_entry *hsrc;
 
hsrc = bfd_link_hash_lookup (link_info.hash,
tree->assign.src->name.name,
FALSE, FALSE, TRUE);
if (hsrc)
bfd_copy_link_hash_symbol_type (link_info.output_bfd, h,
hsrc);
}
}
else if (expld.phase == lang_final_phase_enum)
{
h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
FALSE, FALSE, TRUE);
if (h != NULL
&& h->type == bfd_link_hash_new)
h->type = bfd_link_hash_undefined;
}
expld.assign_name = NULL;
}
break;
 
case etree_name:
fold_name (tree);
break;
 
default:
FAIL ();
memset (&expld.result, 0, sizeof (expld.result));
break;
}
}
 
void
exp_fold_tree (etree_type *tree, asection *current_section, bfd_vma *dotp)
{
expld.dot = *dotp;
expld.dotp = dotp;
expld.section = current_section;
exp_fold_tree_1 (tree);
}
 
void
exp_fold_tree_no_dot (etree_type *tree)
{
expld.dot = 0;
expld.dotp = NULL;
expld.section = bfd_abs_section_ptr;
exp_fold_tree_1 (tree);
}
 
etree_type *
exp_binop (int code, etree_type *lhs, etree_type *rhs)
{
etree_type value, *new_e;
 
value.type.node_code = code;
value.type.filename = lhs->type.filename;
value.type.lineno = lhs->type.lineno;
value.binary.lhs = lhs;
value.binary.rhs = rhs;
value.type.node_class = etree_binary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
return exp_intop (expld.result.value);
 
new_e = (etree_type *) stat_alloc (sizeof (new_e->binary));
memcpy (new_e, &value, sizeof (new_e->binary));
return new_e;
}
 
etree_type *
exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
{
etree_type value, *new_e;
 
value.type.node_code = code;
value.type.filename = cond->type.filename;
value.type.lineno = cond->type.lineno;
value.trinary.lhs = lhs;
value.trinary.cond = cond;
value.trinary.rhs = rhs;
value.type.node_class = etree_trinary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
return exp_intop (expld.result.value);
 
new_e = (etree_type *) stat_alloc (sizeof (new_e->trinary));
memcpy (new_e, &value, sizeof (new_e->trinary));
return new_e;
}
 
etree_type *
exp_unop (int code, etree_type *child)
{
etree_type value, *new_e;
 
value.unary.type.node_code = code;
value.unary.type.filename = child->type.filename;
value.unary.type.lineno = child->type.lineno;
value.unary.child = child;
value.unary.type.node_class = etree_unary;
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
return exp_intop (expld.result.value);
 
new_e = (etree_type *) stat_alloc (sizeof (new_e->unary));
memcpy (new_e, &value, sizeof (new_e->unary));
return new_e;
}
 
etree_type *
exp_nameop (int code, const char *name)
{
etree_type value, *new_e;
 
value.name.type.node_code = code;
value.name.type.filename = ldlex_filename ();
value.name.type.lineno = lineno;
value.name.name = name;
value.name.type.node_class = etree_name;
 
exp_fold_tree_no_dot (&value);
if (expld.result.valid_p)
return exp_intop (expld.result.value);
 
new_e = (etree_type *) stat_alloc (sizeof (new_e->name));
memcpy (new_e, &value, sizeof (new_e->name));
return new_e;
 
}
 
static etree_type *
exp_assop (const char *dst,
etree_type *src,
enum node_tree_enum class,
bfd_boolean defsym,
bfd_boolean hidden)
{
etree_type *n;
 
n = (etree_type *) stat_alloc (sizeof (n->assign));
n->assign.type.node_code = '=';
n->assign.type.filename = src->type.filename;
n->assign.type.lineno = src->type.lineno;
n->assign.type.node_class = class;
n->assign.src = src;
n->assign.dst = dst;
n->assign.defsym = defsym;
n->assign.hidden = hidden;
return n;
}
 
/* Handle linker script assignments and HIDDEN. */
 
etree_type *
exp_assign (const char *dst, etree_type *src, bfd_boolean hidden)
{
return exp_assop (dst, src, etree_assign, FALSE, hidden);
}
 
/* Handle --defsym command-line option. */
 
etree_type *
exp_defsym (const char *dst, etree_type *src)
{
return exp_assop (dst, src, etree_assign, TRUE, FALSE);
}
 
/* Handle PROVIDE. */
 
etree_type *
exp_provide (const char *dst, etree_type *src, bfd_boolean hidden)
{
return exp_assop (dst, src, etree_provide, FALSE, hidden);
}
 
/* Handle ASSERT. */
 
etree_type *
exp_assert (etree_type *exp, const char *message)
{
etree_type *n;
 
n = (etree_type *) stat_alloc (sizeof (n->assert_s));
n->assert_s.type.node_code = '!';
n->assert_s.type.filename = exp->type.filename;
n->assert_s.type.lineno = exp->type.lineno;
n->assert_s.type.node_class = etree_assert;
n->assert_s.child = exp;
n->assert_s.message = message;
return n;
}
 
void
exp_print_tree (etree_type *tree)
{
bfd_boolean function_like;
 
if (config.map_file == NULL)
config.map_file = stderr;
 
if (tree == NULL)
{
minfo ("NULL TREE\n");
return;
}
 
switch (tree->type.node_class)
{
case etree_value:
minfo ("0x%v", tree->value.value);
return;
case etree_rel:
if (tree->rel.section->owner != NULL)
minfo ("%B:", tree->rel.section->owner);
minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
return;
case etree_assign:
fputs (tree->assign.dst, config.map_file);
exp_print_token (tree->type.node_code, TRUE);
exp_print_tree (tree->assign.src);
break;
case etree_provide:
case etree_provided:
fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
exp_print_tree (tree->assign.src);
fputc (')', config.map_file);
break;
case etree_binary:
function_like = FALSE;
switch (tree->type.node_code)
{
case MAX_K:
case MIN_K:
case ALIGN_K:
case DATA_SEGMENT_ALIGN:
case DATA_SEGMENT_RELRO_END:
function_like = TRUE;
break;
case SEGMENT_START:
/* Special handling because arguments are in reverse order and
the segment name is quoted. */
exp_print_token (tree->type.node_code, FALSE);
fputs (" (\"", config.map_file);
exp_print_tree (tree->binary.rhs);
fputs ("\", ", config.map_file);
exp_print_tree (tree->binary.lhs);
fputc (')', config.map_file);
return;
}
if (function_like)
{
exp_print_token (tree->type.node_code, FALSE);
fputc (' ', config.map_file);
}
fputc ('(', config.map_file);
exp_print_tree (tree->binary.lhs);
if (function_like)
fprintf (config.map_file, ", ");
else
exp_print_token (tree->type.node_code, TRUE);
exp_print_tree (tree->binary.rhs);
fputc (')', config.map_file);
break;
case etree_trinary:
exp_print_tree (tree->trinary.cond);
fputc ('?', config.map_file);
exp_print_tree (tree->trinary.lhs);
fputc (':', config.map_file);
exp_print_tree (tree->trinary.rhs);
break;
case etree_unary:
exp_print_token (tree->unary.type.node_code, FALSE);
if (tree->unary.child)
{
fprintf (config.map_file, " (");
exp_print_tree (tree->unary.child);
fputc (')', config.map_file);
}
break;
 
case etree_assert:
fprintf (config.map_file, "ASSERT (");
exp_print_tree (tree->assert_s.child);
fprintf (config.map_file, ", %s)", tree->assert_s.message);
break;
 
case etree_name:
if (tree->type.node_code == NAME)
fputs (tree->name.name, config.map_file);
else
{
exp_print_token (tree->type.node_code, FALSE);
if (tree->name.name)
fprintf (config.map_file, " (%s)", tree->name.name);
}
break;
default:
FAIL ();
break;
}
}
 
bfd_vma
exp_get_vma (etree_type *tree, bfd_vma def, char *name)
{
if (tree != NULL)
{
exp_fold_tree_no_dot (tree);
if (expld.result.valid_p)
return expld.result.value;
else if (name != NULL && expld.phase != lang_mark_phase_enum)
einfo (_("%F%S: nonconstant expression for %s\n"),
tree, name);
}
return def;
}
 
int
exp_get_value_int (etree_type *tree, int def, char *name)
{
return exp_get_vma (tree, def, name);
}
 
fill_type *
exp_get_fill (etree_type *tree, fill_type *def, char *name)
{
fill_type *fill;
size_t len;
unsigned int val;
 
if (tree == NULL)
return def;
 
exp_fold_tree_no_dot (tree);
if (!expld.result.valid_p)
{
if (name != NULL && expld.phase != lang_mark_phase_enum)
einfo (_("%F%S: nonconstant expression for %s\n"),
tree, name);
return def;
}
 
if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
{
unsigned char *dst;
unsigned char *s;
fill = (fill_type *) xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
fill->size = (len + 1) / 2;
dst = fill->data;
s = (unsigned char *) expld.result.str;
val = 0;
do
{
unsigned int digit;
 
digit = *s++ - '0';
if (digit > 9)
digit = (digit - 'A' + '0' + 10) & 0xf;
val <<= 4;
val += digit;
--len;
if ((len & 1) == 0)
{
*dst++ = val;
val = 0;
}
}
while (len != 0);
}
else
{
fill = (fill_type *) xmalloc (4 + sizeof (*fill) - 1);
val = expld.result.value;
fill->data[0] = (val >> 24) & 0xff;
fill->data[1] = (val >> 16) & 0xff;
fill->data[2] = (val >> 8) & 0xff;
fill->data[3] = (val >> 0) & 0xff;
fill->size = 4;
}
return fill;
}
 
bfd_vma
exp_get_abs_int (etree_type *tree, int def, char *name)
{
if (tree != NULL)
{
exp_fold_tree_no_dot (tree);
 
if (expld.result.valid_p)
{
if (expld.result.section != NULL)
expld.result.value += expld.result.section->vma;
return expld.result.value;
}
else if (name != NULL && expld.phase != lang_mark_phase_enum)
{
einfo (_("%F%S: nonconstant expression for %s\n"),
tree, name);
}
}
return def;
}
 
static bfd_vma
align_n (bfd_vma value, bfd_vma align)
{
if (align <= 1)
return value;
 
value = (value + align - 1) / align;
return value * align;
}
/contrib/toolchain/binutils/ld/ldexp.h
0,0 → 1,226
/* ldexp.h -
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2007, 2011, 2012 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDEXP_H
#define LDEXP_H
 
/* The result of an expression tree */
typedef struct {
bfd_vma value;
char *str;
asection *section;
bfd_boolean valid_p;
} etree_value_type;
 
enum node_tree_enum {
etree_binary,
etree_trinary,
etree_unary,
etree_name,
etree_assign,
etree_provide,
etree_provided,
etree_value,
etree_assert,
etree_rel
};
 
typedef struct {
int node_code;
unsigned int lineno;
const char *filename;
enum node_tree_enum node_class;
} node_type;
 
typedef union etree_union {
node_type type;
struct {
node_type type;
union etree_union *lhs;
union etree_union *rhs;
} binary;
struct {
node_type type;
union etree_union *cond;
union etree_union *lhs;
union etree_union *rhs;
} trinary;
struct {
node_type type;
const char *dst;
union etree_union *src;
bfd_boolean defsym;
bfd_boolean hidden;
} assign;
struct {
node_type type;
union etree_union *child;
} unary;
struct {
node_type type;
const char *name;
} name;
struct {
node_type type;
bfd_vma value;
char *str;
} value;
struct {
node_type type;
asection *section;
bfd_vma value;
} rel;
struct {
node_type type;
union etree_union *child;
const char *message;
} assert_s;
} etree_type;
 
/* Expression evaluation control. */
typedef enum
{
/* Parsing linker script. Will only return "valid" for expressions
that evaluate to a constant. */
lang_first_phase_enum,
/* Prior to section sizing. */
lang_mark_phase_enum,
/* During section sizing. */
lang_allocating_phase_enum,
/* During assignment of symbol values when relaxation in progress. */
lang_assigning_phase_enum,
/* Final assignment of symbol values. */
lang_final_phase_enum
} lang_phase_type;
 
union lang_statement_union;
 
enum phase_enum {
/* We step through the first four states here as we see the
associated linker script tokens. */
exp_dataseg_none,
exp_dataseg_align_seen,
exp_dataseg_relro_seen,
exp_dataseg_end_seen,
/* The last three states are final, and affect the value returned
by DATA_SEGMENT_ALIGN. */
exp_dataseg_relro_adjust,
exp_dataseg_adjust,
exp_dataseg_done
};
 
enum relro_enum {
exp_dataseg_relro_none,
exp_dataseg_relro_start,
exp_dataseg_relro_end,
};
 
struct ldexp_control {
/* Modify expression evaluation depending on this. */
lang_phase_type phase;
 
/* Principally used for diagnostics. */
bfd_boolean assigning_to_dot;
/* If evaluating an assignment, the destination. Cleared if an
etree_name NAME matches this, to signal a self-assignment.
Note that an etree_name DEFINED does not clear this field, nor
does the false branch of a trinary expression. */
const char *assign_name;
 
/* Working results. */
etree_value_type result;
bfd_vma dot;
 
/* Current dot and section passed to ldexp folder. */
bfd_vma *dotp;
asection *section;
 
/* State machine and results for DATASEG. */
struct {
enum phase_enum phase;
 
bfd_vma base, min_base, relro_end, end, pagesize, maxpagesize;
 
enum relro_enum relro;
 
union lang_statement_union *relro_start_stat;
union lang_statement_union *relro_end_stat;
} dataseg;
};
 
extern struct ldexp_control expld;
 
/* A maps from a segment name to a base address. */
typedef struct segment_struct {
/* The next segment in the linked list. */
struct segment_struct *next;
/* The name of the sgement. */
const char *name;
/* The base address for the segment. */
bfd_vma value;
/* True if a SEGMENT_START directive corresponding to this segment
has been seen. */
bfd_boolean used;
} segment_type;
 
/* The segments specified by the user on the command-line. */
extern segment_type *segments;
 
typedef struct _fill_type fill_type;
 
etree_type *exp_intop
(bfd_vma);
etree_type *exp_bigintop
(bfd_vma, char *);
etree_type *exp_relop
(asection *, bfd_vma);
void exp_fold_tree
(etree_type *, asection *, bfd_vma *);
void exp_fold_tree_no_dot
(etree_type *);
etree_type *exp_binop
(int, etree_type *, etree_type *);
etree_type *exp_trinop
(int,etree_type *, etree_type *, etree_type *);
etree_type *exp_unop
(int, etree_type *);
etree_type *exp_nameop
(int, const char *);
etree_type *exp_assign
(const char *, etree_type *, bfd_boolean);
etree_type *exp_defsym
(const char *, etree_type *);
etree_type *exp_provide
(const char *, etree_type *, bfd_boolean);
etree_type *exp_assert
(etree_type *, const char *);
void exp_print_tree
(etree_type *);
bfd_vma exp_get_vma
(etree_type *, bfd_vma, char *);
int exp_get_value_int
(etree_type *, int, char *);
fill_type *exp_get_fill
(etree_type *, fill_type *, char *);
bfd_vma exp_get_abs_int
(etree_type *, int, char *);
 
#endif
/contrib/toolchain/binutils/ld/ldfile.c
0,0 → 1,672
/* Linker file opening and searching.
Copyright 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "safe-ctype.h"
#include "ld.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldmain.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldemul.h"
#include "libiberty.h"
#include "filenames.h"
#ifdef ENABLE_PLUGINS
#include "plugin-api.h"
#include "plugin.h"
#endif /* ENABLE_PLUGINS */
 
bfd_boolean ldfile_assumed_script = FALSE;
const char * ldfile_output_machine_name = "";
unsigned long ldfile_output_machine;
enum bfd_architecture ldfile_output_architecture;
search_dirs_type * search_head;
 
#ifdef VMS
static char * slash = "";
#else
#if defined (_WIN32) && ! defined (__CYGWIN32__)
static char * slash = "\\";
#else
static char * slash = "/";
#endif
#endif
 
typedef struct search_arch
{
char *name;
struct search_arch *next;
} search_arch_type;
 
static search_dirs_type **search_tail_ptr = &search_head;
static search_arch_type *search_arch_head;
static search_arch_type **search_arch_tail_ptr = &search_arch_head;
 
/* Test whether a pathname, after canonicalization, is the same or a
sub-directory of the sysroot directory. */
 
static bfd_boolean
is_sysrooted_pathname (const char *name)
{
char *realname;
int len;
bfd_boolean result;
 
if (ld_canon_sysroot == NULL)
return FALSE;
 
realname = lrealpath (name);
len = strlen (realname);
result = FALSE;
if (len > ld_canon_sysroot_len
&& IS_DIR_SEPARATOR (realname[ld_canon_sysroot_len]))
{
realname[ld_canon_sysroot_len] = '\0';
result = FILENAME_CMP (ld_canon_sysroot, realname) == 0;
}
 
free (realname);
return result;
}
 
/* Adds NAME to the library search path.
Makes a copy of NAME using xmalloc(). */
 
void
ldfile_add_library_path (const char *name, bfd_boolean cmdline)
{
search_dirs_type *new_dirs;
 
if (!cmdline && config.only_cmd_line_lib_dirs)
return;
 
new_dirs = (search_dirs_type *) xmalloc (sizeof (search_dirs_type));
new_dirs->next = NULL;
new_dirs->cmdline = cmdline;
*search_tail_ptr = new_dirs;
search_tail_ptr = &new_dirs->next;
 
/* If a directory is marked as honoring sysroot, prepend the sysroot path
now. */
if (name[0] == '=')
new_dirs->name = concat (ld_sysroot, name + 1, (const char *) NULL);
else
new_dirs->name = xstrdup (name);
}
 
/* Try to open a BFD for a lang_input_statement. */
 
bfd_boolean
ldfile_try_open_bfd (const char *attempt,
lang_input_statement_type *entry)
{
entry->the_bfd = bfd_openr (attempt, entry->target);
 
if (verbose)
{
if (entry->the_bfd == NULL)
info_msg (_("attempt to open %s failed\n"), attempt);
else
info_msg (_("attempt to open %s succeeded\n"), attempt);
}
 
if (entry->the_bfd == NULL)
{
if (bfd_get_error () == bfd_error_invalid_target)
einfo (_("%F%P: invalid BFD target `%s'\n"), entry->target);
return FALSE;
}
 
/* Linker needs to decompress sections. */
entry->the_bfd->flags |= BFD_DECOMPRESS;
 
/* If we are searching for this file, see if the architecture is
compatible with the output file. If it isn't, keep searching.
If we can't open the file as an object file, stop the search
here. If we are statically linking, ensure that we don't link
a dynamic object.
 
In the code below, it's OK to exit early if the check fails,
closing the checked BFD and returning FALSE, but if the BFD
checks out compatible, do not exit early returning TRUE, or
the plugins will not get a chance to claim the file. */
 
if (entry->flags.search_dirs || !entry->flags.dynamic)
{
bfd *check;
 
if (bfd_check_format (entry->the_bfd, bfd_archive))
check = bfd_openr_next_archived_file (entry->the_bfd, NULL);
else
check = entry->the_bfd;
 
if (check != NULL)
{
if (! bfd_check_format (check, bfd_object))
{
if (check == entry->the_bfd
&& entry->flags.search_dirs
&& bfd_get_error () == bfd_error_file_not_recognized
&& ! ldemul_unrecognized_file (entry))
{
int token, skip = 0;
char *arg, *arg1, *arg2, *arg3;
extern FILE *yyin;
 
/* Try to interpret the file as a linker script. */
ldfile_open_command_file (attempt);
 
ldfile_assumed_script = TRUE;
parser_input = input_selected;
ldlex_both ();
token = INPUT_SCRIPT;
while (token != 0)
{
switch (token)
{
case OUTPUT_FORMAT:
if ((token = yylex ()) != '(')
continue;
if ((token = yylex ()) != NAME)
continue;
arg1 = yylval.name;
arg2 = NULL;
arg3 = NULL;
token = yylex ();
if (token == ',')
{
if ((token = yylex ()) != NAME)
{
free (arg1);
continue;
}
arg2 = yylval.name;
if ((token = yylex ()) != ','
|| (token = yylex ()) != NAME)
{
free (arg1);
free (arg2);
continue;
}
arg3 = yylval.name;
token = yylex ();
}
if (token == ')')
{
switch (command_line.endian)
{
default:
case ENDIAN_UNSET:
arg = arg1; break;
case ENDIAN_BIG:
arg = arg2 ? arg2 : arg1; break;
case ENDIAN_LITTLE:
arg = arg3 ? arg3 : arg1; break;
}
if (strcmp (arg, lang_get_output_target ()) != 0)
skip = 1;
}
free (arg1);
if (arg2) free (arg2);
if (arg3) free (arg3);
break;
case NAME:
case LNAME:
case VERS_IDENTIFIER:
case VERS_TAG:
free (yylval.name);
break;
case INT:
if (yylval.bigint.str)
free (yylval.bigint.str);
break;
}
token = yylex ();
}
ldlex_popstate ();
ldfile_assumed_script = FALSE;
fclose (yyin);
yyin = NULL;
if (skip)
{
if (command_line.warn_search_mismatch)
einfo (_("%P: skipping incompatible %s "
"when searching for %s\n"),
attempt, entry->local_sym_name);
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
return FALSE;
}
}
goto success;
}
 
if (!entry->flags.dynamic && (entry->the_bfd->flags & DYNAMIC) != 0)
{
einfo (_("%F%P: attempted static link of dynamic object `%s'\n"),
attempt);
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
return FALSE;
}
 
if (entry->flags.search_dirs
&& !bfd_arch_get_compatible (check, link_info.output_bfd,
command_line.accept_unknown_input_arch)
/* XCOFF archives can have 32 and 64 bit objects. */
&& ! (bfd_get_flavour (check) == bfd_target_xcoff_flavour
&& bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour
&& bfd_check_format (entry->the_bfd, bfd_archive)))
{
if (command_line.warn_search_mismatch)
einfo (_("%P: skipping incompatible %s "
"when searching for %s\n"),
attempt, entry->local_sym_name);
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
return FALSE;
}
}
}
success:
#ifdef ENABLE_PLUGINS
/* If plugins are active, they get first chance to claim
any successfully-opened input file. We skip archives
here; the plugin wants us to offer it the individual
members when we enumerate them, not the whole file. We
also ignore corefiles, because that's just weird. It is
a needed side-effect of calling bfd_check_format with
bfd_object that it sets the bfd's arch and mach, which
will be needed when and if we want to bfd_create a new
one using this one as a template. */
if (bfd_check_format (entry->the_bfd, bfd_object)
&& plugin_active_plugins_p ()
&& !no_more_claiming)
{
int fd = open (attempt, O_RDONLY | O_BINARY);
if (fd >= 0)
{
struct ld_plugin_input_file file;
 
file.name = attempt;
file.offset = 0;
file.filesize = lseek (fd, 0, SEEK_END);
file.fd = fd;
plugin_maybe_claim (&file, entry);
}
}
#endif /* ENABLE_PLUGINS */
 
/* It opened OK, the format checked out, and the plugins have had
their chance to claim it, so this is success. */
return TRUE;
}
 
/* Search for and open the file specified by ENTRY. If it is an
archive, use ARCH, LIB and SUFFIX to modify the file name. */
 
bfd_boolean
ldfile_open_file_search (const char *arch,
lang_input_statement_type *entry,
const char *lib,
const char *suffix)
{
search_dirs_type *search;
 
/* If this is not an archive, try to open it in the current
directory first. */
if (! entry->flags.maybe_archive)
{
if (entry->flags.sysrooted && IS_ABSOLUTE_PATH (entry->filename))
{
char *name = concat (ld_sysroot, entry->filename,
(const char *) NULL);
if (ldfile_try_open_bfd (name, entry))
{
entry->filename = name;
return TRUE;
}
free (name);
}
else if (ldfile_try_open_bfd (entry->filename, entry))
return TRUE;
 
if (IS_ABSOLUTE_PATH (entry->filename))
return FALSE;
}
 
for (search = search_head; search != NULL; search = search->next)
{
char *string;
 
if (entry->flags.dynamic && ! link_info.relocatable)
{
if (ldemul_open_dynamic_archive (arch, search, entry))
return TRUE;
}
 
if (entry->flags.maybe_archive)
string = concat (search->name, slash, lib, entry->filename,
arch, suffix, (const char *) NULL);
else
string = concat (search->name, slash, entry->filename,
(const char *) 0);
 
if (ldfile_try_open_bfd (string, entry))
{
entry->filename = string;
return TRUE;
}
 
free (string);
}
 
return FALSE;
}
 
/* Open the input file specified by ENTRY.
PR 4437: Do not stop on the first missing file, but
continue processing other input files in case there
are more errors to report. */
 
void
ldfile_open_file (lang_input_statement_type *entry)
{
if (entry->the_bfd != NULL)
return;
 
printf("%s %s\n", __FUNCTION__, entry->filename);
 
if (! entry->flags.search_dirs)
{
if (ldfile_try_open_bfd (entry->filename, entry))
return;
 
if (filename_cmp (entry->filename, entry->local_sym_name) != 0)
einfo (_("%P: cannot find %s (%s): %E\n"),
entry->filename, entry->local_sym_name);
else
einfo (_("%P: cannot find %s: %E\n"), entry->local_sym_name);
 
entry->flags.missing_file = TRUE;
input_flags.missing_file = TRUE;
}
else
{
search_arch_type *arch;
bfd_boolean found = FALSE;
 
/* Try to open <filename><suffix> or lib<filename><suffix>.a */
for (arch = search_arch_head; arch != NULL; arch = arch->next)
{
found = ldfile_open_file_search (arch->name, entry, "lib", ".a");
if (found)
break;
#ifdef VMS
found = ldfile_open_file_search (arch->name, entry, ":lib", ".a");
if (found)
break;
#endif
found = ldemul_find_potential_libraries (arch->name, entry);
if (found)
break;
}
 
/* If we have found the file, we don't need to search directories
again. */
if (found)
entry->flags.search_dirs = FALSE;
else
{
if (entry->flags.sysrooted
&& ld_sysroot
&& IS_ABSOLUTE_PATH (entry->local_sym_name))
einfo (_("%P: cannot find %s inside %s\n"),
entry->local_sym_name, ld_sysroot);
else
einfo (_("%P: cannot find %s\n"), entry->local_sym_name);
entry->flags.missing_file = TRUE;
input_flags.missing_file = TRUE;
}
}
}
 
/* Try to open NAME. */
 
static FILE *
try_open (const char *name, bfd_boolean *sysrooted)
{
FILE *result;
 
result = fopen (name, "r");
 
if (result != NULL)
*sysrooted = is_sysrooted_pathname (name);
 
if (verbose)
{
if (result == NULL)
info_msg (_("cannot find script file %s\n"), name);
else
info_msg (_("opened script file %s\n"), name);
}
 
return result;
}
 
/* Return TRUE iff directory DIR contains an "ldscripts" subdirectory. */
 
static bfd_boolean
check_for_scripts_dir (char *dir)
{
char *buf;
struct stat s;
bfd_boolean res;
 
buf = concat (dir, "/ldscripts", (const char *) NULL);
res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
free (buf);
return res;
}
 
/* Return the default directory for finding script files.
We look for the "ldscripts" directory in:
 
SCRIPTDIR (passed from Makefile)
(adjusted according to the current location of the binary)
the dir where this program is (for using it from the build tree). */
 
static char *
find_scripts_dir (void)
{
char *dir;
 
dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
if (dir)
{
if (check_for_scripts_dir (dir))
return dir;
free (dir);
}
 
dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
if (dir)
{
if (check_for_scripts_dir (dir))
return dir;
free (dir);
}
 
/* Look for "ldscripts" in the dir where our binary is. */
dir = make_relative_prefix (program_name, ".", ".");
if (dir)
{
if (check_for_scripts_dir (dir))
return dir;
free (dir);
}
 
return NULL;
}
 
/* If DEFAULT_ONLY is false, try to open NAME; if that fails, look for
it in directories specified with -L, then in the default script
directory. If DEFAULT_ONLY is true, the search is restricted to
the default script location. */
 
static FILE *
ldfile_find_command_file (const char *name,
bfd_boolean default_only,
bfd_boolean *sysrooted)
{
search_dirs_type *search;
FILE *result = NULL;
char *path;
static search_dirs_type *script_search;
 
if (!default_only)
{
/* First try raw name. */
result = try_open (name, sysrooted);
if (result != NULL)
return result;
}
 
if (!script_search)
{
char *script_dir = find_scripts_dir ();
if (script_dir)
{
search_dirs_type **save_tail_ptr = search_tail_ptr;
search_tail_ptr = &script_search;
ldfile_add_library_path (script_dir, TRUE);
search_tail_ptr = save_tail_ptr;
}
}
 
/* Temporarily append script_search to the path list so that the
paths specified with -L will be searched first. */
*search_tail_ptr = script_search;
 
/* Try now prefixes. */
for (search = default_only ? script_search : search_head;
search != NULL;
search = search->next)
{
path = concat (search->name, slash, name, (const char *) NULL);
result = try_open (path, sysrooted);
free (path);
if (result)
break;
}
 
/* Restore the original path list. */
*search_tail_ptr = NULL;
 
return result;
}
 
/* Open command file NAME. */
 
static void
ldfile_open_command_file_1 (const char *name, bfd_boolean default_only)
{
FILE *ldlex_input_stack;
bfd_boolean sysrooted;
 
ldlex_input_stack = ldfile_find_command_file (name, default_only, &sysrooted);
 
if (ldlex_input_stack == NULL)
{
bfd_set_error (bfd_error_system_call);
einfo (_("%P%F: cannot open linker script file %s: %E\n"), name);
return;
}
 
lex_push_file (ldlex_input_stack, name, sysrooted);
 
lineno = 1;
 
saved_script_handle = ldlex_input_stack;
}
 
/* Open command file NAME in the current directory, -L directories,
the default script location, in that order. */
 
void
ldfile_open_command_file (const char *name)
{
ldfile_open_command_file_1 (name, FALSE);
}
 
/* Open command file NAME at the default script location. */
 
void
ldfile_open_default_command_file (const char *name)
{
ldfile_open_command_file_1 (name, TRUE);
}
 
void
ldfile_add_arch (const char *in_name)
{
char *name = xstrdup (in_name);
search_arch_type *new_arch = (search_arch_type *)
xmalloc (sizeof (search_arch_type));
 
ldfile_output_machine_name = in_name;
 
new_arch->name = name;
new_arch->next = NULL;
while (*name)
{
*name = TOLOWER (*name);
name++;
}
*search_arch_tail_ptr = new_arch;
search_arch_tail_ptr = &new_arch->next;
 
}
 
/* Set the output architecture. */
 
void
ldfile_set_output_arch (const char *string, enum bfd_architecture defarch)
{
const bfd_arch_info_type *arch = bfd_scan_arch (string);
 
if (arch)
{
ldfile_output_architecture = arch->arch;
ldfile_output_machine = arch->mach;
ldfile_output_machine_name = arch->printable_name;
}
else if (defarch != bfd_arch_unknown)
ldfile_output_architecture = defarch;
else
einfo (_("%P%F: cannot represent machine `%s'\n"), string);
}
/contrib/toolchain/binutils/ld/ldfile.h
0,0 → 1,62
/* ldfile.h -
Copyright 1991, 1992, 1993, 1994, 1995, 2000, 2002, 2003, 2004, 2005,
2007, 2012 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDFILE_H
#define LDFILE_H
 
extern bfd_boolean ldfile_assumed_script;
extern unsigned long ldfile_output_machine;
extern enum bfd_architecture ldfile_output_architecture;
extern const char *ldfile_output_machine_name;
 
/* Structure used to hold the list of directories to search for
libraries. */
 
typedef struct search_dirs {
/* Next directory on list. */
struct search_dirs *next;
/* Name of directory. */
const char *name;
/* TRUE if this is from the command line. */
bfd_boolean cmdline;
} search_dirs_type;
 
extern search_dirs_type *search_head;
 
extern void ldfile_add_arch
(const char *);
extern void ldfile_add_library_path
(const char *, bfd_boolean cmdline);
extern void ldfile_open_command_file
(const char *name);
extern void ldfile_open_default_command_file
(const char *name);
extern void ldfile_open_file
(struct lang_input_statement_struct *);
extern bfd_boolean ldfile_try_open_bfd
(const char *, struct lang_input_statement_struct *);
extern void ldfile_set_output_arch
(const char *, enum bfd_architecture);
extern bfd_boolean ldfile_open_file_search
(const char *arch, struct lang_input_statement_struct *,
const char *lib, const char *suffix);
 
#endif
/contrib/toolchain/binutils/ld/ldgram.c
0,0 → 1,4717
/* A Bison parser, made by GNU Bison 2.3. */
 
/* Skeleton implementation for Bison's Yacc-like parsers in C
 
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
 
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, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
 
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
 
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
 
/* C LALR(1) parser skeleton written by Richard Stallman, by
simplifying the original so-called "semantic" parser. */
 
/* All symbols defined below should begin with yy or YY, to avoid
infringing on user name space. This should be done even for local
variables, as they might otherwise be expanded by user macros.
There are some unavoidable exceptions within include files to
define necessary library symbols; they are noted "INFRINGES ON
USER NAME SPACE" below. */
 
/* Identify Bison output. */
#define YYBISON 1
 
/* Bison version. */
#define YYBISON_VERSION "2.3"
 
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
 
/* Pure parsers. */
#define YYPURE 0
 
/* Using locations. */
#define YYLSP_NEEDED 0
 
 
 
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
INT = 258,
NAME = 259,
LNAME = 260,
OREQ = 261,
ANDEQ = 262,
RSHIFTEQ = 263,
LSHIFTEQ = 264,
DIVEQ = 265,
MULTEQ = 266,
MINUSEQ = 267,
PLUSEQ = 268,
OROR = 269,
ANDAND = 270,
NE = 271,
EQ = 272,
GE = 273,
LE = 274,
RSHIFT = 275,
LSHIFT = 276,
UNARY = 277,
END = 278,
ALIGN_K = 279,
BLOCK = 280,
BIND = 281,
QUAD = 282,
SQUAD = 283,
LONG = 284,
SHORT = 285,
BYTE = 286,
SECTIONS = 287,
PHDRS = 288,
INSERT_K = 289,
AFTER = 290,
BEFORE = 291,
DATA_SEGMENT_ALIGN = 292,
DATA_SEGMENT_RELRO_END = 293,
DATA_SEGMENT_END = 294,
SORT_BY_NAME = 295,
SORT_BY_ALIGNMENT = 296,
SORT_NONE = 297,
SORT_BY_INIT_PRIORITY = 298,
SIZEOF_HEADERS = 299,
OUTPUT_FORMAT = 300,
FORCE_COMMON_ALLOCATION = 301,
OUTPUT_ARCH = 302,
INHIBIT_COMMON_ALLOCATION = 303,
SEGMENT_START = 304,
INCLUDE = 305,
MEMORY = 306,
REGION_ALIAS = 307,
LD_FEATURE = 308,
NOLOAD = 309,
DSECT = 310,
COPY = 311,
INFO = 312,
OVERLAY = 313,
DEFINED = 314,
TARGET_K = 315,
SEARCH_DIR = 316,
MAP = 317,
ENTRY = 318,
NEXT = 319,
SIZEOF = 320,
ALIGNOF = 321,
ADDR = 322,
LOADADDR = 323,
MAX_K = 324,
MIN_K = 325,
STARTUP = 326,
HLL = 327,
SYSLIB = 328,
FLOAT = 329,
NOFLOAT = 330,
NOCROSSREFS = 331,
ORIGIN = 332,
FILL = 333,
LENGTH = 334,
CREATE_OBJECT_SYMBOLS = 335,
INPUT = 336,
GROUP = 337,
OUTPUT = 338,
CONSTRUCTORS = 339,
ALIGNMOD = 340,
AT = 341,
SUBALIGN = 342,
HIDDEN = 343,
PROVIDE = 344,
PROVIDE_HIDDEN = 345,
AS_NEEDED = 346,
CHIP = 347,
LIST = 348,
SECT = 349,
ABSOLUTE = 350,
LOAD = 351,
NEWLINE = 352,
ENDWORD = 353,
ORDER = 354,
NAMEWORD = 355,
ASSERT_K = 356,
LOG2CEIL = 357,
FORMAT = 358,
PUBLIC = 359,
DEFSYMEND = 360,
BASE = 361,
ALIAS = 362,
TRUNCATE = 363,
REL = 364,
INPUT_SCRIPT = 365,
INPUT_MRI_SCRIPT = 366,
INPUT_DEFSYM = 367,
CASE = 368,
EXTERN = 369,
START = 370,
VERS_TAG = 371,
VERS_IDENTIFIER = 372,
GLOBAL = 373,
LOCAL = 374,
VERSIONK = 375,
INPUT_VERSION_SCRIPT = 376,
KEEP = 377,
ONLY_IF_RO = 378,
ONLY_IF_RW = 379,
SPECIAL = 380,
INPUT_SECTION_FLAGS = 381,
ALIGN_WITH_INPUT = 382,
EXCLUDE_FILE = 383,
CONSTANT = 384,
INPUT_DYNAMIC_LIST = 385
};
#endif
/* Tokens. */
#define INT 258
#define NAME 259
#define LNAME 260
#define OREQ 261
#define ANDEQ 262
#define RSHIFTEQ 263
#define LSHIFTEQ 264
#define DIVEQ 265
#define MULTEQ 266
#define MINUSEQ 267
#define PLUSEQ 268
#define OROR 269
#define ANDAND 270
#define NE 271
#define EQ 272
#define GE 273
#define LE 274
#define RSHIFT 275
#define LSHIFT 276
#define UNARY 277
#define END 278
#define ALIGN_K 279
#define BLOCK 280
#define BIND 281
#define QUAD 282
#define SQUAD 283
#define LONG 284
#define SHORT 285
#define BYTE 286
#define SECTIONS 287
#define PHDRS 288
#define INSERT_K 289
#define AFTER 290
#define BEFORE 291
#define DATA_SEGMENT_ALIGN 292
#define DATA_SEGMENT_RELRO_END 293
#define DATA_SEGMENT_END 294
#define SORT_BY_NAME 295
#define SORT_BY_ALIGNMENT 296
#define SORT_NONE 297
#define SORT_BY_INIT_PRIORITY 298
#define SIZEOF_HEADERS 299
#define OUTPUT_FORMAT 300
#define FORCE_COMMON_ALLOCATION 301
#define OUTPUT_ARCH 302
#define INHIBIT_COMMON_ALLOCATION 303
#define SEGMENT_START 304
#define INCLUDE 305
#define MEMORY 306
#define REGION_ALIAS 307
#define LD_FEATURE 308
#define NOLOAD 309
#define DSECT 310
#define COPY 311
#define INFO 312
#define OVERLAY 313
#define DEFINED 314
#define TARGET_K 315
#define SEARCH_DIR 316
#define MAP 317
#define ENTRY 318
#define NEXT 319
#define SIZEOF 320
#define ALIGNOF 321
#define ADDR 322
#define LOADADDR 323
#define MAX_K 324
#define MIN_K 325
#define STARTUP 326
#define HLL 327
#define SYSLIB 328
#define FLOAT 329
#define NOFLOAT 330
#define NOCROSSREFS 331
#define ORIGIN 332
#define FILL 333
#define LENGTH 334
#define CREATE_OBJECT_SYMBOLS 335
#define INPUT 336
#define GROUP 337
#define OUTPUT 338
#define CONSTRUCTORS 339
#define ALIGNMOD 340
#define AT 341
#define SUBALIGN 342
#define HIDDEN 343
#define PROVIDE 344
#define PROVIDE_HIDDEN 345
#define AS_NEEDED 346
#define CHIP 347
#define LIST 348
#define SECT 349
#define ABSOLUTE 350
#define LOAD 351
#define NEWLINE 352
#define ENDWORD 353
#define ORDER 354
#define NAMEWORD 355
#define ASSERT_K 356
#define LOG2CEIL 357
#define FORMAT 358
#define PUBLIC 359
#define DEFSYMEND 360
#define BASE 361
#define ALIAS 362
#define TRUNCATE 363
#define REL 364
#define INPUT_SCRIPT 365
#define INPUT_MRI_SCRIPT 366
#define INPUT_DEFSYM 367
#define CASE 368
#define EXTERN 369
#define START 370
#define VERS_TAG 371
#define VERS_IDENTIFIER 372
#define GLOBAL 373
#define LOCAL 374
#define VERSIONK 375
#define INPUT_VERSION_SCRIPT 376
#define KEEP 377
#define ONLY_IF_RO 378
#define ONLY_IF_RW 379
#define SPECIAL 380
#define INPUT_SECTION_FLAGS 381
#define ALIGN_WITH_INPUT 382
#define EXCLUDE_FILE 383
#define CONSTANT 384
#define INPUT_DYNAMIC_LIST 385
 
 
 
 
/* Copy the first part of user declarations. */
#line 22 "ldgram.y"
 
/*
 
*/
 
#define DONTDECLARE_MALLOC
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "ld.h"
#include "ldexp.h"
#include "ldver.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
#include "ldmisc.h"
#include "ldmain.h"
#include "mri.h"
#include "ldctor.h"
#include "ldlex.h"
 
#ifndef YYDEBUG
#define YYDEBUG 1
#endif
 
static enum section_type sectype;
static lang_memory_region_type *region;
 
bfd_boolean ldgram_had_keep = FALSE;
char *ldgram_vers_current_lang = NULL;
 
#define ERROR_NAME_MAX 20
static char *error_names[ERROR_NAME_MAX];
static int error_index;
#define PUSH_ERROR(x) if (error_index < ERROR_NAME_MAX) error_names[error_index] = x; error_index++;
#define POP_ERROR() error_index--;
 
 
/* Enabling traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
 
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
# define YYERROR_VERBOSE 1
#else
# define YYERROR_VERBOSE 0
#endif
 
/* Enabling the token table. */
#ifndef YYTOKEN_TABLE
# define YYTOKEN_TABLE 0
#endif
 
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 60 "ldgram.y"
{
bfd_vma integer;
struct big_int
{
bfd_vma integer;
char *str;
} bigint;
fill_type *fill;
char *name;
const char *cname;
struct wildcard_spec wildcard;
struct wildcard_list *wildcard_list;
struct name_list *name_list;
struct flag_info_list *flag_info_list;
struct flag_info *flag_info;
int token;
union etree_union *etree;
struct phdr_info
{
bfd_boolean filehdr;
bfd_boolean phdrs;
union etree_union *at;
union etree_union *flags;
} phdr;
struct lang_nocrossref *nocrossref;
struct lang_output_section_phdr_list *section_phdr;
struct bfd_elf_version_deps *deflist;
struct bfd_elf_version_expr *versyms;
struct bfd_elf_version_tree *versnode;
}
/* Line 193 of yacc.c. */
#line 426 "ldgram.c"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
 
 
 
/* Copy the second part of user declarations. */
 
 
/* Line 216 of yacc.c. */
#line 439 "ldgram.c"
 
#ifdef short
# undef short
#endif
 
#ifdef YYTYPE_UINT8
typedef YYTYPE_UINT8 yytype_uint8;
#else
typedef unsigned char yytype_uint8;
#endif
 
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
#elif (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
typedef signed char yytype_int8;
#else
typedef short int yytype_int8;
#endif
 
#ifdef YYTYPE_UINT16
typedef YYTYPE_UINT16 yytype_uint16;
#else
typedef unsigned short int yytype_uint16;
#endif
 
#ifdef YYTYPE_INT16
typedef YYTYPE_INT16 yytype_int16;
#else
typedef short int yytype_int16;
#endif
 
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
# define YYSIZE_T unsigned int
# endif
#endif
 
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
#ifndef YY_
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
# endif
# endif
# ifndef YY_
# define YY_(msgid) msgid
# endif
#endif
 
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
# define YYUSE(e) ((void) (e))
#else
# define YYUSE(e) /* empty */
#endif
 
/* Identity function, used to suppress warnings about constant conditions. */
#ifndef lint
# define YYID(n) (n)
#else
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
YYID (int i)
#else
static int
YYID (i)
int i;
#endif
{
return i;
}
#endif
 
#if ! defined yyoverflow || YYERROR_VERBOSE
 
/* The parser invokes alloca or malloc; define the necessary symbols. */
 
# ifdef YYSTACK_USE_ALLOCA
# if YYSTACK_USE_ALLOCA
# ifdef __GNUC__
# define YYSTACK_ALLOC __builtin_alloca
# elif defined __BUILTIN_VA_ARG_INCR
# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
# elif defined _AIX
# define YYSTACK_ALLOC __alloca
# elif defined _MSC_VER
# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
# endif
# endif
# endif
# endif
# endif
 
# ifdef YYSTACK_ALLOC
/* Pacify GCC's `empty if-body' warning. */
# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
to allow for a few compiler-allocated temporary stack slots. */
# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
# endif
# else
# define YYSTACK_ALLOC YYMALLOC
# define YYSTACK_FREE YYFREE
# ifndef YYSTACK_ALLOC_MAXIMUM
# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
# endif
# if (defined __cplusplus && ! defined _STDLIB_H \
&& ! ((defined YYMALLOC || defined malloc) \
&& (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef _STDLIB_H
# define _STDLIB_H 1
# endif
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# endif
#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
 
 
#if (! defined yyoverflow \
&& (! defined __cplusplus \
|| (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
/* A type that is properly aligned for any stack member. */
union yyalloc
{
yytype_int16 yyss;
YYSTYPE yyvs;
};
 
/* The size of the maximum gap between one aligned stack and the next. */
# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
 
/* The size of an array large to enough to hold all stacks, each with
N elements. */
# define YYSTACK_BYTES(N) \
((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ YYSTACK_GAP_MAXIMUM)
 
/* Copy COUNT objects from FROM to TO. The source and destination do
not overlap. */
# ifndef YYCOPY
# if defined __GNUC__ && 1 < __GNUC__
# define YYCOPY(To, From, Count) \
__builtin_memcpy (To, From, (Count) * sizeof (*(From)))
# else
# define YYCOPY(To, From, Count) \
do \
{ \
YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
while (YYID (0))
# endif
# endif
 
/* Relocate STACK from its old location to the new one. The
local variables YYSIZE and YYSTACKSIZE give the old and new number of
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
# define YYSTACK_RELOCATE(Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
YYCOPY (&yyptr->Stack, Stack, yysize); \
Stack = &yyptr->Stack; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
while (YYID (0))
 
#endif
 
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 17
/* YYLAST -- Last index in YYTABLE. */
#define YYLAST 1999
 
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 154
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 129
/* YYNRULES -- Number of rules. */
#define YYNRULES 369
/* YYNRULES -- Number of states. */
#define YYNSTATES 803
 
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
#define YYMAXUTOK 385
 
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 152, 2, 2, 2, 34, 21, 2,
37, 149, 32, 30, 147, 31, 2, 33, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 16, 148,
24, 6, 25, 15, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 150, 2, 151, 20, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 58, 19, 59, 153, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
5, 7, 8, 9, 10, 11, 12, 13, 14, 17,
18, 22, 23, 26, 27, 28, 29, 35, 36, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 60,
61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
141, 142, 143, 144, 145, 146
};
 
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
static const yytype_uint16 yyprhs[] =
{
0, 0, 3, 6, 9, 12, 15, 18, 20, 21,
26, 27, 30, 34, 35, 38, 43, 45, 47, 50,
52, 57, 62, 66, 69, 74, 78, 83, 88, 93,
98, 103, 106, 109, 112, 117, 122, 125, 128, 131,
134, 135, 141, 144, 145, 149, 152, 153, 155, 159,
161, 165, 166, 168, 172, 173, 176, 178, 181, 185,
186, 189, 192, 193, 195, 197, 199, 201, 203, 205,
207, 209, 211, 213, 218, 223, 228, 233, 242, 247,
249, 251, 256, 257, 263, 268, 269, 275, 280, 285,
289, 293, 300, 305, 307, 311, 314, 316, 320, 323,
324, 330, 331, 339, 340, 347, 352, 355, 358, 359,
364, 367, 368, 376, 378, 380, 382, 384, 390, 395,
400, 405, 413, 421, 429, 437, 446, 451, 453, 457,
462, 465, 467, 471, 473, 475, 478, 482, 487, 492,
498, 500, 501, 507, 510, 512, 514, 516, 521, 523,
528, 533, 534, 543, 544, 550, 553, 555, 556, 558,
560, 562, 564, 566, 568, 570, 573, 574, 576, 578,
580, 582, 584, 586, 588, 590, 592, 594, 598, 602,
609, 616, 623, 625, 626, 631, 633, 634, 638, 640,
641, 649, 650, 656, 660, 664, 665, 669, 671, 674,
676, 679, 684, 689, 693, 697, 699, 704, 708, 709,
711, 713, 714, 717, 721, 722, 725, 728, 732, 737,
740, 743, 746, 750, 754, 758, 762, 766, 770, 774,
778, 782, 786, 790, 794, 798, 802, 806, 810, 816,
820, 824, 829, 831, 833, 838, 843, 848, 853, 858,
863, 868, 875, 882, 889, 894, 901, 906, 908, 915,
922, 929, 934, 939, 944, 948, 949, 954, 955, 960,
961, 963, 964, 969, 970, 972, 974, 976, 977, 978,
979, 980, 981, 982, 1003, 1004, 1005, 1006, 1007, 1008,
1027, 1028, 1029, 1037, 1038, 1044, 1046, 1048, 1050, 1052,
1054, 1058, 1059, 1062, 1066, 1069, 1076, 1087, 1090, 1092,
1093, 1095, 1098, 1099, 1100, 1104, 1105, 1106, 1107, 1108,
1120, 1125, 1126, 1129, 1130, 1131, 1138, 1140, 1141, 1145,
1151, 1152, 1156, 1157, 1160, 1162, 1165, 1170, 1173, 1174,
1177, 1178, 1184, 1186, 1189, 1194, 1200, 1207, 1209, 1212,
1213, 1216, 1221, 1226, 1235, 1237, 1239, 1243, 1247, 1248,
1258, 1259, 1267, 1269, 1273, 1275, 1279, 1281, 1285, 1286
};
 
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int16 yyrhs[] =
{
155, 0, -1, 126, 171, -1, 127, 159, -1, 137,
271, -1, 146, 266, -1, 128, 157, -1, 4, -1,
-1, 158, 4, 6, 226, -1, -1, 160, 161, -1,
161, 162, 113, -1, -1, 108, 226, -1, 108, 226,
147, 226, -1, 4, -1, 109, -1, 115, 164, -1,
114, -1, 120, 4, 6, 226, -1, 120, 4, 147,
226, -1, 120, 4, 226, -1, 119, 4, -1, 110,
4, 147, 226, -1, 110, 4, 226, -1, 110, 4,
6, 226, -1, 38, 4, 6, 226, -1, 38, 4,
147, 226, -1, 101, 4, 6, 226, -1, 101, 4,
147, 226, -1, 111, 166, -1, 112, 165, -1, 116,
4, -1, 123, 4, 147, 4, -1, 123, 4, 147,
3, -1, 122, 226, -1, 124, 3, -1, 129, 167,
-1, 130, 168, -1, -1, 66, 156, 163, 161, 36,
-1, 131, 4, -1, -1, 164, 147, 4, -1, 164,
4, -1, -1, 4, -1, 165, 147, 4, -1, 4,
-1, 166, 147, 4, -1, -1, 4, -1, 167, 147,
4, -1, -1, 169, 170, -1, 4, -1, 170, 4,
-1, 170, 147, 4, -1, -1, 172, 173, -1, 173,
174, -1, -1, 206, -1, 181, -1, 258, -1, 217,
-1, 218, -1, 220, -1, 222, -1, 183, -1, 273,
-1, 148, -1, 76, 37, 4, 149, -1, 77, 37,
156, 149, -1, 99, 37, 156, 149, -1, 61, 37,
4, 149, -1, 61, 37, 4, 147, 4, 147, 4,
149, -1, 63, 37, 4, 149, -1, 62, -1, 64,
-1, 97, 37, 177, 149, -1, -1, 98, 175, 37,
177, 149, -1, 78, 37, 156, 149, -1, -1, 66,
156, 176, 173, 36, -1, 92, 37, 223, 149, -1,
130, 37, 168, 149, -1, 48, 49, 4, -1, 48,
50, 4, -1, 68, 37, 4, 147, 4, 149, -1,
69, 37, 4, 149, -1, 4, -1, 177, 147, 4,
-1, 177, 4, -1, 5, -1, 177, 147, 5, -1,
177, 5, -1, -1, 107, 37, 178, 177, 149, -1,
-1, 177, 147, 107, 37, 179, 177, 149, -1, -1,
177, 107, 37, 180, 177, 149, -1, 46, 58, 182,
59, -1, 182, 233, -1, 182, 183, -1, -1, 79,
37, 4, 149, -1, 204, 203, -1, -1, 117, 184,
37, 226, 147, 4, 149, -1, 4, -1, 32, -1,
15, -1, 185, -1, 144, 37, 189, 149, 185, -1,
54, 37, 185, 149, -1, 55, 37, 185, 149, -1,
56, 37, 185, 149, -1, 54, 37, 55, 37, 185,
149, 149, -1, 54, 37, 54, 37, 185, 149, 149,
-1, 55, 37, 54, 37, 185, 149, 149, -1, 55,
37, 55, 37, 185, 149, 149, -1, 54, 37, 144,
37, 189, 149, 185, 149, -1, 57, 37, 185, 149,
-1, 4, -1, 187, 21, 4, -1, 142, 37, 187,
149, -1, 189, 185, -1, 185, -1, 190, 205, 186,
-1, 186, -1, 4, -1, 188, 4, -1, 150, 190,
151, -1, 188, 150, 190, 151, -1, 186, 37, 190,
149, -1, 188, 186, 37, 190, 149, -1, 191, -1,
-1, 138, 37, 193, 191, 149, -1, 204, 203, -1,
96, -1, 148, -1, 100, -1, 54, 37, 100, 149,
-1, 192, -1, 199, 37, 224, 149, -1, 94, 37,
200, 149, -1, -1, 117, 195, 37, 226, 147, 4,
149, 203, -1, -1, 66, 156, 196, 198, 36, -1,
197, 194, -1, 194, -1, -1, 197, -1, 41, -1,
42, -1, 43, -1, 44, -1, 45, -1, 224, -1,
6, 200, -1, -1, 14, -1, 13, -1, 12, -1,
11, -1, 10, -1, 9, -1, 8, -1, 7, -1,
148, -1, 147, -1, 4, 6, 224, -1, 4, 202,
224, -1, 104, 37, 4, 6, 224, 149, -1, 105,
37, 4, 6, 224, 149, -1, 106, 37, 4, 6,
224, 149, -1, 147, -1, -1, 67, 58, 207, 59,
-1, 208, -1, -1, 208, 205, 209, -1, 209, -1,
-1, 4, 210, 214, 16, 212, 205, 213, -1, -1,
66, 156, 211, 207, 36, -1, 93, 6, 224, -1,
95, 6, 224, -1, -1, 37, 215, 149, -1, 216,
-1, 215, 216, -1, 4, -1, 152, 4, -1, 87,
37, 156, 149, -1, 88, 37, 219, 149, -1, 88,
37, 149, -1, 219, 205, 156, -1, 156, -1, 89,
37, 221, 149, -1, 221, 205, 156, -1, -1, 90,
-1, 91, -1, -1, 4, 223, -1, 4, 147, 223,
-1, -1, 225, 226, -1, 31, 226, -1, 37, 226,
149, -1, 80, 37, 226, 149, -1, 152, 226, -1,
30, 226, -1, 153, 226, -1, 226, 32, 226, -1,
226, 33, 226, -1, 226, 34, 226, -1, 226, 30,
226, -1, 226, 31, 226, -1, 226, 29, 226, -1,
226, 28, 226, -1, 226, 23, 226, -1, 226, 22,
226, -1, 226, 27, 226, -1, 226, 26, 226, -1,
226, 24, 226, -1, 226, 25, 226, -1, 226, 21,
226, -1, 226, 20, 226, -1, 226, 19, 226, -1,
226, 15, 226, 16, 226, -1, 226, 18, 226, -1,
226, 17, 226, -1, 75, 37, 4, 149, -1, 3,
-1, 60, -1, 82, 37, 4, 149, -1, 81, 37,
4, 149, -1, 83, 37, 4, 149, -1, 84, 37,
4, 149, -1, 145, 37, 4, 149, -1, 111, 37,
226, 149, -1, 38, 37, 226, 149, -1, 38, 37,
226, 147, 226, 149, -1, 51, 37, 226, 147, 226,
149, -1, 52, 37, 226, 147, 226, 149, -1, 53,
37, 226, 149, -1, 65, 37, 4, 147, 226, 149,
-1, 39, 37, 226, 149, -1, 4, -1, 85, 37,
226, 147, 226, 149, -1, 86, 37, 226, 147, 226,
149, -1, 117, 37, 226, 147, 4, 149, -1, 93,
37, 4, 149, -1, 95, 37, 4, 149, -1, 118,
37, 226, 149, -1, 102, 25, 4, -1, -1, 102,
37, 226, 149, -1, -1, 38, 37, 226, 149, -1,
-1, 143, -1, -1, 103, 37, 226, 149, -1, -1,
139, -1, 140, -1, 141, -1, -1, -1, -1, -1,
-1, -1, 4, 234, 249, 228, 229, 230, 231, 235,
232, 58, 236, 198, 59, 237, 252, 227, 253, 201,
238, 205, -1, -1, -1, -1, -1, -1, 74, 239,
250, 251, 228, 231, 240, 58, 241, 254, 59, 242,
252, 227, 253, 201, 243, 205, -1, -1, -1, 98,
244, 249, 245, 58, 182, 59, -1, -1, 66, 156,
246, 182, 36, -1, 70, -1, 71, -1, 72, -1,
73, -1, 74, -1, 37, 247, 149, -1, -1, 37,
149, -1, 226, 248, 16, -1, 248, 16, -1, 40,
37, 226, 149, 248, 16, -1, 40, 37, 226, 149,
39, 37, 226, 149, 248, 16, -1, 226, 16, -1,
16, -1, -1, 92, -1, 25, 4, -1, -1, -1,
253, 16, 4, -1, -1, -1, -1, -1, 254, 4,
255, 58, 198, 59, 256, 253, 201, 257, 205, -1,
47, 58, 259, 59, -1, -1, 259, 260, -1, -1,
-1, 4, 261, 263, 264, 262, 148, -1, 226, -1,
-1, 4, 265, 264, -1, 102, 37, 226, 149, 264,
-1, -1, 37, 226, 149, -1, -1, 267, 268, -1,
269, -1, 268, 269, -1, 58, 270, 59, 148, -1,
279, 148, -1, -1, 272, 275, -1, -1, 274, 136,
58, 275, 59, -1, 276, -1, 275, 276, -1, 58,
278, 59, 148, -1, 132, 58, 278, 59, 148, -1,
132, 58, 278, 59, 277, 148, -1, 132, -1, 277,
132, -1, -1, 279, 148, -1, 134, 16, 279, 148,
-1, 135, 16, 279, 148, -1, 134, 16, 279, 148,
135, 16, 279, 148, -1, 133, -1, 4, -1, 279,
148, 133, -1, 279, 148, 4, -1, -1, 279, 148,
130, 4, 58, 280, 279, 282, 59, -1, -1, 130,
4, 58, 281, 279, 282, 59, -1, 134, -1, 279,
148, 134, -1, 135, -1, 279, 148, 135, -1, 130,
-1, 279, 148, 130, -1, -1, 148, -1
};
 
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
0, 166, 166, 167, 168, 169, 170, 174, 178, 178,
188, 188, 201, 202, 206, 207, 208, 211, 214, 215,
216, 218, 220, 222, 224, 226, 228, 230, 232, 234,
236, 238, 239, 240, 242, 244, 246, 248, 250, 251,
253, 252, 256, 258, 262, 263, 264, 268, 270, 274,
276, 281, 282, 283, 288, 288, 293, 295, 297, 302,
302, 308, 309, 314, 315, 316, 317, 318, 319, 320,
321, 322, 323, 324, 326, 328, 330, 333, 335, 337,
339, 341, 343, 342, 346, 349, 348, 352, 356, 357,
359, 361, 363, 368, 371, 374, 377, 380, 383, 387,
386, 392, 391, 397, 396, 404, 408, 409, 410, 414,
416, 417, 417, 425, 429, 433, 440, 447, 454, 461,
468, 475, 482, 489, 496, 503, 510, 519, 537, 558,
571, 580, 591, 600, 611, 620, 629, 633, 642, 646,
654, 656, 655, 662, 663, 667, 668, 673, 678, 679,
684, 688, 688, 692, 691, 698, 699, 702, 704, 708,
710, 712, 714, 716, 721, 728, 730, 734, 736, 738,
740, 742, 744, 746, 748, 753, 753, 758, 762, 770,
774, 778, 786, 786, 790, 793, 793, 796, 797, 802,
801, 807, 806, 813, 821, 829, 830, 834, 835, 839,
841, 846, 851, 852, 857, 859, 865, 867, 869, 873,
875, 881, 884, 893, 904, 904, 910, 912, 914, 916,
918, 920, 923, 925, 927, 929, 931, 933, 935, 937,
939, 941, 943, 945, 947, 949, 951, 953, 955, 957,
959, 961, 963, 965, 968, 970, 972, 974, 976, 978,
980, 982, 984, 986, 988, 990, 999, 1001, 1003, 1005,
1007, 1009, 1011, 1013, 1019, 1020, 1024, 1025, 1029, 1030,
1034, 1035, 1039, 1040, 1044, 1045, 1046, 1047, 1050, 1055,
1058, 1064, 1066, 1050, 1073, 1075, 1077, 1082, 1084, 1072,
1094, 1096, 1094, 1102, 1101, 1108, 1109, 1110, 1111, 1112,
1116, 1117, 1118, 1122, 1123, 1128, 1129, 1134, 1135, 1140,
1141, 1146, 1148, 1153, 1156, 1169, 1173, 1178, 1180, 1171,
1188, 1191, 1193, 1197, 1198, 1197, 1207, 1252, 1255, 1268,
1277, 1280, 1287, 1287, 1299, 1300, 1304, 1308, 1317, 1317,
1331, 1331, 1341, 1342, 1346, 1350, 1354, 1361, 1365, 1373,
1376, 1380, 1384, 1388, 1395, 1399, 1403, 1407, 1412, 1411,
1425, 1424, 1434, 1438, 1442, 1446, 1450, 1454, 1460, 1462
};
#endif
 
#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
"$end", "error", "$undefined", "INT", "NAME", "LNAME", "'='", "OREQ",
"ANDEQ", "RSHIFTEQ", "LSHIFTEQ", "DIVEQ", "MULTEQ", "MINUSEQ", "PLUSEQ",
"'?'", "':'", "OROR", "ANDAND", "'|'", "'^'", "'&'", "NE", "EQ", "'<'",
"'>'", "GE", "LE", "RSHIFT", "LSHIFT", "'+'", "'-'", "'*'", "'/'", "'%'",
"UNARY", "END", "'('", "ALIGN_K", "BLOCK", "BIND", "QUAD", "SQUAD",
"LONG", "SHORT", "BYTE", "SECTIONS", "PHDRS", "INSERT_K", "AFTER",
"BEFORE", "DATA_SEGMENT_ALIGN", "DATA_SEGMENT_RELRO_END",
"DATA_SEGMENT_END", "SORT_BY_NAME", "SORT_BY_ALIGNMENT", "SORT_NONE",
"SORT_BY_INIT_PRIORITY", "'{'", "'}'", "SIZEOF_HEADERS", "OUTPUT_FORMAT",
"FORCE_COMMON_ALLOCATION", "OUTPUT_ARCH", "INHIBIT_COMMON_ALLOCATION",
"SEGMENT_START", "INCLUDE", "MEMORY", "REGION_ALIAS", "LD_FEATURE",
"NOLOAD", "DSECT", "COPY", "INFO", "OVERLAY", "DEFINED", "TARGET_K",
"SEARCH_DIR", "MAP", "ENTRY", "NEXT", "SIZEOF", "ALIGNOF", "ADDR",
"LOADADDR", "MAX_K", "MIN_K", "STARTUP", "HLL", "SYSLIB", "FLOAT",
"NOFLOAT", "NOCROSSREFS", "ORIGIN", "FILL", "LENGTH",
"CREATE_OBJECT_SYMBOLS", "INPUT", "GROUP", "OUTPUT", "CONSTRUCTORS",
"ALIGNMOD", "AT", "SUBALIGN", "HIDDEN", "PROVIDE", "PROVIDE_HIDDEN",
"AS_NEEDED", "CHIP", "LIST", "SECT", "ABSOLUTE", "LOAD", "NEWLINE",
"ENDWORD", "ORDER", "NAMEWORD", "ASSERT_K", "LOG2CEIL", "FORMAT",
"PUBLIC", "DEFSYMEND", "BASE", "ALIAS", "TRUNCATE", "REL",
"INPUT_SCRIPT", "INPUT_MRI_SCRIPT", "INPUT_DEFSYM", "CASE", "EXTERN",
"START", "VERS_TAG", "VERS_IDENTIFIER", "GLOBAL", "LOCAL", "VERSIONK",
"INPUT_VERSION_SCRIPT", "KEEP", "ONLY_IF_RO", "ONLY_IF_RW", "SPECIAL",
"INPUT_SECTION_FLAGS", "ALIGN_WITH_INPUT", "EXCLUDE_FILE", "CONSTANT",
"INPUT_DYNAMIC_LIST", "','", "';'", "')'", "'['", "']'", "'!'", "'~'",
"$accept", "file", "filename", "defsym_expr", "@1", "mri_script_file",
"@2", "mri_script_lines", "mri_script_command", "@3", "ordernamelist",
"mri_load_name_list", "mri_abs_name_list", "casesymlist",
"extern_name_list", "@4", "extern_name_list_body", "script_file", "@5",
"ifile_list", "ifile_p1", "@6", "@7", "input_list", "@8", "@9", "@10",
"sections", "sec_or_group_p1", "statement_anywhere", "@11",
"wildcard_name", "wildcard_spec", "sect_flag_list", "sect_flags",
"exclude_name_list", "file_NAME_list", "input_section_spec_no_keep",
"input_section_spec", "@12", "statement", "@13", "@14", "statement_list",
"statement_list_opt", "length", "fill_exp", "fill_opt", "assign_op",
"end", "assignment", "opt_comma", "memory", "memory_spec_list_opt",
"memory_spec_list", "memory_spec", "@15", "@16", "origin_spec",
"length_spec", "attributes_opt", "attributes_list", "attributes_string",
"startup", "high_level_library", "high_level_library_NAME_list",
"low_level_library", "low_level_library_NAME_list",
"floating_point_support", "nocrossref_list", "mustbe_exp", "@17", "exp",
"memspec_at_opt", "opt_at", "opt_align", "opt_align_with_input",
"opt_subalign", "sect_constraint", "section", "@18", "@19", "@20", "@21",
"@22", "@23", "@24", "@25", "@26", "@27", "@28", "@29", "@30", "type",
"atype", "opt_exp_with_type", "opt_exp_without_type", "opt_nocrossrefs",
"memspec_opt", "phdr_opt", "overlay_section", "@31", "@32", "@33",
"phdrs", "phdr_list", "phdr", "@34", "@35", "phdr_type",
"phdr_qualifiers", "phdr_val", "dynamic_list_file", "@36",
"dynamic_list_nodes", "dynamic_list_node", "dynamic_list_tag",
"version_script_file", "@37", "version", "@38", "vers_nodes",
"vers_node", "verdep", "vers_tag", "vers_defns", "@39", "@40",
"opt_semicolon", 0
};
#endif
 
# ifdef YYPRINT
/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
token YYLEX-NUM. */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 61, 261, 262, 263,
264, 265, 266, 267, 268, 63, 58, 269, 270, 124,
94, 38, 271, 272, 60, 62, 273, 274, 275, 276,
43, 45, 42, 47, 37, 277, 278, 40, 279, 280,
281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298, 123, 125,
299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
319, 320, 321, 322, 323, 324, 325, 326, 327, 328,
329, 330, 331, 332, 333, 334, 335, 336, 337, 338,
339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
349, 350, 351, 352, 353, 354, 355, 356, 357, 358,
359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
379, 380, 381, 382, 383, 384, 385, 44, 59, 41,
91, 93, 33, 126
};
# endif
 
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint16 yyr1[] =
{
0, 154, 155, 155, 155, 155, 155, 156, 158, 157,
160, 159, 161, 161, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
162, 162, 162, 162, 162, 162, 162, 162, 162, 162,
163, 162, 162, 162, 164, 164, 164, 165, 165, 166,
166, 167, 167, 167, 169, 168, 170, 170, 170, 172,
171, 173, 173, 174, 174, 174, 174, 174, 174, 174,
174, 174, 174, 174, 174, 174, 174, 174, 174, 174,
174, 174, 175, 174, 174, 176, 174, 174, 174, 174,
174, 174, 174, 177, 177, 177, 177, 177, 177, 178,
177, 179, 177, 180, 177, 181, 182, 182, 182, 183,
183, 184, 183, 185, 185, 185, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 187, 187, 188,
189, 189, 190, 190, 191, 191, 191, 191, 191, 191,
192, 193, 192, 194, 194, 194, 194, 194, 194, 194,
194, 195, 194, 196, 194, 197, 197, 198, 198, 199,
199, 199, 199, 199, 200, 201, 201, 202, 202, 202,
202, 202, 202, 202, 202, 203, 203, 204, 204, 204,
204, 204, 205, 205, 206, 207, 207, 208, 208, 210,
209, 211, 209, 212, 213, 214, 214, 215, 215, 216,
216, 217, 218, 218, 219, 219, 220, 221, 221, 222,
222, 223, 223, 223, 225, 224, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
226, 226, 226, 226, 227, 227, 228, 228, 229, 229,
230, 230, 231, 231, 232, 232, 232, 232, 234, 235,
236, 237, 238, 233, 239, 240, 241, 242, 243, 233,
244, 245, 233, 246, 233, 247, 247, 247, 247, 247,
248, 248, 248, 249, 249, 249, 249, 250, 250, 251,
251, 252, 252, 253, 253, 254, 255, 256, 257, 254,
258, 259, 259, 261, 262, 260, 263, 264, 264, 264,
265, 265, 267, 266, 268, 268, 269, 270, 272, 271,
274, 273, 275, 275, 276, 276, 276, 277, 277, 278,
278, 278, 278, 278, 279, 279, 279, 279, 280, 279,
281, 279, 279, 279, 279, 279, 279, 279, 282, 282
};
 
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
0, 2, 2, 2, 2, 2, 2, 1, 0, 4,
0, 2, 3, 0, 2, 4, 1, 1, 2, 1,
4, 4, 3, 2, 4, 3, 4, 4, 4, 4,
4, 2, 2, 2, 4, 4, 2, 2, 2, 2,
0, 5, 2, 0, 3, 2, 0, 1, 3, 1,
3, 0, 1, 3, 0, 2, 1, 2, 3, 0,
2, 2, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 4, 4, 4, 4, 8, 4, 1,
1, 4, 0, 5, 4, 0, 5, 4, 4, 3,
3, 6, 4, 1, 3, 2, 1, 3, 2, 0,
5, 0, 7, 0, 6, 4, 2, 2, 0, 4,
2, 0, 7, 1, 1, 1, 1, 5, 4, 4,
4, 7, 7, 7, 7, 8, 4, 1, 3, 4,
2, 1, 3, 1, 1, 2, 3, 4, 4, 5,
1, 0, 5, 2, 1, 1, 1, 4, 1, 4,
4, 0, 8, 0, 5, 2, 1, 0, 1, 1,
1, 1, 1, 1, 1, 2, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 3, 3, 6,
6, 6, 1, 0, 4, 1, 0, 3, 1, 0,
7, 0, 5, 3, 3, 0, 3, 1, 2, 1,
2, 4, 4, 3, 3, 1, 4, 3, 0, 1,
1, 0, 2, 3, 0, 2, 2, 3, 4, 2,
2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 5, 3,
3, 4, 1, 1, 4, 4, 4, 4, 4, 4,
4, 6, 6, 6, 4, 6, 4, 1, 6, 6,
6, 4, 4, 4, 3, 0, 4, 0, 4, 0,
1, 0, 4, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 20, 0, 0, 0, 0, 0, 18,
0, 0, 7, 0, 5, 1, 1, 1, 1, 1,
3, 0, 2, 3, 2, 6, 10, 2, 1, 0,
1, 2, 0, 0, 3, 0, 0, 0, 0, 11,
4, 0, 2, 0, 0, 6, 1, 0, 3, 5,
0, 3, 0, 2, 1, 2, 4, 2, 0, 2,
0, 5, 1, 2, 4, 5, 6, 1, 2, 0,
2, 4, 4, 8, 1, 1, 3, 3, 0, 9,
0, 7, 1, 3, 1, 3, 1, 3, 0, 1
};
 
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
STATE-NUM when YYTABLE doesn't specify something else to do. Zero
means the default is an error. */
static const yytype_uint16 yydefact[] =
{
0, 59, 10, 8, 338, 332, 0, 2, 62, 3,
13, 6, 0, 4, 0, 5, 0, 1, 60, 11,
0, 349, 0, 339, 342, 0, 333, 334, 0, 0,
0, 0, 0, 79, 0, 80, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 209, 210, 0,
0, 82, 0, 0, 0, 0, 111, 0, 72, 61,
64, 70, 0, 63, 66, 67, 68, 69, 65, 71,
0, 16, 0, 0, 0, 0, 17, 0, 0, 0,
19, 46, 0, 0, 0, 0, 0, 0, 51, 54,
0, 0, 0, 355, 366, 354, 362, 364, 0, 0,
349, 343, 362, 364, 0, 0, 335, 214, 174, 173,
172, 171, 170, 169, 168, 167, 214, 108, 321, 0,
0, 0, 0, 7, 85, 186, 0, 0, 0, 0,
0, 0, 0, 0, 208, 211, 0, 0, 0, 0,
0, 0, 0, 54, 176, 175, 110, 0, 0, 40,
0, 242, 257, 0, 0, 0, 0, 0, 0, 0,
0, 243, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 14,
0, 49, 31, 47, 32, 18, 33, 23, 0, 36,
0, 37, 52, 38, 39, 0, 42, 12, 9, 0,
0, 0, 0, 350, 0, 0, 337, 177, 0, 178,
0, 0, 89, 90, 0, 0, 62, 189, 0, 0,
183, 188, 0, 0, 0, 0, 0, 0, 0, 203,
205, 183, 183, 211, 0, 93, 96, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 13,
0, 0, 220, 216, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 219, 221, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 25,
0, 0, 45, 0, 0, 0, 22, 0, 0, 56,
55, 360, 0, 0, 344, 357, 367, 356, 363, 365,
0, 336, 215, 278, 105, 0, 284, 290, 107, 106,
323, 320, 322, 0, 76, 78, 340, 195, 191, 184,
182, 0, 0, 92, 73, 74, 84, 109, 201, 202,
0, 206, 0, 211, 212, 87, 99, 95, 98, 0,
0, 81, 0, 75, 214, 214, 214, 0, 88, 0,
27, 28, 43, 29, 30, 217, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 240, 239, 237,
236, 235, 230, 229, 233, 234, 232, 231, 228, 227,
225, 226, 222, 223, 224, 15, 26, 24, 50, 48,
44, 20, 21, 35, 34, 53, 57, 0, 0, 351,
352, 0, 347, 345, 0, 301, 293, 0, 301, 0,
0, 86, 0, 0, 186, 187, 0, 204, 207, 213,
0, 103, 94, 97, 0, 83, 0, 0, 0, 0,
341, 41, 0, 250, 256, 0, 0, 254, 0, 241,
218, 245, 244, 246, 247, 0, 0, 261, 262, 249,
0, 263, 248, 0, 58, 368, 365, 358, 348, 346,
0, 0, 301, 0, 267, 108, 308, 0, 309, 291,
326, 327, 0, 199, 0, 0, 197, 0, 0, 91,
0, 0, 101, 179, 180, 181, 0, 0, 0, 0,
0, 0, 0, 0, 238, 369, 0, 0, 0, 295,
296, 297, 298, 299, 302, 0, 0, 0, 0, 304,
0, 269, 0, 307, 310, 267, 0, 330, 0, 324,
0, 200, 196, 198, 0, 183, 192, 100, 0, 0,
112, 251, 252, 253, 255, 258, 259, 260, 361, 0,
368, 300, 0, 303, 0, 0, 271, 294, 273, 108,
0, 327, 0, 0, 77, 214, 0, 104, 0, 353,
0, 301, 0, 0, 270, 273, 0, 285, 0, 0,
328, 0, 325, 193, 0, 190, 102, 359, 0, 0,
266, 0, 279, 0, 0, 292, 331, 327, 214, 0,
305, 268, 277, 0, 286, 329, 194, 0, 274, 275,
276, 0, 272, 315, 301, 280, 0, 0, 157, 316,
287, 306, 134, 115, 114, 159, 160, 161, 162, 163,
0, 0, 0, 0, 0, 0, 144, 146, 151, 0,
0, 0, 145, 0, 116, 0, 0, 140, 148, 156,
158, 0, 0, 0, 0, 312, 0, 0, 0, 0,
153, 214, 0, 141, 0, 0, 113, 0, 133, 183,
0, 135, 0, 0, 155, 281, 214, 143, 157, 0,
265, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 157, 0, 164, 0, 0, 127, 0, 131, 0,
0, 136, 0, 183, 183, 0, 312, 0, 0, 311,
0, 313, 0, 0, 147, 0, 118, 0, 0, 119,
120, 126, 0, 150, 0, 113, 0, 0, 129, 0,
130, 132, 138, 137, 183, 265, 149, 317, 0, 166,
0, 0, 0, 0, 0, 154, 0, 142, 128, 117,
139, 313, 313, 264, 214, 0, 288, 0, 0, 0,
0, 0, 0, 166, 166, 165, 314, 183, 122, 121,
0, 123, 124, 0, 282, 318, 289, 125, 152, 183,
183, 283, 319
};
 
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
-1, 6, 124, 11, 12, 9, 10, 19, 91, 249,
185, 184, 182, 193, 194, 195, 310, 7, 8, 18,
59, 137, 216, 238, 450, 559, 511, 60, 210, 328,
142, 664, 665, 717, 666, 719, 689, 667, 668, 715,
669, 682, 711, 670, 671, 672, 712, 776, 116, 146,
62, 722, 63, 219, 220, 221, 337, 444, 555, 605,
443, 505, 506, 64, 65, 231, 66, 232, 67, 234,
713, 208, 254, 731, 541, 576, 595, 597, 631, 329,
435, 622, 638, 726, 799, 437, 614, 633, 675, 787,
438, 546, 495, 535, 493, 494, 498, 545, 700, 759,
636, 674, 772, 800, 68, 211, 332, 439, 583, 501,
549, 581, 15, 16, 26, 27, 104, 13, 14, 69,
70, 23, 24, 434, 98, 99, 528, 428, 526
};
 
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
#define YYPACT_NINF -647
static const yytype_int16 yypact[] =
{
-46, -647, -647, -647, -647, -647, 74, -647, -647, -647,
-647, -647, 64, -647, -3, -647, 65, -647, 957, 1755,
124, 5, 166, -3, -647, 114, 65, -647, 682, 169,
179, 192, 105, -647, 213, -647, 259, 221, 246, 248,
256, 258, 262, 263, 265, 266, 267, -647, -647, 268,
276, -647, 291, 293, 295, 296, -647, 298, -647, -647,
-647, -647, 110, -647, -647, -647, -647, -647, -647, -647,
178, -647, 332, 259, 334, 781, -647, 336, 337, 338,
-647, -647, 341, 342, 344, 781, 346, 348, 351, -647,
352, 245, 781, -647, 355, -647, 345, 353, 313, 226,
5, -647, -647, -647, 318, 230, -647, -647, -647, -647,
-647, -647, -647, -647, -647, -647, -647, -647, -647, 375,
376, 388, 390, -647, -647, 49, 395, 398, 405, 259,
259, 409, 259, 4, -647, 410, 34, 378, 259, 413,
417, 418, 386, -647, -647, -647, -647, 366, 31, -647,
38, -647, -647, 781, 781, 781, 393, 394, 404, 407,
408, -647, 419, 420, 422, 426, 427, 428, 430, 431,
432, 433, 440, 444, 445, 446, 449, 781, 781, 1564,
367, -647, 282, -647, 299, 20, -647, -647, 525, 1936,
307, -647, -647, 340, -647, 439, -647, -647, 1936, 421,
114, 114, 343, 121, 434, 354, 121, -647, 781, -647,
278, 55, -647, -647, -53, 357, -647, -647, 259, 435,
85, -647, 363, 362, 368, 372, 373, 374, 377, -647,
-647, -4, 96, 24, 381, -647, -647, 452, 17, 34,
383, 486, 494, 495, 781, 387, -3, 781, 781, -647,
781, 781, -647, -647, 965, 781, 781, 781, 781, 781,
500, 520, 781, 521, 533, 535, 536, 781, 781, 537,
538, 781, 781, 781, 539, -647, -647, 781, 781, 781,
781, 781, 781, 781, 781, 781, 781, 781, 781, 781,
781, 781, 781, 781, 781, 781, 781, 781, 781, 1936,
541, 543, -647, 544, 781, 781, 1936, 273, 545, -647,
27, -647, 402, 403, -647, -647, 548, -647, -647, -647,
-47, -647, 1936, 682, -647, 259, -647, -647, -647, -647,
-647, -647, -647, 549, -647, -647, 1033, 517, -647, -647,
-647, 49, 553, -647, -647, -647, -647, -647, -647, -647,
259, -647, 259, 410, -647, -647, -647, -647, -647, 522,
88, -647, 21, -647, -647, -647, -647, 1584, -647, -16,
1936, 1936, 1779, 1936, 1936, -647, 921, 1165, 1604, 1624,
1185, 411, 412, 1205, 416, 423, 424, 425, 1644, 1664,
437, 438, 1225, 1695, 1245, 443, 1896, 1776, 1145, 1951,
1965, 1278, 856, 856, 406, 406, 406, 406, 442, 442,
167, 167, -647, -647, -647, 1936, 1936, 1936, -647, -647,
-647, 1936, 1936, -647, -647, -647, -647, 556, 114, 277,
121, 508, -647, -647, -37, 622, -647, 697, 622, 781,
441, -647, 3, 551, 49, -647, 447, -647, -647, -647,
34, -647, -647, -647, 531, -647, 448, 450, 453, 565,
-647, -647, 781, -647, -647, 781, 781, -647, 781, -647,
-647, -647, -647, -647, -647, 781, 781, -647, -647, -647,
566, -647, -647, 781, -647, 455, 559, -647, -647, -647,
236, 542, 1807, 564, 479, -647, -647, 1916, 497, -647,
1936, 29, 589, -647, 590, 2, -647, 502, 562, -647,
30, 34, -647, -647, -647, -647, 463, 1265, 1298, 1318,
1338, 1358, 1378, 464, 1936, 121, 555, 114, 114, -647,
-647, -647, -647, -647, -647, 466, 781, -22, 585, -647,
567, 578, 392, -647, -647, 479, 561, 580, 584, -647,
473, -647, -647, -647, 617, 477, -647, -647, 79, 34,
-647, -647, -647, -647, -647, -647, -647, -647, -647, 489,
455, -647, 1398, -647, 781, 601, 498, -647, 546, -647,
781, 29, 781, 492, -647, -647, 550, -647, 84, 121,
587, 225, 1431, 781, -647, 546, 607, -647, 429, 1451,
-647, 1471, -647, -647, 641, -647, -647, -647, 611, 634,
-647, 1491, -647, 781, 593, -647, -647, 29, -647, 781,
-647, -647, 95, 1511, -647, -647, -647, 1531, -647, -647,
-647, 596, -647, -647, 618, -647, 63, 640, 864, -647,
-647, -647, 621, -647, -647, -647, -647, -647, -647, -647,
620, 626, 627, 628, 259, 629, -647, -647, -647, 630,
631, 632, -647, 311, -647, 639, 15, -647, -647, -647,
864, 612, 642, 110, 623, 655, 94, 371, 72, 72,
-647, -647, 646, -647, 680, 72, -647, 648, -647, -39,
311, 649, 311, 661, -647, -647, -647, -647, 864, 695,
608, 672, 674, 563, 677, 569, 679, 683, 570, 572,
573, 864, 574, -647, 781, 8, -647, 11, -647, 14,
102, -647, 311, 122, -15, 311, 655, 575, 666, -647,
701, -647, 72, 72, -647, 72, -647, 72, 72, -647,
-647, -647, 693, -647, 1715, 581, 582, 728, -647, 72,
-647, -647, -647, -647, 123, 608, -647, -647, 733, 91,
592, 594, 41, 602, 603, -647, 734, -647, -647, -647,
-647, -647, -647, -647, -647, 738, -647, 605, 606, 72,
609, 610, 614, 91, 91, -647, -647, 477, -647, -647,
615, -647, -647, 110, -647, -647, -647, -647, -647, 477,
477, -647, -647
};
 
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
-647, -647, -72, -647, -647, -647, -647, 507, -647, -647,
-647, -647, -647, -647, 625, -647, -647, -647, -647, 554,
-647, -647, -647, -225, -647, -647, -647, -647, -459, -13,
-647, 68, -398, -647, -647, 25, -615, 46, -647, -647,
99, -647, -647, -647, -612, -647, -9, -493, -647, -646,
-386, -216, -647, 322, -647, 454, -647, -647, -647, -647,
-647, -647, 271, -647, -647, -647, -647, -647, -647, -192,
-105, -647, -75, 16, 228, -647, -647, 191, -647, -647,
-647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-647, -647, -647, -647, -472, 356, -647, -647, 67, -474,
-647, -647, -647, -647, -647, -647, -647, -647, -647, -647,
-527, -647, -647, -647, -647, 763, -647, -647, -647, -647,
-647, 552, -20, -647, 691, -12, -647, -647, 227
};
 
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
positive, shift that token. If negative, reduce the rule which
number is the opposite. If zero, do what YYDEFACT says.
If YYTABLE_NINF, syntax error. */
#define YYTABLE_NINF -341
static const yytype_int16 yytable[] =
{
179, 149, 207, 101, 341, 61, 503, 503, 123, 93,
189, 209, 745, 105, 362, 350, 352, 198, 686, 691,
538, 357, 358, 643, 302, 357, 358, 697, 233, 643,
643, 426, 747, 547, 357, 358, 542, 247, 235, 236,
644, 354, 21, 460, 250, 686, 644, 644, 529, 530,
531, 532, 533, 217, 600, 21, 643, 225, 226, 330,
228, 230, 687, 651, 652, 653, 240, 639, 20, 687,
651, 652, 653, 644, 17, 723, 686, 724, 252, 253,
1, 2, 3, 357, 358, 432, 728, 643, 357, 358,
625, 4, 452, 453, 333, 488, 334, 774, 686, 742,
5, 433, 275, 276, 644, 299, 686, 775, 340, 643,
754, 489, 721, 306, 331, 218, 22, 643, 93, 609,
598, -185, 640, 25, 359, 315, 644, 534, 359, 22,
92, 548, 340, 322, 644, 94, 753, 359, 95, 96,
97, 237, 121, 340, -185, 349, 338, 798, 701, 702,
660, 552, 661, 229, 504, 504, 701, 702, 663, 661,
748, 449, 637, 749, 360, 692, 361, 303, 360, 367,
455, 353, 370, 371, 427, 373, 374, 360, 248, 557,
376, 377, 378, 379, 380, 251, 359, 383, 312, 313,
779, 359, 388, 389, 703, 454, 392, 393, 394, 293,
294, 295, 396, 397, 398, 399, 400, 401, 402, 403,
404, 405, 406, 407, 408, 409, 410, 411, 412, 413,
414, 415, 416, 417, 100, 510, 360, 117, 587, 421,
422, 360, 340, 606, 628, 629, 630, 118, 704, 151,
152, 119, 120, 340, 94, 351, 704, 95, 102, 103,
122, 316, 673, 436, 317, 318, 319, 144, 145, 456,
457, 458, 537, 123, 608, 688, 153, 154, 693, 340,
340, 752, 770, 155, 156, 157, 423, 424, 447, 125,
448, 315, 323, 126, 673, 127, 558, 158, 159, 160,
794, 795, 688, 128, 688, 129, 161, 783, 784, 130,
131, 162, 132, 133, 134, 135, 529, 530, 531, 532,
533, 163, 673, 136, 147, 686, 164, 165, 166, 167,
168, 169, 170, 61, 751, 673, 643, 688, 138, 171,
139, 172, 140, 141, 588, 143, 148, 324, 150, 586,
180, 181, 183, 644, 325, 186, 187, 173, 188, 101,
190, 191, 326, 174, 175, 192, 196, 43, 197, 199,
492, 200, 497, 492, 500, 687, 651, 652, 653, 201,
151, 152, 202, 297, 203, 686, 327, 205, 206, 212,
213, 176, 53, 54, 55, 534, 643, 517, 177, 178,
518, 519, 214, 520, 215, 56, 323, 153, 154, 222,
521, 522, 223, 644, 155, 156, 157, 316, 524, 224,
317, 318, 486, 227, 233, 239, 485, 241, 158, 159,
160, 242, 243, 244, 246, 706, 707, 161, 577, 300,
255, 256, 162, 323, 289, 290, 291, 292, 293, 294,
295, 257, 163, 309, 258, 259, 301, 164, 165, 166,
167, 168, 169, 170, 307, 661, 260, 261, 325, 262,
171, 572, 172, 263, 264, 265, 326, 266, 267, 268,
269, 43, 291, 292, 293, 294, 295, 270, 173, 311,
603, 271, 272, 273, 174, 175, 274, 308, 615, 356,
327, 314, 364, 320, 339, 325, 53, 54, 55, 592,
365, 366, 321, 326, 381, 599, 335, 601, 43, 56,
342, 343, 176, 626, 298, 569, 570, 344, 611, 177,
178, 345, 346, 347, 382, 384, 348, 327, 151, 152,
355, 304, 363, 53, 54, 55, 368, 385, 623, 386,
387, 390, 391, 395, 627, 418, 56, 419, 420, 425,
429, 430, 431, 440, 442, 153, 154, 446, 468, 451,
484, 469, 155, 156, 157, 471, 487, 507, 512, 516,
523, 796, 472, 473, 474, 527, 158, 159, 160, 536,
539, 540, 680, 801, 802, 161, 477, 478, 502, 544,
162, 727, 482, 550, 551, 554, 509, 513, 556, 514,
163, 573, 515, 525, 574, 164, 165, 166, 167, 168,
169, 170, 560, 567, 568, 571, 575, 580, 171, 579,
172, 582, 584, 585, 340, 151, 152, 107, 108, 109,
110, 111, 112, 113, 114, 115, 173, 589, 593, 744,
602, 594, 174, 175, 613, 604, 607, 618, 619, 596,
620, 624, 153, 154, 635, 537, 641, 676, -113, 490,
156, 157, 491, 677, 678, 679, 681, 683, 684, 685,
176, 695, 305, 158, 159, 160, 690, 177, 178, 696,
699, 698, 161, 714, 716, 720, -113, 162, 107, 108,
109, 110, 111, 112, 113, 114, 115, 163, 725, 729,
151, 152, 164, 165, 166, 167, 168, 169, 170, 732,
730, 733, 734, 496, 735, 171, 737, 172, 736, 739,
738, 740, 741, 743, 756, 757, 758, 153, 154, 765,
-134, 767, 768, 173, 155, 156, 157, 773, 782, 174,
175, 777, 786, 778, 705, 708, 709, 710, 158, 159,
160, 780, 781, 718, 788, 789, 372, 161, 791, 792,
762, 746, 162, 793, 797, 785, 508, 176, 245, 694,
336, 771, 163, 578, 177, 178, 553, 164, 165, 166,
167, 168, 169, 170, 151, 152, 612, 750, 705, 106,
171, 204, 172, 755, 499, 445, 0, 590, 369, 0,
760, 761, 0, 718, 0, 763, 764, 0, 173, 0,
0, 153, 154, 0, 174, 175, 0, 769, 155, 156,
157, 0, 0, 0, 0, 0, 0, 0, 0, 0,
750, 0, 158, 159, 160, 0, 0, 0, 0, 0,
0, 161, 176, 0, 0, 0, 162, 790, 0, 177,
178, 0, 0, 0, 0, 0, 163, 0, 0, 0,
0, 164, 165, 166, 167, 168, 169, 170, 642, 0,
0, 0, 0, 0, 171, 0, 172, 0, 0, 643,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 0, 173, 0, 0, 0, 644, 0, 174, 175,
0, 0, 0, 0, 0, 645, 646, 647, 648, 649,
0, 0, 0, 0, 0, 0, 0, 0, 650, 651,
652, 653, 0, 0, 0, 0, 176, 0, 0, 0,
654, 0, 0, 177, 178, 0, 277, 0, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 0, 0, 655, 0,
656, 28, 0, 0, 657, 0, 0, 0, 53, 54,
55, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277, 658, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
0, 0, 659, 29, 30, 31, 660, 0, 661, 0,
0, 0, 662, 0, 663, 0, 0, 0, 32, 33,
34, 35, 0, 36, 37, 38, 39, 0, 0, 0,
0, 0, 0, 40, 41, 42, 43, 28, 0, 0,
0, 0, 0, 0, 44, 45, 46, 47, 48, 49,
0, 0, 0, 0, 50, 51, 52, 0, 0, 0,
0, 53, 54, 55, 0, 0, 0, 0, 462, 441,
463, 0, 0, 0, 56, 0, 0, 0, 0, 29,
30, 31, 0, 0, 0, 0, 0, 57, 0, 0,
0, 0, 0, -340, 32, 33, 34, 35, 0, 36,
37, 38, 39, 0, 0, 58, 0, 0, 0, 40,
41, 42, 43, 0, 375, 0, 0, 0, 0, 0,
44, 45, 46, 47, 48, 49, 0, 0, 0, 0,
50, 51, 52, 0, 0, 0, 0, 53, 54, 55,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 57, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 58, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 0, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 0, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 0, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 0, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 0, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 464, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 467, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 470, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 479, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 481, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 277, 561, 278, 279, 280, 281, 282,
283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
293, 294, 295, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 277, 562, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 277, 563, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 277, 564, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 277, 565, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 277, 566, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 277, 591, 278, 279,
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 277,
610, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 277,
616, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 277,
617, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 277,
621, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 277,
632, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 277,
634, 278, 279, 280, 281, 282, 283, 284, 285, 286,
287, 288, 289, 290, 291, 292, 293, 294, 295, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277, 296, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
277, 459, 278, 279, 280, 281, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
0, 465, 0, 0, 0, 0, 0, 0, 0, 71,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 466, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 71, 0, 0, 0, 0, 0, 0,
0, 475, 0, 72, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 476, 0, 0, 0, 461, 0, 72, 0, 0,
0, 73, 277, 0, 278, 279, 280, 281, 282, 283,
284, 285, 286, 287, 288, 289, 290, 291, 292, 293,
294, 295, 480, 0, 537, 73, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 74, 0, 0, 0,
0, 0, 766, 75, 76, 77, 78, 79, -43, 80,
81, 82, 0, 0, 83, 84, 0, 85, 86, 87,
74, 0, 0, 0, 88, 89, 90, 75, 76, 77,
78, 79, 0, 80, 81, 82, 0, 0, 83, 84,
0, 85, 86, 87, 0, 0, 0, 0, 88, 89,
90, 277, 483, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 277, 543, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 277, 0, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 281, 282, 283, 284, 285, 286, 287, 288, 289,
290, 291, 292, 293, 294, 295, 282, 283, 284, 285,
286, 287, 288, 289, 290, 291, 292, 293, 294, 295
};
 
static const yytype_int16 yycheck[] =
{
75, 73, 107, 23, 220, 18, 4, 4, 4, 4,
85, 116, 4, 25, 239, 231, 232, 92, 4, 4,
492, 4, 5, 15, 4, 4, 5, 673, 4, 15,
15, 4, 21, 4, 4, 5, 495, 6, 4, 5,
32, 233, 58, 59, 6, 4, 32, 32, 70, 71,
72, 73, 74, 4, 581, 58, 15, 129, 130, 4,
132, 133, 54, 55, 56, 57, 138, 4, 4, 54,
55, 56, 57, 32, 0, 690, 4, 692, 153, 154,
126, 127, 128, 4, 5, 132, 698, 15, 4, 5,
617, 137, 4, 5, 147, 132, 149, 6, 4, 711,
146, 148, 177, 178, 32, 180, 4, 16, 147, 15,
725, 148, 151, 188, 59, 66, 132, 15, 4, 591,
579, 36, 59, 58, 107, 4, 32, 149, 107, 132,
6, 102, 147, 208, 32, 130, 151, 107, 133, 134,
135, 107, 37, 147, 59, 149, 218, 793, 54, 55,
142, 149, 144, 149, 152, 152, 54, 55, 150, 144,
149, 353, 634, 149, 147, 150, 149, 147, 147, 244,
149, 147, 247, 248, 147, 250, 251, 147, 147, 149,
255, 256, 257, 258, 259, 147, 107, 262, 200, 201,
149, 107, 267, 268, 100, 107, 271, 272, 273, 32,
33, 34, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 296, 297, 298, 58, 450, 147, 58, 149, 304,
305, 147, 147, 149, 139, 140, 141, 58, 144, 3,
4, 49, 50, 147, 130, 149, 144, 133, 134, 135,
37, 130, 638, 325, 133, 134, 135, 147, 148, 364,
365, 366, 37, 4, 39, 663, 30, 31, 666, 147,
147, 149, 149, 37, 38, 39, 3, 4, 350, 58,
352, 4, 4, 37, 670, 37, 511, 51, 52, 53,
783, 784, 690, 37, 692, 37, 60, 771, 772, 37,
37, 65, 37, 37, 37, 37, 70, 71, 72, 73,
74, 75, 698, 37, 136, 4, 80, 81, 82, 83,
84, 85, 86, 336, 722, 711, 15, 725, 37, 93,
37, 95, 37, 37, 559, 37, 4, 59, 4, 555,
4, 4, 4, 32, 66, 4, 4, 111, 4, 369,
4, 3, 74, 117, 118, 4, 4, 79, 113, 4,
435, 16, 437, 438, 439, 54, 55, 56, 57, 16,
3, 4, 59, 6, 148, 4, 98, 59, 148, 4,
4, 145, 104, 105, 106, 149, 15, 462, 152, 153,
465, 466, 4, 468, 4, 117, 4, 30, 31, 4,
475, 476, 4, 32, 37, 38, 39, 130, 483, 4,
133, 134, 135, 4, 4, 37, 428, 4, 51, 52,
53, 4, 4, 37, 58, 54, 55, 60, 36, 147,
37, 37, 65, 4, 28, 29, 30, 31, 32, 33,
34, 37, 75, 4, 37, 37, 147, 80, 81, 82,
83, 84, 85, 86, 147, 144, 37, 37, 66, 37,
93, 536, 95, 37, 37, 37, 74, 37, 37, 37,
37, 79, 30, 31, 32, 33, 34, 37, 111, 58,
585, 37, 37, 37, 117, 118, 37, 147, 59, 37,
98, 148, 6, 59, 59, 66, 104, 105, 106, 574,
6, 6, 148, 74, 4, 580, 149, 582, 79, 117,
147, 149, 145, 618, 147, 527, 528, 149, 593, 152,
153, 149, 149, 149, 4, 4, 149, 98, 3, 4,
149, 6, 149, 104, 105, 106, 149, 4, 613, 4,
4, 4, 4, 4, 619, 4, 117, 4, 4, 4,
148, 148, 4, 4, 37, 30, 31, 4, 147, 37,
4, 149, 37, 38, 39, 149, 58, 16, 37, 4,
4, 787, 149, 149, 149, 16, 51, 52, 53, 37,
16, 102, 654, 799, 800, 60, 149, 149, 147, 92,
65, 696, 149, 4, 4, 93, 149, 149, 36, 149,
75, 16, 149, 148, 37, 80, 81, 82, 83, 84,
85, 86, 149, 149, 59, 149, 38, 37, 93, 58,
95, 37, 149, 6, 147, 3, 4, 6, 7, 8,
9, 10, 11, 12, 13, 14, 111, 148, 37, 714,
148, 143, 117, 118, 37, 95, 59, 6, 37, 103,
16, 58, 30, 31, 58, 37, 16, 37, 37, 37,
38, 39, 40, 37, 37, 37, 37, 37, 37, 37,
145, 59, 147, 51, 52, 53, 37, 152, 153, 37,
25, 58, 60, 37, 4, 37, 37, 65, 6, 7,
8, 9, 10, 11, 12, 13, 14, 75, 37, 4,
3, 4, 80, 81, 82, 83, 84, 85, 86, 37,
102, 37, 149, 16, 37, 93, 37, 95, 149, 149,
37, 149, 149, 149, 149, 59, 25, 30, 31, 36,
149, 149, 4, 111, 37, 38, 39, 4, 4, 117,
118, 149, 4, 149, 676, 677, 678, 679, 51, 52,
53, 149, 149, 685, 149, 149, 249, 60, 149, 149,
735, 715, 65, 149, 149, 774, 444, 145, 143, 670,
216, 755, 75, 545, 152, 153, 505, 80, 81, 82,
83, 84, 85, 86, 3, 4, 595, 719, 720, 26,
93, 100, 95, 726, 438, 341, -1, 570, 246, -1,
732, 733, -1, 735, -1, 737, 738, -1, 111, -1,
-1, 30, 31, -1, 117, 118, -1, 749, 37, 38,
39, -1, -1, -1, -1, -1, -1, -1, -1, -1,
762, -1, 51, 52, 53, -1, -1, -1, -1, -1,
-1, 60, 145, -1, -1, -1, 65, 779, -1, 152,
153, -1, -1, -1, -1, -1, 75, -1, -1, -1,
-1, 80, 81, 82, 83, 84, 85, 86, 4, -1,
-1, -1, -1, -1, 93, -1, 95, -1, -1, 15,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, -1, 111, -1, -1, -1, 32, -1, 117, 118,
-1, -1, -1, -1, -1, 41, 42, 43, 44, 45,
-1, -1, -1, -1, -1, -1, -1, -1, 54, 55,
56, 57, -1, -1, -1, -1, 145, -1, -1, -1,
66, -1, -1, 152, 153, -1, 15, -1, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, -1, -1, 94, -1,
96, 4, -1, -1, 100, -1, -1, -1, 104, 105,
106, -1, -1, -1, -1, -1, -1, -1, -1, -1,
15, 117, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-1, -1, 138, 46, 47, 48, 142, -1, 144, -1,
-1, -1, 148, -1, 150, -1, -1, -1, 61, 62,
63, 64, -1, 66, 67, 68, 69, -1, -1, -1,
-1, -1, -1, 76, 77, 78, 79, 4, -1, -1,
-1, -1, -1, -1, 87, 88, 89, 90, 91, 92,
-1, -1, -1, -1, 97, 98, 99, -1, -1, -1,
-1, 104, 105, 106, -1, -1, -1, -1, 147, 36,
149, -1, -1, -1, 117, -1, -1, -1, -1, 46,
47, 48, -1, -1, -1, -1, -1, 130, -1, -1,
-1, -1, -1, 136, 61, 62, 63, 64, -1, 66,
67, 68, 69, -1, -1, 148, -1, -1, -1, 76,
77, 78, 79, -1, 149, -1, -1, -1, -1, -1,
87, 88, 89, 90, 91, 92, -1, -1, -1, -1,
97, 98, 99, -1, -1, -1, -1, 104, 105, 106,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
117, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 130, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, 148, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 15, 149, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 15, 149, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, 15,
149, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32, 33, 34, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
15, 147, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
15, 147, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-1, 147, -1, -1, -1, -1, -1, -1, -1, 4,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 147, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4, -1, -1, -1, -1, -1, -1,
-1, 147, -1, 38, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 147, -1, -1, -1, 36, -1, 38, -1, -1,
-1, 66, 15, -1, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 147, -1, 37, 66, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 101, -1, -1, -1,
-1, -1, 147, 108, 109, 110, 111, 112, 113, 114,
115, 116, -1, -1, 119, 120, -1, 122, 123, 124,
101, -1, -1, -1, 129, 130, 131, 108, 109, 110,
111, 112, -1, 114, 115, 116, -1, -1, 119, 120,
-1, 122, 123, 124, -1, -1, -1, -1, 129, 130,
131, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 15, -1, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34
};
 
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint16 yystos[] =
{
0, 126, 127, 128, 137, 146, 155, 171, 172, 159,
160, 157, 158, 271, 272, 266, 267, 0, 173, 161,
4, 58, 132, 275, 276, 58, 268, 269, 4, 46,
47, 48, 61, 62, 63, 64, 66, 67, 68, 69,
76, 77, 78, 79, 87, 88, 89, 90, 91, 92,
97, 98, 99, 104, 105, 106, 117, 130, 148, 174,
181, 183, 204, 206, 217, 218, 220, 222, 258, 273,
274, 4, 38, 66, 101, 108, 109, 110, 111, 112,
114, 115, 116, 119, 120, 122, 123, 124, 129, 130,
131, 162, 6, 4, 130, 133, 134, 135, 278, 279,
58, 276, 134, 135, 270, 279, 269, 6, 7, 8,
9, 10, 11, 12, 13, 14, 202, 58, 58, 49,
50, 37, 37, 4, 156, 58, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 175, 37, 37,
37, 37, 184, 37, 147, 148, 203, 136, 4, 156,
4, 3, 4, 30, 31, 37, 38, 39, 51, 52,
53, 60, 65, 75, 80, 81, 82, 83, 84, 85,
86, 93, 95, 111, 117, 118, 145, 152, 153, 226,
4, 4, 166, 4, 165, 164, 4, 4, 4, 226,
4, 3, 4, 167, 168, 169, 4, 113, 226, 4,
16, 16, 59, 148, 278, 59, 148, 224, 225, 224,
182, 259, 4, 4, 4, 4, 176, 4, 66, 207,
208, 209, 4, 4, 4, 156, 156, 4, 156, 149,
156, 219, 221, 4, 223, 4, 5, 107, 177, 37,
156, 4, 4, 4, 37, 168, 58, 6, 147, 163,
6, 147, 226, 226, 226, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
37, 37, 37, 37, 37, 226, 226, 15, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
29, 30, 31, 32, 33, 34, 147, 6, 147, 226,
147, 147, 4, 147, 6, 147, 226, 147, 147, 4,
170, 58, 279, 279, 148, 4, 130, 133, 134, 135,
59, 148, 226, 4, 59, 66, 74, 98, 183, 233,
4, 59, 260, 147, 149, 149, 173, 210, 156, 59,
147, 205, 147, 149, 149, 149, 149, 149, 149, 149,
205, 149, 205, 147, 223, 149, 37, 4, 5, 107,
147, 149, 177, 149, 6, 6, 6, 226, 149, 275,
226, 226, 161, 226, 226, 149, 226, 226, 226, 226,
226, 4, 4, 226, 4, 4, 4, 4, 226, 226,
4, 4, 226, 226, 226, 4, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
226, 226, 226, 226, 226, 226, 226, 226, 4, 4,
4, 226, 226, 3, 4, 4, 4, 147, 281, 148,
148, 4, 132, 148, 277, 234, 156, 239, 244, 261,
4, 36, 37, 214, 211, 209, 4, 156, 156, 223,
178, 37, 4, 5, 107, 149, 224, 224, 224, 147,
59, 36, 147, 149, 149, 147, 147, 149, 147, 149,
149, 149, 149, 149, 149, 147, 147, 149, 149, 149,
147, 149, 149, 16, 4, 279, 135, 58, 132, 148,
37, 40, 226, 248, 249, 246, 16, 226, 250, 249,
226, 263, 147, 4, 152, 215, 216, 16, 207, 149,
177, 180, 37, 149, 149, 149, 4, 226, 226, 226,
226, 226, 226, 4, 226, 148, 282, 16, 280, 70,
71, 72, 73, 74, 149, 247, 37, 37, 248, 16,
102, 228, 182, 16, 92, 251, 245, 4, 102, 264,
4, 4, 149, 216, 93, 212, 36, 149, 177, 179,
149, 149, 149, 149, 149, 149, 149, 149, 59, 279,
279, 149, 226, 16, 37, 38, 229, 36, 228, 58,
37, 265, 37, 262, 149, 6, 205, 149, 177, 148,
282, 149, 226, 37, 143, 230, 103, 231, 182, 226,
264, 226, 148, 224, 95, 213, 149, 59, 39, 248,
149, 226, 231, 37, 240, 59, 149, 149, 6, 37,
16, 149, 235, 226, 58, 264, 224, 226, 139, 140,
141, 232, 149, 241, 149, 58, 254, 248, 236, 4,
59, 16, 4, 15, 32, 41, 42, 43, 44, 45,
54, 55, 56, 57, 66, 94, 96, 100, 117, 138,
142, 144, 148, 150, 185, 186, 188, 191, 192, 194,
197, 198, 199, 204, 255, 242, 37, 37, 37, 37,
156, 37, 195, 37, 37, 37, 4, 54, 186, 190,
37, 4, 150, 186, 194, 59, 37, 203, 58, 25,
252, 54, 55, 100, 144, 185, 54, 55, 185, 185,
185, 196, 200, 224, 37, 193, 4, 187, 185, 189,
37, 151, 205, 190, 190, 37, 237, 224, 198, 4,
102, 227, 37, 37, 149, 37, 149, 37, 37, 149,
149, 149, 198, 149, 226, 4, 191, 21, 149, 149,
185, 186, 149, 151, 190, 252, 149, 59, 25, 253,
185, 185, 189, 185, 185, 36, 147, 149, 4, 185,
149, 227, 256, 4, 6, 16, 201, 149, 149, 149,
149, 149, 4, 253, 253, 200, 4, 243, 149, 149,
185, 149, 149, 149, 201, 201, 205, 149, 203, 238,
257, 205, 205
};
 
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY (-2)
#define YYEOF 0
 
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
 
 
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
Once GCC version 2 has supplanted version 1, this can go. */
 
#define YYFAIL goto yyerrlab
 
#define YYRECOVERING() (!!yyerrstatus)
 
#define YYBACKUP(Token, Value) \
do \
if (yychar == YYEMPTY && yylen == 1) \
{ \
yychar = (Token); \
yylval = (Value); \
yytoken = YYTRANSLATE (yychar); \
YYPOPSTACK (1); \
goto yybackup; \
} \
else \
{ \
yyerror (YY_("syntax error: cannot back up")); \
YYERROR; \
} \
while (YYID (0))
 
 
#define YYTERROR 1
#define YYERRCODE 256
 
 
/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
If N is 0, then set CURRENT to the empty location which ends
the previous symbol: RHS[0] (always defined). */
 
#define YYRHSLOC(Rhs, K) ((Rhs)[K])
#ifndef YYLLOC_DEFAULT
# define YYLLOC_DEFAULT(Current, Rhs, N) \
do \
if (YYID (N)) \
{ \
(Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
(Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
(Current).last_line = YYRHSLOC (Rhs, N).last_line; \
(Current).last_column = YYRHSLOC (Rhs, N).last_column; \
} \
else \
{ \
(Current).first_line = (Current).last_line = \
YYRHSLOC (Rhs, 0).last_line; \
(Current).first_column = (Current).last_column = \
YYRHSLOC (Rhs, 0).last_column; \
} \
while (YYID (0))
#endif
 
 
/* YY_LOCATION_PRINT -- Print the location on the stream.
This macro was not mandated originally: define only if we know
we won't break user code: when these are the locations we know. */
 
#ifndef YY_LOCATION_PRINT
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
(Loc).last_line, (Loc).last_column)
# else
# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
# endif
#endif
 
 
/* YYLEX -- calling `yylex' with the right arguments. */
 
#ifdef YYLEX_PARAM
# define YYLEX yylex (YYLEX_PARAM)
#else
# define YYLEX yylex ()
#endif
 
/* Enable debugging if requested. */
#if YYDEBUG
 
# ifndef YYFPRINTF
# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
# define YYFPRINTF fprintf
# endif
 
# define YYDPRINTF(Args) \
do { \
if (yydebug) \
YYFPRINTF Args; \
} while (YYID (0))
 
# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
do { \
if (yydebug) \
{ \
YYFPRINTF (stderr, "%s ", Title); \
yy_symbol_print (stderr, \
Type, Value); \
YYFPRINTF (stderr, "\n"); \
} \
} while (YYID (0))
 
 
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
 
/*ARGSUSED*/
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
static void
yy_symbol_value_print (yyoutput, yytype, yyvaluep)
FILE *yyoutput;
int yytype;
YYSTYPE const * const yyvaluep;
#endif
{
if (!yyvaluep)
return;
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# else
YYUSE (yyoutput);
# endif
switch (yytype)
{
default:
break;
}
}
 
 
/*--------------------------------.
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
#else
static void
yy_symbol_print (yyoutput, yytype, yyvaluep)
FILE *yyoutput;
int yytype;
YYSTYPE const * const yyvaluep;
#endif
{
if (yytype < YYNTOKENS)
YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
else
YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
 
yy_symbol_value_print (yyoutput, yytype, yyvaluep);
YYFPRINTF (yyoutput, ")");
}
 
/*------------------------------------------------------------------.
| yy_stack_print -- Print the state stack from its BOTTOM up to its |
| TOP (included). |
`------------------------------------------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
#else
static void
yy_stack_print (bottom, top)
yytype_int16 *bottom;
yytype_int16 *top;
#endif
{
YYFPRINTF (stderr, "Stack now");
for (; bottom <= top; ++bottom)
YYFPRINTF (stderr, " %d", *bottom);
YYFPRINTF (stderr, "\n");
}
 
# define YY_STACK_PRINT(Bottom, Top) \
do { \
if (yydebug) \
yy_stack_print ((Bottom), (Top)); \
} while (YYID (0))
 
 
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
 
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
#else
static void
yy_reduce_print (yyvsp, yyrule)
YYSTYPE *yyvsp;
int yyrule;
#endif
{
int yynrhs = yyr2[yyrule];
int yyi;
unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
fprintf (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
);
fprintf (stderr, "\n");
}
}
 
# define YY_REDUCE_PRINT(Rule) \
do { \
if (yydebug) \
yy_reduce_print (yyvsp, Rule); \
} while (YYID (0))
 
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
int yydebug;
#else /* !YYDEBUG */
# define YYDPRINTF(Args)
# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
# define YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */
 
 
/* YYINITDEPTH -- initial size of the parser's stacks. */
#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif
 
/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
if the built-in stack extension method is used).
 
Do not make this value too large; the results are undefined if
YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
evaluated with infinite-precision integer arithmetic. */
 
#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif
 
 
#if YYERROR_VERBOSE
 
# ifndef yystrlen
# if defined __GLIBC__ && defined _STRING_H
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
#else
static YYSIZE_T
yystrlen (yystr)
const char *yystr;
#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
continue;
return yylen;
}
# endif
# endif
 
# ifndef yystpcpy
# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
# define yystpcpy stpcpy
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
#else
static char *
yystpcpy (yydest, yysrc)
char *yydest;
const char *yysrc;
#endif
{
char *yyd = yydest;
const char *yys = yysrc;
 
while ((*yyd++ = *yys++) != '\0')
continue;
 
return yyd - 1;
}
# endif
# endif
 
# ifndef yytnamerr
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
quotes and backslashes, so that it's suitable for yyerror. The
heuristic is that double-quoting is unnecessary unless the string
contains an apostrophe, a comma, or backslash (other than
backslash-backslash). YYSTR is taken from yytname. If YYRES is
null, do not copy; instead, return the length of what the result
would have been. */
static YYSIZE_T
yytnamerr (char *yyres, const char *yystr)
{
if (*yystr == '"')
{
YYSIZE_T yyn = 0;
char const *yyp = yystr;
 
for (;;)
switch (*++yyp)
{
case '\'':
case ',':
goto do_not_strip_quotes;
 
case '\\':
if (*++yyp != '\\')
goto do_not_strip_quotes;
/* Fall through. */
default:
if (yyres)
yyres[yyn] = *yyp;
yyn++;
break;
 
case '"':
if (yyres)
yyres[yyn] = '\0';
return yyn;
}
do_not_strip_quotes: ;
}
 
if (! yyres)
return yystrlen (yystr);
 
return yystpcpy (yyres, yystr) - yyres;
}
# endif
 
/* Copy into YYRESULT an error message about the unexpected token
YYCHAR while in state YYSTATE. Return the number of bytes copied,
including the terminating null byte. If YYRESULT is null, do not
copy anything; just return the number of bytes that would be
copied. As a special case, return 0 if an ordinary "syntax error"
message will do. Return YYSIZE_MAXIMUM if overflow occurs during
size calculation. */
static YYSIZE_T
yysyntax_error (char *yyresult, int yystate, int yychar)
{
int yyn = yypact[yystate];
 
if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
return 0;
else
{
int yytype = YYTRANSLATE (yychar);
YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
YYSIZE_T yysize = yysize0;
YYSIZE_T yysize1;
int yysize_overflow = 0;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
int yyx;
 
# if 0
/* This is so xgettext sees the translatable formats that are
constructed on the fly. */
YY_("syntax error, unexpected %s");
YY_("syntax error, unexpected %s, expecting %s");
YY_("syntax error, unexpected %s, expecting %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s");
YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
# endif
char *yyfmt;
char const *yyf;
static char const yyunexpected[] = "syntax error, unexpected %s";
static char const yyexpecting[] = ", expecting %s";
static char const yyor[] = " or %s";
char yyformat[sizeof yyunexpected
+ sizeof yyexpecting - 1
+ ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
* (sizeof yyor - 1))];
char const *yyprefix = yyexpecting;
 
/* Start YYX at -YYN if negative to avoid negative indexes in
YYCHECK. */
int yyxbegin = yyn < 0 ? -yyn : 0;
 
/* Stay within bounds of both yycheck and yytname. */
int yychecklim = YYLAST - yyn + 1;
int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
int yycount = 1;
 
yyarg[0] = yytname[yytype];
yyfmt = yystpcpy (yyformat, yyunexpected);
 
for (yyx = yyxbegin; yyx < yyxend; ++yyx)
if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
{
if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
{
yycount = 1;
yysize = yysize0;
yyformat[sizeof yyunexpected - 1] = '\0';
break;
}
yyarg[yycount++] = yytname[yyx];
yysize1 = yysize + yytnamerr (0, yytname[yyx]);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
yyfmt = yystpcpy (yyfmt, yyprefix);
yyprefix = yyor;
}
 
yyf = YY_(yyformat);
yysize1 = yysize + yystrlen (yyf);
yysize_overflow |= (yysize1 < yysize);
yysize = yysize1;
 
if (yysize_overflow)
return YYSIZE_MAXIMUM;
 
if (yyresult)
{
/* Avoid sprintf, as that infringes on the user's name space.
Don't have undefined behavior even if the translation
produced a string with the wrong number of "%s"s. */
char *yyp = yyresult;
int yyi = 0;
while ((*yyp = *yyf) != '\0')
{
if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
{
yyp += yytnamerr (yyp, yyarg[yyi++]);
yyf += 2;
}
else
{
yyp++;
yyf++;
}
}
}
return yysize;
}
}
#endif /* YYERROR_VERBOSE */
 
/*-----------------------------------------------.
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
 
/*ARGSUSED*/
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
#else
static void
yydestruct (yymsg, yytype, yyvaluep)
const char *yymsg;
int yytype;
YYSTYPE *yyvaluep;
#endif
{
YYUSE (yyvaluep);
 
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
switch (yytype)
{
 
default:
break;
}
}
 
/* Prevent warnings from -Wmissing-prototypes. */
 
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
#else
int yyparse ();
#endif
#else /* ! YYPARSE_PARAM */
#if defined __STDC__ || defined __cplusplus
int yyparse (void);
#else
int yyparse ();
#endif
#endif /* ! YYPARSE_PARAM */
 
 
 
/* The look-ahead symbol. */
int yychar;
 
/* The semantic value of the look-ahead symbol. */
YYSTYPE yylval;
 
/* Number of syntax errors so far. */
int yynerrs;
 
 
 
/*----------.
| yyparse. |
`----------*/
 
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
int
yyparse (void *YYPARSE_PARAM)
#else
int
yyparse (YYPARSE_PARAM)
void *YYPARSE_PARAM;
#endif
#else /* ! YYPARSE_PARAM */
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
#else
int
yyparse ()
 
#endif
#endif
{
int yystate;
int yyn;
int yyresult;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* Look-ahead token as an internal (translated) token number. */
int yytoken = 0;
#if YYERROR_VERBOSE
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
#endif
 
/* Three stacks and their tools:
`yyss': related to states,
`yyvs': related to semantic values,
`yyls': related to locations.
 
Refer to the stacks thru separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
 
/* The state stack. */
yytype_int16 yyssa[YYINITDEPTH];
yytype_int16 *yyss = yyssa;
yytype_int16 *yyssp;
 
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
YYSTYPE *yyvsp;
 
 
 
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
 
YYSIZE_T yystacksize = YYINITDEPTH;
 
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
 
 
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
 
YYDPRINTF ((stderr, "Starting parse\n"));
 
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
 
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
 
yyssp = yyss;
yyvsp = yyvs;
 
goto yysetstate;
 
/*------------------------------------------------------------.
| yynewstate -- Push a new state, which is found in yystate. |
`------------------------------------------------------------*/
yynewstate:
/* In all cases, when you get here, the value and location stacks
have just been pushed. So pushing a state here evens the stacks. */
yyssp++;
 
yysetstate:
*yyssp = yystate;
 
if (yyss + yystacksize - 1 <= yyssp)
{
/* Get the current used size of the three stacks, in elements. */
YYSIZE_T yysize = yyssp - yyss + 1;
 
#ifdef yyoverflow
{
/* Give user a chance to reallocate the stack. Use copies of
these so that the &'s don't force the real ones into
memory. */
YYSTYPE *yyvs1 = yyvs;
yytype_int16 *yyss1 = yyss;
 
 
/* Each stack pointer address is followed by the size of the
data in use in that stack, in bytes. This used to be a
conditional around just the two extra args, but that might
be undefined if yyoverflow is a macro. */
yyoverflow (YY_("memory exhausted"),
&yyss1, yysize * sizeof (*yyssp),
&yyvs1, yysize * sizeof (*yyvsp),
 
&yystacksize);
 
yyss = yyss1;
yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
goto yyexhaustedlab;
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
 
{
yytype_int16 *yyss1 = yyss;
union yyalloc *yyptr =
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
YYSTACK_RELOCATE (yyss);
YYSTACK_RELOCATE (yyvs);
 
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
 
yyssp = yyss + yysize - 1;
yyvsp = yyvs + yysize - 1;
 
 
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
(unsigned long int) yystacksize));
 
if (yyss + yystacksize - 1 <= yyssp)
YYABORT;
}
 
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
goto yybackup;
 
/*-----------.
| yybackup. |
`-----------*/
yybackup:
 
/* Do appropriate processing given the current state. Read a
look-ahead token if we need one and don't already have one. */
 
/* First try to decide what to do without reference to look-ahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
 
/* Not known => get a look-ahead token if don't already have one. */
 
/* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
yychar = YYLEX;
}
 
if (yychar <= YYEOF)
{
yychar = yytoken = YYEOF;
YYDPRINTF ((stderr, "Now at end of input.\n"));
}
else
{
yytoken = YYTRANSLATE (yychar);
YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
}
 
/* If the proper action on seeing token YYTOKEN is to reduce or to
detect an error, take that action. */
yyn += yytoken;
if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
goto yydefault;
yyn = yytable[yyn];
if (yyn <= 0)
{
if (yyn == 0 || yyn == YYTABLE_NINF)
goto yyerrlab;
yyn = -yyn;
goto yyreduce;
}
 
if (yyn == YYFINAL)
YYACCEPT;
 
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
 
/* Shift the look-ahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
/* Discard the shifted token unless it is eof. */
if (yychar != YYEOF)
yychar = YYEMPTY;
 
yystate = yyn;
*++yyvsp = yylval;
 
goto yynewstate;
 
 
/*-----------------------------------------------------------.
| yydefault -- do the default action for the current state. |
`-----------------------------------------------------------*/
yydefault:
yyn = yydefact[yystate];
if (yyn == 0)
goto yyerrlab;
goto yyreduce;
 
 
/*-----------------------------.
| yyreduce -- Do a reduction. |
`-----------------------------*/
yyreduce:
/* yyn is the number of a rule to reduce with. */
yylen = yyr2[yyn];
 
/* If YYLEN is nonzero, implement the default value of the action:
`$$ = $1'.
 
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
users should not rely upon it. Assigning to YYVAL
unconditionally makes the parser a bit smaller, and it avoids a
GCC warning that YYVAL may be used uninitialized. */
yyval = yyvsp[1-yylen];
 
 
YY_REDUCE_PRINT (yyn);
switch (yyn)
{
case 8:
#line 178 "ldgram.y"
{ ldlex_defsym(); }
break;
 
case 9:
#line 180 "ldgram.y"
{
ldlex_popstate();
lang_add_assignment (exp_defsym ((yyvsp[(2) - (4)].name), (yyvsp[(4) - (4)].etree)));
}
break;
 
case 10:
#line 188 "ldgram.y"
{
ldlex_mri_script ();
PUSH_ERROR (_("MRI style script"));
}
break;
 
case 11:
#line 193 "ldgram.y"
{
ldlex_popstate ();
mri_draw_tree ();
POP_ERROR ();
}
break;
 
case 16:
#line 208 "ldgram.y"
{
einfo(_("%P%F: unrecognised keyword in MRI style script '%s'\n"),(yyvsp[(1) - (1)].name));
}
break;
 
case 17:
#line 211 "ldgram.y"
{
config.map_filename = "-";
}
break;
 
case 20:
#line 217 "ldgram.y"
{ mri_public((yyvsp[(2) - (4)].name), (yyvsp[(4) - (4)].etree)); }
break;
 
case 21:
#line 219 "ldgram.y"
{ mri_public((yyvsp[(2) - (4)].name), (yyvsp[(4) - (4)].etree)); }
break;
 
case 22:
#line 221 "ldgram.y"
{ mri_public((yyvsp[(2) - (3)].name), (yyvsp[(3) - (3)].etree)); }
break;
 
case 23:
#line 223 "ldgram.y"
{ mri_format((yyvsp[(2) - (2)].name)); }
break;
 
case 24:
#line 225 "ldgram.y"
{ mri_output_section((yyvsp[(2) - (4)].name), (yyvsp[(4) - (4)].etree));}
break;
 
case 25:
#line 227 "ldgram.y"
{ mri_output_section((yyvsp[(2) - (3)].name), (yyvsp[(3) - (3)].etree));}
break;
 
case 26:
#line 229 "ldgram.y"
{ mri_output_section((yyvsp[(2) - (4)].name), (yyvsp[(4) - (4)].etree));}
break;
 
case 27:
#line 231 "ldgram.y"
{ mri_align((yyvsp[(2) - (4)].name),(yyvsp[(4) - (4)].etree)); }
break;
 
case 28:
#line 233 "ldgram.y"
{ mri_align((yyvsp[(2) - (4)].name),(yyvsp[(4) - (4)].etree)); }
break;
 
case 29:
#line 235 "ldgram.y"
{ mri_alignmod((yyvsp[(2) - (4)].name),(yyvsp[(4) - (4)].etree)); }
break;
 
case 30:
#line 237 "ldgram.y"
{ mri_alignmod((yyvsp[(2) - (4)].name),(yyvsp[(4) - (4)].etree)); }
break;
 
case 33:
#line 241 "ldgram.y"
{ mri_name((yyvsp[(2) - (2)].name)); }
break;
 
case 34:
#line 243 "ldgram.y"
{ mri_alias((yyvsp[(2) - (4)].name),(yyvsp[(4) - (4)].name),0);}
break;
 
case 35:
#line 245 "ldgram.y"
{ mri_alias ((yyvsp[(2) - (4)].name), 0, (int) (yyvsp[(4) - (4)].bigint).integer); }
break;
 
case 36:
#line 247 "ldgram.y"
{ mri_base((yyvsp[(2) - (2)].etree)); }
break;
 
case 37:
#line 249 "ldgram.y"
{ mri_truncate ((unsigned int) (yyvsp[(2) - (2)].bigint).integer); }
break;
 
case 40:
#line 253 "ldgram.y"
{ ldlex_script (); ldfile_open_command_file((yyvsp[(2) - (2)].name)); }
break;
 
case 41:
#line 255 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 42:
#line 257 "ldgram.y"
{ lang_add_entry ((yyvsp[(2) - (2)].name), FALSE); }
break;
 
case 44:
#line 262 "ldgram.y"
{ mri_order((yyvsp[(3) - (3)].name)); }
break;
 
case 45:
#line 263 "ldgram.y"
{ mri_order((yyvsp[(2) - (2)].name)); }
break;
 
case 47:
#line 269 "ldgram.y"
{ mri_load((yyvsp[(1) - (1)].name)); }
break;
 
case 48:
#line 270 "ldgram.y"
{ mri_load((yyvsp[(3) - (3)].name)); }
break;
 
case 49:
#line 275 "ldgram.y"
{ mri_only_load((yyvsp[(1) - (1)].name)); }
break;
 
case 50:
#line 277 "ldgram.y"
{ mri_only_load((yyvsp[(3) - (3)].name)); }
break;
 
case 51:
#line 281 "ldgram.y"
{ (yyval.name) = NULL; }
break;
 
case 54:
#line 288 "ldgram.y"
{ ldlex_expression (); }
break;
 
case 55:
#line 290 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 56:
#line 294 "ldgram.y"
{ ldlang_add_undef ((yyvsp[(1) - (1)].name), FALSE); }
break;
 
case 57:
#line 296 "ldgram.y"
{ ldlang_add_undef ((yyvsp[(2) - (2)].name), FALSE); }
break;
 
case 58:
#line 298 "ldgram.y"
{ ldlang_add_undef ((yyvsp[(3) - (3)].name), FALSE); }
break;
 
case 59:
#line 302 "ldgram.y"
{ ldlex_both(); }
break;
 
case 60:
#line 304 "ldgram.y"
{ ldlex_popstate(); }
break;
 
case 73:
#line 325 "ldgram.y"
{ lang_add_target((yyvsp[(3) - (4)].name)); }
break;
 
case 74:
#line 327 "ldgram.y"
{ ldfile_add_library_path ((yyvsp[(3) - (4)].name), FALSE); }
break;
 
case 75:
#line 329 "ldgram.y"
{ lang_add_output((yyvsp[(3) - (4)].name), 1); }
break;
 
case 76:
#line 331 "ldgram.y"
{ lang_add_output_format ((yyvsp[(3) - (4)].name), (char *) NULL,
(char *) NULL, 1); }
break;
 
case 77:
#line 334 "ldgram.y"
{ lang_add_output_format ((yyvsp[(3) - (8)].name), (yyvsp[(5) - (8)].name), (yyvsp[(7) - (8)].name), 1); }
break;
 
case 78:
#line 336 "ldgram.y"
{ ldfile_set_output_arch ((yyvsp[(3) - (4)].name), bfd_arch_unknown); }
break;
 
case 79:
#line 338 "ldgram.y"
{ command_line.force_common_definition = TRUE ; }
break;
 
case 80:
#line 340 "ldgram.y"
{ command_line.inhibit_common_definition = TRUE ; }
break;
 
case 82:
#line 343 "ldgram.y"
{ lang_enter_group (); }
break;
 
case 83:
#line 345 "ldgram.y"
{ lang_leave_group (); }
break;
 
case 84:
#line 347 "ldgram.y"
{ lang_add_map((yyvsp[(3) - (4)].name)); }
break;
 
case 85:
#line 349 "ldgram.y"
{ ldlex_script (); ldfile_open_command_file((yyvsp[(2) - (2)].name)); }
break;
 
case 86:
#line 351 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 87:
#line 353 "ldgram.y"
{
lang_add_nocrossref ((yyvsp[(3) - (4)].nocrossref));
}
break;
 
case 89:
#line 358 "ldgram.y"
{ lang_add_insert ((yyvsp[(3) - (3)].name), 0); }
break;
 
case 90:
#line 360 "ldgram.y"
{ lang_add_insert ((yyvsp[(3) - (3)].name), 1); }
break;
 
case 91:
#line 362 "ldgram.y"
{ lang_memory_region_alias ((yyvsp[(3) - (6)].name), (yyvsp[(5) - (6)].name)); }
break;
 
case 92:
#line 364 "ldgram.y"
{ lang_ld_feature ((yyvsp[(3) - (4)].name)); }
break;
 
case 93:
#line 369 "ldgram.y"
{ lang_add_input_file((yyvsp[(1) - (1)].name),lang_input_file_is_search_file_enum,
(char *)NULL); }
break;
 
case 94:
#line 372 "ldgram.y"
{ lang_add_input_file((yyvsp[(3) - (3)].name),lang_input_file_is_search_file_enum,
(char *)NULL); }
break;
 
case 95:
#line 375 "ldgram.y"
{ lang_add_input_file((yyvsp[(2) - (2)].name),lang_input_file_is_search_file_enum,
(char *)NULL); }
break;
 
case 96:
#line 378 "ldgram.y"
{ lang_add_input_file((yyvsp[(1) - (1)].name),lang_input_file_is_l_enum,
(char *)NULL); }
break;
 
case 97:
#line 381 "ldgram.y"
{ lang_add_input_file((yyvsp[(3) - (3)].name),lang_input_file_is_l_enum,
(char *)NULL); }
break;
 
case 98:
#line 384 "ldgram.y"
{ lang_add_input_file((yyvsp[(2) - (2)].name),lang_input_file_is_l_enum,
(char *)NULL); }
break;
 
case 99:
#line 387 "ldgram.y"
{ (yyval.integer) = input_flags.add_DT_NEEDED_for_regular;
input_flags.add_DT_NEEDED_for_regular = TRUE; }
break;
 
case 100:
#line 390 "ldgram.y"
{ input_flags.add_DT_NEEDED_for_regular = (yyvsp[(3) - (5)].integer); }
break;
 
case 101:
#line 392 "ldgram.y"
{ (yyval.integer) = input_flags.add_DT_NEEDED_for_regular;
input_flags.add_DT_NEEDED_for_regular = TRUE; }
break;
 
case 102:
#line 395 "ldgram.y"
{ input_flags.add_DT_NEEDED_for_regular = (yyvsp[(5) - (7)].integer); }
break;
 
case 103:
#line 397 "ldgram.y"
{ (yyval.integer) = input_flags.add_DT_NEEDED_for_regular;
input_flags.add_DT_NEEDED_for_regular = TRUE; }
break;
 
case 104:
#line 400 "ldgram.y"
{ input_flags.add_DT_NEEDED_for_regular = (yyvsp[(4) - (6)].integer); }
break;
 
case 109:
#line 415 "ldgram.y"
{ lang_add_entry ((yyvsp[(3) - (4)].name), FALSE); }
break;
 
case 111:
#line 417 "ldgram.y"
{ldlex_expression ();}
break;
 
case 112:
#line 418 "ldgram.y"
{ ldlex_popstate ();
lang_add_assignment (exp_assert ((yyvsp[(4) - (7)].etree), (yyvsp[(6) - (7)].name))); }
break;
 
case 113:
#line 426 "ldgram.y"
{
(yyval.cname) = (yyvsp[(1) - (1)].name);
}
break;
 
case 114:
#line 430 "ldgram.y"
{
(yyval.cname) = "*";
}
break;
 
case 115:
#line 434 "ldgram.y"
{
(yyval.cname) = "?";
}
break;
 
case 116:
#line 441 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(1) - (1)].cname);
(yyval.wildcard).sorted = none;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 117:
#line 448 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(5) - (5)].cname);
(yyval.wildcard).sorted = none;
(yyval.wildcard).exclude_name_list = (yyvsp[(3) - (5)].name_list);
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 118:
#line 455 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(3) - (4)].cname);
(yyval.wildcard).sorted = by_name;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 119:
#line 462 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(3) - (4)].cname);
(yyval.wildcard).sorted = by_alignment;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 120:
#line 469 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(3) - (4)].cname);
(yyval.wildcard).sorted = by_none;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 121:
#line 476 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(5) - (7)].cname);
(yyval.wildcard).sorted = by_name_alignment;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 122:
#line 483 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(5) - (7)].cname);
(yyval.wildcard).sorted = by_name;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 123:
#line 490 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(5) - (7)].cname);
(yyval.wildcard).sorted = by_alignment_name;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 124:
#line 497 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(5) - (7)].cname);
(yyval.wildcard).sorted = by_alignment;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 125:
#line 504 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(7) - (8)].cname);
(yyval.wildcard).sorted = by_name;
(yyval.wildcard).exclude_name_list = (yyvsp[(5) - (8)].name_list);
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 126:
#line 511 "ldgram.y"
{
(yyval.wildcard).name = (yyvsp[(3) - (4)].cname);
(yyval.wildcard).sorted = by_init_priority;
(yyval.wildcard).exclude_name_list = NULL;
(yyval.wildcard).section_flag_list = NULL;
}
break;
 
case 127:
#line 520 "ldgram.y"
{
struct flag_info_list *n;
n = ((struct flag_info_list *) xmalloc (sizeof *n));
if ((yyvsp[(1) - (1)].name)[0] == '!')
{
n->with = without_flags;
n->name = &(yyvsp[(1) - (1)].name)[1];
}
else
{
n->with = with_flags;
n->name = (yyvsp[(1) - (1)].name);
}
n->valid = FALSE;
n->next = NULL;
(yyval.flag_info_list) = n;
}
break;
 
case 128:
#line 538 "ldgram.y"
{
struct flag_info_list *n;
n = ((struct flag_info_list *) xmalloc (sizeof *n));
if ((yyvsp[(3) - (3)].name)[0] == '!')
{
n->with = without_flags;
n->name = &(yyvsp[(3) - (3)].name)[1];
}
else
{
n->with = with_flags;
n->name = (yyvsp[(3) - (3)].name);
}
n->valid = FALSE;
n->next = (yyvsp[(1) - (3)].flag_info_list);
(yyval.flag_info_list) = n;
}
break;
 
case 129:
#line 559 "ldgram.y"
{
struct flag_info *n;
n = ((struct flag_info *) xmalloc (sizeof *n));
n->flag_list = (yyvsp[(3) - (4)].flag_info_list);
n->flags_initialized = FALSE;
n->not_with_flags = 0;
n->only_with_flags = 0;
(yyval.flag_info) = n;
}
break;
 
case 130:
#line 572 "ldgram.y"
{
struct name_list *tmp;
tmp = (struct name_list *) xmalloc (sizeof *tmp);
tmp->name = (yyvsp[(2) - (2)].cname);
tmp->next = (yyvsp[(1) - (2)].name_list);
(yyval.name_list) = tmp;
}
break;
 
case 131:
#line 581 "ldgram.y"
{
struct name_list *tmp;
tmp = (struct name_list *) xmalloc (sizeof *tmp);
tmp->name = (yyvsp[(1) - (1)].cname);
tmp->next = NULL;
(yyval.name_list) = tmp;
}
break;
 
case 132:
#line 592 "ldgram.y"
{
struct wildcard_list *tmp;
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = (yyvsp[(1) - (3)].wildcard_list);
tmp->spec = (yyvsp[(3) - (3)].wildcard);
(yyval.wildcard_list) = tmp;
}
break;
 
case 133:
#line 601 "ldgram.y"
{
struct wildcard_list *tmp;
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = NULL;
tmp->spec = (yyvsp[(1) - (1)].wildcard);
(yyval.wildcard_list) = tmp;
}
break;
 
case 134:
#line 612 "ldgram.y"
{
struct wildcard_spec tmp;
tmp.name = (yyvsp[(1) - (1)].name);
tmp.exclude_name_list = NULL;
tmp.sorted = none;
tmp.section_flag_list = NULL;
lang_add_wild (&tmp, NULL, ldgram_had_keep);
}
break;
 
case 135:
#line 621 "ldgram.y"
{
struct wildcard_spec tmp;
tmp.name = (yyvsp[(2) - (2)].name);
tmp.exclude_name_list = NULL;
tmp.sorted = none;
tmp.section_flag_list = (yyvsp[(1) - (2)].flag_info);
lang_add_wild (&tmp, NULL, ldgram_had_keep);
}
break;
 
case 136:
#line 630 "ldgram.y"
{
lang_add_wild (NULL, (yyvsp[(2) - (3)].wildcard_list), ldgram_had_keep);
}
break;
 
case 137:
#line 634 "ldgram.y"
{
struct wildcard_spec tmp;
tmp.name = NULL;
tmp.exclude_name_list = NULL;
tmp.sorted = none;
tmp.section_flag_list = (yyvsp[(1) - (4)].flag_info);
lang_add_wild (&tmp, (yyvsp[(3) - (4)].wildcard_list), ldgram_had_keep);
}
break;
 
case 138:
#line 643 "ldgram.y"
{
lang_add_wild (&(yyvsp[(1) - (4)].wildcard), (yyvsp[(3) - (4)].wildcard_list), ldgram_had_keep);
}
break;
 
case 139:
#line 647 "ldgram.y"
{
(yyvsp[(2) - (5)].wildcard).section_flag_list = (yyvsp[(1) - (5)].flag_info);
lang_add_wild (&(yyvsp[(2) - (5)].wildcard), (yyvsp[(4) - (5)].wildcard_list), ldgram_had_keep);
}
break;
 
case 141:
#line 656 "ldgram.y"
{ ldgram_had_keep = TRUE; }
break;
 
case 142:
#line 658 "ldgram.y"
{ ldgram_had_keep = FALSE; }
break;
 
case 144:
#line 664 "ldgram.y"
{
lang_add_attribute(lang_object_symbols_statement_enum);
}
break;
 
case 146:
#line 669 "ldgram.y"
{
 
lang_add_attribute(lang_constructors_statement_enum);
}
break;
 
case 147:
#line 674 "ldgram.y"
{
constructors_sorted = TRUE;
lang_add_attribute (lang_constructors_statement_enum);
}
break;
 
case 149:
#line 680 "ldgram.y"
{
lang_add_data ((int) (yyvsp[(1) - (4)].integer), (yyvsp[(3) - (4)].etree));
}
break;
 
case 150:
#line 685 "ldgram.y"
{
lang_add_fill ((yyvsp[(3) - (4)].fill));
}
break;
 
case 151:
#line 688 "ldgram.y"
{ldlex_expression ();}
break;
 
case 152:
#line 689 "ldgram.y"
{ ldlex_popstate ();
lang_add_assignment (exp_assert ((yyvsp[(4) - (8)].etree), (yyvsp[(6) - (8)].name))); }
break;
 
case 153:
#line 692 "ldgram.y"
{ ldlex_script (); ldfile_open_command_file((yyvsp[(2) - (2)].name)); }
break;
 
case 154:
#line 694 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 159:
#line 709 "ldgram.y"
{ (yyval.integer) = (yyvsp[(1) - (1)].token); }
break;
 
case 160:
#line 711 "ldgram.y"
{ (yyval.integer) = (yyvsp[(1) - (1)].token); }
break;
 
case 161:
#line 713 "ldgram.y"
{ (yyval.integer) = (yyvsp[(1) - (1)].token); }
break;
 
case 162:
#line 715 "ldgram.y"
{ (yyval.integer) = (yyvsp[(1) - (1)].token); }
break;
 
case 163:
#line 717 "ldgram.y"
{ (yyval.integer) = (yyvsp[(1) - (1)].token); }
break;
 
case 164:
#line 722 "ldgram.y"
{
(yyval.fill) = exp_get_fill ((yyvsp[(1) - (1)].etree), 0, "fill value");
}
break;
 
case 165:
#line 729 "ldgram.y"
{ (yyval.fill) = (yyvsp[(2) - (2)].fill); }
break;
 
case 166:
#line 730 "ldgram.y"
{ (yyval.fill) = (fill_type *) 0; }
break;
 
case 167:
#line 735 "ldgram.y"
{ (yyval.token) = '+'; }
break;
 
case 168:
#line 737 "ldgram.y"
{ (yyval.token) = '-'; }
break;
 
case 169:
#line 739 "ldgram.y"
{ (yyval.token) = '*'; }
break;
 
case 170:
#line 741 "ldgram.y"
{ (yyval.token) = '/'; }
break;
 
case 171:
#line 743 "ldgram.y"
{ (yyval.token) = LSHIFT; }
break;
 
case 172:
#line 745 "ldgram.y"
{ (yyval.token) = RSHIFT; }
break;
 
case 173:
#line 747 "ldgram.y"
{ (yyval.token) = '&'; }
break;
 
case 174:
#line 749 "ldgram.y"
{ (yyval.token) = '|'; }
break;
 
case 177:
#line 759 "ldgram.y"
{
lang_add_assignment (exp_assign ((yyvsp[(1) - (3)].name), (yyvsp[(3) - (3)].etree), FALSE));
}
break;
 
case 178:
#line 763 "ldgram.y"
{
lang_add_assignment (exp_assign ((yyvsp[(1) - (3)].name),
exp_binop ((yyvsp[(2) - (3)].token),
exp_nameop (NAME,
(yyvsp[(1) - (3)].name)),
(yyvsp[(3) - (3)].etree)), FALSE));
}
break;
 
case 179:
#line 771 "ldgram.y"
{
lang_add_assignment (exp_assign ((yyvsp[(3) - (6)].name), (yyvsp[(5) - (6)].etree), TRUE));
}
break;
 
case 180:
#line 775 "ldgram.y"
{
lang_add_assignment (exp_provide ((yyvsp[(3) - (6)].name), (yyvsp[(5) - (6)].etree), FALSE));
}
break;
 
case 181:
#line 779 "ldgram.y"
{
lang_add_assignment (exp_provide ((yyvsp[(3) - (6)].name), (yyvsp[(5) - (6)].etree), TRUE));
}
break;
 
case 189:
#line 802 "ldgram.y"
{ region = lang_memory_region_lookup ((yyvsp[(1) - (1)].name), TRUE); }
break;
 
case 190:
#line 805 "ldgram.y"
{}
break;
 
case 191:
#line 807 "ldgram.y"
{ ldlex_script (); ldfile_open_command_file((yyvsp[(2) - (2)].name)); }
break;
 
case 192:
#line 809 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 193:
#line 814 "ldgram.y"
{
region->origin = exp_get_vma ((yyvsp[(3) - (3)].etree), 0, "origin");
region->current = region->origin;
}
break;
 
case 194:
#line 822 "ldgram.y"
{
region->length = exp_get_vma ((yyvsp[(3) - (3)].etree), -1, "length");
}
break;
 
case 195:
#line 829 "ldgram.y"
{ /* dummy action to avoid bison 1.25 error message */ }
break;
 
case 199:
#line 840 "ldgram.y"
{ lang_set_flags (region, (yyvsp[(1) - (1)].name), 0); }
break;
 
case 200:
#line 842 "ldgram.y"
{ lang_set_flags (region, (yyvsp[(2) - (2)].name), 1); }
break;
 
case 201:
#line 847 "ldgram.y"
{ lang_startup((yyvsp[(3) - (4)].name)); }
break;
 
case 203:
#line 853 "ldgram.y"
{ ldemul_hll((char *)NULL); }
break;
 
case 204:
#line 858 "ldgram.y"
{ ldemul_hll((yyvsp[(3) - (3)].name)); }
break;
 
case 205:
#line 860 "ldgram.y"
{ ldemul_hll((yyvsp[(1) - (1)].name)); }
break;
 
case 207:
#line 868 "ldgram.y"
{ ldemul_syslib((yyvsp[(3) - (3)].name)); }
break;
 
case 209:
#line 874 "ldgram.y"
{ lang_float(TRUE); }
break;
 
case 210:
#line 876 "ldgram.y"
{ lang_float(FALSE); }
break;
 
case 211:
#line 881 "ldgram.y"
{
(yyval.nocrossref) = NULL;
}
break;
 
case 212:
#line 885 "ldgram.y"
{
struct lang_nocrossref *n;
 
n = (struct lang_nocrossref *) xmalloc (sizeof *n);
n->name = (yyvsp[(1) - (2)].name);
n->next = (yyvsp[(2) - (2)].nocrossref);
(yyval.nocrossref) = n;
}
break;
 
case 213:
#line 894 "ldgram.y"
{
struct lang_nocrossref *n;
 
n = (struct lang_nocrossref *) xmalloc (sizeof *n);
n->name = (yyvsp[(1) - (3)].name);
n->next = (yyvsp[(3) - (3)].nocrossref);
(yyval.nocrossref) = n;
}
break;
 
case 214:
#line 904 "ldgram.y"
{ ldlex_expression (); }
break;
 
case 215:
#line 906 "ldgram.y"
{ ldlex_popstate (); (yyval.etree)=(yyvsp[(2) - (2)].etree);}
break;
 
case 216:
#line 911 "ldgram.y"
{ (yyval.etree) = exp_unop ('-', (yyvsp[(2) - (2)].etree)); }
break;
 
case 217:
#line 913 "ldgram.y"
{ (yyval.etree) = (yyvsp[(2) - (3)].etree); }
break;
 
case 218:
#line 915 "ldgram.y"
{ (yyval.etree) = exp_unop ((int) (yyvsp[(1) - (4)].integer),(yyvsp[(3) - (4)].etree)); }
break;
 
case 219:
#line 917 "ldgram.y"
{ (yyval.etree) = exp_unop ('!', (yyvsp[(2) - (2)].etree)); }
break;
 
case 220:
#line 919 "ldgram.y"
{ (yyval.etree) = (yyvsp[(2) - (2)].etree); }
break;
 
case 221:
#line 921 "ldgram.y"
{ (yyval.etree) = exp_unop ('~', (yyvsp[(2) - (2)].etree));}
break;
 
case 222:
#line 924 "ldgram.y"
{ (yyval.etree) = exp_binop ('*', (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 223:
#line 926 "ldgram.y"
{ (yyval.etree) = exp_binop ('/', (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 224:
#line 928 "ldgram.y"
{ (yyval.etree) = exp_binop ('%', (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 225:
#line 930 "ldgram.y"
{ (yyval.etree) = exp_binop ('+', (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 226:
#line 932 "ldgram.y"
{ (yyval.etree) = exp_binop ('-' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 227:
#line 934 "ldgram.y"
{ (yyval.etree) = exp_binop (LSHIFT , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 228:
#line 936 "ldgram.y"
{ (yyval.etree) = exp_binop (RSHIFT , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 229:
#line 938 "ldgram.y"
{ (yyval.etree) = exp_binop (EQ , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 230:
#line 940 "ldgram.y"
{ (yyval.etree) = exp_binop (NE , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 231:
#line 942 "ldgram.y"
{ (yyval.etree) = exp_binop (LE , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 232:
#line 944 "ldgram.y"
{ (yyval.etree) = exp_binop (GE , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 233:
#line 946 "ldgram.y"
{ (yyval.etree) = exp_binop ('<' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 234:
#line 948 "ldgram.y"
{ (yyval.etree) = exp_binop ('>' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 235:
#line 950 "ldgram.y"
{ (yyval.etree) = exp_binop ('&' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 236:
#line 952 "ldgram.y"
{ (yyval.etree) = exp_binop ('^' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 237:
#line 954 "ldgram.y"
{ (yyval.etree) = exp_binop ('|' , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 238:
#line 956 "ldgram.y"
{ (yyval.etree) = exp_trinop ('?' , (yyvsp[(1) - (5)].etree), (yyvsp[(3) - (5)].etree), (yyvsp[(5) - (5)].etree)); }
break;
 
case 239:
#line 958 "ldgram.y"
{ (yyval.etree) = exp_binop (ANDAND , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 240:
#line 960 "ldgram.y"
{ (yyval.etree) = exp_binop (OROR , (yyvsp[(1) - (3)].etree), (yyvsp[(3) - (3)].etree)); }
break;
 
case 241:
#line 962 "ldgram.y"
{ (yyval.etree) = exp_nameop (DEFINED, (yyvsp[(3) - (4)].name)); }
break;
 
case 242:
#line 964 "ldgram.y"
{ (yyval.etree) = exp_bigintop ((yyvsp[(1) - (1)].bigint).integer, (yyvsp[(1) - (1)].bigint).str); }
break;
 
case 243:
#line 966 "ldgram.y"
{ (yyval.etree) = exp_nameop (SIZEOF_HEADERS,0); }
break;
 
case 244:
#line 969 "ldgram.y"
{ (yyval.etree) = exp_nameop (ALIGNOF,(yyvsp[(3) - (4)].name)); }
break;
 
case 245:
#line 971 "ldgram.y"
{ (yyval.etree) = exp_nameop (SIZEOF,(yyvsp[(3) - (4)].name)); }
break;
 
case 246:
#line 973 "ldgram.y"
{ (yyval.etree) = exp_nameop (ADDR,(yyvsp[(3) - (4)].name)); }
break;
 
case 247:
#line 975 "ldgram.y"
{ (yyval.etree) = exp_nameop (LOADADDR,(yyvsp[(3) - (4)].name)); }
break;
 
case 248:
#line 977 "ldgram.y"
{ (yyval.etree) = exp_nameop (CONSTANT,(yyvsp[(3) - (4)].name)); }
break;
 
case 249:
#line 979 "ldgram.y"
{ (yyval.etree) = exp_unop (ABSOLUTE, (yyvsp[(3) - (4)].etree)); }
break;
 
case 250:
#line 981 "ldgram.y"
{ (yyval.etree) = exp_unop (ALIGN_K,(yyvsp[(3) - (4)].etree)); }
break;
 
case 251:
#line 983 "ldgram.y"
{ (yyval.etree) = exp_binop (ALIGN_K,(yyvsp[(3) - (6)].etree),(yyvsp[(5) - (6)].etree)); }
break;
 
case 252:
#line 985 "ldgram.y"
{ (yyval.etree) = exp_binop (DATA_SEGMENT_ALIGN, (yyvsp[(3) - (6)].etree), (yyvsp[(5) - (6)].etree)); }
break;
 
case 253:
#line 987 "ldgram.y"
{ (yyval.etree) = exp_binop (DATA_SEGMENT_RELRO_END, (yyvsp[(5) - (6)].etree), (yyvsp[(3) - (6)].etree)); }
break;
 
case 254:
#line 989 "ldgram.y"
{ (yyval.etree) = exp_unop (DATA_SEGMENT_END, (yyvsp[(3) - (4)].etree)); }
break;
 
case 255:
#line 991 "ldgram.y"
{ /* The operands to the expression node are
placed in the opposite order from the way
in which they appear in the script as
that allows us to reuse more code in
fold_binary. */
(yyval.etree) = exp_binop (SEGMENT_START,
(yyvsp[(5) - (6)].etree),
exp_nameop (NAME, (yyvsp[(3) - (6)].name))); }
break;
 
case 256:
#line 1000 "ldgram.y"
{ (yyval.etree) = exp_unop (ALIGN_K,(yyvsp[(3) - (4)].etree)); }
break;
 
case 257:
#line 1002 "ldgram.y"
{ (yyval.etree) = exp_nameop (NAME,(yyvsp[(1) - (1)].name)); }
break;
 
case 258:
#line 1004 "ldgram.y"
{ (yyval.etree) = exp_binop (MAX_K, (yyvsp[(3) - (6)].etree), (yyvsp[(5) - (6)].etree) ); }
break;
 
case 259:
#line 1006 "ldgram.y"
{ (yyval.etree) = exp_binop (MIN_K, (yyvsp[(3) - (6)].etree), (yyvsp[(5) - (6)].etree) ); }
break;
 
case 260:
#line 1008 "ldgram.y"
{ (yyval.etree) = exp_assert ((yyvsp[(3) - (6)].etree), (yyvsp[(5) - (6)].name)); }
break;
 
case 261:
#line 1010 "ldgram.y"
{ (yyval.etree) = exp_nameop (ORIGIN, (yyvsp[(3) - (4)].name)); }
break;
 
case 262:
#line 1012 "ldgram.y"
{ (yyval.etree) = exp_nameop (LENGTH, (yyvsp[(3) - (4)].name)); }
break;
 
case 263:
#line 1014 "ldgram.y"
{ (yyval.etree) = exp_unop (LOG2CEIL, (yyvsp[(3) - (4)].etree)); }
break;
 
case 264:
#line 1019 "ldgram.y"
{ (yyval.name) = (yyvsp[(3) - (3)].name); }
break;
 
case 265:
#line 1020 "ldgram.y"
{ (yyval.name) = 0; }
break;
 
case 266:
#line 1024 "ldgram.y"
{ (yyval.etree) = (yyvsp[(3) - (4)].etree); }
break;
 
case 267:
#line 1025 "ldgram.y"
{ (yyval.etree) = 0; }
break;
 
case 268:
#line 1029 "ldgram.y"
{ (yyval.etree) = (yyvsp[(3) - (4)].etree); }
break;
 
case 269:
#line 1030 "ldgram.y"
{ (yyval.etree) = 0; }
break;
 
case 270:
#line 1034 "ldgram.y"
{ (yyval.token) = ALIGN_WITH_INPUT; }
break;
 
case 271:
#line 1035 "ldgram.y"
{ (yyval.token) = 0; }
break;
 
case 272:
#line 1039 "ldgram.y"
{ (yyval.etree) = (yyvsp[(3) - (4)].etree); }
break;
 
case 273:
#line 1040 "ldgram.y"
{ (yyval.etree) = 0; }
break;
 
case 274:
#line 1044 "ldgram.y"
{ (yyval.token) = ONLY_IF_RO; }
break;
 
case 275:
#line 1045 "ldgram.y"
{ (yyval.token) = ONLY_IF_RW; }
break;
 
case 276:
#line 1046 "ldgram.y"
{ (yyval.token) = SPECIAL; }
break;
 
case 277:
#line 1047 "ldgram.y"
{ (yyval.token) = 0; }
break;
 
case 278:
#line 1050 "ldgram.y"
{ ldlex_expression(); }
break;
 
case 279:
#line 1055 "ldgram.y"
{ ldlex_popstate (); ldlex_script (); }
break;
 
case 280:
#line 1058 "ldgram.y"
{
lang_enter_output_section_statement((yyvsp[(1) - (10)].name), (yyvsp[(3) - (10)].etree),
sectype,
(yyvsp[(5) - (10)].etree), (yyvsp[(7) - (10)].etree), (yyvsp[(4) - (10)].etree), (yyvsp[(9) - (10)].token), (yyvsp[(6) - (10)].token));
}
break;
 
case 281:
#line 1064 "ldgram.y"
{ ldlex_popstate (); ldlex_expression (); }
break;
 
case 282:
#line 1066 "ldgram.y"
{
ldlex_popstate ();
lang_leave_output_section_statement ((yyvsp[(18) - (18)].fill), (yyvsp[(15) - (18)].name), (yyvsp[(17) - (18)].section_phdr), (yyvsp[(16) - (18)].name));
}
break;
 
case 283:
#line 1071 "ldgram.y"
{}
break;
 
case 284:
#line 1073 "ldgram.y"
{ ldlex_expression (); }
break;
 
case 285:
#line 1075 "ldgram.y"
{ ldlex_popstate (); ldlex_script (); }
break;
 
case 286:
#line 1077 "ldgram.y"
{
lang_enter_overlay ((yyvsp[(3) - (8)].etree), (yyvsp[(6) - (8)].etree));
}
break;
 
case 287:
#line 1082 "ldgram.y"
{ ldlex_popstate (); ldlex_expression (); }
break;
 
case 288:
#line 1084 "ldgram.y"
{
ldlex_popstate ();
lang_leave_overlay ((yyvsp[(5) - (16)].etree), (int) (yyvsp[(4) - (16)].integer),
(yyvsp[(16) - (16)].fill), (yyvsp[(13) - (16)].name), (yyvsp[(15) - (16)].section_phdr), (yyvsp[(14) - (16)].name));
}
break;
 
case 290:
#line 1094 "ldgram.y"
{ ldlex_expression (); }
break;
 
case 291:
#line 1096 "ldgram.y"
{
ldlex_popstate ();
lang_add_assignment (exp_assign (".", (yyvsp[(3) - (3)].etree), FALSE));
}
break;
 
case 293:
#line 1102 "ldgram.y"
{ ldlex_script (); ldfile_open_command_file((yyvsp[(2) - (2)].name)); }
break;
 
case 294:
#line 1104 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 295:
#line 1108 "ldgram.y"
{ sectype = noload_section; }
break;
 
case 296:
#line 1109 "ldgram.y"
{ sectype = noalloc_section; }
break;
 
case 297:
#line 1110 "ldgram.y"
{ sectype = noalloc_section; }
break;
 
case 298:
#line 1111 "ldgram.y"
{ sectype = noalloc_section; }
break;
 
case 299:
#line 1112 "ldgram.y"
{ sectype = noalloc_section; }
break;
 
case 301:
#line 1117 "ldgram.y"
{ sectype = normal_section; }
break;
 
case 302:
#line 1118 "ldgram.y"
{ sectype = normal_section; }
break;
 
case 303:
#line 1122 "ldgram.y"
{ (yyval.etree) = (yyvsp[(1) - (3)].etree); }
break;
 
case 304:
#line 1123 "ldgram.y"
{ (yyval.etree) = (etree_type *)NULL; }
break;
 
case 305:
#line 1128 "ldgram.y"
{ (yyval.etree) = (yyvsp[(3) - (6)].etree); }
break;
 
case 306:
#line 1130 "ldgram.y"
{ (yyval.etree) = (yyvsp[(3) - (10)].etree); }
break;
 
case 307:
#line 1134 "ldgram.y"
{ (yyval.etree) = (yyvsp[(1) - (2)].etree); }
break;
 
case 308:
#line 1135 "ldgram.y"
{ (yyval.etree) = (etree_type *) NULL; }
break;
 
case 309:
#line 1140 "ldgram.y"
{ (yyval.integer) = 0; }
break;
 
case 310:
#line 1142 "ldgram.y"
{ (yyval.integer) = 1; }
break;
 
case 311:
#line 1147 "ldgram.y"
{ (yyval.name) = (yyvsp[(2) - (2)].name); }
break;
 
case 312:
#line 1148 "ldgram.y"
{ (yyval.name) = DEFAULT_MEMORY_REGION; }
break;
 
case 313:
#line 1153 "ldgram.y"
{
(yyval.section_phdr) = NULL;
}
break;
 
case 314:
#line 1157 "ldgram.y"
{
struct lang_output_section_phdr_list *n;
 
n = ((struct lang_output_section_phdr_list *)
xmalloc (sizeof *n));
n->name = (yyvsp[(3) - (3)].name);
n->used = FALSE;
n->next = (yyvsp[(1) - (3)].section_phdr);
(yyval.section_phdr) = n;
}
break;
 
case 316:
#line 1173 "ldgram.y"
{
ldlex_script ();
lang_enter_overlay_section ((yyvsp[(2) - (2)].name));
}
break;
 
case 317:
#line 1178 "ldgram.y"
{ ldlex_popstate (); ldlex_expression (); }
break;
 
case 318:
#line 1180 "ldgram.y"
{
ldlex_popstate ();
lang_leave_overlay_section ((yyvsp[(9) - (9)].fill), (yyvsp[(8) - (9)].section_phdr));
}
break;
 
case 323:
#line 1197 "ldgram.y"
{ ldlex_expression (); }
break;
 
case 324:
#line 1198 "ldgram.y"
{ ldlex_popstate (); }
break;
 
case 325:
#line 1200 "ldgram.y"
{
lang_new_phdr ((yyvsp[(1) - (6)].name), (yyvsp[(3) - (6)].etree), (yyvsp[(4) - (6)].phdr).filehdr, (yyvsp[(4) - (6)].phdr).phdrs, (yyvsp[(4) - (6)].phdr).at,
(yyvsp[(4) - (6)].phdr).flags);
}
break;
 
case 326:
#line 1208 "ldgram.y"
{
(yyval.etree) = (yyvsp[(1) - (1)].etree);
 
if ((yyvsp[(1) - (1)].etree)->type.node_class == etree_name
&& (yyvsp[(1) - (1)].etree)->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", "PT_TLS"
};
 
s = (yyvsp[(1) - (1)].etree)->name.name;
for (i = 0;
i < sizeof phdr_types / sizeof phdr_types[0];
i++)
if (strcmp (s, phdr_types[i]) == 0)
{
(yyval.etree) = exp_intop (i);
break;
}
if (i == sizeof phdr_types / sizeof phdr_types[0])
{
if (strcmp (s, "PT_GNU_EH_FRAME") == 0)
(yyval.etree) = exp_intop (0x6474e550);
else if (strcmp (s, "PT_GNU_STACK") == 0)
(yyval.etree) = exp_intop (0x6474e551);
else
{
einfo (_("\
%X%P:%S: unknown phdr type `%s' (try integer literal)\n"),
NULL, s);
(yyval.etree) = exp_intop (0);
}
}
}
}
break;
 
case 327:
#line 1252 "ldgram.y"
{
memset (&(yyval.phdr), 0, sizeof (struct phdr_info));
}
break;
 
case 328:
#line 1256 "ldgram.y"
{
(yyval.phdr) = (yyvsp[(3) - (3)].phdr);
if (strcmp ((yyvsp[(1) - (3)].name), "FILEHDR") == 0 && (yyvsp[(2) - (3)].etree) == NULL)
(yyval.phdr).filehdr = TRUE;
else if (strcmp ((yyvsp[(1) - (3)].name), "PHDRS") == 0 && (yyvsp[(2) - (3)].etree) == NULL)
(yyval.phdr).phdrs = TRUE;
else if (strcmp ((yyvsp[(1) - (3)].name), "FLAGS") == 0 && (yyvsp[(2) - (3)].etree) != NULL)
(yyval.phdr).flags = (yyvsp[(2) - (3)].etree);
else
einfo (_("%X%P:%S: PHDRS syntax error at `%s'\n"),
NULL, (yyvsp[(1) - (3)].name));
}
break;
 
case 329:
#line 1269 "ldgram.y"
{
(yyval.phdr) = (yyvsp[(5) - (5)].phdr);
(yyval.phdr).at = (yyvsp[(3) - (5)].etree);
}
break;
 
case 330:
#line 1277 "ldgram.y"
{
(yyval.etree) = NULL;
}
break;
 
case 331:
#line 1281 "ldgram.y"
{
(yyval.etree) = (yyvsp[(2) - (3)].etree);
}
break;
 
case 332:
#line 1287 "ldgram.y"
{
ldlex_version_file ();
PUSH_ERROR (_("dynamic list"));
}
break;
 
case 333:
#line 1292 "ldgram.y"
{
ldlex_popstate ();
POP_ERROR ();
}
break;
 
case 337:
#line 1309 "ldgram.y"
{
lang_append_dynamic_list ((yyvsp[(1) - (2)].versyms));
}
break;
 
case 338:
#line 1317 "ldgram.y"
{
ldlex_version_file ();
PUSH_ERROR (_("VERSION script"));
}
break;
 
case 339:
#line 1322 "ldgram.y"
{
ldlex_popstate ();
POP_ERROR ();
}
break;
 
case 340:
#line 1331 "ldgram.y"
{
ldlex_version_script ();
}
break;
 
case 341:
#line 1335 "ldgram.y"
{
ldlex_popstate ();
}
break;
 
case 344:
#line 1347 "ldgram.y"
{
lang_register_vers_node (NULL, (yyvsp[(2) - (4)].versnode), NULL);
}
break;
 
case 345:
#line 1351 "ldgram.y"
{
lang_register_vers_node ((yyvsp[(1) - (5)].name), (yyvsp[(3) - (5)].versnode), NULL);
}
break;
 
case 346:
#line 1355 "ldgram.y"
{
lang_register_vers_node ((yyvsp[(1) - (6)].name), (yyvsp[(3) - (6)].versnode), (yyvsp[(5) - (6)].deflist));
}
break;
 
case 347:
#line 1362 "ldgram.y"
{
(yyval.deflist) = lang_add_vers_depend (NULL, (yyvsp[(1) - (1)].name));
}
break;
 
case 348:
#line 1366 "ldgram.y"
{
(yyval.deflist) = lang_add_vers_depend ((yyvsp[(1) - (2)].deflist), (yyvsp[(2) - (2)].name));
}
break;
 
case 349:
#line 1373 "ldgram.y"
{
(yyval.versnode) = lang_new_vers_node (NULL, NULL);
}
break;
 
case 350:
#line 1377 "ldgram.y"
{
(yyval.versnode) = lang_new_vers_node ((yyvsp[(1) - (2)].versyms), NULL);
}
break;
 
case 351:
#line 1381 "ldgram.y"
{
(yyval.versnode) = lang_new_vers_node ((yyvsp[(3) - (4)].versyms), NULL);
}
break;
 
case 352:
#line 1385 "ldgram.y"
{
(yyval.versnode) = lang_new_vers_node (NULL, (yyvsp[(3) - (4)].versyms));
}
break;
 
case 353:
#line 1389 "ldgram.y"
{
(yyval.versnode) = lang_new_vers_node ((yyvsp[(3) - (8)].versyms), (yyvsp[(7) - (8)].versyms));
}
break;
 
case 354:
#line 1396 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern (NULL, (yyvsp[(1) - (1)].name), ldgram_vers_current_lang, FALSE);
}
break;
 
case 355:
#line 1400 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern (NULL, (yyvsp[(1) - (1)].name), ldgram_vers_current_lang, TRUE);
}
break;
 
case 356:
#line 1404 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern ((yyvsp[(1) - (3)].versyms), (yyvsp[(3) - (3)].name), ldgram_vers_current_lang, FALSE);
}
break;
 
case 357:
#line 1408 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern ((yyvsp[(1) - (3)].versyms), (yyvsp[(3) - (3)].name), ldgram_vers_current_lang, TRUE);
}
break;
 
case 358:
#line 1412 "ldgram.y"
{
(yyval.name) = ldgram_vers_current_lang;
ldgram_vers_current_lang = (yyvsp[(4) - (5)].name);
}
break;
 
case 359:
#line 1417 "ldgram.y"
{
struct bfd_elf_version_expr *pat;
for (pat = (yyvsp[(7) - (9)].versyms); pat->next != NULL; pat = pat->next);
pat->next = (yyvsp[(1) - (9)].versyms);
(yyval.versyms) = (yyvsp[(7) - (9)].versyms);
ldgram_vers_current_lang = (yyvsp[(6) - (9)].name);
}
break;
 
case 360:
#line 1425 "ldgram.y"
{
(yyval.name) = ldgram_vers_current_lang;
ldgram_vers_current_lang = (yyvsp[(2) - (3)].name);
}
break;
 
case 361:
#line 1430 "ldgram.y"
{
(yyval.versyms) = (yyvsp[(5) - (7)].versyms);
ldgram_vers_current_lang = (yyvsp[(4) - (7)].name);
}
break;
 
case 362:
#line 1435 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern (NULL, "global", ldgram_vers_current_lang, FALSE);
}
break;
 
case 363:
#line 1439 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern ((yyvsp[(1) - (3)].versyms), "global", ldgram_vers_current_lang, FALSE);
}
break;
 
case 364:
#line 1443 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern (NULL, "local", ldgram_vers_current_lang, FALSE);
}
break;
 
case 365:
#line 1447 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern ((yyvsp[(1) - (3)].versyms), "local", ldgram_vers_current_lang, FALSE);
}
break;
 
case 366:
#line 1451 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern (NULL, "extern", ldgram_vers_current_lang, FALSE);
}
break;
 
case 367:
#line 1455 "ldgram.y"
{
(yyval.versyms) = lang_new_vers_pattern ((yyvsp[(1) - (3)].versyms), "extern", ldgram_vers_current_lang, FALSE);
}
break;
 
 
/* Line 1267 of yacc.c. */
#line 4490 "ldgram.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
 
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
 
*++yyvsp = yyval;
 
 
/* Now `shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
 
yyn = yyr1[yyn];
 
yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
yystate = yytable[yystate];
else
yystate = yydefgoto[yyn - YYNTOKENS];
 
goto yynewstate;
 
 
/*------------------------------------.
| yyerrlab -- here on detecting error |
`------------------------------------*/
yyerrlab:
/* If not already recovering from an error, report this error. */
if (!yyerrstatus)
{
++yynerrs;
#if ! YYERROR_VERBOSE
yyerror (YY_("syntax error"));
#else
{
YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
{
YYSIZE_T yyalloc = 2 * yysize;
if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
yyalloc = YYSTACK_ALLOC_MAXIMUM;
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
yymsg = (char *) YYSTACK_ALLOC (yyalloc);
if (yymsg)
yymsg_alloc = yyalloc;
else
{
yymsg = yymsgbuf;
yymsg_alloc = sizeof yymsgbuf;
}
}
 
if (0 < yysize && yysize <= yymsg_alloc)
{
(void) yysyntax_error (yymsg, yystate, yychar);
yyerror (yymsg);
}
else
{
yyerror (YY_("syntax error"));
if (yysize != 0)
goto yyexhaustedlab;
}
}
#endif
}
 
 
 
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse look-ahead token after an
error, discard it. */
 
if (yychar <= YYEOF)
{
/* Return failure if at end of input. */
if (yychar == YYEOF)
YYABORT;
}
else
{
yydestruct ("Error: discarding",
yytoken, &yylval);
yychar = YYEMPTY;
}
}
 
/* Else will try to reuse look-ahead token after shifting the error
token. */
goto yyerrlab1;
 
 
/*---------------------------------------------------.
| yyerrorlab -- error raised explicitly by YYERROR. |
`---------------------------------------------------*/
yyerrorlab:
 
/* Pacify compilers like GCC when the user code never invokes
YYERROR and the label yyerrorlab therefore never appears in user
code. */
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
 
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
YY_STACK_PRINT (yyss, yyssp);
yystate = *yyssp;
goto yyerrlab1;
 
 
/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
yyerrstatus = 3; /* Each real token shifted decrements this. */
 
for (;;)
{
yyn = yypact[yystate];
if (yyn != YYPACT_NINF)
{
yyn += YYTERROR;
if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
{
yyn = yytable[yyn];
if (0 < yyn)
break;
}
}
 
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
YYABORT;
 
 
yydestruct ("Error: popping",
yystos[yystate], yyvsp);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
 
if (yyn == YYFINAL)
YYACCEPT;
 
*++yyvsp = yylval;
 
 
/* Shift the error token. */
YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
 
yystate = yyn;
goto yynewstate;
 
 
/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here. |
`-------------------------------------*/
yyacceptlab:
yyresult = 0;
goto yyreturn;
 
/*-----------------------------------.
| yyabortlab -- YYABORT comes here. |
`-----------------------------------*/
yyabortlab:
yyresult = 1;
goto yyreturn;
 
#ifndef yyoverflow
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_("memory exhausted"));
yyresult = 2;
/* Fall through. */
#endif
 
yyreturn:
if (yychar != YYEOF && yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
/* Do not reclaim the symbols of the rule which action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
yystos[*yyssp], yyvsp);
YYPOPSTACK (1);
}
#ifndef yyoverflow
if (yyss != yyssa)
YYSTACK_FREE (yyss);
#endif
#if YYERROR_VERBOSE
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
/* Make sure YYID is used. */
return YYID (yyresult);
}
 
 
#line 1465 "ldgram.y"
 
void
yyerror(arg)
const char *arg;
{
if (ldfile_assumed_script)
einfo (_("%P:%s: file format not recognized; treating as linker script\n"),
ldlex_filename ());
if (error_index > 0 && error_index < ERROR_NAME_MAX)
einfo ("%P%F:%S: %s in %s\n", NULL, arg, error_names[error_index - 1]);
else
einfo ("%P%F:%S: %s\n", NULL, arg);
}
 
/contrib/toolchain/binutils/ld/ldgram.h
0,0 → 1,347
/* A Bison parser, made by GNU Bison 2.3. */
 
/* Skeleton interface for Bison's Yacc-like parsers in C
 
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
 
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, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
 
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
 
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
 
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
INT = 258,
NAME = 259,
LNAME = 260,
OREQ = 261,
ANDEQ = 262,
RSHIFTEQ = 263,
LSHIFTEQ = 264,
DIVEQ = 265,
MULTEQ = 266,
MINUSEQ = 267,
PLUSEQ = 268,
OROR = 269,
ANDAND = 270,
NE = 271,
EQ = 272,
GE = 273,
LE = 274,
RSHIFT = 275,
LSHIFT = 276,
UNARY = 277,
END = 278,
ALIGN_K = 279,
BLOCK = 280,
BIND = 281,
QUAD = 282,
SQUAD = 283,
LONG = 284,
SHORT = 285,
BYTE = 286,
SECTIONS = 287,
PHDRS = 288,
INSERT_K = 289,
AFTER = 290,
BEFORE = 291,
DATA_SEGMENT_ALIGN = 292,
DATA_SEGMENT_RELRO_END = 293,
DATA_SEGMENT_END = 294,
SORT_BY_NAME = 295,
SORT_BY_ALIGNMENT = 296,
SORT_NONE = 297,
SORT_BY_INIT_PRIORITY = 298,
SIZEOF_HEADERS = 299,
OUTPUT_FORMAT = 300,
FORCE_COMMON_ALLOCATION = 301,
OUTPUT_ARCH = 302,
INHIBIT_COMMON_ALLOCATION = 303,
SEGMENT_START = 304,
INCLUDE = 305,
MEMORY = 306,
REGION_ALIAS = 307,
LD_FEATURE = 308,
NOLOAD = 309,
DSECT = 310,
COPY = 311,
INFO = 312,
OVERLAY = 313,
DEFINED = 314,
TARGET_K = 315,
SEARCH_DIR = 316,
MAP = 317,
ENTRY = 318,
NEXT = 319,
SIZEOF = 320,
ALIGNOF = 321,
ADDR = 322,
LOADADDR = 323,
MAX_K = 324,
MIN_K = 325,
STARTUP = 326,
HLL = 327,
SYSLIB = 328,
FLOAT = 329,
NOFLOAT = 330,
NOCROSSREFS = 331,
ORIGIN = 332,
FILL = 333,
LENGTH = 334,
CREATE_OBJECT_SYMBOLS = 335,
INPUT = 336,
GROUP = 337,
OUTPUT = 338,
CONSTRUCTORS = 339,
ALIGNMOD = 340,
AT = 341,
SUBALIGN = 342,
HIDDEN = 343,
PROVIDE = 344,
PROVIDE_HIDDEN = 345,
AS_NEEDED = 346,
CHIP = 347,
LIST = 348,
SECT = 349,
ABSOLUTE = 350,
LOAD = 351,
NEWLINE = 352,
ENDWORD = 353,
ORDER = 354,
NAMEWORD = 355,
ASSERT_K = 356,
LOG2CEIL = 357,
FORMAT = 358,
PUBLIC = 359,
DEFSYMEND = 360,
BASE = 361,
ALIAS = 362,
TRUNCATE = 363,
REL = 364,
INPUT_SCRIPT = 365,
INPUT_MRI_SCRIPT = 366,
INPUT_DEFSYM = 367,
CASE = 368,
EXTERN = 369,
START = 370,
VERS_TAG = 371,
VERS_IDENTIFIER = 372,
GLOBAL = 373,
LOCAL = 374,
VERSIONK = 375,
INPUT_VERSION_SCRIPT = 376,
KEEP = 377,
ONLY_IF_RO = 378,
ONLY_IF_RW = 379,
SPECIAL = 380,
INPUT_SECTION_FLAGS = 381,
ALIGN_WITH_INPUT = 382,
EXCLUDE_FILE = 383,
CONSTANT = 384,
INPUT_DYNAMIC_LIST = 385
};
#endif
/* Tokens. */
#define INT 258
#define NAME 259
#define LNAME 260
#define OREQ 261
#define ANDEQ 262
#define RSHIFTEQ 263
#define LSHIFTEQ 264
#define DIVEQ 265
#define MULTEQ 266
#define MINUSEQ 267
#define PLUSEQ 268
#define OROR 269
#define ANDAND 270
#define NE 271
#define EQ 272
#define GE 273
#define LE 274
#define RSHIFT 275
#define LSHIFT 276
#define UNARY 277
#define END 278
#define ALIGN_K 279
#define BLOCK 280
#define BIND 281
#define QUAD 282
#define SQUAD 283
#define LONG 284
#define SHORT 285
#define BYTE 286
#define SECTIONS 287
#define PHDRS 288
#define INSERT_K 289
#define AFTER 290
#define BEFORE 291
#define DATA_SEGMENT_ALIGN 292
#define DATA_SEGMENT_RELRO_END 293
#define DATA_SEGMENT_END 294
#define SORT_BY_NAME 295
#define SORT_BY_ALIGNMENT 296
#define SORT_NONE 297
#define SORT_BY_INIT_PRIORITY 298
#define SIZEOF_HEADERS 299
#define OUTPUT_FORMAT 300
#define FORCE_COMMON_ALLOCATION 301
#define OUTPUT_ARCH 302
#define INHIBIT_COMMON_ALLOCATION 303
#define SEGMENT_START 304
#define INCLUDE 305
#define MEMORY 306
#define REGION_ALIAS 307
#define LD_FEATURE 308
#define NOLOAD 309
#define DSECT 310
#define COPY 311
#define INFO 312
#define OVERLAY 313
#define DEFINED 314
#define TARGET_K 315
#define SEARCH_DIR 316
#define MAP 317
#define ENTRY 318
#define NEXT 319
#define SIZEOF 320
#define ALIGNOF 321
#define ADDR 322
#define LOADADDR 323
#define MAX_K 324
#define MIN_K 325
#define STARTUP 326
#define HLL 327
#define SYSLIB 328
#define FLOAT 329
#define NOFLOAT 330
#define NOCROSSREFS 331
#define ORIGIN 332
#define FILL 333
#define LENGTH 334
#define CREATE_OBJECT_SYMBOLS 335
#define INPUT 336
#define GROUP 337
#define OUTPUT 338
#define CONSTRUCTORS 339
#define ALIGNMOD 340
#define AT 341
#define SUBALIGN 342
#define HIDDEN 343
#define PROVIDE 344
#define PROVIDE_HIDDEN 345
#define AS_NEEDED 346
#define CHIP 347
#define LIST 348
#define SECT 349
#define ABSOLUTE 350
#define LOAD 351
#define NEWLINE 352
#define ENDWORD 353
#define ORDER 354
#define NAMEWORD 355
#define ASSERT_K 356
#define LOG2CEIL 357
#define FORMAT 358
#define PUBLIC 359
#define DEFSYMEND 360
#define BASE 361
#define ALIAS 362
#define TRUNCATE 363
#define REL 364
#define INPUT_SCRIPT 365
#define INPUT_MRI_SCRIPT 366
#define INPUT_DEFSYM 367
#define CASE 368
#define EXTERN 369
#define START 370
#define VERS_TAG 371
#define VERS_IDENTIFIER 372
#define GLOBAL 373
#define LOCAL 374
#define VERSIONK 375
#define INPUT_VERSION_SCRIPT 376
#define KEEP 377
#define ONLY_IF_RO 378
#define ONLY_IF_RW 379
#define SPECIAL 380
#define INPUT_SECTION_FLAGS 381
#define ALIGN_WITH_INPUT 382
#define EXCLUDE_FILE 383
#define CONSTANT 384
#define INPUT_DYNAMIC_LIST 385
 
 
 
 
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 60 "ldgram.y"
{
bfd_vma integer;
struct big_int
{
bfd_vma integer;
char *str;
} bigint;
fill_type *fill;
char *name;
const char *cname;
struct wildcard_spec wildcard;
struct wildcard_list *wildcard_list;
struct name_list *name_list;
struct flag_info_list *flag_info_list;
struct flag_info *flag_info;
int token;
union etree_union *etree;
struct phdr_info
{
bfd_boolean filehdr;
bfd_boolean phdrs;
union etree_union *at;
union etree_union *flags;
} phdr;
struct lang_nocrossref *nocrossref;
struct lang_output_section_phdr_list *section_phdr;
struct bfd_elf_version_deps *deflist;
struct bfd_elf_version_expr *versyms;
struct bfd_elf_version_tree *versnode;
}
/* Line 1529 of yacc.c. */
#line 340 "ldgram.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
# define YYSTYPE_IS_TRIVIAL 1
#endif
 
extern YYSTYPE yylval;
 
/contrib/toolchain/binutils/ld/ldlang.c
0,0 → 1,8066
/* Linker command language support.
Copyright 1991-2013 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "libiberty.h"
#include "filenames.h"
#include "safe-ctype.h"
#include "obstack.h"
#include "bfdlink.h"
 
#include "ld.h"
#include "ldmain.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldmisc.h"
#include "ldctor.h"
#include "ldfile.h"
#include "ldemul.h"
#include "fnmatch.h"
#include "demangle.h"
#include "hashtab.h"
#include "libbfd.h"
#ifdef ENABLE_PLUGINS
#include "plugin.h"
#endif /* ENABLE_PLUGINS */
 
#include <limits.h>
 
 
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
#endif
 
/* Locals variables. */
static struct obstack stat_obstack;
static struct obstack map_obstack;
 
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
static const char *entry_symbol_default = "start";
static bfd_boolean placed_commons = FALSE;
static bfd_boolean stripped_excluded_sections = FALSE;
static lang_output_section_statement_type *default_common_section;
static bfd_boolean map_option_f;
static bfd_vma print_dot;
static lang_input_statement_type *first_file;
static const char *current_target;
static lang_statement_list_type statement_list;
static struct bfd_hash_table lang_definedness_table;
static lang_statement_list_type *stat_save[10];
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
static struct unique_sections *unique_section_list;
 
/* Forward declarations. */
static void exp_init_os (etree_type *);
static void init_map_userdata (bfd *, asection *, void *);
static lang_input_statement_type *lookup_name (const char *);
static struct bfd_hash_entry *lang_definedness_newfunc
(struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
static void insert_undefined (const char *);
static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
static void print_statement (lang_statement_union_type *,
lang_output_section_statement_type *);
static void print_statement_list (lang_statement_union_type *,
lang_output_section_statement_type *);
static void print_statements (void);
static void print_input_section (asection *, bfd_boolean);
static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
static void lang_record_phdrs (void);
static void lang_do_version_exports_section (void);
static void lang_finalize_version_expr_head
(struct bfd_elf_version_expr_head *);
 
/* Exported variables. */
const char *output_target;
lang_output_section_statement_type *abs_output_section;
lang_statement_list_type lang_output_section_statement;
lang_statement_list_type *stat_ptr = &statement_list;
lang_statement_list_type file_chain = { NULL, NULL };
lang_statement_list_type input_file_chain;
struct bfd_sym_chain entry_symbol = { NULL, NULL };
const char *entry_section = ".text";
struct lang_input_statement_flags input_flags;
bfd_boolean entry_from_cmdline;
bfd_boolean undef_from_cmdline;
bfd_boolean lang_has_input_file = FALSE;
bfd_boolean had_output_filename = FALSE;
bfd_boolean lang_float_flag = FALSE;
bfd_boolean delete_output_file_on_failure = FALSE;
struct lang_phdr *lang_phdr_list;
struct lang_nocrossrefs *nocrossref_list;
 
/* Functions that traverse the linker script and might evaluate
DEFINED() need to increment this. */
int lang_statement_iteration = 0;
 
etree_type *base; /* Relocation base - or null */
 
/* Return TRUE if the PATTERN argument is a wildcard pattern.
Although backslashes are treated specially if a pattern contains
wildcards, we do not consider the mere presence of a backslash to
be enough to cause the pattern to be treated as a wildcard.
That lets us handle DOS filenames more naturally. */
#define wildcardp(pattern) (strpbrk ((pattern), "?*[") != NULL)
 
#define new_stat(x, y) \
(x##_type *) new_statement (x##_enum, sizeof (x##_type), y)
 
#define outside_section_address(q) \
((q)->output_offset + (q)->output_section->vma)
 
#define outside_symbol_address(q) \
((q)->value + outside_section_address (q->section))
 
#define SECTION_NAME_MAP_LENGTH (16)
 
void *
stat_alloc (size_t size)
{
return obstack_alloc (&stat_obstack, size);
}
 
static int
name_match (const char *pattern, const char *name)
{
if (wildcardp (pattern))
return fnmatch (pattern, name, 0);
return strcmp (pattern, name);
}
 
/* If PATTERN is of the form archive:file, return a pointer to the
separator. If not, return NULL. */
 
static char *
archive_path (const char *pattern)
{
char *p = NULL;
 
if (link_info.path_separator == 0)
return p;
 
p = strchr (pattern, link_info.path_separator);
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
if (p == NULL || link_info.path_separator != ':')
return p;
 
/* Assume a match on the second char is part of drive specifier,
as in "c:\silly.dos". */
if (p == pattern + 1 && ISALPHA (*pattern))
p = strchr (p + 1, link_info.path_separator);
#endif
return p;
}
 
/* Given that FILE_SPEC results in a non-NULL SEP result from archive_path,
return whether F matches FILE_SPEC. */
 
static bfd_boolean
input_statement_is_archive_path (const char *file_spec, char *sep,
lang_input_statement_type *f)
{
bfd_boolean match = FALSE;
 
if ((*(sep + 1) == 0
|| name_match (sep + 1, f->filename) == 0)
&& ((sep != file_spec)
== (f->the_bfd != NULL && f->the_bfd->my_archive != NULL)))
{
match = TRUE;
 
if (sep != file_spec)
{
const char *aname = f->the_bfd->my_archive->filename;
*sep = 0;
match = name_match (file_spec, aname) == 0;
*sep = link_info.path_separator;
}
}
return match;
}
 
static bfd_boolean
unique_section_p (const asection *sec,
const lang_output_section_statement_type *os)
{
struct unique_sections *unam;
const char *secnam;
 
if (link_info.relocatable
&& sec->owner != NULL
&& bfd_is_group_section (sec->owner, sec))
return !(os != NULL
&& strcmp (os->name, DISCARD_SECTION_NAME) == 0);
 
secnam = sec->name;
for (unam = unique_section_list; unam; unam = unam->next)
if (name_match (unam->name, secnam) == 0)
return TRUE;
 
return FALSE;
}
 
/* Generic traversal routines for finding matching sections. */
 
/* Try processing a section against a wildcard. This just calls
the callback unless the filename exclusion list is present
and excludes the file. It's hardly ever present so this
function is very fast. */
 
static void
walk_wild_consider_section (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
asection *s,
struct wildcard_list *sec,
callback_t callback,
void *data)
{
struct name_list *list_tmp;
 
/* Don't process sections from files which were excluded. */
for (list_tmp = sec->spec.exclude_name_list;
list_tmp;
list_tmp = list_tmp->next)
{
char *p = archive_path (list_tmp->name);
 
if (p != NULL)
{
if (input_statement_is_archive_path (list_tmp->name, p, file))
return;
}
 
else if (name_match (list_tmp->name, file->filename) == 0)
return;
 
/* FIXME: Perhaps remove the following at some stage? Matching
unadorned archives like this was never documented and has
been superceded by the archive:path syntax. */
else if (file->the_bfd != NULL
&& file->the_bfd->my_archive != NULL
&& name_match (list_tmp->name,
file->the_bfd->my_archive->filename) == 0)
return;
}
 
(*callback) (ptr, sec, s, ptr->section_flag_list, file, data);
}
 
/* Lowest common denominator routine that can handle everything correctly,
but slowly. */
 
static void
walk_wild_section_general (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
asection *s;
struct wildcard_list *sec;
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
sec = ptr->section_list;
if (sec == NULL)
(*callback) (ptr, sec, s, ptr->section_flag_list, file, data);
 
while (sec != NULL)
{
bfd_boolean skip = FALSE;
 
if (sec->spec.name != NULL)
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
 
skip = name_match (sec->spec.name, sname) != 0;
}
 
if (!skip)
walk_wild_consider_section (ptr, file, s, sec, callback, data);
 
sec = sec->next;
}
}
}
 
/* Routines to find a single section given its name. If there's more
than one section with that name, we report that. */
 
typedef struct
{
asection *found_section;
bfd_boolean multiple_sections_found;
} section_iterator_callback_data;
 
static bfd_boolean
section_iterator_callback (bfd *abfd ATTRIBUTE_UNUSED, asection *s, void *data)
{
section_iterator_callback_data *d = (section_iterator_callback_data *) data;
 
if (d->found_section != NULL)
{
d->multiple_sections_found = TRUE;
return TRUE;
}
 
d->found_section = s;
return FALSE;
}
 
static asection *
find_section (lang_input_statement_type *file,
struct wildcard_list *sec,
bfd_boolean *multiple_sections_found)
{
section_iterator_callback_data cb_data = { NULL, FALSE };
 
bfd_get_section_by_name_if (file->the_bfd, sec->spec.name,
section_iterator_callback, &cb_data);
*multiple_sections_found = cb_data.multiple_sections_found;
return cb_data.found_section;
}
 
/* Code for handling simple wildcards without going through fnmatch,
which can be expensive because of charset translations etc. */
 
/* A simple wild is a literal string followed by a single '*',
where the literal part is at least 4 characters long. */
 
static bfd_boolean
is_simple_wild (const char *name)
{
size_t len = strcspn (name, "*?[");
return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
}
 
static bfd_boolean
match_simple_wild (const char *pattern, const char *name)
{
/* The first four characters of the pattern are guaranteed valid
non-wildcard characters. So we can go faster. */
if (pattern[0] != name[0] || pattern[1] != name[1]
|| pattern[2] != name[2] || pattern[3] != name[3])
return FALSE;
 
pattern += 4;
name += 4;
while (*pattern != '*')
if (*name++ != *pattern++)
return FALSE;
 
return TRUE;
}
 
/* Return the numerical value of the init_priority attribute from
section name NAME. */
 
static unsigned long
get_init_priority (const char *name)
{
char *end;
unsigned long init_priority;
 
/* GCC uses the following section names for the init_priority
attribute with numerical values 101 and 65535 inclusive. A
lower value means a higher priority.
 
1: .init_array.NNNN/.fini_array.NNNN: Where NNNN is the
decimal numerical value of the init_priority attribute.
The order of execution in .init_array is forward and
.fini_array is backward.
2: .ctors.NNNN/.dtors.NNNN: Where NNNN is 65535 minus the
decimal numerical value of the init_priority attribute.
The order of execution in .ctors is backward and .dtors
is forward.
*/
if (strncmp (name, ".init_array.", 12) == 0
|| strncmp (name, ".fini_array.", 12) == 0)
{
init_priority = strtoul (name + 12, &end, 10);
return *end ? 0 : init_priority;
}
else if (strncmp (name, ".ctors.", 7) == 0
|| strncmp (name, ".dtors.", 7) == 0)
{
init_priority = strtoul (name + 7, &end, 10);
return *end ? 0 : 65535 - init_priority;
}
 
return 0;
}
 
/* Compare sections ASEC and BSEC according to SORT. */
 
static int
compare_section (sort_type sort, asection *asec, asection *bsec)
{
int ret;
unsigned long ainit_priority, binit_priority;
 
switch (sort)
{
default:
abort ();
 
case by_init_priority:
ainit_priority
= get_init_priority (bfd_get_section_name (asec->owner, asec));
binit_priority
= get_init_priority (bfd_get_section_name (bsec->owner, bsec));
if (ainit_priority == 0 || binit_priority == 0)
goto sort_by_name;
ret = ainit_priority - binit_priority;
if (ret)
break;
else
goto sort_by_name;
 
case by_alignment_name:
ret = (bfd_section_alignment (bsec->owner, bsec)
- bfd_section_alignment (asec->owner, asec));
if (ret)
break;
/* Fall through. */
 
case by_name:
sort_by_name:
ret = strcmp (bfd_get_section_name (asec->owner, asec),
bfd_get_section_name (bsec->owner, bsec));
break;
 
case by_name_alignment:
ret = strcmp (bfd_get_section_name (asec->owner, asec),
bfd_get_section_name (bsec->owner, bsec));
if (ret)
break;
/* Fall through. */
 
case by_alignment:
ret = (bfd_section_alignment (bsec->owner, bsec)
- bfd_section_alignment (asec->owner, asec));
break;
}
 
return ret;
}
 
/* Build a Binary Search Tree to sort sections, unlike insertion sort
used in wild_sort(). BST is considerably faster if the number of
of sections are large. */
 
static lang_section_bst_type **
wild_sort_fast (lang_wild_statement_type *wild,
struct wildcard_list *sec,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
asection *section)
{
lang_section_bst_type **tree;
 
tree = &wild->tree;
if (!wild->filenames_sorted
&& (sec == NULL || sec->spec.sorted == none))
{
/* Append at the right end of tree. */
while (*tree)
tree = &((*tree)->right);
return tree;
}
 
while (*tree)
{
/* Find the correct node to append this section. */
if (compare_section (sec->spec.sorted, section, (*tree)->section) < 0)
tree = &((*tree)->left);
else
tree = &((*tree)->right);
}
 
return tree;
}
 
/* Use wild_sort_fast to build a BST to sort sections. */
 
static void
output_section_callback_fast (lang_wild_statement_type *ptr,
struct wildcard_list *sec,
asection *section,
struct flag_info *sflag_list ATTRIBUTE_UNUSED,
lang_input_statement_type *file,
void *output)
{
lang_section_bst_type *node;
lang_section_bst_type **tree;
lang_output_section_statement_type *os;
 
os = (lang_output_section_statement_type *) output;
 
if (unique_section_p (section, os))
return;
 
node = (lang_section_bst_type *) xmalloc (sizeof (lang_section_bst_type));
node->left = 0;
node->right = 0;
node->section = section;
 
tree = wild_sort_fast (ptr, sec, file, section);
if (tree != NULL)
*tree = node;
}
 
/* Convert a sorted sections' BST back to list form. */
 
static void
output_section_callback_tree_to_list (lang_wild_statement_type *ptr,
lang_section_bst_type *tree,
void *output)
{
if (tree->left)
output_section_callback_tree_to_list (ptr, tree->left, output);
 
lang_add_section (&ptr->children, tree->section, NULL,
(lang_output_section_statement_type *) output);
 
if (tree->right)
output_section_callback_tree_to_list (ptr, tree->right, output);
 
free (tree);
}
 
/* Specialized, optimized routines for handling different kinds of
wildcards */
 
static void
walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
/* We can just do a hash lookup for the section with the right name.
But if that lookup discovers more than one section with the name
(should be rare), we fall back to the general algorithm because
we would otherwise have to sort the sections to make sure they
get processed in the bfd's order. */
bfd_boolean multiple_sections_found;
struct wildcard_list *sec0 = ptr->handler_data[0];
asection *s0 = find_section (file, sec0, &multiple_sections_found);
 
if (multiple_sections_found)
walk_wild_section_general (ptr, file, callback, data);
else if (s0)
walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
}
 
static void
walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
asection *s;
struct wildcard_list *wildsec0 = ptr->handler_data[0];
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
 
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
}
}
 
static void
walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
asection *s;
struct wildcard_list *sec0 = ptr->handler_data[0];
struct wildcard_list *wildsec1 = ptr->handler_data[1];
bfd_boolean multiple_sections_found;
asection *s0 = find_section (file, sec0, &multiple_sections_found);
 
if (multiple_sections_found)
{
walk_wild_section_general (ptr, file, callback, data);
return;
}
 
/* Note that if the section was not found, s0 is NULL and
we'll simply never succeed the s == s0 test below. */
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
/* Recall that in this code path, a section cannot satisfy more
than one spec, so if s == s0 then it cannot match
wildspec1. */
if (s == s0)
walk_wild_consider_section (ptr, file, s, sec0, callback, data);
else
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
 
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec1, callback,
data);
}
}
}
 
static void
walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
asection *s;
struct wildcard_list *sec0 = ptr->handler_data[0];
struct wildcard_list *wildsec1 = ptr->handler_data[1];
struct wildcard_list *wildsec2 = ptr->handler_data[2];
bfd_boolean multiple_sections_found;
asection *s0 = find_section (file, sec0, &multiple_sections_found);
 
if (multiple_sections_found)
{
walk_wild_section_general (ptr, file, callback, data);
return;
}
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
if (s == s0)
walk_wild_consider_section (ptr, file, s, sec0, callback, data);
else
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
 
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
else
{
skip = !match_simple_wild (wildsec2->spec.name, sname);
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec2, callback,
data);
}
}
}
}
 
static void
walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
asection *s;
struct wildcard_list *sec0 = ptr->handler_data[0];
struct wildcard_list *sec1 = ptr->handler_data[1];
struct wildcard_list *wildsec2 = ptr->handler_data[2];
struct wildcard_list *wildsec3 = ptr->handler_data[3];
bfd_boolean multiple_sections_found;
asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
 
if (multiple_sections_found)
{
walk_wild_section_general (ptr, file, callback, data);
return;
}
 
s1 = find_section (file, sec1, &multiple_sections_found);
if (multiple_sections_found)
{
walk_wild_section_general (ptr, file, callback, data);
return;
}
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
if (s == s0)
walk_wild_consider_section (ptr, file, s, sec0, callback, data);
else
if (s == s1)
walk_wild_consider_section (ptr, file, s, sec1, callback, data);
else
{
const char *sname = bfd_get_section_name (file->the_bfd, s);
bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
sname);
 
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec2, callback,
data);
else
{
skip = !match_simple_wild (wildsec3->spec.name, sname);
if (!skip)
walk_wild_consider_section (ptr, file, s, wildsec3,
callback, data);
}
}
}
}
 
static void
walk_wild_section (lang_wild_statement_type *ptr,
lang_input_statement_type *file,
callback_t callback,
void *data)
{
if (file->flags.just_syms)
return;
 
(*ptr->walk_wild_section_handler) (ptr, file, callback, data);
}
 
/* Returns TRUE when name1 is a wildcard spec that might match
something name2 can match. We're conservative: we return FALSE
only if the prefixes of name1 and name2 are different up to the
first wildcard character. */
 
static bfd_boolean
wild_spec_can_overlap (const char *name1, const char *name2)
{
size_t prefix1_len = strcspn (name1, "?*[");
size_t prefix2_len = strcspn (name2, "?*[");
size_t min_prefix_len;
 
/* Note that if there is no wildcard character, then we treat the
terminating 0 as part of the prefix. Thus ".text" won't match
".text." or ".text.*", for example. */
if (name1[prefix1_len] == '\0')
prefix1_len++;
if (name2[prefix2_len] == '\0')
prefix2_len++;
 
min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
 
return memcmp (name1, name2, min_prefix_len) == 0;
}
 
/* Select specialized code to handle various kinds of wildcard
statements. */
 
static void
analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
{
int sec_count = 0;
int wild_name_count = 0;
struct wildcard_list *sec;
int signature;
int data_counter;
 
ptr->walk_wild_section_handler = walk_wild_section_general;
ptr->handler_data[0] = NULL;
ptr->handler_data[1] = NULL;
ptr->handler_data[2] = NULL;
ptr->handler_data[3] = NULL;
ptr->tree = NULL;
 
/* Count how many wildcard_specs there are, and how many of those
actually use wildcards in the name. Also, bail out if any of the
wildcard names are NULL. (Can this actually happen?
walk_wild_section used to test for it.) And bail out if any
of the wildcards are more complex than a simple string
ending in a single '*'. */
for (sec = ptr->section_list; sec != NULL; sec = sec->next)
{
++sec_count;
if (sec->spec.name == NULL)
return;
if (wildcardp (sec->spec.name))
{
++wild_name_count;
if (!is_simple_wild (sec->spec.name))
return;
}
}
 
/* The zero-spec case would be easy to optimize but it doesn't
happen in practice. Likewise, more than 4 specs doesn't
happen in practice. */
if (sec_count == 0 || sec_count > 4)
return;
 
/* Check that no two specs can match the same section. */
for (sec = ptr->section_list; sec != NULL; sec = sec->next)
{
struct wildcard_list *sec2;
for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
{
if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
return;
}
}
 
signature = (sec_count << 8) + wild_name_count;
switch (signature)
{
case 0x0100:
ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
break;
case 0x0101:
ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
break;
case 0x0201:
ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
break;
case 0x0302:
ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
break;
case 0x0402:
ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
break;
default:
return;
}
 
/* Now fill the data array with pointers to the specs, first the
specs with non-wildcard names, then the specs with wildcard
names. It's OK to process the specs in different order from the
given order, because we've already determined that no section
will match more than one spec. */
data_counter = 0;
for (sec = ptr->section_list; sec != NULL; sec = sec->next)
if (!wildcardp (sec->spec.name))
ptr->handler_data[data_counter++] = sec;
for (sec = ptr->section_list; sec != NULL; sec = sec->next)
if (wildcardp (sec->spec.name))
ptr->handler_data[data_counter++] = sec;
}
 
/* Handle a wild statement for a single file F. */
 
static void
walk_wild_file (lang_wild_statement_type *s,
lang_input_statement_type *f,
callback_t callback,
void *data)
{
if (f->the_bfd == NULL
|| ! bfd_check_format (f->the_bfd, bfd_archive))
walk_wild_section (s, f, callback, data);
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, 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)
{
walk_wild_section (s,
(lang_input_statement_type *) member->usrdata,
callback, data);
}
 
member = bfd_openr_next_archived_file (f->the_bfd, member);
}
}
}
 
static void
walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
{
const char *file_spec = s->filename;
char *p;
 
if (file_spec == NULL)
{
/* Perform the iteration over all files in the list. */
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
walk_wild_file (s, f, callback, data);
}
}
else if ((p = archive_path (file_spec)) != NULL)
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
if (input_statement_is_archive_path (file_spec, p, f))
walk_wild_file (s, f, callback, data);
}
}
else if (wildcardp (file_spec))
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
if (fnmatch (file_spec, f->filename, 0) == 0)
walk_wild_file (s, f, callback, data);
}
}
else
{
lang_input_statement_type *f;
 
/* Perform the iteration over a single file. */
f = lookup_name (file_spec);
if (f)
walk_wild_file (s, f, callback, data);
}
}
 
/* lang_for_each_statement walks the parse tree and calls the provided
function for each node, except those inside output section statements
with constraint set to -1. */
 
void
lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
lang_statement_union_type *s)
{
for (; s != NULL; s = s->header.next)
{
func (s);
 
switch (s->header.type)
{
case lang_constructors_statement_enum:
lang_for_each_statement_worker (func, constructor_list.head);
break;
case lang_output_section_statement_enum:
if (s->output_section_statement.constraint != -1)
lang_for_each_statement_worker
(func, s->output_section_statement.children.head);
break;
case lang_wild_statement_enum:
lang_for_each_statement_worker (func,
s->wild_statement.children.head);
break;
case lang_group_statement_enum:
lang_for_each_statement_worker (func,
s->group_statement.children.head);
break;
case lang_data_statement_enum:
case lang_reloc_statement_enum:
case lang_object_symbols_statement_enum:
case lang_output_statement_enum:
case lang_target_statement_enum:
case lang_input_section_enum:
case lang_input_statement_enum:
case lang_assignment_statement_enum:
case lang_padding_statement_enum:
case lang_address_statement_enum:
case lang_fill_statement_enum:
case lang_insert_statement_enum:
break;
default:
FAIL ();
break;
}
}
}
 
void
lang_for_each_statement (void (*func) (lang_statement_union_type *))
{
lang_for_each_statement_worker (func, statement_list.head);
}
 
/*----------------------------------------------------------------------*/
 
void
lang_list_init (lang_statement_list_type *list)
{
list->head = NULL;
list->tail = &list->head;
}
 
void
push_stat_ptr (lang_statement_list_type *new_ptr)
{
if (stat_save_ptr >= stat_save + sizeof (stat_save) / sizeof (stat_save[0]))
abort ();
*stat_save_ptr++ = stat_ptr;
stat_ptr = new_ptr;
}
 
void
pop_stat_ptr (void)
{
if (stat_save_ptr <= stat_save)
abort ();
stat_ptr = *--stat_save_ptr;
}
 
/* Build a new statement node for the parse tree. */
 
static lang_statement_union_type *
new_statement (enum statement_enum type,
size_t size,
lang_statement_list_type *list)
{
lang_statement_union_type *new_stmt;
 
new_stmt = (lang_statement_union_type *) stat_alloc (size);
new_stmt->header.type = type;
new_stmt->header.next = NULL;
lang_statement_append (list, new_stmt, &new_stmt->header.next);
return new_stmt;
}
 
/* Build a new input file node for the language. There are several
ways in which we treat an input file, eg, we only look at symbols,
or prefix it with a -l etc.
 
We can be supplied with requests for input files more than once;
they may, for example be split over several lines like foo.o(.text)
foo.o(.data) etc, so when asked for a file we check that we haven't
got it already so we don't duplicate the bfd. */
 
static lang_input_statement_type *
new_afile (const char *name,
lang_input_file_enum_type file_type,
const char *target,
bfd_boolean add_to_list)
{
lang_input_statement_type *p;
 
lang_has_input_file = TRUE;
 
if (add_to_list)
p = (lang_input_statement_type *) new_stat (lang_input_statement, stat_ptr);
else
{
p = (lang_input_statement_type *)
stat_alloc (sizeof (lang_input_statement_type));
p->header.type = lang_input_statement_enum;
p->header.next = NULL;
}
 
memset (&p->the_bfd, 0,
sizeof (*p) - offsetof (lang_input_statement_type, the_bfd));
p->target = target;
p->flags.dynamic = input_flags.dynamic;
p->flags.add_DT_NEEDED_for_dynamic = input_flags.add_DT_NEEDED_for_dynamic;
p->flags.add_DT_NEEDED_for_regular = input_flags.add_DT_NEEDED_for_regular;
p->flags.whole_archive = input_flags.whole_archive;
p->flags.sysrooted = input_flags.sysrooted;
 
if (file_type == lang_input_file_is_l_enum
&& name[0] == ':' && name[1] != '\0')
{
file_type = lang_input_file_is_search_file_enum;
name = name + 1;
}
 
switch (file_type)
{
case lang_input_file_is_symbols_only_enum:
p->filename = name;
p->local_sym_name = name;
p->flags.real = TRUE;
p->flags.just_syms = TRUE;
break;
case lang_input_file_is_fake_enum:
p->filename = name;
p->local_sym_name = name;
break;
case lang_input_file_is_l_enum:
p->filename = name;
p->local_sym_name = concat ("-l", name, (const char *) NULL);
p->flags.maybe_archive = TRUE;
p->flags.real = TRUE;
p->flags.search_dirs = TRUE;
break;
case lang_input_file_is_marker_enum:
p->filename = name;
p->local_sym_name = name;
p->flags.search_dirs = TRUE;
break;
case lang_input_file_is_search_file_enum:
p->filename = name;
p->local_sym_name = name;
p->flags.real = TRUE;
p->flags.search_dirs = TRUE;
break;
case lang_input_file_is_file_enum:
p->filename = name;
p->local_sym_name = name;
p->flags.real = TRUE;
break;
default:
FAIL ();
}
 
lang_statement_append (&input_file_chain,
(lang_statement_union_type *) p,
&p->next_real_file);
return p;
}
 
lang_input_statement_type *
lang_add_input_file (const char *name,
lang_input_file_enum_type file_type,
const char *target)
{
return new_afile (name, file_type, target, TRUE);
}
 
struct out_section_hash_entry
{
struct bfd_hash_entry root;
lang_statement_union_type s;
};
 
/* The hash table. */
 
static struct bfd_hash_table output_section_statement_table;
 
/* Support routines for the hash table used by lang_output_section_find,
initialize the table, fill in an entry and remove the table. */
 
static struct bfd_hash_entry *
output_section_statement_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table,
const char *string)
{
lang_output_section_statement_type **nextp;
struct out_section_hash_entry *ret;
 
if (entry == NULL)
{
entry = (struct bfd_hash_entry *) bfd_hash_allocate (table,
sizeof (*ret));
if (entry == NULL)
return entry;
}
 
entry = bfd_hash_newfunc (entry, table, string);
if (entry == NULL)
return entry;
 
ret = (struct out_section_hash_entry *) entry;
memset (&ret->s, 0, sizeof (ret->s));
ret->s.header.type = lang_output_section_statement_enum;
ret->s.output_section_statement.subsection_alignment = -1;
ret->s.output_section_statement.section_alignment = -1;
ret->s.output_section_statement.block_value = 1;
lang_list_init (&ret->s.output_section_statement.children);
lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next);
 
/* For every output section statement added to the list, except the
first one, lang_output_section_statement.tail points to the "next"
field of the last element of the list. */
if (lang_output_section_statement.head != NULL)
ret->s.output_section_statement.prev
= ((lang_output_section_statement_type *)
((char *) lang_output_section_statement.tail
- offsetof (lang_output_section_statement_type, next)));
 
/* GCC's strict aliasing rules prevent us from just casting the
address, so we store the pointer in a variable and cast that
instead. */
nextp = &ret->s.output_section_statement.next;
lang_statement_append (&lang_output_section_statement,
&ret->s,
(lang_statement_union_type **) nextp);
return &ret->root;
}
 
static void
output_section_statement_table_init (void)
{
if (!bfd_hash_table_init_n (&output_section_statement_table,
output_section_statement_newfunc,
sizeof (struct out_section_hash_entry),
61))
einfo (_("%P%F: can not create hash table: %E\n"));
}
 
static void
output_section_statement_table_free (void)
{
bfd_hash_table_free (&output_section_statement_table);
}
 
/* Build enough state so that the parser can build its tree. */
 
void
lang_init (void)
{
obstack_begin (&stat_obstack, 1000);
 
stat_ptr = &statement_list;
 
output_section_statement_table_init ();
 
lang_list_init (stat_ptr);
 
lang_list_init (&input_file_chain);
lang_list_init (&lang_output_section_statement);
lang_list_init (&file_chain);
first_file = lang_add_input_file (NULL, lang_input_file_is_marker_enum,
NULL);
abs_output_section =
lang_output_section_statement_lookup (BFD_ABS_SECTION_NAME, 0, TRUE);
 
abs_output_section->bfd_section = bfd_abs_section_ptr;
 
/* The value "3" is ad-hoc, somewhat related to the expected number of
DEFINED expressions in a linker script. For most default linker
scripts, there are none. Why a hash table then? Well, it's somewhat
simpler to re-use working machinery than using a linked list in terms
of code-complexity here in ld, besides the initialization which just
looks like other code here. */
if (!bfd_hash_table_init_n (&lang_definedness_table,
lang_definedness_newfunc,
sizeof (struct lang_definedness_hash_entry),
3))
einfo (_("%P%F: can not create hash table: %E\n"));
}
 
void
lang_finish (void)
{
bfd_link_hash_table_free (link_info.output_bfd, link_info.hash);
bfd_hash_table_free (&lang_definedness_table);
output_section_statement_table_free ();
}
 
/*----------------------------------------------------------------------
A region is an area of memory declared with the
MEMORY { name:org=exp, len=exp ... }
syntax.
 
We maintain a list of all the regions here.
 
If no regions are specified in the script, then the default is used
which is created when looked up to be the entire data space.
 
If create is true we are creating a region inside a MEMORY block.
In this case it is probably an error to create a region that has
already been created. If we are not inside a MEMORY block it is
dubious to use an undeclared region name (except DEFAULT_MEMORY_REGION)
and so we issue a warning.
 
Each region has at least one name. The first name is either
DEFAULT_MEMORY_REGION or the name given in the MEMORY block. You can add
alias names to an existing region within a script with
REGION_ALIAS (alias, region_name). Each name corresponds to at most one
region. */
 
static lang_memory_region_type *lang_memory_region_list;
static lang_memory_region_type **lang_memory_region_list_tail
= &lang_memory_region_list;
 
lang_memory_region_type *
lang_memory_region_lookup (const char *const name, bfd_boolean create)
{
lang_memory_region_name *n;
lang_memory_region_type *r;
lang_memory_region_type *new_region;
 
/* NAME is NULL for LMA memspecs if no region was specified. */
if (name == NULL)
return NULL;
 
for (r = lang_memory_region_list; r != NULL; r = r->next)
for (n = &r->name_list; n != NULL; n = n->next)
if (strcmp (n->name, name) == 0)
{
if (create)
einfo (_("%P:%S: warning: redeclaration of memory region `%s'\n"),
NULL, name);
return r;
}
 
if (!create && strcmp (name, DEFAULT_MEMORY_REGION))
einfo (_("%P:%S: warning: memory region `%s' not declared\n"),
NULL, name);
 
new_region = (lang_memory_region_type *)
stat_alloc (sizeof (lang_memory_region_type));
 
new_region->name_list.name = xstrdup (name);
new_region->name_list.next = NULL;
new_region->next = NULL;
new_region->origin = 0;
new_region->length = ~(bfd_size_type) 0;
new_region->current = 0;
new_region->last_os = NULL;
new_region->flags = 0;
new_region->not_flags = 0;
new_region->had_full_message = FALSE;
 
*lang_memory_region_list_tail = new_region;
lang_memory_region_list_tail = &new_region->next;
 
return new_region;
}
 
void
lang_memory_region_alias (const char * alias, const char * region_name)
{
lang_memory_region_name * n;
lang_memory_region_type * r;
lang_memory_region_type * region;
 
/* The default region must be unique. This ensures that it is not necessary
to iterate through the name list if someone wants the check if a region is
the default memory region. */
if (strcmp (region_name, DEFAULT_MEMORY_REGION) == 0
|| strcmp (alias, DEFAULT_MEMORY_REGION) == 0)
einfo (_("%F%P:%S: error: alias for default memory region\n"), NULL);
 
/* Look for the target region and check if the alias is not already
in use. */
region = NULL;
for (r = lang_memory_region_list; r != NULL; r = r->next)
for (n = &r->name_list; n != NULL; n = n->next)
{
if (region == NULL && strcmp (n->name, region_name) == 0)
region = r;
if (strcmp (n->name, alias) == 0)
einfo (_("%F%P:%S: error: redefinition of memory region "
"alias `%s'\n"),
NULL, alias);
}
 
/* Check if the target region exists. */
if (region == NULL)
einfo (_("%F%P:%S: error: memory region `%s' "
"for alias `%s' does not exist\n"),
NULL, region_name, alias);
 
/* Add alias to region name list. */
n = (lang_memory_region_name *) stat_alloc (sizeof (lang_memory_region_name));
n->name = xstrdup (alias);
n->next = region->name_list.next;
region->name_list.next = n;
}
 
static lang_memory_region_type *
lang_memory_default (asection * section)
{
lang_memory_region_type *p;
 
flagword sec_flags = section->flags;
 
/* Override SEC_DATA to mean a writable section. */
if ((sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE)) == SEC_ALLOC)
sec_flags |= SEC_DATA;
 
for (p = lang_memory_region_list; p != NULL; p = p->next)
{
if ((p->flags & sec_flags) != 0
&& (p->not_flags & sec_flags) == 0)
{
return p;
}
}
return lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
}
 
/* Find or create an output_section_statement with the given NAME.
If CONSTRAINT is non-zero match one with that constraint, otherwise
match any non-negative constraint. If CREATE, always make a
new output_section_statement for SPECIAL CONSTRAINT. */
 
lang_output_section_statement_type *
lang_output_section_statement_lookup (const char *name,
int constraint,
bfd_boolean create)
{
struct out_section_hash_entry *entry;
 
entry = ((struct out_section_hash_entry *)
bfd_hash_lookup (&output_section_statement_table, name,
create, FALSE));
if (entry == NULL)
{
if (create)
einfo (_("%P%F: failed creating section `%s': %E\n"), name);
return NULL;
}
 
if (entry->s.output_section_statement.name != NULL)
{
/* We have a section of this name, but it might not have the correct
constraint. */
struct out_section_hash_entry *last_ent;
 
name = entry->s.output_section_statement.name;
if (create && constraint == SPECIAL)
/* Not traversing to the end reverses the order of the second
and subsequent SPECIAL sections in the hash table chain,
but that shouldn't matter. */
last_ent = entry;
else
do
{
if (constraint == entry->s.output_section_statement.constraint
|| (constraint == 0
&& entry->s.output_section_statement.constraint >= 0))
return &entry->s.output_section_statement;
last_ent = entry;
entry = (struct out_section_hash_entry *) entry->root.next;
}
while (entry != NULL
&& name == entry->s.output_section_statement.name);
 
if (!create)
return NULL;
 
entry
= ((struct out_section_hash_entry *)
output_section_statement_newfunc (NULL,
&output_section_statement_table,
name));
if (entry == NULL)
{
einfo (_("%P%F: failed creating section `%s': %E\n"), name);
return NULL;
}
entry->root = last_ent->root;
last_ent->root.next = &entry->root;
}
 
entry->s.output_section_statement.name = name;
entry->s.output_section_statement.constraint = constraint;
return &entry->s.output_section_statement;
}
 
/* Find the next output_section_statement with the same name as OS.
If CONSTRAINT is non-zero, find one with that constraint otherwise
match any non-negative constraint. */
 
lang_output_section_statement_type *
next_matching_output_section_statement (lang_output_section_statement_type *os,
int constraint)
{
/* All output_section_statements are actually part of a
struct out_section_hash_entry. */
struct out_section_hash_entry *entry = (struct out_section_hash_entry *)
((char *) os
- offsetof (struct out_section_hash_entry, s.output_section_statement));
const char *name = os->name;
 
ASSERT (name == entry->root.string);
do
{
entry = (struct out_section_hash_entry *) entry->root.next;
if (entry == NULL
|| name != entry->s.output_section_statement.name)
return NULL;
}
while (constraint != entry->s.output_section_statement.constraint
&& (constraint != 0
|| entry->s.output_section_statement.constraint < 0));
 
return &entry->s.output_section_statement;
}
 
/* A variant of lang_output_section_find used by place_orphan.
Returns the output statement that should precede a new output
statement for SEC. If an exact match is found on certain flags,
sets *EXACT too. */
 
lang_output_section_statement_type *
lang_output_section_find_by_flags (const asection *sec,
lang_output_section_statement_type **exact,
lang_match_sec_type_func match_type)
{
lang_output_section_statement_type *first, *look, *found;
flagword flags;
 
/* We know the first statement on this list is *ABS*. May as well
skip it. */
first = &lang_output_section_statement.head->output_section_statement;
first = first->next;
 
/* First try for an exact match. */
found = NULL;
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
if (found != NULL)
{
if (exact != NULL)
*exact = found;
return found;
}
 
if ((sec->flags & SEC_CODE) != 0
&& (sec->flags & SEC_ALLOC) != 0)
{
/* Try for a rw code section. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_CODE | SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
}
else if ((sec->flags & (SEC_READONLY | SEC_THREAD_LOCAL)) != 0
&& (sec->flags & SEC_ALLOC) != 0)
{
/* .rodata can go after .text, .sdata2 after .rodata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_READONLY | SEC_SMALL_DATA))
|| (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_READONLY))
&& !(look->flags & SEC_SMALL_DATA))
|| (!(flags & (SEC_THREAD_LOCAL | SEC_ALLOC))
&& (look->flags & SEC_THREAD_LOCAL)
&& (!(flags & SEC_LOAD)
|| (look->flags & SEC_LOAD))))
found = look;
}
}
else if ((sec->flags & SEC_SMALL_DATA) != 0
&& (sec->flags & SEC_ALLOC) != 0)
{
/* .sdata goes after .data, .sbss after .sdata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_THREAD_LOCAL))
|| ((look->flags & SEC_SMALL_DATA)
&& !(sec->flags & SEC_HAS_CONTENTS)))
found = look;
}
}
else if ((sec->flags & SEC_HAS_CONTENTS) != 0
&& (sec->flags & SEC_ALLOC) != 0)
{
/* .data goes after .rodata. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD
| SEC_SMALL_DATA | SEC_THREAD_LOCAL)))
found = look;
}
}
else if ((sec->flags & SEC_ALLOC) != 0)
{
/* .bss goes after any other alloc section. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
{
flags = look->bfd_section->flags;
if (match_type && !match_type (link_info.output_bfd,
look->bfd_section,
sec->owner, sec))
continue;
}
flags ^= sec->flags;
if (!(flags & SEC_ALLOC))
found = look;
}
}
else
{
/* non-alloc go last. */
for (look = first; look; look = look->next)
{
flags = look->flags;
if (look->bfd_section != NULL)
flags = look->bfd_section->flags;
flags ^= sec->flags;
if (!(flags & SEC_DEBUGGING))
found = look;
}
return found;
}
 
if (found || !match_type)
return found;
 
return lang_output_section_find_by_flags (sec, NULL, NULL);
}
 
/* Find the last output section before given output statement.
Used by place_orphan. */
 
static asection *
output_prev_sec_find (lang_output_section_statement_type *os)
{
lang_output_section_statement_type *lookup;
 
for (lookup = os->prev; lookup != NULL; lookup = lookup->prev)
{
if (lookup->constraint < 0)
continue;
 
if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL)
return lookup->bfd_section;
}
 
return NULL;
}
 
/* Look for a suitable place for a new output section statement. The
idea is to skip over anything that might be inside a SECTIONS {}
statement in a script, before we find another output section
statement. Assignments to "dot" before an output section statement
are assumed to belong to it, except in two cases; The first
assignment to dot, and assignments before non-alloc sections.
Otherwise we might put an orphan before . = . + SIZEOF_HEADERS or
similar assignments that set the initial address, or we might
insert non-alloc note sections among assignments setting end of
image symbols. */
 
static lang_statement_union_type **
insert_os_after (lang_output_section_statement_type *after)
{
lang_statement_union_type **where;
lang_statement_union_type **assign = NULL;
bfd_boolean ignore_first;
 
ignore_first
= after == &lang_output_section_statement.head->output_section_statement;
 
for (where = &after->header.next;
*where != NULL;
where = &(*where)->header.next)
{
switch ((*where)->header.type)
{
case lang_assignment_statement_enum:
if (assign == NULL)
{
lang_assignment_statement_type *ass;
 
ass = &(*where)->assignment_statement;
if (ass->exp->type.node_class != etree_assert
&& ass->exp->assign.dst[0] == '.'
&& ass->exp->assign.dst[1] == 0
&& !ignore_first)
assign = where;
}
ignore_first = FALSE;
continue;
case lang_wild_statement_enum:
case lang_input_section_enum:
case lang_object_symbols_statement_enum:
case lang_fill_statement_enum:
case lang_data_statement_enum:
case lang_reloc_statement_enum:
case lang_padding_statement_enum:
case lang_constructors_statement_enum:
assign = NULL;
continue;
case lang_output_section_statement_enum:
if (assign != NULL)
{
asection *s = (*where)->output_section_statement.bfd_section;
 
if (s == NULL
|| s->map_head.s == NULL
|| (s->flags & SEC_ALLOC) != 0)
where = assign;
}
break;
case lang_input_statement_enum:
case lang_address_statement_enum:
case lang_target_statement_enum:
case lang_output_statement_enum:
case lang_group_statement_enum:
case lang_insert_statement_enum:
continue;
}
break;
}
 
return where;
}
 
lang_output_section_statement_type *
lang_insert_orphan (asection *s,
const char *secname,
int constraint,
lang_output_section_statement_type *after,
struct orphan_save *place,
etree_type *address,
lang_statement_list_type *add_child)
{
lang_statement_list_type add;
const char *ps;
lang_output_section_statement_type *os;
lang_output_section_statement_type **os_tail;
 
/* If we have found an appropriate place for the output section
statements for this orphan, add them to our own private list,
inserting them later into the global statement list. */
if (after != NULL)
{
lang_list_init (&add);
push_stat_ptr (&add);
}
 
if (link_info.relocatable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
address = exp_intop (0);
 
os_tail = ((lang_output_section_statement_type **)
lang_output_section_statement.tail);
os = lang_enter_output_section_statement (secname, address, normal_section,
NULL, NULL, NULL, constraint, 0);
 
ps = NULL;
if (config.build_constructors && *os_tail == os)
{
/* If the name of the section is representable in C, then create
symbols to mark the start and the end of the section. */
for (ps = secname; *ps != '\0'; ps++)
if (! ISALNUM ((unsigned char) *ps) && *ps != '_')
break;
if (*ps == '\0')
{
char *symname;
 
symname = (char *) xmalloc (ps - secname + sizeof "__start_" + 1);
symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
sprintf (symname + (symname[0] != 0), "__start_%s", secname);
lang_add_assignment (exp_provide (symname,
exp_nameop (NAME, "."),
FALSE));
}
}
 
if (add_child == NULL)
add_child = &os->children;
lang_add_section (add_child, s, NULL, os);
 
if (after && (s->flags & (SEC_LOAD | SEC_ALLOC)) != 0)
{
const char *region = (after->region
? after->region->name_list.name
: DEFAULT_MEMORY_REGION);
const char *lma_region = (after->lma_region
? after->lma_region->name_list.name
: NULL);
lang_leave_output_section_statement (NULL, region, after->phdrs,
lma_region);
}
else
lang_leave_output_section_statement (NULL, DEFAULT_MEMORY_REGION, NULL,
NULL);
 
if (ps != NULL && *ps == '\0')
{
char *symname;
 
symname = (char *) xmalloc (ps - secname + sizeof "__stop_" + 1);
symname[0] = bfd_get_symbol_leading_char (link_info.output_bfd);
sprintf (symname + (symname[0] != 0), "__stop_%s", secname);
lang_add_assignment (exp_provide (symname,
exp_nameop (NAME, "."),
FALSE));
}
 
/* Restore the global list pointer. */
if (after != NULL)
pop_stat_ptr ();
 
if (after != NULL && os->bfd_section != NULL)
{
asection *snew, *as;
 
snew = os->bfd_section;
 
/* Shuffle the bfd section list to make the output file look
neater. This is really only cosmetic. */
if (place->section == NULL
&& after != (&lang_output_section_statement.head
->output_section_statement))
{
asection *bfd_section = after->bfd_section;
 
/* If the output statement hasn't been used to place any input
sections (and thus doesn't have an output bfd_section),
look for the closest prior output statement having an
output section. */
if (bfd_section == NULL)
bfd_section = output_prev_sec_find (after);
 
if (bfd_section != NULL && bfd_section != snew)
place->section = &bfd_section->next;
}
 
if (place->section == NULL)
place->section = &link_info.output_bfd->sections;
 
as = *place->section;
 
if (!as)
{
/* Put the section at the end of the list. */
 
/* Unlink the section. */
bfd_section_list_remove (link_info.output_bfd, snew);
 
/* Now tack it back on in the right place. */
bfd_section_list_append (link_info.output_bfd, snew);
}
else if (as != snew && as->prev != snew)
{
/* Unlink the section. */
bfd_section_list_remove (link_info.output_bfd, snew);
 
/* Now tack it back on in the right place. */
bfd_section_list_insert_before (link_info.output_bfd, as, snew);
}
 
/* Save the end of this list. Further ophans of this type will
follow the one we've just added. */
place->section = &snew->next;
 
/* The following is non-cosmetic. We try to put the output
statements in some sort of reasonable order here, because they
determine the final load addresses of the orphan sections.
In addition, placing output statements in the wrong order may
require extra segments. For instance, given a typical
situation of all read-only sections placed in one segment and
following that a segment containing all the read-write
sections, we wouldn't want to place an orphan read/write
section before or amongst the read-only ones. */
if (add.head != NULL)
{
lang_output_section_statement_type *newly_added_os;
 
if (place->stmt == NULL)
{
lang_statement_union_type **where = insert_os_after (after);
 
*add.tail = *where;
*where = add.head;
 
place->os_tail = &after->next;
}
else
{
/* Put it after the last orphan statement we added. */
*add.tail = *place->stmt;
*place->stmt = add.head;
}
 
/* Fix the global list pointer if we happened to tack our
new list at the tail. */
if (*stat_ptr->tail == add.head)
stat_ptr->tail = add.tail;
 
/* Save the end of this list. */
place->stmt = add.tail;
 
/* Do the same for the list of output section statements. */
newly_added_os = *os_tail;
*os_tail = NULL;
newly_added_os->prev = (lang_output_section_statement_type *)
((char *) place->os_tail
- offsetof (lang_output_section_statement_type, next));
newly_added_os->next = *place->os_tail;
if (newly_added_os->next != NULL)
newly_added_os->next->prev = newly_added_os;
*place->os_tail = newly_added_os;
place->os_tail = &newly_added_os->next;
 
/* Fixing the global list pointer here is a little different.
We added to the list in lang_enter_output_section_statement,
trimmed off the new output_section_statment above when
assigning *os_tail = NULL, but possibly added it back in
the same place when assigning *place->os_tail. */
if (*os_tail == NULL)
lang_output_section_statement.tail
= (lang_statement_union_type **) os_tail;
}
}
return os;
}
 
static void
lang_map_flags (flagword flag)
{
if (flag & SEC_ALLOC)
minfo ("a");
 
if (flag & SEC_CODE)
minfo ("x");
 
if (flag & SEC_READONLY)
minfo ("r");
 
if (flag & SEC_DATA)
minfo ("w");
 
if (flag & SEC_LOAD)
minfo ("l");
}
 
void
lang_map (void)
{
lang_memory_region_type *m;
bfd_boolean dis_header_printed = FALSE;
bfd *p;
 
LANG_FOR_EACH_INPUT_STATEMENT (file)
{
asection *s;
 
if ((file->the_bfd->flags & (BFD_LINKER_CREATED | DYNAMIC)) != 0
|| file->flags.just_syms)
continue;
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
if ((s->output_section == NULL
|| s->output_section->owner != link_info.output_bfd)
&& (s->flags & (SEC_LINKER_CREATED | SEC_KEEP)) == 0)
{
if (! dis_header_printed)
{
fprintf (config.map_file, _("\nDiscarded input sections\n\n"));
dis_header_printed = TRUE;
}
 
print_input_section (s, TRUE);
}
}
 
minfo (_("\nMemory Configuration\n\n"));
fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
_("Name"), _("Origin"), _("Length"), _("Attributes"));
 
for (m = lang_memory_region_list; m != NULL; m = m->next)
{
char buf[100];
int len;
 
fprintf (config.map_file, "%-16s ", m->name_list.name);
 
sprintf_vma (buf, m->origin);
minfo ("0x%s ", buf);
len = strlen (buf);
while (len < 16)
{
print_space ();
++len;
}
 
minfo ("0x%V", m->length);
if (m->flags || m->not_flags)
{
#ifndef BFD64
minfo (" ");
#endif
if (m->flags)
{
print_space ();
lang_map_flags (m->flags);
}
 
if (m->not_flags)
{
minfo (" !");
lang_map_flags (m->not_flags);
}
}
 
print_nl ();
}
 
fprintf (config.map_file, _("\nLinker script and memory map\n\n"));
 
if (! link_info.reduce_memory_overheads)
{
obstack_begin (&map_obstack, 1000);
for (p = link_info.input_bfds; p != (bfd *) NULL; p = p->link_next)
bfd_map_over_sections (p, init_map_userdata, 0);
bfd_link_hash_traverse (link_info.hash, sort_def_symbol, 0);
}
lang_statement_iteration ++;
print_statements ();
}
 
static void
init_map_userdata (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec,
void *data ATTRIBUTE_UNUSED)
{
fat_section_userdata_type *new_data
= ((fat_section_userdata_type *) (stat_alloc
(sizeof (fat_section_userdata_type))));
 
ASSERT (get_userdata (sec) == NULL);
get_userdata (sec) = new_data;
new_data->map_symbol_def_tail = &new_data->map_symbol_def_head;
new_data->map_symbol_def_count = 0;
}
 
static bfd_boolean
sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
void *info ATTRIBUTE_UNUSED)
{
if (hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
{
struct fat_user_section_struct *ud;
struct map_symbol_def *def;
 
ud = (struct fat_user_section_struct *)
get_userdata (hash_entry->u.def.section);
if (! ud)
{
/* ??? What do we have to do to initialize this beforehand? */
/* The first time we get here is bfd_abs_section... */
init_map_userdata (0, hash_entry->u.def.section, 0);
ud = (struct fat_user_section_struct *)
get_userdata (hash_entry->u.def.section);
}
else if (!ud->map_symbol_def_tail)
ud->map_symbol_def_tail = &ud->map_symbol_def_head;
 
def = (struct map_symbol_def *) obstack_alloc (&map_obstack, sizeof *def);
def->entry = hash_entry;
*(ud->map_symbol_def_tail) = def;
ud->map_symbol_def_tail = &def->next;
ud->map_symbol_def_count++;
}
return TRUE;
}
 
/* Initialize an output section. */
 
static void
init_os (lang_output_section_statement_type *s, flagword flags)
{
if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
 
if (s->constraint != SPECIAL)
s->bfd_section = bfd_get_section_by_name (link_info.output_bfd, s->name);
if (s->bfd_section == NULL)
s->bfd_section = bfd_make_section_anyway_with_flags (link_info.output_bfd,
s->name, flags);
if (s->bfd_section == NULL)
{
einfo (_("%P%F: output format %s cannot represent section called %s\n"),
link_info.output_bfd->xvec->name, s->name);
}
s->bfd_section->output_section = s->bfd_section;
s->bfd_section->output_offset = 0;
 
if (!link_info.reduce_memory_overheads)
{
fat_section_userdata_type *new_userdata = (fat_section_userdata_type *)
stat_alloc (sizeof (fat_section_userdata_type));
memset (new_userdata, 0, sizeof (fat_section_userdata_type));
get_userdata (s->bfd_section) = new_userdata;
}
 
/* 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);
 
if (s->load_base != NULL)
exp_init_os (s->load_base);
 
/* If supplied an alignment, set it. */
if (s->section_alignment != -1)
s->bfd_section->alignment_power = s->section_alignment;
}
 
/* Make sure that all output sections mentioned in an expression are
initialized. */
 
static void
exp_init_os (etree_type *exp)
{
switch (exp->type.node_class)
{
case etree_assign:
case etree_provide:
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_assert:
exp_init_os (exp->assert_s.child);
break;
 
case etree_unary:
exp_init_os (exp->unary.child);
break;
 
case etree_name:
switch (exp->type.node_code)
{
case ADDR:
case LOADADDR:
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, 0);
}
}
break;
 
default:
break;
}
}
static void
section_already_linked (bfd *abfd, asection *sec, void *data)
{
lang_input_statement_type *entry = (lang_input_statement_type *) data;
 
/* If we are only reading symbols from this object, then we want to
discard all sections. */
if (entry->flags.just_syms)
{
bfd_link_just_syms (abfd, sec, &link_info);
return;
}
 
if (!(abfd->flags & DYNAMIC))
bfd_section_already_linked (abfd, sec, &link_info);
}
/* The wild routines.
 
These expand statements like *(.text) and foo.o to a list of
explicit actions, like foo.o(.text), bar.o(.text) and
foo.o(.text, .data). */
 
/* Add SECTION to the output section OUTPUT. Do this by creating a
lang_input_section statement which is placed at PTR. */
 
void
lang_add_section (lang_statement_list_type *ptr,
asection *section,
struct flag_info *sflag_info,
lang_output_section_statement_type *output)
{
flagword flags = section->flags;
 
bfd_boolean discard;
lang_input_section_type *new_section;
bfd *abfd = link_info.output_bfd;
 
/* Discard sections marked with SEC_EXCLUDE. */
discard = (flags & SEC_EXCLUDE) != 0;
 
/* Discard input sections which are assigned to a section named
DISCARD_SECTION_NAME. */
if (strcmp (output->name, DISCARD_SECTION_NAME) == 0)
discard = TRUE;
 
/* Discard debugging sections if we are stripping debugging
information. */
if ((link_info.strip == strip_debugger || link_info.strip == strip_all)
&& (flags & SEC_DEBUGGING) != 0)
discard = TRUE;
 
if (discard)
{
if (section->output_section == NULL)
{
/* This prevents future calls from assigning this section. */
section->output_section = bfd_abs_section_ptr;
}
return;
}
 
if (sflag_info)
{
bfd_boolean keep;
 
keep = bfd_lookup_section_flags (&link_info, sflag_info, section);
if (!keep)
return;
}
 
if (section->output_section != NULL)
return;
 
/* We don't copy the SEC_NEVER_LOAD flag from an input section
to an output section, because we want to be able to include a
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. */
flags &= ~ SEC_NEVER_LOAD;
 
/* 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. */
 
if (!link_info.relocatable)
flags &= ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC);
 
switch (output->sectype)
{
case normal_section:
case overlay_section:
break;
case noalloc_section:
flags &= ~SEC_ALLOC;
break;
case noload_section:
flags &= ~SEC_LOAD;
flags |= SEC_NEVER_LOAD;
/* Unfortunately GNU ld has managed to evolve two different
meanings to NOLOAD in scripts. ELF gets a .bss style noload,
alloc, no contents section. All others get a noload, noalloc
section. */
if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
flags &= ~SEC_HAS_CONTENTS;
else
flags &= ~SEC_ALLOC;
break;
}
 
if (output->bfd_section == NULL)
init_os (output, flags);
 
/* If SEC_READONLY is not set in the input section, then clear
it from the output section. */
output->bfd_section->flags &= flags | ~SEC_READONLY;
 
if (output->bfd_section->linker_has_input)
{
/* Only set SEC_READONLY flag on the first input section. */
flags &= ~ SEC_READONLY;
 
/* Keep SEC_MERGE and SEC_STRINGS only if they are the same. */
if ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
!= (flags & (SEC_MERGE | SEC_STRINGS))
|| ((flags & SEC_MERGE) != 0
&& output->bfd_section->entsize != section->entsize))
{
output->bfd_section->flags &= ~ (SEC_MERGE | SEC_STRINGS);
flags &= ~ (SEC_MERGE | SEC_STRINGS);
}
}
output->bfd_section->flags |= flags;
 
if (!output->bfd_section->linker_has_input)
{
output->bfd_section->linker_has_input = 1;
/* This must happen after flags have been updated. The output
section may have been created before we saw its first input
section, eg. for a data statement. */
bfd_init_private_section_data (section->owner, section,
link_info.output_bfd,
output->bfd_section,
&link_info);
if ((flags & SEC_MERGE) != 0)
output->bfd_section->entsize = section->entsize;
}
 
if ((flags & SEC_TIC54X_BLOCK) != 0
&& bfd_get_arch (section->owner) == bfd_arch_tic54x)
{
/* FIXME: This value should really be obtained from the bfd... */
output->block_value = 128;
}
 
if (section->alignment_power > output->bfd_section->alignment_power)
output->bfd_section->alignment_power = section->alignment_power;
 
section->output_section = output->bfd_section;
 
if (!link_info.relocatable
&& !stripped_excluded_sections)
{
asection *s = output->bfd_section->map_tail.s;
output->bfd_section->map_tail.s = section;
section->map_head.s = NULL;
section->map_tail.s = s;
if (s != NULL)
s->map_head.s = section;
else
output->bfd_section->map_head.s = section;
}
 
/* Add a section reference to the list. */
new_section = new_stat (lang_input_section, ptr);
new_section->section = section;
}
 
/* Handle wildcard sorting. This returns the lang_input_section which
should follow the one we are going to create for SECTION and FILE,
based on the sorting requirements of WILD. It returns NULL if the
new section should just go at the end of the current list. */
 
static lang_statement_union_type *
wild_sort (lang_wild_statement_type *wild,
struct wildcard_list *sec,
lang_input_statement_type *file,
asection *section)
{
lang_statement_union_type *l;
 
if (!wild->filenames_sorted
&& (sec == NULL || sec->spec.sorted == none))
return NULL;
 
for (l = wild->children.head; l != NULL; l = l->header.next)
{
lang_input_section_type *ls;
 
if (l->header.type != lang_input_section_enum)
continue;
ls = &l->input_section;
 
/* Sorting by filename takes precedence over sorting by section
name. */
 
if (wild->filenames_sorted)
{
const char *fn, *ln;
bfd_boolean fa, la;
int i;
 
/* The PE support for the .idata section as generated by
dlltool assumes that files will be sorted by the name of
the archive and then the name of the file within the
archive. */
 
if (file->the_bfd != NULL
&& bfd_my_archive (file->the_bfd) != NULL)
{
fn = bfd_get_filename (bfd_my_archive (file->the_bfd));
fa = TRUE;
}
else
{
fn = file->filename;
fa = FALSE;
}
 
if (bfd_my_archive (ls->section->owner) != NULL)
{
ln = bfd_get_filename (bfd_my_archive (ls->section->owner));
la = TRUE;
}
else
{
ln = ls->section->owner->filename;
la = FALSE;
}
 
i = filename_cmp (fn, ln);
if (i > 0)
continue;
else if (i < 0)
break;
 
if (fa || la)
{
if (fa)
fn = file->filename;
if (la)
ln = ls->section->owner->filename;
 
i = filename_cmp (fn, ln);
if (i > 0)
continue;
else if (i < 0)
break;
}
}
 
/* Here either the files are not sorted by name, or we are
looking at the sections for this file. */
 
if (sec != NULL
&& sec->spec.sorted != none
&& sec->spec.sorted != by_none)
if (compare_section (sec->spec.sorted, section, ls->section) < 0)
break;
}
 
return l;
}
 
/* Expand a wild statement for a particular FILE. SECTION may be
NULL, in which case it is a wild card. */
 
static void
output_section_callback (lang_wild_statement_type *ptr,
struct wildcard_list *sec,
asection *section,
struct flag_info *sflag_info,
lang_input_statement_type *file,
void *output)
{
lang_statement_union_type *before;
lang_output_section_statement_type *os;
 
os = (lang_output_section_statement_type *) output;
 
/* Exclude sections that match UNIQUE_SECTION_LIST. */
if (unique_section_p (section, os))
return;
 
before = wild_sort (ptr, sec, file, section);
 
/* Here BEFORE points to the lang_input_section which
should follow the one we are about to add. If BEFORE
is NULL, then the section should just go at the end
of the current list. */
 
if (before == NULL)
lang_add_section (&ptr->children, section, sflag_info, os);
else
{
lang_statement_list_type list;
lang_statement_union_type **pp;
 
lang_list_init (&list);
lang_add_section (&list, section, sflag_info, os);
 
/* If we are discarding the section, LIST.HEAD will
be NULL. */
if (list.head != NULL)
{
ASSERT (list.head->header.next == NULL);
 
for (pp = &ptr->children.head;
*pp != before;
pp = &(*pp)->header.next)
ASSERT (*pp != NULL);
 
list.head->header.next = *pp;
*pp = list.head;
}
}
}
 
/* Check if all sections in a wild statement for a particular FILE
are readonly. */
 
static void
check_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
struct wildcard_list *sec ATTRIBUTE_UNUSED,
asection *section,
struct flag_info *sflag_info ATTRIBUTE_UNUSED,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
void *output)
{
lang_output_section_statement_type *os;
 
os = (lang_output_section_statement_type *) output;
 
/* Exclude sections that match UNIQUE_SECTION_LIST. */
if (unique_section_p (section, os))
return;
 
if (section->output_section == NULL && (section->flags & SEC_READONLY) == 0)
os->all_input_readonly = FALSE;
}
 
/* This is passed a file name which must have been seen already and
added to the statement tree. We will see if it has been opened
already and had its symbols read. If not then we'll read it. */
 
static lang_input_statement_type *
lookup_name (const char *name)
{
lang_input_statement_type *search;
 
for (search = (lang_input_statement_type *) input_file_chain.head;
search != NULL;
search = (lang_input_statement_type *) search->next_real_file)
{
/* Use the local_sym_name as the name of the file that has
already been loaded as filename might have been transformed
via the search directory lookup mechanism. */
const char *filename = search->local_sym_name;
 
if (filename != NULL
&& filename_cmp (filename, name) == 0)
break;
}
 
if (search == NULL)
search = new_afile (name, lang_input_file_is_search_file_enum,
default_target, FALSE);
 
/* If we have already added this file, or this file is not real
don't add this file. */
if (search->flags.loaded || !search->flags.real)
return search;
 
if (! load_symbols (search, NULL))
return NULL;
 
return search;
}
 
/* Save LIST as a list of libraries whose symbols should not be exported. */
 
struct excluded_lib
{
char *name;
struct excluded_lib *next;
};
static struct excluded_lib *excluded_libs;
 
void
add_excluded_libs (const char *list)
{
const char *p = list, *end;
 
while (*p != '\0')
{
struct excluded_lib *entry;
end = strpbrk (p, ",:");
if (end == NULL)
end = p + strlen (p);
entry = (struct excluded_lib *) xmalloc (sizeof (*entry));
entry->next = excluded_libs;
entry->name = (char *) xmalloc (end - p + 1);
memcpy (entry->name, p, end - p);
entry->name[end - p] = '\0';
excluded_libs = entry;
if (*end == '\0')
break;
p = end + 1;
}
}
 
static void
check_excluded_libs (bfd *abfd)
{
struct excluded_lib *lib = excluded_libs;
 
while (lib)
{
int len = strlen (lib->name);
const char *filename = lbasename (abfd->filename);
 
if (strcmp (lib->name, "ALL") == 0)
{
abfd->no_export = TRUE;
return;
}
 
if (filename_ncmp (lib->name, filename, len) == 0
&& (filename[len] == '\0'
|| (filename[len] == '.' && filename[len + 1] == 'a'
&& filename[len + 2] == '\0')))
{
abfd->no_export = TRUE;
return;
}
 
lib = lib->next;
}
}
 
/* Get the symbols for an input file. */
 
bfd_boolean
load_symbols (lang_input_statement_type *entry,
lang_statement_list_type *place)
{
char **matching;
 
if (entry->flags.loaded)
return TRUE;
 
ldfile_open_file (entry);
 
/* Do not process further if the file was missing. */
if (entry->flags.missing_file)
return TRUE;
 
if (! bfd_check_format (entry->the_bfd, bfd_archive)
&& ! bfd_check_format_matches (entry->the_bfd, bfd_object, &matching))
{
bfd_error_type err;
struct lang_input_statement_flags save_flags;
extern FILE *yyin;
 
err = bfd_get_error ();
 
/* See if the emulation has some special knowledge. */
if (ldemul_unrecognized_file (entry))
return TRUE;
 
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
|| place == NULL)
einfo (_("%F%B: file not recognized: %E\n"), entry->the_bfd);
 
bfd_close (entry->the_bfd);
entry->the_bfd = NULL;
 
/* Try to interpret the file as a linker script. */
save_flags = input_flags;
ldfile_open_command_file (entry->filename);
 
push_stat_ptr (place);
input_flags.add_DT_NEEDED_for_regular
= entry->flags.add_DT_NEEDED_for_regular;
input_flags.add_DT_NEEDED_for_dynamic
= entry->flags.add_DT_NEEDED_for_dynamic;
input_flags.whole_archive = entry->flags.whole_archive;
input_flags.dynamic = entry->flags.dynamic;
 
ldfile_assumed_script = TRUE;
parser_input = input_script;
yyparse ();
ldfile_assumed_script = FALSE;
 
/* missing_file is sticky. sysrooted will already have been
restored when seeing EOF in yyparse, but no harm to restore
again. */
save_flags.missing_file |= input_flags.missing_file;
input_flags = save_flags;
pop_stat_ptr ();
fclose (yyin);
yyin = NULL;
entry->flags.loaded = TRUE;
 
return TRUE;
}
 
if (ldemul_recognized_file (entry))
return TRUE;
 
/* 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. */
switch (bfd_get_format (entry->the_bfd))
{
default:
break;
 
case bfd_object:
#ifdef ENABLE_PLUGINS
if (!entry->flags.reload)
#endif
ldlang_add_file (entry);
if (trace_files || verbose)
info_msg ("%I\n", entry);
break;
 
case bfd_archive:
check_excluded_libs (entry->the_bfd);
 
if (entry->flags.whole_archive)
{
bfd *member = NULL;
bfd_boolean loaded = TRUE;
 
for (;;)
{
bfd *subsbfd;
member = bfd_openr_next_archived_file (entry->the_bfd, member);
 
if (member == NULL)
break;
 
if (! bfd_check_format (member, bfd_object))
{
einfo (_("%F%B: member %B in archive is not an object\n"),
entry->the_bfd, member);
loaded = FALSE;
}
 
subsbfd = member;
if (!(*link_info.callbacks
->add_archive_element) (&link_info, member,
"--whole-archive", &subsbfd))
abort ();
 
/* Potentially, the add_archive_element hook may have set a
substitute BFD for us. */
if (!bfd_link_add_symbols (subsbfd, &link_info))
{
einfo (_("%F%B: error adding symbols: %E\n"), member);
loaded = FALSE;
}
}
 
entry->flags.loaded = loaded;
return loaded;
}
break;
}
 
if (bfd_link_add_symbols (entry->the_bfd, &link_info))
entry->flags.loaded = TRUE;
else
einfo (_("%F%B: error adding symbols: %E\n"), entry->the_bfd);
 
return entry->flags.loaded;
}
 
/* Handle a wild statement. S->FILENAME or S->SECTION_LIST 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 added after the wild statement S. OUTPUT is
the output section. */
 
static void
wild (lang_wild_statement_type *s,
const char *target ATTRIBUTE_UNUSED,
lang_output_section_statement_type *output)
{
struct wildcard_list *sec;
 
if (s->handler_data[0]
&& s->handler_data[0]->spec.sorted == by_name
&& !s->filenames_sorted)
{
lang_section_bst_type *tree;
 
walk_wild (s, output_section_callback_fast, output);
 
tree = s->tree;
if (tree)
{
output_section_callback_tree_to_list (s, tree, output);
s->tree = NULL;
}
}
else
walk_wild (s, output_section_callback, output);
 
if (default_common_section == NULL)
for (sec = s->section_list; sec != NULL; sec = sec->next)
if (sec->spec.name != NULL && strcmp (sec->spec.name, "COMMON") == 0)
{
/* Remember the section that common is going to in case we
later get something which doesn't know where to put it. */
default_common_section = output;
break;
}
}
 
/* Return TRUE iff target is the sought target. */
 
static int
get_target (const bfd_target *target, void *data)
{
const char *sought = (const char *) data;
 
return strcmp (target->name, sought) == 0;
}
 
/* Like strcpy() but convert to lower case as well. */
 
static void
stricpy (char *dest, char *src)
{
char c;
 
while ((c = *src++) != 0)
*dest++ = TOLOWER (c);
 
*dest = 0;
}
 
/* Remove the first occurrence of needle (if any) in haystack
from haystack. */
 
static void
strcut (char *haystack, char *needle)
{
haystack = strstr (haystack, needle);
 
if (haystack)
{
char *src;
 
for (src = haystack + strlen (needle); *src;)
*haystack++ = *src++;
 
*haystack = 0;
}
}
 
/* Compare two target format name strings.
Return a value indicating how "similar" they are. */
 
static int
name_compare (char *first, char *second)
{
char *copy1;
char *copy2;
int result;
 
copy1 = (char *) xmalloc (strlen (first) + 1);
copy2 = (char *) xmalloc (strlen (second) + 1);
 
/* Convert the names to lower case. */
stricpy (copy1, first);
stricpy (copy2, second);
 
/* Remove size and endian strings from the name. */
strcut (copy1, "big");
strcut (copy1, "little");
strcut (copy2, "big");
strcut (copy2, "little");
 
/* Return a value based on how many characters match,
starting from the beginning. If both strings are
the same then return 10 * their length. */
for (result = 0; copy1[result] == copy2[result]; result++)
if (copy1[result] == 0)
{
result *= 10;
break;
}
 
free (copy1);
free (copy2);
 
return result;
}
 
/* Set by closest_target_match() below. */
static const bfd_target *winner;
 
/* Scan all the valid bfd targets looking for one that has the endianness
requirement that was specified on the command line, and is the nearest
match to the original output target. */
 
static int
closest_target_match (const bfd_target *target, void *data)
{
const bfd_target *original = (const bfd_target *) data;
 
if (command_line.endian == ENDIAN_BIG
&& target->byteorder != BFD_ENDIAN_BIG)
return 0;
 
if (command_line.endian == ENDIAN_LITTLE
&& target->byteorder != BFD_ENDIAN_LITTLE)
return 0;
 
/* Must be the same flavour. */
if (target->flavour != original->flavour)
return 0;
 
/* Ignore generic big and little endian elf vectors. */
if (strcmp (target->name, "elf32-big") == 0
|| strcmp (target->name, "elf64-big") == 0
|| strcmp (target->name, "elf32-little") == 0
|| strcmp (target->name, "elf64-little") == 0)
return 0;
 
/* If we have not found a potential winner yet, then record this one. */
if (winner == NULL)
{
winner = target;
return 0;
}
 
/* Oh dear, we now have two potential candidates for a successful match.
Compare their names and choose the better one. */
if (name_compare (target->name, original->name)
> name_compare (winner->name, original->name))
winner = target;
 
/* Keep on searching until wqe have checked them all. */
return 0;
}
 
/* Return the BFD target format of the first input file. */
 
static char *
get_first_input_target (void)
{
char *target = NULL;
 
LANG_FOR_EACH_INPUT_STATEMENT (s)
{
if (s->header.type == lang_input_statement_enum
&& s->flags.real)
{
ldfile_open_file (s);
 
if (s->the_bfd != NULL
&& bfd_check_format (s->the_bfd, bfd_object))
{
target = bfd_get_target (s->the_bfd);
 
if (target != NULL)
break;
}
}
}
 
return target;
}
 
const char *
lang_get_output_target (void)
{
const char *target;
 
/* Has the user told us which output format to use? */
if (output_target != NULL)
return output_target;
 
/* No - has the current target been set to something other than
the default? */
if (current_target != default_target && current_target != NULL)
return current_target;
 
/* No - can we determine the format of the first input file? */
target = get_first_input_target ();
if (target != NULL)
return target;
 
/* Failed - use the default output target. */
return default_target;
}
 
/* Open the output file. */
 
static void
open_output (const char *name)
{
output_target = lang_get_output_target ();
 
/* Has the user requested a particular endianness on the command
line? */
if (command_line.endian != ENDIAN_UNSET)
{
const bfd_target *target;
enum bfd_endian desired_endian;
 
/* Get the chosen target. */
target = bfd_search_for_target (get_target, (void *) output_target);
 
/* If the target is not supported, we cannot do anything. */
if (target != NULL)
{
if (command_line.endian == ENDIAN_BIG)
desired_endian = BFD_ENDIAN_BIG;
else
desired_endian = BFD_ENDIAN_LITTLE;
 
/* See if the target has the wrong endianness. This should
not happen if the linker script has provided big and
little endian alternatives, but some scrips don't do
this. */
if (target->byteorder != desired_endian)
{
/* If it does, then see if the target provides
an alternative with the correct endianness. */
if (target->alternative_target != NULL
&& (target->alternative_target->byteorder == desired_endian))
output_target = target->alternative_target->name;
else
{
/* Try to find a target as similar as possible to
the default target, but which has the desired
endian characteristic. */
bfd_search_for_target (closest_target_match,
(void *) target);
 
/* Oh dear - we could not find any targets that
satisfy our requirements. */
if (winner == NULL)
einfo (_("%P: warning: could not find any targets"
" that match endianness requirement\n"));
else
output_target = winner->name;
}
}
}
}
 
link_info.output_bfd = bfd_openw (name, output_target);
 
if (link_info.output_bfd == NULL)
{
if (bfd_get_error () == bfd_error_invalid_target)
einfo (_("%P%F: target %s not found\n"), output_target);
 
einfo (_("%P%F: cannot open output file %s: %E\n"), name);
}
 
delete_output_file_on_failure = TRUE;
 
if (! bfd_set_format (link_info.output_bfd, bfd_object))
einfo (_("%P%F:%s: can not make object file: %E\n"), name);
if (! bfd_set_arch_mach (link_info.output_bfd,
ldfile_output_architecture,
ldfile_output_machine))
einfo (_("%P%F:%s: can not set architecture: %E\n"), name);
 
link_info.hash = bfd_link_hash_table_create (link_info.output_bfd);
if (link_info.hash == NULL)
einfo (_("%P%F: can not create hash table: %E\n"));
 
bfd_set_gp_size (link_info.output_bfd, g_switch_value);
}
 
static void
ldlang_open_output (lang_statement_union_type *statement)
{
switch (statement->header.type)
{
case lang_output_statement_enum:
ASSERT (link_info.output_bfd == NULL);
open_output (statement->output_statement.name);
ldemul_set_output_arch ();
if (config.magic_demand_paged && !link_info.relocatable)
link_info.output_bfd->flags |= D_PAGED;
else
link_info.output_bfd->flags &= ~D_PAGED;
if (config.text_read_only)
link_info.output_bfd->flags |= WP_TEXT;
else
link_info.output_bfd->flags &= ~WP_TEXT;
if (link_info.traditional_format)
link_info.output_bfd->flags |= BFD_TRADITIONAL_FORMAT;
else
link_info.output_bfd->flags &= ~BFD_TRADITIONAL_FORMAT;
break;
 
case lang_target_statement_enum:
current_target = statement->target_statement.target;
break;
default:
break;
}
}
 
/* Convert between addresses in bytes and sizes in octets.
For currently supported targets, octets_per_byte is always a power
of two, so we can use shifts. */
#define TO_ADDR(X) ((X) >> opb_shift)
#define TO_SIZE(X) ((X) << opb_shift)
 
/* Support the above. */
static unsigned int opb_shift = 0;
 
static void
init_opb (void)
{
unsigned x = bfd_arch_mach_octets_per_byte (ldfile_output_architecture,
ldfile_output_machine);
opb_shift = 0;
if (x > 1)
while ((x & 1) == 0)
{
x >>= 1;
++opb_shift;
}
ASSERT (x == 1);
}
 
/* Open all the input files. */
 
enum open_bfd_mode
{
OPEN_BFD_NORMAL = 0,
OPEN_BFD_FORCE = 1,
OPEN_BFD_RESCAN = 2
};
#ifdef ENABLE_PLUGINS
static lang_input_statement_type *plugin_insert = NULL;
#endif
 
static void
open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
{
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_constructors_statement_enum:
open_input_bfds (constructor_list.head, mode);
break;
case lang_output_section_statement_enum:
open_input_bfds (s->output_section_statement.children.head, mode);
break;
case lang_wild_statement_enum:
/* Maybe we should load the file's symbols. */
if ((mode & OPEN_BFD_RESCAN) == 0
&& s->wild_statement.filename
&& !wildcardp (s->wild_statement.filename)
&& !archive_path (s->wild_statement.filename))
lookup_name (s->wild_statement.filename);
open_input_bfds (s->wild_statement.children.head, mode);
break;
case lang_group_statement_enum:
{
struct bfd_link_hash_entry *undefs;
 
/* We must continually search the entries in the group
until no new symbols are added to the list of undefined
symbols. */
 
do
{
undefs = link_info.hash->undefs_tail;
open_input_bfds (s->group_statement.children.head,
mode | OPEN_BFD_FORCE);
}
while (undefs != link_info.hash->undefs_tail);
}
break;
case lang_target_statement_enum:
current_target = s->target_statement.target;
break;
case lang_input_statement_enum:
if (s->input_statement.flags.real)
{
lang_statement_union_type **os_tail;
lang_statement_list_type add;
 
s->input_statement.target = current_target;
 
/* If we are being called from within a group, and this
is an archive which has already been searched, then
force it to be researched unless the whole archive
has been loaded already. Do the same for a rescan. */
if (mode != OPEN_BFD_NORMAL
#ifdef ENABLE_PLUGINS
&& ((mode & OPEN_BFD_RESCAN) == 0
|| plugin_insert == NULL)
#endif
&& !s->input_statement.flags.whole_archive
&& s->input_statement.flags.loaded
&& s->input_statement.the_bfd != NULL
&& bfd_check_format (s->input_statement.the_bfd,
bfd_archive))
s->input_statement.flags.loaded = FALSE;
#ifdef ENABLE_PLUGINS
/* When rescanning, reload --as-needed shared libs. */
else if ((mode & OPEN_BFD_RESCAN) != 0
&& plugin_insert == NULL
&& s->input_statement.flags.loaded
&& s->input_statement.flags.add_DT_NEEDED_for_regular
&& s->input_statement.the_bfd != NULL
&& ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0
&& plugin_should_reload (s->input_statement.the_bfd))
{
s->input_statement.flags.loaded = FALSE;
s->input_statement.flags.reload = TRUE;
}
#endif
 
os_tail = lang_output_section_statement.tail;
lang_list_init (&add);
 
if (! load_symbols (&s->input_statement, &add))
config.make_executable = FALSE;
 
if (add.head != NULL)
{
/* If this was a script with output sections then
tack any added statements on to the end of the
list. This avoids having to reorder the output
section statement list. Very likely the user
forgot -T, and whatever we do here will not meet
naive user expectations. */
if (os_tail != lang_output_section_statement.tail)
{
einfo (_("%P: warning: %s contains output sections;"
" did you forget -T?\n"),
s->input_statement.filename);
*stat_ptr->tail = add.head;
stat_ptr->tail = add.tail;
}
else
{
*add.tail = s->header.next;
s->header.next = add.head;
}
}
}
#ifdef ENABLE_PLUGINS
/* If we have found the point at which a plugin added new
files, clear plugin_insert to enable archive rescan. */
if (&s->input_statement == plugin_insert)
plugin_insert = NULL;
#endif
break;
case lang_assignment_statement_enum:
if (s->assignment_statement.exp->assign.defsym)
/* This is from a --defsym on the command line. */
exp_fold_tree_no_dot (s->assignment_statement.exp);
break;
default:
break;
}
}
 
/* Exit if any of the files were missing. */
if (input_flags.missing_file)
einfo ("%F");
}
 
/* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions. */
 
void
lang_track_definedness (const char *name)
{
if (bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE) == NULL)
einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
}
 
/* New-function for the definedness hash table. */
 
static struct bfd_hash_entry *
lang_definedness_newfunc (struct bfd_hash_entry *entry,
struct bfd_hash_table *table ATTRIBUTE_UNUSED,
const char *name ATTRIBUTE_UNUSED)
{
struct lang_definedness_hash_entry *ret
= (struct lang_definedness_hash_entry *) entry;
 
if (ret == NULL)
ret = (struct lang_definedness_hash_entry *)
bfd_hash_allocate (table, sizeof (struct lang_definedness_hash_entry));
 
if (ret == NULL)
einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
 
ret->iteration = -1;
return &ret->root;
}
 
/* Return the iteration when the definition of NAME was last updated. A
value of -1 means that the symbol is not defined in the linker script
or the command line, but may be defined in the linker symbol table. */
 
int
lang_symbol_definition_iteration (const char *name)
{
struct lang_definedness_hash_entry *defentry
= (struct lang_definedness_hash_entry *)
bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE);
 
/* We've already created this one on the presence of DEFINED in the
script, so it can't be NULL unless something is borked elsewhere in
the code. */
if (defentry == NULL)
FAIL ();
 
return defentry->iteration;
}
 
/* Update the definedness state of NAME. */
 
void
lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
{
struct lang_definedness_hash_entry *defentry
= (struct lang_definedness_hash_entry *)
bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE);
 
/* We don't keep track of symbols not tested with DEFINED. */
if (defentry == NULL)
return;
 
/* If the symbol was already defined, and not from an earlier statement
iteration, don't update the definedness iteration, because that'd
make the symbol seem defined in the linker script at this point, and
it wasn't; it was defined in some object. If we do anyway, DEFINED
would start to yield false before this point and the construct "sym =
DEFINED (sym) ? sym : X;" would change sym to X despite being defined
in an object. */
if (h->type != bfd_link_hash_undefined
&& h->type != bfd_link_hash_common
&& h->type != bfd_link_hash_new
&& defentry->iteration == -1)
return;
 
defentry->iteration = lang_statement_iteration;
}
 
/* Add the supplied name to the symbol table as an undefined reference.
This is a two step process as the symbol table doesn't even exist at
the time the ld command line is processed. First we put the name
on a list, then, once the output file has been opened, transfer the
name to the symbol table. */
 
typedef struct bfd_sym_chain ldlang_undef_chain_list_type;
 
#define ldlang_undef_chain_list_head entry_symbol.next
 
void
ldlang_add_undef (const char *const name, bfd_boolean cmdline)
{
ldlang_undef_chain_list_type *new_undef;
 
undef_from_cmdline = undef_from_cmdline || cmdline;
new_undef = (ldlang_undef_chain_list_type *) stat_alloc (sizeof (*new_undef));
new_undef->next = ldlang_undef_chain_list_head;
ldlang_undef_chain_list_head = new_undef;
 
new_undef->name = xstrdup (name);
 
if (link_info.output_bfd != NULL)
insert_undefined (new_undef->name);
}
 
/* Insert NAME as undefined in the symbol table. */
 
static void
insert_undefined (const char *name)
{
struct bfd_link_hash_entry *h;
 
h = bfd_link_hash_lookup (link_info.hash, name, TRUE, FALSE, TRUE);
if (h == NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
bfd_link_add_undef (link_info.hash, h);
}
}
 
/* Run through the list of undefineds created above and place them
into the linker hash table as undefined symbols belonging to the
script file. */
 
static void
lang_place_undefineds (void)
{
ldlang_undef_chain_list_type *ptr;
 
for (ptr = ldlang_undef_chain_list_head; ptr != NULL; ptr = ptr->next)
insert_undefined (ptr->name);
}
 
/* Check for all readonly or some readwrite sections. */
 
static void
check_input_sections
(lang_statement_union_type *s,
lang_output_section_statement_type *output_section_statement)
{
for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_wild_statement_enum:
walk_wild (&s->wild_statement, check_section_callback,
output_section_statement);
if (! output_section_statement->all_input_readonly)
return;
break;
case lang_constructors_statement_enum:
check_input_sections (constructor_list.head,
output_section_statement);
if (! output_section_statement->all_input_readonly)
return;
break;
case lang_group_statement_enum:
check_input_sections (s->group_statement.children.head,
output_section_statement);
if (! output_section_statement->all_input_readonly)
return;
break;
default:
break;
}
}
}
 
/* Update wildcard statements if needed. */
 
static void
update_wild_statements (lang_statement_union_type *s)
{
struct wildcard_list *sec;
 
switch (sort_section)
{
default:
FAIL ();
 
case none:
break;
 
case by_name:
case by_alignment:
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
default:
break;
 
case lang_wild_statement_enum:
for (sec = s->wild_statement.section_list; sec != NULL;
sec = sec->next)
{
switch (sec->spec.sorted)
{
case none:
sec->spec.sorted = sort_section;
break;
case by_name:
if (sort_section == by_alignment)
sec->spec.sorted = by_name_alignment;
break;
case by_alignment:
if (sort_section == by_name)
sec->spec.sorted = by_alignment_name;
break;
default:
break;
}
}
break;
 
case lang_constructors_statement_enum:
update_wild_statements (constructor_list.head);
break;
 
case lang_output_section_statement_enum:
/* Don't sort .init/.fini sections. */
if (strcmp (s->output_section_statement.name, ".init") != 0
&& strcmp (s->output_section_statement.name, ".fini") != 0)
update_wild_statements
(s->output_section_statement.children.head);
break;
 
case lang_group_statement_enum:
update_wild_statements (s->group_statement.children.head);
break;
}
}
break;
}
}
 
/* Open input files and attach to output sections. */
 
static void
map_input_to_output_sections
(lang_statement_union_type *s, const char *target,
lang_output_section_statement_type *os)
{
for (; s != NULL; s = s->header.next)
{
lang_output_section_statement_type *tos;
flagword flags;
 
switch (s->header.type)
{
case lang_wild_statement_enum:
wild (&s->wild_statement, target, os);
break;
case lang_constructors_statement_enum:
map_input_to_output_sections (constructor_list.head,
target,
os);
break;
case lang_output_section_statement_enum:
tos = &s->output_section_statement;
if (tos->constraint != 0)
{
if (tos->constraint != ONLY_IF_RW
&& tos->constraint != ONLY_IF_RO)
break;
tos->all_input_readonly = TRUE;
check_input_sections (tos->children.head, tos);
if (tos->all_input_readonly != (tos->constraint == ONLY_IF_RO))
{
tos->constraint = -1;
break;
}
}
map_input_to_output_sections (tos->children.head,
target,
tos);
break;
case lang_output_statement_enum:
break;
case lang_target_statement_enum:
target = s->target_statement.target;
break;
case lang_group_statement_enum:
map_input_to_output_sections (s->group_statement.children.head,
target,
os);
break;
case lang_data_statement_enum:
/* Make sure that any sections mentioned in the expression
are initialized. */
exp_init_os (s->data_statement.exp);
/* The output section gets CONTENTS, ALLOC and LOAD, but
these may be overridden by the script. */
flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD;
switch (os->sectype)
{
case normal_section:
case overlay_section:
break;
case noalloc_section:
flags = SEC_HAS_CONTENTS;
break;
case noload_section:
if (bfd_get_flavour (link_info.output_bfd)
== bfd_target_elf_flavour)
flags = SEC_NEVER_LOAD | SEC_ALLOC;
else
flags = SEC_NEVER_LOAD | SEC_HAS_CONTENTS;
break;
}
if (os->bfd_section == NULL)
init_os (os, flags);
else
os->bfd_section->flags |= flags;
break;
case lang_input_section_enum:
break;
case lang_fill_statement_enum:
case lang_object_symbols_statement_enum:
case lang_reloc_statement_enum:
case lang_padding_statement_enum:
case lang_input_statement_enum:
if (os != NULL && os->bfd_section == NULL)
init_os (os, 0);
break;
case lang_assignment_statement_enum:
if (os != NULL && os->bfd_section == NULL)
init_os (os, 0);
 
/* Make sure that any sections mentioned in the assignment
are initialized. */
exp_init_os (s->assignment_statement.exp);
break;
case lang_address_statement_enum:
/* Mark the specified section with the supplied address.
If this section was actually a segment marker, then the
directive is ignored if the linker script explicitly
processed the segment marker. Originally, the linker
treated segment directives (like -Ttext on the
command-line) as section directives. We honor the
section directive semantics for backwards compatibilty;
linker scripts that do not specifically check for
SEGMENT_START automatically get the old semantics. */
if (!s->address_statement.segment
|| !s->address_statement.segment->used)
{
const char *name = s->address_statement.section_name;
 
/* Create the output section statement here so that
orphans with a set address will be placed after other
script sections. If we let the orphan placement code
place them in amongst other sections then the address
will affect following script sections, which is
likely to surprise naive users. */
tos = lang_output_section_statement_lookup (name, 0, TRUE);
tos->addr_tree = s->address_statement.address;
if (tos->bfd_section == NULL)
init_os (tos, 0);
}
break;
case lang_insert_statement_enum:
break;
}
}
}
 
/* An insert statement snips out all the linker statements from the
start of the list and places them after the output section
statement specified by the insert. This operation is complicated
by the fact that we keep a doubly linked list of output section
statements as well as the singly linked list of all statements. */
 
static void
process_insert_statements (void)
{
lang_statement_union_type **s;
lang_output_section_statement_type *first_os = NULL;
lang_output_section_statement_type *last_os = NULL;
lang_output_section_statement_type *os;
 
/* "start of list" is actually the statement immediately after
the special abs_section output statement, so that it isn't
reordered. */
s = &lang_output_section_statement.head;
while (*(s = &(*s)->header.next) != NULL)
{
if ((*s)->header.type == lang_output_section_statement_enum)
{
/* Keep pointers to the first and last output section
statement in the sequence we may be about to move. */
os = &(*s)->output_section_statement;
 
ASSERT (last_os == NULL || last_os->next == os);
last_os = os;
 
/* Set constraint negative so that lang_output_section_find
won't match this output section statement. At this
stage in linking constraint has values in the range
[-1, ONLY_IN_RW]. */
last_os->constraint = -2 - last_os->constraint;
if (first_os == NULL)
first_os = last_os;
}
else if ((*s)->header.type == lang_insert_statement_enum)
{
lang_insert_statement_type *i = &(*s)->insert_statement;
lang_output_section_statement_type *where;
lang_statement_union_type **ptr;
lang_statement_union_type *first;
 
where = lang_output_section_find (i->where);
if (where != NULL && i->is_before)
{
do
where = where->prev;
while (where != NULL && where->constraint < 0);
}
if (where == NULL)
{
einfo (_("%F%P: %s not found for insert\n"), i->where);
return;
}
 
/* Deal with reordering the output section statement list. */
if (last_os != NULL)
{
asection *first_sec, *last_sec;
struct lang_output_section_statement_struct **next;
 
/* Snip out the output sections we are moving. */
first_os->prev->next = last_os->next;
if (last_os->next == NULL)
{
next = &first_os->prev->next;
lang_output_section_statement.tail
= (lang_statement_union_type **) next;
}
else
last_os->next->prev = first_os->prev;
/* Add them in at the new position. */
last_os->next = where->next;
if (where->next == NULL)
{
next = &last_os->next;
lang_output_section_statement.tail
= (lang_statement_union_type **) next;
}
else
where->next->prev = last_os;
first_os->prev = where;
where->next = first_os;
 
/* Move the bfd sections in the same way. */
first_sec = NULL;
last_sec = NULL;
for (os = first_os; os != NULL; os = os->next)
{
os->constraint = -2 - os->constraint;
if (os->bfd_section != NULL
&& os->bfd_section->owner != NULL)
{
last_sec = os->bfd_section;
if (first_sec == NULL)
first_sec = last_sec;
}
if (os == last_os)
break;
}
if (last_sec != NULL)
{
asection *sec = where->bfd_section;
if (sec == NULL)
sec = output_prev_sec_find (where);
 
/* The place we want to insert must come after the
sections we are moving. So if we find no
section or if the section is the same as our
last section, then no move is needed. */
if (sec != NULL && sec != last_sec)
{
/* Trim them off. */
if (first_sec->prev != NULL)
first_sec->prev->next = last_sec->next;
else
link_info.output_bfd->sections = last_sec->next;
if (last_sec->next != NULL)
last_sec->next->prev = first_sec->prev;
else
link_info.output_bfd->section_last = first_sec->prev;
/* Add back. */
last_sec->next = sec->next;
if (sec->next != NULL)
sec->next->prev = last_sec;
else
link_info.output_bfd->section_last = last_sec;
first_sec->prev = sec;
sec->next = first_sec;
}
}
 
first_os = NULL;
last_os = NULL;
}
 
ptr = insert_os_after (where);
/* Snip everything after the abs_section output statement we
know is at the start of the list, up to and including
the insert statement we are currently processing. */
first = lang_output_section_statement.head->header.next;
lang_output_section_statement.head->header.next = (*s)->header.next;
/* Add them back where they belong. */
*s = *ptr;
if (*s == NULL)
statement_list.tail = s;
*ptr = first;
s = &lang_output_section_statement.head;
}
}
 
/* Undo constraint twiddling. */
for (os = first_os; os != NULL; os = os->next)
{
os->constraint = -2 - os->constraint;
if (os == last_os)
break;
}
}
 
/* An output section might have been removed after its statement was
added. For example, ldemul_before_allocation can remove dynamic
sections if they turn out to be not needed. Clean them up here. */
 
void
strip_excluded_output_sections (void)
{
lang_output_section_statement_type *os;
 
/* Run lang_size_sections (if not already done). */
if (expld.phase != lang_mark_phase_enum)
{
expld.phase = lang_mark_phase_enum;
expld.dataseg.phase = exp_dataseg_none;
one_lang_size_sections_pass (NULL, FALSE);
lang_reset_memory_regions ();
}
 
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
{
asection *output_section;
bfd_boolean exclude;
 
if (os->constraint < 0)
continue;
 
output_section = os->bfd_section;
if (output_section == NULL)
continue;
 
exclude = (output_section->rawsize == 0
&& (output_section->flags & SEC_KEEP) == 0
&& !bfd_section_removed_from_list (link_info.output_bfd,
output_section));
 
/* Some sections have not yet been sized, notably .gnu.version,
.dynsym, .dynstr and .hash. These all have SEC_LINKER_CREATED
input sections, so don't drop output sections that have such
input sections unless they are also marked SEC_EXCLUDE. */
if (exclude && output_section->map_head.s != NULL)
{
asection *s;
 
for (s = output_section->map_head.s; s != NULL; s = s->map_head.s)
if ((s->flags & SEC_EXCLUDE) == 0
&& ((s->flags & SEC_LINKER_CREATED) != 0
|| link_info.emitrelocations))
{
exclude = FALSE;
break;
}
}
 
/* TODO: Don't just junk map_head.s, turn them into link_orders. */
output_section->map_head.link_order = NULL;
output_section->map_tail.link_order = NULL;
 
if (exclude)
{
/* We don't set bfd_section to NULL since bfd_section of the
removed output section statement may still be used. */
if (!os->update_dot)
os->ignored = TRUE;
output_section->flags |= SEC_EXCLUDE;
bfd_section_list_remove (link_info.output_bfd, output_section);
link_info.output_bfd->section_count--;
}
}
 
/* Stop future calls to lang_add_section from messing with map_head
and map_tail link_order fields. */
stripped_excluded_sections = TRUE;
}
 
static void
print_output_section_statement
(lang_output_section_statement_type *output_section_statement)
{
asection *section = output_section_statement->bfd_section;
int len;
 
if (output_section_statement != abs_output_section)
{
minfo ("\n%s", output_section_statement->name);
 
if (section != NULL)
{
print_dot = section->vma;
 
len = strlen (output_section_statement->name);
if (len >= SECTION_NAME_MAP_LENGTH - 1)
{
print_nl ();
len = 0;
}
while (len < SECTION_NAME_MAP_LENGTH)
{
print_space ();
++len;
}
 
minfo ("0x%V %W", section->vma, section->size);
 
if (section->vma != section->lma)
minfo (_(" load address 0x%V"), section->lma);
 
if (output_section_statement->update_dot_tree != NULL)
exp_fold_tree (output_section_statement->update_dot_tree,
bfd_abs_section_ptr, &print_dot);
}
 
print_nl ();
}
 
print_statement_list (output_section_statement->children.head,
output_section_statement);
}
 
static void
print_assignment (lang_assignment_statement_type *assignment,
lang_output_section_statement_type *output_section)
{
unsigned int i;
bfd_boolean is_dot;
etree_type *tree;
asection *osec;
 
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
 
if (assignment->exp->type.node_class == etree_assert)
{
is_dot = FALSE;
tree = assignment->exp->assert_s.child;
}
else
{
const char *dst = assignment->exp->assign.dst;
 
is_dot = (dst[0] == '.' && dst[1] == 0);
expld.assign_name = dst;
tree = assignment->exp->assign.src;
}
 
osec = output_section->bfd_section;
if (osec == NULL)
osec = bfd_abs_section_ptr;
exp_fold_tree (tree, osec, &print_dot);
if (expld.result.valid_p)
{
bfd_vma value;
 
if (assignment->exp->type.node_class == etree_assert
|| is_dot
|| expld.assign_name != NULL)
{
value = expld.result.value;
 
if (expld.result.section != NULL)
value += expld.result.section->vma;
 
minfo ("0x%V", value);
if (is_dot)
print_dot = value;
}
else
{
struct bfd_link_hash_entry *h;
 
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
FALSE, FALSE, TRUE);
if (h)
{
value = h->u.def.value;
value += h->u.def.section->output_section->vma;
value += h->u.def.section->output_offset;
 
minfo ("[0x%V]", value);
}
else
minfo ("[unresolved]");
}
}
else
{
minfo ("*undef* ");
#ifdef BFD64
minfo (" ");
#endif
}
expld.assign_name = NULL;
 
minfo (" ");
exp_print_tree (assignment->exp);
print_nl ();
}
 
static void
print_input_statement (lang_input_statement_type *statm)
{
if (statm->filename != NULL
&& (statm->the_bfd == NULL
|| (statm->the_bfd->flags & BFD_LINKER_CREATED) == 0))
fprintf (config.map_file, "LOAD %s\n", statm->filename);
}
 
/* Print all symbols defined in a particular section. This is called
via bfd_link_hash_traverse, or by print_all_symbols. */
 
static bfd_boolean
print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
{
asection *sec = (asection *) ptr;
 
if ((hash_entry->type == bfd_link_hash_defined
|| hash_entry->type == bfd_link_hash_defweak)
&& sec == hash_entry->u.def.section)
{
int i;
 
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
minfo ("0x%V ",
(hash_entry->u.def.value
+ hash_entry->u.def.section->output_offset
+ hash_entry->u.def.section->output_section->vma));
 
minfo (" %T\n", hash_entry->root.string);
}
 
return TRUE;
}
 
static int
hash_entry_addr_cmp (const void *a, const void *b)
{
const struct bfd_link_hash_entry *l = *(const struct bfd_link_hash_entry **)a;
const struct bfd_link_hash_entry *r = *(const struct bfd_link_hash_entry **)b;
 
if (l->u.def.value < r->u.def.value)
return -1;
else if (l->u.def.value > r->u.def.value)
return 1;
else
return 0;
}
 
static void
print_all_symbols (asection *sec)
{
struct fat_user_section_struct *ud =
(struct fat_user_section_struct *) get_userdata (sec);
struct map_symbol_def *def;
struct bfd_link_hash_entry **entries;
unsigned int i;
 
if (!ud)
return;
 
*ud->map_symbol_def_tail = 0;
 
/* Sort the symbols by address. */
entries = (struct bfd_link_hash_entry **)
obstack_alloc (&map_obstack, ud->map_symbol_def_count * sizeof (*entries));
 
for (i = 0, def = ud->map_symbol_def_head; def; def = def->next, i++)
entries[i] = def->entry;
 
qsort (entries, ud->map_symbol_def_count, sizeof (*entries),
hash_entry_addr_cmp);
 
/* Print the symbols. */
for (i = 0; i < ud->map_symbol_def_count; i++)
print_one_symbol (entries[i], sec);
 
obstack_free (&map_obstack, entries);
}
 
/* Print information about an input section to the map file. */
 
static void
print_input_section (asection *i, bfd_boolean is_discarded)
{
bfd_size_type size = i->size;
int len;
bfd_vma addr;
 
init_opb ();
 
print_space ();
minfo ("%s", i->name);
 
len = 1 + strlen (i->name);
if (len >= SECTION_NAME_MAP_LENGTH - 1)
{
print_nl ();
len = 0;
}
while (len < SECTION_NAME_MAP_LENGTH)
{
print_space ();
++len;
}
 
if (i->output_section != NULL
&& i->output_section->owner == link_info.output_bfd)
addr = i->output_section->vma + i->output_offset;
else
{
addr = print_dot;
if (!is_discarded)
size = 0;
}
 
minfo ("0x%V %W %B\n", addr, TO_ADDR (size), i->owner);
 
if (size != i->rawsize && i->rawsize != 0)
{
len = SECTION_NAME_MAP_LENGTH + 3;
#ifdef BFD64
len += 16;
#else
len += 8;
#endif
while (len > 0)
{
print_space ();
--len;
}
 
minfo (_("%W (size before relaxing)\n"), i->rawsize);
}
 
if (i->output_section != NULL
&& i->output_section->owner == link_info.output_bfd)
{
if (link_info.reduce_memory_overheads)
bfd_link_hash_traverse (link_info.hash, print_one_symbol, i);
else
print_all_symbols (i);
 
/* Update print_dot, but make sure that we do not move it
backwards - this could happen if we have overlays and a
later overlay is shorter than an earier one. */
if (addr + TO_ADDR (size) > print_dot)
print_dot = addr + TO_ADDR (size);
}
}
 
static void
print_fill_statement (lang_fill_statement_type *fill)
{
size_t size;
unsigned char *p;
fputs (" FILL mask 0x", config.map_file);
for (p = fill->fill->data, size = fill->fill->size; size != 0; p++, size--)
fprintf (config.map_file, "%02x", *p);
fputs ("\n", config.map_file);
}
 
static void
print_data_statement (lang_data_statement_type *data)
{
int i;
bfd_vma addr;
bfd_size_type size;
const char *name;
 
init_opb ();
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
 
addr = data->output_offset;
if (data->output_section != NULL)
addr += data->output_section->vma;
 
switch (data->type)
{
default:
abort ();
case BYTE:
size = BYTE_SIZE;
name = "BYTE";
break;
case SHORT:
size = SHORT_SIZE;
name = "SHORT";
break;
case LONG:
size = LONG_SIZE;
name = "LONG";
break;
case QUAD:
size = QUAD_SIZE;
name = "QUAD";
break;
case SQUAD:
size = QUAD_SIZE;
name = "SQUAD";
break;
}
 
minfo ("0x%V %W %s 0x%v", addr, size, name, data->value);
 
if (data->exp->type.node_class != etree_value)
{
print_space ();
exp_print_tree (data->exp);
}
 
print_nl ();
 
print_dot = addr + TO_ADDR (size);
}
 
/* Print an address statement. These are generated by options like
-Ttext. */
 
static void
print_address_statement (lang_address_statement_type *address)
{
minfo (_("Address of section %s set to "), address->section_name);
exp_print_tree (address->address);
print_nl ();
}
 
/* Print a reloc statement. */
 
static void
print_reloc_statement (lang_reloc_statement_type *reloc)
{
int i;
bfd_vma addr;
bfd_size_type size;
 
init_opb ();
for (i = 0; i < SECTION_NAME_MAP_LENGTH; i++)
print_space ();
 
addr = reloc->output_offset;
if (reloc->output_section != NULL)
addr += reloc->output_section->vma;
 
size = bfd_get_reloc_size (reloc->howto);
 
minfo ("0x%V %W RELOC %s ", addr, size, reloc->howto->name);
 
if (reloc->name != NULL)
minfo ("%s+", reloc->name);
else
minfo ("%s+", reloc->section->name);
 
exp_print_tree (reloc->addend_exp);
 
print_nl ();
 
print_dot = addr + TO_ADDR (size);
}
 
static void
print_padding_statement (lang_padding_statement_type *s)
{
int len;
bfd_vma addr;
 
init_opb ();
minfo (" *fill*");
 
len = sizeof " *fill*" - 1;
while (len < SECTION_NAME_MAP_LENGTH)
{
print_space ();
++len;
}
 
addr = s->output_offset;
if (s->output_section != NULL)
addr += s->output_section->vma;
minfo ("0x%V %W ", addr, (bfd_vma) s->size);
 
if (s->fill->size != 0)
{
size_t size;
unsigned char *p;
for (p = s->fill->data, size = s->fill->size; size != 0; p++, size--)
fprintf (config.map_file, "%02x", *p);
}
 
print_nl ();
 
print_dot = addr + TO_ADDR (s->size);
}
 
static void
print_wild_statement (lang_wild_statement_type *w,
lang_output_section_statement_type *os)
{
struct wildcard_list *sec;
 
print_space ();
 
if (w->filenames_sorted)
minfo ("SORT(");
if (w->filename != NULL)
minfo ("%s", w->filename);
else
minfo ("*");
if (w->filenames_sorted)
minfo (")");
 
minfo ("(");
for (sec = w->section_list; sec; sec = sec->next)
{
if (sec->spec.sorted)
minfo ("SORT(");
if (sec->spec.exclude_name_list != NULL)
{
name_list *tmp;
minfo ("EXCLUDE_FILE(%s", sec->spec.exclude_name_list->name);
for (tmp = sec->spec.exclude_name_list->next; tmp; tmp = tmp->next)
minfo (" %s", tmp->name);
minfo (") ");
}
if (sec->spec.name != NULL)
minfo ("%s", sec->spec.name);
else
minfo ("*");
if (sec->spec.sorted)
minfo (")");
if (sec->next)
minfo (" ");
}
minfo (")");
 
print_nl ();
 
print_statement_list (w->children.head, os);
}
 
/* Print a group statement. */
 
static void
print_group (lang_group_statement_type *s,
lang_output_section_statement_type *os)
{
fprintf (config.map_file, "START GROUP\n");
print_statement_list (s->children.head, os);
fprintf (config.map_file, "END GROUP\n");
}
 
/* Print the list of statements in S.
This can be called for any statement type. */
 
static void
print_statement_list (lang_statement_union_type *s,
lang_output_section_statement_type *os)
{
while (s != NULL)
{
print_statement (s, os);
s = s->header.next;
}
}
 
/* Print the first statement in statement list S.
This can be called for any statement type. */
 
static void
print_statement (lang_statement_union_type *s,
lang_output_section_statement_type *os)
{
switch (s->header.type)
{
default:
fprintf (config.map_file, _("Fail with %d\n"), s->header.type);
FAIL ();
break;
case lang_constructors_statement_enum:
if (constructor_list.head != NULL)
{
if (constructors_sorted)
minfo (" SORT (CONSTRUCTORS)\n");
else
minfo (" CONSTRUCTORS\n");
print_statement_list (constructor_list.head, os);
}
break;
case lang_wild_statement_enum:
print_wild_statement (&s->wild_statement, os);
break;
case lang_address_statement_enum:
print_address_statement (&s->address_statement);
break;
case lang_object_symbols_statement_enum:
minfo (" CREATE_OBJECT_SYMBOLS\n");
break;
case lang_fill_statement_enum:
print_fill_statement (&s->fill_statement);
break;
case lang_data_statement_enum:
print_data_statement (&s->data_statement);
break;
case lang_reloc_statement_enum:
print_reloc_statement (&s->reloc_statement);
break;
case lang_input_section_enum:
print_input_section (s->input_section.section, FALSE);
break;
case lang_padding_statement_enum:
print_padding_statement (&s->padding_statement);
break;
case lang_output_section_statement_enum:
print_output_section_statement (&s->output_section_statement);
break;
case lang_assignment_statement_enum:
print_assignment (&s->assignment_statement, os);
break;
case lang_target_statement_enum:
fprintf (config.map_file, "TARGET(%s)\n", s->target_statement.target);
break;
case lang_output_statement_enum:
minfo ("OUTPUT(%s", s->output_statement.name);
if (output_target != NULL)
minfo (" %s", output_target);
minfo (")\n");
break;
case lang_input_statement_enum:
print_input_statement (&s->input_statement);
break;
case lang_group_statement_enum:
print_group (&s->group_statement, os);
break;
case lang_insert_statement_enum:
minfo ("INSERT %s %s\n",
s->insert_statement.is_before ? "BEFORE" : "AFTER",
s->insert_statement.where);
break;
}
}
 
static void
print_statements (void)
{
print_statement_list (statement_list.head, abs_output_section);
}
 
/* Print the first N statements in statement list S to STDERR.
If N == 0, nothing is printed.
If N < 0, the entire list is printed.
Intended to be called from GDB. */
 
void
dprint_statement (lang_statement_union_type *s, int n)
{
FILE *map_save = config.map_file;
 
config.map_file = stderr;
 
if (n < 0)
print_statement_list (s, abs_output_section);
else
{
while (s && --n >= 0)
{
print_statement (s, abs_output_section);
s = s->header.next;
}
}
 
config.map_file = map_save;
}
 
static void
insert_pad (lang_statement_union_type **ptr,
fill_type *fill,
bfd_size_type alignment_needed,
asection *output_section,
bfd_vma dot)
{
static fill_type zero_fill;
lang_statement_union_type *pad = NULL;
 
if (ptr != &statement_list.head)
pad = ((lang_statement_union_type *)
((char *) ptr - offsetof (lang_statement_union_type, header.next)));
if (pad != NULL
&& pad->header.type == lang_padding_statement_enum
&& pad->padding_statement.output_section == output_section)
{
/* Use the existing pad statement. */
}
else if ((pad = *ptr) != NULL
&& pad->header.type == lang_padding_statement_enum
&& pad->padding_statement.output_section == output_section)
{
/* Use the existing pad statement. */
}
else
{
/* Make a new padding statement, linked into existing chain. */
pad = (lang_statement_union_type *)
stat_alloc (sizeof (lang_padding_statement_type));
pad->header.next = *ptr;
*ptr = pad;
pad->header.type = lang_padding_statement_enum;
pad->padding_statement.output_section = output_section;
if (fill == NULL)
fill = &zero_fill;
pad->padding_statement.fill = fill;
}
pad->padding_statement.output_offset = dot - output_section->vma;
pad->padding_statement.size = alignment_needed;
output_section->size = TO_SIZE (dot + TO_ADDR (alignment_needed)
- output_section->vma);
}
 
/* Work out how much this section will move the dot point. */
 
static bfd_vma
size_input_section
(lang_statement_union_type **this_ptr,
lang_output_section_statement_type *output_section_statement,
fill_type *fill,
bfd_vma dot)
{
lang_input_section_type *is = &((*this_ptr)->input_section);
asection *i = is->section;
 
if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
&& (i->flags & SEC_EXCLUDE) == 0)
{
bfd_size_type alignment_needed;
asection *o;
 
/* Align this section first to the input sections requirement,
then to the output section's requirement. If this alignment
is greater than any seen before, then record it too. Perform
the alignment by inserting a magic 'padding' statement. */
 
if (output_section_statement->subsection_alignment != -1)
i->alignment_power = output_section_statement->subsection_alignment;
 
o = output_section_statement->bfd_section;
if (o->alignment_power < i->alignment_power)
o->alignment_power = i->alignment_power;
 
alignment_needed = align_power (dot, i->alignment_power) - dot;
 
if (alignment_needed != 0)
{
insert_pad (this_ptr, fill, TO_SIZE (alignment_needed), o, dot);
dot += alignment_needed;
}
 
/* Remember where in the output section this input section goes. */
 
i->output_offset = dot - o->vma;
 
/* Mark how big the output section must be to contain this now. */
dot += TO_ADDR (i->size);
o->size = TO_SIZE (dot - o->vma);
}
else
{
i->output_offset = i->vma - output_section_statement->bfd_section->vma;
}
 
return dot;
}
 
static int
sort_sections_by_lma (const void *arg1, const void *arg2)
{
const asection *sec1 = *(const asection **) arg1;
const asection *sec2 = *(const asection **) arg2;
 
if (bfd_section_lma (sec1->owner, sec1)
< bfd_section_lma (sec2->owner, sec2))
return -1;
else if (bfd_section_lma (sec1->owner, sec1)
> bfd_section_lma (sec2->owner, sec2))
return 1;
else if (sec1->id < sec2->id)
return -1;
else if (sec1->id > sec2->id)
return 1;
 
return 0;
}
 
#define IGNORE_SECTION(s) \
((s->flags & SEC_ALLOC) == 0 \
|| ((s->flags & SEC_THREAD_LOCAL) != 0 \
&& (s->flags & SEC_LOAD) == 0))
 
/* Check to see if any allocated sections overlap with other allocated
sections. This can happen if a linker script specifies the output
section addresses of the two sections. Also check whether any memory
region has overflowed. */
 
static void
lang_check_section_addresses (void)
{
asection *s, *p;
asection **sections, **spp;
unsigned int count;
bfd_vma s_start;
bfd_vma s_end;
bfd_vma p_start;
bfd_vma p_end;
bfd_size_type amt;
lang_memory_region_type *m;
 
if (bfd_count_sections (link_info.output_bfd) <= 1)
return;
 
amt = bfd_count_sections (link_info.output_bfd) * sizeof (asection *);
sections = (asection **) xmalloc (amt);
 
/* Scan all sections in the output list. */
count = 0;
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
{
/* Only consider loadable sections with real contents. */
if (!(s->flags & SEC_LOAD)
|| !(s->flags & SEC_ALLOC)
|| s->size == 0)
continue;
 
sections[count] = s;
count++;
}
 
if (count <= 1)
return;
 
qsort (sections, (size_t) count, sizeof (asection *),
sort_sections_by_lma);
 
spp = sections;
s = *spp++;
s_start = s->lma;
s_end = s_start + TO_ADDR (s->size) - 1;
for (count--; count; count--)
{
/* We must check the sections' LMA addresses not their VMA
addresses because overlay sections can have overlapping VMAs
but they must have distinct LMAs. */
p = s;
p_start = s_start;
p_end = s_end;
s = *spp++;
s_start = s->lma;
s_end = s_start + TO_ADDR (s->size) - 1;
 
/* Look for an overlap. We have sorted sections by lma, so we
know that s_start >= p_start. Besides the obvious case of
overlap when the current section starts before the previous
one ends, we also must have overlap if the previous section
wraps around the address space. */
if (s_start <= p_end
|| p_end < p_start)
einfo (_("%X%P: section %s loaded at [%V,%V] overlaps section %s loaded at [%V,%V]\n"),
s->name, s_start, s_end, p->name, p_start, p_end);
}
 
free (sections);
 
/* If any memory region has overflowed, report by how much.
We do not issue this diagnostic for regions that had sections
explicitly placed outside their bounds; os_region_check's
diagnostics are adequate for that case.
 
FIXME: It is conceivable that m->current - (m->origin + m->length)
might overflow a 32-bit integer. There is, alas, no way to print
a bfd_vma quantity in decimal. */
for (m = lang_memory_region_list; m; m = m->next)
if (m->had_full_message)
einfo (_("%X%P: region `%s' overflowed by %ld bytes\n"),
m->name_list.name, (long)(m->current - (m->origin + m->length)));
 
}
 
/* Make sure the new address is within the region. We explicitly permit the
current address to be at the exact end of the region when the address is
non-zero, in case the region is at the end of addressable memory and the
calculation wraps around. */
 
static void
os_region_check (lang_output_section_statement_type *os,
lang_memory_region_type *region,
etree_type *tree,
bfd_vma rbase)
{
if ((region->current < region->origin
|| (region->current - region->origin > region->length))
&& ((region->current != region->origin + region->length)
|| rbase == 0))
{
if (tree != NULL)
{
einfo (_("%X%P: address 0x%v of %B section `%s'"
" is not within region `%s'\n"),
region->current,
os->bfd_section->owner,
os->bfd_section->name,
region->name_list.name);
}
else if (!region->had_full_message)
{
region->had_full_message = TRUE;
 
einfo (_("%X%P: %B section `%s' will not fit in region `%s'\n"),
os->bfd_section->owner,
os->bfd_section->name,
region->name_list.name);
}
}
}
 
/* Set the sizes for all the output sections. */
 
static bfd_vma
lang_size_sections_1
(lang_statement_union_type **prev,
lang_output_section_statement_type *output_section_statement,
fill_type *fill,
bfd_vma dot,
bfd_boolean *relax,
bfd_boolean check_regions)
{
lang_statement_union_type *s;
 
/* Size up the sections from their constituent parts. */
for (s = *prev; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_output_section_statement_enum:
{
bfd_vma newdot, after;
lang_output_section_statement_type *os;
lang_memory_region_type *r;
int section_alignment = 0;
 
os = &s->output_section_statement;
if (os->constraint == -1)
break;
 
/* FIXME: We shouldn't need to zero section vmas for ld -r
here, in lang_insert_orphan, or in the default linker scripts.
This is covering for coff backend linker bugs. See PR6945. */
if (os->addr_tree == NULL
&& link_info.relocatable
&& (bfd_get_flavour (link_info.output_bfd)
== bfd_target_coff_flavour))
os->addr_tree = exp_intop (0);
if (os->addr_tree != NULL)
{
os->processed_vma = FALSE;
exp_fold_tree (os->addr_tree, bfd_abs_section_ptr, &dot);
 
if (expld.result.valid_p)
{
dot = expld.result.value;
if (expld.result.section != NULL)
dot += expld.result.section->vma;
}
else if (expld.phase != lang_mark_phase_enum)
einfo (_("%F%S: non constant or forward reference"
" address expression for section %s\n"),
os->addr_tree, os->name);
}
 
if (os->bfd_section == NULL)
/* This section was removed or never actually created. */
break;
 
/* If this is a COFF shared library section, use the size and
address from the input section. FIXME: This is COFF
specific; it would be cleaner if there were some other way
to do this, but nothing simple comes to mind. */
if (((bfd_get_flavour (link_info.output_bfd)
== bfd_target_ecoff_flavour)
|| (bfd_get_flavour (link_info.output_bfd)
== bfd_target_coff_flavour))
&& (os->bfd_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
{
asection *input;
 
if (os->children.head == NULL
|| os->children.head->header.next != NULL
|| (os->children.head->header.type
!= lang_input_section_enum))
einfo (_("%P%X: Internal error on COFF shared library"
" section %s\n"), os->name);
 
input = os->children.head->input_section.section;
bfd_set_section_vma (os->bfd_section->owner,
os->bfd_section,
bfd_section_vma (input->owner, input));
os->bfd_section->size = input->size;
break;
}
 
newdot = dot;
if (bfd_is_abs_section (os->bfd_section))
{
/* No matter what happens, an abs section starts at zero. */
ASSERT (os->bfd_section->vma == 0);
}
else
{
if (os->addr_tree == NULL)
{
/* No address specified for this section, get one
from the region specification. */
if (os->region == NULL
|| ((os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD))
&& os->region->name_list.name[0] == '*'
&& strcmp (os->region->name_list.name,
DEFAULT_MEMORY_REGION) == 0))
{
os->region = lang_memory_default (os->bfd_section);
}
 
/* If a loadable section is using the default memory
region, and some non default memory regions were
defined, issue an error message. */
if (!os->ignored
&& !IGNORE_SECTION (os->bfd_section)
&& ! link_info.relocatable
&& check_regions
&& strcmp (os->region->name_list.name,
DEFAULT_MEMORY_REGION) == 0
&& lang_memory_region_list != NULL
&& (strcmp (lang_memory_region_list->name_list.name,
DEFAULT_MEMORY_REGION) != 0
|| lang_memory_region_list->next != NULL)
&& expld.phase != lang_mark_phase_enum)
{
/* By default this is an error rather than just a
warning because if we allocate the section to the
default memory region we can end up creating an
excessively large binary, or even seg faulting when
attempting to perform a negative seek. See
sources.redhat.com/ml/binutils/2003-04/msg00423.html
for an example of this. This behaviour can be
overridden by the using the --no-check-sections
switch. */
if (command_line.check_section_addresses)
einfo (_("%P%F: error: no memory region specified"
" for loadable section `%s'\n"),
bfd_get_section_name (link_info.output_bfd,
os->bfd_section));
else
einfo (_("%P: warning: no memory region specified"
" for loadable section `%s'\n"),
bfd_get_section_name (link_info.output_bfd,
os->bfd_section));
}
 
newdot = os->region->current;
section_alignment = os->bfd_section->alignment_power;
}
else
section_alignment = os->section_alignment;
 
/* Align to what the section needs. */
if (section_alignment > 0)
{
bfd_vma savedot = newdot;
newdot = align_power (newdot, section_alignment);
 
if (newdot != savedot
&& (config.warn_section_align
|| os->addr_tree != NULL)
&& expld.phase != lang_mark_phase_enum)
einfo (_("%P: warning: changing start of section"
" %s by %lu bytes\n"),
os->name, (unsigned long) (newdot - savedot));
}
 
bfd_set_section_vma (0, os->bfd_section, newdot);
 
os->bfd_section->output_offset = 0;
}
 
lang_size_sections_1 (&os->children.head, os,
os->fill, newdot, relax, check_regions);
 
os->processed_vma = TRUE;
 
if (bfd_is_abs_section (os->bfd_section) || os->ignored)
/* Except for some special linker created sections,
no output section should change from zero size
after strip_excluded_output_sections. A non-zero
size on an ignored section indicates that some
input section was not sized early enough. */
ASSERT (os->bfd_section->size == 0);
else
{
dot = os->bfd_section->vma;
 
/* Put the section within the requested block size, or
align at the block boundary. */
after = ((dot
+ TO_ADDR (os->bfd_section->size)
+ os->block_value - 1)
& - (bfd_vma) os->block_value);
 
os->bfd_section->size = TO_SIZE (after - os->bfd_section->vma);
}
 
/* Set section lma. */
r = os->region;
if (r == NULL)
r = lang_memory_region_lookup (DEFAULT_MEMORY_REGION, FALSE);
 
if (os->load_base)
{
bfd_vma lma = exp_get_abs_int (os->load_base, 0, "load base");
os->bfd_section->lma = lma;
}
else if (os->lma_region != NULL)
{
bfd_vma lma = os->lma_region->current;
 
/* When LMA_REGION is the same as REGION, align the LMA
as we did for the VMA, possibly including alignment
from the bfd section. If a different region, then
only align according to the value in the output
statement unless specified otherwise. */
if (os->lma_region != os->region && !os->align_lma_with_input)
section_alignment = os->section_alignment;
if (section_alignment > 0)
lma = align_power (lma, section_alignment);
os->bfd_section->lma = lma;
}
else if (r->last_os != NULL
&& (os->bfd_section->flags & SEC_ALLOC) != 0)
{
bfd_vma lma;
asection *last;
 
last = r->last_os->output_section_statement.bfd_section;
 
/* A backwards move of dot should be accompanied by
an explicit assignment to the section LMA (ie.
os->load_base set) because backwards moves can
create overlapping LMAs. */
if (dot < last->vma
&& os->bfd_section->size != 0
&& dot + os->bfd_section->size <= last->vma)
{
/* If dot moved backwards then leave lma equal to
vma. This is the old default lma, which might
just happen to work when the backwards move is
sufficiently large. Nag if this changes anything,
so people can fix their linker scripts. */
 
if (last->vma != last->lma)
einfo (_("%P: warning: dot moved backwards before `%s'\n"),
os->name);
}
else
{
/* If this is an overlay, set the current lma to that
at the end of the previous section. */
if (os->sectype == overlay_section)
lma = last->lma + last->size;
 
/* Otherwise, keep the same lma to vma relationship
as the previous section. */
else
lma = dot + last->lma - last->vma;
 
if (section_alignment > 0)
lma = align_power (lma, section_alignment);
os->bfd_section->lma = lma;
}
}
os->processed_lma = TRUE;
 
if (bfd_is_abs_section (os->bfd_section) || os->ignored)
break;
 
/* Keep track of normal sections using the default
lma region. We use this to set the lma for
following sections. Overlays or other linker
script assignment to lma might mean that the
default lma == vma is incorrect.
To avoid warnings about dot moving backwards when using
-Ttext, don't start tracking sections until we find one
of non-zero size or with lma set differently to vma. */
if (((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0)
&& (os->bfd_section->flags & SEC_ALLOC) != 0
&& (os->bfd_section->size != 0
|| (r->last_os == NULL
&& os->bfd_section->vma != os->bfd_section->lma)
|| (r->last_os != NULL
&& dot >= (r->last_os->output_section_statement
.bfd_section->vma)))
&& os->lma_region == NULL
&& !link_info.relocatable)
r->last_os = s;
 
/* .tbss sections effectively have zero size. */
if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
|| link_info.relocatable)
dot += TO_ADDR (os->bfd_section->size);
 
if (os->update_dot_tree != 0)
exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
 
/* Update dot in the region ?
We only do this if the section is going to be allocated,
since unallocated sections do not contribute to the region's
overall size in memory. */
if (os->region != NULL
&& (os->bfd_section->flags & (SEC_ALLOC | SEC_LOAD)))
{
os->region->current = dot;
 
if (check_regions)
/* Make sure the new address is within the region. */
os_region_check (os, os->region, os->addr_tree,
os->bfd_section->vma);
 
if (os->lma_region != NULL && os->lma_region != os->region
&& (os->bfd_section->flags & SEC_LOAD))
{
os->lma_region->current
= os->bfd_section->lma + TO_ADDR (os->bfd_section->size);
 
if (check_regions)
os_region_check (os, os->lma_region, NULL,
os->bfd_section->lma);
}
}
}
break;
 
case lang_constructors_statement_enum:
dot = lang_size_sections_1 (&constructor_list.head,
output_section_statement,
fill, dot, relax, check_regions);
break;
 
case lang_data_statement_enum:
{
unsigned int size = 0;
 
s->data_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
s->data_statement.output_section =
output_section_statement->bfd_section;
 
/* We might refer to provided symbols in the expression, and
need to mark them as needed. */
exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
 
switch (s->data_statement.type)
{
default:
abort ();
case QUAD:
case SQUAD:
size = QUAD_SIZE;
break;
case LONG:
size = LONG_SIZE;
break;
case SHORT:
size = SHORT_SIZE;
break;
case BYTE:
size = BYTE_SIZE;
break;
}
if (size < TO_SIZE ((unsigned) 1))
size = TO_SIZE ((unsigned) 1);
dot += TO_ADDR (size);
output_section_statement->bfd_section->size
= TO_SIZE (dot - output_section_statement->bfd_section->vma);
 
}
break;
 
case lang_reloc_statement_enum:
{
int size;
 
s->reloc_statement.output_offset =
dot - output_section_statement->bfd_section->vma;
s->reloc_statement.output_section =
output_section_statement->bfd_section;
size = bfd_get_reloc_size (s->reloc_statement.howto);
dot += TO_ADDR (size);
output_section_statement->bfd_section->size
= TO_SIZE (dot - output_section_statement->bfd_section->vma);
}
break;
 
case lang_wild_statement_enum:
dot = lang_size_sections_1 (&s->wild_statement.children.head,
output_section_statement,
fill, dot, relax, check_regions);
break;
 
case lang_object_symbols_statement_enum:
link_info.create_object_symbols_section =
output_section_statement->bfd_section;
break;
 
case lang_output_statement_enum:
case lang_target_statement_enum:
break;
 
case lang_input_section_enum:
{
asection *i;
 
i = s->input_section.section;
if (relax)
{
bfd_boolean again;
 
if (! bfd_relax_section (i->owner, i, &link_info, &again))
einfo (_("%P%F: can't relax section: %E\n"));
if (again)
*relax = TRUE;
}
dot = size_input_section (prev, output_section_statement,
output_section_statement->fill, dot);
}
break;
 
case lang_input_statement_enum:
break;
 
case lang_fill_statement_enum:
s->fill_statement.output_section =
output_section_statement->bfd_section;
 
fill = s->fill_statement.fill;
break;
 
case lang_assignment_statement_enum:
{
bfd_vma newdot = dot;
etree_type *tree = s->assignment_statement.exp;
 
expld.dataseg.relro = exp_dataseg_relro_none;
 
exp_fold_tree (tree,
output_section_statement->bfd_section,
&newdot);
 
if (expld.dataseg.relro == exp_dataseg_relro_start)
{
if (!expld.dataseg.relro_start_stat)
expld.dataseg.relro_start_stat = s;
else
{
ASSERT (expld.dataseg.relro_start_stat == s);
}
}
else if (expld.dataseg.relro == exp_dataseg_relro_end)
{
if (!expld.dataseg.relro_end_stat)
expld.dataseg.relro_end_stat = s;
else
{
ASSERT (expld.dataseg.relro_end_stat == s);
}
}
expld.dataseg.relro = exp_dataseg_relro_none;
 
/* This symbol may be relative to this section. */
if ((tree->type.node_class == etree_provided
|| tree->type.node_class == etree_assign)
&& (tree->assign.dst [0] != '.'
|| tree->assign.dst [1] != '\0'))
output_section_statement->update_dot = 1;
 
if (!output_section_statement->ignored)
{
if (output_section_statement == abs_output_section)
{
/* If we don't have an output section, then just adjust
the default memory address. */
lang_memory_region_lookup (DEFAULT_MEMORY_REGION,
FALSE)->current = newdot;
}
else if (newdot != dot)
{
/* Insert a pad after this statement. We can't
put the pad before when relaxing, in case the
assignment references dot. */
insert_pad (&s->header.next, fill, TO_SIZE (newdot - dot),
output_section_statement->bfd_section, dot);
 
/* Don't neuter the pad below when relaxing. */
s = s->header.next;
 
/* If dot is advanced, this implies that the section
should have space allocated to it, unless the
user has explicitly stated that the section
should not be allocated. */
if (output_section_statement->sectype != noalloc_section
&& (output_section_statement->sectype != noload_section
|| (bfd_get_flavour (link_info.output_bfd)
== bfd_target_elf_flavour)))
output_section_statement->bfd_section->flags |= SEC_ALLOC;
}
dot = newdot;
}
}
break;
 
case lang_padding_statement_enum:
/* If this is the first time lang_size_sections is called,
we won't have any padding statements. If this is the
second or later passes when relaxing, we should allow
padding to shrink. If padding is needed on this pass, it
will be added back in. */
s->padding_statement.size = 0;
 
/* Make sure output_offset is valid. If relaxation shrinks
the section and this pad isn't needed, it's possible to
have output_offset larger than the final size of the
section. bfd_set_section_contents will complain even for
a pad size of zero. */
s->padding_statement.output_offset
= dot - output_section_statement->bfd_section->vma;
break;
 
case lang_group_statement_enum:
dot = lang_size_sections_1 (&s->group_statement.children.head,
output_section_statement,
fill, dot, relax, check_regions);
break;
 
case lang_insert_statement_enum:
break;
 
/* We can only get here when relaxing is turned on. */
case lang_address_statement_enum:
break;
 
default:
FAIL ();
break;
}
prev = &s->header.next;
}
return dot;
}
 
/* Callback routine that is used in _bfd_elf_map_sections_to_segments.
The BFD library has set NEW_SEGMENT to TRUE iff it thinks that
CURRENT_SECTION and PREVIOUS_SECTION ought to be placed into different
segments. We are allowed an opportunity to override this decision. */
 
bfd_boolean
ldlang_override_segment_assignment (struct bfd_link_info * info ATTRIBUTE_UNUSED,
bfd * abfd ATTRIBUTE_UNUSED,
asection * current_section,
asection * previous_section,
bfd_boolean new_segment)
{
lang_output_section_statement_type * cur;
lang_output_section_statement_type * prev;
 
/* The checks below are only necessary when the BFD library has decided
that the two sections ought to be placed into the same segment. */
if (new_segment)
return TRUE;
 
/* Paranoia checks. */
if (current_section == NULL || previous_section == NULL)
return new_segment;
 
/* If this flag is set, the target never wants code and non-code
sections comingled in the same segment. */
if (config.separate_code
&& ((current_section->flags ^ previous_section->flags) & SEC_CODE))
return TRUE;
 
/* Find the memory regions associated with the two sections.
We call lang_output_section_find() here rather than scanning the list
of output sections looking for a matching section pointer because if
we have a large number of sections then a hash lookup is faster. */
cur = lang_output_section_find (current_section->name);
prev = lang_output_section_find (previous_section->name);
 
/* More paranoia. */
if (cur == NULL || prev == NULL)
return new_segment;
 
/* If the regions are different then force the sections to live in
different segments. See the email thread starting at the following
URL for the reasons why this is necessary:
http://sourceware.org/ml/binutils/2007-02/msg00216.html */
return cur->region != prev->region;
}
 
void
one_lang_size_sections_pass (bfd_boolean *relax, bfd_boolean check_regions)
{
lang_statement_iteration++;
lang_size_sections_1 (&statement_list.head, abs_output_section,
0, 0, relax, check_regions);
}
 
void
lang_size_sections (bfd_boolean *relax, bfd_boolean check_regions)
{
expld.phase = lang_allocating_phase_enum;
expld.dataseg.phase = exp_dataseg_none;
 
one_lang_size_sections_pass (relax, check_regions);
if (expld.dataseg.phase == exp_dataseg_end_seen
&& link_info.relro && expld.dataseg.relro_end)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_RELRO_END pair was seen, try
to put expld.dataseg.relro on a (common) page boundary. */
bfd_vma min_base, old_base, relro_end, maxpage;
 
expld.dataseg.phase = exp_dataseg_relro_adjust;
maxpage = expld.dataseg.maxpagesize;
/* MIN_BASE is the absolute minimum address we are allowed to start the
read-write segment (byte before will be mapped read-only). */
min_base = (expld.dataseg.min_base + maxpage - 1) & ~(maxpage - 1);
/* OLD_BASE is the address for a feasible minimum address which will
still not cause a data overlap inside MAXPAGE causing file offset skip
by MAXPAGE. */
old_base = expld.dataseg.base;
expld.dataseg.base += (-expld.dataseg.relro_end
& (expld.dataseg.pagesize - 1));
/* Compute the expected PT_GNU_RELRO segment end. */
relro_end = ((expld.dataseg.relro_end + expld.dataseg.pagesize - 1)
& ~(expld.dataseg.pagesize - 1));
if (min_base + maxpage < expld.dataseg.base)
{
expld.dataseg.base -= maxpage;
relro_end -= maxpage;
}
lang_reset_memory_regions ();
one_lang_size_sections_pass (relax, check_regions);
if (expld.dataseg.relro_end > relro_end)
{
/* The alignment of sections between DATA_SEGMENT_ALIGN
and DATA_SEGMENT_RELRO_END caused huge padding to be
inserted at DATA_SEGMENT_RELRO_END. Try to start a bit lower so
that the section alignments will fit in. */
asection *sec;
unsigned int max_alignment_power = 0;
 
/* Find maximum alignment power of sections between
DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END. */
for (sec = link_info.output_bfd->sections; sec; sec = sec->next)
if (sec->vma >= expld.dataseg.base
&& sec->vma < expld.dataseg.relro_end
&& sec->alignment_power > max_alignment_power)
max_alignment_power = sec->alignment_power;
 
if (((bfd_vma) 1 << max_alignment_power) < expld.dataseg.pagesize)
{
if (expld.dataseg.base - (1 << max_alignment_power) < old_base)
expld.dataseg.base += expld.dataseg.pagesize;
expld.dataseg.base -= (1 << max_alignment_power);
lang_reset_memory_regions ();
one_lang_size_sections_pass (relax, check_regions);
}
}
link_info.relro_start = expld.dataseg.base;
link_info.relro_end = expld.dataseg.relro_end;
}
else if (expld.dataseg.phase == exp_dataseg_end_seen)
{
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
a page could be saved in the data segment. */
bfd_vma first, last;
 
first = -expld.dataseg.base & (expld.dataseg.pagesize - 1);
last = expld.dataseg.end & (expld.dataseg.pagesize - 1);
if (first && last
&& ((expld.dataseg.base & ~(expld.dataseg.pagesize - 1))
!= (expld.dataseg.end & ~(expld.dataseg.pagesize - 1)))
&& first + last <= expld.dataseg.pagesize)
{
expld.dataseg.phase = exp_dataseg_adjust;
lang_reset_memory_regions ();
one_lang_size_sections_pass (relax, check_regions);
}
else
expld.dataseg.phase = exp_dataseg_done;
}
else
expld.dataseg.phase = exp_dataseg_done;
}
 
static lang_output_section_statement_type *current_section;
static lang_assignment_statement_type *current_assign;
static bfd_boolean prefer_next_section;
 
/* Worker function for lang_do_assignments. Recursiveness goes here. */
 
static bfd_vma
lang_do_assignments_1 (lang_statement_union_type *s,
lang_output_section_statement_type *current_os,
fill_type *fill,
bfd_vma dot,
bfd_boolean *found_end)
{
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_constructors_statement_enum:
dot = lang_do_assignments_1 (constructor_list.head,
current_os, fill, dot, found_end);
break;
 
case lang_output_section_statement_enum:
{
lang_output_section_statement_type *os;
 
os = &(s->output_section_statement);
os->after_end = *found_end;
if (os->bfd_section != NULL && !os->ignored)
{
if ((os->bfd_section->flags & SEC_ALLOC) != 0)
{
current_section = os;
prefer_next_section = FALSE;
}
dot = os->bfd_section->vma;
 
lang_do_assignments_1 (os->children.head,
os, os->fill, dot, found_end);
 
/* .tbss sections effectively have zero size. */
if ((os->bfd_section->flags & SEC_HAS_CONTENTS) != 0
|| (os->bfd_section->flags & SEC_THREAD_LOCAL) == 0
|| link_info.relocatable)
dot += TO_ADDR (os->bfd_section->size);
 
if (os->update_dot_tree != NULL)
exp_fold_tree (os->update_dot_tree, bfd_abs_section_ptr, &dot);
}
}
break;
 
case lang_wild_statement_enum:
 
dot = lang_do_assignments_1 (s->wild_statement.children.head,
current_os, fill, dot, found_end);
break;
 
case lang_object_symbols_statement_enum:
case lang_output_statement_enum:
case lang_target_statement_enum:
break;
 
case lang_data_statement_enum:
exp_fold_tree (s->data_statement.exp, bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
{
s->data_statement.value = expld.result.value;
if (expld.result.section != NULL)
s->data_statement.value += expld.result.section->vma;
}
else
einfo (_("%F%P: invalid data statement\n"));
{
unsigned int size;
switch (s->data_statement.type)
{
default:
abort ();
case QUAD:
case SQUAD:
size = QUAD_SIZE;
break;
case LONG:
size = LONG_SIZE;
break;
case SHORT:
size = SHORT_SIZE;
break;
case BYTE:
size = BYTE_SIZE;
break;
}
if (size < TO_SIZE ((unsigned) 1))
size = TO_SIZE ((unsigned) 1);
dot += TO_ADDR (size);
}
break;
 
case lang_reloc_statement_enum:
exp_fold_tree (s->reloc_statement.addend_exp,
bfd_abs_section_ptr, &dot);
if (expld.result.valid_p)
s->reloc_statement.addend_value = expld.result.value;
else
einfo (_("%F%P: invalid reloc statement\n"));
dot += TO_ADDR (bfd_get_reloc_size (s->reloc_statement.howto));
break;
 
case lang_input_section_enum:
{
asection *in = s->input_section.section;
 
if ((in->flags & SEC_EXCLUDE) == 0)
dot += TO_ADDR (in->size);
}
break;
 
case lang_input_statement_enum:
break;
 
case lang_fill_statement_enum:
fill = s->fill_statement.fill;
break;
 
case lang_assignment_statement_enum:
current_assign = &s->assignment_statement;
if (current_assign->exp->type.node_class != etree_assert)
{
const char *p = current_assign->exp->assign.dst;
 
if (current_os == abs_output_section && p[0] == '.' && p[1] == 0)
prefer_next_section = TRUE;
 
while (*p == '_')
++p;
if (strcmp (p, "end") == 0)
*found_end = TRUE;
}
exp_fold_tree (s->assignment_statement.exp,
current_os->bfd_section,
&dot);
break;
 
case lang_padding_statement_enum:
dot += TO_ADDR (s->padding_statement.size);
break;
 
case lang_group_statement_enum:
dot = lang_do_assignments_1 (s->group_statement.children.head,
current_os, fill, dot, found_end);
break;
 
case lang_insert_statement_enum:
break;
 
case lang_address_statement_enum:
break;
 
default:
FAIL ();
break;
}
}
return dot;
}
 
void
lang_do_assignments (lang_phase_type phase)
{
bfd_boolean found_end = FALSE;
 
current_section = NULL;
prefer_next_section = FALSE;
expld.phase = phase;
lang_statement_iteration++;
lang_do_assignments_1 (statement_list.head,
abs_output_section, NULL, 0, &found_end);
}
 
/* For an assignment statement outside of an output section statement,
choose the best of neighbouring output sections to use for values
of "dot". */
 
asection *
section_for_dot (void)
{
asection *s;
 
/* Assignments belong to the previous output section, unless there
has been an assignment to "dot", in which case following
assignments belong to the next output section. (The assumption
is that an assignment to "dot" is setting up the address for the
next output section.) Except that past the assignment to "_end"
we always associate with the previous section. This exception is
for targets like SH that define an alloc .stack or other
weirdness after non-alloc sections. */
if (current_section == NULL || prefer_next_section)
{
lang_statement_union_type *stmt;
lang_output_section_statement_type *os;
 
for (stmt = (lang_statement_union_type *) current_assign;
stmt != NULL;
stmt = stmt->header.next)
if (stmt->header.type == lang_output_section_statement_enum)
break;
 
os = &stmt->output_section_statement;
while (os != NULL
&& !os->after_end
&& (os->bfd_section == NULL
|| (os->bfd_section->flags & SEC_EXCLUDE) != 0
|| bfd_section_removed_from_list (link_info.output_bfd,
os->bfd_section)))
os = os->next;
 
if (current_section == NULL || os == NULL || !os->after_end)
{
if (os != NULL)
s = os->bfd_section;
else
s = link_info.output_bfd->section_last;
while (s != NULL
&& ((s->flags & SEC_ALLOC) == 0
|| (s->flags & SEC_THREAD_LOCAL) != 0))
s = s->prev;
if (s != NULL)
return s;
 
return bfd_abs_section_ptr;
}
}
 
s = current_section->bfd_section;
 
/* The section may have been stripped. */
while (s != NULL
&& ((s->flags & SEC_EXCLUDE) != 0
|| (s->flags & SEC_ALLOC) == 0
|| (s->flags & SEC_THREAD_LOCAL) != 0
|| bfd_section_removed_from_list (link_info.output_bfd, s)))
s = s->prev;
if (s == NULL)
s = link_info.output_bfd->sections;
while (s != NULL
&& ((s->flags & SEC_ALLOC) == 0
|| (s->flags & SEC_THREAD_LOCAL) != 0))
s = s->next;
if (s != NULL)
return s;
 
return bfd_abs_section_ptr;
}
 
/* Fix any .startof. or .sizeof. symbols. When the assemblers see the
operator .startof. (section_name), it produces an undefined symbol
.startof.section_name. Similarly, when it sees
.sizeof. (section_name), it produces an undefined symbol
.sizeof.section_name. For all the output sections, we look for
such symbols, and set them to the correct value. */
 
static void
lang_set_startof (void)
{
asection *s;
 
if (link_info.relocatable)
return;
 
for (s = link_info.output_bfd->sections; s != NULL; s = s->next)
{
const char *secname;
char *buf;
struct bfd_link_hash_entry *h;
 
secname = bfd_get_section_name (link_info.output_bfd, s);
buf = (char *) xmalloc (10 + strlen (secname));
 
sprintf (buf, ".startof.%s", secname);
h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
h->type = bfd_link_hash_defined;
h->u.def.value = 0;
h->u.def.section = s;
}
 
sprintf (buf, ".sizeof.%s", secname);
h = bfd_link_hash_lookup (link_info.hash, buf, FALSE, FALSE, TRUE);
if (h != NULL && h->type == bfd_link_hash_undefined)
{
h->type = bfd_link_hash_defined;
h->u.def.value = TO_ADDR (s->size);
h->u.def.section = bfd_abs_section_ptr;
}
 
free (buf);
}
}
 
static void
lang_end (void)
{
struct bfd_link_hash_entry *h;
bfd_boolean warn;
 
if ((link_info.relocatable && !link_info.gc_sections)
|| (link_info.shared && !link_info.executable))
warn = entry_from_cmdline;
else
warn = TRUE;
 
/* Force the user to specify a root when generating a relocatable with
--gc-sections. */
if (link_info.gc_sections && link_info.relocatable
&& !(entry_from_cmdline || undef_from_cmdline))
einfo (_("%P%F: gc-sections requires either an entry or "
"an undefined symbol\n"));
 
if (entry_symbol.name == NULL)
{
/* No entry has been specified. Look for the default entry, but
don't warn if we don't find it. */
entry_symbol.name = entry_symbol_default;
warn = FALSE;
}
 
h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
FALSE, FALSE, TRUE);
if (h != NULL
&& (h->type == bfd_link_hash_defined
|| h->type == bfd_link_hash_defweak)
&& h->u.def.section->output_section != NULL)
{
bfd_vma val;
 
val = (h->u.def.value
+ bfd_get_section_vma (link_info.output_bfd,
h->u.def.section->output_section)
+ h->u.def.section->output_offset);
if (! bfd_set_start_address (link_info.output_bfd, val))
einfo (_("%P%F:%s: can't set start address\n"), entry_symbol.name);
}
else
{
bfd_vma val;
const char *send;
 
/* We couldn't find the entry symbol. Try parsing it as a
number. */
val = bfd_scan_vma (entry_symbol.name, &send, 0);
if (*send == '\0')
{
if (! bfd_set_start_address (link_info.output_bfd, val))
einfo (_("%P%F: can't set start address\n"));
}
else
{
asection *ts;
 
/* Can't find the entry symbol, and it's not a number. Use
the first address in the text section. */
ts = bfd_get_section_by_name (link_info.output_bfd, entry_section);
if (ts != NULL)
{
if (warn)
einfo (_("%P: warning: cannot find entry symbol %s;"
" defaulting to %V\n"),
entry_symbol.name,
bfd_get_section_vma (link_info.output_bfd, ts));
if (!(bfd_set_start_address
(link_info.output_bfd,
bfd_get_section_vma (link_info.output_bfd, ts))))
einfo (_("%P%F: can't set start address\n"));
}
else
{
if (warn)
einfo (_("%P: warning: cannot find entry symbol %s;"
" not setting start address\n"),
entry_symbol.name);
}
}
}
}
 
/* This is a small function used when we want to ignore errors from
BFD. */
 
static void
ignore_bfd_errors (const char *s ATTRIBUTE_UNUSED, ...)
{
/* Don't do anything. */
}
 
/* Check that the architecture of all the input files is compatible
with the output file. Also call the backend to let it do any
other checking that is needed. */
 
static void
lang_check (void)
{
lang_statement_union_type *file;
bfd *input_bfd;
const bfd_arch_info_type *compatible;
 
for (file = file_chain.head; file != NULL; file = file->input_statement.next)
{
#ifdef ENABLE_PLUGINS
/* Don't check format of files claimed by plugin. */
if (file->input_statement.flags.claimed)
continue;
#endif /* ENABLE_PLUGINS */
input_bfd = file->input_statement.the_bfd;
compatible
= bfd_arch_get_compatible (input_bfd, link_info.output_bfd,
command_line.accept_unknown_input_arch);
 
/* In general it is not possible to perform a relocatable
link between differing object formats when the input
file has relocations, because the relocations in the
input format may not have equivalent representations in
the output format (and besides BFD does not translate
relocs for other link purposes than a final link). */
if ((link_info.relocatable || link_info.emitrelocations)
&& (compatible == NULL
|| (bfd_get_flavour (input_bfd)
!= bfd_get_flavour (link_info.output_bfd)))
&& (bfd_get_file_flags (input_bfd) & HAS_RELOC) != 0)
{
einfo (_("%P%F: Relocatable linking with relocations from"
" format %s (%B) to format %s (%B) is not supported\n"),
bfd_get_target (input_bfd), input_bfd,
bfd_get_target (link_info.output_bfd), link_info.output_bfd);
/* einfo with %F exits. */
}
 
if (compatible == NULL)
{
if (command_line.warn_mismatch)
einfo (_("%P%X: %s architecture of input file `%B'"
" is incompatible with %s output\n"),
bfd_printable_name (input_bfd), input_bfd,
bfd_printable_name (link_info.output_bfd));
}
else if (bfd_count_sections (input_bfd))
{
/* If the input bfd has no contents, it shouldn't set the
private data of the output bfd. */
 
bfd_error_handler_type pfn = NULL;
 
/* If we aren't supposed to warn about mismatched input
files, temporarily set the BFD error handler to a
function which will do nothing. We still want to call
bfd_merge_private_bfd_data, since it may set up
information which is needed in the output file. */
if (! command_line.warn_mismatch)
pfn = bfd_set_error_handler (ignore_bfd_errors);
if (! bfd_merge_private_bfd_data (input_bfd, link_info.output_bfd))
{
if (command_line.warn_mismatch)
einfo (_("%P%X: failed to merge target specific data"
" of file %B\n"), input_bfd);
}
if (! command_line.warn_mismatch)
bfd_set_error_handler (pfn);
}
}
}
 
/* Look through all the global common symbols and attach them to the
correct section. The -sort-common command line switch may be used
to roughly sort the entries by alignment. */
 
static void
lang_common (void)
{
if (command_line.inhibit_common_definition)
return;
if (link_info.relocatable
&& ! command_line.force_common_definition)
return;
 
if (! config.sort_common)
bfd_link_hash_traverse (link_info.hash, lang_one_common, NULL);
else
{
unsigned int power;
 
if (config.sort_common == sort_descending)
{
for (power = 4; power > 0; power--)
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
 
power = 0;
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
}
else
{
for (power = 0; power <= 4; power++)
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
 
power = UINT_MAX;
bfd_link_hash_traverse (link_info.hash, lang_one_common, &power);
}
}
}
 
/* Place one common symbol in the correct section. */
 
static bfd_boolean
lang_one_common (struct bfd_link_hash_entry *h, void *info)
{
unsigned int power_of_two;
bfd_vma size;
asection *section;
 
if (h->type != bfd_link_hash_common)
return TRUE;
 
size = h->u.c.size;
power_of_two = h->u.c.p->alignment_power;
 
if (config.sort_common == sort_descending
&& power_of_two < *(unsigned int *) info)
return TRUE;
else if (config.sort_common == sort_ascending
&& power_of_two > *(unsigned int *) info)
return TRUE;
 
section = h->u.c.p->section;
if (!bfd_define_common_symbol (link_info.output_bfd, &link_info, h))
einfo (_("%P%F: Could not define common symbol `%T': %E\n"),
h->root.string);
 
if (config.map_file != NULL)
{
static bfd_boolean header_printed;
int len;
char *name;
char buf[50];
 
if (! header_printed)
{
minfo (_("\nAllocating common symbols\n"));
minfo (_("Common symbol size file\n\n"));
header_printed = TRUE;
}
 
name = bfd_demangle (link_info.output_bfd, h->root.string,
DMGL_ANSI | DMGL_PARAMS);
if (name == NULL)
{
minfo ("%s", h->root.string);
len = strlen (h->root.string);
}
else
{
minfo ("%s", name);
len = strlen (name);
free (name);
}
 
if (len >= 19)
{
print_nl ();
len = 0;
}
while (len < 20)
{
print_space ();
++len;
}
 
minfo ("0x");
if (size <= 0xffffffff)
sprintf (buf, "%lx", (unsigned long) size);
else
sprintf_vma (buf, size);
minfo ("%s", buf);
len = strlen (buf);
 
while (len < 16)
{
print_space ();
++len;
}
 
minfo ("%B\n", section->owner);
}
 
return TRUE;
}
 
/* Run through the input files and ensure that every input section has
somewhere to go. If one is found without a destination then create
an input request and place it into the statement tree. */
 
static void
lang_place_orphans (void)
{
LANG_FOR_EACH_INPUT_STATEMENT (file)
{
asection *s;
 
for (s = file->the_bfd->sections; s != NULL; s = s->next)
{
if (s->output_section == NULL)
{
/* This section of the file is not attached, root
around for a sensible place for it to go. */
 
if (file->flags.just_syms)
bfd_link_just_syms (file->the_bfd, s, &link_info);
else if ((s->flags & SEC_EXCLUDE) != 0)
s->output_section = bfd_abs_section_ptr;
else if (strcmp (s->name, "COMMON") == 0)
{
/* This is a lonely common section which must have
come from an archive. We attach to the section
with the wildcard. */
if (! link_info.relocatable
|| command_line.force_common_definition)
{
if (default_common_section == NULL)
default_common_section
= lang_output_section_statement_lookup (".bss", 0,
TRUE);
lang_add_section (&default_common_section->children, s,
NULL, default_common_section);
}
}
else
{
const char *name = s->name;
int constraint = 0;
 
if (config.unique_orphan_sections
|| unique_section_p (s, NULL))
constraint = SPECIAL;
 
if (!ldemul_place_orphan (s, name, constraint))
{
lang_output_section_statement_type *os;
os = lang_output_section_statement_lookup (name,
constraint,
TRUE);
if (os->addr_tree == NULL
&& (link_info.relocatable
|| (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0))
os->addr_tree = exp_intop (0);
lang_add_section (&os->children, s, NULL, os);
}
}
}
}
}
}
 
void
lang_set_flags (lang_memory_region_type *ptr, const char *flags, int invert)
{
flagword *ptr_flags;
 
ptr_flags = invert ? &ptr->not_flags : &ptr->flags;
while (*flags)
{
switch (*flags)
{
case 'A': case 'a':
*ptr_flags |= SEC_ALLOC;
break;
 
case 'R': case 'r':
*ptr_flags |= SEC_READONLY;
break;
 
case 'W': case 'w':
*ptr_flags |= SEC_DATA;
break;
 
case 'X': case 'x':
*ptr_flags |= SEC_CODE;
break;
 
case 'L': case 'l':
case 'I': case 'i':
*ptr_flags |= SEC_LOAD;
break;
 
default:
einfo (_("%P%F: invalid syntax in flags\n"));
break;
}
flags++;
}
}
 
/* Call a function on each input file. This function will be called
on an archive, but not on the elements. */
 
void
lang_for_each_input_file (void (*func) (lang_input_statement_type *))
{
lang_input_statement_type *f;
 
for (f = (lang_input_statement_type *) input_file_chain.head;
f != NULL;
f = (lang_input_statement_type *) f->next_real_file)
func (f);
}
 
/* Call a function on each file. The function will be called on all
the elements of an archive which are included in the link, but will
not be called on the archive file itself. */
 
void
lang_for_each_file (void (*func) (lang_input_statement_type *))
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
func (f);
}
}
 
void
ldlang_add_file (lang_input_statement_type *entry)
{
lang_statement_append (&file_chain,
(lang_statement_union_type *) entry,
&entry->next);
 
/* The BFD linker needs to have a list of all input BFDs involved in
a link. */
ASSERT (entry->the_bfd->link_next == NULL);
ASSERT (entry->the_bfd != link_info.output_bfd);
 
*link_info.input_bfds_tail = entry->the_bfd;
link_info.input_bfds_tail = &entry->the_bfd->link_next;
entry->the_bfd->usrdata = entry;
bfd_set_gp_size (entry->the_bfd, g_switch_value);
 
/* Look through the sections and check for any which should not be
included in the link. We need to do this now, so that we can
notice when the backend linker tries to report multiple
definition errors for symbols which are in sections we aren't
going to link. FIXME: It might be better to entirely ignore
symbols which are defined in sections which are going to be
discarded. This would require modifying the backend linker for
each backend which might set the SEC_LINK_ONCE flag. If we do
this, we should probably handle SEC_EXCLUDE in the same way. */
 
bfd_map_over_sections (entry->the_bfd, section_already_linked, entry);
}
 
void
lang_add_output (const char *name, int from_script)
{
/* Make -o on command line override OUTPUT in script. */
if (!had_output_filename || !from_script)
{
output_filename = name;
had_output_filename = TRUE;
}
}
 
static int
topower (int x)
{
unsigned int i = 1;
int l;
 
if (x < 0)
return -1;
 
for (l = 0; l < 32; l++)
{
if (i >= (unsigned int) x)
return l;
i <<= 1;
}
 
return 0;
}
 
lang_output_section_statement_type *
lang_enter_output_section_statement (const char *output_section_statement_name,
etree_type *address_exp,
enum section_type sectype,
etree_type *align,
etree_type *subalign,
etree_type *ebase,
int constraint,
int align_with_input)
{
lang_output_section_statement_type *os;
 
os = lang_output_section_statement_lookup (output_section_statement_name,
constraint, TRUE);
current_section = os;
 
if (os->addr_tree == NULL)
{
os->addr_tree = address_exp;
}
os->sectype = sectype;
if (sectype != noload_section)
os->flags = SEC_NO_FLAGS;
else
os->flags = SEC_NEVER_LOAD;
os->block_value = 1;
 
/* Make next things chain into subchain of this. */
push_stat_ptr (&os->children);
 
os->align_lma_with_input = align_with_input == ALIGN_WITH_INPUT;
if (os->align_lma_with_input && align != NULL)
einfo (_("%F%P:%S: error: align with input and explicit align specified\n"), NULL);
 
os->subsection_alignment =
topower (exp_get_value_int (subalign, -1, "subsection alignment"));
os->section_alignment =
topower (exp_get_value_int (align, -1, "section alignment"));
 
os->load_base = ebase;
return os;
}
 
void
lang_final (void)
{
lang_output_statement_type *new_stmt;
 
new_stmt = new_stat (lang_output_statement, stat_ptr);
new_stmt->name = output_filename;
 
}
 
/* Reset the current counters in the regions. */
 
void
lang_reset_memory_regions (void)
{
lang_memory_region_type *p = lang_memory_region_list;
asection *o;
lang_output_section_statement_type *os;
 
for (p = lang_memory_region_list; p != NULL; p = p->next)
{
p->current = p->origin;
p->last_os = NULL;
}
 
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
{
os->processed_vma = FALSE;
os->processed_lma = FALSE;
}
 
for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
{
/* Save the last size for possible use by bfd_relax_section. */
o->rawsize = o->size;
o->size = 0;
}
}
 
/* Worker for lang_gc_sections_1. */
 
static void
gc_section_callback (lang_wild_statement_type *ptr,
struct wildcard_list *sec ATTRIBUTE_UNUSED,
asection *section,
struct flag_info *sflag_info ATTRIBUTE_UNUSED,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
/* If the wild pattern was marked KEEP, the member sections
should be as well. */
if (ptr->keep_sections)
section->flags |= SEC_KEEP;
}
 
/* Iterate over sections marking them against GC. */
 
static void
lang_gc_sections_1 (lang_statement_union_type *s)
{
for (; s != NULL; s = s->header.next)
{
switch (s->header.type)
{
case lang_wild_statement_enum:
walk_wild (&s->wild_statement, gc_section_callback, NULL);
break;
case lang_constructors_statement_enum:
lang_gc_sections_1 (constructor_list.head);
break;
case lang_output_section_statement_enum:
lang_gc_sections_1 (s->output_section_statement.children.head);
break;
case lang_group_statement_enum:
lang_gc_sections_1 (s->group_statement.children.head);
break;
default:
break;
}
}
}
 
static void
lang_gc_sections (void)
{
/* Keep all sections so marked in the link script. */
 
lang_gc_sections_1 (statement_list.head);
 
/* SEC_EXCLUDE is ignored when doing a relocatable link, except in
the special case of debug info. (See bfd/stabs.c)
Twiddle the flag here, to simplify later linker code. */
if (link_info.relocatable)
{
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
asection *sec;
#ifdef ENABLE_PLUGINS
if (f->flags.claimed)
continue;
#endif
for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_DEBUGGING) == 0)
sec->flags &= ~SEC_EXCLUDE;
}
}
 
if (link_info.gc_sections)
bfd_gc_sections (link_info.output_bfd, &link_info);
}
 
/* Worker for lang_find_relro_sections_1. */
 
static void
find_relro_section_callback (lang_wild_statement_type *ptr ATTRIBUTE_UNUSED,
struct wildcard_list *sec ATTRIBUTE_UNUSED,
asection *section,
struct flag_info *sflag_info ATTRIBUTE_UNUSED,
lang_input_statement_type *file ATTRIBUTE_UNUSED,
void *data)
{
/* Discarded, excluded and ignored sections effectively have zero
size. */
if (section->output_section != NULL
&& section->output_section->owner == link_info.output_bfd
&& (section->output_section->flags & SEC_EXCLUDE) == 0
&& !IGNORE_SECTION (section)
&& section->size != 0)
{
bfd_boolean *has_relro_section = (bfd_boolean *) data;
*has_relro_section = TRUE;
}
}
 
/* Iterate over sections for relro sections. */
 
static void
lang_find_relro_sections_1 (lang_statement_union_type *s,
bfd_boolean *has_relro_section)
{
if (*has_relro_section)
return;
 
for (; s != NULL; s = s->header.next)
{
if (s == expld.dataseg.relro_end_stat)
break;
 
switch (s->header.type)
{
case lang_wild_statement_enum:
walk_wild (&s->wild_statement,
find_relro_section_callback,
has_relro_section);
break;
case lang_constructors_statement_enum:
lang_find_relro_sections_1 (constructor_list.head,
has_relro_section);
break;
case lang_output_section_statement_enum:
lang_find_relro_sections_1 (s->output_section_statement.children.head,
has_relro_section);
break;
case lang_group_statement_enum:
lang_find_relro_sections_1 (s->group_statement.children.head,
has_relro_section);
break;
default:
break;
}
}
}
 
static void
lang_find_relro_sections (void)
{
bfd_boolean has_relro_section = FALSE;
 
/* Check all sections in the link script. */
 
lang_find_relro_sections_1 (expld.dataseg.relro_start_stat,
&has_relro_section);
 
if (!has_relro_section)
link_info.relro = FALSE;
}
 
/* Relax all sections until bfd_relax_section gives up. */
 
void
lang_relax_sections (bfd_boolean need_layout)
{
if (RELAXATION_ENABLED)
{
/* We may need more than one relaxation pass. */
int i = link_info.relax_pass;
 
/* The backend can use it to determine the current pass. */
link_info.relax_pass = 0;
 
while (i--)
{
/* Keep relaxing until bfd_relax_section gives up. */
bfd_boolean relax_again;
 
link_info.relax_trip = -1;
do
{
link_info.relax_trip++;
 
/* Note: pe-dll.c does something like this also. If you find
you need to change this code, you probably need to change
pe-dll.c also. DJ */
 
/* Do all the assignments with our current guesses as to
section sizes. */
lang_do_assignments (lang_assigning_phase_enum);
 
/* We must do this after lang_do_assignments, because it uses
size. */
lang_reset_memory_regions ();
 
/* Perform another relax pass - this time we know where the
globals are, so can make a better guess. */
relax_again = FALSE;
lang_size_sections (&relax_again, FALSE);
}
while (relax_again);
 
link_info.relax_pass++;
}
need_layout = TRUE;
}
 
if (need_layout)
{
/* Final extra sizing to report errors. */
lang_do_assignments (lang_assigning_phase_enum);
lang_reset_memory_regions ();
lang_size_sections (NULL, TRUE);
}
}
 
#ifdef ENABLE_PLUGINS
/* Find the insert point for the plugin's replacement files. We
place them after the first claimed real object file, or if the
first claimed object is an archive member, after the last real
object file immediately preceding the archive. In the event
no objects have been claimed at all, we return the first dummy
object file on the list as the insert point; that works, but
the callee must be careful when relinking the file_chain as it
is not actually on that chain, only the statement_list and the
input_file list; in that case, the replacement files must be
inserted at the head of the file_chain. */
 
static lang_input_statement_type *
find_replacements_insert_point (void)
{
lang_input_statement_type *claim1, *lastobject;
lastobject = &input_file_chain.head->input_statement;
for (claim1 = &file_chain.head->input_statement;
claim1 != NULL;
claim1 = &claim1->next->input_statement)
{
if (claim1->flags.claimed)
return claim1->flags.claim_archive ? lastobject : claim1;
/* Update lastobject if this is a real object file. */
if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
lastobject = claim1;
}
/* No files were claimed by the plugin. Choose the last object
file found on the list (maybe the first, dummy entry) as the
insert point. */
return lastobject;
}
 
/* Insert SRCLIST into DESTLIST after given element by chaining
on FIELD as the next-pointer. (Counterintuitively does not need
a pointer to the actual after-node itself, just its chain field.) */
 
static void
lang_list_insert_after (lang_statement_list_type *destlist,
lang_statement_list_type *srclist,
lang_statement_union_type **field)
{
*(srclist->tail) = *field;
*field = srclist->head;
if (destlist->tail == field)
destlist->tail = srclist->tail;
}
 
/* Detach new nodes added to DESTLIST since the time ORIGLIST
was taken as a copy of it and leave them in ORIGLIST. */
 
static void
lang_list_remove_tail (lang_statement_list_type *destlist,
lang_statement_list_type *origlist)
{
union lang_statement_union **savetail;
/* Check that ORIGLIST really is an earlier state of DESTLIST. */
ASSERT (origlist->head == destlist->head);
savetail = origlist->tail;
origlist->head = *(savetail);
origlist->tail = destlist->tail;
destlist->tail = savetail;
*savetail = NULL;
}
#endif /* ENABLE_PLUGINS */
 
void
lang_process (void)
{
/* Finalize dynamic list. */
if (link_info.dynamic_list)
lang_finalize_version_expr_head (&link_info.dynamic_list->head);
 
current_target = default_target;
 
/* Open the output file. */
lang_for_each_statement (ldlang_open_output);
init_opb ();
 
ldemul_create_output_section_statements ();
 
/* Add to the hash table all undefineds on the command line. */
lang_place_undefineds ();
 
if (!bfd_section_already_linked_table_init ())
einfo (_("%P%F: Failed to create hash table\n"));
 
/* Create a bfd for each input file. */
current_target = default_target;
open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
#ifdef ENABLE_PLUGINS
if (plugin_active_plugins_p ())
{
lang_statement_list_type added;
lang_statement_list_type files, inputfiles;
 
/* Now all files are read, let the plugin(s) decide if there
are any more to be added to the link before we call the
emulation's after_open hook. We create a private list of
input statements for this purpose, which we will eventually
insert into the global statment list after the first claimed
file. */
added = *stat_ptr;
/* We need to manipulate all three chains in synchrony. */
files = file_chain;
inputfiles = input_file_chain;
if (plugin_call_all_symbols_read ())
einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
plugin_error_plugin ());
/* Open any newly added files, updating the file chains. */
link_info.loading_lto_outputs = TRUE;
open_input_bfds (*added.tail, OPEN_BFD_NORMAL);
/* Restore the global list pointer now they have all been added. */
lang_list_remove_tail (stat_ptr, &added);
/* And detach the fresh ends of the file lists. */
lang_list_remove_tail (&file_chain, &files);
lang_list_remove_tail (&input_file_chain, &inputfiles);
/* Were any new files added? */
if (added.head != NULL)
{
/* If so, we will insert them into the statement list immediately
after the first input file that was claimed by the plugin. */
plugin_insert = find_replacements_insert_point ();
/* If a plugin adds input files without having claimed any, we
don't really have a good idea where to place them. Just putting
them at the start or end of the list is liable to leave them
outside the crtbegin...crtend range. */
ASSERT (plugin_insert != NULL);
/* Splice the new statement list into the old one. */
lang_list_insert_after (stat_ptr, &added,
&plugin_insert->header.next);
/* Likewise for the file chains. */
lang_list_insert_after (&input_file_chain, &inputfiles,
&plugin_insert->next_real_file);
/* We must be careful when relinking file_chain; we may need to
insert the new files at the head of the list if the insert
point chosen is the dummy first input file. */
if (plugin_insert->filename)
lang_list_insert_after (&file_chain, &files, &plugin_insert->next);
else
lang_list_insert_after (&file_chain, &files, &file_chain.head);
 
/* Rescan archives in case new undefined symbols have appeared. */
open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
}
}
#endif /* ENABLE_PLUGINS */
 
link_info.gc_sym_list = &entry_symbol;
if (entry_symbol.name == NULL)
link_info.gc_sym_list = ldlang_undef_chain_list_head;
 
ldemul_after_open ();
 
bfd_section_already_linked_table_free ();
 
/* Make sure that we're not mixing architectures. We call this
after all the input files have been opened, but before we do any
other processing, so that any operations merge_private_bfd_data
does on the output file will be known during the rest of the
link. */
lang_check ();
 
/* Handle .exports instead of a version script if we're told to do so. */
if (command_line.version_exports_section)
lang_do_version_exports_section ();
 
/* Build all sets based on the information gathered from the input
files. */
ldctor_build_sets ();
 
/* PR 13683: We must rerun the assignments prior to running garbage
collection in order to make sure that all symbol aliases are resolved. */
lang_do_assignments (lang_mark_phase_enum);
expld.phase = lang_first_phase_enum;
 
/* Remove unreferenced sections if asked to. */
lang_gc_sections ();
 
/* Size up the common data. */
lang_common ();
 
/* Update wild statements. */
update_wild_statements (statement_list.head);
 
/* Run through the contours of the script and attach input sections
to the correct output sections. */
lang_statement_iteration++;
map_input_to_output_sections (statement_list.head, NULL, NULL);
 
process_insert_statements ();
 
/* Find any sections not attached explicitly and handle them. */
lang_place_orphans ();
 
if (! link_info.relocatable)
{
asection *found;
 
/* Merge SEC_MERGE sections. This has to be done after GC of
sections, so that GCed sections are not merged, but before
assigning dynamic symbols, since removing whole input sections
is hard then. */
bfd_merge_sections (link_info.output_bfd, &link_info);
 
/* Look for a text section and set the readonly attribute in it. */
found = bfd_get_section_by_name (link_info.output_bfd, ".text");
 
if (found != NULL)
{
if (config.text_read_only)
found->flags |= SEC_READONLY;
else
found->flags &= ~SEC_READONLY;
}
}
 
/* Do anything special before sizing sections. This is where ELF
and other back-ends size dynamic sections. */
ldemul_before_allocation ();
 
/* We must record the program headers before we try to fix the
section positions, since they will affect SIZEOF_HEADERS. */
lang_record_phdrs ();
 
/* Check relro sections. */
if (link_info.relro && ! link_info.relocatable)
lang_find_relro_sections ();
 
/* Size up the sections. */
lang_size_sections (NULL, ! RELAXATION_ENABLED);
 
/* See if anything special should be done now we know how big
everything is. This is where relaxation is done. */
ldemul_after_allocation ();
 
/* Fix any .startof. or .sizeof. symbols. */
lang_set_startof ();
 
/* Do all the assignments, now that we know the final resting places
of all the symbols. */
lang_do_assignments (lang_final_phase_enum);
 
ldemul_finish ();
 
/* Make sure that the section addresses make sense. */
if (command_line.check_section_addresses)
lang_check_section_addresses ();
 
lang_end ();
}
 
/* EXPORTED TO YACC */
 
void
lang_add_wild (struct wildcard_spec *filespec,
struct wildcard_list *section_list,
bfd_boolean keep_sections)
{
struct wildcard_list *curr, *next;
lang_wild_statement_type *new_stmt;
 
/* Reverse the list as the parser puts it back to front. */
for (curr = section_list, section_list = NULL;
curr != NULL;
section_list = curr, curr = next)
{
if (curr->spec.name != NULL && strcmp (curr->spec.name, "COMMON") == 0)
placed_commons = TRUE;
 
next = curr->next;
curr->next = section_list;
}
 
if (filespec != NULL && filespec->name != NULL)
{
if (strcmp (filespec->name, "*") == 0)
filespec->name = NULL;
else if (! wildcardp (filespec->name))
lang_has_input_file = TRUE;
}
 
new_stmt = new_stat (lang_wild_statement, stat_ptr);
new_stmt->filename = NULL;
new_stmt->filenames_sorted = FALSE;
new_stmt->section_flag_list = NULL;
if (filespec != NULL)
{
new_stmt->filename = filespec->name;
new_stmt->filenames_sorted = filespec->sorted == by_name;
new_stmt->section_flag_list = filespec->section_flag_list;
}
new_stmt->section_list = section_list;
new_stmt->keep_sections = keep_sections;
lang_list_init (&new_stmt->children);
analyze_walk_wild_section_handler (new_stmt);
}
 
void
lang_section_start (const char *name, etree_type *address,
const segment_type *segment)
{
lang_address_statement_type *ad;
 
ad = new_stat (lang_address_statement, stat_ptr);
ad->section_name = name;
ad->address = address;
ad->segment = segment;
}
 
/* Set the start symbol to NAME. CMDLINE is nonzero if this is called
because of a -e argument on the command line, or zero if this is
called by ENTRY in a linker script. Command line arguments take
precedence. */
 
void
lang_add_entry (const char *name, bfd_boolean cmdline)
{
if (entry_symbol.name == NULL
|| cmdline
|| ! entry_from_cmdline)
{
entry_symbol.name = name;
entry_from_cmdline = cmdline;
}
}
 
/* Set the default start symbol to NAME. .em files should use this,
not lang_add_entry, to override the use of "start" if neither the
linker script nor the command line specifies an entry point. NAME
must be permanently allocated. */
void
lang_default_entry (const char *name)
{
entry_symbol_default = name;
}
 
void
lang_add_target (const char *name)
{
lang_target_statement_type *new_stmt;
 
new_stmt = new_stat (lang_target_statement, stat_ptr);
new_stmt->target = name;
}
 
void
lang_add_map (const char *name)
{
while (*name)
{
switch (*name)
{
case 'F':
map_option_f = TRUE;
break;
}
name++;
}
}
 
void
lang_add_fill (fill_type *fill)
{
lang_fill_statement_type *new_stmt;
 
new_stmt = new_stat (lang_fill_statement, stat_ptr);
new_stmt->fill = fill;
}
 
void
lang_add_data (int type, union etree_union *exp)
{
lang_data_statement_type *new_stmt;
 
new_stmt = new_stat (lang_data_statement, stat_ptr);
new_stmt->exp = exp;
new_stmt->type = type;
}
 
/* Create a new reloc statement. RELOC is the BFD relocation type to
generate. HOWTO is the corresponding howto structure (we could
look this up, but the caller has already done so). SECTION is the
section to generate a reloc against, or NAME is the name of the
symbol to generate a reloc against. Exactly one of SECTION and
NAME must be NULL. ADDEND is an expression for the addend. */
 
void
lang_add_reloc (bfd_reloc_code_real_type reloc,
reloc_howto_type *howto,
asection *section,
const char *name,
union etree_union *addend)
{
lang_reloc_statement_type *p = new_stat (lang_reloc_statement, stat_ptr);
 
p->reloc = reloc;
p->howto = howto;
p->section = section;
p->name = name;
p->addend_exp = addend;
 
p->addend_value = 0;
p->output_section = NULL;
p->output_offset = 0;
}
 
lang_assignment_statement_type *
lang_add_assignment (etree_type *exp)
{
lang_assignment_statement_type *new_stmt;
 
new_stmt = new_stat (lang_assignment_statement, stat_ptr);
new_stmt->exp = exp;
return new_stmt;
}
 
void
lang_add_attribute (enum statement_enum attribute)
{
new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr);
}
 
void
lang_startup (const char *name)
{
if (first_file->filename != NULL)
{
einfo (_("%P%F: multiple STARTUP files\n"));
}
first_file->filename = name;
first_file->local_sym_name = name;
first_file->flags.real = TRUE;
}
 
void
lang_float (bfd_boolean maybe)
{
lang_float_flag = maybe;
}
 
 
/* Work out the load- and run-time regions from a script statement, and
store them in *LMA_REGION and *REGION respectively.
 
MEMSPEC is the name of the run-time region, or the value of
DEFAULT_MEMORY_REGION if the statement didn't specify one.
LMA_MEMSPEC is the name of the load-time region, or null if the
statement didn't specify one.HAVE_LMA_P is TRUE if the statement
had an explicit load address.
 
It is an error to specify both a load region and a load address. */
 
static void
lang_get_regions (lang_memory_region_type **region,
lang_memory_region_type **lma_region,
const char *memspec,
const char *lma_memspec,
bfd_boolean have_lma,
bfd_boolean have_vma)
{
*lma_region = lang_memory_region_lookup (lma_memspec, FALSE);
 
/* If no runtime region or VMA has been specified, but the load region
has been specified, then use the load region for the runtime region
as well. */
if (lma_memspec != NULL
&& ! have_vma
&& strcmp (memspec, DEFAULT_MEMORY_REGION) == 0)
*region = *lma_region;
else
*region = lang_memory_region_lookup (memspec, FALSE);
 
if (have_lma && lma_memspec != 0)
einfo (_("%X%P:%S: section has both a load address and a load region\n"),
NULL);
}
 
void
lang_leave_output_section_statement (fill_type *fill, const char *memspec,
lang_output_section_phdr_list *phdrs,
const char *lma_memspec)
{
lang_get_regions (&current_section->region,
&current_section->lma_region,
memspec, lma_memspec,
current_section->load_base != NULL,
current_section->addr_tree != NULL);
 
/* If this section has no load region or base, but uses the same
region as the previous section, then propagate the previous
section's load region. */
 
if (current_section->lma_region == NULL
&& current_section->load_base == NULL
&& current_section->addr_tree == NULL
&& current_section->region == current_section->prev->region)
current_section->lma_region = current_section->prev->lma_region;
 
current_section->fill = fill;
current_section->phdrs = phdrs;
pop_stat_ptr ();
}
 
void
lang_statement_append (lang_statement_list_type *list,
lang_statement_union_type *element,
lang_statement_union_type **field)
{
*(list->tail) = element;
list->tail = field;
}
 
/* Set the output format type. -oformat overrides scripts. */
 
void
lang_add_output_format (const char *format,
const char *big,
const char *little,
int from_script)
{
if (output_target == NULL || !from_script)
{
if (command_line.endian == ENDIAN_BIG
&& big != NULL)
format = big;
else if (command_line.endian == ENDIAN_LITTLE
&& little != NULL)
format = little;
 
output_target = format;
}
}
 
void
lang_add_insert (const char *where, int is_before)
{
lang_insert_statement_type *new_stmt;
 
new_stmt = new_stat (lang_insert_statement, stat_ptr);
new_stmt->where = where;
new_stmt->is_before = is_before;
saved_script_handle = previous_script_handle;
}
 
/* Enter a group. This creates a new lang_group_statement, and sets
stat_ptr to build new statements within the group. */
 
void
lang_enter_group (void)
{
lang_group_statement_type *g;
 
g = new_stat (lang_group_statement, stat_ptr);
lang_list_init (&g->children);
push_stat_ptr (&g->children);
}
 
/* Leave a group. This just resets stat_ptr to start writing to the
regular list of statements again. Note that this will not work if
groups can occur inside anything else which can adjust stat_ptr,
but currently they can't. */
 
void
lang_leave_group (void)
{
pop_stat_ptr ();
}
 
/* Add a new program header. This is called for each entry in a PHDRS
command in a linker script. */
 
void
lang_new_phdr (const char *name,
etree_type *type,
bfd_boolean filehdr,
bfd_boolean phdrs,
etree_type *at,
etree_type *flags)
{
struct lang_phdr *n, **pp;
bfd_boolean hdrs;
 
n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr));
n->next = NULL;
n->name = name;
n->type = exp_get_value_int (type, 0, "program header type");
n->filehdr = filehdr;
n->phdrs = phdrs;
n->at = at;
n->flags = flags;
 
hdrs = n->type == 1 && (phdrs || filehdr);
 
for (pp = &lang_phdr_list; *pp != NULL; pp = &(*pp)->next)
if (hdrs
&& (*pp)->type == 1
&& !((*pp)->filehdr || (*pp)->phdrs))
{
einfo (_("%X%P:%S: PHDRS and FILEHDR are not supported"
" when prior PT_LOAD headers lack them\n"), NULL);
hdrs = FALSE;
}
 
*pp = n;
}
 
/* Record the program header information in the output BFD. FIXME: We
should not be calling an ELF specific function here. */
 
static void
lang_record_phdrs (void)
{
unsigned int alc;
asection **secs;
lang_output_section_phdr_list *last;
struct lang_phdr *l;
lang_output_section_statement_type *os;
 
alc = 10;
secs = (asection **) xmalloc (alc * sizeof (asection *));
last = NULL;
 
for (l = lang_phdr_list; l != NULL; l = l->next)
{
unsigned int c;
flagword flags;
bfd_vma at;
 
c = 0;
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
{
lang_output_section_phdr_list *pl;
 
if (os->constraint < 0)
continue;
 
pl = os->phdrs;
if (pl != NULL)
last = pl;
else
{
if (os->sectype == noload_section
|| os->bfd_section == NULL
|| (os->bfd_section->flags & SEC_ALLOC) == 0)
continue;
 
/* Don't add orphans to PT_INTERP header. */
if (l->type == 3)
continue;
 
if (last == NULL)
{
lang_output_section_statement_type * tmp_os;
 
/* If we have not run across a section with a program
header assigned to it yet, then scan forwards to find
one. This prevents inconsistencies in the linker's
behaviour when a script has specified just a single
header and there are sections in that script which are
not assigned to it, and which occur before the first
use of that header. See here for more details:
http://sourceware.org/ml/binutils/2007-02/msg00291.html */
for (tmp_os = os; tmp_os; tmp_os = tmp_os->next)
if (tmp_os->phdrs)
{
last = tmp_os->phdrs;
break;
}
if (last == NULL)
einfo (_("%F%P: no sections assigned to phdrs\n"));
}
pl = last;
}
 
if (os->bfd_section == NULL)
continue;
 
for (; pl != NULL; pl = pl->next)
{
if (strcmp (pl->name, l->name) == 0)
{
if (c >= alc)
{
alc *= 2;
secs = (asection **) xrealloc (secs,
alc * sizeof (asection *));
}
secs[c] = os->bfd_section;
++c;
pl->used = TRUE;
}
}
}
 
if (l->flags == NULL)
flags = 0;
else
flags = exp_get_vma (l->flags, 0, "phdr flags");
 
if (l->at == NULL)
at = 0;
else
at = exp_get_vma (l->at, 0, "phdr load address");
 
if (! bfd_record_phdr (link_info.output_bfd, l->type,
l->flags != NULL, flags, l->at != NULL,
at, l->filehdr, l->phdrs, c, secs))
einfo (_("%F%P: bfd_record_phdr failed: %E\n"));
}
 
free (secs);
 
/* Make sure all the phdr assignments succeeded. */
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
{
lang_output_section_phdr_list *pl;
 
if (os->constraint < 0
|| os->bfd_section == NULL)
continue;
 
for (pl = os->phdrs;
pl != NULL;
pl = pl->next)
if (! pl->used && strcmp (pl->name, "NONE") != 0)
einfo (_("%X%P: section `%s' assigned to non-existent phdr `%s'\n"),
os->name, pl->name);
}
}
 
/* Record a list of sections which may not be cross referenced. */
 
void
lang_add_nocrossref (lang_nocrossref_type *l)
{
struct lang_nocrossrefs *n;
 
n = (struct lang_nocrossrefs *) xmalloc (sizeof *n);
n->next = nocrossref_list;
n->list = l;
nocrossref_list = n;
 
/* Set notice_all so that we get informed about all symbols. */
link_info.notice_all = TRUE;
}
/* Overlay handling. We handle overlays with some static variables. */
 
/* The overlay virtual address. */
static etree_type *overlay_vma;
/* And subsection alignment. */
static etree_type *overlay_subalign;
 
/* An expression for the maximum section size seen so far. */
static etree_type *overlay_max;
 
/* A list of all the sections in this overlay. */
 
struct overlay_list {
struct overlay_list *next;
lang_output_section_statement_type *os;
};
 
static struct overlay_list *overlay_list;
 
/* Start handling an overlay. */
 
void
lang_enter_overlay (etree_type *vma_expr, etree_type *subalign)
{
/* The grammar should prevent nested overlays from occurring. */
ASSERT (overlay_vma == NULL
&& overlay_subalign == NULL
&& overlay_max == NULL);
 
overlay_vma = vma_expr;
overlay_subalign = subalign;
}
 
/* Start a section in an overlay. We handle this by calling
lang_enter_output_section_statement with the correct VMA.
lang_leave_overlay sets up the LMA and memory regions. */
 
void
lang_enter_overlay_section (const char *name)
{
struct overlay_list *n;
etree_type *size;
 
lang_enter_output_section_statement (name, overlay_vma, overlay_section,
0, overlay_subalign, 0, 0, 0);
 
/* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is
used in the addresses. */
if (overlay_list == NULL)
overlay_vma = exp_nameop (ADDR, name);
 
/* Remember the section. */
n = (struct overlay_list *) xmalloc (sizeof *n);
n->os = current_section;
n->next = overlay_list;
overlay_list = n;
 
size = exp_nameop (SIZEOF, name);
 
/* Arrange to work out the maximum section end address. */
if (overlay_max == NULL)
overlay_max = size;
else
overlay_max = exp_binop (MAX_K, overlay_max, size);
}
 
/* Finish a section in an overlay. There isn't any special to do
here. */
 
void
lang_leave_overlay_section (fill_type *fill,
lang_output_section_phdr_list *phdrs)
{
const char *name;
char *clean, *s2;
const char *s1;
char *buf;
 
name = current_section->name;
 
/* For now, assume that DEFAULT_MEMORY_REGION is the run-time memory
region and that no load-time region has been specified. It doesn't
really matter what we say here, since lang_leave_overlay will
override it. */
lang_leave_output_section_statement (fill, DEFAULT_MEMORY_REGION, phdrs, 0);
 
/* Define the magic symbols. */
 
clean = (char *) xmalloc (strlen (name) + 1);
s2 = clean;
for (s1 = name; *s1 != '\0'; s1++)
if (ISALNUM (*s1) || *s1 == '_')
*s2++ = *s1;
*s2 = '\0';
 
buf = (char *) xmalloc (strlen (clean) + sizeof "__load_start_");
sprintf (buf, "__load_start_%s", clean);
lang_add_assignment (exp_provide (buf,
exp_nameop (LOADADDR, name),
FALSE));
 
buf = (char *) xmalloc (strlen (clean) + sizeof "__load_stop_");
sprintf (buf, "__load_stop_%s", clean);
lang_add_assignment (exp_provide (buf,
exp_binop ('+',
exp_nameop (LOADADDR, name),
exp_nameop (SIZEOF, name)),
FALSE));
 
free (clean);
}
 
/* Finish an overlay. If there are any overlay wide settings, this
looks through all the sections in the overlay and sets them. */
 
void
lang_leave_overlay (etree_type *lma_expr,
int nocrossrefs,
fill_type *fill,
const char *memspec,
lang_output_section_phdr_list *phdrs,
const char *lma_memspec)
{
lang_memory_region_type *region;
lang_memory_region_type *lma_region;
struct overlay_list *l;
lang_nocrossref_type *nocrossref;
 
lang_get_regions (&region, &lma_region,
memspec, lma_memspec,
lma_expr != NULL, FALSE);
 
nocrossref = NULL;
 
/* After setting the size of the last section, set '.' to end of the
overlay region. */
if (overlay_list != NULL)
{
overlay_list->os->update_dot = 1;
overlay_list->os->update_dot_tree
= exp_assign (".", exp_binop ('+', overlay_vma, overlay_max), FALSE);
}
 
l = overlay_list;
while (l != NULL)
{
struct overlay_list *next;
 
if (fill != NULL && l->os->fill == NULL)
l->os->fill = fill;
 
l->os->region = region;
l->os->lma_region = lma_region;
 
/* The first section has the load address specified in the
OVERLAY statement. The rest are worked out from that.
The base address is not needed (and should be null) if
an LMA region was specified. */
if (l->next == 0)
{
l->os->load_base = lma_expr;
l->os->sectype = normal_section;
}
if (phdrs != NULL && l->os->phdrs == NULL)
l->os->phdrs = phdrs;
 
if (nocrossrefs)
{
lang_nocrossref_type *nc;
 
nc = (lang_nocrossref_type *) xmalloc (sizeof *nc);
nc->name = l->os->name;
nc->next = nocrossref;
nocrossref = nc;
}
 
next = l->next;
free (l);
l = next;
}
 
if (nocrossref != NULL)
lang_add_nocrossref (nocrossref);
 
overlay_vma = NULL;
overlay_list = NULL;
overlay_max = NULL;
}
/* Version handling. This is only useful for ELF. */
 
/* If PREV is NULL, return first version pattern matching particular symbol.
If PREV is non-NULL, return first version pattern matching particular
symbol after PREV (previously returned by lang_vers_match). */
 
static struct bfd_elf_version_expr *
lang_vers_match (struct bfd_elf_version_expr_head *head,
struct bfd_elf_version_expr *prev,
const char *sym)
{
const char *c_sym;
const char *cxx_sym = sym;
const char *java_sym = sym;
struct bfd_elf_version_expr *expr = NULL;
enum demangling_styles curr_style;
 
curr_style = CURRENT_DEMANGLING_STYLE;
cplus_demangle_set_style (no_demangling);
c_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_NO_OPTS);
if (!c_sym)
c_sym = sym;
cplus_demangle_set_style (curr_style);
 
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
cxx_sym = bfd_demangle (link_info.output_bfd, sym,
DMGL_PARAMS | DMGL_ANSI);
if (!cxx_sym)
cxx_sym = sym;
}
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
java_sym = bfd_demangle (link_info.output_bfd, sym, DMGL_JAVA);
if (!java_sym)
java_sym = sym;
}
 
if (head->htab && (prev == NULL || prev->literal))
{
struct bfd_elf_version_expr e;
 
switch (prev ? prev->mask : 0)
{
case 0:
if (head->mask & BFD_ELF_VERSION_C_TYPE)
{
e.pattern = c_sym;
expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, c_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
else
expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_C_TYPE:
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
e.pattern = cxx_sym;
expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
else
expr = expr->next;
}
/* Fallthrough */
case BFD_ELF_VERSION_CXX_TYPE:
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
e.pattern = java_sym;
expr = (struct bfd_elf_version_expr *)
htab_find ((htab_t) head->htab, &e);
while (expr && strcmp (expr->pattern, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
else
expr = expr->next;
}
/* Fallthrough */
default:
break;
}
}
 
/* Finally, try the wildcards. */
if (prev == NULL || prev->literal)
expr = head->remaining;
else
expr = prev->next;
for (; expr; expr = expr->next)
{
const char *s;
 
if (!expr->pattern)
continue;
 
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
break;
 
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
s = java_sym;
else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
s = cxx_sym;
else
s = c_sym;
if (fnmatch (expr->pattern, s, 0) == 0)
break;
}
 
out_ret:
if (c_sym != sym)
free ((char *) c_sym);
if (cxx_sym != sym)
free ((char *) cxx_sym);
if (java_sym != sym)
free ((char *) java_sym);
return expr;
}
 
/* Return NULL if the PATTERN argument is a glob pattern, otherwise,
return a pointer to the symbol name with any backslash quotes removed. */
 
static const char *
realsymbol (const char *pattern)
{
const char *p;
bfd_boolean changed = FALSE, backslash = FALSE;
char *s, *symbol = (char *) xmalloc (strlen (pattern) + 1);
 
for (p = pattern, s = symbol; *p != '\0'; ++p)
{
/* It is a glob pattern only if there is no preceding
backslash. */
if (backslash)
{
/* Remove the preceding backslash. */
*(s - 1) = *p;
backslash = FALSE;
changed = TRUE;
}
else
{
if (*p == '?' || *p == '*' || *p == '[')
{
free (symbol);
return NULL;
}
 
*s++ = *p;
backslash = *p == '\\';
}
}
 
if (changed)
{
*s = '\0';
return symbol;
}
else
{
free (symbol);
return pattern;
}
}
 
/* This is called for each variable name or match expression. NEW_NAME is
the name of the symbol to match, or, if LITERAL_P is FALSE, a glob
pattern to be matched against symbol names. */
 
struct bfd_elf_version_expr *
lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
const char *new_name,
const char *lang,
bfd_boolean literal_p)
{
struct bfd_elf_version_expr *ret;
 
ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
ret->next = orig;
ret->symver = 0;
ret->script = 0;
ret->literal = TRUE;
ret->pattern = literal_p ? new_name : realsymbol (new_name);
if (ret->pattern == NULL)
{
ret->pattern = new_name;
ret->literal = FALSE;
}
 
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
else if (strcasecmp (lang, "C++") == 0)
ret->mask = BFD_ELF_VERSION_CXX_TYPE;
else if (strcasecmp (lang, "Java") == 0)
ret->mask = BFD_ELF_VERSION_JAVA_TYPE;
else
{
einfo (_("%X%P: unknown language `%s' in version information\n"),
lang);
ret->mask = BFD_ELF_VERSION_C_TYPE;
}
 
return ldemul_new_vers_pattern (ret);
}
 
/* This is called for each set of variable names and match
expressions. */
 
struct bfd_elf_version_tree *
lang_new_vers_node (struct bfd_elf_version_expr *globals,
struct bfd_elf_version_expr *locals)
{
struct bfd_elf_version_tree *ret;
 
ret = (struct bfd_elf_version_tree *) xcalloc (1, sizeof *ret);
ret->globals.list = globals;
ret->locals.list = locals;
ret->match = lang_vers_match;
ret->name_indx = (unsigned int) -1;
return ret;
}
 
/* This static variable keeps track of version indices. */
 
static int version_index;
 
static hashval_t
version_expr_head_hash (const void *p)
{
const struct bfd_elf_version_expr *e =
(const struct bfd_elf_version_expr *) p;
 
return htab_hash_string (e->pattern);
}
 
static int
version_expr_head_eq (const void *p1, const void *p2)
{
const struct bfd_elf_version_expr *e1 =
(const struct bfd_elf_version_expr *) p1;
const struct bfd_elf_version_expr *e2 =
(const struct bfd_elf_version_expr *) p2;
 
return strcmp (e1->pattern, e2->pattern) == 0;
}
 
static void
lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
{
size_t count = 0;
struct bfd_elf_version_expr *e, *next;
struct bfd_elf_version_expr **list_loc, **remaining_loc;
 
for (e = head->list; e; e = e->next)
{
if (e->literal)
count++;
head->mask |= e->mask;
}
 
if (count)
{
head->htab = htab_create (count * 2, version_expr_head_hash,
version_expr_head_eq, NULL);
list_loc = &head->list;
remaining_loc = &head->remaining;
for (e = head->list; e; e = next)
{
next = e->next;
if (!e->literal)
{
*remaining_loc = e;
remaining_loc = &e->next;
}
else
{
void **loc = htab_find_slot ((htab_t) head->htab, e, INSERT);
 
if (*loc)
{
struct bfd_elf_version_expr *e1, *last;
 
e1 = (struct bfd_elf_version_expr *) *loc;
last = NULL;
do
{
if (e1->mask == e->mask)
{
last = NULL;
break;
}
last = e1;
e1 = e1->next;
}
while (e1 && strcmp (e1->pattern, e->pattern) == 0);
 
if (last == NULL)
{
/* This is a duplicate. */
/* FIXME: Memory leak. Sometimes pattern is not
xmalloced alone, but in larger chunk of memory. */
/* free (e->pattern); */
free (e);
}
else
{
e->next = last->next;
last->next = e;
}
}
else
{
*loc = e;
*list_loc = e;
list_loc = &e->next;
}
}
}
*remaining_loc = NULL;
*list_loc = head->remaining;
}
else
head->remaining = head->list;
}
 
/* This is called when we know the name and dependencies of the
version. */
 
void
lang_register_vers_node (const char *name,
struct bfd_elf_version_tree *version,
struct bfd_elf_version_deps *deps)
{
struct bfd_elf_version_tree *t, **pp;
struct bfd_elf_version_expr *e1;
 
if (name == NULL)
name = "";
 
if (link_info.version_info != NULL
&& (name[0] == '\0' || link_info.version_info->name[0] == '\0'))
{
einfo (_("%X%P: anonymous version tag cannot be combined"
" with other version tags\n"));
free (version);
return;
}
 
/* Make sure this node has a unique name. */
for (t = link_info.version_info; t != NULL; t = t->next)
if (strcmp (t->name, name) == 0)
einfo (_("%X%P: duplicate version tag `%s'\n"), name);
 
lang_finalize_version_expr_head (&version->globals);
lang_finalize_version_expr_head (&version->locals);
 
/* Check the global and local match names, and make sure there
aren't any duplicates. */
 
for (e1 = version->globals.list; e1 != NULL; e1 = e1->next)
{
for (t = link_info.version_info; t != NULL; t = t->next)
{
struct bfd_elf_version_expr *e2;
 
if (t->locals.htab && e1->literal)
{
e2 = (struct bfd_elf_version_expr *)
htab_find ((htab_t) t->locals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"), e1->pattern);
e2 = e2->next;
}
}
else if (!e1->literal)
for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"), e1->pattern);
}
}
 
for (e1 = version->locals.list; e1 != NULL; e1 = e1->next)
{
for (t = link_info.version_info; t != NULL; t = t->next)
{
struct bfd_elf_version_expr *e2;
 
if (t->globals.htab && e1->literal)
{
e2 = (struct bfd_elf_version_expr *)
htab_find ((htab_t) t->globals.htab, e1);
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"),
e1->pattern);
e2 = e2->next;
}
}
else if (!e1->literal)
for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"), e1->pattern);
}
}
 
version->deps = deps;
version->name = name;
if (name[0] != '\0')
{
++version_index;
version->vernum = version_index;
}
else
version->vernum = 0;
 
for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next)
;
*pp = version;
}
 
/* This is called when we see a version dependency. */
 
struct bfd_elf_version_deps *
lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
{
struct bfd_elf_version_deps *ret;
struct bfd_elf_version_tree *t;
 
ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
ret->next = list;
 
for (t = link_info.version_info; t != NULL; t = t->next)
{
if (strcmp (t->name, name) == 0)
{
ret->version_needed = t;
return ret;
}
}
 
einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
 
ret->version_needed = NULL;
return ret;
}
 
static void
lang_do_version_exports_section (void)
{
struct bfd_elf_version_expr *greg = NULL, *lreg;
 
LANG_FOR_EACH_INPUT_STATEMENT (is)
{
asection *sec = bfd_get_section_by_name (is->the_bfd, ".exports");
char *contents, *p;
bfd_size_type len;
 
if (sec == NULL)
continue;
 
len = sec->size;
contents = (char *) xmalloc (len);
if (!bfd_get_section_contents (is->the_bfd, sec, contents, 0, len))
einfo (_("%X%P: unable to read .exports section contents\n"), sec);
 
p = contents;
while (p < contents + len)
{
greg = lang_new_vers_pattern (greg, p, NULL, FALSE);
p = strchr (p, '\0') + 1;
}
 
/* Do not free the contents, as we used them creating the regex. */
 
/* Do not include this section in the link. */
sec->flags |= SEC_EXCLUDE | SEC_KEEP;
}
 
lreg = lang_new_vers_pattern (NULL, "*", NULL, FALSE);
lang_register_vers_node (command_line.version_exports_section,
lang_new_vers_node (greg, lreg), NULL);
}
 
void
lang_add_unique (const char *name)
{
struct unique_sections *ent;
 
for (ent = unique_section_list; ent; ent = ent->next)
if (strcmp (ent->name, name) == 0)
return;
 
ent = (struct unique_sections *) xmalloc (sizeof *ent);
ent->name = xstrdup (name);
ent->next = unique_section_list;
unique_section_list = ent;
}
 
/* Append the list of dynamic symbols to the existing one. */
 
void
lang_append_dynamic_list (struct bfd_elf_version_expr *dynamic)
{
if (link_info.dynamic_list)
{
struct bfd_elf_version_expr *tail;
for (tail = dynamic; tail->next != NULL; tail = tail->next)
;
tail->next = link_info.dynamic_list->head.list;
link_info.dynamic_list->head.list = dynamic;
}
else
{
struct bfd_elf_dynamic_list *d;
 
d = (struct bfd_elf_dynamic_list *) xcalloc (1, sizeof *d);
d->head.list = dynamic;
d->match = lang_vers_match;
link_info.dynamic_list = d;
}
}
 
/* Append the list of C++ typeinfo dynamic symbols to the existing
one. */
 
void
lang_append_dynamic_list_cpp_typeinfo (void)
{
const char * symbols [] =
{
"typeinfo name for*",
"typeinfo for*"
};
struct bfd_elf_version_expr *dynamic = NULL;
unsigned int i;
 
for (i = 0; i < ARRAY_SIZE (symbols); i++)
dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
FALSE);
 
lang_append_dynamic_list (dynamic);
}
 
/* Append the list of C++ operator new and delete dynamic symbols to the
existing one. */
 
void
lang_append_dynamic_list_cpp_new (void)
{
const char * symbols [] =
{
"operator new*",
"operator delete*"
};
struct bfd_elf_version_expr *dynamic = NULL;
unsigned int i;
 
for (i = 0; i < ARRAY_SIZE (symbols); i++)
dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
FALSE);
 
lang_append_dynamic_list (dynamic);
}
 
/* Scan a space and/or comma separated string of features. */
 
void
lang_ld_feature (char *str)
{
char *p, *q;
 
p = str;
while (*p)
{
char sep;
while (*p == ',' || ISSPACE (*p))
++p;
if (!*p)
break;
q = p + 1;
while (*q && *q != ',' && !ISSPACE (*q))
++q;
sep = *q;
*q = 0;
if (strcasecmp (p, "SANE_EXPR") == 0)
config.sane_expr = TRUE;
else
einfo (_("%X%P: unknown feature `%s'\n"), p);
*q = sep;
p = q;
}
}
/contrib/toolchain/binutils/ld/ldlang.h
0,0 → 1,663
/* ldlang.h - linker command language support
Copyright 1991-2013 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDLANG_H
#define LDLANG_H
 
#define DEFAULT_MEMORY_REGION "*default*"
 
typedef enum
{
lang_input_file_is_l_enum,
lang_input_file_is_symbols_only_enum,
lang_input_file_is_marker_enum,
lang_input_file_is_fake_enum,
lang_input_file_is_search_file_enum,
lang_input_file_is_file_enum
} lang_input_file_enum_type;
 
struct _fill_type
{
size_t size;
unsigned char data[1];
};
 
typedef struct statement_list
{
union lang_statement_union * head;
union lang_statement_union ** tail;
} lang_statement_list_type;
 
typedef struct memory_region_name_struct
{
const char * name;
struct memory_region_name_struct * next;
} lang_memory_region_name;
 
typedef struct memory_region_struct
{
lang_memory_region_name name_list;
struct memory_region_struct *next;
bfd_vma origin;
bfd_size_type length;
bfd_vma current;
union lang_statement_union *last_os;
flagword flags;
flagword not_flags;
bfd_boolean had_full_message;
} lang_memory_region_type;
 
enum statement_enum
{
lang_output_section_statement_enum,
lang_assignment_statement_enum,
lang_input_statement_enum,
lang_address_statement_enum,
lang_wild_statement_enum,
lang_input_section_enum,
lang_object_symbols_statement_enum,
lang_fill_statement_enum,
lang_data_statement_enum,
lang_reloc_statement_enum,
lang_target_statement_enum,
lang_output_statement_enum,
lang_padding_statement_enum,
lang_group_statement_enum,
lang_insert_statement_enum,
lang_constructors_statement_enum
};
 
typedef struct lang_statement_header_struct
{
union lang_statement_union *next;
enum statement_enum type;
} lang_statement_header_type;
 
typedef struct
{
lang_statement_header_type header;
union etree_union *exp;
} lang_assignment_statement_type;
 
typedef struct lang_target_statement_struct
{
lang_statement_header_type header;
const char *target;
} lang_target_statement_type;
 
typedef struct lang_output_statement_struct
{
lang_statement_header_type header;
const char *name;
} lang_output_statement_type;
 
/* Section types specified in a linker script. */
 
enum section_type
{
normal_section,
overlay_section,
noload_section,
noalloc_section
};
 
/* This structure holds a list of program headers describing
segments in which this section should be placed. */
 
typedef struct lang_output_section_phdr_list
{
struct lang_output_section_phdr_list *next;
const char *name;
bfd_boolean used;
} lang_output_section_phdr_list;
 
typedef struct lang_output_section_statement_struct
{
lang_statement_header_type header;
lang_statement_list_type children;
struct lang_output_section_statement_struct *next;
struct lang_output_section_statement_struct *prev;
const char *name;
asection *bfd_section;
lang_memory_region_type *region;
lang_memory_region_type *lma_region;
fill_type *fill;
union etree_union *addr_tree;
union etree_union *load_base;
 
/* If non-null, an expression to evaluate after setting the section's
size. The expression is evaluated inside REGION (above) with '.'
set to the end of the section. Used in the last overlay section
to move '.' past all the overlaid sections. */
union etree_union *update_dot_tree;
 
lang_output_section_phdr_list *phdrs;
 
unsigned int block_value;
int subsection_alignment; /* Alignment of components. */
int section_alignment; /* Alignment of start of section. */
int constraint;
flagword flags;
enum section_type sectype;
unsigned int processed_vma : 1;
unsigned int processed_lma : 1;
unsigned int all_input_readonly : 1;
/* If this section should be ignored. */
unsigned int ignored : 1;
/* If this section should update "dot". Prevents section being ignored. */
unsigned int update_dot : 1;
/* If this section is after assignment to _end. */
unsigned int after_end : 1;
/* If this section uses the alignment of its input sections. */
unsigned int align_lma_with_input : 1;
} lang_output_section_statement_type;
 
typedef struct
{
lang_statement_header_type header;
} lang_common_statement_type;
 
typedef struct
{
lang_statement_header_type header;
} lang_object_symbols_statement_type;
 
typedef struct
{
lang_statement_header_type header;
fill_type *fill;
int size;
asection *output_section;
} lang_fill_statement_type;
 
typedef struct
{
lang_statement_header_type header;
unsigned int type;
union etree_union *exp;
bfd_vma value;
asection *output_section;
bfd_vma output_offset;
} lang_data_statement_type;
 
/* Generate a reloc in the output file. */
 
typedef struct
{
lang_statement_header_type header;
 
/* Reloc to generate. */
bfd_reloc_code_real_type reloc;
 
/* Reloc howto structure. */
reloc_howto_type *howto;
 
/* Section to generate reloc against.
Exactly one of section and name must be NULL. */
asection *section;
 
/* Name of symbol to generate reloc against.
Exactly one of section and name must be NULL. */
const char *name;
 
/* Expression for addend. */
union etree_union *addend_exp;
 
/* Resolved addend. */
bfd_vma addend_value;
 
/* Output section where reloc should be performed. */
asection *output_section;
 
/* Offset within output section. */
bfd_vma output_offset;
} lang_reloc_statement_type;
 
struct lang_input_statement_flags
{
/* 1 means this file was specified in a -l option. */
unsigned int maybe_archive : 1;
 
/* 1 means search a set of directories for this file. */
unsigned int search_dirs : 1;
 
/* 1 means this was found when processing a script in the sysroot. */
unsigned int sysrooted : 1;
 
/* 1 means this is base file of incremental load.
Do not load this file's text or data.
Also default text_start to after this file's bss. */
unsigned int just_syms : 1;
 
/* Whether to search for this entry as a dynamic archive. */
unsigned int dynamic : 1;
 
/* Set if a DT_NEEDED tag should be added not just for the dynamic library
explicitly given by this entry but also for any dynamic libraries in
this entry's needed list. */
unsigned int add_DT_NEEDED_for_dynamic : 1;
 
/* Set if this entry should cause a DT_NEEDED tag only when some
regular file references its symbols (ie. --as-needed is in effect). */
unsigned int add_DT_NEEDED_for_regular : 1;
 
/* Whether to include the entire contents of an archive. */
unsigned int whole_archive : 1;
 
/* Set when bfd opening is successful. */
unsigned int loaded : 1;
 
unsigned int real : 1;
 
/* Set if the file does not exist. */
unsigned int missing_file : 1;
 
#ifdef ENABLE_PLUGINS
/* Set if the file was claimed by a plugin. */
unsigned int claimed : 1;
 
/* Set if the file was claimed from an archive. */
unsigned int claim_archive : 1;
 
/* Set if reloading an --as-needed lib. */
unsigned int reload : 1;
#endif /* ENABLE_PLUGINS */
};
 
typedef struct lang_input_statement_struct
{
lang_statement_header_type header;
/* Name of this file. */
const char *filename;
/* Name to use for the symbol giving address of text start.
Usually the same as filename, but for a file spec'd with
-l this is the -l switch itself rather than the filename. */
const char *local_sym_name;
 
bfd *the_bfd;
 
struct flag_info *section_flag_list;
 
/* Point to the next file - whatever it is, wanders up and down
archives */
union lang_statement_union *next;
 
/* Point to the next file, but skips archive contents. */
union lang_statement_union *next_real_file;
 
const char *target;
 
struct lang_input_statement_flags flags;
} lang_input_statement_type;
 
typedef struct
{
lang_statement_header_type header;
asection *section;
} lang_input_section_type;
 
typedef struct lang_wild_statement_struct lang_wild_statement_type;
 
typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
asection *, struct flag_info *,
lang_input_statement_type *, void *);
 
typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
lang_input_statement_type *,
callback_t callback,
void *data);
 
typedef bfd_boolean (*lang_match_sec_type_func) (bfd *, const asection *,
bfd *, const asection *);
 
/* Binary search tree structure to efficiently sort sections by
name. */
typedef struct lang_section_bst
{
asection *section;
struct lang_section_bst *left;
struct lang_section_bst *right;
} lang_section_bst_type;
 
struct lang_wild_statement_struct
{
lang_statement_header_type header;
const char *filename;
bfd_boolean filenames_sorted;
struct wildcard_list *section_list;
bfd_boolean keep_sections;
lang_statement_list_type children;
 
walk_wild_section_handler_t walk_wild_section_handler;
struct wildcard_list *handler_data[4];
lang_section_bst_type *tree;
struct flag_info *section_flag_list;
};
 
typedef struct lang_address_statement_struct
{
lang_statement_header_type header;
const char *section_name;
union etree_union *address;
const segment_type *segment;
} lang_address_statement_type;
 
typedef struct
{
lang_statement_header_type header;
bfd_vma output_offset;
bfd_size_type size;
asection *output_section;
fill_type *fill;
} lang_padding_statement_type;
 
/* A group statement collects a set of libraries together. The
libraries are searched multiple times, until no new undefined
symbols are found. The effect is to search a group of libraries as
though they were a single library. */
 
typedef struct
{
lang_statement_header_type header;
lang_statement_list_type children;
} lang_group_statement_type;
 
typedef struct
{
lang_statement_header_type header;
const char *where;
bfd_boolean is_before;
} lang_insert_statement_type;
 
typedef union lang_statement_union
{
lang_statement_header_type header;
lang_wild_statement_type wild_statement;
lang_data_statement_type data_statement;
lang_reloc_statement_type reloc_statement;
lang_address_statement_type address_statement;
lang_output_section_statement_type output_section_statement;
lang_assignment_statement_type assignment_statement;
lang_input_statement_type input_statement;
lang_target_statement_type target_statement;
lang_output_statement_type output_statement;
lang_input_section_type input_section;
lang_common_statement_type common_statement;
lang_object_symbols_statement_type object_symbols_statement;
lang_fill_statement_type fill_statement;
lang_padding_statement_type padding_statement;
lang_group_statement_type group_statement;
lang_insert_statement_type insert_statement;
} lang_statement_union_type;
 
/* This structure holds information about a program header, from the
PHDRS command in the linker script. */
 
struct lang_phdr
{
struct lang_phdr *next;
const char *name;
unsigned long type;
bfd_boolean filehdr;
bfd_boolean phdrs;
etree_type *at;
etree_type *flags;
};
 
/* This structure is used to hold a list of sections which may not
cross reference each other. */
 
typedef struct lang_nocrossref
{
struct lang_nocrossref *next;
const char *name;
} lang_nocrossref_type;
 
/* The list of nocrossref lists. */
 
struct lang_nocrossrefs
{
struct lang_nocrossrefs *next;
lang_nocrossref_type *list;
};
 
/* This structure is used to hold a list of input section names which
will not match an output section in the linker script. */
 
struct unique_sections
{
struct unique_sections *next;
const char *name;
};
 
/* This structure records symbols for which we need to keep track of
definedness for use in the DEFINED () test. */
 
struct lang_definedness_hash_entry
{
struct bfd_hash_entry root;
int iteration;
};
 
/* Used by place_orphan to keep track of orphan sections and statements. */
 
struct orphan_save
{
const char *name;
flagword flags;
lang_output_section_statement_type *os;
asection **section;
lang_statement_union_type **stmt;
lang_output_section_statement_type **os_tail;
};
 
extern struct lang_phdr *lang_phdr_list;
extern struct lang_nocrossrefs *nocrossref_list;
extern const char *output_target;
extern lang_output_section_statement_type *abs_output_section;
extern lang_statement_list_type lang_output_section_statement;
extern struct lang_input_statement_flags input_flags;
extern bfd_boolean lang_has_input_file;
extern etree_type *base;
extern lang_statement_list_type *stat_ptr;
extern bfd_boolean delete_output_file_on_failure;
 
extern struct bfd_sym_chain entry_symbol;
extern const char *entry_section;
extern bfd_boolean entry_from_cmdline;
extern lang_statement_list_type file_chain;
extern lang_statement_list_type input_file_chain;
 
extern int lang_statement_iteration;
 
extern void lang_init
(void);
extern void lang_finish
(void);
extern lang_memory_region_type * lang_memory_region_lookup
(const char * const, bfd_boolean);
extern void lang_memory_region_alias
(const char *, const char *);
extern void lang_map
(void);
extern void lang_set_flags
(lang_memory_region_type *, const char *, int);
extern void lang_add_output
(const char *, int from_script);
extern lang_output_section_statement_type *lang_enter_output_section_statement
(const char *, etree_type *, enum section_type, etree_type *, etree_type *,
etree_type *, int, int);
extern void lang_final
(void);
extern void lang_relax_sections
(bfd_boolean);
extern void lang_process
(void);
extern void lang_section_start
(const char *, union etree_union *, const segment_type *);
extern void lang_add_entry
(const char *, bfd_boolean);
extern void lang_default_entry
(const char *);
extern void lang_add_target
(const char *);
extern void lang_add_wild
(struct wildcard_spec *, struct wildcard_list *, bfd_boolean);
extern void lang_add_map
(const char *);
extern void lang_add_fill
(fill_type *);
extern lang_assignment_statement_type *lang_add_assignment
(union etree_union *);
extern void lang_add_attribute
(enum statement_enum);
extern void lang_startup
(const char *);
extern void lang_float
(bfd_boolean);
extern void lang_leave_output_section_statement
(fill_type *, const char *, lang_output_section_phdr_list *,
const char *);
extern void lang_statement_append
(lang_statement_list_type *, lang_statement_union_type *,
lang_statement_union_type **);
extern void lang_for_each_input_file
(void (*dothis) (lang_input_statement_type *));
extern void lang_for_each_file
(void (*dothis) (lang_input_statement_type *));
extern void lang_reset_memory_regions
(void);
extern void lang_do_assignments
(lang_phase_type);
extern asection *section_for_dot
(void);
 
#define LANG_FOR_EACH_INPUT_STATEMENT(statement) \
lang_input_statement_type *statement; \
for (statement = (lang_input_statement_type *) file_chain.head; \
statement != (lang_input_statement_type *) NULL; \
statement = (lang_input_statement_type *) statement->next) \
 
#define lang_output_section_find(NAME) \
lang_output_section_statement_lookup (NAME, 0, FALSE)
 
extern void lang_process
(void);
extern void ldlang_add_file
(lang_input_statement_type *);
extern lang_output_section_statement_type *lang_output_section_find_by_flags
(const asection *, lang_output_section_statement_type **,
lang_match_sec_type_func);
extern lang_output_section_statement_type *lang_insert_orphan
(asection *, const char *, int, lang_output_section_statement_type *,
struct orphan_save *, etree_type *, lang_statement_list_type *);
extern lang_input_statement_type *lang_add_input_file
(const char *, lang_input_file_enum_type, const char *);
extern void lang_add_keepsyms_file
(const char *);
extern lang_output_section_statement_type *lang_output_section_statement_lookup
(const char *, int, bfd_boolean);
extern lang_output_section_statement_type *next_matching_output_section_statement
(lang_output_section_statement_type *, int);
extern void ldlang_add_undef
(const char *const, bfd_boolean);
extern void lang_add_output_format
(const char *, const char *, const char *, int);
extern void lang_list_init
(lang_statement_list_type *);
extern void push_stat_ptr
(lang_statement_list_type *);
extern void pop_stat_ptr
(void);
extern void lang_add_data
(int type, union etree_union *);
extern void lang_add_reloc
(bfd_reloc_code_real_type, reloc_howto_type *, asection *, const char *,
union etree_union *);
extern void lang_for_each_statement
(void (*) (lang_statement_union_type *));
extern void lang_for_each_statement_worker
(void (*) (lang_statement_union_type *), lang_statement_union_type *);
extern void *stat_alloc
(size_t);
extern void strip_excluded_output_sections
(void);
extern void dprint_statement
(lang_statement_union_type *, int);
extern void lang_size_sections
(bfd_boolean *, bfd_boolean);
extern void one_lang_size_sections_pass
(bfd_boolean *, bfd_boolean);
extern void lang_add_insert
(const char *, int);
extern void lang_enter_group
(void);
extern void lang_leave_group
(void);
extern void lang_add_section
(lang_statement_list_type *, asection *,
struct flag_info *, lang_output_section_statement_type *);
extern void lang_new_phdr
(const char *, etree_type *, bfd_boolean, bfd_boolean, etree_type *,
etree_type *);
extern void lang_add_nocrossref
(lang_nocrossref_type *);
extern void lang_enter_overlay
(etree_type *, etree_type *);
extern void lang_enter_overlay_section
(const char *);
extern void lang_leave_overlay_section
(fill_type *, lang_output_section_phdr_list *);
extern void lang_leave_overlay
(etree_type *, int, fill_type *, const char *,
lang_output_section_phdr_list *, const char *);
 
extern struct bfd_elf_version_expr *lang_new_vers_pattern
(struct bfd_elf_version_expr *, const char *, const char *, bfd_boolean);
extern struct bfd_elf_version_tree *lang_new_vers_node
(struct bfd_elf_version_expr *, struct bfd_elf_version_expr *);
extern struct bfd_elf_version_deps *lang_add_vers_depend
(struct bfd_elf_version_deps *, const char *);
extern void lang_register_vers_node
(const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
extern void lang_append_dynamic_list_cpp_typeinfo (void);
extern void lang_append_dynamic_list_cpp_new (void);
extern void lang_add_unique
(const char *);
extern const char *lang_get_output_target
(void);
extern void lang_track_definedness (const char *);
extern int lang_symbol_definition_iteration (const char *);
extern void lang_update_definedness
(const char *, struct bfd_link_hash_entry *);
 
extern void add_excluded_libs (const char *);
extern bfd_boolean load_symbols
(lang_input_statement_type *, lang_statement_list_type *);
 
extern bfd_boolean
ldlang_override_segment_assignment
(struct bfd_link_info *, bfd *, asection *, asection *, bfd_boolean);
 
extern void
lang_ld_feature (char *);
 
#endif
/contrib/toolchain/binutils/ld/ldlex-wrapper.c
0,0 → 1,26
/* Copyright 2012 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
/* The flex output (ldlex.c) includes stdio.h before any of the C code
in ldlex.l. Make sure we include sysdep.h first, so that config.h
can select the correct value of things like _FILE_OFFSET_BITS and
_LARGE_FILES. */
 
#include "sysdep.h"
#include "ldlex.c"
/contrib/toolchain/binutils/ld/ldlex.c
0,0 → 1,4348
 
#line 3 "ldlex.c"
 
#define YY_INT_ALIGNED short int
 
/* A lexical scanner generated by flex */
 
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
 
/* First, we deal with platform-specific or compiler-specific issues. */
 
/* begin standard C headers. */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
 
/* end standard C headers. */
 
/* flex integer type definitions */
 
#ifndef FLEXINT_H
#define FLEXINT_H
 
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
 
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
* if you want the limit (max/min) macros for int types.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
 
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
typedef int16_t flex_int16_t;
typedef uint16_t flex_uint16_t;
typedef int32_t flex_int32_t;
typedef uint32_t flex_uint32_t;
typedef uint64_t flex_uint64_t;
#else
typedef signed char flex_int8_t;
typedef short int flex_int16_t;
typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
#endif /* ! C99 */
 
/* Limits of integral types. */
#ifndef INT8_MIN
#define INT8_MIN (-128)
#endif
#ifndef INT16_MIN
#define INT16_MIN (-32767-1)
#endif
#ifndef INT32_MIN
#define INT32_MIN (-2147483647-1)
#endif
#ifndef INT8_MAX
#define INT8_MAX (127)
#endif
#ifndef INT16_MAX
#define INT16_MAX (32767)
#endif
#ifndef INT32_MAX
#define INT32_MAX (2147483647)
#endif
#ifndef UINT8_MAX
#define UINT8_MAX (255U)
#endif
#ifndef UINT16_MAX
#define UINT16_MAX (65535U)
#endif
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
 
#endif /* ! FLEXINT_H */
 
#ifdef __cplusplus
 
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
 
#else /* ! __cplusplus */
 
/* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)
 
#define YY_USE_CONST
 
#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
 
#ifdef YY_USE_CONST
#define yyconst const
#else
#define yyconst
#endif
 
/* Returned upon end-of-file. */
#define YY_NULL 0
 
/* Promotes a possibly negative, possibly signed char to an unsigned
* integer for use as an array index. If the signed char is negative,
* we want to instead treat it as an 8-bit unsigned char, hence the
* double cast.
*/
#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
 
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
*/
#define BEGIN (yy_start) = 1 + 2 *
 
/* Translate the current start state into a value that can be later handed
* to BEGIN to return to the state. The YYSTATE alias is for lex
* compatibility.
*/
#define YY_START (((yy_start) - 1) / 2)
#define YYSTATE YY_START
 
/* Action number for EOF rule of a given start state. */
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
 
/* Special action meaning "start processing a new file". */
#define YY_NEW_FILE yyrestart(yyin )
 
#define YY_END_OF_BUFFER_CHAR 0
 
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
#define YY_BUF_SIZE 16384
#endif
 
/* The state buf must be large enough to hold one state per character in the main buffer.
*/
#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
 
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
#endif
 
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
typedef size_t yy_size_t;
#endif
 
extern yy_size_t yyleng;
 
extern FILE *yyin, *yyout;
 
#define EOB_ACT_CONTINUE_SCAN 0
#define EOB_ACT_END_OF_FILE 1
#define EOB_ACT_LAST_MATCH 2
 
#define YY_LESS_LINENO(n)
 
/* Return all but the first "n" matched characters back to the input stream. */
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
int yyless_macro_arg = (n); \
YY_LESS_LINENO(yyless_macro_arg);\
*yy_cp = (yy_hold_char); \
YY_RESTORE_YY_MORE_OFFSET \
(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
} \
while ( 0 )
 
#define unput(c) yyunput( c, (yytext_ptr) )
 
#ifndef YY_STRUCT_YY_BUFFER_STATE
#define YY_STRUCT_YY_BUFFER_STATE
struct yy_buffer_state
{
FILE *yy_input_file;
 
char *yy_ch_buf; /* input buffer */
char *yy_buf_pos; /* current position in input buffer */
 
/* Size of input buffer in bytes, not including room for EOB
* characters.
*/
yy_size_t yy_buf_size;
 
/* Number of characters read into yy_ch_buf, not including EOB
* characters.
*/
yy_size_t yy_n_chars;
 
/* Whether we "own" the buffer - i.e., we know we created it,
* and can realloc() it to grow it, and should free() it to
* delete it.
*/
int yy_is_our_buffer;
 
/* Whether this is an "interactive" input source; if so, and
* if we're using stdio for input, then we want to use getc()
* instead of fread(), to make sure we stop fetching input after
* each newline.
*/
int yy_is_interactive;
 
/* Whether we're considered to be at the beginning of a line.
* If so, '^' rules will be active on the next match, otherwise
* not.
*/
int yy_at_bol;
 
int yy_bs_lineno; /**< The line count. */
int yy_bs_column; /**< The column count. */
 
/* Whether to try to fill the input buffer when we reach the
* end of it.
*/
int yy_fill_buffer;
 
int yy_buffer_status;
 
#define YY_BUFFER_NEW 0
#define YY_BUFFER_NORMAL 1
/* When an EOF's been seen but there's still some text to process
* then we mark the buffer as YY_EOF_PENDING, to indicate that we
* shouldn't try reading from the input source any more. We might
* still have a bunch of tokens to match, though, because of
* possible backing-up.
*
* When we actually see the EOF, we change the status to "new"
* (via yyrestart()), so that the user can continue scanning by
* just pointing yyin at a new input file.
*/
#define YY_BUFFER_EOF_PENDING 2
 
};
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
 
/* Stack of input buffers. */
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
 
/* We provide macros for accessing buffer states in case in the
* future we want to put the buffer states in a more general
* "scanner state".
*
* Returns the top of the stack, or NULL.
*/
#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
? (yy_buffer_stack)[(yy_buffer_stack_top)] \
: NULL)
 
/* Same as previous macro, but useful when we know that the buffer stack is not
* NULL or when we need an lvalue. For internal use only.
*/
#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
 
/* yy_hold_char holds the character lost when yytext is formed. */
static char yy_hold_char;
static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
yy_size_t yyleng;
 
/* Points to current character in buffer. */
static char *yy_c_buf_p = (char *) 0;
static int yy_init = 0; /* whether we need to initialize */
static int yy_start = 0; /* start state number */
 
/* Flag which is used to allow yywrap()'s to do buffer switches
* instead of setting up a fresh yyin. A bit of a hack ...
*/
static int yy_did_buffer_switch_on_eof;
 
void yyrestart (FILE *input_file );
void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
void yy_delete_buffer (YY_BUFFER_STATE b );
void yy_flush_buffer (YY_BUFFER_STATE b );
void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
void yypop_buffer_state (void );
 
static void yyensure_buffer_stack (void );
static void yy_load_buffer_state (void );
static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
 
#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
 
YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
 
void *yyalloc (yy_size_t );
void *yyrealloc (void *,yy_size_t );
void yyfree (void * );
 
#define yy_new_buffer yy_create_buffer
 
#define yy_set_interactive(is_interactive) \
{ \
if ( ! YY_CURRENT_BUFFER ){ \
yyensure_buffer_stack (); \
YY_CURRENT_BUFFER_LVALUE = \
yy_create_buffer(yyin,YY_BUF_SIZE ); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
}
 
#define yy_set_bol(at_bol) \
{ \
if ( ! YY_CURRENT_BUFFER ){\
yyensure_buffer_stack (); \
YY_CURRENT_BUFFER_LVALUE = \
yy_create_buffer(yyin,YY_BUF_SIZE ); \
} \
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
}
 
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
 
/* Begin user sect3 */
 
typedef unsigned char YY_CHAR;
 
FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
 
typedef int yy_state_type;
 
extern int yylineno;
 
int yylineno = 1;
 
extern char *yytext;
#define yytext_ptr yytext
 
static yy_state_type yy_get_previous_state (void );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
static int yy_get_next_buffer (void );
static void yy_fatal_error (yyconst char msg[] );
 
/* Done after the current pattern has been matched and before the
* corresponding action - sets up yytext.
*/
#define YY_DO_BEFORE_ACTION \
(yytext_ptr) = yy_bp; \
yyleng = (yy_size_t) (yy_cp - yy_bp); \
(yy_hold_char) = *yy_cp; \
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
 
#define YY_NUM_RULES 197
#define YY_END_OF_BUFFER 198
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
{
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
static yyconst flex_int16_t yy_accept[1751] =
{ 0,
0, 0, 177, 177, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 198, 197,
195, 180, 179, 32, 195, 177, 38, 29, 44, 43,
34, 35, 28, 36, 177, 37, 8, 8, 45, 46,
39, 40, 27, 33, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 10, 9, 177, 119, 117, 177,
42, 30, 41, 31, 196, 180, 32, 196, 175, 38,
29, 44, 43, 34, 35, 28, 36, 175, 37, 8,
8, 45, 46, 39, 40, 27, 33, 175, 175, 175,
 
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 10, 9, 175, 175, 42, 30, 41,
31, 173, 36, 173, 37, 8, 8, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 119, 117,
173, 31, 4, 3, 2, 4, 5, 134, 32, 133,
172, 34, 35, 28, 36, 172, 37, 8, 8, 45,
46, 40, 33, 172, 172, 172, 172, 172, 172, 172,
172, 172, 172, 172, 172, 10, 9, 172, 172, 172,
172, 172, 172, 172, 172, 172, 172, 172, 31, 194,
 
192, 193, 195, 187, 186, 181, 188, 189, 185, 185,
185, 185, 190, 191, 180, 177, 15, 0, 178, 8,
26, 24, 22, 20, 21, 1, 23, 8, 8, 177,
18, 17, 14, 16, 19, 177, 177, 177, 177, 177,
124, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
25, 13, 15, 175, 6, 22, 20, 21, 0, 1,
 
23, 8, 0, 7, 7, 8, 7, 14, 175, 7,
7, 7, 175, 175, 124, 7, 175, 175, 7, 175,
175, 175, 7, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
175, 7, 175, 173, 8, 0, 23, 8, 0, 173,
173, 173, 173, 173, 124, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
 
173, 173, 173, 173, 173, 4, 4, 133, 133, 172,
6, 135, 22, 136, 172, 7, 7, 7, 172, 172,
172, 7, 172, 7, 7, 172, 172, 172, 172, 172,
172, 172, 172, 7, 172, 172, 172, 7, 172, 7,
7, 172, 172, 172, 172, 172, 172, 172, 172, 194,
193, 186, 185, 0, 185, 185, 185, 11, 12, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 93, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 72, 177, 177, 177, 177, 177,
 
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 120, 118, 177, 8, 176, 8, 175, 7,
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
62, 63, 175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 8, 174, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 93, 173, 173, 173, 173, 173, 173, 173, 173,
 
173, 173, 173, 72, 62, 173, 63, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 120, 118, 173, 4, 8, 172, 172,
172, 172, 172, 137, 172, 172, 172, 172, 172, 172,
172, 172, 172, 172, 172, 172, 172, 172, 172, 154,
172, 172, 172, 172, 172, 172, 172, 172, 172, 172,
185, 185, 185, 177, 59, 177, 177, 177, 177, 177,
53, 177, 100, 177, 111, 177, 177, 177, 177, 177,
177, 177, 89, 177, 177, 177, 177, 177, 112, 177,
 
177, 177, 130, 177, 177, 177, 98, 177, 68, 177,
177, 177, 177, 177, 177, 177, 177, 177, 96, 177,
177, 177, 177, 177, 177, 106, 177, 177, 177, 177,
177, 177, 177, 177, 177, 175, 59, 175, 175, 175,
53, 175, 175, 111, 175, 175, 175, 175, 175, 175,
175, 112, 175, 130, 175, 175, 175, 68, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175, 175, 175,
173, 59, 173, 173, 173, 173, 173, 53, 173, 100,
173, 111, 173, 173, 173, 173, 173, 173, 173, 89,
173, 173, 173, 173, 173, 112, 173, 173, 173, 130,
 
173, 173, 173, 173, 98, 173, 68, 173, 173, 173,
173, 173, 173, 173, 173, 173, 96, 173, 173, 173,
173, 173, 173, 106, 173, 173, 173, 173, 173, 173,
173, 173, 173, 172, 172, 172, 141, 149, 140, 172,
172, 151, 144, 147, 172, 172, 152, 172, 172, 172,
172, 172, 158, 166, 157, 172, 172, 169, 161, 164,
172, 172, 170, 172, 172, 185, 185, 185, 177, 87,
55, 177, 177, 177, 52, 177, 177, 177, 177, 110,
66, 177, 177, 95, 177, 78, 177, 177, 177, 77,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
 
177, 177, 123, 177, 177, 177, 177, 177, 99, 177,
177, 177, 97, 177, 177, 177, 177, 177, 177, 177,
175, 55, 175, 175, 52, 175, 175, 175, 110, 175,
78, 175, 175, 175, 175, 175, 175, 175, 175, 175,
175, 175, 175, 175, 175, 175, 175, 175, 175, 173,
87, 55, 173, 173, 173, 52, 173, 173, 173, 173,
110, 66, 173, 173, 95, 173, 78, 173, 173, 173,
77, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 123, 173, 173, 173, 173, 173,
99, 173, 173, 173, 97, 173, 173, 173, 173, 173,
 
173, 173, 172, 142, 139, 172, 172, 151, 151, 146,
172, 150, 172, 172, 159, 156, 172, 172, 169, 169,
163, 172, 168, 172, 185, 185, 183, 177, 177, 177,
65, 177, 88, 177, 177, 177, 177, 177, 177, 67,
177, 127, 177, 177, 177, 86, 177, 54, 177, 47,
177, 177, 109, 177, 50, 76, 177, 177, 177, 177,
177, 177, 73, 177, 177, 177, 177, 177, 94, 74,
177, 177, 177, 175, 175, 175, 65, 175, 175, 175,
175, 175, 127, 175, 175, 54, 175, 175, 175, 109,
175, 50, 175, 175, 175, 73, 175, 175, 175, 175,
 
173, 173, 173, 65, 173, 88, 173, 173, 173, 173,
173, 173, 67, 173, 127, 173, 173, 173, 86, 173,
54, 173, 173, 47, 173, 173, 109, 173, 50, 76,
173, 173, 173, 173, 173, 173, 73, 173, 173, 173,
173, 173, 94, 74, 173, 173, 173, 172, 172, 67,
148, 145, 172, 172, 172, 167, 165, 162, 172, 184,
182, 177, 61, 177, 177, 177, 177, 177, 177, 80,
177, 177, 122, 177, 177, 177, 177, 177, 101, 177,
177, 103, 128, 177, 177, 177, 177, 177, 177, 177,
116, 90, 177, 51, 177, 177, 175, 61, 175, 175,
 
175, 175, 80, 175, 122, 175, 175, 175, 175, 175,
113, 128, 175, 175, 116, 175, 175, 175, 173, 61,
173, 173, 173, 173, 173, 173, 80, 173, 173, 122,
173, 173, 173, 173, 173, 173, 101, 173, 173, 103,
128, 173, 173, 173, 173, 173, 173, 173, 116, 90,
173, 51, 173, 173, 172, 172, 172, 172, 172, 172,
153, 177, 177, 132, 177, 177, 177, 177, 177, 177,
177, 177, 60, 177, 177, 177, 177, 177, 177, 177,
85, 177, 177, 177, 177, 126, 171, 177, 153, 175,
175, 132, 175, 175, 175, 60, 64, 175, 175, 175,
 
175, 175, 126, 171, 175, 153, 173, 173, 132, 173,
173, 173, 173, 173, 173, 173, 173, 60, 64, 173,
173, 173, 173, 173, 173, 173, 85, 173, 173, 173,
173, 126, 171, 173, 153, 138, 143, 171, 155, 160,
177, 79, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 108, 177, 175, 79, 175, 175, 175, 175,
175, 175, 175, 175, 175, 173, 79, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 108, 173, 177,
 
177, 177, 177, 177, 177, 177, 177, 49, 177, 114,
115, 177, 177, 177, 177, 75, 177, 177, 177, 177,
177, 177, 175, 175, 175, 175, 175, 114, 115, 175,
175, 175, 175, 173, 173, 173, 173, 173, 173, 173,
173, 49, 173, 114, 115, 173, 173, 173, 173, 75,
173, 173, 173, 173, 173, 173, 177, 177, 177, 177,
177, 177, 177, 177, 102, 92, 177, 177, 177, 177,
177, 177, 177, 177, 177, 175, 175, 175, 175, 102,
175, 175, 175, 175, 173, 173, 173, 173, 173, 173,
173, 173, 102, 92, 173, 173, 173, 173, 173, 173,
 
173, 173, 173, 177, 82, 177, 177, 131, 177, 177,
177, 177, 177, 48, 177, 177, 177, 177, 104, 177,
175, 175, 131, 175, 175, 175, 175, 175, 173, 82,
173, 173, 131, 173, 173, 173, 173, 173, 48, 173,
173, 173, 173, 104, 173, 177, 177, 177, 177, 177,
177, 91, 177, 71, 177, 177, 177, 177, 175, 175,
175, 175, 71, 175, 175, 173, 173, 173, 173, 173,
173, 91, 173, 71, 173, 173, 173, 173, 177, 177,
177, 177, 177, 177, 177, 177, 129, 70, 177, 177,
69, 175, 175, 175, 175, 175, 129, 70, 69, 173,
 
173, 173, 173, 173, 173, 173, 173, 129, 70, 173,
173, 69, 177, 177, 177, 177, 177, 177, 177, 177,
177, 177, 175, 175, 175, 175, 175, 173, 173, 173,
173, 173, 173, 173, 173, 173, 173, 125, 177, 177,
58, 177, 177, 177, 177, 177, 177, 125, 175, 58,
175, 175, 125, 173, 173, 58, 173, 173, 173, 173,
173, 173, 177, 177, 177, 177, 177, 177, 105, 177,
175, 175, 175, 173, 173, 173, 173, 173, 173, 105,
173, 177, 56, 177, 177, 177, 177, 177, 56, 175,
175, 173, 56, 173, 173, 173, 173, 173, 177, 177,
 
177, 177, 121, 177, 175, 121, 173, 173, 173, 173,
121, 173, 177, 177, 177, 177, 177, 175, 173, 173,
173, 173, 173, 81, 177, 177, 177, 107, 175, 81,
173, 173, 173, 107, 57, 177, 177, 57, 57, 173,
173, 83, 177, 83, 173, 177, 173, 84, 84, 0
} ;
 
static yyconst flex_int32_t yy_ec[256] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 4, 5, 6, 7, 8, 9, 1, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
19, 19, 19, 19, 19, 19, 19, 21, 22, 23,
24, 25, 26, 1, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 1, 58, 59, 60, 61,
 
62, 63, 64, 65, 66, 16, 67, 68, 69, 70,
71, 72, 16, 73, 74, 75, 76, 16, 16, 77,
16, 78, 79, 80, 81, 82, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1
} ;
 
static yyconst flex_int32_t yy_meta[83] =
{ 0,
1, 1, 2, 3, 1, 1, 4, 1, 1, 1,
1, 3, 5, 6, 7, 8, 9, 10, 10, 10,
7, 1, 1, 6, 1, 3, 10, 10, 10, 10,
10, 10, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 7, 4, 7, 3, 8, 10, 10, 10,
10, 10, 10, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 1, 1,
1, 9
} ;
 
static yyconst flex_int16_t yy_base[1775] =
{ 0,
0, 0, 0, 0, 82, 0, 164, 0, 246, 327,
408, 0, 275, 277, 490, 572, 654, 736, 2703, 2704,
2704, 2700, 2704, 2677, 2695, 801, 2704, 264, 2704, 2704,
2675, 2674, 0, 2673, 0, 250, 581, 499, 0, 2704,
252, 2672, 260, 0, 259, 255, 254, 269, 263, 274,
2651, 272, 2654, 2662, 327, 289, 277, 315, 277, 2645,
2660, 330, 2663, 2658, 0, 0, 2629, 2625, 2613, 2619,
2704, 239, 2704, 0, 2704, 2682, 2659, 2677, 847, 2704,
351, 2704, 2704, 2657, 2656, 2704, 298, 0, 355, 893,
267, 2704, 2704, 300, 2655, 345, 2704, 953, 356, 359,
 
494, 503, 576, 2634, 2642, 2636, 2644, 347, 358, 489,
355, 2630, 516, 2704, 2704, 652, 2607, 2704, 482, 2704,
0, 1013, 499, 0, 530, 745, 757, 655, 572, 485,
534, 487, 567, 2628, 517, 2631, 2639, 599, 529, 578,
594, 599, 2622, 2637, 661, 2640, 2635, 2606, 2602, 2590,
2596, 0, 1059, 2704, 2704, 0, 2704, 2704, 2637, 2657,
1105, 2635, 2634, 2704, 2633, 0, 2632, 0, 538, 2704,
0, 2631, 2704, 1151, 608, 686, 609, 677, 653, 355,
2627, 2609, 2605, 504, 2607, 2704, 2704, 724, 611, 661,
702, 740, 545, 2592, 2576, 2572, 570, 2574, 0, 2644,
 
2704, 0, 2633, 2704, 0, 2704, 2704, 2704, 2623, 536,
663, 700, 2704, 2704, 2641, 0, 0, 2637, 2704, 730,
2704, 2704, 0, 0, 0, 0, 0, 768, 0, 0,
2617, 2704, 0, 2704, 2616, 2594, 2608, 2591, 2601, 567,
0, 2603, 2594, 2592, 2586, 646, 2600, 2584, 2597, 2597,
2581, 615, 2588, 2584, 2580, 2582, 2592, 2583, 807, 2589,
2562, 2578, 683, 2575, 2577, 2565, 813, 2576, 2578, 2566,
2580, 2580, 2568, 2581, 2574, 811, 2565, 2553, 2560, 2572,
2555, 2574, 2572, 2554, 2554, 2553, 2522, 2525, 2530, 2515,
2704, 2704, 2704, 0, 1211, 2704, 2704, 2704, 0, 2704,
 
2704, 693, 864, 0, 2704, 2704, 0, 2704, 763, 842,
929, 0, 2557, 728, 0, 962, 2551, 2549, 783, 989,
1018, 2558, 2559, 2546, 2556, 814, 2554, 2544, 365, 2533,
2542, 2531, 751, 2542, 2544, 2547, 2536, 2543, 2523, 2543,
2545, 1009, 2494, 0, 1263, 0, 0, 878, 0, 2526,
2540, 2523, 2533, 745, 0, 2535, 2526, 2524, 2518, 808,
2532, 2516, 2529, 2529, 2513, 781, 2520, 2516, 2512, 2514,
2524, 2515, 857, 2521, 2494, 2510, 902, 724, 2510, 2508,
2497, 908, 2508, 2510, 2498, 2512, 2512, 2500, 2513, 2506,
936, 2497, 2485, 2492, 2504, 2487, 2506, 2504, 2486, 2486,
 
2485, 2454, 2457, 2462, 2447, 0, 1315, 2521, 2704, 0,
1367, 0, 0, 0, 775, 948, 819, 0, 2488, 950,
951, 2487, 2491, 2474, 2475, 2473, 2490, 2477, 2485, 2486,
2484, 2485, 2464, 830, 2444, 862, 1021, 2443, 2447, 2432,
2433, 2431, 2446, 2434, 2441, 2442, 2440, 2441, 2422, 2495,
0, 0, 2475, 2474, 864, 848, 649, 2704, 2704, 2453,
2449, 2461, 2458, 2459, 2449, 2447, 2457, 2457, 2454, 2439,
2432, 2455, 2454, 2445, 2450, 2434, 2439, 2445, 2437, 2447,
2444, 2425, 2441, 0, 2432, 2428, 2433, 2420, 2435, 2423,
2432, 2430, 2432, 2428, 0, 2419, 2413, 2414, 2419, 2415,
 
2404, 2421, 2411, 2408, 2407, 2402, 2419, 2413, 2403, 2400,
2406, 2400, 2412, 2396, 2412, 2413, 2395, 2411, 2399, 2403,
2390, 2363, 0, 0, 2371, 0, 0, 984, 2391, 1054,
2398, 2399, 2389, 2398, 2398, 2381, 2374, 2397, 1066, 2394,
2384, 2374, 2390, 2381, 2377, 2370, 2374, 2382, 2384, 2393,
0, 0, 2366, 2367, 2369, 2358, 2375, 2363, 2358, 2366,
2373, 2374, 2375, 2330, 2338, 0, 0, 2358, 2354, 2366,
2363, 2364, 2354, 2352, 2362, 2362, 2359, 2344, 2337, 2360,
2359, 2350, 2355, 2339, 2344, 2350, 2342, 2352, 2349, 2330,
2346, 0, 2337, 2333, 2338, 2325, 2340, 2328, 2337, 2335,
 
2337, 2346, 2332, 0, 0, 2323, 0, 2317, 2318, 2323,
2319, 2308, 2325, 2315, 2312, 2311, 2306, 2323, 2317, 2307,
2304, 2310, 2304, 2316, 2300, 2316, 2317, 2299, 2315, 2303,
2307, 2294, 2267, 0, 0, 2275, 0, 0, 2295, 501,
2304, 2303, 2291, 0, 2301, 2292, 2284, 2299, 2297, 2296,
2288, 2279, 2280, 2283, 2251, 880, 2259, 2258, 2247, 0,
2256, 2248, 2241, 2254, 2252, 2251, 2244, 2236, 2237, 2239,
832, 833, 813, 2270, 0, 2263, 2266, 2261, 2273, 2259,
0, 2265, 0, 2255, 0, 2254, 2242, 2258, 2251, 2245,
2248, 2250, 0, 2247, 2261, 2249, 2259, 2242, 0, 2260,
 
2241, 2242, 0, 2254, 2238, 2256, 0, 2238, 0, 2240,
2239, 2252, 2221, 2242, 2229, 2237, 2229, 2238, 0, 2231,
2242, 2235, 2238, 2222, 2226, 2209, 2230, 2234, 2217, 2224,
2226, 2229, 2224, 2190, 2186, 2218, 0, 2215, 2210, 2222,
0, 2215, 2205, 0, 2193, 2209, 2202, 2200, 2204, 2214,
2197, 0, 2197, 0, 2196, 2214, 2211, 0, 2198, 2211,
2180, 2201, 2197, 2199, 2202, 2191, 2196, 2192, 2161, 2157,
2189, 0, 2182, 2185, 2180, 2192, 2178, 0, 2184, 0,
2166, 0, 2156, 2135, 2142, 2123, 2114, 2115, 2117, 0,
2111, 2116, 2095, 2096, 2074, 0, 2077, 2058, 2059, 0,
 
251, 297, 347, 468, 0, 515, 0, 576, 625, 679,
668, 693, 682, 694, 703, 716, 0, 740, 777, 820,
842, 835, 852, 838, 881, 888, 880, 890, 913, 918,
915, 893, 895, 930, 932, 957, 0, 0, 0, 957,
975, 1436, 0, 0, 960, 970, 0, 960, 980, 942,
946, 952, 0, 0, 0, 952, 968, 1517, 0, 0,
955, 963, 0, 961, 978, 1036, 1039, 1037, 1005, 0,
1024, 1015, 1031, 1035, 0, 1041, 1036, 1024, 1039, 0,
0, 1050, 1053, 0, 1045, 0, 1063, 1076, 1072, 1051,
1064, 1086, 1080, 1085, 1065, 1081, 1100, 1098, 1094, 1090,
 
1085, 1111, 0, 1109, 1100, 1107, 1101, 1103, 0, 1112,
1117, 1119, 0, 1100, 1113, 1121, 1104, 1110, 1076, 1090,
1107, 1115, 1109, 1127, 0, 1132, 1115, 1130, 0, 1132,
0, 1133, 1144, 1118, 1142, 1147, 1153, 1141, 1157, 1153,
1150, 1164, 1163, 1154, 1163, 1169, 1162, 1122, 1136, 1153,
0, 1161, 1157, 1173, 1174, 0, 1179, 1176, 1163, 1184,
0, 0, 1187, 1179, 0, 1163, 0, 1181, 1194, 1190,
1169, 1181, 1205, 1199, 1204, 1204, 1185, 1192, 1217, 1215,
1211, 1207, 1203, 1224, 0, 1222, 1213, 1220, 1214, 1216,
0, 1225, 1235, 1231, 0, 1212, 1225, 1233, 1216, 1223,
 
1189, 1203, 1220, 0, 1229, 1236, 1231, 0, 1598, 0,
1250, 0, 1257, 1209, 0, 1217, 1217, 1213, 0, 1679,
0, 1229, 0, 1238, 1278, 1282, 1276, 1252, 1269, 1255,
0, 1275, 0, 1266, 1260, 1251, 1278, 1280, 1280, 0,
1283, 0, 1282, 1268, 1270, 0, 1270, 0, 1287, 0,
1273, 1273, 0, 1288, 0, 1270, 1277, 1298, 1274, 1279,
1297, 1292, 1282, 1289, 1300, 1311, 1309, 1320, 0, 0,
1315, 1281, 1300, 1312, 1327, 1311, 0, 1331, 1322, 1332,
1334, 1334, 0, 1335, 1322, 0, 1338, 1334, 1325, 0,
1339, 0, 1321, 1348, 1334, 1324, 1345, 1355, 1314, 1333,
 
1345, 1360, 1344, 0, 1370, 0, 1361, 1355, 1346, 1374,
1377, 1377, 0, 1380, 0, 1379, 1365, 1367, 0, 1367,
0, 1384, 1380, 0, 1371, 1371, 0, 1386, 0, 1362,
1369, 1390, 1365, 1366, 1384, 1385, 1375, 1382, 1394, 1401,
1401, 1416, 0, 0, 1411, 1377, 1396, 1408, 1414, 0,
0, 0, 1410, 1382, 1392, 0, 0, 0, 1389, 1444,
1445, 1436, 0, 1433, 1438, 1424, 1442, 1431, 1440, 0,
1417, 1434, 0, 1419, 1446, 1431, 1435, 1436, 0, 1424,
1455, 0, 1426, 1457, 1455, 1441, 1431, 1455, 1433, 1451,
0, 0, 1453, 0, 1432, 1430, 1465, 0, 1462, 1467,
 
1453, 1467, 0, 1444, 0, 1471, 1459, 1466, 1461, 1449,
0, 1450, 1451, 1475, 0, 1470, 1449, 1447, 1482, 0,
1479, 1489, 1478, 1501, 1491, 1500, 0, 1477, 1494, 0,
1479, 1506, 1491, 1500, 1507, 1502, 0, 1490, 1521, 0,
1492, 1523, 1521, 1507, 1497, 1521, 1499, 1517, 0, 0,
1518, 0, 1497, 1495, 1530, 1532, 1532, 1502, 1504, 1504,
0, 1521, 1538, 0, 1523, 1542, 1532, 1540, 1535, 1546,
1547, 1533, 0, 1547, 1535, 1536, 1540, 1548, 1545, 1549,
0, 1540, 1555, 1578, 1556, 0, 0, 1526, 0, 1543,
1560, 0, 1552, 1560, 1564, 0, 0, 1563, 1551, 1567,
 
1566, 1583, 0, 0, 1553, 0, 1570, 1587, 0, 1573,
1597, 1587, 1595, 1589, 1600, 1601, 1587, 0, 0, 1601,
1589, 1590, 1594, 1602, 1599, 1603, 0, 1594, 1609, 1615,
1610, 0, 0, 1581, 0, 0, 0, 0, 0, 0,
1610, 0, 1604, 1610, 1616, 1613, 1610, 1610, 1606, 1622,
1624, 1616, 1629, 1615, 1625, 1626, 1618, 1617, 1637, 1628,
1627, 1641, 0, 1611, 1636, 0, 1640, 1637, 1627, 1642,
1645, 1640, 1630, 1655, 1634, 1661, 0, 1655, 1661, 1667,
1664, 1661, 1665, 1661, 1677, 1677, 1669, 1682, 1668, 1678,
1679, 1671, 1670, 1690, 1681, 1680, 1694, 0, 1664, 1666,
 
1680, 1694, 1686, 1689, 1687, 1690, 1695, 0, 1686, 0,
0, 1698, 1694, 1704, 1709, 0, 1710, 1708, 1704, 1705,
1702, 1681, 1686, 1704, 1707, 1711, 1702, 0, 0, 1718,
1722, 1720, 1690, 1695, 1709, 1723, 1715, 1718, 1716, 1722,
1727, 0, 1718, 0, 0, 1730, 1726, 1736, 1740, 0,
1741, 1739, 1735, 1736, 1733, 1712, 1739, 1730, 1747, 1731,
1747, 1739, 1741, 1740, 0, 0, 1755, 1753, 1739, 1741,
1755, 1754, 1742, 1758, 1728, 1756, 1746, 1762, 1753, 0,
1765, 1752, 1766, 1736, 1764, 1755, 1772, 1756, 1772, 1764,
1766, 1765, 0, 0, 1780, 1778, 1764, 1766, 1780, 1779,
 
1767, 1783, 1753, 1776, 0, 1771, 1761, 0, 1762, 1779,
1781, 1776, 1792, 0, 1778, 1781, 1786, 1770, 0, 1755,
1789, 1773, 0, 1791, 1801, 1787, 1790, 1762, 1796, 0,
1791, 1781, 0, 1782, 1799, 1801, 1796, 1812, 0, 1798,
1801, 1806, 1790, 0, 1775, 1807, 1793, 1824, 1825, 1813,
1797, 0, 1816, 0, 1812, 1819, 1817, 1786, 1819, 1835,
1806, 1824, 0, 1820, 1793, 1827, 1813, 1844, 1845, 1833,
1817, 0, 1836, 0, 1832, 1839, 1838, 1807, 1835, 1838,
1846, 1845, 1855, 1849, 1832, 1858, 0, 0, 1860, 1848,
0, 1846, 1856, 1855, 1865, 1865, 0, 0, 0, 1851,
 
1854, 1862, 1861, 1871, 1865, 1847, 1873, 0, 0, 1875,
1863, 0, 1862, 1858, 1875, 1881, 1874, 1875, 1887, 1877,
1876, 1882, 1872, 1884, 1890, 1883, 1884, 1877, 1873, 1890,
1896, 1889, 1890, 1902, 1892, 1891, 1897, 0, 1894, 1901,
0, 1891, 1895, 1899, 1911, 1893, 1899, 0, 1908, 0,
1898, 1916, 0, 1905, 1912, 0, 1902, 1906, 1910, 1922,
1904, 1910, 1924, 1913, 1913, 1926, 1918, 1924, 0, 1914,
1919, 1919, 1928, 1934, 1923, 1923, 1936, 1928, 1934, 0,
1924, 1928, 0, 1913, 1944, 1931, 1928, 1939, 0, 1918,
1931, 1936, 0, 1921, 1952, 1939, 1936, 1947, 1945, 1953,
 
1939, 1957, 0, 1941, 1957, 0, 1951, 1959, 1945, 1963,
0, 1947, 1949, 1955, 1961, 1970, 1947, 1959, 1955, 1961,
1967, 1976, 1953, 0, 1975, 1965, 1961, 0, 1978, 0,
1979, 1969, 1965, 0, 0, 1972, 1978, 0, 0, 1974,
1980, 0, 1975, 0, 1976, 1978, 1979, 0, 0, 2704,
2019, 2029, 2039, 2049, 2059, 2067, 2077, 2084, 2091, 2098,
2108, 2115, 2125, 2135, 2145, 2148, 2156, 2163, 2080, 2170,
2180, 2190, 2200, 2210
} ;
 
static yyconst flex_int16_t yy_def[1775] =
{ 0,
1751, 1751, 1750, 3, 1750, 5, 1750, 7, 1752, 1752,
1750, 11, 1753, 1753, 1754, 1754, 1755, 1755, 1750, 1750,
1750, 1750, 1750, 1756, 1757, 1756, 1750, 1750, 1750, 1750,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1750,
1750, 1756, 1750, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1750, 1750, 1750, 1756, 1750, 1750, 1750, 1757, 1758, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1758, 1758, 1750,
90, 1750, 1750, 1750, 1750, 1750, 1750, 1758, 98, 98,
 
98, 98, 98, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1750, 1750, 98, 1758, 1750, 1750, 1750,
1758, 1759, 1750, 1759, 1759, 1750, 1750, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1760, 1750, 1750, 1760, 1750, 1750, 1750, 1761,
1762, 1763, 1750, 1750, 1750, 1762, 1762, 90, 90, 1750,
1764, 1750, 1750, 1762, 174, 174, 174, 174, 174, 1762,
1762, 1762, 1762, 1762, 1762, 1750, 1750, 174, 174, 174,
174, 174, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1750,
 
1750, 1765, 1750, 1750, 1766, 1750, 1750, 1750, 1767, 1767,
1767, 1767, 1750, 1750, 1750, 1756, 1756, 1757, 1750, 26,
1750, 1750, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 26,
1750, 1750, 1756, 1750, 1750, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1750, 1750, 1750, 1758, 1758, 1750, 1750, 1750, 1768, 1750,
 
1750, 90, 90, 303, 1750, 1750, 1769, 1750, 98, 98,
98, 1758, 1758, 1758, 1758, 98, 1758, 1758, 1758, 98,
98, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 98, 1758, 1759, 1759, 1770, 1759, 1750, 1769, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1759, 1759, 1759, 1759, 1760, 1760, 1761, 1750, 1762,
1762, 1763, 1763, 1764, 174, 174, 174, 1762, 1762, 174,
174, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1762, 1762, 1762, 174, 1762, 174, 174, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1750,
1765, 1766, 1767, 1750, 1767, 1767, 1767, 1750, 1750, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
 
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1758, 1768, 1769, 1758, 98,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 98, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1759, 1770, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1760, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1767, 1767, 1767, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
 
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1762, 1771, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1772, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1767, 1767, 1767, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
 
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1759, 1762, 1762, 1762, 1762, 1762, 1773, 1771, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1774, 1772,
1762, 1762, 1762, 1762, 1767, 1767, 1767, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
 
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1762, 1762, 1762,
1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1762, 1767,
1767, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1758, 1758, 1758, 1758,
 
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1762, 1762, 1762, 1762, 1762, 1762,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
 
1758, 1758, 1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1762, 1762, 1762, 1762, 1762, 1762,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1756,
 
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1758, 1758, 1758, 1758, 1758,
1758, 1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1759, 1759, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1758, 1758,
1758, 1758, 1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1758, 1759,
 
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1756, 1756, 1758, 1758, 1758, 1758, 1758, 1759, 1759, 1759,
1759, 1759, 1759, 1759, 1759, 1759, 1759, 1756, 1756, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1758, 1758, 1758,
1758, 1758, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1759, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1756,
1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759, 1759, 1759,
1759, 1756, 1756, 1756, 1756, 1756, 1756, 1756, 1758, 1758,
1758, 1759, 1759, 1759, 1759, 1759, 1759, 1759, 1756, 1756,
 
1756, 1756, 1756, 1756, 1758, 1758, 1759, 1759, 1759, 1759,
1759, 1759, 1756, 1756, 1756, 1756, 1756, 1758, 1759, 1759,
1759, 1759, 1759, 1756, 1756, 1756, 1756, 1756, 1758, 1759,
1759, 1759, 1759, 1759, 1756, 1756, 1756, 1758, 1759, 1759,
1759, 1756, 1756, 1759, 1759, 1756, 1759, 1756, 1759, 0,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750
} ;
 
static yyconst flex_int16_t yy_nxt[2787] =
{ 0,
21, 22, 23, 24, 25, 21, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 35, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 35, 64, 35, 35,
35, 35, 65, 35, 66, 35, 35, 67, 35, 35,
35, 35, 35, 35, 35, 35, 35, 68, 35, 35,
69, 35, 35, 70, 35, 35, 35, 35, 71, 72,
73, 74, 75, 76, 23, 77, 78, 75, 79, 80,
81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
 
91, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 88, 107, 108,
109, 110, 111, 112, 88, 88, 113, 88, 88, 88,
88, 88, 88, 88, 114, 88, 115, 75, 88, 116,
103, 103, 103, 103, 103, 88, 88, 88, 88, 88,
88, 88, 88, 88, 88, 117, 88, 88, 88, 88,
118, 119, 120, 121, 75, 76, 23, 77, 78, 75,
122, 80, 81, 82, 83, 84, 85, 86, 123, 124,
125, 126, 127, 127, 92, 93, 94, 95, 96, 97,
128, 129, 130, 131, 132, 133, 134, 135, 136, 124,
 
137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
124, 147, 124, 124, 124, 124, 114, 124, 115, 75,
124, 148, 124, 124, 124, 124, 124, 124, 124, 124,
124, 149, 124, 124, 150, 124, 124, 151, 124, 124,
124, 124, 118, 119, 120, 152, 75, 75, 20, 75,
75, 75, 153, 75, 75, 75, 75, 75, 154, 75,
155, 226, 291, 126, 127, 127, 75, 75, 75, 157,
75, 75, 221, 227, 231, 232, 200, 201, 200, 201,
202, 973, 202, 234, 235, 242, 236, 222, 237, 243,
238, 203, 244, 203, 246, 248, 239, 247, 75, 249,
 
75, 75, 251, 240, 241, 245, 257, 266, 253, 258,
272, 254, 252, 250, 255, 264, 305, 267, 292, 265,
273, 298, 231, 232, 75, 75, 75, 75, 75, 20,
75, 75, 75, 153, 75, 75, 75, 75, 75, 154,
75, 155, 974, 305, 126, 127, 127, 75, 75, 75,
157, 75, 75, 204, 268, 204, 261, 262, 269, 221,
276, 270, 271, 277, 278, 299, 300, 263, 234, 235,
279, 280, 281, 975, 222, 282, 283, 328, 301, 75,
284, 75, 75, 316, 330, 316, 316, 329, 316, 426,
317, 549, 331, 318, 334, 427, 294, 550, 335, 319,
 
294, 294, 336, 294, 294, 75, 75, 75, 21, 22,
158, 159, 21, 160, 161, 27, 28, 29, 30, 162,
163, 164, 165, 166, 167, 168, 169, 169, 170, 171,
41, 172, 43, 173, 174, 175, 176, 177, 178, 179,
166, 166, 166, 166, 166, 180, 166, 181, 182, 183,
166, 166, 184, 185, 166, 166, 166, 166, 166, 166,
186, 166, 187, 21, 166, 188, 189, 190, 177, 191,
192, 166, 166, 166, 166, 193, 166, 194, 195, 196,
166, 197, 198, 166, 166, 166, 71, 72, 73, 199,
21, 200, 201, 21, 21, 202, 976, 21, 21, 21,
 
21, 21, 21, 206, 21, 291, 203, 21, 21, 21,
206, 206, 21, 21, 21, 21, 228, 228, 228, 332,
320, 316, 298, 316, 321, 360, 365, 835, 361, 333,
316, 294, 316, 836, 431, 229, 366, 229, 322, 294,
294, 300, 21, 21, 21, 21, 338, 294, 294, 432,
339, 371, 323, 347, 372, 378, 454, 340, 977, 379,
362, 292, 341, 380, 363, 229, 346, 229, 207, 21,
208, 21, 21, 200, 201, 21, 21, 202, 364, 21,
21, 21, 21, 21, 21, 206, 21, 305, 203, 21,
21, 21, 206, 206, 21, 21, 21, 21, 228, 228,
 
228, 367, 356, 316, 368, 316, 357, 369, 381, 358,
442, 464, 455, 294, 305, 443, 978, 229, 382, 229,
294, 294, 359, 465, 21, 21, 21, 21, 375, 376,
230, 447, 387, 383, 420, 417, 417, 384, 417, 377,
385, 386, 388, 477, 448, 410, 410, 229, 410, 229,
207, 21, 208, 21, 21, 200, 201, 230, 25, 202,
478, 21, 21, 21, 21, 979, 21, 206, 436, 454,
203, 21, 21, 21, 206, 206, 21, 21, 21, 316,
417, 316, 350, 454, 351, 470, 352, 471, 417, 294,
410, 391, 353, 425, 392, 393, 294, 294, 410, 354,
 
355, 394, 395, 396, 417, 980, 397, 398, 673, 493,
342, 399, 421, 417, 410, 210, 423, 211, 437, 422,
454, 212, 494, 410, 981, 438, 424, 982, 983, 417,
456, 984, 213, 21, 214, 21, 21, 200, 201, 410,
25, 202, 305, 21, 21, 21, 21, 985, 21, 206,
986, 417, 203, 21, 21, 21, 206, 206, 21, 21,
21, 410, 348, 348, 348, 604, 229, 417, 229, 305,
457, 439, 532, 605, 348, 348, 348, 410, 440, 554,
987, 306, 434, 306, 533, 228, 228, 228, 555, 572,
316, 435, 316, 306, 349, 306, 229, 210, 229, 211,
 
294, 573, 417, 212, 229, 988, 229, 294, 294, 585,
441, 306, 410, 306, 213, 21, 214, 21, 220, 220,
220, 349, 536, 306, 537, 306, 586, 220, 220, 220,
220, 220, 220, 454, 229, 485, 229, 509, 486, 510,
487, 498, 544, 511, 499, 545, 417, 578, 488, 579,
500, 489, 454, 454, 989, 546, 410, 417, 220, 220,
220, 220, 220, 220, 295, 295, 295, 410, 454, 316,
868, 316, 990, 295, 295, 295, 295, 295, 295, 294,
991, 303, 303, 303, 454, 593, 529, 294, 594, 417,
595, 867, 992, 866, 993, 348, 348, 348, 596, 410,
 
1750, 597, 1750, 655, 295, 295, 295, 295, 295, 295,
302, 302, 302, 305, 306, 994, 306, 995, 672, 303,
304, 303, 304, 303, 303, 996, 305, 997, 601, 306,
1750, 306, 1750, 305, 602, 657, 609, 851, 671, 610,
305, 603, 307, 852, 306, 611, 306, 998, 999, 1000,
303, 304, 303, 304, 303, 303, 316, 305, 530, 306,
1001, 306, 620, 305, 621, 1002, 294, 1003, 622, 307,
309, 309, 309, 294, 294, 417, 1004, 417, 417, 309,
310, 309, 311, 309, 309, 410, 312, 410, 410, 316,
313, 316, 639, 312, 641, 642, 1005, 314, 315, 294,
 
1006, 1007, 312, 1010, 1011, 1012, 294, 294, 1013, 1014,
309, 316, 309, 316, 309, 309, 316, 312, 316, 1015,
306, 1016, 306, 312, 1017, 1018, 294, 1021, 1022, 312,
345, 345, 345, 294, 538, 1023, 316, 1024, 316, 345,
345, 345, 345, 345, 345, 316, 294, 316, 417, 539,
306, 1028, 306, 294, 294, 294, 454, 454, 410, 454,
1031, 1032, 294, 294, 1029, 1033, 1036, 1034, 1037, 1038,
345, 345, 345, 345, 345, 345, 407, 407, 407, 1039,
1030, 316, 564, 316, 1035, 407, 407, 407, 407, 407,
407, 294, 1040, 316, 658, 316, 1026, 737, 294, 294,
 
746, 1041, 1042, 294, 1027, 1043, 1044, 1045, 1025, 1046,
294, 294, 1047, 1048, 1049, 1050, 407, 407, 407, 407,
407, 407, 411, 411, 411, 1051, 1052, 1053, 1054, 1055,
1056, 411, 411, 411, 411, 411, 411, 1057, 1058, 1059,
1060, 1061, 1062, 1063, 1064, 1066, 1067, 1068, 1069, 1070,
1071, 1072, 1073, 1074, 1077, 1075, 1065, 1078, 1079, 1080,
1081, 1082, 411, 411, 411, 411, 411, 411, 415, 415,
415, 1076, 1083, 1084, 1085, 1086, 1087, 415, 416, 415,
417, 415, 415, 1088, 418, 1089, 1090, 1091, 419, 1092,
1093, 418, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101,
 
418, 1102, 1104, 1105, 1106, 1107, 1109, 1110, 415, 417,
415, 417, 415, 415, 1111, 418, 1112, 1103, 1113, 1114,
1115, 418, 1108, 1116, 1117, 1118, 1119, 418, 295, 295,
295, 1120, 1121, 1122, 1123, 1124, 1125, 295, 295, 295,
295, 295, 295, 1126, 1127, 1128, 1129, 526, 1130, 526,
1131, 1132, 1133, 1134, 1135, 1136, 1137, 1140, 1141, 1142,
1143, 1144, 1138, 1145, 1146, 1147, 1148, 1149, 295, 295,
295, 295, 295, 295, 1139, 1150, 1151, 526, 1152, 526,
345, 345, 345, 1153, 1154, 1155, 1156, 1157, 1158, 345,
345, 345, 345, 345, 345, 1159, 454, 1162, 454, 566,
 
1163, 566, 454, 1164, 1165, 1166, 1167, 1168, 1169, 1170,
1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180,
345, 345, 345, 345, 345, 345, 1181, 1182, 1183, 566,
1184, 566, 407, 407, 407, 1185, 1186, 1187, 1188, 1189,
1190, 407, 407, 407, 407, 407, 407, 1160, 1191, 1161,
1192, 637, 1193, 637, 1194, 1195, 1196, 1197, 1198, 1199,
1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209,
1210, 1211, 407, 407, 407, 407, 407, 407, 1212, 1213,
1214, 637, 1215, 637, 411, 411, 411, 1216, 1217, 1218,
1219, 1220, 1221, 411, 411, 411, 411, 411, 411, 1222,
 
1223, 1224, 1225, 638, 1226, 638, 1227, 1228, 1229, 1230,
1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240,
1241, 1242, 1243, 1244, 411, 411, 411, 411, 411, 411,
1245, 1246, 1247, 638, 1248, 638, 1008, 1008, 1249, 1008,
1008, 1008, 1250, 1008, 1008, 1008, 1008, 1008, 1251, 1008,
1252, 1253, 1254, 1255, 1256, 1257, 1258, 1008, 1008, 1008,
1008, 1008, 1259, 1260, 454, 454, 1261, 1262, 1263, 1264,
1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274,
1275, 1276, 1278, 1279, 1280, 1281, 1277, 1282, 1283, 1284,
1285, 1008, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293,
 
1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303,
1304, 1305, 1306, 1307, 1008, 1008, 1008, 1019, 1019, 1308,
1019, 1019, 1019, 1309, 1019, 1019, 1019, 1019, 1019, 1310,
1019, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1019, 1019,
1019, 1019, 1019, 1318, 1319, 1320, 1321, 1322, 1324, 1325,
1326, 1327, 1323, 1328, 1329, 1330, 1331, 1332, 1333, 1334,
1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344,
1345, 1346, 1019, 1347, 1348, 1349, 1350, 1351, 1352, 1353,
1354, 1355, 1356, 1357, 1358, 1359, 1363, 1364, 1365, 1366,
1367, 1368, 1369, 1370, 1371, 1019, 1019, 1019, 1008, 1008,
 
1372, 1008, 1008, 1008, 1360, 1008, 1008, 1008, 1008, 1008,
1373, 1008, 1361, 1374, 1375, 1376, 1377, 1362, 1378, 1008,
1008, 1008, 1008, 1008, 1379, 1380, 1381, 1382, 1383, 1384,
1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394,
1398, 1395, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1396,
1406, 1407, 1408, 1008, 1397, 1409, 1410, 1412, 1413, 1414,
1415, 1416, 1417, 1418, 1411, 1419, 1420, 1421, 1422, 1423,
1424, 1425, 1426, 1427, 1430, 1431, 1008, 1008, 1008, 1019,
1019, 1432, 1019, 1019, 1019, 1428, 1019, 1019, 1019, 1019,
1019, 1433, 1019, 1429, 1434, 1435, 1436, 1437, 1438, 1439,
 
1019, 1019, 1019, 1019, 1019, 1440, 1441, 1442, 1443, 1444,
1446, 1447, 1448, 1449, 1450, 1451, 1452, 1445, 1453, 1454,
1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464,
1465, 1466, 1467, 1468, 1019, 1469, 1470, 1471, 1472, 1473,
1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483,
1484, 1485, 1486, 1487, 1488, 1489, 1490, 1019, 1019, 1019,
1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500,
1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510,
1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520,
1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530,
 
1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540,
1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550,
1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560,
1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570,
1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580,
1581, 1584, 1585, 1586, 1582, 1587, 1588, 1589, 1590, 1591,
1592, 1593, 1596, 1597, 1598, 1594, 1599, 1583, 1600, 1601,
1602, 1605, 1606, 1607, 1603, 1608, 1609, 1610, 1595, 1611,
1612, 1613, 1614, 1615, 1616, 1617, 1618, 1604, 1619, 1620,
1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630,
 
1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640,
1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650,
1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660,
1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670,
1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680,
1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690,
1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700,
1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710,
1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720,
1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730,
 
1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740,
1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 156,
156, 156, 156, 156, 156, 156, 156, 156, 156, 21,
21, 21, 21, 21, 21, 21, 21, 21, 21, 205,
205, 205, 205, 205, 205, 205, 205, 205, 205, 209,
209, 209, 209, 209, 209, 209, 209, 209, 209, 216,
216, 216, 216, 216, 216, 216, 216, 218, 218, 218,
218, 218, 218, 218, 218, 218, 218, 294, 294, 528,
294, 294, 294, 294, 344, 344, 344, 344, 344, 344,
 
344, 406, 972, 971, 970, 406, 406, 406, 408, 408,
408, 408, 408, 408, 408, 408, 408, 408, 410, 410,
969, 410, 410, 410, 410, 412, 968, 412, 412, 412,
412, 412, 412, 412, 412, 414, 967, 414, 414, 414,
414, 414, 414, 414, 414, 451, 966, 451, 451, 451,
451, 451, 451, 451, 451, 452, 965, 452, 453, 453,
964, 963, 453, 453, 962, 453, 527, 527, 961, 527,
527, 527, 527, 567, 567, 567, 567, 567, 567, 567,
1009, 960, 1009, 1009, 1009, 1009, 1009, 1009, 1009, 1009,
1020, 959, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020,
 
1008, 958, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008,
1019, 957, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019,
956, 955, 954, 953, 952, 951, 950, 949, 948, 947,
946, 945, 944, 943, 942, 941, 940, 939, 938, 937,
936, 935, 934, 933, 932, 931, 930, 929, 928, 927,
926, 925, 924, 923, 922, 921, 920, 919, 918, 917,
916, 915, 914, 913, 912, 911, 910, 909, 908, 907,
906, 905, 904, 903, 902, 901, 900, 899, 898, 897,
896, 895, 894, 893, 892, 891, 890, 889, 888, 887,
886, 885, 884, 883, 882, 881, 880, 879, 878, 877,
 
876, 875, 874, 873, 872, 871, 870, 869, 865, 864,
863, 862, 861, 860, 859, 858, 857, 856, 855, 854,
853, 850, 849, 848, 847, 846, 845, 844, 843, 842,
841, 840, 839, 838, 837, 834, 833, 832, 831, 830,
829, 828, 827, 826, 825, 824, 823, 822, 821, 820,
819, 818, 817, 816, 815, 814, 813, 812, 811, 810,
809, 808, 807, 806, 805, 804, 803, 802, 801, 800,
799, 798, 797, 796, 795, 794, 793, 792, 791, 790,
789, 788, 787, 786, 785, 784, 783, 782, 781, 780,
779, 778, 777, 776, 775, 774, 773, 772, 771, 770,
 
769, 768, 767, 766, 765, 764, 763, 762, 761, 760,
759, 758, 757, 756, 755, 754, 753, 752, 751, 750,
749, 748, 747, 745, 744, 743, 742, 741, 740, 739,
738, 736, 735, 734, 733, 732, 731, 730, 729, 728,
727, 726, 725, 724, 723, 722, 721, 720, 719, 718,
717, 716, 715, 714, 713, 712, 711, 710, 709, 708,
707, 706, 705, 704, 703, 702, 701, 700, 699, 698,
697, 696, 695, 694, 693, 692, 691, 690, 689, 688,
687, 686, 685, 684, 683, 682, 681, 680, 679, 678,
677, 676, 675, 674, 453, 454, 450, 670, 669, 668,
 
667, 666, 665, 664, 663, 662, 661, 660, 659, 656,
654, 653, 652, 651, 650, 649, 648, 647, 646, 645,
644, 643, 640, 409, 636, 635, 634, 633, 632, 631,
630, 629, 628, 627, 626, 625, 624, 623, 619, 618,
617, 616, 615, 614, 613, 612, 608, 607, 606, 600,
599, 598, 592, 591, 590, 589, 588, 587, 584, 583,
582, 581, 580, 577, 576, 575, 574, 571, 570, 569,
568, 565, 563, 562, 561, 560, 559, 558, 557, 556,
553, 552, 551, 548, 547, 543, 542, 541, 540, 535,
534, 531, 525, 524, 523, 522, 521, 520, 519, 518,
 
517, 516, 515, 514, 513, 512, 508, 507, 506, 505,
504, 503, 502, 501, 497, 496, 495, 492, 491, 490,
484, 483, 482, 481, 480, 479, 476, 475, 474, 473,
472, 469, 468, 467, 466, 463, 462, 461, 460, 459,
458, 219, 215, 454, 300, 450, 449, 446, 445, 444,
433, 430, 429, 428, 308, 301, 298, 297, 413, 409,
293, 405, 404, 403, 402, 401, 400, 390, 389, 374,
373, 370, 343, 337, 327, 326, 325, 324, 308, 297,
296, 219, 293, 215, 290, 289, 288, 287, 286, 285,
275, 274, 260, 259, 256, 233, 225, 224, 223, 219,
 
217, 215, 1750, 19, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750
} ;
 
static yyconst flex_int16_t yy_chk[2787] =
{ 0,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 36, 72, 9, 9, 9, 9, 9, 9, 9,
9, 9, 28, 36, 41, 41, 13, 13, 14, 14,
13, 801, 14, 43, 43, 46, 45, 28, 45, 46,
45, 13, 46, 14, 47, 48, 45, 47, 9, 48,
 
9, 9, 49, 45, 45, 46, 52, 57, 50, 52,
59, 50, 49, 48, 50, 56, 91, 57, 72, 56,
59, 87, 94, 94, 9, 9, 9, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 802, 91, 10, 10, 10, 10, 10, 10,
10, 10, 10, 13, 58, 14, 55, 55, 58, 81,
62, 58, 58, 62, 62, 87, 89, 55, 96, 96,
62, 62, 62, 803, 81, 62, 62, 108, 89, 10,
62, 10, 10, 99, 109, 99, 100, 108, 100, 180,
99, 329, 109, 99, 111, 180, 100, 329, 111, 100,
 
99, 99, 111, 100, 100, 10, 10, 10, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
15, 15, 15, 15, 15, 15, 804, 15, 15, 15,
 
15, 15, 15, 15, 15, 119, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 38, 38, 38, 110,
101, 101, 123, 101, 101, 130, 132, 640, 130, 110,
102, 101, 102, 640, 184, 38, 132, 38, 101, 101,
102, 125, 15, 15, 15, 15, 113, 102, 102, 184,
113, 135, 102, 125, 135, 139, 210, 113, 806, 139,
131, 119, 113, 139, 131, 38, 123, 38, 15, 15,
15, 15, 16, 16, 16, 16, 16, 16, 131, 16,
16, 16, 16, 16, 16, 16, 16, 169, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 37, 37,
 
37, 133, 129, 103, 133, 103, 129, 133, 140, 129,
193, 240, 210, 103, 169, 193, 808, 37, 140, 37,
103, 103, 129, 240, 16, 16, 16, 16, 138, 138,
37, 197, 142, 141, 175, 175, 177, 141, 189, 138,
141, 141, 142, 252, 197, 175, 177, 37, 189, 37,
16, 16, 16, 16, 17, 17, 17, 37, 17, 17,
252, 17, 17, 17, 17, 809, 17, 17, 189, 457,
17, 17, 17, 17, 17, 17, 17, 17, 17, 116,
179, 116, 128, 211, 128, 246, 128, 246, 190, 116,
179, 145, 128, 179, 145, 145, 116, 116, 190, 128,
 
128, 145, 145, 145, 178, 810, 145, 145, 457, 263,
116, 145, 176, 176, 178, 17, 178, 17, 190, 176,
212, 17, 263, 176, 811, 190, 178, 812, 813, 191,
211, 814, 17, 17, 17, 17, 18, 18, 18, 191,
18, 18, 302, 18, 18, 18, 18, 815, 18, 18,
816, 188, 18, 18, 18, 18, 18, 18, 18, 18,
18, 188, 126, 126, 126, 378, 220, 192, 220, 302,
212, 191, 314, 378, 127, 127, 127, 192, 191, 333,
818, 126, 188, 126, 314, 228, 228, 228, 333, 354,
309, 188, 309, 127, 126, 127, 220, 18, 220, 18,
 
309, 354, 415, 18, 228, 819, 228, 309, 309, 366,
192, 126, 415, 126, 18, 18, 18, 18, 26, 26,
26, 126, 319, 127, 319, 127, 366, 26, 26, 26,
26, 26, 26, 673, 228, 259, 228, 276, 259, 276,
259, 267, 326, 276, 267, 326, 417, 360, 259, 360,
267, 259, 671, 672, 820, 326, 417, 434, 26, 26,
26, 26, 26, 26, 79, 79, 79, 434, 456, 310,
673, 310, 821, 79, 79, 79, 79, 79, 79, 310,
822, 303, 303, 303, 455, 373, 310, 310, 373, 436,
373, 672, 823, 671, 824, 348, 348, 348, 373, 436,
 
303, 373, 303, 434, 79, 79, 79, 79, 79, 79,
90, 90, 90, 303, 348, 825, 348, 826, 456, 90,
90, 90, 90, 90, 90, 827, 90, 828, 377, 90,
303, 90, 303, 90, 377, 436, 382, 656, 455, 382,
303, 377, 90, 656, 348, 382, 348, 829, 830, 831,
90, 90, 90, 90, 90, 90, 311, 90, 311, 90,
832, 90, 391, 90, 391, 833, 311, 834, 391, 90,
98, 98, 98, 311, 311, 416, 835, 420, 421, 98,
98, 98, 98, 98, 98, 416, 98, 420, 421, 316,
98, 316, 416, 98, 420, 421, 836, 98, 98, 316,
 
840, 841, 98, 845, 846, 848, 316, 316, 849, 850,
98, 98, 98, 98, 98, 98, 320, 98, 320, 851,
528, 852, 528, 98, 856, 857, 320, 861, 862, 98,
122, 122, 122, 320, 320, 864, 342, 865, 342, 122,
122, 122, 122, 122, 122, 321, 342, 321, 437, 321,
528, 869, 528, 342, 342, 321, 866, 868, 437, 867,
872, 873, 321, 321, 871, 874, 877, 876, 878, 879,
122, 122, 122, 122, 122, 122, 153, 153, 153, 882,
871, 530, 342, 530, 876, 153, 153, 153, 153, 153,
153, 530, 883, 539, 437, 539, 867, 530, 530, 530,
 
539, 885, 887, 539, 868, 888, 889, 890, 866, 891,
539, 539, 892, 893, 894, 895, 153, 153, 153, 153,
153, 153, 161, 161, 161, 896, 897, 898, 899, 900,
901, 161, 161, 161, 161, 161, 161, 902, 904, 905,
906, 907, 908, 910, 911, 912, 914, 915, 916, 917,
918, 919, 920, 921, 923, 922, 911, 924, 926, 927,
928, 930, 161, 161, 161, 161, 161, 161, 174, 174,
174, 922, 932, 933, 934, 935, 936, 174, 174, 174,
174, 174, 174, 937, 174, 938, 939, 940, 174, 941,
942, 174, 943, 944, 945, 946, 947, 948, 949, 950,
 
174, 952, 953, 954, 955, 957, 958, 959, 174, 174,
174, 174, 174, 174, 960, 174, 963, 952, 964, 966,
968, 174, 957, 969, 970, 971, 972, 174, 295, 295,
295, 973, 974, 975, 976, 977, 978, 295, 295, 295,
295, 295, 295, 979, 980, 981, 982, 295, 983, 295,
984, 986, 987, 988, 989, 990, 992, 994, 996, 997,
998, 999, 993, 1000, 1001, 1002, 1003, 1005, 295, 295,
295, 295, 295, 295, 993, 1006, 1007, 295, 1011, 295,
345, 345, 345, 1013, 1014, 1016, 1017, 1018, 1022, 345,
345, 345, 345, 345, 345, 1024, 1027, 1028, 1025, 345,
 
1029, 345, 1026, 1030, 1032, 1034, 1035, 1036, 1037, 1038,
1039, 1041, 1043, 1044, 1045, 1047, 1049, 1051, 1052, 1054,
345, 345, 345, 345, 345, 345, 1056, 1057, 1058, 345,
1059, 345, 407, 407, 407, 1060, 1061, 1062, 1063, 1064,
1065, 407, 407, 407, 407, 407, 407, 1025, 1066, 1026,
1067, 407, 1068, 407, 1071, 1072, 1073, 1074, 1075, 1076,
1078, 1079, 1080, 1081, 1082, 1084, 1085, 1087, 1088, 1089,
1091, 1093, 407, 407, 407, 407, 407, 407, 1094, 1095,
1096, 407, 1097, 407, 411, 411, 411, 1098, 1099, 1100,
1101, 1102, 1103, 411, 411, 411, 411, 411, 411, 1105,
 
1107, 1108, 1109, 411, 1110, 411, 1111, 1112, 1114, 1116,
1117, 1118, 1120, 1122, 1123, 1125, 1126, 1128, 1130, 1131,
1132, 1133, 1134, 1135, 411, 411, 411, 411, 411, 411,
1136, 1137, 1138, 411, 1139, 411, 842, 842, 1140, 842,
842, 842, 1141, 842, 842, 842, 842, 842, 1142, 842,
1145, 1146, 1147, 1148, 1149, 1153, 1154, 842, 842, 842,
842, 842, 1155, 1159, 1160, 1161, 1162, 1164, 1165, 1166,
1167, 1168, 1169, 1171, 1172, 1174, 1175, 1176, 1177, 1178,
1180, 1181, 1183, 1184, 1185, 1186, 1181, 1187, 1188, 1189,
1190, 842, 1193, 1195, 1196, 1197, 1199, 1200, 1201, 1202,
 
1204, 1206, 1207, 1208, 1209, 1210, 1212, 1213, 1214, 1216,
1217, 1218, 1219, 1221, 842, 842, 842, 858, 858, 1222,
858, 858, 858, 1223, 858, 858, 858, 858, 858, 1224,
858, 1225, 1226, 1228, 1229, 1231, 1232, 1233, 858, 858,
858, 858, 858, 1234, 1235, 1236, 1238, 1239, 1241, 1242,
1243, 1244, 1239, 1245, 1246, 1247, 1248, 1251, 1253, 1254,
1255, 1256, 1257, 1258, 1259, 1260, 1262, 1263, 1265, 1266,
1267, 1268, 858, 1269, 1270, 1271, 1272, 1274, 1275, 1276,
1277, 1278, 1279, 1280, 1282, 1283, 1285, 1288, 1290, 1291,
1293, 1294, 1295, 1298, 1299, 858, 858, 858, 1009, 1009,
 
1300, 1009, 1009, 1009, 1284, 1009, 1009, 1009, 1009, 1009,
1301, 1009, 1284, 1302, 1305, 1307, 1308, 1284, 1310, 1009,
1009, 1009, 1009, 1009, 1311, 1312, 1313, 1314, 1315, 1316,
1317, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1328, 1329,
1331, 1330, 1334, 1341, 1343, 1344, 1345, 1346, 1347, 1330,
1348, 1349, 1350, 1009, 1330, 1351, 1352, 1353, 1354, 1355,
1356, 1357, 1358, 1359, 1352, 1360, 1361, 1362, 1364, 1365,
1367, 1368, 1369, 1370, 1372, 1373, 1009, 1009, 1009, 1020,
1020, 1374, 1020, 1020, 1020, 1371, 1020, 1020, 1020, 1020,
1020, 1375, 1020, 1371, 1376, 1378, 1379, 1380, 1381, 1382,
 
1020, 1020, 1020, 1020, 1020, 1383, 1384, 1385, 1386, 1387,
1388, 1389, 1390, 1391, 1392, 1393, 1394, 1387, 1395, 1396,
1397, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407,
1409, 1412, 1413, 1414, 1020, 1415, 1417, 1418, 1419, 1420,
1421, 1422, 1423, 1424, 1425, 1426, 1427, 1430, 1431, 1432,
1433, 1434, 1435, 1436, 1437, 1438, 1439, 1020, 1020, 1020,
1440, 1441, 1443, 1446, 1447, 1448, 1449, 1451, 1452, 1453,
1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463,
1464, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475,
1476, 1477, 1478, 1479, 1481, 1482, 1483, 1484, 1485, 1486,
 
1487, 1488, 1489, 1490, 1491, 1492, 1495, 1496, 1497, 1498,
1499, 1500, 1501, 1502, 1503, 1504, 1506, 1507, 1509, 1510,
1511, 1512, 1513, 1515, 1516, 1517, 1518, 1520, 1521, 1522,
1524, 1525, 1526, 1527, 1528, 1529, 1531, 1532, 1534, 1535,
1536, 1537, 1538, 1540, 1541, 1542, 1543, 1545, 1546, 1547,
1548, 1549, 1550, 1551, 1548, 1553, 1555, 1556, 1557, 1558,
1559, 1560, 1561, 1562, 1564, 1560, 1565, 1548, 1566, 1567,
1568, 1569, 1570, 1571, 1568, 1573, 1575, 1576, 1560, 1577,
1578, 1579, 1580, 1581, 1582, 1583, 1584, 1568, 1585, 1586,
1589, 1590, 1592, 1593, 1594, 1595, 1596, 1600, 1601, 1602,
 
1603, 1604, 1605, 1606, 1607, 1610, 1611, 1613, 1614, 1615,
1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625,
1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635,
1636, 1637, 1639, 1640, 1642, 1643, 1644, 1645, 1646, 1647,
1649, 1651, 1652, 1654, 1655, 1657, 1658, 1659, 1660, 1661,
1662, 1663, 1664, 1665, 1666, 1667, 1668, 1670, 1671, 1672,
1673, 1674, 1675, 1676, 1677, 1678, 1679, 1681, 1682, 1684,
1685, 1686, 1687, 1688, 1690, 1691, 1692, 1694, 1695, 1696,
1697, 1698, 1699, 1700, 1701, 1702, 1704, 1705, 1707, 1708,
1709, 1710, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719,
 
1720, 1721, 1722, 1723, 1725, 1726, 1727, 1729, 1731, 1732,
1733, 1736, 1737, 1740, 1741, 1743, 1745, 1746, 1747, 1751,
1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1751, 1752,
1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1752, 1753,
1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1753, 1754,
1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1754, 1755,
1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1755, 1756,
1756, 1756, 1756, 1756, 1756, 1756, 1756, 1757, 1757, 1757,
1757, 1757, 1757, 1757, 1757, 1757, 1757, 1758, 1758, 1769,
1758, 1758, 1758, 1758, 1759, 1759, 1759, 1759, 1759, 1759,
 
1759, 1760, 799, 798, 797, 1760, 1760, 1760, 1761, 1761,
1761, 1761, 1761, 1761, 1761, 1761, 1761, 1761, 1762, 1762,
795, 1762, 1762, 1762, 1762, 1763, 794, 1763, 1763, 1763,
1763, 1763, 1763, 1763, 1763, 1764, 793, 1764, 1764, 1764,
1764, 1764, 1764, 1764, 1764, 1765, 792, 1765, 1765, 1765,
1765, 1765, 1765, 1765, 1765, 1766, 791, 1766, 1767, 1767,
789, 788, 1767, 1767, 787, 1767, 1768, 1768, 786, 1768,
1768, 1768, 1768, 1770, 1770, 1770, 1770, 1770, 1770, 1770,
1771, 785, 1771, 1771, 1771, 1771, 1771, 1771, 1771, 1771,
1772, 784, 1772, 1772, 1772, 1772, 1772, 1772, 1772, 1772,
 
1773, 783, 1773, 1773, 1773, 1773, 1773, 1773, 1773, 1773,
1774, 781, 1774, 1774, 1774, 1774, 1774, 1774, 1774, 1774,
779, 777, 776, 775, 774, 773, 771, 770, 769, 768,
767, 766, 765, 764, 763, 762, 761, 760, 759, 757,
756, 755, 753, 751, 750, 749, 748, 747, 746, 745,
743, 742, 740, 739, 738, 736, 735, 734, 733, 732,
731, 730, 729, 728, 727, 726, 725, 724, 723, 722,
721, 720, 718, 717, 716, 715, 714, 713, 712, 711,
710, 708, 706, 705, 704, 702, 701, 700, 698, 697,
696, 695, 694, 692, 691, 690, 689, 688, 687, 686,
 
684, 682, 680, 679, 678, 677, 676, 674, 670, 669,
668, 667, 666, 665, 664, 663, 662, 661, 659, 658,
657, 655, 654, 653, 652, 651, 650, 649, 648, 647,
646, 645, 643, 642, 641, 639, 636, 633, 632, 631,
630, 629, 628, 627, 626, 625, 624, 623, 622, 621,
620, 619, 618, 617, 616, 615, 614, 613, 612, 611,
610, 609, 608, 606, 603, 602, 601, 600, 599, 598,
597, 596, 595, 594, 593, 591, 590, 589, 588, 587,
586, 585, 584, 583, 582, 581, 580, 579, 578, 577,
576, 575, 574, 573, 572, 571, 570, 569, 568, 565,
 
564, 563, 562, 561, 560, 559, 558, 557, 556, 555,
554, 553, 550, 549, 548, 547, 546, 545, 544, 543,
542, 541, 540, 538, 537, 536, 535, 534, 533, 532,
531, 529, 525, 522, 521, 520, 519, 518, 517, 516,
515, 514, 513, 512, 511, 510, 509, 508, 507, 506,
505, 504, 503, 502, 501, 500, 499, 498, 497, 496,
494, 493, 492, 491, 490, 489, 488, 487, 486, 485,
483, 482, 481, 480, 479, 478, 477, 476, 475, 474,
473, 472, 471, 470, 469, 468, 467, 466, 465, 464,
463, 462, 461, 460, 454, 453, 450, 449, 448, 447,
 
446, 445, 444, 443, 442, 441, 440, 439, 438, 435,
433, 432, 431, 430, 429, 428, 427, 426, 425, 424,
423, 422, 419, 408, 405, 404, 403, 402, 401, 400,
399, 398, 397, 396, 395, 394, 393, 392, 390, 389,
388, 387, 386, 385, 384, 383, 381, 380, 379, 376,
375, 374, 372, 371, 370, 369, 368, 367, 365, 364,
363, 362, 361, 359, 358, 357, 356, 353, 352, 351,
350, 343, 341, 340, 339, 338, 337, 336, 335, 334,
332, 331, 330, 328, 327, 325, 324, 323, 322, 318,
317, 313, 290, 289, 288, 287, 286, 285, 284, 283,
 
282, 281, 280, 279, 278, 277, 275, 274, 273, 272,
271, 270, 269, 268, 266, 265, 264, 262, 261, 260,
258, 257, 256, 255, 254, 253, 251, 250, 249, 248,
247, 245, 244, 243, 242, 239, 238, 237, 236, 235,
231, 218, 215, 209, 203, 200, 198, 196, 195, 194,
185, 183, 182, 181, 172, 167, 165, 163, 162, 160,
159, 151, 150, 149, 148, 147, 146, 144, 143, 137,
136, 134, 117, 112, 107, 106, 105, 104, 95, 85,
84, 78, 77, 76, 70, 69, 68, 67, 64, 63,
61, 60, 54, 53, 51, 42, 34, 32, 31, 25,
 
24, 22, 19, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750,
1750, 1750, 1750, 1750, 1750, 1750
} ;
 
static yy_state_type yy_last_accepting_state;
static char *yy_last_accepting_cpos;
 
extern int yy_flex_debug;
int yy_flex_debug = 0;
 
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
*/
#define REJECT reject_used_but_not_detected
#define yymore() yymore_used_but_not_detected
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
#line 1 "ldlex.l"
#line 4 "ldlex.l"
 
/* Copyright 1991-2013 Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "bfd.h"
#include "safe-ctype.h"
#include "bfdlink.h"
#include "ld.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldfile.h"
#include "ldlex.h"
#include "ldmain.h"
#include "libiberty.h"
 
/* The type of top-level parser input.
yylex and yyparse (indirectly) both check this. */
input_type parser_input;
 
/* Line number in the current input file.
(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. `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. */
 
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) result = yy_input (buf, max_size)
 
#ifndef YY_NO_UNPUT
#define YY_NO_UNPUT
#endif
 
#define MAX_INCLUDE_DEPTH 10
static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
static const char *file_name_stack[MAX_INCLUDE_DEPTH];
static unsigned int lineno_stack[MAX_INCLUDE_DEPTH];
static unsigned int sysrooted_stack[MAX_INCLUDE_DEPTH];
static unsigned int include_stack_ptr = 0;
static int vers_node_nesting = 0;
 
static int yy_input (char *, int);
static void comment (void);
static void lex_warn_invalid (char *where, char *what);
 
/* STATES
EXPRESSION definitely in an expression
SCRIPT definitely in a script
BOTH either EXPRESSION or SCRIPT
DEFSYMEXP in an argument to -defsym
MRI in an MRI script
VERS_START starting a Sun style mapfile
VERS_SCRIPT a Sun style mapfile
VERS_NODE a node within a Sun style mapfile
*/
#define RTOKEN(x) { yylval.token = x; return x; }
 
/* Some versions of flex want this. */
#ifndef yywrap
int yywrap (void) { return 1; }
#endif
 
 
 
 
 
 
 
 
#line 1745 "ldlex.c"
 
#define INITIAL 0
#define SCRIPT 1
#define EXPRESSION 2
#define BOTH 3
#define DEFSYMEXP 4
#define MRI 5
#define VERS_START 6
#define VERS_SCRIPT 7
#define VERS_NODE 8
 
#ifndef YY_NO_UNISTD_H
/* Special case for "unistd.h", since it is non-ANSI. We include it way
* down here because we want the user's section 1 to have been scanned first.
* The user has a chance to override it with an option.
*/
#include <unistd.h>
#endif
 
#ifndef YY_EXTRA_TYPE
#define YY_EXTRA_TYPE void *
#endif
 
static int yy_init_globals (void );
 
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
 
int yylex_destroy (void );
 
int yyget_debug (void );
 
void yyset_debug (int debug_flag );
 
YY_EXTRA_TYPE yyget_extra (void );
 
void yyset_extra (YY_EXTRA_TYPE user_defined );
 
FILE *yyget_in (void );
 
void yyset_in (FILE * in_str );
 
FILE *yyget_out (void );
 
void yyset_out (FILE * out_str );
 
yy_size_t yyget_leng (void );
 
char *yyget_text (void );
 
int yyget_lineno (void );
 
void yyset_lineno (int line_number );
 
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
 
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap (void );
#else
extern int yywrap (void );
#endif
#endif
 
#ifndef yytext_ptr
static void yy_flex_strncpy (char *,yyconst char *,int );
#endif
 
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * );
#endif
 
#ifndef YY_NO_INPUT
 
#ifdef __cplusplus
static int yyinput (void );
#else
static int input (void );
#endif
 
#endif
 
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
#define YY_READ_BUF_SIZE 8192
#endif
 
/* Copy whatever the last rule matched to the standard output. */
#ifndef ECHO
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
#define ECHO fwrite( yytext, yyleng, 1, yyout )
#endif
 
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
* is returned in "result".
*/
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
yy_size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
if ( c == '\n' ) \
buf[n++] = (char) c; \
if ( c == EOF && ferror( yyin ) ) \
YY_FATAL_ERROR( "input in flex scanner failed" ); \
result = n; \
} \
else \
{ \
errno=0; \
while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
YY_FATAL_ERROR( "input in flex scanner failed" ); \
break; \
} \
errno=0; \
clearerr(yyin); \
} \
}\
\
 
#endif
 
/* No semi-colon after return; correct usage is to write "yyterminate();" -
* we don't want an extra ';' after the "return" because that will cause
* some compilers to complain about unreachable statements.
*/
#ifndef yyterminate
#define yyterminate() return YY_NULL
#endif
 
/* Number of entries by which start-condition stack grows. */
#ifndef YY_START_STACK_INCR
#define YY_START_STACK_INCR 25
#endif
 
/* Report a fatal error. */
#ifndef YY_FATAL_ERROR
#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
#endif
 
/* end tables serialization structures and prototypes */
 
/* Default declaration of generated scanner - a define so the user can
* easily add parameters.
*/
#ifndef YY_DECL
#define YY_DECL_IS_OURS 1
 
extern int yylex (void);
 
#define YY_DECL int yylex (void)
#endif /* !YY_DECL */
 
/* Code executed at the beginning of each rule, after yytext and yyleng
* have been set up.
*/
#ifndef YY_USER_ACTION
#define YY_USER_ACTION
#endif
 
/* Code executed at the end of each rule. */
#ifndef YY_BREAK
#define YY_BREAK break;
#endif
 
#define YY_RULE_SETUP \
YY_USER_ACTION
 
/** The main scanner function which does all the work.
*/
YY_DECL
{
register yy_state_type yy_current_state;
register char *yy_cp, *yy_bp;
register int yy_act;
 
#line 119 "ldlex.l"
 
 
if (parser_input != input_selected)
{
/* The first token of the input determines the initial parser state. */
input_type t = parser_input;
parser_input = input_selected;
switch (t)
{
case input_script: return INPUT_SCRIPT; break;
case input_mri_script: return INPUT_MRI_SCRIPT; break;
case input_version_script: return INPUT_VERSION_SCRIPT; break;
case input_dynamic_list: return INPUT_DYNAMIC_LIST; break;
case input_defsym: return INPUT_DEFSYM; break;
default: abort ();
}
}
 
#line 1952 "ldlex.c"
 
if ( !(yy_init) )
{
(yy_init) = 1;
 
#ifdef YY_USER_INIT
YY_USER_INIT;
#endif
 
if ( ! (yy_start) )
(yy_start) = 1; /* first start state */
 
if ( ! yyin )
yyin = stdin;
 
if ( ! yyout )
yyout = stdout;
 
if ( ! YY_CURRENT_BUFFER ) {
yyensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
yy_create_buffer(yyin,YY_BUF_SIZE );
}
 
yy_load_buffer_state( );
}
 
while ( 1 ) /* loops until end-of-file is reached */
{
yy_cp = (yy_c_buf_p);
 
/* Support of yytext. */
*yy_cp = (yy_hold_char);
 
/* yy_bp points to the position in yy_ch_buf of the start of
* the current run.
*/
yy_bp = yy_cp;
 
yy_current_state = (yy_start);
yy_match:
do
{
register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
(yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 1751 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
while ( yy_base[yy_current_state] != 2704 );
 
yy_find_action:
yy_act = yy_accept[yy_current_state];
if ( yy_act == 0 )
{ /* have to back up */
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
yy_act = yy_accept[yy_current_state];
}
 
YY_DO_BEFORE_ACTION;
 
do_action: /* This label is used only to access EOF actions. */
 
switch ( yy_act )
{ /* beginning of action switch */
case 0: /* must back up */
/* undo the effects of YY_DO_BEFORE_ACTION */
*yy_cp = (yy_hold_char);
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
goto yy_find_action;
 
case 1:
YY_RULE_SETUP
#line 137 "ldlex.l"
{ comment (); }
YY_BREAK
case 2:
YY_RULE_SETUP
#line 140 "ldlex.l"
{ RTOKEN('-');}
YY_BREAK
case 3:
YY_RULE_SETUP
#line 141 "ldlex.l"
{ RTOKEN('+');}
YY_BREAK
case 4:
YY_RULE_SETUP
#line 142 "ldlex.l"
{ yylval.name = xstrdup (yytext); return NAME; }
YY_BREAK
case 5:
YY_RULE_SETUP
#line 143 "ldlex.l"
{ RTOKEN('='); }
YY_BREAK
case 6:
YY_RULE_SETUP
#line 145 "ldlex.l"
{
yylval.integer = bfd_scan_vma (yytext + 1, 0, 16);
yylval.bigint.str = NULL;
return INT;
}
YY_BREAK
case 7:
YY_RULE_SETUP
#line 151 "ldlex.l"
{
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, 0,
ibase);
yylval.bigint.str = NULL;
return INT;
}
YY_BREAK
case 8:
YY_RULE_SETUP
#line 176 "ldlex.l"
{
char *s = yytext;
int ibase = 0;
 
if (*s == '$')
{
++s;
ibase = 16;
}
yylval.integer = bfd_scan_vma (s, 0, ibase);
yylval.bigint.str = NULL;
if (yytext[yyleng - 1] == 'M'
|| yytext[yyleng - 1] == 'm')
{
yylval.integer *= 1024 * 1024;
}
else if (yytext[yyleng - 1] == 'K'
|| yytext[yyleng - 1]=='k')
{
yylval.integer *= 1024;
}
else if (yytext[0] == '0'
&& (yytext[1] == 'x'
|| yytext[1] == 'X'))
{
yylval.bigint.str = xstrdup (yytext + 2);
}
return INT;
}
YY_BREAK
case 9:
YY_RULE_SETUP
#line 205 "ldlex.l"
{ RTOKEN(']');}
YY_BREAK
case 10:
YY_RULE_SETUP
#line 206 "ldlex.l"
{ RTOKEN('[');}
YY_BREAK
case 11:
YY_RULE_SETUP
#line 207 "ldlex.l"
{ RTOKEN(LSHIFTEQ);}
YY_BREAK
case 12:
YY_RULE_SETUP
#line 208 "ldlex.l"
{ RTOKEN(RSHIFTEQ);}
YY_BREAK
case 13:
YY_RULE_SETUP
#line 209 "ldlex.l"
{ RTOKEN(OROR);}
YY_BREAK
case 14:
YY_RULE_SETUP
#line 210 "ldlex.l"
{ RTOKEN(EQ);}
YY_BREAK
case 15:
YY_RULE_SETUP
#line 211 "ldlex.l"
{ RTOKEN(NE);}
YY_BREAK
case 16:
YY_RULE_SETUP
#line 212 "ldlex.l"
{ RTOKEN(GE);}
YY_BREAK
case 17:
YY_RULE_SETUP
#line 213 "ldlex.l"
{ RTOKEN(LE);}
YY_BREAK
case 18:
YY_RULE_SETUP
#line 214 "ldlex.l"
{ RTOKEN(LSHIFT);}
YY_BREAK
case 19:
YY_RULE_SETUP
#line 215 "ldlex.l"
{ RTOKEN(RSHIFT);}
YY_BREAK
case 20:
YY_RULE_SETUP
#line 216 "ldlex.l"
{ RTOKEN(PLUSEQ);}
YY_BREAK
case 21:
YY_RULE_SETUP
#line 217 "ldlex.l"
{ RTOKEN(MINUSEQ);}
YY_BREAK
case 22:
YY_RULE_SETUP
#line 218 "ldlex.l"
{ RTOKEN(MULTEQ);}
YY_BREAK
case 23:
YY_RULE_SETUP
#line 219 "ldlex.l"
{ RTOKEN(DIVEQ);}
YY_BREAK
case 24:
YY_RULE_SETUP
#line 220 "ldlex.l"
{ RTOKEN(ANDEQ);}
YY_BREAK
case 25:
YY_RULE_SETUP
#line 221 "ldlex.l"
{ RTOKEN(OREQ);}
YY_BREAK
case 26:
YY_RULE_SETUP
#line 222 "ldlex.l"
{ RTOKEN(ANDAND);}
YY_BREAK
case 27:
YY_RULE_SETUP
#line 223 "ldlex.l"
{ RTOKEN('>');}
YY_BREAK
case 28:
YY_RULE_SETUP
#line 224 "ldlex.l"
{ RTOKEN(',');}
YY_BREAK
case 29:
YY_RULE_SETUP
#line 225 "ldlex.l"
{ RTOKEN('&');}
YY_BREAK
case 30:
YY_RULE_SETUP
#line 226 "ldlex.l"
{ RTOKEN('|');}
YY_BREAK
case 31:
YY_RULE_SETUP
#line 227 "ldlex.l"
{ RTOKEN('~');}
YY_BREAK
case 32:
YY_RULE_SETUP
#line 228 "ldlex.l"
{ RTOKEN('!');}
YY_BREAK
case 33:
YY_RULE_SETUP
#line 229 "ldlex.l"
{ RTOKEN('?');}
YY_BREAK
case 34:
YY_RULE_SETUP
#line 230 "ldlex.l"
{ RTOKEN('*');}
YY_BREAK
case 35:
YY_RULE_SETUP
#line 231 "ldlex.l"
{ RTOKEN('+');}
YY_BREAK
case 36:
YY_RULE_SETUP
#line 232 "ldlex.l"
{ RTOKEN('-');}
YY_BREAK
case 37:
YY_RULE_SETUP
#line 233 "ldlex.l"
{ RTOKEN('/');}
YY_BREAK
case 38:
YY_RULE_SETUP
#line 234 "ldlex.l"
{ RTOKEN('%');}
YY_BREAK
case 39:
YY_RULE_SETUP
#line 235 "ldlex.l"
{ RTOKEN('<');}
YY_BREAK
case 40:
YY_RULE_SETUP
#line 236 "ldlex.l"
{ RTOKEN('=');}
YY_BREAK
case 41:
YY_RULE_SETUP
#line 237 "ldlex.l"
{ RTOKEN('}') ; }
YY_BREAK
case 42:
YY_RULE_SETUP
#line 238 "ldlex.l"
{ RTOKEN('{'); }
YY_BREAK
case 43:
YY_RULE_SETUP
#line 239 "ldlex.l"
{ RTOKEN(')');}
YY_BREAK
case 44:
YY_RULE_SETUP
#line 240 "ldlex.l"
{ RTOKEN('(');}
YY_BREAK
case 45:
YY_RULE_SETUP
#line 241 "ldlex.l"
{ RTOKEN(':'); }
YY_BREAK
case 46:
YY_RULE_SETUP
#line 242 "ldlex.l"
{ RTOKEN(';');}
YY_BREAK
case 47:
YY_RULE_SETUP
#line 243 "ldlex.l"
{ RTOKEN(MEMORY);}
YY_BREAK
case 48:
YY_RULE_SETUP
#line 244 "ldlex.l"
{ RTOKEN(REGION_ALIAS);}
YY_BREAK
case 49:
YY_RULE_SETUP
#line 245 "ldlex.l"
{ RTOKEN(LD_FEATURE);}
YY_BREAK
case 50:
YY_RULE_SETUP
#line 246 "ldlex.l"
{ RTOKEN(ORIGIN);}
YY_BREAK
case 51:
YY_RULE_SETUP
#line 247 "ldlex.l"
{ RTOKEN(VERSIONK);}
YY_BREAK
case 52:
YY_RULE_SETUP
#line 248 "ldlex.l"
{ RTOKEN(BLOCK);}
YY_BREAK
case 53:
YY_RULE_SETUP
#line 249 "ldlex.l"
{ RTOKEN(BIND);}
YY_BREAK
case 54:
YY_RULE_SETUP
#line 250 "ldlex.l"
{ RTOKEN(LENGTH);}
YY_BREAK
case 55:
YY_RULE_SETUP
#line 251 "ldlex.l"
{ RTOKEN(ALIGN_K);}
YY_BREAK
case 56:
YY_RULE_SETUP
#line 252 "ldlex.l"
{ RTOKEN(DATA_SEGMENT_ALIGN);}
YY_BREAK
case 57:
YY_RULE_SETUP
#line 253 "ldlex.l"
{ RTOKEN(DATA_SEGMENT_RELRO_END);}
YY_BREAK
case 58:
YY_RULE_SETUP
#line 254 "ldlex.l"
{ RTOKEN(DATA_SEGMENT_END);}
YY_BREAK
case 59:
YY_RULE_SETUP
#line 255 "ldlex.l"
{ RTOKEN(ADDR);}
YY_BREAK
case 60:
YY_RULE_SETUP
#line 256 "ldlex.l"
{ RTOKEN(LOADADDR);}
YY_BREAK
case 61:
YY_RULE_SETUP
#line 257 "ldlex.l"
{ RTOKEN(ALIGNOF); }
YY_BREAK
case 62:
YY_RULE_SETUP
#line 258 "ldlex.l"
{ RTOKEN(MAX_K); }
YY_BREAK
case 63:
YY_RULE_SETUP
#line 259 "ldlex.l"
{ RTOKEN(MIN_K); }
YY_BREAK
case 64:
YY_RULE_SETUP
#line 260 "ldlex.l"
{ RTOKEN(LOG2CEIL); }
YY_BREAK
case 65:
YY_RULE_SETUP
#line 261 "ldlex.l"
{ RTOKEN(ASSERT_K); }
YY_BREAK
case 66:
YY_RULE_SETUP
#line 262 "ldlex.l"
{ RTOKEN(ENTRY);}
YY_BREAK
case 67:
YY_RULE_SETUP
#line 263 "ldlex.l"
{ RTOKEN(EXTERN);}
YY_BREAK
case 68:
YY_RULE_SETUP
#line 264 "ldlex.l"
{ RTOKEN(NEXT);}
YY_BREAK
case 69:
YY_RULE_SETUP
#line 265 "ldlex.l"
{ RTOKEN(SIZEOF_HEADERS);}
YY_BREAK
case 70:
YY_RULE_SETUP
#line 266 "ldlex.l"
{ RTOKEN(SIZEOF_HEADERS);}
YY_BREAK
case 71:
YY_RULE_SETUP
#line 267 "ldlex.l"
{ RTOKEN(SEGMENT_START);}
YY_BREAK
case 72:
YY_RULE_SETUP
#line 268 "ldlex.l"
{ RTOKEN(MAP);}
YY_BREAK
case 73:
YY_RULE_SETUP
#line 269 "ldlex.l"
{ RTOKEN(SIZEOF);}
YY_BREAK
case 74:
YY_RULE_SETUP
#line 270 "ldlex.l"
{ RTOKEN(TARGET_K);}
YY_BREAK
case 75:
YY_RULE_SETUP
#line 271 "ldlex.l"
{ RTOKEN(SEARCH_DIR);}
YY_BREAK
case 76:
YY_RULE_SETUP
#line 272 "ldlex.l"
{ RTOKEN(OUTPUT);}
YY_BREAK
case 77:
YY_RULE_SETUP
#line 273 "ldlex.l"
{ RTOKEN(INPUT);}
YY_BREAK
case 78:
YY_RULE_SETUP
#line 274 "ldlex.l"
{ RTOKEN(GROUP);}
YY_BREAK
case 79:
YY_RULE_SETUP
#line 275 "ldlex.l"
{ RTOKEN(AS_NEEDED);}
YY_BREAK
case 80:
YY_RULE_SETUP
#line 276 "ldlex.l"
{ RTOKEN(DEFINED);}
YY_BREAK
case 81:
YY_RULE_SETUP
#line 277 "ldlex.l"
{ RTOKEN(CREATE_OBJECT_SYMBOLS);}
YY_BREAK
case 82:
YY_RULE_SETUP
#line 278 "ldlex.l"
{ RTOKEN( CONSTRUCTORS);}
YY_BREAK
case 83:
YY_RULE_SETUP
#line 279 "ldlex.l"
{ RTOKEN(FORCE_COMMON_ALLOCATION);}
YY_BREAK
case 84:
YY_RULE_SETUP
#line 280 "ldlex.l"
{ RTOKEN(INHIBIT_COMMON_ALLOCATION);}
YY_BREAK
case 85:
YY_RULE_SETUP
#line 281 "ldlex.l"
{ RTOKEN(SECTIONS);}
YY_BREAK
case 86:
YY_RULE_SETUP
#line 282 "ldlex.l"
{ RTOKEN(INSERT_K);}
YY_BREAK
case 87:
YY_RULE_SETUP
#line 283 "ldlex.l"
{ RTOKEN(AFTER);}
YY_BREAK
case 88:
YY_RULE_SETUP
#line 284 "ldlex.l"
{ RTOKEN(BEFORE);}
YY_BREAK
case 89:
YY_RULE_SETUP
#line 285 "ldlex.l"
{ RTOKEN(FILL);}
YY_BREAK
case 90:
YY_RULE_SETUP
#line 286 "ldlex.l"
{ RTOKEN(STARTUP);}
YY_BREAK
case 91:
YY_RULE_SETUP
#line 287 "ldlex.l"
{ RTOKEN(OUTPUT_FORMAT);}
YY_BREAK
case 92:
YY_RULE_SETUP
#line 288 "ldlex.l"
{ RTOKEN( OUTPUT_ARCH);}
YY_BREAK
case 93:
YY_RULE_SETUP
#line 289 "ldlex.l"
{ RTOKEN(HLL);}
YY_BREAK
case 94:
YY_RULE_SETUP
#line 290 "ldlex.l"
{ RTOKEN(SYSLIB);}
YY_BREAK
case 95:
YY_RULE_SETUP
#line 291 "ldlex.l"
{ RTOKEN(FLOAT);}
YY_BREAK
case 96:
YY_RULE_SETUP
#line 292 "ldlex.l"
{ RTOKEN( QUAD);}
YY_BREAK
case 97:
YY_RULE_SETUP
#line 293 "ldlex.l"
{ RTOKEN( SQUAD);}
YY_BREAK
case 98:
YY_RULE_SETUP
#line 294 "ldlex.l"
{ RTOKEN( LONG);}
YY_BREAK
case 99:
YY_RULE_SETUP
#line 295 "ldlex.l"
{ RTOKEN( SHORT);}
YY_BREAK
case 100:
YY_RULE_SETUP
#line 296 "ldlex.l"
{ RTOKEN( BYTE);}
YY_BREAK
case 101:
YY_RULE_SETUP
#line 297 "ldlex.l"
{ RTOKEN(NOFLOAT);}
YY_BREAK
case 102:
YY_RULE_SETUP
#line 298 "ldlex.l"
{ RTOKEN(NOCROSSREFS);}
YY_BREAK
case 103:
YY_RULE_SETUP
#line 299 "ldlex.l"
{ RTOKEN(OVERLAY); }
YY_BREAK
case 104:
YY_RULE_SETUP
#line 300 "ldlex.l"
{ RTOKEN(SORT_BY_NAME); }
YY_BREAK
case 105:
YY_RULE_SETUP
#line 301 "ldlex.l"
{ RTOKEN(SORT_BY_ALIGNMENT); }
YY_BREAK
case 106:
YY_RULE_SETUP
#line 302 "ldlex.l"
{ RTOKEN(SORT_BY_NAME); }
YY_BREAK
case 107:
YY_RULE_SETUP
#line 303 "ldlex.l"
{ RTOKEN(SORT_BY_INIT_PRIORITY); }
YY_BREAK
case 108:
YY_RULE_SETUP
#line 304 "ldlex.l"
{ RTOKEN(SORT_NONE); }
YY_BREAK
case 109:
YY_RULE_SETUP
#line 305 "ldlex.l"
{ RTOKEN(NOLOAD);}
YY_BREAK
case 110:
YY_RULE_SETUP
#line 306 "ldlex.l"
{ RTOKEN(DSECT);}
YY_BREAK
case 111:
YY_RULE_SETUP
#line 307 "ldlex.l"
{ RTOKEN(COPY);}
YY_BREAK
case 112:
YY_RULE_SETUP
#line 308 "ldlex.l"
{ RTOKEN(INFO);}
YY_BREAK
case 113:
YY_RULE_SETUP
#line 309 "ldlex.l"
{ RTOKEN(OVERLAY);}
YY_BREAK
case 114:
YY_RULE_SETUP
#line 310 "ldlex.l"
{ RTOKEN(ONLY_IF_RO); }
YY_BREAK
case 115:
YY_RULE_SETUP
#line 311 "ldlex.l"
{ RTOKEN(ONLY_IF_RW); }
YY_BREAK
case 116:
YY_RULE_SETUP
#line 312 "ldlex.l"
{ RTOKEN(SPECIAL); }
YY_BREAK
case 117:
YY_RULE_SETUP
#line 313 "ldlex.l"
{ RTOKEN(ORIGIN);}
YY_BREAK
case 118:
YY_RULE_SETUP
#line 314 "ldlex.l"
{ RTOKEN(ORIGIN);}
YY_BREAK
case 119:
YY_RULE_SETUP
#line 315 "ldlex.l"
{ RTOKEN( LENGTH);}
YY_BREAK
case 120:
YY_RULE_SETUP
#line 316 "ldlex.l"
{ RTOKEN( LENGTH);}
YY_BREAK
case 121:
YY_RULE_SETUP
#line 317 "ldlex.l"
{ RTOKEN(INPUT_SECTION_FLAGS); }
YY_BREAK
case 122:
YY_RULE_SETUP
#line 318 "ldlex.l"
{ RTOKEN(INCLUDE);}
YY_BREAK
case 123:
YY_RULE_SETUP
#line 319 "ldlex.l"
{ RTOKEN (PHDRS); }
YY_BREAK
case 124:
YY_RULE_SETUP
#line 320 "ldlex.l"
{ RTOKEN(AT);}
YY_BREAK
case 125:
YY_RULE_SETUP
#line 321 "ldlex.l"
{ RTOKEN(ALIGN_WITH_INPUT);}
YY_BREAK
case 126:
YY_RULE_SETUP
#line 322 "ldlex.l"
{ RTOKEN(SUBALIGN);}
YY_BREAK
case 127:
YY_RULE_SETUP
#line 323 "ldlex.l"
{ RTOKEN(HIDDEN); }
YY_BREAK
case 128:
YY_RULE_SETUP
#line 324 "ldlex.l"
{ RTOKEN(PROVIDE); }
YY_BREAK
case 129:
YY_RULE_SETUP
#line 325 "ldlex.l"
{ RTOKEN(PROVIDE_HIDDEN); }
YY_BREAK
case 130:
YY_RULE_SETUP
#line 326 "ldlex.l"
{ RTOKEN(KEEP); }
YY_BREAK
case 131:
YY_RULE_SETUP
#line 327 "ldlex.l"
{ RTOKEN(EXCLUDE_FILE); }
YY_BREAK
case 132:
YY_RULE_SETUP
#line 328 "ldlex.l"
{ RTOKEN(CONSTANT);}
YY_BREAK
case 133:
/* rule 133 can match eol */
YY_RULE_SETUP
#line 329 "ldlex.l"
{ ++ lineno; }
YY_BREAK
case 134:
/* rule 134 can match eol */
YY_RULE_SETUP
#line 330 "ldlex.l"
{ ++ lineno; RTOKEN(NEWLINE); }
YY_BREAK
case 135:
YY_RULE_SETUP
#line 331 "ldlex.l"
{ /* Mri comment line */ }
YY_BREAK
case 136:
YY_RULE_SETUP
#line 332 "ldlex.l"
{ /* Mri comment line */ }
YY_BREAK
case 137:
YY_RULE_SETUP
#line 333 "ldlex.l"
{ RTOKEN(ENDWORD); }
YY_BREAK
case 138:
YY_RULE_SETUP
#line 334 "ldlex.l"
{ RTOKEN(ALIGNMOD);}
YY_BREAK
case 139:
YY_RULE_SETUP
#line 335 "ldlex.l"
{ RTOKEN(ALIGN_K);}
YY_BREAK
case 140:
YY_RULE_SETUP
#line 336 "ldlex.l"
{ RTOKEN(CHIP); }
YY_BREAK
case 141:
YY_RULE_SETUP
#line 337 "ldlex.l"
{ RTOKEN(BASE); }
YY_BREAK
case 142:
YY_RULE_SETUP
#line 338 "ldlex.l"
{ RTOKEN(ALIAS); }
YY_BREAK
case 143:
YY_RULE_SETUP
#line 339 "ldlex.l"
{ RTOKEN(TRUNCATE); }
YY_BREAK
case 144:
YY_RULE_SETUP
#line 340 "ldlex.l"
{ RTOKEN(LOAD); }
YY_BREAK
case 145:
YY_RULE_SETUP
#line 341 "ldlex.l"
{ RTOKEN(PUBLIC); }
YY_BREAK
case 146:
YY_RULE_SETUP
#line 342 "ldlex.l"
{ RTOKEN(ORDER); }
YY_BREAK
case 147:
YY_RULE_SETUP
#line 343 "ldlex.l"
{ RTOKEN(NAMEWORD); }
YY_BREAK
case 148:
YY_RULE_SETUP
#line 344 "ldlex.l"
{ RTOKEN(FORMAT); }
YY_BREAK
case 149:
YY_RULE_SETUP
#line 345 "ldlex.l"
{ RTOKEN(CASE); }
YY_BREAK
case 150:
YY_RULE_SETUP
#line 346 "ldlex.l"
{ RTOKEN(START); }
YY_BREAK
case 151:
YY_RULE_SETUP
#line 347 "ldlex.l"
{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
YY_BREAK
case 152:
YY_RULE_SETUP
#line 348 "ldlex.l"
{ RTOKEN(SECT); }
YY_BREAK
case 153:
YY_RULE_SETUP
#line 349 "ldlex.l"
{ RTOKEN(ABSOLUTE); }
YY_BREAK
case 154:
YY_RULE_SETUP
#line 350 "ldlex.l"
{ RTOKEN(ENDWORD); }
YY_BREAK
case 155:
YY_RULE_SETUP
#line 351 "ldlex.l"
{ RTOKEN(ALIGNMOD);}
YY_BREAK
case 156:
YY_RULE_SETUP
#line 352 "ldlex.l"
{ RTOKEN(ALIGN_K);}
YY_BREAK
case 157:
YY_RULE_SETUP
#line 353 "ldlex.l"
{ RTOKEN(CHIP); }
YY_BREAK
case 158:
YY_RULE_SETUP
#line 354 "ldlex.l"
{ RTOKEN(BASE); }
YY_BREAK
case 159:
YY_RULE_SETUP
#line 355 "ldlex.l"
{ RTOKEN(ALIAS); }
YY_BREAK
case 160:
YY_RULE_SETUP
#line 356 "ldlex.l"
{ RTOKEN(TRUNCATE); }
YY_BREAK
case 161:
YY_RULE_SETUP
#line 357 "ldlex.l"
{ RTOKEN(LOAD); }
YY_BREAK
case 162:
YY_RULE_SETUP
#line 358 "ldlex.l"
{ RTOKEN(PUBLIC); }
YY_BREAK
case 163:
YY_RULE_SETUP
#line 359 "ldlex.l"
{ RTOKEN(ORDER); }
YY_BREAK
case 164:
YY_RULE_SETUP
#line 360 "ldlex.l"
{ RTOKEN(NAMEWORD); }
YY_BREAK
case 165:
YY_RULE_SETUP
#line 361 "ldlex.l"
{ RTOKEN(FORMAT); }
YY_BREAK
case 166:
YY_RULE_SETUP
#line 362 "ldlex.l"
{ RTOKEN(CASE); }
YY_BREAK
case 167:
YY_RULE_SETUP
#line 363 "ldlex.l"
{ RTOKEN(EXTERN); }
YY_BREAK
case 168:
YY_RULE_SETUP
#line 364 "ldlex.l"
{ RTOKEN(START); }
YY_BREAK
case 169:
YY_RULE_SETUP
#line 365 "ldlex.l"
{ RTOKEN(LIST); /* LIST and ignore to end of line */ }
YY_BREAK
case 170:
YY_RULE_SETUP
#line 366 "ldlex.l"
{ RTOKEN(SECT); }
YY_BREAK
case 171:
YY_RULE_SETUP
#line 367 "ldlex.l"
{ RTOKEN(ABSOLUTE); }
YY_BREAK
case 172:
YY_RULE_SETUP
#line 369 "ldlex.l"
{
/* Filename without commas, needed to parse mri stuff */
yylval.name = xstrdup (yytext);
return NAME;
}
YY_BREAK
case 173:
YY_RULE_SETUP
#line 376 "ldlex.l"
{
yylval.name = xstrdup (yytext);
return NAME;
}
YY_BREAK
case 174:
YY_RULE_SETUP
#line 380 "ldlex.l"
{
yylval.name = xstrdup (yytext + 2);
return LNAME;
}
YY_BREAK
case 175:
YY_RULE_SETUP
#line 384 "ldlex.l"
{
yylval.name = xstrdup (yytext);
return NAME;
}
YY_BREAK
case 176:
YY_RULE_SETUP
#line 388 "ldlex.l"
{
yylval.name = xstrdup (yytext + 2);
return LNAME;
}
YY_BREAK
case 177:
YY_RULE_SETUP
#line 392 "ldlex.l"
{
/* Annoyingly, this pattern can match comments, and we have
longest match issues to consider. So if the first two
characters are a comment opening, put the input back and
try again. */
if (yytext[0] == '/' && yytext[1] == '*')
{
yyless (2);
comment ();
}
else
{
yylval.name = xstrdup (yytext);
return NAME;
}
}
YY_BREAK
case 178:
/* rule 178 can match eol */
YY_RULE_SETUP
#line 409 "ldlex.l"
{
/* No matter the state, quotes
give what's inside */
yylval.name = xstrdup (yytext + 1);
yylval.name[yyleng - 2] = 0;
return NAME;
}
YY_BREAK
case 179:
/* rule 179 can match eol */
YY_RULE_SETUP
#line 416 "ldlex.l"
{ lineno++;}
YY_BREAK
case 180:
YY_RULE_SETUP
#line 417 "ldlex.l"
{ }
YY_BREAK
case 181:
YY_RULE_SETUP
#line 419 "ldlex.l"
{ return *yytext; }
YY_BREAK
case 182:
YY_RULE_SETUP
#line 421 "ldlex.l"
{ RTOKEN(GLOBAL); }
YY_BREAK
case 183:
YY_RULE_SETUP
#line 423 "ldlex.l"
{ RTOKEN(LOCAL); }
YY_BREAK
case 184:
YY_RULE_SETUP
#line 425 "ldlex.l"
{ RTOKEN(EXTERN); }
YY_BREAK
case 185:
YY_RULE_SETUP
#line 427 "ldlex.l"
{ yylval.name = xstrdup (yytext);
return VERS_IDENTIFIER; }
YY_BREAK
case 186:
YY_RULE_SETUP
#line 430 "ldlex.l"
{ yylval.name = xstrdup (yytext);
return VERS_TAG; }
YY_BREAK
case 187:
YY_RULE_SETUP
#line 433 "ldlex.l"
{ BEGIN(VERS_SCRIPT); return *yytext; }
YY_BREAK
case 188:
YY_RULE_SETUP
#line 435 "ldlex.l"
{ BEGIN(VERS_NODE);
vers_node_nesting = 0;
return *yytext;
}
YY_BREAK
case 189:
YY_RULE_SETUP
#line 439 "ldlex.l"
{ return *yytext; }
YY_BREAK
case 190:
YY_RULE_SETUP
#line 440 "ldlex.l"
{ vers_node_nesting++; return *yytext; }
YY_BREAK
case 191:
YY_RULE_SETUP
#line 441 "ldlex.l"
{ if (--vers_node_nesting < 0)
BEGIN(VERS_SCRIPT);
return *yytext;
}
YY_BREAK
case 192:
/* rule 192 can match eol */
YY_RULE_SETUP
#line 446 "ldlex.l"
{ lineno++; }
YY_BREAK
case 193:
YY_RULE_SETUP
#line 448 "ldlex.l"
{ /* Eat up comments */ }
YY_BREAK
case 194:
YY_RULE_SETUP
#line 450 "ldlex.l"
{ /* Eat up whitespace */ }
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(SCRIPT):
case YY_STATE_EOF(EXPRESSION):
case YY_STATE_EOF(BOTH):
case YY_STATE_EOF(DEFSYMEXP):
case YY_STATE_EOF(MRI):
case YY_STATE_EOF(VERS_START):
case YY_STATE_EOF(VERS_SCRIPT):
case YY_STATE_EOF(VERS_NODE):
#line 452 "ldlex.l"
{
include_stack_ptr--;
if (include_stack_ptr == 0)
yyterminate ();
else
yy_switch_to_buffer (include_stack[include_stack_ptr]);
 
lineno = lineno_stack[include_stack_ptr];
input_flags.sysrooted = sysrooted_stack[include_stack_ptr];
 
return END;
}
YY_BREAK
case 195:
YY_RULE_SETUP
#line 465 "ldlex.l"
lex_warn_invalid (" in script", yytext);
YY_BREAK
case 196:
YY_RULE_SETUP
#line 466 "ldlex.l"
lex_warn_invalid (" in expression", yytext);
YY_BREAK
case 197:
YY_RULE_SETUP
#line 468 "ldlex.l"
ECHO;
YY_BREAK
#line 3149 "ldlex.c"
 
case YY_END_OF_BUFFER:
{
/* Amount of text matched not including the EOB char. */
int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
 
/* Undo the effects of YY_DO_BEFORE_ACTION. */
*yy_cp = (yy_hold_char);
YY_RESTORE_YY_MORE_OFFSET
 
if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
{
/* We're scanning a new file or input source. It's
* possible that this happened because the user
* just pointed yyin at a new source and called
* yylex(). If so, then we have to assure
* consistency between YY_CURRENT_BUFFER and our
* globals. Here is the right place to do so, because
* this is the first action (other than possibly a
* back-up) that will match for the new input source.
*/
(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
}
 
/* Note that here we test for yy_c_buf_p "<=" to the position
* of the first EOB in the buffer, since yy_c_buf_p will
* already have been incremented past the NUL character
* (since all states make transitions on EOB to the
* end-of-buffer state). Contrast this with the test
* in input().
*/
if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
{ /* This was really a NUL. */
yy_state_type yy_next_state;
 
(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
 
yy_current_state = yy_get_previous_state( );
 
/* Okay, we're now positioned to make the NUL
* transition. We couldn't have
* yy_get_previous_state() go ahead and do it
* for us because it doesn't know how to deal
* with the possibility of jamming (and we don't
* want to build jamming into it because then it
* will run more slowly).
*/
 
yy_next_state = yy_try_NUL_trans( yy_current_state );
 
yy_bp = (yytext_ptr) + YY_MORE_ADJ;
 
if ( yy_next_state )
{
/* Consume the NUL. */
yy_cp = ++(yy_c_buf_p);
yy_current_state = yy_next_state;
goto yy_match;
}
 
else
{
yy_cp = (yy_c_buf_p);
goto yy_find_action;
}
}
 
else switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_END_OF_FILE:
{
(yy_did_buffer_switch_on_eof) = 0;
 
if ( yywrap( ) )
{
/* Note: because we've taken care in
* yy_get_next_buffer() to have set up
* yytext, we can now set up
* yy_c_buf_p so that if some total
* hoser (like flex itself) wants to
* call the scanner after we return the
* YY_NULL, it'll still work - another
* YY_NULL will get returned.
*/
(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
 
yy_act = YY_STATE_EOF(YY_START);
goto do_action;
}
 
else
{
if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
}
break;
}
 
case EOB_ACT_CONTINUE_SCAN:
(yy_c_buf_p) =
(yytext_ptr) + yy_amount_of_matched_text;
 
yy_current_state = yy_get_previous_state( );
 
yy_cp = (yy_c_buf_p);
yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_match;
 
case EOB_ACT_LAST_MATCH:
(yy_c_buf_p) =
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
 
yy_current_state = yy_get_previous_state( );
 
yy_cp = (yy_c_buf_p);
yy_bp = (yytext_ptr) + YY_MORE_ADJ;
goto yy_find_action;
}
break;
}
 
default:
YY_FATAL_ERROR(
"fatal flex scanner internal error--no action found" );
} /* end of action switch */
} /* end of scanning one token */
} /* end of yylex */
 
/* yy_get_next_buffer - try to read in a new buffer
*
* Returns a code representing an action:
* EOB_ACT_LAST_MATCH -
* EOB_ACT_CONTINUE_SCAN - continue scanning from current position
* EOB_ACT_END_OF_FILE - end of file
*/
static int yy_get_next_buffer (void)
{
register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
register char *source = (yytext_ptr);
register int number_to_move, i;
int ret_val;
 
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
YY_FATAL_ERROR(
"fatal flex scanner internal error--end of buffer missed" );
 
if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
{ /* Don't try to fill the buffer, so this is an EOF. */
if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
{
/* We matched a single character, the EOB, so
* treat this as a final EOF.
*/
return EOB_ACT_END_OF_FILE;
}
 
else
{
/* We matched some text prior to the EOB, first
* process it.
*/
return EOB_ACT_LAST_MATCH;
}
}
 
/* Try to read more data. */
 
/* First move last chars to start of buffer. */
number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
 
for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++);
 
if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
/* don't do the read, it's not guaranteed to return an EOF,
* just force an EOF
*/
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
 
else
{
yy_size_t num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
while ( num_to_read <= 0 )
{ /* Not enough room in the buffer - grow it. */
 
/* just a shorter name for the current buffer */
YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
 
int yy_c_buf_p_offset =
(int) ((yy_c_buf_p) - b->yy_ch_buf);
 
if ( b->yy_is_our_buffer )
{
yy_size_t new_size = b->yy_buf_size * 2;
 
if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8;
else
b->yy_buf_size *= 2;
 
b->yy_ch_buf = (char *)
/* Include room in for 2 EOB chars. */
yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
}
else
/* Can't grow it, we don't own it. */
b->yy_ch_buf = 0;
 
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR(
"fatal error - scanner input buffer overflow" );
 
(yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
 
num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
number_to_move - 1;
 
}
 
if ( num_to_read > YY_READ_BUF_SIZE )
num_to_read = YY_READ_BUF_SIZE;
 
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
(yy_n_chars), num_to_read );
 
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
 
if ( (yy_n_chars) == 0 )
{
if ( number_to_move == YY_MORE_ADJ )
{
ret_val = EOB_ACT_END_OF_FILE;
yyrestart(yyin );
}
 
else
{
ret_val = EOB_ACT_LAST_MATCH;
YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
YY_BUFFER_EOF_PENDING;
}
}
 
else
ret_val = EOB_ACT_CONTINUE_SCAN;
 
if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */
yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
}
 
(yy_n_chars) += number_to_move;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
 
(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
 
return ret_val;
}
 
/* yy_get_previous_state - get the state just before the EOB char was reached */
 
static yy_state_type yy_get_previous_state (void)
{
register yy_state_type yy_current_state;
register char *yy_cp;
 
yy_current_state = (yy_start);
 
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
(yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 1751 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
}
 
return yy_current_state;
}
 
/* yy_try_NUL_trans - try to make a transition on the NUL character
*
* synopsis
* next_state = yy_try_NUL_trans( current_state );
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
{
register int yy_is_jam;
register char *yy_cp = (yy_c_buf_p);
 
register YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
(yy_last_accepting_state) = yy_current_state;
(yy_last_accepting_cpos) = yy_cp;
}
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
if ( yy_current_state >= 1751 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
yy_is_jam = (yy_current_state == 1750);
 
return yy_is_jam ? 0 : yy_current_state;
}
 
#ifndef YY_NO_INPUT
#ifdef __cplusplus
static int yyinput (void)
#else
static int input (void)
#endif
 
{
int c;
 
*(yy_c_buf_p) = (yy_hold_char);
 
if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
{
/* yy_c_buf_p now points to the character we want to return.
* If this occurs *before* the EOB characters, then it's a
* valid NUL; if not, then we've hit the end of the buffer.
*/
if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
/* This was really a NUL. */
*(yy_c_buf_p) = '\0';
 
else
{ /* need more input */
yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
++(yy_c_buf_p);
 
switch ( yy_get_next_buffer( ) )
{
case EOB_ACT_LAST_MATCH:
/* This happens because yy_g_n_b()
* sees that we've accumulated a
* token and flags that we need to
* try matching the token before
* proceeding. But for input(),
* there's no matching to consider.
* So convert the EOB_ACT_LAST_MATCH
* to EOB_ACT_END_OF_FILE.
*/
 
/* Reset buffer status. */
yyrestart(yyin );
 
/*FALLTHROUGH*/
 
case EOB_ACT_END_OF_FILE:
{
if ( yywrap( ) )
return 0;
 
if ( ! (yy_did_buffer_switch_on_eof) )
YY_NEW_FILE;
#ifdef __cplusplus
return yyinput();
#else
return input();
#endif
}
 
case EOB_ACT_CONTINUE_SCAN:
(yy_c_buf_p) = (yytext_ptr) + offset;
break;
}
}
}
 
c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
*(yy_c_buf_p) = '\0'; /* preserve yytext */
(yy_hold_char) = *++(yy_c_buf_p);
 
return c;
}
#endif /* ifndef YY_NO_INPUT */
 
/** Immediately switch to a different input stream.
* @param input_file A readable stream.
*
* @note This function does not reset the start condition to @c INITIAL .
*/
void yyrestart (FILE * input_file )
{
 
if ( ! YY_CURRENT_BUFFER ){
yyensure_buffer_stack ();
YY_CURRENT_BUFFER_LVALUE =
yy_create_buffer(yyin,YY_BUF_SIZE );
}
 
yy_init_buffer(YY_CURRENT_BUFFER,input_file );
yy_load_buffer_state( );
}
 
/** Switch to a different input buffer.
* @param new_buffer The new input buffer.
*
*/
void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
{
 
/* TODO. We should be able to replace this entire function body
* with
* yypop_buffer_state();
* yypush_buffer_state(new_buffer);
*/
yyensure_buffer_stack ();
if ( YY_CURRENT_BUFFER == new_buffer )
return;
 
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
*(yy_c_buf_p) = (yy_hold_char);
YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
 
YY_CURRENT_BUFFER_LVALUE = new_buffer;
yy_load_buffer_state( );
 
/* We don't actually know whether we did this switch during
* EOF (yywrap()) processing, but the only time this flag
* is looked at is after yywrap() is called, so it's safe
* to go ahead and always set it.
*/
(yy_did_buffer_switch_on_eof) = 1;
}
 
static void yy_load_buffer_state (void)
{
(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
(yy_hold_char) = *(yy_c_buf_p);
}
 
/** Allocate and initialize an input buffer state.
* @param file A readable stream.
* @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
*
* @return the allocated buffer state.
*/
YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
{
YY_BUFFER_STATE b;
 
b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
b->yy_buf_size = 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 = (char *) yyalloc(b->yy_buf_size + 2 );
if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
 
b->yy_is_our_buffer = 1;
 
yy_init_buffer(b,file );
 
return b;
}
 
/** Destroy the buffer.
* @param b a buffer created with yy_create_buffer()
*
*/
void yy_delete_buffer (YY_BUFFER_STATE b )
{
 
if ( ! b )
return;
 
if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
 
if ( b->yy_is_our_buffer )
yyfree((void *) b->yy_ch_buf );
 
yyfree((void *) b );
}
 
#ifndef __cplusplus
extern int isatty (int );
#endif /* __cplusplus */
 
/* Initializes or reinitializes a buffer.
* This function is sometimes called more than once on the same buffer,
* such as during a yyrestart() or at EOF.
*/
static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
 
{
int oerrno = errno;
 
yy_flush_buffer(b );
 
b->yy_input_file = file;
b->yy_fill_buffer = 1;
 
/* If b is the current buffer, then yy_init_buffer was _probably_
* called from yyrestart() or through yy_get_next_buffer.
* In that case, we don't want to reset the lineno or column.
*/
if (b != YY_CURRENT_BUFFER){
b->yy_bs_lineno = 1;
b->yy_bs_column = 0;
}
 
b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
 
errno = oerrno;
}
 
/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
* @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
*
*/
void yy_flush_buffer (YY_BUFFER_STATE b )
{
if ( ! b )
return;
 
b->yy_n_chars = 0;
 
/* We always need two end-of-buffer characters. The first causes
* a transition to the end-of-buffer state. The second causes
* a jam in that state.
*/
b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
 
b->yy_buf_pos = &b->yy_ch_buf[0];
 
b->yy_at_bol = 1;
b->yy_buffer_status = YY_BUFFER_NEW;
 
if ( b == YY_CURRENT_BUFFER )
yy_load_buffer_state( );
}
 
/** Pushes the new state onto the stack. The new state becomes
* the current state. This function will allocate the stack
* if necessary.
* @param new_buffer The new state.
*
*/
void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
{
if (new_buffer == NULL)
return;
 
yyensure_buffer_stack();
 
/* This block is copied from yy_switch_to_buffer. */
if ( YY_CURRENT_BUFFER )
{
/* Flush out information for old buffer. */
*(yy_c_buf_p) = (yy_hold_char);
YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
}
 
/* Only push if top exists. Otherwise, replace top. */
if (YY_CURRENT_BUFFER)
(yy_buffer_stack_top)++;
YY_CURRENT_BUFFER_LVALUE = new_buffer;
 
/* copied from yy_switch_to_buffer. */
yy_load_buffer_state( );
(yy_did_buffer_switch_on_eof) = 1;
}
 
/** Removes and deletes the top of the stack, if present.
* The next element becomes the new top.
*
*/
void yypop_buffer_state (void)
{
if (!YY_CURRENT_BUFFER)
return;
 
yy_delete_buffer(YY_CURRENT_BUFFER );
YY_CURRENT_BUFFER_LVALUE = NULL;
if ((yy_buffer_stack_top) > 0)
--(yy_buffer_stack_top);
 
if (YY_CURRENT_BUFFER) {
yy_load_buffer_state( );
(yy_did_buffer_switch_on_eof) = 1;
}
}
 
/* Allocates the stack if it does not exist.
* Guarantees space for at least one push.
*/
static void yyensure_buffer_stack (void)
{
yy_size_t num_to_alloc;
 
if (!(yy_buffer_stack)) {
 
/* First allocation is just for 2 elements, since we don't know if this
* scanner will even need a stack. We use 2 instead of 1 to avoid an
* immediate realloc on the next call.
*/
num_to_alloc = 1;
(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
 
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
}
 
if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
 
/* Increase the buffer to prepare for a possible push. */
int grow_size = 8 /* arbitrary grow size */;
 
num_to_alloc = (yy_buffer_stack_max) + grow_size;
(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
((yy_buffer_stack),
num_to_alloc * sizeof(struct yy_buffer_state*)
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
 
/* zero only the new slots.*/
memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
(yy_buffer_stack_max) = num_to_alloc;
}
}
 
/** Setup the input buffer state to scan directly from a user-specified character buffer.
* @param base the character buffer
* @param size the size in bytes of the character buffer
*
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
{
YY_BUFFER_STATE b;
 
if ( size < 2 ||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */
return 0;
 
b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
if ( ! b )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
 
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0;
b->yy_input_file = 0;
b->yy_n_chars = b->yy_buf_size;
b->yy_is_interactive = 0;
b->yy_at_bol = 1;
b->yy_fill_buffer = 0;
b->yy_buffer_status = YY_BUFFER_NEW;
 
yy_switch_to_buffer(b );
 
return b;
}
 
/** Setup the input buffer state to scan a string. The next call to yylex() will
* scan from a @e copy of @a str.
* @param yystr a NUL-terminated string to scan
*
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* yy_scan_bytes() instead.
*/
YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
{
 
return yy_scan_bytes(yystr,strlen(yystr) );
}
 
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
* @param bytes the byte buffer to scan
* @param len the number of bytes in the buffer pointed to by @a bytes.
*
* @return the newly allocated buffer state object.
*/
YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
{
YY_BUFFER_STATE b;
char *buf;
yy_size_t n, i;
 
/* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2;
buf = (char *) yyalloc(n );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
 
for ( i = 0; i < _yybytes_len; ++i )
buf[i] = yybytes[i];
 
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
b = yy_scan_buffer(buf,n );
if ( ! b )
YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
 
/* It's okay to grow etc. this buffer, and we should throw it
* away when we're done.
*/
b->yy_is_our_buffer = 1;
 
return b;
}
 
#ifndef YY_EXIT_FAILURE
#define YY_EXIT_FAILURE 2
#endif
 
static void yy_fatal_error (yyconst char* msg )
{
(void) fprintf( stderr, "%s\n", msg );
exit( YY_EXIT_FAILURE );
}
 
/* Redefine yyless() so it works in section 3 code. */
 
#undef yyless
#define yyless(n) \
do \
{ \
/* Undo effects of setting up yytext. */ \
int yyless_macro_arg = (n); \
YY_LESS_LINENO(yyless_macro_arg);\
yytext[yyleng] = (yy_hold_char); \
(yy_c_buf_p) = yytext + yyless_macro_arg; \
(yy_hold_char) = *(yy_c_buf_p); \
*(yy_c_buf_p) = '\0'; \
yyleng = yyless_macro_arg; \
} \
while ( 0 )
 
/* Accessor methods (get/set functions) to struct members. */
 
/** Get the current line number.
*
*/
int yyget_lineno (void)
{
 
return yylineno;
}
 
/** Get the input stream.
*
*/
FILE *yyget_in (void)
{
return yyin;
}
 
/** Get the output stream.
*
*/
FILE *yyget_out (void)
{
return yyout;
}
 
/** Get the length of the current token.
*
*/
yy_size_t yyget_leng (void)
{
return yyleng;
}
 
/** Get the current token.
*
*/
 
char *yyget_text (void)
{
return yytext;
}
 
/** Set the current line number.
* @param line_number
*
*/
void yyset_lineno (int line_number )
{
 
yylineno = line_number;
}
 
/** Set the input stream. This does not discard the current
* input buffer.
* @param in_str A readable stream.
*
* @see yy_switch_to_buffer
*/
void yyset_in (FILE * in_str )
{
yyin = in_str ;
}
 
void yyset_out (FILE * out_str )
{
yyout = out_str ;
}
 
int yyget_debug (void)
{
return yy_flex_debug;
}
 
void yyset_debug (int bdebug )
{
yy_flex_debug = bdebug ;
}
 
static int yy_init_globals (void)
{
/* Initialization is the same as for the non-reentrant scanner.
* This function is called from yylex_destroy(), so don't allocate here.
*/
 
(yy_buffer_stack) = 0;
(yy_buffer_stack_top) = 0;
(yy_buffer_stack_max) = 0;
(yy_c_buf_p) = (char *) 0;
(yy_init) = 0;
(yy_start) = 0;
 
/* Defined in main.c */
#ifdef YY_STDINIT
yyin = stdin;
yyout = stdout;
#else
yyin = (FILE *) 0;
yyout = (FILE *) 0;
#endif
 
/* For future reference: Set errno on error, since we are called by
* yylex_init()
*/
return 0;
}
 
/* yylex_destroy is for both reentrant and non-reentrant scanners. */
int yylex_destroy (void)
{
 
/* Pop the buffer stack, destroying each element. */
while(YY_CURRENT_BUFFER){
yy_delete_buffer(YY_CURRENT_BUFFER );
YY_CURRENT_BUFFER_LVALUE = NULL;
yypop_buffer_state();
}
 
/* Destroy the stack itself. */
yyfree((yy_buffer_stack) );
(yy_buffer_stack) = NULL;
 
/* Reset the globals. This is important in a non-reentrant scanner so the next time
* yylex() is called, initialization will occur. */
yy_init_globals( );
 
return 0;
}
 
/*
* Internal utility routines.
*/
 
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
{
register int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
#endif
 
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s )
{
register int n;
for ( n = 0; s[n]; ++n )
;
 
return n;
}
#endif
 
void *yyalloc (yy_size_t size )
{
return (void *) malloc( size );
}
 
void *yyrealloc (void * ptr, yy_size_t size )
{
/* The cast to (char *) in the following accommodates both
* implementations that use char* generic pointers, and those
* that use void* generic pointers. It works with the latter
* because both ANSI C and C++ allow castless assignment from
* any pointer type to void*, and deal with argument conversions
* as though doing an assignment.
*/
return (void *) realloc( (char *) ptr, size );
}
 
void yyfree (void * ptr )
{
free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
}
 
#define YYTABLES_NAME "yytables"
 
#line 468 "ldlex.l"
 
 
 
/* Switch flex to reading script file NAME, open on FILE,
saving the current input info on the include stack. */
 
void
lex_push_file (FILE *file, const char *name, unsigned int sysrooted)
{
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] = lineno;
sysrooted_stack[include_stack_ptr] = input_flags.sysrooted;
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
 
include_stack_ptr++;
lineno = 1;
input_flags.sysrooted = sysrooted;
yyin = file;
yy_switch_to_buffer (yy_create_buffer (yyin, YY_BUF_SIZE));
}
 
/* Return a newly created flex input buffer containing STRING,
which is SIZE bytes long. */
 
static YY_BUFFER_STATE
yy_create_string_buffer (const char *string, size_t size)
{
YY_BUFFER_STATE b;
 
/* Calls to m-alloc get turned by sed into xm-alloc. */
b = malloc (sizeof (struct yy_buffer_state));
b->yy_input_file = 0;
b->yy_buf_size = 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 = malloc ((unsigned) (b->yy_buf_size + 3));
 
b->yy_ch_buf[0] = '\n';
strcpy (b->yy_ch_buf+1, string);
b->yy_ch_buf[size+1] = YY_END_OF_BUFFER_CHAR;
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];
 
b->yy_is_our_buffer = 1;
b->yy_is_interactive = 0;
b->yy_at_bol = 1;
b->yy_fill_buffer = 0;
 
/* 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;
}
 
/* Switch flex to reading from STRING, saving the current input info
on the include stack. */
 
void
lex_redirect (const char *string, const char *fake_filename, unsigned int count)
{
YY_BUFFER_STATE tmp;
 
yy_init = 0;
if (include_stack_ptr >= MAX_INCLUDE_DEPTH)
{
einfo("%F: macros nested too deeply\n");
}
file_name_stack[include_stack_ptr] = fake_filename;
lineno_stack[include_stack_ptr] = lineno;
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
include_stack_ptr++;
lineno = count;
tmp = yy_create_string_buffer (string, strlen (string));
yy_switch_to_buffer (tmp);
}
/* Functions to switch to a different flex start condition,
saving the current start condition on `state_stack'. */
 
static int state_stack[MAX_INCLUDE_DEPTH * 2];
static int *state_stack_p = state_stack;
 
void
ldlex_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (SCRIPT);
}
 
void
ldlex_mri_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (MRI);
}
 
void
ldlex_version_script (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (VERS_START);
}
 
void
ldlex_version_file (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (VERS_SCRIPT);
}
 
void
ldlex_defsym (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (DEFSYMEXP);
}
 
void
ldlex_expression (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (EXPRESSION);
}
 
void
ldlex_both (void)
{
*(state_stack_p)++ = yy_start;
BEGIN (BOTH);
}
 
void
ldlex_popstate (void)
{
yy_start = *(--state_stack_p);
}
 
/* Return the current file name, or the previous file if no file is
current. */
 
const char*
ldlex_filename (void)
{
return file_name_stack[include_stack_ptr - (include_stack_ptr != 0)];
}
 
/* Place up to MAX_SIZE characters in BUF and return
either the number of characters read, or 0 to indicate EOF. */
 
static int
yy_input (char *buf, int max_size)
{
int result = 0;
if (YY_CURRENT_BUFFER->yy_input_file)
{
if (yyin)
{
result = fread (buf, 1, max_size, yyin);
// if (result < max_size && ferror (yyin))
// einfo ("%F%P: read in flex scanner failed\n");
}
}
return result;
}
 
/* Eat the rest of a C-style comment. */
 
static void
comment (void)
{
int c;
 
while (1)
{
c = input();
while (c != '*' && c != EOF)
{
if (c == '\n')
lineno++;
c = input();
}
 
if (c == '*')
{
c = input();
while (c == '*')
c = input();
if (c == '/')
break; /* found the end */
}
 
if (c == '\n')
lineno++;
 
if (c == EOF)
{
einfo( "%F%P: EOF in comment\n");
break;
}
}
}
 
/* Warn the user about a garbage character WHAT in the input
in context WHERE. */
 
static void
lex_warn_invalid (char *where, char *what)
{
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", ldlex_filename ());
}
 
if (! ISPRINT (*what))
{
sprintf (buf, "\\%03o", *(unsigned char *) what);
what = buf;
}
 
einfo ("%P:%S: ignoring invalid character `%s'%s\n", NULL, what, where);
}
 
/contrib/toolchain/binutils/ld/ldlex.h
0,0 → 1,181
/* ldlex.h -
Copyright 1991, 1992, 1993, 1994, 1995, 1997, 2000, 2003, 2005, 2006,
2007, 2012 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDLEX_H
#define LDLEX_H
 
#include <stdio.h>
 
/* Codes used for the long options with no short synonyms. 150 isn't
special; it's just an arbitrary non-ASCII char value. */
enum option_values
{
OPTION_ASSERT = 150,
OPTION_CALL_SHARED,
OPTION_CREF,
OPTION_DEFSYM,
OPTION_DEMANGLE,
OPTION_DYNAMIC_LINKER,
OPTION_SYSROOT,
OPTION_EB,
OPTION_EL,
OPTION_EMBEDDED_RELOCS,
OPTION_EXPORT_DYNAMIC,
OPTION_NO_EXPORT_DYNAMIC,
OPTION_HELP,
OPTION_IGNORE,
OPTION_MAP,
OPTION_NO_DEMANGLE,
OPTION_NO_KEEP_MEMORY,
OPTION_NO_WARN_MISMATCH,
OPTION_NO_WARN_SEARCH_MISMATCH,
OPTION_NOINHIBIT_EXEC,
OPTION_NON_SHARED,
OPTION_NO_WHOLE_ARCHIVE,
OPTION_OFORMAT,
OPTION_RELAX,
OPTION_NO_RELAX,
OPTION_RETAIN_SYMBOLS_FILE,
OPTION_RPATH,
OPTION_RPATH_LINK,
OPTION_SHARED,
OPTION_SONAME,
OPTION_SORT_COMMON,
OPTION_SORT_SECTION,
OPTION_STATS,
OPTION_SYMBOLIC,
OPTION_SYMBOLIC_FUNCTIONS,
OPTION_TASK_LINK,
OPTION_TBSS,
OPTION_TDATA,
OPTION_TTEXT,
OPTION_TTEXT_SEGMENT,
OPTION_TRODATA_SEGMENT,
OPTION_TLDATA_SEGMENT,
OPTION_TRADITIONAL_FORMAT,
OPTION_UR,
OPTION_VERBOSE,
OPTION_VERSION,
OPTION_VERSION_SCRIPT,
OPTION_VERSION_EXPORTS_SECTION,
OPTION_DYNAMIC_LIST,
OPTION_DYNAMIC_LIST_CPP_NEW,
OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
OPTION_DYNAMIC_LIST_DATA,
OPTION_WARN_COMMON,
OPTION_WARN_CONSTRUCTORS,
OPTION_WARN_FATAL,
OPTION_NO_WARN_FATAL,
OPTION_WARN_MULTIPLE_GP,
OPTION_WARN_ONCE,
OPTION_WARN_SECTION_ALIGN,
OPTION_SPLIT_BY_RELOC,
OPTION_SPLIT_BY_FILE ,
OPTION_WHOLE_ARCHIVE,
OPTION_ADD_DT_NEEDED_FOR_DYNAMIC,
OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC,
OPTION_ADD_DT_NEEDED_FOR_REGULAR,
OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR,
OPTION_WRAP,
OPTION_FORCE_EXE_SUFFIX,
OPTION_GC_SECTIONS,
OPTION_NO_GC_SECTIONS,
OPTION_PRINT_GC_SECTIONS,
OPTION_NO_PRINT_GC_SECTIONS,
OPTION_HASH_SIZE,
OPTION_CHECK_SECTIONS,
OPTION_NO_CHECK_SECTIONS,
OPTION_NO_UNDEFINED,
OPTION_INIT,
OPTION_FINI,
OPTION_SECTION_START,
OPTION_UNIQUE,
OPTION_TARGET_HELP,
OPTION_ALLOW_SHLIB_UNDEFINED,
OPTION_NO_ALLOW_SHLIB_UNDEFINED,
OPTION_ALLOW_MULTIPLE_DEFINITION,
OPTION_NO_UNDEFINED_VERSION,
OPTION_DEFAULT_SYMVER,
OPTION_DEFAULT_IMPORTED_SYMVER,
OPTION_DISCARD_NONE,
OPTION_SPARE_DYNAMIC_TAGS,
OPTION_NO_DEFINE_COMMON,
OPTION_NOSTDLIB,
OPTION_NO_OMAGIC,
OPTION_STRIP_DISCARDED,
OPTION_NO_STRIP_DISCARDED,
OPTION_ACCEPT_UNKNOWN_INPUT_ARCH,
OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH,
OPTION_PIE,
OPTION_UNRESOLVED_SYMBOLS,
OPTION_WARN_UNRESOLVED_SYMBOLS,
OPTION_ERROR_UNRESOLVED_SYMBOLS,
OPTION_WARN_SHARED_TEXTREL,
OPTION_WARN_ALTERNATE_EM,
OPTION_REDUCE_MEMORY_OVERHEADS,
#ifdef ENABLE_PLUGINS
OPTION_PLUGIN,
OPTION_PLUGIN_OPT,
#endif /* ENABLE_PLUGINS */
OPTION_DEFAULT_SCRIPT,
OPTION_PRINT_OUTPUT_FORMAT,
OPTION_IGNORE_UNRESOLVED_SYMBOL,
};
 
/* The initial parser states. */
typedef enum input_enum {
input_selected, /* We've set the initial state. */
input_script,
input_mri_script,
input_version_script,
input_dynamic_list,
input_defsym
} input_type;
 
extern input_type parser_input;
 
extern unsigned int lineno;
extern const char *lex_string;
 
/* In ldlex.l. */
extern int yylex (void);
extern void lex_push_file (FILE *, const char *, unsigned int);
extern void lex_redirect (const char *, const char *, unsigned int);
extern void ldlex_script (void);
extern void ldlex_mri_script (void);
extern void ldlex_version_script (void);
extern void ldlex_version_file (void);
extern void ldlex_defsym (void);
extern void ldlex_expression (void);
extern void ldlex_both (void);
extern void ldlex_command (void);
extern void ldlex_popstate (void);
extern const char* ldlex_filename (void);
 
/* In lexsup.c. */
extern int lex_input (void);
extern void lex_unput (int);
#ifndef yywrap
extern int yywrap (void);
#endif
extern void parse_args (unsigned, char **);
 
#endif
/contrib/toolchain/binutils/ld/ldmain.c
0,0 → 1,1480
/* Main program of GNU linker.
Copyright 1991-2013 Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "safe-ctype.h"
#include "libiberty.h"
#include "progress.h"
#include "bfdlink.h"
#include "filenames.h"
 
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
#include "ldwrite.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldfile.h"
#include "ldemul.h"
#include "ldctor.h"
#ifdef ENABLE_PLUGINS
#include "plugin.h"
#include "plugin-api.h"
#include "libbfd.h"
#endif /* ENABLE_PLUGINS */
 
/* Somewhere above, sys/stat.h got included. */
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
 
#include <string.h>
 
#ifdef HAVE_SBRK
#if !HAVE_DECL_SBRK
extern void *sbrk ();
#endif
#endif
 
#ifndef TARGET_SYSTEM_ROOT
#define TARGET_SYSTEM_ROOT ""
#endif
 
/* EXPORTS */
 
FILE *saved_script_handle = NULL;
FILE *previous_script_handle = NULL;
bfd_boolean force_make_executable = FALSE;
 
char *default_target;
const char *output_filename = "a.out";
 
/* Name this program was invoked by. */
char *program_name;
 
/* The prefix for system library directories. */
const char *ld_sysroot;
 
/* The canonical representation of ld_sysroot. */
char * ld_canon_sysroot;
int ld_canon_sysroot_len;
 
/* Set by -G argument, for targets like MIPS ELF. */
int g_switch_value = 8;
 
/* Nonzero means print names of input files as processed. */
bfd_boolean trace_files;
 
/* Nonzero means report actions taken by the linker, and describe the linker script in use. */
bfd_boolean verbose;
 
/* Nonzero means version number was printed, so exit successfully
instead of complaining if no input files are given. */
bfd_boolean version_printed;
 
/* TRUE if we should demangle symbol names. */
bfd_boolean demangling;
 
args_type command_line;
 
ld_config_type config;
 
sort_type sort_section;
 
static const char *get_sysroot
(int, char **);
static char *get_emulation
(int, char **);
static bfd_boolean add_archive_element
(struct bfd_link_info *, bfd *, const char *, bfd **);
static bfd_boolean multiple_definition
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma);
static bfd_boolean multiple_common
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, enum bfd_link_hash_type, bfd_vma);
static bfd_boolean add_to_set
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd_reloc_code_real_type, bfd *, asection *, bfd_vma);
static bfd_boolean constructor_callback
(struct bfd_link_info *, bfd_boolean, const char *, bfd *,
asection *, bfd_vma);
static bfd_boolean warning_callback
(struct bfd_link_info *, const char *, const char *, bfd *,
asection *, bfd_vma);
static void warning_find_reloc
(bfd *, asection *, void *);
static bfd_boolean undefined_symbol
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma,
bfd_boolean);
static bfd_boolean reloc_overflow
(struct bfd_link_info *, struct bfd_link_hash_entry *, const char *,
const char *, bfd_vma, bfd *, asection *, bfd_vma);
static bfd_boolean reloc_dangerous
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
static bfd_boolean unattached_reloc
(struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
static bfd_boolean notice
(struct bfd_link_info *, struct bfd_link_hash_entry *,
bfd *, asection *, bfd_vma, flagword, const char *);
 
static struct bfd_link_callbacks link_callbacks =
{
add_archive_element,
multiple_definition,
multiple_common,
add_to_set,
constructor_callback,
warning_callback,
undefined_symbol,
reloc_overflow,
reloc_dangerous,
unattached_reloc,
notice,
einfo,
info_msg,
minfo,
ldlang_override_segment_assignment
};
 
static bfd_assert_handler_type default_bfd_assert_handler;
 
struct bfd_link_info link_info;
static void
ld_cleanup (void)
{
bfd_cache_close_all ();
#ifdef ENABLE_PLUGINS
plugin_call_cleanup ();
#endif
if (output_filename && delete_output_file_on_failure)
unlink_if_ordinary (output_filename);
}
 
/* If there's a BFD assertion, we'll notice and exit with an error
unless otherwise instructed. */
 
static void
ld_bfd_assert_handler (const char *fmt, const char *bfdver,
const char *file, int line)
{
(*default_bfd_assert_handler) (fmt, bfdver, file, line);
config.make_executable = FALSE;
}
 
static inline void set_cwd(const char* cwd)
{
__asm__ __volatile__(
"int $0x40"
::"a"(30),"b"(1),"c"(cwd));
};
 
 
int
main (int argc, char **argv)
{
char *emulation;
long start_time = get_run_time ();
 
set_cwd("/kolibrios/contrib/toolchain/binutils/ld");
 
 
#ifdef HAVE_SBRK
char *start_sbrk = (char *) sbrk (0);
#endif
 
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
#endif
#if defined (HAVE_SETLOCALE)
setlocale (LC_CTYPE, "");
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
 
program_name = argv[0];
xmalloc_set_program_name (program_name);
 
START_PROGRESS (program_name, 0);
 
expandargv (&argc, &argv);
 
bfd_init ();
 
bfd_set_error_program_name (program_name);
 
/* We want to notice and fail on those nasty BFD assertions which are
likely to signal incorrect output being generated but otherwise may
leave no trace. */
default_bfd_assert_handler = bfd_set_assert_handler (ld_bfd_assert_handler);
 
xatexit (ld_cleanup);
 
/* Set up the sysroot directory. */
ld_sysroot = get_sysroot (argc, argv);
if (*ld_sysroot)
{
if (*TARGET_SYSTEM_ROOT == 0)
{
einfo ("%P%F: this linker was not configured to use sysroots\n");
ld_sysroot = "";
}
else
ld_canon_sysroot = lrealpath (ld_sysroot);
}
if (ld_canon_sysroot)
ld_canon_sysroot_len = strlen (ld_canon_sysroot);
else
ld_canon_sysroot_len = -1;
 
/* Set the default BFD target based on the configured target. Doing
this permits the linker to be configured for a particular target,
and linked against a shared BFD library which was configured for
a different target. The macro TARGET is defined by Makefile. */
if (! bfd_set_default_target (TARGET))
{
einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), TARGET);
xexit (1);
}
 
#if YYDEBUG
{
extern int yydebug;
yydebug = 1;
}
#endif
 
config.build_constructors = TRUE;
config.rpath_separator = ':';
config.split_by_reloc = (unsigned) -1;
config.split_by_file = (bfd_size_type) -1;
config.make_executable = TRUE;
config.magic_demand_paged = TRUE;
config.text_read_only = TRUE;
link_info.disable_target_specific_optimizations = -1;
 
command_line.warn_mismatch = TRUE;
command_line.warn_search_mismatch = TRUE;
command_line.check_section_addresses = -1;
 
/* We initialize DEMANGLING based on the environment variable
COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the
output of the linker, unless COLLECT_NO_DEMANGLE is set in the
environment. Acting the same way here lets us provide the same
interface by default. */
demangling = getenv ("COLLECT_NO_DEMANGLE") == NULL;
 
link_info.allow_undefined_version = TRUE;
link_info.keep_memory = TRUE;
link_info.combreloc = TRUE;
link_info.strip_discarded = TRUE;
link_info.emit_hash = TRUE;
link_info.callbacks = &link_callbacks;
link_info.input_bfds_tail = &link_info.input_bfds;
/* SVR4 linkers seem to set DT_INIT and DT_FINI based on magic _init
and _fini symbols. We are compatible. */
link_info.init_function = "_init";
link_info.fini_function = "_fini";
link_info.relax_pass = 1;
link_info.pei386_auto_import = -1;
link_info.spare_dynamic_tags = 5;
link_info.path_separator = ':';
 
ldfile_add_arch ("");
emulation = get_emulation (argc, argv);
ldemul_choose_mode (emulation);
default_target = ldemul_choose_target (argc, argv);
config.maxpagesize = bfd_emul_get_maxpagesize (default_target);
config.commonpagesize = bfd_emul_get_commonpagesize (default_target);
lang_init ();
ldemul_before_parse ();
lang_has_input_file = FALSE;
parse_args (argc, argv);
 
if (config.hash_table_size != 0)
bfd_hash_set_default_size (config.hash_table_size);
 
#ifdef ENABLE_PLUGINS
/* Now all the plugin arguments have been gathered, we can load them. */
plugin_load_plugins ();
#endif /* ENABLE_PLUGINS */
 
ldemul_set_symbols ();
 
/* If we have not already opened and parsed a linker script,
try the default script from command line first. */
if (saved_script_handle == NULL
&& command_line.default_script != NULL)
{
ldfile_open_command_file (command_line.default_script);
parser_input = input_script;
yyparse ();
}
 
/* If we have not already opened and parsed a linker script
read the emulation's appropriate default script. */
if (saved_script_handle == NULL)
{
int isfile;
char *s = ldemul_get_script (&isfile);
 
if (isfile)
ldfile_open_default_command_file (s);
else
{
lex_string = s;
lex_redirect (s, _("built in linker script"), 1);
}
parser_input = input_script;
yyparse ();
lex_string = NULL;
}
 
if (verbose)
{
if (saved_script_handle)
info_msg (_("using external linker script:"));
else
info_msg (_("using internal linker script:"));
info_msg ("\n==================================================\n");
 
if (saved_script_handle)
{
static const int ld_bufsz = 8193;
size_t n;
char *buf = (char *) xmalloc (ld_bufsz);
 
rewind (saved_script_handle);
while ((n = fread (buf, 1, ld_bufsz - 1, saved_script_handle)) > 0)
{
buf[n] = 0;
info_msg (buf);
}
rewind (saved_script_handle);
free (buf);
}
else
{
int isfile;
 
info_msg (ldemul_get_script (&isfile));
}
 
info_msg ("\n==================================================\n");
}
 
if (command_line.print_output_format)
info_msg ("%s\n", lang_get_output_target ());
 
lang_final ();
 
if (!lang_has_input_file)
{
if (version_printed || command_line.print_output_format)
xexit (0);
einfo (_("%P%F: no input files\n"));
}
 
if (trace_files)
info_msg (_("%P: mode %s\n"), emulation);
 
ldemul_after_parse ();
 
if (config.map_filename)
{
if (strcmp (config.map_filename, "-") == 0)
{
config.map_file = stdout;
}
else
{
config.map_file = fopen (config.map_filename, FOPEN_WT);
if (config.map_file == (FILE *) NULL)
{
bfd_set_error (bfd_error_system_call);
einfo (_("%P%F: cannot open map file %s: %E\n"),
config.map_filename);
}
}
}
 
lang_process ();
 
/* Print error messages for any missing symbols, for any warning
symbols, and possibly multiple definitions. */
if (link_info.relocatable)
link_info.output_bfd->flags &= ~EXEC_P;
else
link_info.output_bfd->flags |= EXEC_P;
 
ldwrite ();
 
if (config.map_file != NULL)
lang_map ();
if (command_line.cref)
output_cref (config.map_file != NULL ? config.map_file : stdout);
if (nocrossref_list != NULL)
check_nocrossrefs ();
 
lang_finish ();
 
/* Even if we're producing relocatable output, some non-fatal errors should
be reported in the exit status. (What non-fatal errors, if any, do we
want to ignore for relocatable output?) */
if (!config.make_executable && !force_make_executable)
{
if (trace_files)
einfo (_("%P: link errors found, deleting executable `%s'\n"),
output_filename);
 
/* The file will be removed by ld_cleanup. */
xexit (1);
}
else
{
if (! bfd_close (link_info.output_bfd))
einfo (_("%F%B: final close failed: %E\n"), link_info.output_bfd);
 
/* If the --force-exe-suffix is enabled, and we're making an
executable file and it doesn't end in .exe, copy it to one
which does. */
if (! link_info.relocatable && command_line.force_exe_suffix)
{
int len = strlen (output_filename);
 
if (len < 4
|| (strcasecmp (output_filename + len - 4, ".exe") != 0
&& strcasecmp (output_filename + len - 4, ".dll") != 0))
{
FILE *src;
FILE *dst;
const int bsize = 4096;
char *buf = (char *) xmalloc (bsize);
int l;
char *dst_name = (char *) xmalloc (len + 5);
 
strcpy (dst_name, output_filename);
strcat (dst_name, ".exe");
src = fopen (output_filename, FOPEN_RB);
dst = fopen (dst_name, FOPEN_WB);
 
if (!src)
einfo (_("%X%P: unable to open for source of copy `%s'\n"),
output_filename);
if (!dst)
einfo (_("%X%P: unable to open for destination of copy `%s'\n"),
dst_name);
while ((l = fread (buf, 1, bsize, src)) > 0)
{
int done = fwrite (buf, 1, l, dst);
 
if (done != l)
einfo (_("%P: Error writing file `%s'\n"), dst_name);
}
 
fclose (src);
if (fclose (dst) == EOF)
einfo (_("%P: Error closing file `%s'\n"), dst_name);
free (dst_name);
free (buf);
}
}
}
 
END_PROGRESS (program_name);
 
if (config.stats)
{
#ifdef HAVE_SBRK
char *lim = (char *) sbrk (0);
#endif
long run_time = get_run_time () - start_time;
 
fflush (stdout);
fprintf (stderr, _("%s: total time in link: %ld.%06ld\n"),
program_name, run_time / 1000000, run_time % 1000000);
#ifdef HAVE_SBRK
fprintf (stderr, _("%s: data size %ld\n"), program_name,
(long) (lim - start_sbrk));
#endif
fflush (stderr);
}
 
/* Prevent ld_cleanup from doing anything, after a successful link. */
output_filename = NULL;
 
xexit (0);
return 0;
}
 
/* If the configured sysroot is relocatable, try relocating it based on
default prefix FROM. Return the relocated directory if it exists,
otherwise return null. */
 
static char *
get_relative_sysroot (const char *from ATTRIBUTE_UNUSED)
{
#ifdef TARGET_SYSTEM_ROOT_RELOCATABLE
char *path;
struct stat s;
 
path = make_relative_prefix (program_name, from, TARGET_SYSTEM_ROOT);
if (path)
{
if (stat (path, &s) == 0 && S_ISDIR (s.st_mode))
return path;
free (path);
}
#endif
return 0;
}
 
/* Return the sysroot directory. Return "" if no sysroot is being used. */
 
static const char *
get_sysroot (int argc, char **argv)
{
int i;
const char *path;
 
for (i = 1; i < argc; i++)
if (CONST_STRNEQ (argv[i], "--sysroot="))
return argv[i] + strlen ("--sysroot=");
 
path = get_relative_sysroot (BINDIR);
if (path)
return path;
 
path = get_relative_sysroot (TOOLBINDIR);
if (path)
return path;
 
return TARGET_SYSTEM_ROOT;
}
 
/* We need to find any explicitly given emulation in order to initialize the
state that's needed by the lex&yacc argument parser (parse_args). */
 
static char *
get_emulation (int argc, char **argv)
{
char *emulation;
int i;
 
emulation = getenv (EMULATION_ENVIRON);
if (emulation == NULL)
emulation = DEFAULT_EMULATION;
 
for (i = 1; i < argc; i++)
{
if (CONST_STRNEQ (argv[i], "-m"))
{
if (argv[i][2] == '\0')
{
/* -m EMUL */
if (i < argc - 1)
{
emulation = argv[i + 1];
i++;
}
else
einfo (_("%P%F: missing argument to -m\n"));
}
else if (strcmp (argv[i], "-mips1") == 0
|| strcmp (argv[i], "-mips2") == 0
|| strcmp (argv[i], "-mips3") == 0
|| strcmp (argv[i], "-mips4") == 0
|| strcmp (argv[i], "-mips5") == 0
|| strcmp (argv[i], "-mips32") == 0
|| strcmp (argv[i], "-mips32r2") == 0
|| strcmp (argv[i], "-mips64") == 0
|| strcmp (argv[i], "-mips64r2") == 0)
{
/* FIXME: The arguments -mips1, -mips2, -mips3, etc. are
passed to the linker by some MIPS compilers. They
generally tell the linker to use a slightly different
library path. Perhaps someday these should be
implemented as emulations; until then, we just ignore
the arguments and hope that nobody ever creates
emulations named ips1, ips2 or ips3. */
}
else if (strcmp (argv[i], "-m486") == 0)
{
/* FIXME: The argument -m486 is passed to the linker on
some Linux systems. Hope that nobody creates an
emulation named 486. */
}
else
{
/* -mEMUL */
emulation = &argv[i][2];
}
}
}
 
return emulation;
}
 
void
add_ysym (const char *name)
{
if (link_info.notice_hash == NULL)
{
link_info.notice_hash =
(struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init_n (link_info.notice_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
}
 
if (bfd_hash_lookup (link_info.notice_hash, name, TRUE, TRUE) == NULL)
einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
}
 
void
add_ignoresym (struct bfd_link_info *info, const char *name)
{
if (info->ignore_hash == NULL)
{
info->ignore_hash = xmalloc (sizeof (struct bfd_hash_table));
if (! bfd_hash_table_init_n (info->ignore_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
}
 
if (bfd_hash_lookup (info->ignore_hash, name, TRUE, TRUE) == NULL)
einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
}
 
/* Record a symbol to be wrapped, from the --wrap option. */
 
void
add_wrap (const char *name)
{
if (link_info.wrap_hash == NULL)
{
link_info.wrap_hash =
(struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init_n (link_info.wrap_hash,
bfd_hash_newfunc,
sizeof (struct bfd_hash_entry),
61))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
}
 
if (bfd_hash_lookup (link_info.wrap_hash, name, TRUE, TRUE) == NULL)
einfo (_("%P%F: bfd_hash_lookup failed: %E\n"));
}
 
/* Handle the -retain-symbols-file option. */
 
void
add_keepsyms_file (const char *filename)
{
FILE *file;
char *buf;
size_t bufsize;
int c;
 
if (link_info.strip == strip_some)
einfo (_("%X%P: error: duplicate retain-symbols-file\n"));
 
file = fopen (filename, "r");
if (file == NULL)
{
bfd_set_error (bfd_error_system_call);
einfo ("%X%P: %s: %E\n", filename);
return;
}
 
link_info.keep_hash = (struct bfd_hash_table *)
xmalloc (sizeof (struct bfd_hash_table));
if (!bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc,
sizeof (struct bfd_hash_entry)))
einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
 
bufsize = 100;
buf = (char *) xmalloc (bufsize);
 
c = getc (file);
while (c != EOF)
{
while (ISSPACE (c))
c = getc (file);
 
if (c != EOF)
{
size_t len = 0;
 
while (! ISSPACE (c) && c != EOF)
{
buf[len] = c;
++len;
if (len >= bufsize)
{
bufsize *= 2;
buf = (char *) xrealloc (buf, bufsize);
}
c = getc (file);
}
 
buf[len] = '\0';
 
if (bfd_hash_lookup (link_info.keep_hash, buf, TRUE, TRUE) == NULL)
einfo (_("%P%F: bfd_hash_lookup for insertion failed: %E\n"));
}
}
 
if (link_info.strip != strip_none)
einfo (_("%P: `-retain-symbols-file' overrides `-s' and `-S'\n"));
 
free (buf);
link_info.strip = strip_some;
}
/* Callbacks from the BFD linker routines. */
 
/* This is called when BFD has decided to include an archive member in
a link. */
 
static bfd_boolean
add_archive_element (struct bfd_link_info *info,
bfd *abfd,
const char *name,
bfd **subsbfd ATTRIBUTE_UNUSED)
{
lang_input_statement_type *input;
lang_input_statement_type orig_input;
 
input = (lang_input_statement_type *)
xcalloc (1, sizeof (lang_input_statement_type));
input->filename = abfd->filename;
input->local_sym_name = abfd->filename;
input->the_bfd = abfd;
 
/* Save the original data for trace files/tries below, as plugins
(if enabled) may possibly alter it to point to a replacement
BFD, but we still want to output the original BFD filename. */
orig_input = *input;
#ifdef ENABLE_PLUGINS
if (plugin_active_plugins_p () && !no_more_claiming)
{
/* We must offer this archive member to the plugins to claim. */
const char *filename = (bfd_my_archive (abfd) != NULL
? bfd_my_archive (abfd)->filename : abfd->filename);
int fd = open (filename, O_RDONLY | O_BINARY);
if (fd >= 0)
{
struct ld_plugin_input_file file;
 
/* Offset and filesize must refer to the individual archive
member, not the whole file, and must exclude the header.
Fortunately for us, that is how the data is stored in the
origin field of the bfd and in the arelt_data. */
file.name = filename;
file.offset = abfd->origin;
file.filesize = arelt_size (abfd);
file.fd = fd;
plugin_maybe_claim (&file, input);
if (input->flags.claimed)
{
input->flags.claim_archive = TRUE;
*subsbfd = input->the_bfd;
}
}
}
#endif /* ENABLE_PLUGINS */
 
ldlang_add_file (input);
 
if (config.map_file != NULL)
{
static bfd_boolean header_printed;
struct bfd_link_hash_entry *h;
bfd *from;
int len;
 
h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
 
if (h == NULL)
from = NULL;
else
{
switch (h->type)
{
default:
from = NULL;
break;
 
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
from = h->u.def.section->owner;
break;
 
case bfd_link_hash_undefined:
case bfd_link_hash_undefweak:
from = h->u.undef.abfd;
break;
 
case bfd_link_hash_common:
from = h->u.c.p->section->owner;
break;
}
}
 
if (! header_printed)
{
char buf[100];
 
sprintf (buf, _("Archive member included because of file (symbol)\n\n"));
minfo ("%s", buf);
header_printed = TRUE;
}
 
if (bfd_my_archive (abfd) == NULL)
{
minfo ("%s", bfd_get_filename (abfd));
len = strlen (bfd_get_filename (abfd));
}
else
{
minfo ("%s(%s)", bfd_get_filename (bfd_my_archive (abfd)),
bfd_get_filename (abfd));
len = (strlen (bfd_get_filename (bfd_my_archive (abfd)))
+ strlen (bfd_get_filename (abfd))
+ 2);
}
 
if (len >= 29)
{
print_nl ();
len = 0;
}
while (len < 30)
{
print_space ();
++len;
}
 
if (from != NULL)
minfo ("%B ", from);
if (h != NULL)
minfo ("(%T)\n", h->root.string);
else
minfo ("(%s)\n", name);
}
 
if (trace_files || verbose)
info_msg ("%I\n", &orig_input);
return TRUE;
}
 
/* This is called when BFD has discovered a symbol which is defined
multiple times. */
 
static bfd_boolean
multiple_definition (struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
bfd *nbfd,
asection *nsec,
bfd_vma nval)
{
const char *name;
bfd *obfd;
asection *osec;
bfd_vma oval;
 
if (info->allow_multiple_definition)
return TRUE;
 
switch (h->type)
{
case bfd_link_hash_defined:
osec = h->u.def.section;
oval = h->u.def.value;
obfd = h->u.def.section->owner;
break;
case bfd_link_hash_indirect:
osec = bfd_ind_section_ptr;
oval = 0;
obfd = NULL;
break;
default:
abort ();
}
 
/* Ignore a redefinition of an absolute symbol to the
same value; it's harmless. */
if (h->type == bfd_link_hash_defined
&& bfd_is_abs_section (osec)
&& bfd_is_abs_section (nsec)
&& nval == oval)
return TRUE;
 
/* If either section has the output_section field set to
bfd_abs_section_ptr, it means that the section is being
discarded, and this is not really a multiple definition at all.
FIXME: It would be cleaner to somehow ignore symbols defined in
sections which are being discarded. */
if ((osec->output_section != NULL
&& ! bfd_is_abs_section (osec)
&& bfd_is_abs_section (osec->output_section))
|| (nsec->output_section != NULL
&& ! bfd_is_abs_section (nsec)
&& bfd_is_abs_section (nsec->output_section)))
return TRUE;
 
name = h->root.string;
if (nbfd == NULL)
{
nbfd = obfd;
nsec = osec;
nval = oval;
obfd = NULL;
}
einfo (_("%X%C: multiple definition of `%T'\n"),
nbfd, nsec, nval, name);
if (obfd != NULL)
einfo (_("%D: first defined here\n"), obfd, osec, oval);
 
if (RELAXATION_ENABLED_BY_USER)
{
einfo (_("%P: Disabling relaxation: it will not work with multiple definitions\n"));
DISABLE_RELAXATION;
}
 
return TRUE;
}
 
/* This is called when there is a definition of a common symbol, or
when a common symbol is found for a symbol that is already defined,
or when two common symbols are found. We only do something if
-warn-common was used. */
 
static bfd_boolean
multiple_common (struct bfd_link_info *info ATTRIBUTE_UNUSED,
struct bfd_link_hash_entry *h,
bfd *nbfd,
enum bfd_link_hash_type ntype,
bfd_vma nsize)
{
const char *name;
bfd *obfd;
enum bfd_link_hash_type otype;
bfd_vma osize;
 
if (!config.warn_common)
return TRUE;
 
name = h->root.string;
otype = h->type;
if (otype == bfd_link_hash_common)
{
obfd = h->u.c.p->section->owner;
osize = h->u.c.size;
}
else if (otype == bfd_link_hash_defined
|| otype == bfd_link_hash_defweak)
{
obfd = h->u.def.section->owner;
osize = 0;
}
else
{
/* FIXME: It would nice if we could report the BFD which defined
an indirect symbol, but we don't have anywhere to store the
information. */
obfd = NULL;
osize = 0;
}
 
if (ntype == bfd_link_hash_defined
|| ntype == bfd_link_hash_defweak
|| ntype == bfd_link_hash_indirect)
{
ASSERT (otype == bfd_link_hash_common);
einfo (_("%B: warning: definition of `%T' overriding common\n"),
nbfd, name);
if (obfd != NULL)
einfo (_("%B: warning: common is here\n"), obfd);
}
else if (otype == bfd_link_hash_defined
|| otype == bfd_link_hash_defweak
|| otype == bfd_link_hash_indirect)
{
ASSERT (ntype == bfd_link_hash_common);
einfo (_("%B: warning: common of `%T' overridden by definition\n"),
nbfd, name);
if (obfd != NULL)
einfo (_("%B: warning: defined here\n"), obfd);
}
else
{
ASSERT (otype == bfd_link_hash_common && ntype == bfd_link_hash_common);
if (osize > nsize)
{
einfo (_("%B: warning: common of `%T' overridden by larger common\n"),
nbfd, name);
if (obfd != NULL)
einfo (_("%B: warning: larger common is here\n"), obfd);
}
else if (nsize > osize)
{
einfo (_("%B: warning: common of `%T' overriding smaller common\n"),
nbfd, name);
if (obfd != NULL)
einfo (_("%B: warning: smaller common is here\n"), obfd);
}
else
{
einfo (_("%B: warning: multiple common of `%T'\n"), nbfd, name);
if (obfd != NULL)
einfo (_("%B: warning: previous common is here\n"), obfd);
}
}
 
return TRUE;
}
 
/* This is called when BFD has discovered a set element. H is the
entry in the linker hash table for the set. SECTION and VALUE
represent a value which should be added to the set. */
 
static bfd_boolean
add_to_set (struct bfd_link_info *info ATTRIBUTE_UNUSED,
struct bfd_link_hash_entry *h,
bfd_reloc_code_real_type reloc,
bfd *abfd,
asection *section,
bfd_vma value)
{
if (config.warn_constructors)
einfo (_("%P: warning: global constructor %s used\n"),
h->root.string);
 
if (! config.build_constructors)
return TRUE;
 
ldctor_add_set_entry (h, reloc, NULL, section, value);
 
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = abfd;
/* We don't call bfd_link_add_undef to add this to the list of
undefined symbols because we are going to define it
ourselves. */
}
 
return TRUE;
}
 
/* This is called when BFD has discovered a constructor. This is only
called for some object file formats--those which do not handle
constructors in some more clever fashion. This is similar to
adding an element to a set, but less general. */
 
static bfd_boolean
constructor_callback (struct bfd_link_info *info,
bfd_boolean constructor,
const char *name,
bfd *abfd,
asection *section,
bfd_vma value)
{
char *s;
struct bfd_link_hash_entry *h;
char set_name[1 + sizeof "__CTOR_LIST__"];
 
if (config.warn_constructors)
einfo (_("%P: warning: global constructor %s used\n"), name);
 
if (! config.build_constructors)
return TRUE;
 
/* Ensure that BFD_RELOC_CTOR exists now, so that we can give a
useful error message. */
if (bfd_reloc_type_lookup (info->output_bfd, BFD_RELOC_CTOR) == NULL
&& (info->relocatable
|| bfd_reloc_type_lookup (abfd, BFD_RELOC_CTOR) == NULL))
einfo (_("%P%F: BFD backend error: BFD_RELOC_CTOR unsupported\n"));
 
s = set_name;
if (bfd_get_symbol_leading_char (abfd) != '\0')
*s++ = bfd_get_symbol_leading_char (abfd);
if (constructor)
strcpy (s, "__CTOR_LIST__");
else
strcpy (s, "__DTOR_LIST__");
 
h = bfd_link_hash_lookup (info->hash, set_name, TRUE, TRUE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
if (h->type == bfd_link_hash_new)
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = abfd;
/* We don't call bfd_link_add_undef to add this to the list of
undefined symbols because we are going to define it
ourselves. */
}
 
ldctor_add_set_entry (h, BFD_RELOC_CTOR, name, section, value);
return TRUE;
}
 
/* A structure used by warning_callback to pass information through
bfd_map_over_sections. */
 
struct warning_callback_info
{
bfd_boolean found;
const char *warning;
const char *symbol;
asymbol **asymbols;
};
 
/* This is called when there is a reference to a warning symbol. */
 
static bfd_boolean
warning_callback (struct bfd_link_info *info ATTRIBUTE_UNUSED,
const char *warning,
const char *symbol,
bfd *abfd,
asection *section,
bfd_vma address)
{
/* This is a hack to support warn_multiple_gp. FIXME: This should
have a cleaner interface, but what? */
if (! config.warn_multiple_gp
&& strcmp (warning, "using multiple gp values") == 0)
return TRUE;
 
if (section != NULL)
einfo ("%C: %s%s\n", abfd, section, address, _("warning: "), warning);
else if (abfd == NULL)
einfo ("%P: %s%s\n", _("warning: "), warning);
else if (symbol == NULL)
einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
else
{
struct warning_callback_info cinfo;
 
/* Look through the relocs to see if we can find a plausible
address. */
 
if (!bfd_generic_link_read_symbols (abfd))
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
 
cinfo.found = FALSE;
cinfo.warning = warning;
cinfo.symbol = symbol;
cinfo.asymbols = bfd_get_outsymbols (abfd);
bfd_map_over_sections (abfd, warning_find_reloc, &cinfo);
 
if (! cinfo.found)
einfo ("%B: %s%s\n", abfd, _("warning: "), warning);
}
 
return TRUE;
}
 
/* This is called by warning_callback for each section. It checks the
relocs of the section to see if it can find a reference to the
symbol which triggered the warning. If it can, it uses the reloc
to give an error message with a file and line number. */
 
static void
warning_find_reloc (bfd *abfd, asection *sec, void *iarg)
{
struct warning_callback_info *info = (struct warning_callback_info *) iarg;
long relsize;
arelent **relpp;
long relcount;
arelent **p, **pend;
 
if (info->found)
return;
 
relsize = bfd_get_reloc_upper_bound (abfd, sec);
if (relsize < 0)
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
if (relsize == 0)
return;
 
relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols);
if (relcount < 0)
einfo (_("%B%F: could not read relocs: %E\n"), abfd);
 
p = relpp;
pend = p + relcount;
for (; p < pend && *p != NULL; p++)
{
arelent *q = *p;
 
if (q->sym_ptr_ptr != NULL
&& *q->sym_ptr_ptr != NULL
&& strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), info->symbol) == 0)
{
/* We found a reloc for the symbol we are looking for. */
einfo ("%C: %s%s\n", abfd, sec, q->address, _("warning: "),
info->warning);
info->found = TRUE;
break;
}
}
 
free (relpp);
}
 
/* This is called when an undefined symbol is found. */
 
static bfd_boolean
undefined_symbol (struct bfd_link_info *info,
const char *name,
bfd *abfd,
asection *section,
bfd_vma address,
bfd_boolean error)
{
static char *error_name;
static unsigned int error_count;
 
#define MAX_ERRORS_IN_A_ROW 5
 
if (info->ignore_hash != NULL
&& bfd_hash_lookup (info->ignore_hash, name, FALSE, FALSE) != NULL)
return TRUE;
 
if (config.warn_once)
{
/* Only warn once about a particular undefined symbol. */
add_ignoresym (info, name);
}
 
/* We never print more than a reasonable number of errors in a row
for a single symbol. */
if (error_name != NULL
&& strcmp (name, error_name) == 0)
++error_count;
else
{
error_count = 0;
if (error_name != NULL)
free (error_name);
error_name = xstrdup (name);
}
 
if (section != NULL)
{
if (error_count < MAX_ERRORS_IN_A_ROW)
{
if (error)
einfo (_("%X%C: undefined reference to `%T'\n"),
abfd, section, address, name);
else
einfo (_("%C: warning: undefined reference to `%T'\n"),
abfd, section, address, name);
}
else if (error_count == MAX_ERRORS_IN_A_ROW)
{
if (error)
einfo (_("%X%D: more undefined references to `%T' follow\n"),
abfd, section, address, name);
else
einfo (_("%D: warning: more undefined references to `%T' follow\n"),
abfd, section, address, name);
}
else if (error)
einfo ("%X");
}
else
{
if (error_count < MAX_ERRORS_IN_A_ROW)
{
if (error)
einfo (_("%X%B: undefined reference to `%T'\n"),
abfd, name);
else
einfo (_("%B: warning: undefined reference to `%T'\n"),
abfd, name);
}
else if (error_count == MAX_ERRORS_IN_A_ROW)
{
if (error)
einfo (_("%X%B: more undefined references to `%T' follow\n"),
abfd, name);
else
einfo (_("%B: warning: more undefined references to `%T' follow\n"),
abfd, name);
}
else if (error)
einfo ("%X");
}
 
return TRUE;
}
 
/* Counter to limit the number of relocation overflow error messages
to print. Errors are printed as it is decremented. When it's
called and the counter is zero, a final message is printed
indicating more relocations were omitted. When it gets to -1, no
such errors are printed. If it's initially set to a value less
than -1, all such errors will be printed (--verbose does this). */
 
int overflow_cutoff_limit = 10;
 
/* This is called when a reloc overflows. */
 
static bfd_boolean
reloc_overflow (struct bfd_link_info *info,
struct bfd_link_hash_entry *entry,
const char *name,
const char *reloc_name,
bfd_vma addend,
bfd *abfd,
asection *section,
bfd_vma address)
{
if (overflow_cutoff_limit == -1)
return TRUE;
 
einfo ("%X%H:", abfd, section, address);
 
if (overflow_cutoff_limit >= 0
&& overflow_cutoff_limit-- == 0)
{
einfo (_(" additional relocation overflows omitted from the output\n"));
return TRUE;
}
 
if (entry)
{
while (entry->type == bfd_link_hash_indirect
|| entry->type == bfd_link_hash_warning)
entry = entry->u.i.link;
switch (entry->type)
{
case bfd_link_hash_undefined:
case bfd_link_hash_undefweak:
einfo (_(" relocation truncated to fit: %s against undefined symbol `%T'"),
reloc_name, entry->root.string);
break;
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
einfo (_(" relocation truncated to fit: %s against symbol `%T' defined in %A section in %B"),
reloc_name, entry->root.string,
entry->u.def.section,
entry->u.def.section == bfd_abs_section_ptr
? info->output_bfd : entry->u.def.section->owner);
break;
default:
abort ();
break;
}
}
else
einfo (_(" relocation truncated to fit: %s against `%T'"),
reloc_name, name);
if (addend != 0)
einfo ("+%v", addend);
einfo ("\n");
return TRUE;
}
 
/* This is called when a dangerous relocation is made. */
 
static bfd_boolean
reloc_dangerous (struct bfd_link_info *info ATTRIBUTE_UNUSED,
const char *message,
bfd *abfd,
asection *section,
bfd_vma address)
{
einfo (_("%X%H: dangerous relocation: %s\n"),
abfd, section, address, message);
return TRUE;
}
 
/* This is called when a reloc is being generated attached to a symbol
that is not being output. */
 
static bfd_boolean
unattached_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
const char *name,
bfd *abfd,
asection *section,
bfd_vma address)
{
einfo (_("%X%H: reloc refers to symbol `%T' which is not being output\n"),
abfd, section, address, name);
return TRUE;
}
 
/* This is called if link_info.notice_all is set, or when a symbol in
link_info.notice_hash is found. Symbols are put in notice_hash
using the -y option, while notice_all is set if the --cref option
has been supplied, or if there are any NOCROSSREFS sections in the
linker script; and if plugins are active, since they need to monitor
all references from non-IR files. */
 
static bfd_boolean
notice (struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
bfd_vma value,
flagword flags ATTRIBUTE_UNUSED,
const char *string ATTRIBUTE_UNUSED)
{
const char *name;
 
if (h == NULL)
{
if (command_line.cref || nocrossref_list != NULL)
return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value);
return TRUE;
}
 
name = h->root.string;
if (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
{
if (bfd_is_und_section (section))
einfo ("%B: reference to %s\n", abfd, name);
else
einfo ("%B: definition of %s\n", abfd, name);
}
 
if (command_line.cref || nocrossref_list != NULL)
add_cref (name, abfd, section, value);
 
return TRUE;
}
/contrib/toolchain/binutils/ld/ldmain.h
0,0 → 1,62
/* ldmain.h -
Copyright 1991-2013 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDMAIN_H
#define LDMAIN_H
 
extern char *program_name;
extern const char *ld_sysroot;
extern char *ld_canon_sysroot;
extern int ld_canon_sysroot_len;
extern FILE *saved_script_handle;
extern FILE *previous_script_handle;
extern bfd_boolean force_make_executable;
extern char *default_target;
extern bfd_boolean trace_files;
extern bfd_boolean verbose;
extern bfd_boolean version_printed;
extern bfd_boolean demangling;
extern int g_switch_value;
extern const char *output_filename;
extern struct bfd_link_info link_info;
extern int overflow_cutoff_limit;
 
#define RELAXATION_DISABLED_BY_DEFAULT \
(link_info.disable_target_specific_optimizations < 0)
#define RELAXATION_DISABLED_BY_USER \
(link_info.disable_target_specific_optimizations > 1)
#define RELAXATION_ENABLED \
(link_info.disable_target_specific_optimizations == 0 \
|| link_info.disable_target_specific_optimizations == 1)
#define RELAXATION_ENABLED_BY_USER \
(link_info.disable_target_specific_optimizations == 0)
#define TARGET_ENABLE_RELAXATION \
do { link_info.disable_target_specific_optimizations = 1; } while (0)
#define DISABLE_RELAXATION \
do { link_info.disable_target_specific_optimizations = 2; } while (0)
#define ENABLE_RELAXATION \
do { link_info.disable_target_specific_optimizations = 0; } while (0)
 
extern void add_ysym (const char *);
extern void add_wrap (const char *);
extern void add_ignoresym (struct bfd_link_info *, const char *);
extern void add_keepsyms_file (const char *);
 
#endif
/contrib/toolchain/binutils/ld/ldmisc.c
0,0 → 1,530
/* ldmisc.c
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012, 2013
Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libiberty.h"
#include "filenames.h"
#include "demangle.h"
#include <stdarg.h>
#include "ld.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldmain.h"
#include "ldfile.h"
#include "elf-bfd.h"
 
/*
%% literal %
%A section name from a section
%B filename from a bfd
%C clever filename:linenumber with function
%D like %C, but no function name
%E current bfd error or errno
%F error is fatal
%G like %D, but only function name
%H like %C but in addition emit section+offset
%I filename from a lang_input_statement_type
%P print program name
%R info about a relent
%S print script file and linenumber from etree_type.
%T symbol name
%V hex bfd_vma
%W hex bfd_vma with 0x with no leading zeros taking up 8 spaces
%X no object output, fail return
%d integer, like printf
%ld long, like printf
%lu unsigned long, like printf
%p native (host) void* pointer, like printf
%s arbitrary string, like printf
%u integer, like printf
%v hex bfd_vma, no leading zeros
*/
 
void
vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning)
{
bfd_boolean fatal = FALSE;
 
while (*fmt != '\0')
{
const char *str = fmt;
while (*fmt != '%' && *fmt != '\0')
fmt++;
if (fmt != str)
if (fwrite (str, 1, fmt - str, fp))
{
/* Ignore. */
}
 
if (*fmt == '%')
{
fmt++;
switch (*fmt++)
{
case '%':
/* literal % */
putc ('%', fp);
break;
 
case 'X':
/* no object output, fail return */
config.make_executable = FALSE;
break;
 
case 'V':
/* hex bfd_vma */
{
bfd_vma value = va_arg (arg, bfd_vma);
fprintf_vma (fp, value);
}
break;
 
case 'v':
/* hex bfd_vma, no leading zeros */
{
char buf[100];
char *p = buf;
bfd_vma value = va_arg (arg, bfd_vma);
sprintf_vma (p, value);
while (*p == '0')
p++;
if (!*p)
p--;
fputs (p, fp);
}
break;
 
case 'W':
/* hex bfd_vma with 0x with no leading zeroes taking up
8 spaces. */
{
char buf[100];
bfd_vma value;
char *p;
int len;
 
value = va_arg (arg, bfd_vma);
sprintf_vma (buf, value);
for (p = buf; *p == '0'; ++p)
;
if (*p == '\0')
--p;
len = strlen (p);
while (len < 8)
{
putc (' ', fp);
++len;
}
fprintf (fp, "0x%s", p);
}
break;
 
case 'T':
/* Symbol name. */
{
const char *name = va_arg (arg, const char *);
 
if (name == NULL || *name == 0)
{
fprintf (fp, _("no symbol"));
break;
}
else if (demangling)
{
char *demangled;
 
demangled = bfd_demangle (link_info.output_bfd, name,
DMGL_ANSI | DMGL_PARAMS);
if (demangled != NULL)
{
fprintf (fp, "%s", demangled);
free (demangled);
break;
}
}
fprintf (fp, "%s", name);
}
break;
 
case 'A':
/* section name from a section */
{
asection *sec = va_arg (arg, asection *);
bfd *abfd = sec->owner;
const char *group = NULL;
struct coff_comdat_info *ci;
 
fprintf (fp, "%s", sec->name);
if (abfd != NULL
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& elf_next_in_group (sec) != NULL
&& (sec->flags & SEC_GROUP) == 0)
group = elf_group_name (sec);
else if (abfd != NULL
&& bfd_get_flavour (abfd) == bfd_target_coff_flavour
&& (ci = bfd_coff_get_comdat_section (sec->owner,
sec)) != NULL)
group = ci->name;
if (group != NULL)
fprintf (fp, "[%s]", group);
}
break;
 
case 'B':
/* filename from a bfd */
{
bfd *abfd = va_arg (arg, bfd *);
 
if (abfd == NULL)
fprintf (fp, "%s generated", program_name);
else if (abfd->my_archive)
fprintf (fp, "%s(%s)", abfd->my_archive->filename,
abfd->filename);
else
fprintf (fp, "%s", abfd->filename);
}
break;
 
case 'F':
/* Error is fatal. */
fatal = TRUE;
break;
 
case 'P':
/* Print program name. */
fprintf (fp, "%s", program_name);
break;
 
case 'E':
/* current bfd error or errno */
fprintf (fp, "%s", bfd_errmsg (bfd_get_error ()));
break;
 
case 'I':
/* filename from a lang_input_statement_type */
{
lang_input_statement_type *i;
 
i = va_arg (arg, lang_input_statement_type *);
if (bfd_my_archive (i->the_bfd) != NULL)
fprintf (fp, "(%s)",
bfd_get_filename (bfd_my_archive (i->the_bfd)));
fprintf (fp, "%s", i->local_sym_name);
if (bfd_my_archive (i->the_bfd) == NULL
&& filename_cmp (i->local_sym_name, i->filename) != 0)
fprintf (fp, " (%s)", i->filename);
}
break;
 
case 'S':
/* Print script file and linenumber. */
{
etree_type node;
etree_type *tp = va_arg (arg, etree_type *);
 
if (tp == NULL)
{
tp = &node;
tp->type.filename = ldlex_filename ();
tp->type.lineno = lineno;
}
if (tp->type.filename != NULL)
fprintf (fp, "%s:%u", tp->type.filename, tp->type.lineno);
}
break;
 
case 'R':
/* Print all that's interesting about a relent. */
{
arelent *relent = va_arg (arg, arelent *);
 
lfinfo (fp, "%s+0x%v (type %s)",
(*(relent->sym_ptr_ptr))->name,
relent->addend,
relent->howto->name);
}
break;
 
case 'C':
case 'D':
case 'G':
case 'H':
/* Clever filename:linenumber with function name if possible.
The arguments are a BFD, a section, and an offset. */
{
static bfd *last_bfd;
static char *last_file = NULL;
static char *last_function = NULL;
bfd *abfd;
asection *section;
bfd_vma offset;
asymbol **asymbols = NULL;
const char *filename;
const char *functionname;
unsigned int linenumber;
bfd_boolean discard_last;
bfd_boolean done;
 
abfd = va_arg (arg, bfd *);
section = va_arg (arg, asection *);
offset = va_arg (arg, bfd_vma);
 
if (abfd != NULL)
{
if (!bfd_generic_link_read_symbols (abfd))
einfo (_("%B%F: could not read symbols: %E\n"), abfd);
 
asymbols = bfd_get_outsymbols (abfd);
}
 
/* The GNU Coding Standard requires that error messages
be of the form:
 
source-file-name:lineno: message
 
We do not always have a line number available so if
we cannot find them we print out the section name and
offset instead. */
discard_last = TRUE;
if (abfd != NULL
&& bfd_find_nearest_line (abfd, section, asymbols, offset,
&filename, &functionname,
&linenumber))
{
if (functionname != NULL
&& (fmt[-1] == 'C' || fmt[-1] == 'H'))
{
/* Detect the case where we are printing out a
message for the same function as the last
call to vinfo ("%C"). In this situation do
not print out the ABFD filename or the
function name again. Note - we do still
print out the source filename, as this will
allow programs that parse the linker's output
(eg emacs) to correctly locate multiple
errors in the same source file. */
if (last_bfd == NULL
|| last_file == NULL
|| last_function == NULL
|| last_bfd != abfd
|| (filename != NULL
&& filename_cmp (last_file, filename) != 0)
|| strcmp (last_function, functionname) != 0)
{
lfinfo (fp, _("%B: In function `%T':\n"),
abfd, functionname);
 
last_bfd = abfd;
if (last_file != NULL)
free (last_file);
last_file = NULL;
if (filename)
last_file = xstrdup (filename);
if (last_function != NULL)
free (last_function);
last_function = xstrdup (functionname);
}
discard_last = FALSE;
}
else
lfinfo (fp, "%B:", abfd);
 
if (filename != NULL)
fprintf (fp, "%s:", filename);
 
done = fmt[-1] != 'H';
if (functionname != NULL && fmt[-1] == 'G')
lfinfo (fp, "%T", functionname);
else if (filename != NULL && linenumber != 0)
fprintf (fp, "%u%s", linenumber, done ? "" : ":");
else
done = FALSE;
}
else
{
lfinfo (fp, "%B:", abfd);
done = FALSE;
}
if (!done)
lfinfo (fp, "(%A+0x%v)", section, offset);
 
if (discard_last)
{
last_bfd = NULL;
if (last_file != NULL)
{
free (last_file);
last_file = NULL;
}
if (last_function != NULL)
{
free (last_function);
last_function = NULL;
}
}
}
break;
 
case 'p':
/* native (host) void* pointer, like printf */
fprintf (fp, "%p", va_arg (arg, void *));
break;
 
case 's':
/* arbitrary string, like printf */
fprintf (fp, "%s", va_arg (arg, char *));
break;
 
case 'd':
/* integer, like printf */
fprintf (fp, "%d", va_arg (arg, int));
break;
 
case 'u':
/* unsigned integer, like printf */
fprintf (fp, "%u", va_arg (arg, unsigned int));
break;
 
case 'l':
if (*fmt == 'd')
{
fprintf (fp, "%ld", va_arg (arg, long));
++fmt;
break;
}
else if (*fmt == 'u')
{
fprintf (fp, "%lu", va_arg (arg, unsigned long));
++fmt;
break;
}
/* Fall thru */
 
default:
fprintf (fp, "%%%c", fmt[-1]);
break;
}
}
}
 
if (is_warning && config.fatal_warnings)
config.make_executable = FALSE;
 
if (fatal)
xexit (1);
}
 
/* Format info message and print on stdout. */
 
/* (You would think this should be called just "info", but then you
would be hosed by LynxOS, which defines that name in its libc.) */
 
void
info_msg (const char *fmt, ...)
{
va_list arg;
 
va_start (arg, fmt);
vfinfo (stdout, fmt, arg, FALSE);
va_end (arg);
}
 
/* ('e' for error.) Format info message and print on stderr. */
 
void
einfo (const char *fmt, ...)
{
va_list arg;
 
fflush (stdout);
va_start (arg, fmt);
vfinfo (stderr, fmt, arg, TRUE);
va_end (arg);
fflush (stderr);
}
 
void
info_assert (const char *file, unsigned int line)
{
einfo (_("%F%P: internal error %s %d\n"), file, line);
}
 
/* ('m' for map) Format info message and print on map. */
 
void
minfo (const char *fmt, ...)
{
if (config.map_file != NULL)
{
va_list arg;
 
va_start (arg, fmt);
vfinfo (config.map_file, fmt, arg, FALSE);
va_end (arg);
}
}
 
void
lfinfo (FILE *file, const char *fmt, ...)
{
va_list arg;
 
va_start (arg, fmt);
vfinfo (file, fmt, arg, FALSE);
va_end (arg);
}
/* Functions to print the link map. */
 
void
print_space (void)
{
fprintf (config.map_file, " ");
}
 
void
print_nl (void)
{
fprintf (config.map_file, "\n");
}
 
/* A more or less friendly abort message. In ld.h abort is defined to
call this function. */
 
void
ld_abort (const char *file, int line, const char *fn)
{
if (fn != NULL)
einfo (_("%P: internal error: aborting at %s line %d in %s\n"),
file, line, fn);
else
einfo (_("%P: internal error: aborting at %s line %d\n"),
file, line);
einfo (_("%P%F: please report this bug\n"));
xexit (1);
}
/contrib/toolchain/binutils/ld/ldmisc.h
0,0 → 1,45
/* ldmisc.h -
Copyright 1991, 1992, 1993, 1994, 1996, 1997, 2001, 2003, 2004, 2005, 2007
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef LDMISC_H
#define LDMISC_H
 
extern void vfinfo (FILE *fp, const char *fmt, va_list arg, bfd_boolean is_warning);
extern void einfo (const char *, ...);
extern void minfo (const char *, ...);
extern void info_msg (const char *, ...);
extern void lfinfo (FILE *, const char *, ...);
extern void info_assert (const char *, unsigned int);
extern void yyerror (const char *);
extern void *xmalloc (size_t);
extern void *xrealloc (void *, size_t);
extern void xexit (int);
 
#define ASSERT(x) \
do { if (!(x)) info_assert(__FILE__,__LINE__); } while (0)
 
#define FAIL() \
do { info_assert(__FILE__,__LINE__); } while (0)
 
extern void print_space (void);
extern void print_nl (void);
 
#endif
/contrib/toolchain/binutils/ld/ldver.c
0,0 → 1,61
/* ldver.c -- Print linker version.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2002,
2003, 2005, 2007, 2008, 2009, 2010, 2011, 2012, 2013
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdver.h"
 
#include "ld.h"
#include "ldver.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
#include "ldmain.h"
 
void
ldversion (int noisy)
{
/* Output for noisy == 2 is intended to follow the GNU standards. */
fprintf (stdout, _("GNU ld %s\n"), BFD_VERSION_STRING);
 
if (noisy & 2)
{
printf (_("Copyright 2013 Free Software Foundation, Inc.\n"));
printf (_("\
This program is free software; you may redistribute it under the terms of\n\
the GNU General Public License version 3 or (at your option) a later version.\n\
This program has absolutely no warranty.\n"));
}
 
if (noisy & 1)
{
ld_emulation_xfer_type **ptr = ld_emulations;
 
printf (_(" Supported emulations:\n"));
while (*ptr)
{
printf (" %s\n", (*ptr)->emulation_name);
ptr++;
}
}
}
/contrib/toolchain/binutils/ld/ldver.h
0,0 → 1,22
/* ldver.h -- Header file for ldver.c.
Copyright 1991, 1992, 1993, 1996, 2001, 2003, 2005, 2007
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
void ldversion (int);
/contrib/toolchain/binutils/ld/ldwrite.c
0,0 → 1,593
/* ldwrite.c -- write out the linked file
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002,
2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012
Free Software Foundation, Inc.
Written by Steve Chamberlain sac@cygnus.com
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libiberty.h"
#include "safe-ctype.h"
 
#include "ld.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldwrite.h"
#include "ldmisc.h"
#include <ldgram.h>
#include "ldmain.h"
 
/* Build link_order structures for the BFD linker. */
 
static void
build_link_order (lang_statement_union_type *statement)
{
switch (statement->header.type)
{
case lang_data_statement_enum:
{
asection *output_section;
struct bfd_link_order *link_order;
bfd_vma value;
bfd_boolean big_endian = FALSE;
 
output_section = statement->data_statement.output_section;
ASSERT (output_section->owner == link_info.output_bfd);
 
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|| ((output_section->flags & SEC_LOAD) != 0
&& (output_section->flags & SEC_THREAD_LOCAL))))
break;
 
link_order = bfd_new_link_order (link_info.output_bfd, output_section);
if (link_order == NULL)
einfo (_("%P%F: bfd_new_link_order failed\n"));
 
link_order->type = bfd_data_link_order;
link_order->offset = statement->data_statement.output_offset;
link_order->u.data.contents = (bfd_byte *) xmalloc (QUAD_SIZE);
 
value = statement->data_statement.value;
 
/* If the endianness of the output BFD is not known, then we
base the endianness of the data on the first input file.
By convention, the bfd_put routines for an unknown
endianness are big endian, so we must swap here if the
input file is little endian. */
if (bfd_big_endian (link_info.output_bfd))
big_endian = TRUE;
else if (bfd_little_endian (link_info.output_bfd))
big_endian = FALSE;
else
{
bfd_boolean swap;
 
swap = FALSE;
if (command_line.endian == ENDIAN_BIG)
big_endian = TRUE;
else if (command_line.endian == ENDIAN_LITTLE)
{
big_endian = FALSE;
swap = TRUE;
}
else if (command_line.endian == ENDIAN_UNSET)
{
big_endian = TRUE;
{
LANG_FOR_EACH_INPUT_STATEMENT (s)
{
if (s->the_bfd != NULL)
{
if (bfd_little_endian (s->the_bfd))
{
big_endian = FALSE;
swap = TRUE;
}
break;
}
}
}
}
 
if (swap)
{
bfd_byte buffer[8];
 
switch (statement->data_statement.type)
{
case QUAD:
case SQUAD:
if (sizeof (bfd_vma) >= QUAD_SIZE)
{
bfd_putl64 (value, buffer);
value = bfd_getb64 (buffer);
break;
}
/* Fall through. */
case LONG:
bfd_putl32 (value, buffer);
value = bfd_getb32 (buffer);
break;
case SHORT:
bfd_putl16 (value, buffer);
value = bfd_getb16 (buffer);
break;
case BYTE:
break;
default:
abort ();
}
}
}
 
ASSERT (output_section->owner == link_info.output_bfd);
switch (statement->data_statement.type)
{
case QUAD:
case SQUAD:
if (sizeof (bfd_vma) >= QUAD_SIZE)
bfd_put_64 (link_info.output_bfd, value,
link_order->u.data.contents);
else
{
bfd_vma high;
 
if (statement->data_statement.type == QUAD)
high = 0;
else if ((value & 0x80000000) == 0)
high = 0;
else
high = (bfd_vma) -1;
bfd_put_32 (link_info.output_bfd, high,
(link_order->u.data.contents
+ (big_endian ? 0 : 4)));
bfd_put_32 (link_info.output_bfd, value,
(link_order->u.data.contents
+ (big_endian ? 4 : 0)));
}
link_order->size = QUAD_SIZE;
break;
case LONG:
bfd_put_32 (link_info.output_bfd, value,
link_order->u.data.contents);
link_order->size = LONG_SIZE;
break;
case SHORT:
bfd_put_16 (link_info.output_bfd, value,
link_order->u.data.contents);
link_order->size = SHORT_SIZE;
break;
case BYTE:
bfd_put_8 (link_info.output_bfd, value,
link_order->u.data.contents);
link_order->size = BYTE_SIZE;
break;
default:
abort ();
}
link_order->u.data.size = link_order->size;
}
break;
 
case lang_reloc_statement_enum:
{
lang_reloc_statement_type *rs;
asection *output_section;
struct bfd_link_order *link_order;
 
rs = &statement->reloc_statement;
 
output_section = rs->output_section;
ASSERT (output_section->owner == link_info.output_bfd);
 
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|| ((output_section->flags & SEC_LOAD) != 0
&& (output_section->flags & SEC_THREAD_LOCAL))))
break;
 
link_order = bfd_new_link_order (link_info.output_bfd, output_section);
if (link_order == NULL)
einfo (_("%P%F: bfd_new_link_order failed\n"));
 
link_order->offset = rs->output_offset;
link_order->size = bfd_get_reloc_size (rs->howto);
 
link_order->u.reloc.p = (struct bfd_link_order_reloc *)
xmalloc (sizeof (struct bfd_link_order_reloc));
 
link_order->u.reloc.p->reloc = rs->reloc;
link_order->u.reloc.p->addend = rs->addend_value;
 
if (rs->name == NULL)
{
link_order->type = bfd_section_reloc_link_order;
if (rs->section->owner == link_info.output_bfd)
link_order->u.reloc.p->u.section = rs->section;
else
{
link_order->u.reloc.p->u.section = rs->section->output_section;
link_order->u.reloc.p->addend += rs->section->output_offset;
}
}
else
{
link_order->type = bfd_symbol_reloc_link_order;
link_order->u.reloc.p->u.name = rs->name;
}
}
break;
 
case lang_input_section_enum:
{
/* Create a new link_order in the output section with this
attached */
asection *i = statement->input_section.section;
 
if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
&& (i->flags & SEC_EXCLUDE) == 0)
{
asection *output_section = i->output_section;
struct bfd_link_order *link_order;
 
ASSERT (output_section->owner == link_info.output_bfd);
 
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|| ((output_section->flags & SEC_LOAD) != 0
&& (output_section->flags & SEC_THREAD_LOCAL))))
break;
 
link_order = bfd_new_link_order (link_info.output_bfd,
output_section);
 
if ((i->flags & SEC_NEVER_LOAD) != 0
&& (i->flags & SEC_DEBUGGING) == 0)
{
/* We've got a never load section inside one which is
going to be output, we'll change it into a fill. */
link_order->type = bfd_data_link_order;
link_order->u.data.contents = (unsigned char *) "";
link_order->u.data.size = 1;
}
else
{
link_order->type = bfd_indirect_link_order;
link_order->u.indirect.section = i;
ASSERT (i->output_section == output_section);
}
link_order->size = i->size;
link_order->offset = i->output_offset;
}
}
break;
 
case lang_padding_statement_enum:
/* Make a new link_order with the right filler */
{
asection *output_section;
struct bfd_link_order *link_order;
 
output_section = statement->padding_statement.output_section;
ASSERT (statement->padding_statement.output_section->owner
== link_info.output_bfd);
 
if (!((output_section->flags & SEC_HAS_CONTENTS) != 0
|| ((output_section->flags & SEC_LOAD) != 0
&& (output_section->flags & SEC_THREAD_LOCAL))))
break;
 
link_order = bfd_new_link_order (link_info.output_bfd,
output_section);
link_order->type = bfd_data_link_order;
link_order->size = statement->padding_statement.size;
link_order->offset = statement->padding_statement.output_offset;
link_order->u.data.contents = statement->padding_statement.fill->data;
link_order->u.data.size = statement->padding_statement.fill->size;
}
break;
 
default:
/* All the other ones fall through */
break;
}
}
 
/* Return true if NAME is the name of an unsplittable section. These
are the stabs strings, dwarf strings. */
 
static bfd_boolean
unsplittable_name (const char *name)
{
if (CONST_STRNEQ (name, ".stab"))
{
/* There are several stab like string sections. We pattern match on
".stab...str" */
unsigned len = strlen (name);
if (strcmp (&name[len-3], "str") == 0)
return TRUE;
}
else if (strcmp (name, "$GDB_STRINGS$") == 0)
return TRUE;
return FALSE;
}
 
/* Wander around the input sections, make sure that
we'll never try and create an output section with more relocs
than will fit.. Do this by always assuming the worst case, and
creating new output sections with all the right bits. */
#define TESTIT 1
static asection *
clone_section (bfd *abfd, asection *s, const char *name, int *count)
{
char *tname;
char *sname;
unsigned int len;
asection *n;
struct bfd_link_hash_entry *h;
 
/* Invent a section name from the section name and a dotted numeric
suffix. */
len = strlen (name);
tname = (char *) xmalloc (len + 1);
memcpy (tname, name, len + 1);
/* Remove a dotted number suffix, from a previous split link. */
while (len && ISDIGIT (tname[len-1]))
len--;
if (len > 1 && tname[len-1] == '.')
/* It was a dotted number. */
tname[len-1] = 0;
 
/* We want to use the whole of the original section name for the
split name, but coff can be restricted to 8 character names. */
if (bfd_family_coff (abfd) && strlen (tname) > 5)
{
/* Some section names cannot be truncated, as the name is
used to locate some other section. */
if (CONST_STRNEQ (name, ".stab")
|| strcmp (name, "$GDB_SYMBOLS$") == 0)
{
einfo (_ ("%F%P: cannot create split section name for %s\n"), name);
/* Silence gcc warnings. einfo exits, so we never reach here. */
return NULL;
}
tname[5] = 0;
}
 
if ((sname = bfd_get_unique_section_name (abfd, tname, count)) == NULL
|| (n = bfd_make_section_anyway (abfd, sname)) == NULL
|| (h = bfd_link_hash_lookup (link_info.hash,
sname, TRUE, TRUE, FALSE)) == NULL)
{
einfo (_("%F%P: clone section failed: %E\n"));
/* Silence gcc warnings. einfo exits, so we never reach here. */
return NULL;
}
free (tname);
 
/* Set up section symbol. */
h->type = bfd_link_hash_defined;
h->u.def.value = 0;
h->u.def.section = n;
 
n->flags = s->flags;
n->vma = s->vma;
n->user_set_vma = s->user_set_vma;
n->lma = s->lma;
n->size = 0;
n->output_offset = s->output_offset;
n->output_section = n;
n->orelocation = 0;
n->reloc_count = 0;
n->alignment_power = s->alignment_power;
 
bfd_copy_private_section_data (abfd, s, abfd, n);
 
return n;
}
 
#if TESTING
static void
ds (asection *s)
{
struct bfd_link_order *l = s->map_head.link_order;
printf ("vma %x size %x\n", s->vma, s->size);
while (l)
{
if (l->type == bfd_indirect_link_order)
{
printf ("%8x %s\n", l->offset, l->u.indirect.section->owner->filename);
}
else
{
printf (_("%8x something else\n"), l->offset);
}
l = l->next;
}
printf ("\n");
}
 
dump (char *s, asection *a1, asection *a2)
{
printf ("%s\n", s);
ds (a1);
ds (a2);
}
 
static void
sanity_check (bfd *abfd)
{
asection *s;
for (s = abfd->sections; s; s = s->next)
{
struct bfd_link_order *p;
bfd_vma prev = 0;
for (p = s->map_head.link_order; p; p = p->next)
{
if (p->offset > 100000)
abort ();
if (p->offset < prev)
abort ();
prev = p->offset;
}
}
}
#else
#define sanity_check(a)
#define dump(a, b, c)
#endif
 
static void
split_sections (bfd *abfd, struct bfd_link_info *info)
{
asection *original_sec;
int nsecs = abfd->section_count;
sanity_check (abfd);
/* Look through all the original sections. */
for (original_sec = abfd->sections;
original_sec && nsecs;
original_sec = original_sec->next, nsecs--)
{
int count = 0;
unsigned int lines = 0;
unsigned int relocs = 0;
bfd_size_type sec_size = 0;
struct bfd_link_order *l;
struct bfd_link_order *p;
bfd_vma vma = original_sec->vma;
asection *cursor = original_sec;
 
/* Count up the relocations and line entries to see if anything
would be too big to fit. Accumulate section size too. */
for (l = NULL, p = cursor->map_head.link_order; p != NULL; p = l->next)
{
unsigned int thislines = 0;
unsigned int thisrelocs = 0;
bfd_size_type thissize = 0;
if (p->type == bfd_indirect_link_order)
{
asection *sec;
 
sec = p->u.indirect.section;
 
if (info->strip == strip_none
|| info->strip == strip_some)
thislines = sec->lineno_count;
 
if (info->relocatable)
thisrelocs = sec->reloc_count;
 
thissize = sec->size;
 
}
else if (info->relocatable
&& (p->type == bfd_section_reloc_link_order
|| p->type == bfd_symbol_reloc_link_order))
thisrelocs++;
 
if (l != NULL
&& (thisrelocs + relocs >= config.split_by_reloc
|| thislines + lines >= config.split_by_reloc
|| (thissize + sec_size >= config.split_by_file))
&& !unsplittable_name (cursor->name))
{
/* Create a new section and put this link order and the
following link orders into it. */
bfd_vma shift_offset;
asection *n;
 
n = clone_section (abfd, cursor, original_sec->name, &count);
 
/* Attach the link orders to the new section and snip
them off from the old section. */
n->map_head.link_order = p;
n->map_tail.link_order = cursor->map_tail.link_order;
cursor->map_tail.link_order = l;
l->next = NULL;
l = p;
 
/* Change the size of the original section and
update the vma of the new one. */
 
dump ("before snip", cursor, n);
 
shift_offset = p->offset;
n->size = cursor->size - shift_offset;
cursor->size = shift_offset;
 
vma += shift_offset;
n->lma = n->vma = vma;
 
/* Run down the chain and change the output section to
the right one, update the offsets too. */
do
{
p->offset -= shift_offset;
if (p->type == bfd_indirect_link_order)
{
p->u.indirect.section->output_section = n;
p->u.indirect.section->output_offset = p->offset;
}
p = p->next;
}
while (p);
 
dump ("after snip", cursor, n);
cursor = n;
relocs = thisrelocs;
lines = thislines;
sec_size = thissize;
}
else
{
l = p;
relocs += thisrelocs;
lines += thislines;
sec_size += thissize;
}
}
}
sanity_check (abfd);
}
 
/* Call BFD to write out the linked file. */
 
void
ldwrite (void)
{
/* Reset error indicator, which can typically something like invalid
format from opening up the .o files. */
bfd_set_error (bfd_error_no_error);
lang_for_each_statement (build_link_order);
 
if (config.split_by_reloc != (unsigned) -1
|| config.split_by_file != (bfd_size_type) -1)
split_sections (link_info.output_bfd, &link_info);
if (!bfd_final_link (link_info.output_bfd, &link_info))
{
/* If there was an error recorded, print it out. Otherwise assume
an appropriate error message like unknown symbol was printed
out. */
 
if (bfd_get_error () != bfd_error_no_error)
einfo (_("%F%P: final link failed: %E\n"));
else
xexit (1);
}
}
/contrib/toolchain/binutils/ld/ldwrite.h
0,0 → 1,21
/* ldwrite.h -
Copyright 1991, 1992, 1993, 2003, 2005, 2007 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
extern void ldwrite (void);
/contrib/toolchain/binutils/ld/lexsup.c
0,0 → 1,1718
/* Parse options for the GNU linker.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdver.h"
#include "libiberty.h"
#include <stdio.h>
#include <string.h>
#include "safe-ctype.h"
#include "getopt.h"
#include "bfdlink.h"
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include <ldgram.h>
#include "ldlex.h"
#include "ldfile.h"
#include "ldver.h"
#include "ldemul.h"
#include "demangle.h"
#ifdef ENABLE_PLUGINS
#include "plugin.h"
#endif /* ENABLE_PLUGINS */
 
#ifndef PATH_SEPARATOR
#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN32__))
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif
#endif
 
/* Somewhere above, sys/stat.h got included . . . . */
#if !defined(S_ISDIR) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
 
static void set_default_dirlist (char *);
static void set_section_start (char *, char *);
static void set_segment_start (const char *, char *);
static void help (void);
 
/* The long options. This structure is used for both the option
parsing and the help text. */
 
enum control_enum {
/* Use one dash before long option name. */
ONE_DASH,
/* Use two dashes before long option name. */
TWO_DASHES,
/* Only accept two dashes before the long option name.
This is an overloading of the use of this enum, since originally it
was only intended to tell the --help display function how to display
the long option name. This feature was added in order to resolve
the confusion about the -omagic command line switch. Is it setting
the output file name to "magic" or is it setting the NMAGIC flag on
the output ? It has been decided that it is setting the output file
name, and that if you want to set the NMAGIC flag you should use -N
or --omagic. */
EXACTLY_TWO_DASHES,
/* Don't mention this option in --help output. */
NO_HELP
};
 
struct ld_option
{
/* The long option information. */
struct option opt;
/* The short option with the same meaning ('\0' if none). */
char shortopt;
/* The name of the argument (NULL if none). */
const char *arg;
/* The documentation string. If this is NULL, this is a synonym for
the previous option. */
const char *doc;
enum control_enum control;
};
 
static const struct ld_option ld_options[] =
{
{ {NULL, required_argument, NULL, '\0'},
'a', N_("KEYWORD"), N_("Shared library control for HP/UX compatibility"),
ONE_DASH },
{ {"architecture", required_argument, NULL, 'A'},
'A', N_("ARCH"), N_("Set architecture") , TWO_DASHES },
{ {"format", required_argument, NULL, 'b'},
'b', N_("TARGET"), N_("Specify target for following input files"),
TWO_DASHES },
{ {"mri-script", required_argument, NULL, 'c'},
'c', N_("FILE"), N_("Read MRI format linker script"), TWO_DASHES },
{ {"dc", no_argument, NULL, 'd'},
'd', NULL, N_("Force common symbols to be defined"), ONE_DASH },
{ {"dp", no_argument, NULL, 'd'},
'\0', NULL, NULL, ONE_DASH },
{ {"entry", required_argument, NULL, 'e'},
'e', N_("ADDRESS"), N_("Set start address"), TWO_DASHES },
{ {"export-dynamic", no_argument, NULL, OPTION_EXPORT_DYNAMIC},
'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES },
{ {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC},
'\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES },
{ {"EB", no_argument, NULL, OPTION_EB},
'\0', NULL, N_("Link big-endian objects"), ONE_DASH },
{ {"EL", no_argument, NULL, OPTION_EL},
'\0', NULL, N_("Link little-endian objects"), ONE_DASH },
{ {"auxiliary", required_argument, NULL, 'f'},
'f', N_("SHLIB"), N_("Auxiliary filter for shared object symbol table"),
TWO_DASHES },
{ {"filter", required_argument, NULL, 'F'},
'F', N_("SHLIB"), N_("Filter for shared object symbol table"),
TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'g', NULL, N_("Ignored"), ONE_DASH },
{ {"gpsize", required_argument, NULL, 'G'},
'G', N_("SIZE"), N_("Small data size (if no size, same as --shared)"),
TWO_DASHES },
{ {"soname", required_argument, NULL, OPTION_SONAME},
'h', N_("FILENAME"), N_("Set internal name of shared library"), ONE_DASH },
{ {"dynamic-linker", required_argument, NULL, OPTION_DYNAMIC_LINKER},
'I', N_("PROGRAM"), N_("Set PROGRAM as the dynamic linker to use"),
TWO_DASHES },
{ {"library", required_argument, NULL, 'l'},
'l', N_("LIBNAME"), N_("Search for library LIBNAME"), TWO_DASHES },
{ {"library-path", required_argument, NULL, 'L'},
'L', N_("DIRECTORY"), N_("Add DIRECTORY to library search path"),
TWO_DASHES },
{ {"sysroot=<DIRECTORY>", required_argument, NULL, OPTION_SYSROOT},
'\0', NULL, N_("Override the default sysroot location"), TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'm', N_("EMULATION"), N_("Set emulation"), ONE_DASH },
{ {"print-map", no_argument, NULL, 'M'},
'M', NULL, N_("Print map file on standard output"), TWO_DASHES },
{ {"nmagic", no_argument, NULL, 'n'},
'n', NULL, N_("Do not page align data"), TWO_DASHES },
{ {"omagic", no_argument, NULL, 'N'},
'N', NULL, N_("Do not page align data, do not make text readonly"),
EXACTLY_TWO_DASHES },
{ {"no-omagic", no_argument, NULL, OPTION_NO_OMAGIC},
'\0', NULL, N_("Page align data, make text readonly"),
EXACTLY_TWO_DASHES },
{ {"output", required_argument, NULL, 'o'},
'o', N_("FILE"), N_("Set output file name"), EXACTLY_TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'O', NULL, N_("Optimize output file"), ONE_DASH },
#ifdef ENABLE_PLUGINS
{ {"plugin", required_argument, NULL, OPTION_PLUGIN},
'\0', N_("PLUGIN"), N_("Load named plugin"), ONE_DASH },
{ {"plugin-opt", required_argument, NULL, OPTION_PLUGIN_OPT},
'\0', N_("ARG"), N_("Send arg to last-loaded plugin"), ONE_DASH },
{ {"flto", optional_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for GCC LTO option compatibility"),
ONE_DASH },
{ {"flto-partition=", required_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for GCC LTO option compatibility"),
ONE_DASH },
#endif /* ENABLE_PLUGINS */
{ {"fuse-ld=", required_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for GCC linker option compatibility"),
ONE_DASH },
{ {"Qy", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for SVR4 compatibility"), ONE_DASH },
{ {"emit-relocs", no_argument, NULL, 'q'},
'q', NULL, "Generate relocations in final output", TWO_DASHES },
{ {"relocatable", no_argument, NULL, 'r'},
'r', NULL, N_("Generate relocatable output"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'i', NULL, NULL, ONE_DASH },
{ {"just-symbols", required_argument, NULL, 'R'},
'R', N_("FILE"), N_("Just link symbols (if directory, same as --rpath)"),
TWO_DASHES },
{ {"strip-all", no_argument, NULL, 's'},
's', NULL, N_("Strip all symbols"), TWO_DASHES },
{ {"strip-debug", no_argument, NULL, 'S'},
'S', NULL, N_("Strip debugging symbols"), TWO_DASHES },
{ {"strip-discarded", no_argument, NULL, OPTION_STRIP_DISCARDED},
'\0', NULL, N_("Strip symbols in discarded sections"), TWO_DASHES },
{ {"no-strip-discarded", no_argument, NULL, OPTION_NO_STRIP_DISCARDED},
'\0', NULL, N_("Do not strip symbols in discarded sections"), TWO_DASHES },
{ {"trace", no_argument, NULL, 't'},
't', NULL, N_("Trace file opens"), TWO_DASHES },
{ {"script", required_argument, NULL, 'T'},
'T', N_("FILE"), N_("Read linker script"), TWO_DASHES },
{ {"default-script", required_argument, NULL, OPTION_DEFAULT_SCRIPT},
'\0', N_("FILE"), N_("Read default linker script"), TWO_DASHES },
{ {"dT", required_argument, NULL, OPTION_DEFAULT_SCRIPT},
'\0', NULL, NULL, ONE_DASH },
{ {"undefined", required_argument, NULL, 'u'},
'u', N_("SYMBOL"), N_("Start with undefined reference to SYMBOL"),
TWO_DASHES },
{ {"unique", optional_argument, NULL, OPTION_UNIQUE},
'\0', N_("[=SECTION]"),
N_("Don't merge input [SECTION | orphan] sections"), TWO_DASHES },
{ {"Ur", no_argument, NULL, OPTION_UR},
'\0', NULL, N_("Build global constructor/destructor tables"), ONE_DASH },
{ {"version", no_argument, NULL, OPTION_VERSION},
'v', NULL, N_("Print version information"), TWO_DASHES },
{ {NULL, no_argument, NULL, '\0'},
'V', NULL, N_("Print version and emulation information"), ONE_DASH },
{ {"discard-all", no_argument, NULL, 'x'},
'x', NULL, N_("Discard all local symbols"), TWO_DASHES },
{ {"discard-locals", no_argument, NULL, 'X'},
'X', NULL, N_("Discard temporary local symbols (default)"), TWO_DASHES },
{ {"discard-none", no_argument, NULL, OPTION_DISCARD_NONE},
'\0', NULL, N_("Don't discard any local symbols"), TWO_DASHES },
{ {"trace-symbol", required_argument, NULL, 'y'},
'y', N_("SYMBOL"), N_("Trace mentions of SYMBOL"), TWO_DASHES },
{ {NULL, required_argument, NULL, '\0'},
'Y', N_("PATH"), N_("Default search path for Solaris compatibility"),
ONE_DASH },
{ {"start-group", no_argument, NULL, '('},
'(', NULL, N_("Start a group"), TWO_DASHES },
{ {"end-group", no_argument, NULL, ')'},
')', NULL, N_("End a group"), TWO_DASHES },
{ {"accept-unknown-input-arch", no_argument, NULL,
OPTION_ACCEPT_UNKNOWN_INPUT_ARCH},
'\0', NULL,
N_("Accept input files whose architecture cannot be determined"),
TWO_DASHES },
{ {"no-accept-unknown-input-arch", no_argument, NULL,
OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH},
'\0', NULL, N_("Reject input files whose architecture is unknown"),
TWO_DASHES },
 
/* The next two options are deprecated because of their similarity to
--as-needed and --no-as-needed. They have been replaced by
--copy-dt-needed-entries and --no-copy-dt-needed-entries. */
{ {"add-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
'\0', NULL, NULL, NO_HELP },
{ {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
'\0', NULL, NULL, NO_HELP },
 
{ {"as-needed", no_argument, NULL, OPTION_ADD_DT_NEEDED_FOR_REGULAR},
'\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"),
TWO_DASHES },
{ {"no-as-needed", no_argument, NULL, OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR},
'\0', NULL, N_("Always set DT_NEEDED for dynamic libraries mentioned on\n"
" the command line"),
TWO_DASHES },
{ {"assert", required_argument, NULL, OPTION_ASSERT},
'\0', N_("KEYWORD"), N_("Ignored for SunOS compatibility"), ONE_DASH },
{ {"Bdynamic", no_argument, NULL, OPTION_CALL_SHARED},
'\0', NULL, N_("Link against shared libraries"), ONE_DASH },
{ {"dy", no_argument, NULL, OPTION_CALL_SHARED},
'\0', NULL, NULL, ONE_DASH },
{ {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
'\0', NULL, NULL, ONE_DASH },
{ {"Bstatic", no_argument, NULL, OPTION_NON_SHARED},
'\0', NULL, N_("Do not link against shared libraries"), ONE_DASH },
{ {"dn", no_argument, NULL, OPTION_NON_SHARED},
'\0', NULL, NULL, ONE_DASH },
{ {"non_shared", no_argument, NULL, OPTION_NON_SHARED},
'\0', NULL, NULL, ONE_DASH },
{ {"static", no_argument, NULL, OPTION_NON_SHARED},
'\0', NULL, NULL, ONE_DASH },
{ {"Bsymbolic", no_argument, NULL, OPTION_SYMBOLIC},
'\0', NULL, N_("Bind global references locally"), ONE_DASH },
{ {"Bsymbolic-functions", no_argument, NULL, OPTION_SYMBOLIC_FUNCTIONS},
'\0', NULL, N_("Bind global function references locally"), ONE_DASH },
{ {"check-sections", no_argument, NULL, OPTION_CHECK_SECTIONS},
'\0', NULL, N_("Check section addresses for overlaps (default)"),
TWO_DASHES },
{ {"no-check-sections", no_argument, NULL, OPTION_NO_CHECK_SECTIONS},
'\0', NULL, N_("Do not check section addresses for overlaps"),
TWO_DASHES },
{ {"copy-dt-needed-entries", no_argument, NULL,
OPTION_ADD_DT_NEEDED_FOR_DYNAMIC},
'\0', NULL, N_("Copy DT_NEEDED links mentioned inside DSOs that follow"),
TWO_DASHES },
{ {"no-copy-dt-needed-entries", no_argument, NULL,
OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC},
'\0', NULL, N_("Do not copy DT_NEEDED links mentioned inside DSOs that follow"),
TWO_DASHES },
 
{ {"cref", no_argument, NULL, OPTION_CREF},
'\0', NULL, N_("Output cross reference table"), TWO_DASHES },
{ {"defsym", required_argument, NULL, OPTION_DEFSYM},
'\0', N_("SYMBOL=EXPRESSION"), N_("Define a symbol"), TWO_DASHES },
{ {"demangle", optional_argument, NULL, OPTION_DEMANGLE},
'\0', N_("[=STYLE]"), N_("Demangle symbol names [using STYLE]"),
TWO_DASHES },
{ {"embedded-relocs", no_argument, NULL, OPTION_EMBEDDED_RELOCS},
'\0', NULL, N_("Generate embedded relocs"), TWO_DASHES},
{ {"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL},
'\0', NULL, N_("Treat warnings as errors"),
TWO_DASHES },
{ {"no-fatal-warnings", no_argument, NULL, OPTION_NO_WARN_FATAL},
'\0', NULL, N_("Do not treat warnings as errors (default)"),
TWO_DASHES },
{ {"fini", required_argument, NULL, OPTION_FINI},
'\0', N_("SYMBOL"), N_("Call SYMBOL at unload-time"), ONE_DASH },
{ {"force-exe-suffix", no_argument, NULL, OPTION_FORCE_EXE_SUFFIX},
'\0', NULL, N_("Force generation of file with .exe suffix"), TWO_DASHES},
{ {"gc-sections", no_argument, NULL, OPTION_GC_SECTIONS},
'\0', NULL, N_("Remove unused sections (on some targets)"),
TWO_DASHES },
{ {"no-gc-sections", no_argument, NULL, OPTION_NO_GC_SECTIONS},
'\0', NULL, N_("Don't remove unused sections (default)"),
TWO_DASHES },
{ {"print-gc-sections", no_argument, NULL, OPTION_PRINT_GC_SECTIONS},
'\0', NULL, N_("List removed unused sections on stderr"),
TWO_DASHES },
{ {"no-print-gc-sections", no_argument, NULL, OPTION_NO_PRINT_GC_SECTIONS},
'\0', NULL, N_("Do not list removed unused sections"),
TWO_DASHES },
{ {"hash-size=<NUMBER>", required_argument, NULL, OPTION_HASH_SIZE},
'\0', NULL, N_("Set default hash table size close to <NUMBER>"),
TWO_DASHES },
{ {"help", no_argument, NULL, OPTION_HELP},
'\0', NULL, N_("Print option help"), TWO_DASHES },
{ {"init", required_argument, NULL, OPTION_INIT},
'\0', N_("SYMBOL"), N_("Call SYMBOL at load-time"), ONE_DASH },
{ {"Map", required_argument, NULL, OPTION_MAP},
'\0', N_("FILE"), N_("Write a map file"), ONE_DASH },
{ {"no-define-common", no_argument, NULL, OPTION_NO_DEFINE_COMMON},
'\0', NULL, N_("Do not define Common storage"), TWO_DASHES },
{ {"no-demangle", no_argument, NULL, OPTION_NO_DEMANGLE },
'\0', NULL, N_("Do not demangle symbol names"), TWO_DASHES },
{ {"no-keep-memory", no_argument, NULL, OPTION_NO_KEEP_MEMORY},
'\0', NULL, N_("Use less memory and more disk I/O"), TWO_DASHES },
{ {"no-undefined", no_argument, NULL, OPTION_NO_UNDEFINED},
'\0', NULL, N_("Do not allow unresolved references in object files"),
TWO_DASHES },
{ {"allow-shlib-undefined", no_argument, NULL, OPTION_ALLOW_SHLIB_UNDEFINED},
'\0', NULL, N_("Allow unresolved references in shared libraries"),
TWO_DASHES },
{ {"no-allow-shlib-undefined", no_argument, NULL,
OPTION_NO_ALLOW_SHLIB_UNDEFINED},
'\0', NULL, N_("Do not allow unresolved references in shared libs"),
TWO_DASHES },
{ {"allow-multiple-definition", no_argument, NULL,
OPTION_ALLOW_MULTIPLE_DEFINITION},
'\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
{ {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
'\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
{ {"default-symver", no_argument, NULL, OPTION_DEFAULT_SYMVER},
'\0', NULL, N_("Create default symbol version"), TWO_DASHES },
{ {"default-imported-symver", no_argument, NULL,
OPTION_DEFAULT_IMPORTED_SYMVER},
'\0', NULL, N_("Create default symbol version for imported symbols"),
TWO_DASHES },
{ {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-warn-search-mismatch", no_argument, NULL,
OPTION_NO_WARN_SEARCH_MISMATCH},
'\0', NULL, N_("Don't warn on finding an incompatible library"),
TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
'\0', NULL, N_("Turn off --whole-archive"), TWO_DASHES },
{ {"noinhibit-exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
'\0', NULL, N_("Create an output file even if errors occur"),
TWO_DASHES },
{ {"noinhibit_exec", no_argument, NULL, OPTION_NOINHIBIT_EXEC},
'\0', NULL, NULL, NO_HELP },
{ {"nostdlib", no_argument, NULL, OPTION_NOSTDLIB},
'\0', NULL, N_("Only use library directories specified on\n"
" the command line"),
ONE_DASH },
{ {"oformat", required_argument, NULL, OPTION_OFORMAT},
'\0', N_("TARGET"), N_("Specify target of output file"),
EXACTLY_TWO_DASHES },
{ {"print-output-format", no_argument, NULL, OPTION_PRINT_OUTPUT_FORMAT},
'\0', NULL, N_("Print default output format"), TWO_DASHES },
{ {"qmagic", no_argument, NULL, OPTION_IGNORE},
'\0', NULL, N_("Ignored for Linux compatibility"), ONE_DASH },
{ {"reduce-memory-overheads", no_argument, NULL,
OPTION_REDUCE_MEMORY_OVERHEADS},
'\0', NULL, N_("Reduce memory overheads, possibly taking much longer"),
TWO_DASHES },
{ {"relax", no_argument, NULL, OPTION_RELAX},
'\0', NULL, N_("Reduce code size by using target specific optimizations"), TWO_DASHES },
{ {"no-relax", no_argument, NULL, OPTION_NO_RELAX},
'\0', NULL, N_("Do not use relaxation techniques to reduce code size"), TWO_DASHES },
{ {"retain-symbols-file", required_argument, NULL,
OPTION_RETAIN_SYMBOLS_FILE},
'\0', N_("FILE"), N_("Keep only symbols listed in FILE"), TWO_DASHES },
{ {"rpath", required_argument, NULL, OPTION_RPATH},
'\0', N_("PATH"), N_("Set runtime shared library search path"), ONE_DASH },
{ {"rpath-link", required_argument, NULL, OPTION_RPATH_LINK},
'\0', N_("PATH"), N_("Set link time shared library search path"),
ONE_DASH },
{ {"shared", no_argument, NULL, OPTION_SHARED},
'\0', NULL, N_("Create a shared library"), ONE_DASH },
{ {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD. */
'\0', NULL, NULL, ONE_DASH },
{ {"pie", no_argument, NULL, OPTION_PIE},
'\0', NULL, N_("Create a position independent executable"), ONE_DASH },
{ {"pic-executable", no_argument, NULL, OPTION_PIE},
'\0', NULL, NULL, TWO_DASHES },
{ {"sort-common", optional_argument, NULL, OPTION_SORT_COMMON},
'\0', N_("[=ascending|descending]"),
N_("Sort common symbols by alignment [in specified order]"),
TWO_DASHES },
{ {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
'\0', NULL, NULL, NO_HELP },
{ {"sort-section", required_argument, NULL, OPTION_SORT_SECTION},
'\0', N_("name|alignment"),
N_("Sort sections by name or maximum alignment"), TWO_DASHES },
{ {"spare-dynamic-tags", required_argument, NULL, OPTION_SPARE_DYNAMIC_TAGS},
'\0', N_("COUNT"), N_("How many tags to reserve in .dynamic section"),
TWO_DASHES },
{ {"split-by-file", optional_argument, NULL, OPTION_SPLIT_BY_FILE},
'\0', N_("[=SIZE]"), N_("Split output sections every SIZE octets"),
TWO_DASHES },
{ {"split-by-reloc", optional_argument, NULL, OPTION_SPLIT_BY_RELOC},
'\0', N_("[=COUNT]"), N_("Split output sections every COUNT relocs"),
TWO_DASHES },
{ {"stats", no_argument, NULL, OPTION_STATS},
'\0', NULL, N_("Print memory usage statistics"), TWO_DASHES },
{ {"target-help", no_argument, NULL, OPTION_TARGET_HELP},
'\0', NULL, N_("Display target specific options"), TWO_DASHES },
{ {"task-link", required_argument, NULL, OPTION_TASK_LINK},
'\0', N_("SYMBOL"), N_("Do task level linking"), TWO_DASHES },
{ {"traditional-format", no_argument, NULL, OPTION_TRADITIONAL_FORMAT},
'\0', NULL, N_("Use same format as native linker"), TWO_DASHES },
{ {"section-start", required_argument, NULL, OPTION_SECTION_START},
'\0', N_("SECTION=ADDRESS"), N_("Set address of named section"),
TWO_DASHES },
{ {"Tbss", required_argument, NULL, OPTION_TBSS},
'\0', N_("ADDRESS"), N_("Set address of .bss section"), ONE_DASH },
{ {"Tdata", required_argument, NULL, OPTION_TDATA},
'\0', N_("ADDRESS"), N_("Set address of .data section"), ONE_DASH },
{ {"Ttext", required_argument, NULL, OPTION_TTEXT},
'\0', N_("ADDRESS"), N_("Set address of .text section"), ONE_DASH },
{ {"Ttext-segment", required_argument, NULL, OPTION_TTEXT_SEGMENT},
'\0', N_("ADDRESS"), N_("Set address of text segment"), ONE_DASH },
{ {"Trodata-segment", required_argument, NULL, OPTION_TRODATA_SEGMENT},
'\0', N_("ADDRESS"), N_("Set address of rodata segment"), ONE_DASH },
{ {"Tldata-segment", required_argument, NULL, OPTION_TLDATA_SEGMENT},
'\0', N_("ADDRESS"), N_("Set address of ldata segment"), ONE_DASH },
{ {"unresolved-symbols=<method>", required_argument, NULL,
OPTION_UNRESOLVED_SYMBOLS},
'\0', NULL, N_("How to handle unresolved symbols. <method> is:\n"
" ignore-all, report-all, ignore-in-object-files,\n"
" ignore-in-shared-libs"),
TWO_DASHES },
{ {"verbose", optional_argument, NULL, OPTION_VERBOSE},
'\0', N_("[=NUMBER]"),
N_("Output lots of information during link"), TWO_DASHES },
{ {"dll-verbose", no_argument, NULL, OPTION_VERBOSE}, /* Linux. */
'\0', NULL, NULL, NO_HELP },
{ {"version-script", required_argument, NULL, OPTION_VERSION_SCRIPT },
'\0', N_("FILE"), N_("Read version information script"), TWO_DASHES },
{ {"version-exports-section", required_argument, NULL,
OPTION_VERSION_EXPORTS_SECTION },
'\0', N_("SYMBOL"), N_("Take export symbols list from .exports, using\n"
" SYMBOL as the version."),
TWO_DASHES },
{ {"dynamic-list-data", no_argument, NULL, OPTION_DYNAMIC_LIST_DATA},
'\0', NULL, N_("Add data symbols to dynamic list"), TWO_DASHES },
{ {"dynamic-list-cpp-new", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_NEW},
'\0', NULL, N_("Use C++ operator new/delete dynamic list"), TWO_DASHES },
{ {"dynamic-list-cpp-typeinfo", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_TYPEINFO},
'\0', NULL, N_("Use C++ typeinfo dynamic list"), TWO_DASHES },
{ {"dynamic-list", required_argument, NULL, OPTION_DYNAMIC_LIST},
'\0', N_("FILE"), N_("Read dynamic list"), TWO_DASHES },
{ {"warn-common", no_argument, NULL, OPTION_WARN_COMMON},
'\0', NULL, N_("Warn about duplicate common symbols"), TWO_DASHES },
{ {"warn-constructors", no_argument, NULL, OPTION_WARN_CONSTRUCTORS},
'\0', NULL, N_("Warn if global constructors/destructors are seen"),
TWO_DASHES },
{ {"warn-multiple-gp", no_argument, NULL, OPTION_WARN_MULTIPLE_GP},
'\0', NULL, N_("Warn if the multiple GP values are used"), TWO_DASHES },
{ {"warn-once", no_argument, NULL, OPTION_WARN_ONCE},
'\0', NULL, N_("Warn only once per undefined symbol"), TWO_DASHES },
{ {"warn-section-align", no_argument, NULL, OPTION_WARN_SECTION_ALIGN},
'\0', NULL, N_("Warn if start of section changes due to alignment"),
TWO_DASHES },
{ {"warn-shared-textrel", no_argument, NULL, OPTION_WARN_SHARED_TEXTREL},
'\0', NULL, N_("Warn if shared object has DT_TEXTREL"),
TWO_DASHES },
{ {"warn-alternate-em", no_argument, NULL, OPTION_WARN_ALTERNATE_EM},
'\0', NULL, N_("Warn if an object has alternate ELF machine code"),
TWO_DASHES },
{ {"warn-unresolved-symbols", no_argument, NULL,
OPTION_WARN_UNRESOLVED_SYMBOLS},
'\0', NULL, N_("Report unresolved symbols as warnings"), TWO_DASHES },
{ {"error-unresolved-symbols", no_argument, NULL,
OPTION_ERROR_UNRESOLVED_SYMBOLS},
'\0', NULL, N_("Report unresolved symbols as errors"), TWO_DASHES },
{ {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
'\0', NULL, N_("Include all objects from following archives"),
TWO_DASHES },
{ {"wrap", required_argument, NULL, OPTION_WRAP},
'\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES },
{ {"ignore-unresolved-symbol", required_argument, NULL,
OPTION_IGNORE_UNRESOLVED_SYMBOL},
'\0', N_("SYMBOL"),
N_("Unresolved SYMBOL will not cause an error or warning"), TWO_DASHES },
};
 
#define OPTION_COUNT ARRAY_SIZE (ld_options)
 
void
parse_args (unsigned argc, char **argv)
{
unsigned i;
int is, il, irl;
int ingroup = 0;
char *default_dirlist = NULL;
char *shortopts;
struct option *longopts;
struct option *really_longopts;
int last_optind;
enum report_method how_to_report_unresolved_symbols = RM_GENERATE_ERROR;
 
shortopts = (char *) xmalloc (OPTION_COUNT * 3 + 2);
longopts = (struct option *)
xmalloc (sizeof (*longopts) * (OPTION_COUNT + 1));
really_longopts = (struct option *)
malloc (sizeof (*really_longopts) * (OPTION_COUNT + 1));
 
/* Starting the short option string with '-' is for programs that
expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1. */
shortopts[0] = '-';
is = 1;
il = 0;
irl = 0;
for (i = 0; i < OPTION_COUNT; i++)
{
if (ld_options[i].shortopt != '\0')
{
shortopts[is] = ld_options[i].shortopt;
++is;
if (ld_options[i].opt.has_arg == required_argument
|| ld_options[i].opt.has_arg == optional_argument)
{
shortopts[is] = ':';
++is;
if (ld_options[i].opt.has_arg == optional_argument)
{
shortopts[is] = ':';
++is;
}
}
}
if (ld_options[i].opt.name != NULL)
{
if (ld_options[i].control == EXACTLY_TWO_DASHES)
{
really_longopts[irl] = ld_options[i].opt;
++irl;
}
else
{
longopts[il] = ld_options[i].opt;
++il;
}
}
}
shortopts[is] = '\0';
longopts[il].name = NULL;
really_longopts[irl].name = NULL;
 
ldemul_add_options (is, &shortopts, il, &longopts, irl, &really_longopts);
 
/* The -G option is ambiguous on different platforms. Sometimes it
specifies the largest data size to put into the small data
section. Sometimes it is equivalent to --shared. Unfortunately,
the first form takes an argument, while the second does not.
 
We need to permit the --shared form because on some platforms,
such as Solaris, gcc -shared will pass -G to the linker.
 
To permit either usage, we look through the argument list. If we
find -G not followed by a number, we change it into --shared.
This will work for most normal cases. */
for (i = 1; i < argc; i++)
if (strcmp (argv[i], "-G") == 0
&& (i + 1 >= argc
|| ! ISDIGIT (argv[i + 1][0])))
argv[i] = (char *) "--shared";
 
/* Because we permit long options to start with a single dash, and
we have a --library option, and the -l option is conventionally
used with an immediately following argument, we can have bad
results if somebody tries to use -l with a library whose name
happens to start with "ibrary", as in -li. We avoid problems by
simply turning -l into --library. This means that users will
have to use two dashes in order to use --library, which is OK
since that's how it is documented.
 
FIXME: It's possible that this problem can arise for other short
options as well, although the user does always have the recourse
of adding a space between the option and the argument. */
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-'
&& argv[i][1] == 'l'
&& argv[i][2] != '\0')
{
char *n;
 
n = (char *) xmalloc (strlen (argv[i]) + 20);
sprintf (n, "--library=%s", argv[i] + 2);
argv[i] = n;
}
}
 
last_optind = -1;
while (1)
{
int longind;
int optc;
static unsigned int defsym_count;
 
/* Using last_optind lets us avoid calling ldemul_parse_args
multiple times on a single option, which would lead to
confusion in the internal static variables maintained by
getopt. This could otherwise happen for an argument like
-nx, in which the -n is parsed as a single option, and we
loop around to pick up the -x. */
if (optind != last_optind)
if (ldemul_parse_args (argc, argv))
continue;
 
/* getopt_long_only is like getopt_long, but '-' as well as '--'
can indicate a long option. */
opterr = 0;
last_optind = optind;
optc = getopt_long_only (argc, argv, shortopts, longopts, &longind);
if (optc == '?')
{
optind = last_optind;
optc = getopt_long (argc, argv, "-", really_longopts, &longind);
}
 
if (ldemul_handle_option (optc))
continue;
 
if (optc == -1)
break;
 
switch (optc)
{
case '?':
einfo (_("%P: unrecognized option '%s'\n"), argv[last_optind]);
/* Fall through. */
 
default:
einfo (_("%P%F: use the --help option for usage information\n"));
 
case 1: /* File name. */
lang_add_input_file (optarg, lang_input_file_is_file_enum, NULL);
break;
 
case OPTION_IGNORE:
break;
case 'a':
/* For HP/UX compatibility. Actually -a shared should mean
``use only shared libraries'' but, then, we don't
currently support shared libraries on HP/UX anyhow. */
if (strcmp (optarg, "archive") == 0)
input_flags.dynamic = FALSE;
else if (strcmp (optarg, "shared") == 0
|| strcmp (optarg, "default") == 0)
input_flags.dynamic = TRUE;
else
einfo (_("%P%F: unrecognized -a option `%s'\n"), optarg);
break;
case OPTION_ASSERT:
/* FIXME: We just ignore these, but we should handle them. */
if (strcmp (optarg, "definitions") == 0)
;
else if (strcmp (optarg, "nodefinitions") == 0)
;
else if (strcmp (optarg, "nosymbolic") == 0)
;
else if (strcmp (optarg, "pure-text") == 0)
;
else
einfo (_("%P%F: unrecognized -assert option `%s'\n"), optarg);
break;
case 'A':
ldfile_add_arch (optarg);
break;
case 'b':
lang_add_target (optarg);
break;
case 'c':
ldfile_open_command_file (optarg);
parser_input = input_mri_script;
yyparse ();
break;
case OPTION_CALL_SHARED:
input_flags.dynamic = TRUE;
break;
case OPTION_NON_SHARED:
input_flags.dynamic = FALSE;
break;
case OPTION_CREF:
command_line.cref = TRUE;
link_info.notice_all = TRUE;
break;
case 'd':
command_line.force_common_definition = TRUE;
break;
case OPTION_DEFSYM:
lex_string = optarg;
lex_redirect (optarg, "--defsym", ++defsym_count);
parser_input = input_defsym;
yyparse ();
lex_string = NULL;
break;
case OPTION_DEMANGLE:
demangling = TRUE;
if (optarg != NULL)
{
enum demangling_styles style;
 
style = cplus_demangle_name_to_style (optarg);
if (style == unknown_demangling)
einfo (_("%F%P: unknown demangling style `%s'\n"),
optarg);
 
cplus_demangle_set_style (style);
}
break;
case 'I': /* Used on Solaris. */
case OPTION_DYNAMIC_LINKER:
command_line.interpreter = optarg;
break;
case OPTION_SYSROOT:
/* Already handled in ldmain.c. */
break;
case OPTION_EB:
command_line.endian = ENDIAN_BIG;
break;
case OPTION_EL:
command_line.endian = ENDIAN_LITTLE;
break;
case OPTION_EMBEDDED_RELOCS:
command_line.embedded_relocs = TRUE;
break;
case OPTION_EXPORT_DYNAMIC:
case 'E': /* HP/UX compatibility. */
link_info.export_dynamic = TRUE;
break;
case OPTION_NO_EXPORT_DYNAMIC:
link_info.export_dynamic = FALSE;
break;
case 'e':
lang_add_entry (optarg, TRUE);
break;
case 'f':
if (command_line.auxiliary_filters == NULL)
{
command_line.auxiliary_filters = (char **)
xmalloc (2 * sizeof (char *));
command_line.auxiliary_filters[0] = optarg;
command_line.auxiliary_filters[1] = NULL;
}
else
{
int c;
char **p;
 
c = 0;
for (p = command_line.auxiliary_filters; *p != NULL; p++)
++c;
command_line.auxiliary_filters = (char **)
xrealloc (command_line.auxiliary_filters,
(c + 2) * sizeof (char *));
command_line.auxiliary_filters[c] = optarg;
command_line.auxiliary_filters[c + 1] = NULL;
}
break;
case 'F':
command_line.filter_shlib = optarg;
break;
case OPTION_FORCE_EXE_SUFFIX:
command_line.force_exe_suffix = TRUE;
break;
case 'G':
{
char *end;
g_switch_value = strtoul (optarg, &end, 0);
if (*end)
einfo (_("%P%F: invalid number `%s'\n"), optarg);
}
break;
case 'g':
/* Ignore. */
break;
case OPTION_GC_SECTIONS:
link_info.gc_sections = TRUE;
break;
case OPTION_PRINT_GC_SECTIONS:
link_info.print_gc_sections = TRUE;
break;
case OPTION_HELP:
help ();
xexit (0);
break;
case 'L':
ldfile_add_library_path (optarg, TRUE);
break;
case 'l':
lang_add_input_file (optarg, lang_input_file_is_l_enum, NULL);
break;
case 'M':
config.map_filename = "-";
break;
case 'm':
/* Ignore. Was handled in a pre-parse. */
break;
case OPTION_MAP:
config.map_filename = optarg;
break;
case 'N':
config.text_read_only = FALSE;
config.magic_demand_paged = FALSE;
input_flags.dynamic = FALSE;
break;
case OPTION_NO_OMAGIC:
config.text_read_only = TRUE;
config.magic_demand_paged = TRUE;
/* NB/ Does not set input_flags.dynamic to TRUE.
Use --call-shared or -Bdynamic for this. */
break;
case 'n':
config.magic_demand_paged = FALSE;
input_flags.dynamic = FALSE;
break;
case OPTION_NO_DEFINE_COMMON:
command_line.inhibit_common_definition = TRUE;
break;
case OPTION_NO_DEMANGLE:
demangling = FALSE;
break;
case OPTION_NO_GC_SECTIONS:
link_info.gc_sections = FALSE;
break;
case OPTION_NO_PRINT_GC_SECTIONS:
link_info.print_gc_sections = FALSE;
break;
case OPTION_NO_KEEP_MEMORY:
link_info.keep_memory = FALSE;
break;
case OPTION_NO_UNDEFINED:
link_info.unresolved_syms_in_objects
= how_to_report_unresolved_symbols;
break;
case OPTION_ALLOW_SHLIB_UNDEFINED:
link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
break;
case OPTION_NO_ALLOW_SHLIB_UNDEFINED:
link_info.unresolved_syms_in_shared_libs
= how_to_report_unresolved_symbols;
break;
case OPTION_UNRESOLVED_SYMBOLS:
if (strcmp (optarg, "ignore-all") == 0)
{
link_info.unresolved_syms_in_objects = RM_IGNORE;
link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
}
else if (strcmp (optarg, "report-all") == 0)
{
link_info.unresolved_syms_in_objects
= how_to_report_unresolved_symbols;
link_info.unresolved_syms_in_shared_libs
= how_to_report_unresolved_symbols;
}
else if (strcmp (optarg, "ignore-in-object-files") == 0)
{
link_info.unresolved_syms_in_objects = RM_IGNORE;
link_info.unresolved_syms_in_shared_libs
= how_to_report_unresolved_symbols;
}
else if (strcmp (optarg, "ignore-in-shared-libs") == 0)
{
link_info.unresolved_syms_in_objects
= how_to_report_unresolved_symbols;
link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
}
else
einfo (_("%P%F: bad --unresolved-symbols option: %s\n"), optarg);
break;
case OPTION_WARN_UNRESOLVED_SYMBOLS:
how_to_report_unresolved_symbols = RM_GENERATE_WARNING;
if (link_info.unresolved_syms_in_objects == RM_GENERATE_ERROR)
link_info.unresolved_syms_in_objects = RM_GENERATE_WARNING;
if (link_info.unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)
link_info.unresolved_syms_in_shared_libs = RM_GENERATE_WARNING;
break;
 
case OPTION_ERROR_UNRESOLVED_SYMBOLS:
how_to_report_unresolved_symbols = RM_GENERATE_ERROR;
if (link_info.unresolved_syms_in_objects == RM_GENERATE_WARNING)
link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR;
if (link_info.unresolved_syms_in_shared_libs == RM_GENERATE_WARNING)
link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR;
break;
case OPTION_ALLOW_MULTIPLE_DEFINITION:
link_info.allow_multiple_definition = TRUE;
break;
case OPTION_NO_UNDEFINED_VERSION:
link_info.allow_undefined_version = FALSE;
break;
case OPTION_DEFAULT_SYMVER:
link_info.create_default_symver = TRUE;
break;
case OPTION_DEFAULT_IMPORTED_SYMVER:
link_info.default_imported_symver = TRUE;
break;
case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = FALSE;
break;
case OPTION_NO_WARN_SEARCH_MISMATCH:
command_line.warn_search_mismatch = FALSE;
break;
case OPTION_NOINHIBIT_EXEC:
force_make_executable = TRUE;
break;
case OPTION_NOSTDLIB:
config.only_cmd_line_lib_dirs = TRUE;
break;
case OPTION_NO_WHOLE_ARCHIVE:
input_flags.whole_archive = FALSE;
break;
case 'O':
/* FIXME "-O<non-digits> <value>" used to set the address of
section <non-digits>. Was this for compatibility with
something, or can we create a new option to do that
(with a syntax similar to -defsym)?
getopt can't handle two args to an option without kludges. */
 
/* Enable optimizations of output files. */
link_info.optimize = strtoul (optarg, NULL, 0) ? TRUE : FALSE;
break;
case 'o':
lang_add_output (optarg, 0);
break;
case OPTION_OFORMAT:
lang_add_output_format (optarg, NULL, NULL, 0);
break;
case OPTION_PRINT_OUTPUT_FORMAT:
command_line.print_output_format = TRUE;
break;
#ifdef ENABLE_PLUGINS
case OPTION_PLUGIN:
plugin_opt_plugin (optarg);
break;
case OPTION_PLUGIN_OPT:
if (plugin_opt_plugin_arg (optarg))
einfo(_("%P%F: bad -plugin-opt option\n"));
break;
#endif /* ENABLE_PLUGINS */
case 'q':
link_info.emitrelocations = TRUE;
break;
case 'i':
case 'r':
if (optind == last_optind)
/* This can happen if the user put "-rpath,a" on the command
line. (Or something similar. The comma is important).
Getopt becomes confused and thinks that this is a -r option
but it cannot parse the text after the -r so it refuses to
increment the optind counter. Detect this case and issue
an error message here. We cannot just make this a warning,
increment optind, and continue because getopt is too confused
and will seg-fault the next time around. */
einfo(_("%P%F: bad -rpath option\n"));
 
link_info.relocatable = TRUE;
config.build_constructors = FALSE;
config.magic_demand_paged = FALSE;
config.text_read_only = FALSE;
input_flags.dynamic = FALSE;
break;
case 'R':
/* The GNU linker traditionally uses -R to mean to include
only the symbols from a file. The Solaris linker uses -R
to set the path used by the runtime linker to find
libraries. This is the GNU linker -rpath argument. We
try to support both simultaneously by checking the file
named. If it is a directory, rather than a regular file,
we assume -rpath was meant. */
{
struct stat s;
 
if (stat (optarg, &s) >= 0
&& ! S_ISDIR (s.st_mode))
{
lang_add_input_file (optarg,
lang_input_file_is_symbols_only_enum,
NULL);
break;
}
}
/* Fall through. */
case OPTION_RPATH:
if (command_line.rpath == NULL)
command_line.rpath = xstrdup (optarg);
else
{
size_t rpath_len = strlen (command_line.rpath);
size_t optarg_len = strlen (optarg);
char *buf;
char *cp = command_line.rpath;
 
/* First see whether OPTARG is already in the path. */
do
{
if (strncmp (optarg, cp, optarg_len) == 0
&& (cp[optarg_len] == 0
|| cp[optarg_len] == config.rpath_separator))
/* We found it. */
break;
 
/* Not yet found. */
cp = strchr (cp, config.rpath_separator);
if (cp != NULL)
++cp;
}
while (cp != NULL);
 
if (cp == NULL)
{
buf = (char *) xmalloc (rpath_len + optarg_len + 2);
sprintf (buf, "%s%c%s", command_line.rpath,
config.rpath_separator, optarg);
free (command_line.rpath);
command_line.rpath = buf;
}
}
break;
case OPTION_RPATH_LINK:
if (command_line.rpath_link == NULL)
command_line.rpath_link = xstrdup (optarg);
else
{
char *buf;
 
buf = (char *) xmalloc (strlen (command_line.rpath_link)
+ strlen (optarg)
+ 2);
sprintf (buf, "%s%c%s", command_line.rpath_link,
config.rpath_separator, optarg);
free (command_line.rpath_link);
command_line.rpath_link = buf;
}
break;
case OPTION_NO_RELAX:
DISABLE_RELAXATION;
break;
case OPTION_RELAX:
ENABLE_RELAXATION;
break;
case OPTION_RETAIN_SYMBOLS_FILE:
add_keepsyms_file (optarg);
break;
case 'S':
link_info.strip = strip_debugger;
break;
case 's':
link_info.strip = strip_all;
break;
case OPTION_STRIP_DISCARDED:
link_info.strip_discarded = TRUE;
break;
case OPTION_NO_STRIP_DISCARDED:
link_info.strip_discarded = FALSE;
break;
case OPTION_SHARED:
if (config.has_shared)
{
link_info.shared = TRUE;
/* When creating a shared library, the default
behaviour is to ignore any unresolved references. */
if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
link_info.unresolved_syms_in_objects = RM_IGNORE;
if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
link_info.unresolved_syms_in_shared_libs = RM_IGNORE;
}
else
einfo (_("%P%F: -shared not supported\n"));
break;
case OPTION_PIE:
if (config.has_shared)
{
link_info.shared = TRUE;
link_info.pie = TRUE;
}
else
einfo (_("%P%F: -pie not supported\n"));
break;
case 'h': /* Used on Solaris. */
case OPTION_SONAME:
command_line.soname = optarg;
break;
case OPTION_SORT_COMMON:
if (optarg == NULL
|| strcmp (optarg, N_("descending")) == 0)
config.sort_common = sort_descending;
else if (strcmp (optarg, N_("ascending")) == 0)
config.sort_common = sort_ascending;
else
einfo (_("%P%F: invalid common section sorting option: %s\n"),
optarg);
break;
case OPTION_SORT_SECTION:
if (strcmp (optarg, N_("name")) == 0)
sort_section = by_name;
else if (strcmp (optarg, N_("alignment")) == 0)
sort_section = by_alignment;
else
einfo (_("%P%F: invalid section sorting option: %s\n"),
optarg);
break;
case OPTION_STATS:
config.stats = TRUE;
break;
case OPTION_SYMBOLIC:
command_line.symbolic = symbolic;
break;
case OPTION_SYMBOLIC_FUNCTIONS:
command_line.symbolic = symbolic_functions;
break;
case 't':
trace_files = TRUE;
break;
case 'T':
previous_script_handle = saved_script_handle;
ldfile_open_command_file (optarg);
parser_input = input_script;
yyparse ();
previous_script_handle = NULL;
break;
case OPTION_DEFAULT_SCRIPT:
command_line.default_script = optarg;
break;
case OPTION_SECTION_START:
{
char *optarg2;
char *sec_name;
int len;
 
/* Check for <something>=<somthing>... */
optarg2 = strchr (optarg, '=');
if (optarg2 == NULL)
einfo (_("%P%F: invalid argument to option"
" \"--section-start\"\n"));
 
optarg2++;
 
/* So far so good. Are all the args present? */
if ((*optarg == '\0') || (*optarg2 == '\0'))
einfo (_("%P%F: missing argument(s) to option"
" \"--section-start\"\n"));
 
/* We must copy the section name as set_section_start
doesn't do it for us. */
len = optarg2 - optarg;
sec_name = (char *) xmalloc (len);
memcpy (sec_name, optarg, len - 1);
sec_name[len - 1] = 0;
 
/* Then set it... */
set_section_start (sec_name, optarg2);
}
break;
case OPTION_TARGET_HELP:
/* Mention any target specific options. */
ldemul_list_emulation_options (stdout);
exit (0);
case OPTION_TBSS:
set_segment_start (".bss", optarg);
break;
case OPTION_TDATA:
set_segment_start (".data", optarg);
break;
case OPTION_TTEXT:
set_segment_start (".text", optarg);
break;
case OPTION_TTEXT_SEGMENT:
set_segment_start (".text-segment", optarg);
break;
case OPTION_TRODATA_SEGMENT:
set_segment_start (".rodata-segment", optarg);
break;
case OPTION_TLDATA_SEGMENT:
set_segment_start (".ldata-segment", optarg);
break;
case OPTION_TRADITIONAL_FORMAT:
link_info.traditional_format = TRUE;
break;
case OPTION_TASK_LINK:
link_info.task_link = TRUE;
/* Fall through - do an implied -r option. */
case OPTION_UR:
link_info.relocatable = TRUE;
config.build_constructors = TRUE;
config.magic_demand_paged = FALSE;
config.text_read_only = FALSE;
input_flags.dynamic = FALSE;
break;
case 'u':
ldlang_add_undef (optarg, TRUE);
break;
case OPTION_UNIQUE:
if (optarg != NULL)
lang_add_unique (optarg);
else
config.unique_orphan_sections = TRUE;
break;
case OPTION_VERBOSE:
ldversion (1);
version_printed = TRUE;
verbose = TRUE;
overflow_cutoff_limit = -2;
if (optarg != NULL)
{
char *end;
int level ATTRIBUTE_UNUSED = strtoul (optarg, &end, 0);
if (*end)
einfo (_("%P%F: invalid number `%s'\n"), optarg);
#ifdef ENABLE_PLUGINS
report_plugin_symbols = level > 1;
#endif /* ENABLE_PLUGINS */
}
break;
case 'v':
ldversion (0);
version_printed = TRUE;
break;
case 'V':
ldversion (1);
version_printed = TRUE;
break;
case OPTION_VERSION:
ldversion (2);
xexit (0);
break;
case OPTION_VERSION_SCRIPT:
/* This option indicates a small script that only specifies
version information. Read it, but don't assume that
we've seen a linker script. */
{
FILE *hold_script_handle;
 
hold_script_handle = saved_script_handle;
ldfile_open_command_file (optarg);
saved_script_handle = hold_script_handle;
parser_input = input_version_script;
yyparse ();
}
break;
case OPTION_VERSION_EXPORTS_SECTION:
/* This option records a version symbol to be applied to the
symbols listed for export to be found in the object files
.exports sections. */
command_line.version_exports_section = optarg;
break;
case OPTION_DYNAMIC_LIST_DATA:
command_line.dynamic_list = dynamic_list_data;
if (command_line.symbolic == symbolic)
command_line.symbolic = symbolic_unset;
break;
case OPTION_DYNAMIC_LIST_CPP_TYPEINFO:
lang_append_dynamic_list_cpp_typeinfo ();
if (command_line.dynamic_list != dynamic_list_data)
command_line.dynamic_list = dynamic_list;
if (command_line.symbolic == symbolic)
command_line.symbolic = symbolic_unset;
break;
case OPTION_DYNAMIC_LIST_CPP_NEW:
lang_append_dynamic_list_cpp_new ();
if (command_line.dynamic_list != dynamic_list_data)
command_line.dynamic_list = dynamic_list;
if (command_line.symbolic == symbolic)
command_line.symbolic = symbolic_unset;
break;
case OPTION_DYNAMIC_LIST:
/* This option indicates a small script that only specifies
a dynamic list. Read it, but don't assume that we've
seen a linker script. */
{
FILE *hold_script_handle;
 
hold_script_handle = saved_script_handle;
ldfile_open_command_file (optarg);
saved_script_handle = hold_script_handle;
parser_input = input_dynamic_list;
yyparse ();
}
if (command_line.dynamic_list != dynamic_list_data)
command_line.dynamic_list = dynamic_list;
if (command_line.symbolic == symbolic)
command_line.symbolic = symbolic_unset;
break;
case OPTION_WARN_COMMON:
config.warn_common = TRUE;
break;
case OPTION_WARN_CONSTRUCTORS:
config.warn_constructors = TRUE;
break;
case OPTION_WARN_FATAL:
config.fatal_warnings = TRUE;
break;
case OPTION_NO_WARN_FATAL:
config.fatal_warnings = FALSE;
break;
case OPTION_WARN_MULTIPLE_GP:
config.warn_multiple_gp = TRUE;
break;
case OPTION_WARN_ONCE:
config.warn_once = TRUE;
break;
case OPTION_WARN_SECTION_ALIGN:
config.warn_section_align = TRUE;
break;
case OPTION_WARN_SHARED_TEXTREL:
link_info.warn_shared_textrel = TRUE;
break;
case OPTION_WARN_ALTERNATE_EM:
link_info.warn_alternate_em = TRUE;
break;
case OPTION_WHOLE_ARCHIVE:
input_flags.whole_archive = TRUE;
break;
case OPTION_ADD_DT_NEEDED_FOR_DYNAMIC:
input_flags.add_DT_NEEDED_for_dynamic = TRUE;
break;
case OPTION_NO_ADD_DT_NEEDED_FOR_DYNAMIC:
input_flags.add_DT_NEEDED_for_dynamic = FALSE;
break;
case OPTION_ADD_DT_NEEDED_FOR_REGULAR:
input_flags.add_DT_NEEDED_for_regular = TRUE;
break;
case OPTION_NO_ADD_DT_NEEDED_FOR_REGULAR:
input_flags.add_DT_NEEDED_for_regular = FALSE;
break;
case OPTION_WRAP:
add_wrap (optarg);
break;
case OPTION_IGNORE_UNRESOLVED_SYMBOL:
add_ignoresym (&link_info, optarg);
break;
case OPTION_DISCARD_NONE:
link_info.discard = discard_none;
break;
case 'X':
link_info.discard = discard_l;
break;
case 'x':
link_info.discard = discard_all;
break;
case 'Y':
if (CONST_STRNEQ (optarg, "P,"))
optarg += 2;
if (default_dirlist != NULL)
free (default_dirlist);
default_dirlist = xstrdup (optarg);
break;
case 'y':
add_ysym (optarg);
break;
case OPTION_SPARE_DYNAMIC_TAGS:
link_info.spare_dynamic_tags = strtoul (optarg, NULL, 0);
break;
case OPTION_SPLIT_BY_RELOC:
if (optarg != NULL)
config.split_by_reloc = strtoul (optarg, NULL, 0);
else
config.split_by_reloc = 32768;
break;
case OPTION_SPLIT_BY_FILE:
if (optarg != NULL)
config.split_by_file = bfd_scan_vma (optarg, NULL, 0);
else
config.split_by_file = 1;
break;
case OPTION_CHECK_SECTIONS:
command_line.check_section_addresses = 1;
break;
case OPTION_NO_CHECK_SECTIONS:
command_line.check_section_addresses = 0;
break;
case OPTION_ACCEPT_UNKNOWN_INPUT_ARCH:
command_line.accept_unknown_input_arch = TRUE;
break;
case OPTION_NO_ACCEPT_UNKNOWN_INPUT_ARCH:
command_line.accept_unknown_input_arch = FALSE;
break;
case '(':
lang_enter_group ();
ingroup++;
break;
case ')':
if (! ingroup)
einfo (_("%P%F: group ended before it began (--help for usage)\n"));
 
lang_leave_group ();
ingroup--;
break;
 
case OPTION_INIT:
link_info.init_function = optarg;
break;
 
case OPTION_FINI:
link_info.fini_function = optarg;
break;
 
case OPTION_REDUCE_MEMORY_OVERHEADS:
link_info.reduce_memory_overheads = TRUE;
if (config.hash_table_size == 0)
config.hash_table_size = 1021;
break;
 
case OPTION_HASH_SIZE:
{
bfd_size_type new_size;
 
new_size = strtoul (optarg, NULL, 0);
if (new_size)
config.hash_table_size = new_size;
else
einfo (_("%P%X: --hash-size needs a numeric argument\n"));
}
break;
}
}
 
while (ingroup)
{
lang_leave_group ();
ingroup--;
}
 
if (default_dirlist != NULL)
{
set_default_dirlist (default_dirlist);
free (default_dirlist);
}
 
if (link_info.unresolved_syms_in_objects == RM_NOT_YET_SET)
/* FIXME: Should we allow emulations a chance to set this ? */
link_info.unresolved_syms_in_objects = how_to_report_unresolved_symbols;
 
if (link_info.unresolved_syms_in_shared_libs == RM_NOT_YET_SET)
/* FIXME: Should we allow emulations a chance to set this ? */
link_info.unresolved_syms_in_shared_libs = how_to_report_unresolved_symbols;
 
if (link_info.relocatable)
{
if (command_line.check_section_addresses < 0)
command_line.check_section_addresses = 0;
if (link_info.shared)
einfo (_("%P%F: -r and -shared may not be used together\n"));
}
 
/* We may have -Bsymbolic, -Bsymbolic-functions, --dynamic-list-data,
--dynamic-list-cpp-new, --dynamic-list-cpp-typeinfo and
--dynamic-list FILE. -Bsymbolic and -Bsymbolic-functions are
for shared libraries. -Bsymbolic overrides all others and vice
versa. */
switch (command_line.symbolic)
{
case symbolic_unset:
break;
case symbolic:
/* -Bsymbolic is for shared library only. */
if (link_info.shared)
{
link_info.symbolic = TRUE;
/* Should we free the unused memory? */
link_info.dynamic_list = NULL;
command_line.dynamic_list = dynamic_list_unset;
}
break;
case symbolic_functions:
/* -Bsymbolic-functions is for shared library only. */
if (link_info.shared)
command_line.dynamic_list = dynamic_list_data;
break;
}
 
switch (command_line.dynamic_list)
{
case dynamic_list_unset:
break;
case dynamic_list_data:
link_info.dynamic_data = TRUE;
case dynamic_list:
link_info.dynamic = TRUE;
break;
}
 
if (! link_info.shared)
{
if (command_line.filter_shlib)
einfo (_("%P%F: -F may not be used without -shared\n"));
if (command_line.auxiliary_filters)
einfo (_("%P%F: -f may not be used without -shared\n"));
}
 
if (! link_info.shared || link_info.pie)
link_info.executable = TRUE;
 
/* Treat ld -r -s as ld -r -S -x (i.e., strip all local symbols). I
don't see how else this can be handled, since in this case we
must preserve all externally visible symbols. */
if (link_info.relocatable && link_info.strip == strip_all)
{
link_info.strip = strip_debugger;
if (link_info.discard == discard_sec_merge)
link_info.discard = discard_all;
}
}
 
/* Add the (colon-separated) elements of DIRLIST_PTR to the
library search path. */
 
static void
set_default_dirlist (char *dirlist_ptr)
{
char *p;
 
while (1)
{
p = strchr (dirlist_ptr, PATH_SEPARATOR);
if (p != NULL)
*p = '\0';
if (*dirlist_ptr != '\0')
ldfile_add_library_path (dirlist_ptr, TRUE);
if (p == NULL)
break;
dirlist_ptr = p + 1;
}
}
 
static void
set_section_start (char *sect, char *valstr)
{
const char *end;
bfd_vma val = bfd_scan_vma (valstr, &end, 16);
if (*end)
einfo (_("%P%F: invalid hex number `%s'\n"), valstr);
lang_section_start (sect, exp_intop (val), NULL);
}
 
static void
set_segment_start (const char *section, char *valstr)
{
const char *name;
const char *end;
segment_type *seg;
 
bfd_vma val = bfd_scan_vma (valstr, &end, 16);
if (*end)
einfo (_("%P%F: invalid hex number `%s'\n"), valstr);
/* If we already have an entry for this segment, update the existing
value. */
name = section + 1;
for (seg = segments; seg; seg = seg->next)
if (strcmp (seg->name, name) == 0)
{
seg->value = val;
return;
}
/* There was no existing value so we must create a new segment
entry. */
seg = (segment_type *) stat_alloc (sizeof (*seg));
seg->name = name;
seg->value = val;
seg->used = FALSE;
/* Add it to the linked list of segments. */
seg->next = segments;
segments = seg;
/* Historically, -Ttext and friends set the base address of a
particular section. For backwards compatibility, we still do
that. If a SEGMENT_START directive is seen, the section address
assignment will be disabled. */
lang_section_start (section, exp_intop (val), seg);
}
 
/* Print help messages for the options. */
 
static void
help (void)
{
unsigned i;
const char **targets, **pp;
int len;
 
printf (_("Usage: %s [options] file...\n"), program_name);
 
printf (_("Options:\n"));
for (i = 0; i < OPTION_COUNT; i++)
{
if (ld_options[i].doc != NULL)
{
bfd_boolean comma;
unsigned j;
 
printf (" ");
 
comma = FALSE;
len = 2;
 
j = i;
do
{
if (ld_options[j].shortopt != '\0'
&& ld_options[j].control != NO_HELP)
{
printf ("%s-%c", comma ? ", " : "", ld_options[j].shortopt);
len += (comma ? 2 : 0) + 2;
if (ld_options[j].arg != NULL)
{
if (ld_options[j].opt.has_arg != optional_argument)
{
printf (" ");
++len;
}
printf ("%s", _(ld_options[j].arg));
len += strlen (_(ld_options[j].arg));
}
comma = TRUE;
}
++j;
}
while (j < OPTION_COUNT && ld_options[j].doc == NULL);
 
j = i;
do
{
if (ld_options[j].opt.name != NULL
&& ld_options[j].control != NO_HELP)
{
int two_dashes =
(ld_options[j].control == TWO_DASHES
|| ld_options[j].control == EXACTLY_TWO_DASHES);
 
printf ("%s-%s%s",
comma ? ", " : "",
two_dashes ? "-" : "",
ld_options[j].opt.name);
len += ((comma ? 2 : 0)
+ 1
+ (two_dashes ? 1 : 0)
+ strlen (ld_options[j].opt.name));
if (ld_options[j].arg != NULL)
{
printf (" %s", _(ld_options[j].arg));
len += 1 + strlen (_(ld_options[j].arg));
}
comma = TRUE;
}
++j;
}
while (j < OPTION_COUNT && ld_options[j].doc == NULL);
 
if (len >= 30)
{
printf ("\n");
len = 0;
}
 
for (; len < 30; len++)
putchar (' ');
 
printf ("%s\n", _(ld_options[i].doc));
}
}
printf (_(" @FILE"));
for (len = strlen (" @FILE"); len < 30; len++)
putchar (' ');
printf (_("Read options from FILE\n"));
 
/* Note: Various tools (such as libtool) depend upon the
format of the listings below - do not change them. */
/* xgettext:c-format */
printf (_("%s: supported targets:"), program_name);
targets = bfd_target_list ();
for (pp = targets; *pp != NULL; pp++)
printf (" %s", *pp);
free (targets);
printf ("\n");
 
/* xgettext:c-format */
printf (_("%s: supported emulations: "), program_name);
ldemul_list_emulations (stdout);
printf ("\n");
 
/* xgettext:c-format */
printf (_("%s: emulation specific options:\n"), program_name);
ldemul_list_emulation_options (stdout);
printf ("\n");
 
if (REPORT_BUGS_TO[0])
printf (_("Report bugs to %s\n"), REPORT_BUGS_TO);
}
/contrib/toolchain/binutils/ld/mri.c
0,0 → 1,319
/* mri.c -- handle MRI style linker scripts
Copyright 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2007, 2011 Free Software Foundation, Inc.
Contributed by Steve Chamberlain <sac@cygnus.com>.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
 
/* This bit does the tree decoration when MRI style link scripts
are parsed. */
 
#include "sysdep.h"
#include "bfd.h"
#include "ld.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldmisc.h"
#include "mri.h"
#include <ldgram.h>
#include "libiberty.h"
 
struct section_name_struct {
struct section_name_struct *next;
const char *name;
const char *alias;
etree_type *vma;
etree_type *align;
etree_type *subalign;
int ok_to_load;
};
 
static unsigned int symbol_truncate = 10000;
static struct section_name_struct *order;
static struct section_name_struct *only_load;
static struct section_name_struct *address;
static struct section_name_struct *alias;
 
static struct section_name_struct *alignment;
static struct section_name_struct *subalignment;
 
static struct section_name_struct **
lookup (const char *name, struct section_name_struct **list)
{
struct section_name_struct **ptr = list;
 
while (*ptr)
{
if (strcmp (name, (*ptr)->name) == 0)
/* If this is a match, delete it, we only keep the last instance
of any name. */
*ptr = (*ptr)->next;
else
ptr = &((*ptr)->next);
}
 
*ptr = (struct section_name_struct *)
xmalloc (sizeof (struct section_name_struct));
return ptr;
}
 
static void
mri_add_to_list (struct section_name_struct **list,
const char *name,
etree_type *vma,
const char *zalias,
etree_type *align,
etree_type *subalign)
{
struct section_name_struct **ptr = lookup (name, list);
 
(*ptr)->name = name;
(*ptr)->vma = vma;
(*ptr)->next = NULL;
(*ptr)->ok_to_load = 0;
(*ptr)->alias = zalias;
(*ptr)->align = align;
(*ptr)->subalign = subalign;
}
 
void
mri_output_section (const char *name, etree_type *vma)
{
mri_add_to_list (&address, name, vma, 0, 0, 0);
}
 
/* If any ABSOLUTE <name> are in the script, only load those files
marked thus. */
 
void
mri_only_load (const char *name)
{
mri_add_to_list (&only_load, name, 0, 0, 0, 0);
}
 
void
mri_base (etree_type *exp)
{
base = exp;
}
 
static int done_tree = 0;
 
void
mri_draw_tree (void)
{
if (done_tree)
return;
 
/* Now build the statements for the ldlang machine. */
 
/* Attach the addresses of any which have addresses,
and add the ones not mentioned. */
if (address != NULL)
{
struct section_name_struct *alist;
struct section_name_struct *olist;
 
if (order == NULL)
order = address;
 
for (alist = address;
alist != NULL;
alist = alist->next)
{
int done = 0;
 
for (olist = order; done == 0 && olist != NULL; olist = olist->next)
{
if (strcmp (alist->name, olist->name) == 0)
{
olist->vma = alist->vma;
done = 1;
}
}
 
if (!done)
{
/* Add this onto end of order list. */
mri_add_to_list (&order, alist->name, alist->vma, 0, 0, 0);
}
}
}
 
/* If we're only supposed to load a subset of them in, then prune
the list. */
if (only_load != NULL)
{
struct section_name_struct *ptr1;
struct section_name_struct *ptr2;
 
if (order == NULL)
order = only_load;
 
/* See if this name is in the list, if it is then we can load it. */
for (ptr1 = only_load; ptr1; ptr1 = ptr1->next)
for (ptr2 = order; ptr2; ptr2 = ptr2->next)
if (strcmp (ptr2->name, ptr1->name) == 0)
ptr2->ok_to_load = 1;
}
else
{
/* No only load list, so everything is ok to load. */
struct section_name_struct *ptr;
 
for (ptr = order; ptr; ptr = ptr->next)
ptr->ok_to_load = 1;
}
 
/* Create the order of sections to load. */
if (order != NULL)
{
/* Been told to output the sections in a certain order. */
struct section_name_struct *p = order;
 
while (p)
{
struct section_name_struct *aptr;
etree_type *align = 0;
etree_type *subalign = 0;
struct wildcard_list *tmp;
 
/* See if an alignment has been specified. */
for (aptr = alignment; aptr; aptr = aptr->next)
if (strcmp (aptr->name, p->name) == 0)
align = aptr->align;
 
for (aptr = subalignment; aptr; aptr = aptr->next)
if (strcmp (aptr->name, p->name) == 0)
subalign = aptr->subalign;
 
if (base == 0)
base = p->vma ? p->vma : exp_nameop (NAME, ".");
 
lang_enter_output_section_statement (p->name, base,
p->ok_to_load ? normal_section : noload_section,
align, subalign, NULL, 0, 0);
base = 0;
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = NULL;
tmp->spec.name = p->name;
tmp->spec.exclude_name_list = NULL;
tmp->spec.sorted = none;
tmp->spec.section_flag_list = NULL;
lang_add_wild (NULL, tmp, FALSE);
 
/* If there is an alias for this section, add it too. */
for (aptr = alias; aptr; aptr = aptr->next)
if (strcmp (aptr->alias, p->name) == 0)
{
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = NULL;
tmp->spec.name = aptr->name;
tmp->spec.exclude_name_list = NULL;
tmp->spec.sorted = none;
tmp->spec.section_flag_list = NULL;
lang_add_wild (NULL, tmp, FALSE);
}
 
lang_leave_output_section_statement (0, "*default*", NULL, NULL);
 
p = p->next;
}
}
 
done_tree = 1;
}
 
void
mri_load (const char *name)
{
base = 0;
lang_add_input_file (name, lang_input_file_is_file_enum, NULL);
}
 
void
mri_order (const char *name)
{
mri_add_to_list (&order, name, 0, 0, 0, 0);
}
 
void
mri_alias (const char *want, const char *is, int isn)
{
if (!is)
{
char buf[20];
 
/* Some sections are digits. */
sprintf (buf, "%d", isn);
 
is = xstrdup (buf);
 
if (is == NULL)
abort ();
}
 
mri_add_to_list (&alias, is, 0, want, 0, 0);
}
 
void
mri_name (const char *name)
{
lang_add_output (name, 1);
}
 
void
mri_format (const char *name)
{
if (strcmp (name, "S") == 0)
lang_add_output_format ("srec", NULL, NULL, 1);
 
else if (strcmp (name, "IEEE") == 0)
lang_add_output_format ("ieee", NULL, NULL, 1);
 
else if (strcmp (name, "COFF") == 0)
lang_add_output_format ("coff-m68k", NULL, NULL, 1);
 
else
einfo (_("%P%F: unknown format type %s\n"), name);
}
 
void
mri_public (const char *name, etree_type *exp)
{
lang_add_assignment (exp_assign (name, exp, FALSE));
}
 
void
mri_align (const char *name, etree_type *exp)
{
mri_add_to_list (&alignment, name, 0, 0, exp, 0);
}
 
void
mri_alignmod (const char *name, etree_type *exp)
{
mri_add_to_list (&subalignment, name, 0, 0, 0, exp);
}
 
void
mri_truncate (unsigned int exp)
{
symbol_truncate = exp;
}
/contrib/toolchain/binutils/ld/mri.h
0,0 → 1,38
/* mri.h -- header file for MRI scripting functions
Copyright 1993, 1995, 1996, 2003, 2005, 2007 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef MRI_H
#define MRI_H
 
extern void mri_output_section (const char *, etree_type *);
extern void mri_only_load (const char *);
extern void mri_base (etree_type *);
extern void mri_load (const char *);
extern void mri_order (const char *);
extern void mri_alias (const char *, const char *, int);
extern void mri_name (const char *);
extern void mri_format (const char *);
extern void mri_public (const char *, etree_type *);
extern void mri_align (const char *, etree_type *);
extern void mri_alignmod (const char *, etree_type *);
extern void mri_truncate (unsigned int);
extern void mri_draw_tree (void);
 
#endif
/contrib/toolchain/binutils/ld/pe-dll.c
0,0 → 1,3452
/* Routines to help build PEI-format DLLs (Win32 etc)
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Written by DJ Delorie <dj@cygnus.com>
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "libiberty.h"
#include "filenames.h"
#include "safe-ctype.h"
 
#include <time.h>
 
#include "ld.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldwrite.h"
#include "ldmisc.h"
#include <ldgram.h>
#include "ldmain.h"
#include "ldfile.h"
#include "ldemul.h"
#include "coff/internal.h"
#include "../bfd/libcoff.h"
#include "deffile.h"
 
#ifdef pe_use_x86_64
 
#define PE_IDATA4_SIZE 8
#define PE_IDATA5_SIZE 8
#include "pep-dll.h"
#undef AOUTSZ
#define AOUTSZ PEPAOUTSZ
#define PEAOUTHDR PEPAOUTHDR
 
#else
 
#include "pe-dll.h"
 
#endif
 
#ifndef PE_IDATA4_SIZE
#define PE_IDATA4_SIZE 4
#endif
 
#ifndef PE_IDATA5_SIZE
#define PE_IDATA5_SIZE 4
#endif
 
/* This file turns a regular Windows PE image into a DLL. Because of
the complexity of this operation, it has been broken down into a
number of separate modules which are all called by the main function
at the end of this file. This function is not re-entrant and is
normally only called once, so static variables are used to reduce
the number of parameters and return values required.
 
See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */
 
/* Auto-import feature by Paul Sokolovsky
 
Quick facts:
 
1. With this feature on, DLL clients can import variables from DLL
without any concern from their side (for example, without any source
code modifications).
 
2. This is done completely in bounds of the PE specification (to be fair,
there's a place where it pokes nose out of, but in practice it works).
So, resulting module can be used with any other PE compiler/linker.
 
3. Auto-import is fully compatible with standard import method and they
can be mixed together.
 
4. Overheads: space: 8 bytes per imported symbol, plus 20 for each
reference to it; load time: negligible; virtual/physical memory: should be
less than effect of DLL relocation, and I sincerely hope it doesn't affect
DLL sharability (too much).
 
Idea
 
The obvious and only way to get rid of dllimport insanity is to make client
access variable directly in the DLL, bypassing extra dereference. I.e.,
whenever client contains something like
 
mov dll_var,%eax,
 
address of dll_var in the command should be relocated to point into loaded
DLL. The aim is to make OS loader do so, and than make ld help with that.
Import section of PE made following way: there's a vector of structures
each describing imports from particular DLL. Each such structure points
to two other parallel vectors: one holding imported names, and one which
will hold address of corresponding imported name. So, the solution is
de-vectorize these structures, making import locations be sparse and
pointing directly into code. Before continuing, it is worth a note that,
while authors strives to make PE act ELF-like, there're some other people
make ELF act PE-like: elfvector, ;-) .
 
Implementation
 
For each reference of data symbol to be imported from DLL (to set of which
belong symbols with name <sym>, if __imp_<sym> is found in implib), the
import fixup entry is generated. That entry is of type
IMAGE_IMPORT_DESCRIPTOR and stored in .idata$2 subsection. Each
fixup entry contains pointer to symbol's address within .text section
(marked with __fuN_<sym> symbol, where N is integer), pointer to DLL name
(so, DLL name is referenced by multiple entries), and pointer to symbol
name thunk. Symbol name thunk is singleton vector (__nm_th_<symbol>)
pointing to IMAGE_IMPORT_BY_NAME structure (__nm_<symbol>) directly
containing imported name. Here comes that "on the edge" problem mentioned
above: PE specification rambles that name vector (OriginalFirstThunk)
should run in parallel with addresses vector (FirstThunk), i.e. that they
should have same number of elements and terminated with zero. We violate
this, since FirstThunk points directly into machine code. But in practice,
OS loader implemented the sane way: it goes thru OriginalFirstThunk and
puts addresses to FirstThunk, not something else. It once again should be
noted that dll and symbol name structures are reused across fixup entries
and should be there anyway to support standard import stuff, so sustained
overhead is 20 bytes per reference. Other question is whether having several
IMAGE_IMPORT_DESCRIPTORS for the same DLL is possible. Answer is yes, it is
done even by native compiler/linker (libth32's functions are in fact reside
in windows9x kernel32.dll, so if you use it, you have two
IMAGE_IMPORT_DESCRIPTORS for kernel32.dll). Yet other question is whether
referencing the same PE structures several times is valid. The answer is why
not, prohibiting that (detecting violation) would require more work on
behalf of loader than not doing it.
 
See also: ld/emultempl/pe.em and ld/emultempl/pep.em. */
 
static void add_bfd_to_link (bfd *, const char *, struct bfd_link_info *);
 
/* For emultempl/pe.em. */
 
def_file * pe_def_file = 0;
int pe_dll_export_everything = 0;
int pe_dll_exclude_all_symbols = 0;
int pe_dll_do_default_excludes = 1;
int pe_dll_kill_ats = 0;
int pe_dll_stdcall_aliases = 0;
int pe_dll_warn_dup_exports = 0;
int pe_dll_compat_implib = 0;
int pe_dll_extra_pe_debug = 0;
int pe_use_nul_prefixed_import_tables = 0;
int pe_use_coff_long_section_names = -1;
int pe_leading_underscore = -1;
 
/* Static variables and types. */
 
static bfd_vma image_base;
static bfd *filler_bfd;
static struct bfd_section *edata_s, *reloc_s;
static unsigned char *edata_d, *reloc_d;
static size_t edata_sz, reloc_sz;
static int runtime_pseudo_relocs_created = 0;
static int runtime_pseudp_reloc_v2_init = 0;
 
typedef struct
{
const char *name;
int len;
}
autofilter_entry_type;
 
typedef struct
{
const char *target_name;
const char *object_target;
unsigned int imagebase_reloc;
int pe_arch;
int bfd_arch;
bfd_boolean underscored;
const autofilter_entry_type* autofilter_symbollist;
}
pe_details_type;
 
static const autofilter_entry_type autofilter_symbollist_generic[] =
{
{ STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") },
/* Entry point symbols. */
{ STRING_COMMA_LEN ("DllMain") },
{ STRING_COMMA_LEN ("DllMainCRTStartup") },
{ STRING_COMMA_LEN ("_DllMainCRTStartup") },
/* Runtime pseudo-reloc. */
{ STRING_COMMA_LEN ("_pei386_runtime_relocator") },
{ STRING_COMMA_LEN ("do_pseudo_reloc") },
{ NULL, 0 }
};
 
static const autofilter_entry_type autofilter_symbollist_i386[] =
{
{ STRING_COMMA_LEN ("_NULL_IMPORT_DESCRIPTOR") },
/* Entry point symbols, and entry hooks. */
{ STRING_COMMA_LEN ("cygwin_crt0") },
#ifdef pe_use_x86_64
{ STRING_COMMA_LEN ("DllMain") },
{ STRING_COMMA_LEN ("DllEntryPoint") },
{ STRING_COMMA_LEN ("DllMainCRTStartup") },
{ STRING_COMMA_LEN ("_cygwin_dll_entry") },
{ STRING_COMMA_LEN ("_cygwin_crt0_common") },
{ STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry") },
#else
{ STRING_COMMA_LEN ("DllMain@12") },
{ STRING_COMMA_LEN ("DllEntryPoint@0") },
{ STRING_COMMA_LEN ("DllMainCRTStartup@12") },
{ STRING_COMMA_LEN ("_cygwin_dll_entry@12") },
{ STRING_COMMA_LEN ("_cygwin_crt0_common@8") },
{ STRING_COMMA_LEN ("_cygwin_noncygwin_dll_entry@12") },
{ STRING_COMMA_LEN ("cygwin_attach_dll") },
#endif
{ STRING_COMMA_LEN ("cygwin_premain0") },
{ STRING_COMMA_LEN ("cygwin_premain1") },
{ STRING_COMMA_LEN ("cygwin_premain2") },
{ STRING_COMMA_LEN ("cygwin_premain3") },
/* Runtime pseudo-reloc. */
{ STRING_COMMA_LEN ("_pei386_runtime_relocator") },
{ STRING_COMMA_LEN ("do_pseudo_reloc") },
/* Global vars that should not be exported. */
{ STRING_COMMA_LEN ("impure_ptr") },
{ STRING_COMMA_LEN ("_impure_ptr") },
{ STRING_COMMA_LEN ("_fmode") },
{ STRING_COMMA_LEN ("environ") },
{ NULL, 0 }
};
 
#define PE_ARCH_i386 1
#define PE_ARCH_sh 2
#define PE_ARCH_mips 3
#define PE_ARCH_arm 4
#define PE_ARCH_arm_epoc 5
#define PE_ARCH_arm_wince 6
 
/* Don't make it constant as underscore mode gets possibly overriden
by target or -(no-)leading-underscore option. */
static pe_details_type pe_detail_list[] =
{
{
#ifdef pe_use_x86_64
"pei-x86-64",
"pe-x86-64",
3 /* R_IMAGEBASE */,
#else
"pei-i386",
"pe-i386",
7 /* R_IMAGEBASE */,
#endif
PE_ARCH_i386,
bfd_arch_i386,
#ifdef pe_use_x86_64
FALSE,
#else
TRUE,
#endif
autofilter_symbollist_i386
},
{
"pei-shl",
"pe-shl",
16 /* R_SH_IMAGEBASE */,
PE_ARCH_sh,
bfd_arch_sh,
TRUE,
autofilter_symbollist_generic
},
{
"pei-mips",
"pe-mips",
34 /* MIPS_R_RVA */,
PE_ARCH_mips,
bfd_arch_mips,
FALSE,
autofilter_symbollist_generic
},
{
"pei-arm-little",
"pe-arm-little",
11 /* ARM_RVA32 */,
PE_ARCH_arm,
bfd_arch_arm,
TRUE,
autofilter_symbollist_generic
},
{
"epoc-pei-arm-little",
"epoc-pe-arm-little",
11 /* ARM_RVA32 */,
PE_ARCH_arm_epoc,
bfd_arch_arm,
FALSE,
autofilter_symbollist_generic
},
{
"pei-arm-wince-little",
"pe-arm-wince-little",
2, /* ARM_RVA32 on Windows CE, see bfd/coff-arm.c. */
PE_ARCH_arm_wince,
bfd_arch_arm,
FALSE,
autofilter_symbollist_generic
},
{ NULL, NULL, 0, 0, 0, FALSE, NULL }
};
 
static const pe_details_type *pe_details;
 
/* Do not specify library suffix explicitly, to allow for dllized versions. */
static const autofilter_entry_type autofilter_liblist[] =
{
{ STRING_COMMA_LEN ("libcegcc") },
{ STRING_COMMA_LEN ("libcygwin") },
{ STRING_COMMA_LEN ("libgcc") },
{ STRING_COMMA_LEN ("libgcc_s") },
{ STRING_COMMA_LEN ("libstdc++") },
{ STRING_COMMA_LEN ("libmingw32") },
{ STRING_COMMA_LEN ("libmingwex") },
{ STRING_COMMA_LEN ("libg2c") },
{ STRING_COMMA_LEN ("libsupc++") },
{ STRING_COMMA_LEN ("libobjc") },
{ STRING_COMMA_LEN ("libgcj") },
{ NULL, 0 }
};
 
/* Regardless of the suffix issue mentioned above, we must ensure that
we do not falsely match on a leading substring, such as when libtool
builds libstdc++ as a DLL using libsupc++convenience.a as an intermediate.
This routine ensures that the leading part of the name matches and that
it is followed by only an optional version suffix and a file extension,
returning zero if so or -1 if not. */
static int libnamencmp (const char *libname, const autofilter_entry_type *afptr)
{
if (filename_ncmp (libname, afptr->name, afptr->len))
return -1;
 
libname += afptr->len;
 
/* Be liberal in interpreting what counts as a version suffix; we
accept anything that has a dash to separate it from the name and
begins with a digit. */
if (libname[0] == '-')
{
if (!ISDIGIT (*++libname))
return -1;
/* Ensure the filename has an extension. */
while (*++libname != '.')
if (!*libname)
return -1;
}
else if (libname[0] != '.')
return -1;
 
return 0;
}
 
static const autofilter_entry_type autofilter_objlist[] =
{
{ STRING_COMMA_LEN ("crt0.o") },
{ STRING_COMMA_LEN ("crt1.o") },
{ STRING_COMMA_LEN ("crt2.o") },
{ STRING_COMMA_LEN ("dllcrt1.o") },
{ STRING_COMMA_LEN ("dllcrt2.o") },
{ STRING_COMMA_LEN ("gcrt0.o") },
{ STRING_COMMA_LEN ("gcrt1.o") },
{ STRING_COMMA_LEN ("gcrt2.o") },
{ STRING_COMMA_LEN ("crtbegin.o") },
{ STRING_COMMA_LEN ("crtend.o") },
{ NULL, 0 }
};
 
static const autofilter_entry_type autofilter_symbolprefixlist[] =
{
/* _imp_ is treated specially, as it is always underscored. */
/* { STRING_COMMA_LEN ("_imp_") }, */
/* Don't export some c++ symbols. */
{ STRING_COMMA_LEN ("__rtti_") },
{ STRING_COMMA_LEN ("__builtin_") },
/* Don't re-export auto-imported symbols. */
{ STRING_COMMA_LEN ("__nm_") },
/* Don't export symbols specifying internal DLL layout. */
{ STRING_COMMA_LEN ("_head_") },
{ STRING_COMMA_LEN ("_IMPORT_DESCRIPTOR_") },
/* Don't export section labels or artificial symbols
(eg ".weak.foo". */
{ STRING_COMMA_LEN (".") },
{ NULL, 0 }
};
 
static const autofilter_entry_type autofilter_symbolsuffixlist[] =
{
{ STRING_COMMA_LEN ("_iname") },
{ STRING_COMMA_LEN ("_NULL_THUNK_DATA") },
{ NULL, 0 }
};
 
#define U(str) (pe_details->underscored ? "_" str : str)
 
void
pe_dll_id_target (const char *target)
{
int i;
 
for (i = 0; pe_detail_list[i].target_name; i++)
if (strcmp (pe_detail_list[i].target_name, target) == 0
|| strcmp (pe_detail_list[i].object_target, target) == 0)
{
int u = pe_leading_underscore; /* Underscoring mode. -1 for use default. */
if (u == -1)
bfd_get_target_info (target, NULL, NULL, &u, NULL);
if (u == -1)
abort ();
pe_detail_list[i].underscored = (u != 0 ? TRUE : FALSE);
pe_details = pe_detail_list + i;
pe_leading_underscore = (u != 0 ? 1 : 0);
return;
}
einfo (_("%XUnsupported PEI architecture: %s\n"), target);
exit (1);
}
 
/* Helper functions for qsort. Relocs must be sorted so that we can write
them out by pages. */
 
typedef struct
{
bfd_vma vma;
char type;
short extra;
}
reloc_data_type;
 
static int
reloc_sort (const void *va, const void *vb)
{
bfd_vma a = ((const reloc_data_type *) va)->vma;
bfd_vma b = ((const reloc_data_type *) vb)->vma;
 
return (a > b) ? 1 : ((a < b) ? -1 : 0);
}
 
static int
pe_export_sort (const void *va, const void *vb)
{
const def_file_export *a = va;
const def_file_export *b = vb;
char *an = a->name;
char *bn = b->name;
if (a->its_name)
an = a->its_name;
if (b->its_name)
bn = b->its_name;
 
return strcmp (an, bn);
}
 
/* Read and process the .DEF file. */
 
/* These correspond to the entries in pe_def_file->exports[]. I use
exported_symbol_sections[i] to tag whether or not the symbol was
defined, since we can't export symbols we don't have. */
 
static bfd_vma *exported_symbol_offsets;
static struct bfd_section **exported_symbol_sections;
static int export_table_size;
static int count_exported;
static int count_exported_byname;
static int count_with_ordinals;
static const char *dll_name;
static int min_ordinal, max_ordinal;
static int *exported_symbols;
 
typedef struct exclude_list_struct
{
char *string;
struct exclude_list_struct *next;
exclude_type type;
}
exclude_list_struct;
 
static struct exclude_list_struct *excludes = 0;
 
void
pe_dll_add_excludes (const char *new_excludes, const exclude_type type)
{
char *local_copy;
char *exclude_string;
 
local_copy = xstrdup (new_excludes);
 
exclude_string = strtok (local_copy, ",:");
for (; exclude_string; exclude_string = strtok (NULL, ",:"))
{
struct exclude_list_struct *new_exclude;
 
new_exclude = xmalloc (sizeof (struct exclude_list_struct));
new_exclude->string = xmalloc (strlen (exclude_string) + 1);
strcpy (new_exclude->string, exclude_string);
new_exclude->type = type;
new_exclude->next = excludes;
excludes = new_exclude;
}
 
free (local_copy);
}
 
static bfd_boolean
is_import (const char* n)
{
return (CONST_STRNEQ (n, "__imp_"));
}
 
/* abfd is a bfd containing n (or NULL)
It can be used for contextual checks. */
 
static int
auto_export (bfd *abfd, def_file *d, const char *n)
{
def_file_export key;
struct exclude_list_struct *ex;
const autofilter_entry_type *afptr;
const char * libname = NULL;
 
if (abfd && abfd->my_archive)
libname = lbasename (abfd->my_archive->filename);
 
key.name = key.its_name = (char *) n;
 
/* Return false if n is in the d->exports table. */
if (bsearch (&key, d->exports, d->num_exports,
sizeof (pe_def_file->exports[0]), pe_export_sort))
return 0;
 
if (pe_dll_do_default_excludes)
{
const char * p;
int len;
 
if (pe_dll_extra_pe_debug)
printf ("considering exporting: %s, abfd=%p, abfd->my_arc=%p\n",
n, abfd, abfd->my_archive);
 
/* First of all, make context checks:
Don't export anything from standard libs. */
if (libname)
{
afptr = autofilter_liblist;
 
while (afptr->name)
{
if (libnamencmp (libname, afptr) == 0 )
return 0;
afptr++;
}
}
 
/* Next, exclude symbols from certain startup objects. */
 
if (abfd && (p = lbasename (abfd->filename)))
{
afptr = autofilter_objlist;
while (afptr->name)
{
if (strcmp (p, afptr->name) == 0)
return 0;
afptr++;
}
}
 
/* Don't try to blindly exclude all symbols
that begin with '__'; this was tried and
it is too restrictive. Instead we have
a target specific list to use: */
afptr = pe_details->autofilter_symbollist;
 
while (afptr->name)
{
if (strcmp (n, afptr->name) == 0)
return 0;
 
afptr++;
}
 
/* Next, exclude symbols starting with ... */
afptr = autofilter_symbolprefixlist;
while (afptr->name)
{
if (strncmp (n, afptr->name, afptr->len) == 0)
return 0;
 
afptr++;
}
 
/* Finally, exclude symbols ending with ... */
len = strlen (n);
afptr = autofilter_symbolsuffixlist;
while (afptr->name)
{
if ((len >= afptr->len)
/* Add 1 to insure match with trailing '\0'. */
&& strncmp (n + len - afptr->len, afptr->name,
afptr->len + 1) == 0)
return 0;
 
afptr++;
}
}
 
for (ex = excludes; ex; ex = ex->next)
{
if (ex->type == EXCLUDELIBS)
{
if (libname
&& ((filename_cmp (libname, ex->string) == 0)
|| (strcasecmp ("ALL", ex->string) == 0)))
return 0;
}
else if (ex->type == EXCLUDEFORIMPLIB)
{
if (filename_cmp (abfd->filename, ex->string) == 0)
return 0;
}
else if (strcmp (n, ex->string) == 0)
return 0;
}
 
return 1;
}
 
static void
process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
int i, j;
struct bfd_link_hash_entry *blhe;
bfd *b;
struct bfd_section *s;
def_file_export *e = 0;
bfd_boolean resort_needed;
 
if (!pe_def_file)
pe_def_file = def_file_empty ();
 
/* First, run around to all the objects looking for the .drectve
sections, and push those into the def file too. */
for (b = info->input_bfds; b; b = b->link_next)
{
s = bfd_get_section_by_name (b, ".drectve");
if (s)
{
long size = s->size;
char *buf = xmalloc (size);
 
bfd_get_section_contents (b, s, buf, 0, size);
def_file_add_directive (pe_def_file, buf, size);
free (buf);
}
}
 
/* Process aligned common symbol information from the
.drectve sections now; common symbol allocation is
done before final link, so it will be too late to
process them in process_embedded_commands() called
from _bfd_coff_link_input_bfd(). */
if (pe_def_file->aligncomms)
{
def_file_aligncomm *ac = pe_def_file->aligncomms;
while (ac)
{
struct coff_link_hash_entry *sym_hash;
sym_hash = coff_link_hash_lookup (coff_hash_table (info),
ac->symbol_name, FALSE, FALSE, FALSE);
if (sym_hash && sym_hash->root.type == bfd_link_hash_common
&& sym_hash->root.u.c.p->alignment_power < (unsigned) ac->alignment)
{
sym_hash->root.u.c.p->alignment_power = (unsigned) ac->alignment;
}
ac = ac->next;
}
}
 
/* If we are building an executable and there is nothing
to export, we do not build an export table at all. */
if (info->executable && pe_def_file->num_exports == 0
&& (!pe_dll_export_everything || pe_dll_exclude_all_symbols))
return;
 
/* Now, maybe export everything else the default way. */
if ((pe_dll_export_everything || pe_def_file->num_exports == 0)
&& !pe_dll_exclude_all_symbols)
{
for (b = info->input_bfds; b; b = b->link_next)
{
asymbol **symbols;
int nsyms;
 
if (!bfd_generic_link_read_symbols (b))
{
einfo (_("%B%F: could not read symbols: %E\n"), b);
return;
}
 
symbols = bfd_get_outsymbols (b);
nsyms = bfd_get_symcount (b);
 
for (j = 0; j < nsyms; j++)
{
/* We should export symbols which are either global or not
anything at all. (.bss data is the latter)
We should not export undefined symbols. */
bfd_boolean would_export
= (symbols[j]->section != bfd_und_section_ptr
&& ((symbols[j]->flags & BSF_GLOBAL)
|| (symbols[j]->flags == 0)));
if (link_info.version_info && would_export)
would_export
= !bfd_hide_sym_by_version (link_info.version_info,
symbols[j]->name);
if (would_export)
{
const char *sn = symbols[j]->name;
 
/* We should not re-export imported stuff. */
{
char *name;
if (is_import (sn))
continue;
 
name = xmalloc (strlen ("__imp_") + strlen (sn) + 1);
sprintf (name, "%s%s", "__imp_", sn);
 
blhe = bfd_link_hash_lookup (info->hash, name,
FALSE, FALSE, FALSE);
free (name);
 
if (blhe && blhe->type == bfd_link_hash_defined)
continue;
}
 
if (pe_details->underscored && *sn == '_')
sn++;
 
if (auto_export (b, pe_def_file, sn))
{
int is_dup = 0;
def_file_export *p;
 
p = def_file_add_export (pe_def_file, sn, 0, -1,
NULL, &is_dup);
/* Fill data flag properly, from dlltool.c. */
if (!is_dup)
p->flag_data = !(symbols[j]->flags & BSF_FUNCTION);
}
}
}
}
}
 
#undef NE
#define NE pe_def_file->num_exports
 
/* Don't create an empty export table. */
if (NE == 0)
return;
 
resort_needed = FALSE;
 
/* Canonicalize the export list. */
if (pe_dll_kill_ats)
{
for (i = 0; i < NE; i++)
{
/* Check for fastcall/stdcall-decoration, but ignore
C++ mangled names. */
if (pe_def_file->exports[i].name[0] != '?'
&& strchr (pe_def_file->exports[i].name, '@'))
{
/* This will preserve internal_name, which may have been
pointing to the same memory as name, or might not
have. */
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
char *tmp_at = strrchr (tmp, '@');
 
if (tmp_at)
*tmp_at = 0;
else
einfo (_("%XCannot export %s: invalid export name\n"),
pe_def_file->exports[i].name);
pe_def_file->exports[i].name = tmp;
resort_needed = TRUE;
}
}
}
 
/* Re-sort the exports table as we have possibly changed the order
by removing leading @. */
if (resort_needed)
qsort (pe_def_file->exports, NE, sizeof (pe_def_file->exports[0]),
pe_export_sort);
 
if (pe_dll_stdcall_aliases)
{
for (i = 0; i < NE; i++)
{
if (is_import (pe_def_file->exports[i].name))
continue;
 
if (strchr (pe_def_file->exports[i].name, '@'))
{
int is_dup = 1;
int lead_at = (*pe_def_file->exports[i].name == '@');
char *tmp = xstrdup (pe_def_file->exports[i].name + lead_at);
 
*(strchr (tmp, '@')) = 0;
if (auto_export (NULL, pe_def_file, tmp))
def_file_add_export (pe_def_file, tmp,
pe_def_file->exports[i].internal_name,
-1, NULL, &is_dup);
if (is_dup)
free (tmp);
}
}
}
 
/* Convenience, but watch out for it changing. */
e = pe_def_file->exports;
 
for (i = 0, j = 0; i < NE; i++)
{
if (i > 0 && strcmp (e[i].name, e[i - 1].name) == 0)
{
/* This is a duplicate. */
if (e[j - 1].ordinal != -1
&& e[i].ordinal != -1
&& e[j - 1].ordinal != e[i].ordinal)
{
if (pe_dll_warn_dup_exports)
/* xgettext:c-format */
einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
}
else
{
if (pe_dll_warn_dup_exports)
/* xgettext:c-format */
einfo (_("Warning, duplicate EXPORT: %s\n"),
e[j - 1].name);
}
 
if (e[i].ordinal != -1)
e[j - 1].ordinal = e[i].ordinal;
e[j - 1].flag_private |= e[i].flag_private;
e[j - 1].flag_constant |= e[i].flag_constant;
e[j - 1].flag_noname |= e[i].flag_noname;
e[j - 1].flag_data |= e[i].flag_data;
if (e[i].name)
free (e[i].name);
if (e[i].internal_name)
free (e[i].internal_name);
if (e[i].its_name)
free (e[i].its_name);
}
else
{
if (i != j)
e[j] = e[i];
j++;
}
}
pe_def_file->num_exports = j; /* == NE */
 
exported_symbol_offsets = xmalloc (NE * sizeof (bfd_vma));
exported_symbol_sections = xmalloc (NE * sizeof (struct bfd_section *));
 
memset (exported_symbol_sections, 0, NE * sizeof (struct bfd_section *));
max_ordinal = 0;
min_ordinal = 65536;
count_exported = 0;
count_exported_byname = 0;
count_with_ordinals = 0;
 
for (i = 0; i < NE; i++)
{
char *name;
name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
if (pe_details->underscored
&& (*pe_def_file->exports[i].internal_name != '@'))
{
*name = '_';
strcpy (name + 1, pe_def_file->exports[i].internal_name);
}
else
strcpy (name, pe_def_file->exports[i].internal_name);
 
blhe = bfd_link_hash_lookup (info->hash,
name,
FALSE, FALSE, TRUE);
 
if (blhe
&& (blhe->type == bfd_link_hash_defined
|| (blhe->type == bfd_link_hash_common)))
{
count_exported++;
if (!pe_def_file->exports[i].flag_noname)
count_exported_byname++;
 
/* Only fill in the sections. The actual offsets are computed
in fill_exported_offsets() after common symbols are laid
out. */
if (blhe->type == bfd_link_hash_defined)
exported_symbol_sections[i] = blhe->u.def.section;
else
exported_symbol_sections[i] = blhe->u.c.p->section;
 
if (pe_def_file->exports[i].ordinal != -1)
{
if (max_ordinal < pe_def_file->exports[i].ordinal)
max_ordinal = pe_def_file->exports[i].ordinal;
if (min_ordinal > pe_def_file->exports[i].ordinal)
min_ordinal = pe_def_file->exports[i].ordinal;
count_with_ordinals++;
}
}
/* Check for forward exports. These are indicated in DEF files by an
export directive of the form NAME1 = MODULE-NAME.EXTERNAL-NAME
but we must take care not to be fooled when the user wants to export
a symbol that actually really has a dot in it, so we only check
for them here, after real defined symbols have already been matched. */
else if (strchr (pe_def_file->exports[i].internal_name, '.'))
{
count_exported++;
if (!pe_def_file->exports[i].flag_noname)
count_exported_byname++;
 
pe_def_file->exports[i].flag_forward = 1;
 
if (pe_def_file->exports[i].ordinal != -1)
{
if (max_ordinal < pe_def_file->exports[i].ordinal)
max_ordinal = pe_def_file->exports[i].ordinal;
if (min_ordinal > pe_def_file->exports[i].ordinal)
min_ordinal = pe_def_file->exports[i].ordinal;
count_with_ordinals++;
}
}
else if (blhe && blhe->type == bfd_link_hash_undefined)
{
/* xgettext:c-format */
einfo (_("%XCannot export %s: symbol not defined\n"),
pe_def_file->exports[i].internal_name);
}
else if (blhe)
{
/* xgettext:c-format */
einfo (_("%XCannot export %s: symbol wrong type (%d vs %d)\n"),
pe_def_file->exports[i].internal_name,
blhe->type, bfd_link_hash_defined);
}
else
{
/* xgettext:c-format */
einfo (_("%XCannot export %s: symbol not found\n"),
pe_def_file->exports[i].internal_name);
}
free (name);
}
}
 
/* Build the bfd that will contain .edata and .reloc sections. */
 
static void
build_filler_bfd (int include_edata)
{
lang_input_statement_type *filler_file;
filler_file = lang_add_input_file ("dll stuff",
lang_input_file_is_fake_enum,
NULL);
filler_file->the_bfd = filler_bfd = bfd_create ("dll stuff",
link_info.output_bfd);
if (filler_bfd == NULL
|| !bfd_set_arch_mach (filler_bfd,
bfd_get_arch (link_info.output_bfd),
bfd_get_mach (link_info.output_bfd)))
{
einfo ("%X%P: can not create BFD: %E\n");
return;
}
 
if (include_edata)
{
edata_s = bfd_make_section_old_way (filler_bfd, ".edata");
if (edata_s == NULL
|| !bfd_set_section_flags (filler_bfd, edata_s,
(SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_KEEP
| SEC_IN_MEMORY)))
{
einfo ("%X%P: can not create .edata section: %E\n");
return;
}
bfd_set_section_size (filler_bfd, edata_s, edata_sz);
}
 
reloc_s = bfd_make_section_old_way (filler_bfd, ".reloc");
if (reloc_s == NULL
|| !bfd_set_section_flags (filler_bfd, reloc_s,
(SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_KEEP
| SEC_IN_MEMORY)))
{
einfo ("%X%P: can not create .reloc section: %E\n");
return;
}
 
bfd_set_section_size (filler_bfd, reloc_s, 0);
 
ldlang_add_file (filler_file);
}
 
/* Gather all the exported symbols and build the .edata section. */
 
static void
generate_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
int i, next_ordinal;
int name_table_size = 0;
const char *dlnp;
 
/* First, we need to know how many exported symbols there are,
and what the range of ordinals is. */
if (pe_def_file->name)
dll_name = pe_def_file->name;
else
{
dll_name = abfd->filename;
 
for (dlnp = dll_name; *dlnp; dlnp++)
if (*dlnp == '\\' || *dlnp == '/' || *dlnp == ':')
dll_name = dlnp + 1;
}
 
if (count_with_ordinals && max_ordinal > count_exported)
{
if (min_ordinal > max_ordinal - count_exported + 1)
min_ordinal = max_ordinal - count_exported + 1;
}
else
{
min_ordinal = 1;
max_ordinal = count_exported;
}
 
export_table_size = max_ordinal - min_ordinal + 1;
exported_symbols = xmalloc (export_table_size * sizeof (int));
for (i = 0; i < export_table_size; i++)
exported_symbols[i] = -1;
 
/* Now we need to assign ordinals to those that don't have them. */
for (i = 0; i < NE; i++)
{
if (exported_symbol_sections[i] ||
pe_def_file->exports[i].flag_forward)
{
if (pe_def_file->exports[i].ordinal != -1)
{
int ei = pe_def_file->exports[i].ordinal - min_ordinal;
int pi = exported_symbols[ei];
 
if (pi != -1)
{
/* xgettext:c-format */
einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
pe_def_file->exports[i].ordinal,
pe_def_file->exports[i].name,
pe_def_file->exports[pi].name);
}
exported_symbols[ei] = i;
}
if (pe_def_file->exports[i].its_name)
name_table_size += strlen (pe_def_file->exports[i].its_name) + 1;
else
name_table_size += strlen (pe_def_file->exports[i].name) + 1;
}
 
/* Reserve space for the forward name. */
if (pe_def_file->exports[i].flag_forward)
{
name_table_size += strlen (pe_def_file->exports[i].internal_name) + 1;
}
}
 
next_ordinal = min_ordinal;
for (i = 0; i < NE; i++)
if ((exported_symbol_sections[i] ||
pe_def_file->exports[i].flag_forward) &&
pe_def_file->exports[i].ordinal == -1)
{
while (exported_symbols[next_ordinal - min_ordinal] != -1)
next_ordinal++;
 
exported_symbols[next_ordinal - min_ordinal] = i;
pe_def_file->exports[i].ordinal = next_ordinal;
}
 
/* OK, now we can allocate some memory. */
edata_sz = (40 /* directory */
+ 4 * export_table_size /* addresses */
+ 4 * count_exported_byname /* name ptrs */
+ 2 * count_exported_byname /* ordinals */
+ name_table_size + strlen (dll_name) + 1);
}
 
/* Fill the exported symbol offsets. The preliminary work has already
been done in process_def_file_and_drectve(). */
 
static void
fill_exported_offsets (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
{
int i;
struct bfd_link_hash_entry *blhe;
 
for (i = 0; i < pe_def_file->num_exports; i++)
{
char *name;
 
name = xmalloc (strlen (pe_def_file->exports[i].internal_name) + 2);
if (pe_details->underscored
&& *pe_def_file->exports[i].internal_name != '@')
{
*name = '_';
strcpy (name + 1, pe_def_file->exports[i].internal_name);
}
else
strcpy (name, pe_def_file->exports[i].internal_name);
 
blhe = bfd_link_hash_lookup (info->hash,
name,
FALSE, FALSE, TRUE);
 
if (blhe && blhe->type == bfd_link_hash_defined)
exported_symbol_offsets[i] = blhe->u.def.value;
 
free (name);
}
}
 
static void
fill_edata (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
int s, hint;
unsigned char *edirectory;
unsigned char *eaddresses;
unsigned char *enameptrs;
unsigned char *eordinals;
char *enamestr;
 
edata_d = xmalloc (edata_sz);
 
/* Note use of array pointer math here. */
edirectory = edata_d;
eaddresses = edirectory + 40;
enameptrs = eaddresses + 4 * export_table_size;
eordinals = enameptrs + 4 * count_exported_byname;
enamestr = (char *) eordinals + 2 * count_exported_byname;
 
#define ERVA(ptr) (((unsigned char *)(ptr) - edata_d) \
+ edata_s->output_section->vma - image_base)
 
memset (edata_d, 0, edata_sz);
 
if (pe_data (abfd)->insert_timestamp)
H_PUT_32 (abfd, time (0), edata_d + 4);
 
if (pe_def_file->version_major != -1)
{
bfd_put_16 (abfd, pe_def_file->version_major, edata_d + 8);
bfd_put_16 (abfd, pe_def_file->version_minor, edata_d + 10);
}
 
bfd_put_32 (abfd, ERVA (enamestr), edata_d + 12);
strcpy (enamestr, dll_name);
enamestr += strlen (enamestr) + 1;
bfd_put_32 (abfd, min_ordinal, edata_d + 16);
bfd_put_32 (abfd, export_table_size, edata_d + 20);
bfd_put_32 (abfd, count_exported_byname, edata_d + 24);
bfd_put_32 (abfd, ERVA (eaddresses), edata_d + 28);
bfd_put_32 (abfd, ERVA (enameptrs), edata_d + 32);
bfd_put_32 (abfd, ERVA (eordinals), edata_d + 36);
 
fill_exported_offsets (abfd, info);
 
/* Ok, now for the filling in part.
Scan alphabetically - ie the ordering in the exports[] table,
rather than by ordinal - the ordering in the exported_symbol[]
table. See dlltool.c and:
http://sources.redhat.com/ml/binutils/2003-04/msg00379.html
for more information. */
hint = 0;
for (s = 0; s < NE; s++)
{
struct bfd_section *ssec = exported_symbol_sections[s];
if (pe_def_file->exports[s].ordinal != -1 &&
(pe_def_file->exports[s].flag_forward || ssec != NULL))
{
int ord = pe_def_file->exports[s].ordinal;
 
if (pe_def_file->exports[s].flag_forward)
{
bfd_put_32 (abfd, ERVA (enamestr),
eaddresses + 4 * (ord - min_ordinal));
 
strcpy (enamestr, pe_def_file->exports[s].internal_name);
enamestr += strlen (pe_def_file->exports[s].internal_name) + 1;
}
else
{
bfd_vma srva = (exported_symbol_offsets[s]
+ ssec->output_section->vma
+ ssec->output_offset);
 
bfd_put_32 (abfd, srva - image_base,
eaddresses + 4 * (ord - min_ordinal));
}
 
if (!pe_def_file->exports[s].flag_noname)
{
char *ename = pe_def_file->exports[s].name;
if (pe_def_file->exports[s].its_name)
ename = pe_def_file->exports[s].its_name;
 
bfd_put_32 (abfd, ERVA (enamestr), enameptrs);
enameptrs += 4;
strcpy (enamestr, ename);
enamestr += strlen (enamestr) + 1;
bfd_put_16 (abfd, ord - min_ordinal, eordinals);
eordinals += 2;
pe_def_file->exports[s].hint = hint++;
}
}
}
}
 
 
static struct bfd_section *current_sec;
 
void
pe_walk_relocs_of_symbol (struct bfd_link_info *info,
const char *name,
int (*cb) (arelent *, asection *))
{
bfd *b;
asection *s;
 
for (b = info->input_bfds; b; b = b->link_next)
{
asymbol **symbols;
 
if (!bfd_generic_link_read_symbols (b))
{
einfo (_("%B%F: could not read symbols: %E\n"), b);
return;
}
 
symbols = bfd_get_outsymbols (b);
 
for (s = b->sections; s; s = s->next)
{
arelent **relocs;
int relsize, nrelocs, i;
int flags = bfd_get_section_flags (b, s);
 
/* Skip discarded linkonce sections. */
if (flags & SEC_LINK_ONCE
&& s->output_section == bfd_abs_section_ptr)
continue;
 
current_sec = s;
 
relsize = bfd_get_reloc_upper_bound (b, s);
relocs = xmalloc (relsize);
nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
 
for (i = 0; i < nrelocs; i++)
{
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
 
if (!strcmp (name, sym->name))
cb (relocs[i], s);
}
 
free (relocs);
 
/* Warning: the allocated symbols are remembered in BFD and reused
later, so don't free them! */
/* free (symbols); */
}
}
}
 
/* Gather all the relocations and build the .reloc section. */
 
static void
generate_reloc (bfd *abfd, struct bfd_link_info *info)
{
 
/* For .reloc stuff. */
reloc_data_type *reloc_data;
int total_relocs = 0;
int i;
bfd_vma sec_page = (bfd_vma) -1;
bfd_vma page_ptr, page_count;
int bi;
bfd *b;
struct bfd_section *s;
 
total_relocs = 0;
for (b = info->input_bfds; b; b = b->link_next)
for (s = b->sections; s; s = s->next)
total_relocs += s->reloc_count;
 
reloc_data = xmalloc (total_relocs * sizeof (reloc_data_type));
 
total_relocs = 0;
bi = 0;
for (bi = 0, b = info->input_bfds; b; bi++, b = b->link_next)
{
arelent **relocs;
int relsize, nrelocs;
 
for (s = b->sections; s; s = s->next)
{
bfd_vma sec_vma = s->output_section->vma + s->output_offset;
asymbol **symbols;
 
/* If it's not loaded, we don't need to relocate it this way. */
if (!(s->output_section->flags & SEC_LOAD))
continue;
 
/* I don't know why there would be a reloc for these, but I've
seen it happen - DJ */
if (s->output_section == bfd_abs_section_ptr)
continue;
 
if (s->output_section->vma == 0)
{
/* Huh? Shouldn't happen, but punt if it does. */
einfo ("DJ: zero vma section reloc detected: `%s' #%d f=%d\n",
s->output_section->name, s->output_section->index,
s->output_section->flags);
continue;
}
 
if (!bfd_generic_link_read_symbols (b))
{
einfo (_("%B%F: could not read symbols: %E\n"), b);
return;
}
 
symbols = bfd_get_outsymbols (b);
relsize = bfd_get_reloc_upper_bound (b, s);
relocs = xmalloc (relsize);
nrelocs = bfd_canonicalize_reloc (b, s, relocs, symbols);
 
for (i = 0; i < nrelocs; i++)
{
if (pe_dll_extra_pe_debug)
{
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
printf ("rel: %s\n", sym->name);
}
if (!relocs[i]->howto->pc_relative
&& relocs[i]->howto->type != pe_details->imagebase_reloc)
{
struct bfd_symbol *sym = *relocs[i]->sym_ptr_ptr;
 
/* Don't create relocs for undefined weak symbols. */
if (sym->flags == BSF_WEAK)
{
struct bfd_link_hash_entry *blhe
= bfd_wrapped_link_hash_lookup (abfd, info, sym->name,
FALSE, FALSE, FALSE);
if (blhe && blhe->type == bfd_link_hash_undefweak)
{
/* Check aux sym and see if it is defined or not. */
struct coff_link_hash_entry *h, *h2;
h = (struct coff_link_hash_entry *)blhe;
if (h->symbol_class != C_NT_WEAK || h->numaux != 1)
continue;
h2 = h->auxbfd->tdata.coff_obj_data->sym_hashes
[h->aux->x_sym.x_tagndx.l];
/* We don't want a base reloc if the aux sym is not
found, undefined, or if it is the constant ABS
zero default value. (We broaden that slightly by
not testing the value, just the section; there's
no reason we'd want a reference to any absolute
address to get relocated during rebasing). */
if (!h2 || h2->root.type == bfd_link_hash_undefined
|| h2->root.u.def.section == bfd_abs_section_ptr)
continue;
}
else if (!blhe || blhe->type != bfd_link_hash_defined)
continue;
}
/* Nor for Dwarf FDE references to discarded sections. */
else if (bfd_is_abs_section (sym->section->output_section))
{
/* We only ignore relocs from .eh_frame sections, as
they are discarded by the final link rather than
resolved against the kept section. */
if (!strcmp (s->name, ".eh_frame"))
continue;
}
 
reloc_data[total_relocs].vma = sec_vma + relocs[i]->address;
 
#define BITS_AND_SHIFT(bits, shift) (bits * 1000 | shift)
 
switch BITS_AND_SHIFT (relocs[i]->howto->bitsize,
relocs[i]->howto->rightshift)
{
#ifdef pe_use_x86_64
case BITS_AND_SHIFT (64, 0):
reloc_data[total_relocs].type = 10;
total_relocs++;
break;
#endif
case BITS_AND_SHIFT (32, 0):
reloc_data[total_relocs].type = 3;
total_relocs++;
break;
case BITS_AND_SHIFT (16, 0):
reloc_data[total_relocs].type = 2;
total_relocs++;
break;
case BITS_AND_SHIFT (16, 16):
reloc_data[total_relocs].type = 4;
/* FIXME: we can't know the symbol's right value
yet, but we probably can safely assume that
CE will relocate us in 64k blocks, so leaving
it zero is safe. */
reloc_data[total_relocs].extra = 0;
total_relocs++;
break;
case BITS_AND_SHIFT (26, 2):
reloc_data[total_relocs].type = 5;
total_relocs++;
break;
case BITS_AND_SHIFT (24, 2):
/* FIXME: 0 is ARM_26D, it is defined in bfd/coff-arm.c
Those ARM_xxx definitions should go in proper
header someday. */
if (relocs[i]->howto->type == 0
/* Older GNU linkers used 5 instead of 0 for this reloc. */
|| relocs[i]->howto->type == 5)
/* This is an ARM_26D reloc, which is an ARM_26 reloc
that has already been fully processed during a
previous link stage, so ignore it here. */
break;
/* Fall through. */
default:
/* xgettext:c-format */
einfo (_("%XError: %d-bit reloc in dll\n"),
relocs[i]->howto->bitsize);
break;
}
}
}
free (relocs);
/* Warning: the allocated symbols are remembered in BFD and
reused later, so don't free them! */
}
}
 
/* At this point, we have total_relocs relocation addresses in
reloc_addresses, which are all suitable for the .reloc section.
We must now create the new sections. */
qsort (reloc_data, total_relocs, sizeof (*reloc_data), reloc_sort);
 
for (i = 0; i < total_relocs; i++)
{
bfd_vma this_page = (reloc_data[i].vma >> 12);
 
if (this_page != sec_page)
{
reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */
reloc_sz += 8;
sec_page = this_page;
}
 
reloc_sz += 2;
 
if (reloc_data[i].type == 4)
reloc_sz += 2;
}
 
reloc_sz = (reloc_sz + 3) & ~3; /* 4-byte align. */
reloc_d = xmalloc (reloc_sz);
sec_page = (bfd_vma) -1;
reloc_sz = 0;
page_ptr = (bfd_vma) -1;
page_count = 0;
 
for (i = 0; i < total_relocs; i++)
{
bfd_vma rva = reloc_data[i].vma - image_base;
bfd_vma this_page = (rva & ~0xfff);
 
if (this_page != sec_page)
{
while (reloc_sz & 3)
reloc_d[reloc_sz++] = 0;
 
if (page_ptr != (bfd_vma) -1)
bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
 
bfd_put_32 (abfd, this_page, reloc_d + reloc_sz);
page_ptr = reloc_sz;
reloc_sz += 8;
sec_page = this_page;
page_count = 0;
}
 
bfd_put_16 (abfd, (rva & 0xfff) + (reloc_data[i].type << 12),
reloc_d + reloc_sz);
reloc_sz += 2;
 
if (reloc_data[i].type == 4)
{
bfd_put_16 (abfd, reloc_data[i].extra, reloc_d + reloc_sz);
reloc_sz += 2;
}
 
page_count++;
}
 
while (reloc_sz & 3)
reloc_d[reloc_sz++] = 0;
 
if (page_ptr != (bfd_vma) -1)
bfd_put_32 (abfd, reloc_sz - page_ptr, reloc_d + page_ptr + 4);
 
while (reloc_sz < reloc_s->size)
reloc_d[reloc_sz++] = 0;
}
 
/* Given the exiting def_file structure, print out a .DEF file that
corresponds to it. */
 
static void
quoteput (char *s, FILE *f, int needs_quotes)
{
char *cp;
 
for (cp = s; *cp; cp++)
if (*cp == '\''
|| *cp == '"'
|| *cp == '\\'
|| ISSPACE (*cp)
|| *cp == ','
|| *cp == ';')
needs_quotes = 1;
 
if (needs_quotes)
{
putc ('"', f);
 
while (*s)
{
if (*s == '"' || *s == '\\')
putc ('\\', f);
 
putc (*s, f);
s++;
}
 
putc ('"', f);
}
else
fputs (s, f);
}
 
void
pe_dll_generate_def_file (const char *pe_out_def_filename)
{
int i;
FILE *out = fopen (pe_out_def_filename, "w");
 
if (out == NULL)
/* xgettext:c-format */
einfo (_("%s: Can't open output def file %s\n"),
program_name, pe_out_def_filename);
 
if (pe_def_file)
{
if (pe_def_file->name)
{
if (pe_def_file->is_dll)
fprintf (out, "LIBRARY ");
else
fprintf (out, "NAME ");
 
quoteput (pe_def_file->name, out, 1);
 
if (pe_data (link_info.output_bfd)->pe_opthdr.ImageBase)
{
fprintf (out, " BASE=0x");
fprintf_vma (out, ((bfd_vma) pe_data (link_info.output_bfd)->pe_opthdr.ImageBase));
}
fprintf (out, "\n");
}
 
if (pe_def_file->description)
{
fprintf (out, "DESCRIPTION ");
quoteput (pe_def_file->description, out, 1);
fprintf (out, "\n");
}
 
if (pe_def_file->version_minor != -1)
fprintf (out, "VERSION %d.%d\n", pe_def_file->version_major,
pe_def_file->version_minor);
else if (pe_def_file->version_major != -1)
fprintf (out, "VERSION %d\n", pe_def_file->version_major);
 
if (pe_def_file->stack_reserve != -1 || pe_def_file->heap_reserve != -1)
fprintf (out, "\n");
 
if (pe_def_file->stack_commit != -1)
fprintf (out, "STACKSIZE 0x%x,0x%x\n",
pe_def_file->stack_reserve, pe_def_file->stack_commit);
else if (pe_def_file->stack_reserve != -1)
fprintf (out, "STACKSIZE 0x%x\n", pe_def_file->stack_reserve);
 
if (pe_def_file->heap_commit != -1)
fprintf (out, "HEAPSIZE 0x%x,0x%x\n",
pe_def_file->heap_reserve, pe_def_file->heap_commit);
else if (pe_def_file->heap_reserve != -1)
fprintf (out, "HEAPSIZE 0x%x\n", pe_def_file->heap_reserve);
 
if (pe_def_file->num_section_defs > 0)
{
fprintf (out, "\nSECTIONS\n\n");
 
for (i = 0; i < pe_def_file->num_section_defs; i++)
{
fprintf (out, " ");
quoteput (pe_def_file->section_defs[i].name, out, 0);
 
if (pe_def_file->section_defs[i].class)
{
fprintf (out, " CLASS ");
quoteput (pe_def_file->section_defs[i].class, out, 0);
}
 
if (pe_def_file->section_defs[i].flag_read)
fprintf (out, " READ");
 
if (pe_def_file->section_defs[i].flag_write)
fprintf (out, " WRITE");
 
if (pe_def_file->section_defs[i].flag_execute)
fprintf (out, " EXECUTE");
 
if (pe_def_file->section_defs[i].flag_shared)
fprintf (out, " SHARED");
 
fprintf (out, "\n");
}
}
 
if (pe_def_file->num_exports > 0)
{
fprintf (out, "EXPORTS\n");
 
for (i = 0; i < pe_def_file->num_exports; i++)
{
def_file_export *e = pe_def_file->exports + i;
fprintf (out, " ");
quoteput (e->name, out, 0);
 
if (e->internal_name && strcmp (e->internal_name, e->name))
{
fprintf (out, " = ");
quoteput (e->internal_name, out, 0);
}
 
if (e->ordinal != -1)
fprintf (out, " @%d", e->ordinal);
 
if (e->flag_private)
fprintf (out, " PRIVATE");
 
if (e->flag_constant)
fprintf (out, " CONSTANT");
 
if (e->flag_noname)
fprintf (out, " NONAME");
 
if (e->flag_data)
fprintf (out, " DATA");
 
fprintf (out, "\n");
}
}
 
if (pe_def_file->num_imports > 0)
{
fprintf (out, "\nIMPORTS\n\n");
 
for (i = 0; i < pe_def_file->num_imports; i++)
{
def_file_import *im = pe_def_file->imports + i;
fprintf (out, " ");
 
if (im->internal_name
&& (!im->name || strcmp (im->internal_name, im->name)))
{
quoteput (im->internal_name, out, 0);
fprintf (out, " = ");
}
 
quoteput (im->module->name, out, 0);
fprintf (out, ".");
 
if (im->name)
quoteput (im->name, out, 0);
else
fprintf (out, "%d", im->ordinal);
 
if (im->its_name)
{
fprintf (out, " == ");
quoteput (im->its_name, out, 0);
}
 
fprintf (out, "\n");
}
}
}
else
fprintf (out, _("; no contents available\n"));
 
if (fclose (out) == EOF)
/* xgettext:c-format */
einfo (_("%P: Error closing file `%s'\n"), pe_out_def_filename);
}
 
/* Generate the import library. */
 
static asymbol **symtab;
static int symptr;
static int tmp_seq;
static int tmp_seq2;
static const char *dll_filename;
static char *dll_symname;
 
#define UNDSEC bfd_und_section_ptr
 
static asection *
quick_section (bfd *abfd, const char *name, int flags, int align)
{
asection *sec;
asymbol *sym;
 
sec = bfd_make_section_old_way (abfd, name);
bfd_set_section_flags (abfd, sec, flags | SEC_ALLOC | SEC_LOAD | SEC_KEEP);
bfd_set_section_alignment (abfd, sec, align);
/* Remember to undo this before trying to link internally! */
sec->output_section = sec;
 
sym = bfd_make_empty_symbol (abfd);
symtab[symptr++] = sym;
sym->name = sec->name;
sym->section = sec;
sym->flags = BSF_LOCAL;
sym->value = 0;
 
return sec;
}
 
static void
quick_symbol (bfd *abfd,
const char *n1,
const char *n2,
const char *n3,
asection *sec,
int flags,
int addr)
{
asymbol *sym;
char *name = xmalloc (strlen (n1) + strlen (n2) + strlen (n3) + 1);
 
strcpy (name, n1);
strcat (name, n2);
strcat (name, n3);
sym = bfd_make_empty_symbol (abfd);
sym->name = name;
sym->section = sec;
sym->flags = flags;
sym->value = addr;
symtab[symptr++] = sym;
}
 
static arelent *reltab = 0;
static int relcount = 0, relsize = 0;
 
static void
quick_reloc (bfd *abfd, bfd_size_type address, int which_howto, int symidx)
{
if (relcount >= relsize - 1)
{
relsize += 10;
if (reltab)
reltab = xrealloc (reltab, relsize * sizeof (arelent));
else
reltab = xmalloc (relsize * sizeof (arelent));
}
reltab[relcount].address = address;
reltab[relcount].addend = 0;
reltab[relcount].howto = bfd_reloc_type_lookup (abfd, which_howto);
reltab[relcount].sym_ptr_ptr = symtab + symidx;
relcount++;
}
 
static void
save_relocs (asection *sec)
{
int i;
 
sec->relocation = reltab;
sec->reloc_count = relcount;
sec->orelocation = xmalloc ((relcount + 1) * sizeof (arelent *));
for (i = 0; i < relcount; i++)
sec->orelocation[i] = sec->relocation + i;
sec->orelocation[relcount] = 0;
sec->flags |= SEC_RELOC;
reltab = 0;
relcount = relsize = 0;
}
 
/* .section .idata$2
.global __head_my_dll
__head_my_dll:
.rva hname
.long 0
.long 0
.rva __my_dll_iname
.rva fthunk
 
.section .idata$5
.long 0
fthunk:
 
.section .idata$4
.long 0
hname: */
 
static bfd *
make_head (bfd *parent)
{
asection *id2, *id5, *id4;
unsigned char *d2, *d5, *d4;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "d%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (6 * sizeof (asymbol *));
id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
quick_symbol (abfd, U ("_head_"), dll_symname, "", id2, BSF_GLOBAL, 0);
quick_symbol (abfd, U (""), dll_symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
 
/* OK, pay attention here. I got confused myself looking back at
it. We create a four-byte section to mark the beginning of the
list, and we include an offset of 4 in the section, so that the
pointer to the list points to the *end* of this section, which is
the start of the list of sections from other objects. */
 
bfd_set_section_size (abfd, id2, 20);
d2 = xmalloc (20);
id2->contents = d2;
memset (d2, 0, 20);
if (pe_use_nul_prefixed_import_tables)
d2[0] = d2[16] = PE_IDATA5_SIZE; /* Reloc addend. */
quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
quick_reloc (abfd, 12, BFD_RELOC_RVA, 4);
quick_reloc (abfd, 16, BFD_RELOC_RVA, 1);
save_relocs (id2);
 
if (pe_use_nul_prefixed_import_tables)
bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
else
bfd_set_section_size (abfd, id5, 0);
d5 = xmalloc (PE_IDATA5_SIZE);
id5->contents = d5;
memset (d5, 0, PE_IDATA5_SIZE);
if (pe_use_nul_prefixed_import_tables)
bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
else
bfd_set_section_size (abfd, id4, 0);
d4 = xmalloc (PE_IDATA4_SIZE);
id4->contents = d4;
memset (d4, 0, PE_IDATA4_SIZE);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, id2, d2, 0, 20);
if (pe_use_nul_prefixed_import_tables)
{
bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
}
else
{
bfd_set_section_contents (abfd, id5, d5, 0, 0);
bfd_set_section_contents (abfd, id4, d4, 0, 0);
}
 
bfd_make_readable (abfd);
return abfd;
}
 
/* .section .idata$4
.long 0
[.long 0] for PE+
.section .idata$5
.long 0
[.long 0] for PE+
.section idata$7
.global __my_dll_iname
__my_dll_iname:
.asciz "my.dll" */
 
static bfd *
make_tail (bfd *parent)
{
asection *id4, *id5, *id7;
unsigned char *d4, *d5, *d7;
int len;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "d%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (5 * sizeof (asymbol *));
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
quick_symbol (abfd, U (""), dll_symname, "_iname", id7, BSF_GLOBAL, 0);
 
bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
d4 = xmalloc (PE_IDATA4_SIZE);
id4->contents = d4;
memset (d4, 0, PE_IDATA4_SIZE);
 
bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
d5 = xmalloc (PE_IDATA5_SIZE);
id5->contents = d5;
memset (d5, 0, PE_IDATA5_SIZE);
 
len = strlen (dll_filename) + 1;
if (len & 1)
len++;
bfd_set_section_size (abfd, id7, len);
d7 = xmalloc (len);
id7->contents = d7;
strcpy ((char *) d7, dll_filename);
/* If len was odd, the above
strcpy leaves behind an undefined byte. That is harmless,
but we set it to 0 just so the binary dumps are pretty. */
d7[len - 1] = 0;
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
bfd_set_section_contents (abfd, id7, d7, 0, len);
 
bfd_make_readable (abfd);
return abfd;
}
 
/* .text
.global _function
.global ___imp_function
.global __imp__function
_function:
jmp *__imp__function:
 
.section idata$7
.long __head_my_dll
 
.section .idata$5
___imp_function:
__imp__function:
iat?
.section .idata$4
iat?
.section .idata$6
ID<ordinal>:
.short <hint>
.asciz "function" xlate? (add underscore, kill at) */
 
static const unsigned char jmp_ix86_bytes[] =
{
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
};
 
/* _function:
mov.l ip+8,r0
mov.l @r0,r0
jmp @r0
nop
.dw __imp_function */
 
static const unsigned char jmp_sh_bytes[] =
{
0x01, 0xd0, 0x02, 0x60, 0x2b, 0x40, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
};
 
/* _function:
lui $t0,<high:__imp_function>
lw $t0,<low:__imp_function>
jr $t0
nop */
 
static const unsigned char jmp_mips_bytes[] =
{
0x00, 0x00, 0x08, 0x3c, 0x00, 0x00, 0x08, 0x8d,
0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
};
 
static const unsigned char jmp_arm_bytes[] =
{
0x00, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc] */
0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */
0, 0, 0, 0
};
 
 
static bfd *
make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub)
{
asection *tx, *id7, *id5, *id4, *id6;
unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL;
int len;
char *oname;
bfd *abfd;
const unsigned char *jmp_bytes = NULL;
int jmp_byte_count = 0;
 
/* Include the jump stub section only if it is needed. A jump
stub is needed if the symbol being imported <sym> is a function
symbol and there is at least one undefined reference to that
symbol. In other words, if all the import references to <sym> are
explicitly through _declspec(dllimport) then the jump stub is not
needed. */
if (include_jmp_stub)
{
switch (pe_details->pe_arch)
{
case PE_ARCH_i386:
jmp_bytes = jmp_ix86_bytes;
jmp_byte_count = sizeof (jmp_ix86_bytes);
break;
case PE_ARCH_sh:
jmp_bytes = jmp_sh_bytes;
jmp_byte_count = sizeof (jmp_sh_bytes);
break;
case PE_ARCH_mips:
jmp_bytes = jmp_mips_bytes;
jmp_byte_count = sizeof (jmp_mips_bytes);
break;
case PE_ARCH_arm:
case PE_ARCH_arm_epoc:
case PE_ARCH_arm_wince:
jmp_bytes = jmp_arm_bytes;
jmp_byte_count = sizeof (jmp_arm_bytes);
break;
default:
abort ();
}
}
 
oname = xmalloc (20);
sprintf (oname, "d%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (12 * sizeof (asymbol *));
 
tx = quick_section (abfd, ".text", SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY, 2);
id7 = quick_section (abfd, ".idata$7", SEC_HAS_CONTENTS, 2);
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
id6 = quick_section (abfd, ".idata$6", SEC_HAS_CONTENTS, 2);
 
if (*exp->internal_name == '@')
{
quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
BSF_GLOBAL, 0);
if (include_jmp_stub)
quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0);
quick_symbol (abfd, "__imp_", exp->internal_name, "", id5,
BSF_GLOBAL, 0);
/* Fastcall applies only to functions,
so no need for auto-import symbol. */
}
else
{
quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC,
BSF_GLOBAL, 0);
if (include_jmp_stub)
quick_symbol (abfd, U (""), exp->internal_name, "", tx,
BSF_GLOBAL, 0);
quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5,
BSF_GLOBAL, 0);
/* Symbol to reference ord/name of imported
data symbol, used to implement auto-import. */
if (exp->flag_data)
quick_symbol (abfd, "__nm_", U (""), exp->internal_name, id6,
BSF_GLOBAL,0);
}
if (pe_dll_compat_implib)
quick_symbol (abfd, "___imp_", exp->internal_name, "", id5,
BSF_GLOBAL, 0);
 
if (include_jmp_stub)
{
bfd_set_section_size (abfd, tx, jmp_byte_count);
td = xmalloc (jmp_byte_count);
tx->contents = td;
memcpy (td, jmp_bytes, jmp_byte_count);
 
switch (pe_details->pe_arch)
{
case PE_ARCH_i386:
#ifdef pe_use_x86_64
quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2);
#else
/* Mark this object as SAFESEH compatible. */
quick_symbol (abfd, "", "@feat.00", "", bfd_abs_section_ptr,
BSF_LOCAL, 1);
quick_reloc (abfd, 2, BFD_RELOC_32, 2);
#endif
break;
case PE_ARCH_sh:
quick_reloc (abfd, 8, BFD_RELOC_32, 2);
break;
case PE_ARCH_mips:
quick_reloc (abfd, 0, BFD_RELOC_HI16_S, 2);
quick_reloc (abfd, 0, BFD_RELOC_LO16, 0); /* MIPS_R_PAIR */
quick_reloc (abfd, 4, BFD_RELOC_LO16, 2);
break;
case PE_ARCH_arm:
case PE_ARCH_arm_epoc:
case PE_ARCH_arm_wince:
quick_reloc (abfd, 8, BFD_RELOC_32, 2);
break;
default:
abort ();
}
save_relocs (tx);
}
else
bfd_set_section_size (abfd, tx, 0);
 
bfd_set_section_size (abfd, id7, 4);
d7 = xmalloc (4);
id7->contents = d7;
memset (d7, 0, 4);
quick_reloc (abfd, 0, BFD_RELOC_RVA, 5);
save_relocs (id7);
 
bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE);
d5 = xmalloc (PE_IDATA5_SIZE);
id5->contents = d5;
memset (d5, 0, PE_IDATA5_SIZE);
 
if (exp->flag_noname)
{
d5[0] = exp->ordinal;
d5[1] = exp->ordinal >> 8;
d5[PE_IDATA5_SIZE - 1] = 0x80;
}
else
{
quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
save_relocs (id5);
}
 
bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE);
d4 = xmalloc (PE_IDATA4_SIZE);
id4->contents = d4;
memset (d4, 0, PE_IDATA4_SIZE);
 
if (exp->flag_noname)
{
d4[0] = exp->ordinal;
d4[1] = exp->ordinal >> 8;
d4[PE_IDATA4_SIZE - 1] = 0x80;
}
else
{
quick_reloc (abfd, 0, BFD_RELOC_RVA, 4);
save_relocs (id4);
}
 
if (exp->flag_noname)
{
len = 0;
bfd_set_section_size (abfd, id6, 0);
}
else
{
/* { short, asciz } */
if (exp->its_name)
len = 2 + strlen (exp->its_name) + 1;
else
len = 2 + strlen (exp->name) + 1;
if (len & 1)
len++;
bfd_set_section_size (abfd, id6, len);
d6 = xmalloc (len);
id6->contents = d6;
memset (d6, 0, len);
d6[0] = exp->hint & 0xff;
d6[1] = exp->hint >> 8;
if (exp->its_name)
strcpy ((char*) d6 + 2, exp->its_name);
else
strcpy ((char *) d6 + 2, exp->name);
}
 
bfd_set_symtab (abfd, symtab, symptr);
 
if (include_jmp_stub)
bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count);
bfd_set_section_contents (abfd, id7, d7, 0, 4);
bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE);
bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE);
if (!exp->flag_noname)
bfd_set_section_contents (abfd, id6, d6, 0, len);
 
bfd_make_readable (abfd);
return abfd;
}
 
static bfd *
make_singleton_name_imp (const char *import, bfd *parent)
{
/* Name thunks go to idata$4. */
asection *id5;
unsigned char *d5;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "nmimp%06d.o", tmp_seq2);
tmp_seq2++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (3 * sizeof (asymbol *));
id5 = quick_section (abfd, ".idata$5", SEC_HAS_CONTENTS, 2);
quick_symbol (abfd, "__imp_", import, "", id5, BSF_GLOBAL, 0);
 
/* We need space for the real thunk and for the null terminator. */
bfd_set_section_size (abfd, id5, PE_IDATA5_SIZE * 2);
d5 = xmalloc (PE_IDATA5_SIZE * 2);
id5->contents = d5;
memset (d5, 0, PE_IDATA5_SIZE * 2);
quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
save_relocs (id5);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA4_SIZE * 2);
 
bfd_make_readable (abfd);
return abfd;
}
 
static bfd *
make_singleton_name_thunk (const char *import, bfd *parent)
{
/* Name thunks go to idata$4. */
asection *id4;
unsigned char *d4;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "nmth%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (3 * sizeof (asymbol *));
id4 = quick_section (abfd, ".idata$4", SEC_HAS_CONTENTS, 2);
quick_symbol (abfd, "__nm_thnk_", import, "", id4, BSF_GLOBAL, 0);
quick_symbol (abfd, "__nm_", import, "", UNDSEC, BSF_GLOBAL, 0);
 
/* We need space for the real thunk and for the null terminator. */
bfd_set_section_size (abfd, id4, PE_IDATA4_SIZE * 2);
d4 = xmalloc (PE_IDATA4_SIZE * 2);
id4->contents = d4;
memset (d4, 0, PE_IDATA4_SIZE * 2);
quick_reloc (abfd, 0, BFD_RELOC_RVA, 2);
save_relocs (id4);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE * 2);
 
bfd_make_readable (abfd);
return abfd;
}
 
static char *
make_import_fixup_mark (arelent *rel)
{
/* We convert reloc to symbol, for later reference. */
static int counter;
static char *fixup_name = NULL;
static size_t buffer_len = 0;
 
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
 
bfd *abfd = bfd_asymbol_bfd (sym);
struct bfd_link_hash_entry *bh;
 
if (!fixup_name)
{
fixup_name = xmalloc (384);
buffer_len = 384;
}
 
if (strlen (sym->name) + 25 > buffer_len)
/* Assume 25 chars for "__fu" + counter + "_". If counter is
bigger than 20 digits long, we've got worse problems than
overflowing this buffer... */
{
free (fixup_name);
/* New buffer size is length of symbol, plus 25, but
then rounded up to the nearest multiple of 128. */
buffer_len = ((strlen (sym->name) + 25) + 127) & ~127;
fixup_name = xmalloc (buffer_len);
}
 
sprintf (fixup_name, "__fu%d_%s", counter++, sym->name);
 
bh = NULL;
bfd_coff_link_add_one_symbol (&link_info, abfd, fixup_name, BSF_GLOBAL,
current_sec, /* sym->section, */
rel->address, NULL, TRUE, FALSE, &bh);
 
return fixup_name;
}
 
/* .section .idata$2
.rva __nm_thnk_SYM (singleton thunk with name of func)
.long 0
.long 0
.rva __my_dll_iname (name of dll)
.rva __fuNN_SYM (pointer to reference (address) in text) */
 
static bfd *
make_import_fixup_entry (const char *name,
const char *fixup_name,
const char *symname,
bfd *parent)
{
asection *id2;
unsigned char *d2;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "fu%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (6 * sizeof (asymbol *));
id2 = quick_section (abfd, ".idata$2", SEC_HAS_CONTENTS, 2);
 
quick_symbol (abfd, "__nm_thnk_", name, "", UNDSEC, BSF_GLOBAL, 0);
quick_symbol (abfd, U (""), symname, "_iname", UNDSEC, BSF_GLOBAL, 0);
/* For relocator v2 we have to use the .idata$5 element and not
fixup_name. */
if (link_info.pei386_runtime_pseudo_reloc == 2)
quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
else
quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
 
bfd_set_section_size (abfd, id2, 20);
d2 = xmalloc (20);
id2->contents = d2;
memset (d2, 0, 20);
 
quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
quick_reloc (abfd, 12, BFD_RELOC_RVA, 2);
quick_reloc (abfd, 16, BFD_RELOC_RVA, 3);
save_relocs (id2);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, id2, d2, 0, 20);
 
bfd_make_readable (abfd);
return abfd;
}
 
/* .section .rdata_runtime_pseudo_reloc
.long addend
.rva __fuNN_SYM (pointer to reference (address) in text) */
 
static bfd *
make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED,
const char *fixup_name,
bfd_vma addend ATTRIBUTE_UNUSED,
bfd_vma bitsize,
bfd *parent)
{
asection *rt_rel;
unsigned char *rt_rel_d;
char *oname;
bfd *abfd;
oname = xmalloc (20);
sprintf (oname, "rtr%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
if (link_info.pei386_runtime_pseudo_reloc == 2)
{
symtab = xmalloc ((runtime_pseudp_reloc_v2_init ? 3 : 6) * sizeof (asymbol *));
}
else
{
symtab = xmalloc (2 * sizeof (asymbol *));
}
rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc",
SEC_HAS_CONTENTS, 2);
 
quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
 
if (link_info.pei386_runtime_pseudo_reloc == 2)
{
size_t size = 12;
if (! runtime_pseudp_reloc_v2_init)
{
size += 12;
runtime_pseudp_reloc_v2_init = 1;
}
quick_symbol (abfd, "__imp_", name, "", UNDSEC, BSF_GLOBAL, 0);
 
bfd_set_section_size (abfd, rt_rel, size);
rt_rel_d = xmalloc (size);
rt_rel->contents = rt_rel_d;
memset (rt_rel_d, 0, size);
quick_reloc (abfd, size - 8, BFD_RELOC_RVA, 1);
quick_reloc (abfd, size - 12, BFD_RELOC_RVA, 2);
bfd_put_32 (abfd, bitsize, rt_rel_d + (size - 4));
if (size != 12)
bfd_put_32 (abfd, 1, rt_rel_d + 8);
save_relocs (rt_rel);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, size);
}
else
{
bfd_set_section_size (abfd, rt_rel, 8);
rt_rel_d = xmalloc (8);
rt_rel->contents = rt_rel_d;
memset (rt_rel_d, 0, 8);
 
bfd_put_32 (abfd, addend, rt_rel_d);
quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
 
save_relocs (rt_rel);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
}
bfd_make_readable (abfd);
return abfd;
}
 
/* .section .rdata
.rva __pei386_runtime_relocator */
 
static bfd *
pe_create_runtime_relocator_reference (bfd *parent)
{
asection *extern_rt_rel;
unsigned char *extern_rt_rel_d;
char *oname;
bfd *abfd;
 
oname = xmalloc (20);
sprintf (oname, "ertr%06d.o", tmp_seq);
tmp_seq++;
 
abfd = bfd_create (oname, parent);
bfd_find_target (pe_details->object_target, abfd);
bfd_make_writable (abfd);
 
bfd_set_format (abfd, bfd_object);
bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
 
symptr = 0;
symtab = xmalloc (2 * sizeof (asymbol *));
extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
 
quick_symbol (abfd, "", U ("_pei386_runtime_relocator"), "", UNDSEC,
BSF_NO_FLAGS, 0);
 
bfd_set_section_size (abfd, extern_rt_rel, PE_IDATA5_SIZE);
extern_rt_rel_d = xmalloc (PE_IDATA5_SIZE);
extern_rt_rel->contents = extern_rt_rel_d;
 
quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
save_relocs (extern_rt_rel);
 
bfd_set_symtab (abfd, symtab, symptr);
 
bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, PE_IDATA5_SIZE);
 
bfd_make_readable (abfd);
return abfd;
}
 
void
pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend)
{
char buf[300];
struct bfd_symbol *sym = *rel->sym_ptr_ptr;
struct bfd_link_hash_entry *name_thunk_sym;
struct bfd_link_hash_entry *name_imp_sym;
const char *name = sym->name;
char *fixup_name = make_import_fixup_mark (rel);
bfd *b;
int need_import_table = 1;
 
sprintf (buf, "__imp_%s", name);
name_imp_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
 
sprintf (buf, "__nm_thnk_%s", name);
 
name_thunk_sym = bfd_link_hash_lookup (link_info.hash, buf, 0, 0, 1);
 
/* For version 2 pseudo relocation we don't need to add an import
if the import symbol is already present. */
if (link_info.pei386_runtime_pseudo_reloc == 2
&& name_imp_sym
&& name_imp_sym->type == bfd_link_hash_defined)
need_import_table = 0;
 
if (need_import_table == 1
&& (!name_thunk_sym || name_thunk_sym->type != bfd_link_hash_defined))
{
b = make_singleton_name_thunk (name, link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
 
/* If we ever use autoimport, we have to cast text section writable.
But not for version 2. */
if (link_info.pei386_runtime_pseudo_reloc != 2)
{
config.text_read_only = FALSE;
link_info.output_bfd->flags &= ~WP_TEXT;
}
if (link_info.pei386_runtime_pseudo_reloc == 2)
{
b = make_singleton_name_imp (name, link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
}
}
 
if ((addend == 0 || link_info.pei386_runtime_pseudo_reloc)
&& need_import_table == 1)
{
extern char * pe_data_import_dll;
char * symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
 
b = make_import_fixup_entry (name, fixup_name, symname,
link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
}
 
if ((link_info.pei386_runtime_pseudo_reloc != 0 && addend != 0)
|| link_info.pei386_runtime_pseudo_reloc == 2)
{
if (pe_dll_extra_pe_debug)
printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
fixup_name, (int) addend);
 
b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize,
link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
 
if (runtime_pseudo_relocs_created == 0)
{
b = pe_create_runtime_relocator_reference (link_info.output_bfd);
add_bfd_to_link (b, b->filename, &link_info);
}
runtime_pseudo_relocs_created++;
}
else if (addend != 0)
{
einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
s->owner, s, rel->address, sym->name);
einfo ("%X");
}
}
 
 
void
pe_dll_generate_implib (def_file *def, const char *impfilename, struct bfd_link_info *info)
{
int i;
bfd *ar_head;
bfd *ar_tail;
bfd *outarch;
bfd *ibfd;
bfd *head = 0;
 
dll_filename = (def->name) ? def->name : dll_name;
dll_symname = xstrdup (dll_filename);
for (i = 0; dll_symname[i]; i++)
if (!ISALNUM (dll_symname[i]))
dll_symname[i] = '_';
 
unlink_if_ordinary (impfilename);
 
outarch = bfd_openw (impfilename, 0);
 
if (!outarch)
{
/* xgettext:c-format */
einfo (_("%XCan't open .lib file: %s\n"), impfilename);
return;
}
 
if (verbose)
/* xgettext:c-format */
info_msg (_("Creating library file: %s\n"), impfilename);
 
bfd_set_format (outarch, bfd_archive);
outarch->has_armap = 1;
 
/* Work out a reasonable size of things to put onto one line. */
ar_head = make_head (outarch);
 
/* Iterate the input BFDs, looking for exclude-modules-for-implib. */
for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
{
/* Iterate the exclude list. */
struct exclude_list_struct *ex;
char found;
for (ex = excludes, found = 0; ex && !found; ex = ex->next)
{
if (ex->type != EXCLUDEFORIMPLIB)
continue;
found = (filename_cmp (ex->string, ibfd->filename) == 0);
}
/* If it matched, we must open a fresh BFD for it (the original
input BFD is still needed for the DLL's final link) and add
it into the archive member chain. */
if (found)
{
bfd *newbfd = bfd_openr (ibfd->my_archive
? ibfd->my_archive->filename : ibfd->filename, NULL);
if (!newbfd)
{
einfo (_("%Xbfd_openr %s: %E\n"), ibfd->filename);
return;
}
if (ibfd->my_archive)
{
/* Must now iterate through archive until we find the
required member. A minor shame that we'll open the
archive once per member that we require from it, and
leak those archive bfds rather than reuse them. */
bfd *arbfd = newbfd;
if (!bfd_check_format_matches (arbfd, bfd_archive, NULL))
{
einfo (_("%X%s(%s): can't find member in non-archive file"),
ibfd->my_archive->filename, ibfd->filename);
return;
}
newbfd = NULL;
while ((newbfd = bfd_openr_next_archived_file (arbfd, newbfd)) != 0)
{
if (filename_cmp (newbfd->filename, ibfd->filename) == 0)
break;
}
if (!newbfd)
{
einfo (_("%X%s(%s): can't find member in archive"),
ibfd->my_archive->filename, ibfd->filename);
return;
}
}
newbfd->archive_next = head;
head = newbfd;
}
}
 
for (i = 0; i < def->num_exports; i++)
{
/* The import library doesn't know about the internal name. */
char *internal = def->exports[i].internal_name;
bfd *n;
 
/* Don't add PRIVATE entries to import lib. */
if (pe_def_file->exports[i].flag_private)
continue;
def->exports[i].internal_name = def->exports[i].name;
n = make_one (def->exports + i, outarch,
! (def->exports + i)->flag_data);
n->archive_next = head;
head = n;
def->exports[i].internal_name = internal;
}
 
ar_tail = make_tail (outarch);
 
if (ar_head == NULL || ar_tail == NULL)
return;
 
/* Now stick them all into the archive. */
ar_head->archive_next = head;
ar_tail->archive_next = ar_head;
head = ar_tail;
 
if (! bfd_set_archive_head (outarch, head))
einfo ("%Xbfd_set_archive_head: %E\n");
 
if (! bfd_close (outarch))
einfo ("%Xbfd_close %s: %E\n", impfilename);
 
while (head != NULL)
{
bfd *n = head->archive_next;
bfd_close (head);
head = n;
}
}
 
static int undef_count = 0;
 
struct key_value
{
char *key;
const char *oname;
};
 
static struct key_value *udef_table;
 
static int undef_sort_cmp (const void *l1, const void *r1)
{
const struct key_value *l = l1;
const struct key_value *r = r1;
 
return strcmp (l->key, r->key);
}
 
static struct bfd_link_hash_entry *
pe_find_cdecl_alias_match (struct bfd_link_info *linfo, char *name)
{
struct bfd_link_hash_entry *h = NULL;
struct key_value *kv;
struct key_value key;
char *at, *lname = (char *) alloca (strlen (name) + 3);
 
strcpy (lname, name);
 
at = strchr (lname + (lname[0] == '@'), '@');
if (at)
at[1] = 0;
 
key.key = lname;
kv = bsearch (&key, udef_table, undef_count, sizeof (struct key_value),
undef_sort_cmp);
 
if (kv)
{
h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
if (h->type == bfd_link_hash_undefined)
return h;
}
if (lname[0] == '?')
return NULL;
if (at || lname[0] == '@')
{
if (lname[0] == '@')
{
if (pe_details->underscored)
lname[0] = '_';
else
strcpy (lname, lname + 1);
key.key = lname;
kv = bsearch (&key, udef_table, undef_count,
sizeof (struct key_value), undef_sort_cmp);
if (kv)
{
h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
if (h->type == bfd_link_hash_undefined)
return h;
}
}
if (at)
*strchr (lname, '@') = 0;
key.key = lname;
kv = bsearch (&key, udef_table, undef_count,
sizeof (struct key_value), undef_sort_cmp);
if (kv)
{
h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
if (h->type == bfd_link_hash_undefined)
return h;
}
return NULL;
}
 
strcat (lname, "@");
key.key = lname;
kv = bsearch (&key, udef_table, undef_count,
sizeof (struct key_value), undef_sort_cmp);
 
if (kv)
{
h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
if (h->type == bfd_link_hash_undefined)
return h;
}
 
if (lname[0] == '_' && pe_details->underscored)
lname[0] = '@';
else
{
memmove (lname + 1, lname, strlen (lname) + 1);
lname[0] = '@';
}
key.key = lname;
 
kv = bsearch (&key, udef_table, undef_count,
sizeof (struct key_value), undef_sort_cmp);
 
if (kv)
{
h = bfd_link_hash_lookup (linfo->hash, kv->oname, FALSE, FALSE, FALSE);
if (h->type == bfd_link_hash_undefined)
return h;
}
 
return NULL;
}
 
static bfd_boolean
pe_undef_count (struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
void *inf ATTRIBUTE_UNUSED)
{
if (h->type == bfd_link_hash_undefined)
undef_count++;
return TRUE;
}
 
static bfd_boolean
pe_undef_fill (struct bfd_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
{
if (h->type == bfd_link_hash_undefined)
{
char *at;
 
udef_table[undef_count].key = xstrdup (h->root.string);
at = strchr (udef_table[undef_count].key
+ (udef_table[undef_count].key[0] == '@'), '@');
if (at)
at[1] = 0;
udef_table[undef_count].oname = h->root.string;
undef_count++;
}
return TRUE;
}
 
static void
pe_create_undef_table (void)
{
undef_count = 0;
 
/* count undefined symbols */
 
bfd_link_hash_traverse (link_info.hash, pe_undef_count, "");
 
/* create and fill the corresponding table */
udef_table = xmalloc (undef_count * sizeof (struct key_value));
 
undef_count = 0;
bfd_link_hash_traverse (link_info.hash, pe_undef_fill, "");
 
/* sort items */
qsort (udef_table, undef_count, sizeof (struct key_value), undef_sort_cmp);
}
 
static void
add_bfd_to_link (bfd *abfd, const char *name, struct bfd_link_info *linfo)
{
lang_input_statement_type *fake_file;
 
fake_file = lang_add_input_file (name,
lang_input_file_is_fake_enum,
NULL);
fake_file->the_bfd = abfd;
ldlang_add_file (fake_file);
 
if (!bfd_link_add_symbols (abfd, linfo))
einfo ("%Xaddsym %s: %E\n", name);
}
 
void
pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *linfo)
{
int i, j;
def_file_module *module;
def_file_import *imp;
 
pe_dll_id_target (bfd_get_target (output_bfd));
 
if (!pe_def_file)
return;
 
imp = pe_def_file->imports;
 
pe_create_undef_table ();
 
for (module = pe_def_file->modules; module; module = module->next)
{
int do_this_dll = 0;
 
for (i = 0; i < pe_def_file->num_imports && imp[i].module != module; i++)
;
if (i >= pe_def_file->num_imports)
continue;
 
dll_filename = module->name;
dll_symname = xstrdup (module->name);
for (j = 0; dll_symname[j]; j++)
if (!ISALNUM (dll_symname[j]))
dll_symname[j] = '_';
 
for (; i < pe_def_file->num_imports && imp[i].module == module; i++)
{
def_file_export exp;
struct bfd_link_hash_entry *blhe;
int lead_at = (*imp[i].internal_name == '@');
/* See if we need this import. */
size_t len = strlen (imp[i].internal_name);
char *name = xmalloc (len + 2 + 6);
bfd_boolean include_jmp_stub = FALSE;
bfd_boolean is_cdecl = FALSE;
bfd_boolean is_undef = FALSE;
 
if (!lead_at && strchr (imp[i].internal_name, '@') == NULL)
is_cdecl = TRUE;
 
if (lead_at)
sprintf (name, "%s", imp[i].internal_name);
else
sprintf (name, "%s%s",U (""), imp[i].internal_name);
 
blhe = bfd_link_hash_lookup (linfo->hash, name,
FALSE, FALSE, FALSE);
 
/* Include the jump stub for <sym> only if the <sym>
is undefined. */
if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
{
if (lead_at)
sprintf (name, "%s%s", "__imp_", imp[i].internal_name);
else
sprintf (name, "%s%s%s", "__imp_", U (""),
imp[i].internal_name);
 
blhe = bfd_link_hash_lookup (linfo->hash, name,
FALSE, FALSE, FALSE);
if (blhe)
is_undef = (blhe->type == bfd_link_hash_undefined);
}
else
{
include_jmp_stub = TRUE;
is_undef = (blhe->type == bfd_link_hash_undefined);
}
 
if (is_cdecl && (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)))
{
sprintf (name, "%s%s",U (""), imp[i].internal_name);
blhe = pe_find_cdecl_alias_match (linfo, name);
include_jmp_stub = TRUE;
if (blhe)
is_undef = (blhe->type == bfd_link_hash_undefined);
}
 
free (name);
 
if (is_undef)
{
bfd *one;
/* We do. */
if (!do_this_dll)
{
bfd *ar_head = make_head (output_bfd);
add_bfd_to_link (ar_head, ar_head->filename, linfo);
do_this_dll = 1;
}
exp.internal_name = imp[i].internal_name;
exp.name = imp[i].name;
exp.its_name = imp[i].its_name;
exp.ordinal = imp[i].ordinal;
exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
exp.flag_private = 0;
exp.flag_constant = 0;
exp.flag_data = imp[i].data;
exp.flag_noname = exp.name ? 0 : 1;
one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub);
add_bfd_to_link (one, one->filename, linfo);
}
}
if (do_this_dll)
{
bfd *ar_tail = make_tail (output_bfd);
add_bfd_to_link (ar_tail, ar_tail->filename, linfo);
}
 
free (dll_symname);
}
 
while (undef_count)
{
--undef_count;
free (udef_table[undef_count].key);
}
free (udef_table);
}
 
/* We were handed a *.DLL file. Parse it and turn it into a set of
IMPORTS directives in the def file. Return TRUE if the file was
handled, FALSE if not. */
 
static unsigned int
pe_get16 (bfd *abfd, int where)
{
unsigned char b[2];
 
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
bfd_bread (b, (bfd_size_type) 2, abfd);
return b[0] + (b[1] << 8);
}
 
static unsigned int
pe_get32 (bfd *abfd, int where)
{
unsigned char b[4];
 
bfd_seek (abfd, (file_ptr) where, SEEK_SET);
bfd_bread (b, (bfd_size_type) 4, abfd);
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
}
 
static unsigned int
pe_as32 (void *ptr)
{
unsigned char *b = ptr;
 
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
}
 
bfd_boolean
pe_implied_import_dll (const char *filename)
{
bfd *dll;
bfd_vma pe_header_offset, opthdr_ofs, num_entries, i;
bfd_vma export_rva, export_size, nsections, secptr, expptr;
bfd_vma exp_funcbase;
unsigned char *expdata;
char *erva;
bfd_vma name_rvas, nexp;
const char *dllname;
/* Initialization with start > end guarantees that is_data
will not be set by mistake, and avoids compiler warning. */
bfd_vma data_start = 1;
bfd_vma data_end = 0;
bfd_vma rdata_start = 1;
bfd_vma rdata_end = 0;
bfd_vma bss_start = 1;
bfd_vma bss_end = 0;
 
/* No, I can't use bfd here. kernel32.dll puts its export table in
the middle of the .rdata section. */
dll = bfd_openr (filename, pe_details->target_name);
if (!dll)
{
einfo ("%Xopen %s: %E\n", filename);
return FALSE;
}
 
/* PEI dlls seem to be bfd_objects. */
if (!bfd_check_format (dll, bfd_object))
{
einfo ("%X%s: this doesn't appear to be a DLL\n", filename);
return FALSE;
}
 
/* Get pe_header, optional header and numbers of directory entries. */
pe_header_offset = pe_get32 (dll, 0x3c);
opthdr_ofs = pe_header_offset + 4 + 20;
#ifdef pe_use_x86_64
num_entries = pe_get32 (dll, opthdr_ofs + 92 + 4 * 4); /* & NumberOfRvaAndSizes. */
#else
num_entries = pe_get32 (dll, opthdr_ofs + 92);
#endif
 
/* No import or export directory entry. */
if (num_entries < 1)
return FALSE;
 
#ifdef pe_use_x86_64
export_rva = pe_get32 (dll, opthdr_ofs + 96 + 4 * 4);
export_size = pe_get32 (dll, opthdr_ofs + 100 + 4 * 4);
#else
export_rva = pe_get32 (dll, opthdr_ofs + 96);
export_size = pe_get32 (dll, opthdr_ofs + 100);
#endif
 
/* No export table - nothing to export. */
if (export_size == 0)
return FALSE;
 
nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
secptr = (pe_header_offset + 4 + 20 +
pe_get16 (dll, pe_header_offset + 4 + 16));
expptr = 0;
 
/* Get the rva and size of the export section. */
for (i = 0; i < nsections; i++)
{
char sname[8];
bfd_vma secptr1 = secptr + 40 * i;
bfd_vma vaddr = pe_get32 (dll, secptr1 + 12);
bfd_vma vsize = pe_get32 (dll, secptr1 + 16);
bfd_vma fptr = pe_get32 (dll, secptr1 + 20);
 
bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
bfd_bread (sname, (bfd_size_type) 8, dll);
 
if (vaddr <= export_rva && vaddr + vsize > export_rva)
{
expptr = fptr + (export_rva - vaddr);
if (export_rva + export_size > vaddr + vsize)
export_size = vsize - (export_rva - vaddr);
break;
}
}
 
/* Scan sections and store the base and size of the
data and bss segments in data/base_start/end. */
for (i = 0; i < nsections; i++)
{
bfd_vma secptr1 = secptr + 40 * i;
bfd_vma vsize = pe_get32 (dll, secptr1 + 8);
bfd_vma vaddr = pe_get32 (dll, secptr1 + 12);
bfd_vma flags = pe_get32 (dll, secptr1 + 36);
char sec_name[9];
 
sec_name[8] = '\0';
bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
bfd_bread (sec_name, (bfd_size_type) 8, dll);
 
if (strcmp(sec_name,".data") == 0)
{
data_start = vaddr;
data_end = vaddr + vsize;
 
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
else if (strcmp(sec_name,".rdata") == 0)
{
rdata_start = vaddr;
rdata_end = vaddr + vsize;
 
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
else if (strcmp (sec_name,".bss") == 0)
{
bss_start = vaddr;
bss_end = vaddr + vsize;
 
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, (unsigned long) vaddr,
(unsigned long) (vaddr + vsize), (unsigned long) flags);
}
}
 
expdata = xmalloc (export_size);
bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
bfd_bread (expdata, (bfd_size_type) export_size, dll);
erva = (char *) expdata - export_rva;
 
if (pe_def_file == 0)
pe_def_file = def_file_empty ();
 
nexp = pe_as32 (expdata + 24);
name_rvas = pe_as32 (expdata + 32);
exp_funcbase = pe_as32 (expdata + 28);
 
/* Use internal dll name instead of filename
to enable symbolic dll linking. */
dllname = erva + pe_as32 (expdata + 12);
 
/* Check to see if the dll has already been added to
the definition list and if so return without error.
This avoids multiple symbol definitions. */
if (def_get_module (pe_def_file, dllname))
{
if (pe_dll_extra_pe_debug)
printf ("%s is already loaded\n", dllname);
return TRUE;
}
 
/* Iterate through the list of symbols. */
for (i = 0; i < nexp; i++)
{
/* Pointer to the names vector. */
bfd_vma name_rva = pe_as32 (erva + name_rvas + i * 4);
def_file_import *imp;
/* Pointer to the function address vector. */
bfd_vma func_rva = pe_as32 (erva + exp_funcbase + i * 4);
int is_data = 0;
 
/* Skip unwanted symbols, which are
exported in buggy auto-import releases. */
if (! CONST_STRNEQ (erva + name_rva, "__nm_"))
{
int is_dup = 0;
/* is_data is true if the address is in the data, rdata or bss
segment. */
is_data =
(func_rva >= data_start && func_rva < data_end)
|| (func_rva >= rdata_start && func_rva < rdata_end)
|| (func_rva >= bss_start && func_rva < bss_end);
 
imp = def_file_add_import (pe_def_file, erva + name_rva,
dllname, i, NULL, NULL, &is_dup);
/* Mark symbol type. */
if (!is_dup)
imp->data = is_data;
 
if (pe_dll_extra_pe_debug)
printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
__FUNCTION__, dllname, erva + name_rva,
(unsigned long) func_rva, is_data ? "(data)" : "");
}
}
 
return TRUE;
}
 
void
pe_output_file_set_long_section_names (bfd *abfd)
{
if (pe_use_coff_long_section_names < 0)
return;
if (!bfd_coff_set_long_section_names (abfd, pe_use_coff_long_section_names))
einfo (_("%XError: can't use long section names on this arch\n"));
}
 
/* These are the main functions, called from the emulation. The first
is called after the bfds are read, so we can guess at how much space
we need. The second is called after everything is placed, so we
can put the right values in place. */
 
void
pe_dll_build_sections (bfd *abfd, struct bfd_link_info *info)
{
pe_dll_id_target (bfd_get_target (abfd));
pe_output_file_set_long_section_names (abfd);
process_def_file_and_drectve (abfd, info);
 
if (pe_def_file->num_exports == 0 && !info->shared)
return;
 
generate_edata (abfd, info);
build_filler_bfd (1);
pe_output_file_set_long_section_names (filler_bfd);
}
 
void
pe_exe_build_sections (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
pe_dll_id_target (bfd_get_target (abfd));
pe_output_file_set_long_section_names (abfd);
build_filler_bfd (0);
pe_output_file_set_long_section_names (filler_bfd);
}
 
void
pe_dll_fill_sections (bfd *abfd, struct bfd_link_info *info)
{
pe_dll_id_target (bfd_get_target (abfd));
pe_output_file_set_long_section_names (abfd);
image_base = pe_data (abfd)->pe_opthdr.ImageBase;
 
generate_reloc (abfd, info);
if (reloc_sz > 0)
{
bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
 
/* Resize the sections. */
lang_reset_memory_regions ();
lang_size_sections (NULL, TRUE);
 
/* Redo special stuff. */
ldemul_after_allocation ();
 
/* Do the assignments again. */
lang_do_assignments (lang_final_phase_enum);
}
 
fill_edata (abfd, info);
 
if (info->shared && !info->pie)
pe_data (abfd)->dll = 1;
 
edata_s->contents = edata_d;
reloc_s->contents = reloc_d;
}
 
void
pe_exe_fill_sections (bfd *abfd, struct bfd_link_info *info)
{
pe_dll_id_target (bfd_get_target (abfd));
pe_output_file_set_long_section_names (abfd);
image_base = pe_data (abfd)->pe_opthdr.ImageBase;
 
generate_reloc (abfd, info);
if (reloc_sz > 0)
{
bfd_set_section_size (filler_bfd, reloc_s, reloc_sz);
 
/* Resize the sections. */
lang_reset_memory_regions ();
lang_size_sections (NULL, TRUE);
 
/* Redo special stuff. */
ldemul_after_allocation ();
 
/* Do the assignments again. */
lang_do_assignments (lang_final_phase_enum);
}
reloc_s->contents = reloc_d;
}
 
bfd_boolean
pe_bfd_is_dll (bfd *abfd)
{
return (bfd_get_format (abfd) == bfd_object
&& obj_pe (abfd)
&& pe_data (abfd)->dll);
}
/contrib/toolchain/binutils/ld/pe-dll.h
0,0 → 1,74
/* pe-dll.h: Header file for routines used to build Windows DLLs.
Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef PE_DLL_H
#define PE_DLL_H
 
#include "sysdep.h"
#include "bfd.h"
#include "bfdlink.h"
#include "deffile.h"
 
extern def_file *pe_def_file;
extern int pe_dll_export_everything;
extern int pe_dll_exclude_all_symbols;
extern int pe_dll_do_default_excludes;
extern int pe_dll_kill_ats;
extern int pe_dll_stdcall_aliases;
extern int pe_dll_warn_dup_exports;
extern int pe_dll_compat_implib;
extern int pe_dll_extra_pe_debug;
extern int pe_use_nul_prefixed_import_tables;
extern int pe_use_coff_long_section_names;
extern int pe_leading_underscore;
 
typedef enum { EXCLUDESYMS, EXCLUDELIBS, EXCLUDEFORIMPLIB } exclude_type;
 
extern void pe_dll_id_target
(const char *);
extern void pe_dll_add_excludes
(const char *, const exclude_type);
extern void pe_dll_generate_def_file
(const char *);
extern void pe_dll_generate_implib
(def_file *, const char *, struct bfd_link_info *);
extern void pe_process_import_defs
(bfd *, struct bfd_link_info *);
extern bfd_boolean pe_implied_import_dll
(const char *);
extern void pe_dll_build_sections
(bfd *, struct bfd_link_info *);
extern void pe_exe_build_sections
(bfd *, struct bfd_link_info *);
extern void pe_dll_fill_sections
(bfd *, struct bfd_link_info *);
extern void pe_exe_fill_sections
(bfd *, struct bfd_link_info *);
extern void pe_walk_relocs_of_symbol
(struct bfd_link_info *, const char *, int (*) (arelent *, asection *));
extern void pe_create_import_fixup
(arelent * rel, asection *, bfd_vma);
extern bfd_boolean pe_bfd_is_dll
(bfd *);
extern void pe_output_file_set_long_section_names
(bfd *);
 
#endif /* PE_DLL_H */
/contrib/toolchain/binutils/ld/plugin.c
0,0 → 1,1041
/* Plugin control for the GNU linker.
Copyright 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#include "sysdep.h"
#include "libiberty.h"
#include "bfd.h"
#include "bfdlink.h"
#include "bfdver.h"
#include "ld.h"
#include "ldmain.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "plugin.h"
#include "plugin-api.h"
#include "elf-bfd.h"
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
#include <windows.h>
#endif
 
/* Report plugin symbols. */
bfd_boolean report_plugin_symbols;
 
/* The suffix to append to the name of the real (claimed) object file
when generating a dummy BFD to hold the IR symbols sent from the
plugin. For cosmetic use only; appears in maps, crefs etc. */
#define IRONLY_SUFFIX " (symbol from plugin)"
 
/* Stores a single argument passed to a plugin. */
typedef struct plugin_arg
{
struct plugin_arg *next;
const char *arg;
} plugin_arg_t;
 
/* Holds all details of a single plugin. */
typedef struct plugin
{
/* Next on the list of plugins, or NULL at end of chain. */
struct plugin *next;
/* The argument string given to --plugin. */
const char *name;
/* The shared library handle returned by dlopen. */
void *dlhandle;
/* The list of argument string given to --plugin-opt. */
plugin_arg_t *args;
/* Number of args in the list, for convenience. */
size_t n_args;
/* The plugin's event handlers. */
ld_plugin_claim_file_handler claim_file_handler;
ld_plugin_all_symbols_read_handler all_symbols_read_handler;
ld_plugin_cleanup_handler cleanup_handler;
/* TRUE if the cleanup handlers have been called. */
bfd_boolean cleanup_done;
} plugin_t;
 
/* The master list of all plugins. */
static plugin_t *plugins_list = NULL;
 
/* We keep a tail pointer for easy linking on the end. */
static plugin_t **plugins_tail_chain_ptr = &plugins_list;
 
/* The last plugin added to the list, for receiving args. */
static plugin_t *last_plugin = NULL;
 
/* The tail of the arg chain of the last plugin added to the list. */
static plugin_arg_t **last_plugin_args_tail_chain_ptr = NULL;
 
/* The plugin which is currently having a callback executed. */
static plugin_t *called_plugin = NULL;
 
/* Last plugin to cause an error, if any. */
static const char *error_plugin = NULL;
 
/* State of linker "notice" interface before we poked at it. */
static bfd_boolean orig_notice_all;
 
/* Original linker callbacks, and the plugin version. */
static const struct bfd_link_callbacks *orig_callbacks;
static struct bfd_link_callbacks plugin_callbacks;
 
/* Set at all symbols read time, to avoid recursively offering the plugin
its own newly-added input files and libs to claim. */
bfd_boolean no_more_claiming = FALSE;
 
/* List of tags to set in the constant leading part of the tv array. */
static const enum ld_plugin_tag tv_header_tags[] =
{
LDPT_MESSAGE,
LDPT_API_VERSION,
LDPT_GNU_LD_VERSION,
LDPT_LINKER_OUTPUT,
LDPT_OUTPUT_NAME,
LDPT_REGISTER_CLAIM_FILE_HOOK,
LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK,
LDPT_REGISTER_CLEANUP_HOOK,
LDPT_ADD_SYMBOLS,
LDPT_GET_INPUT_FILE,
LDPT_RELEASE_INPUT_FILE,
LDPT_GET_SYMBOLS,
LDPT_GET_SYMBOLS_V2,
LDPT_ADD_INPUT_FILE,
LDPT_ADD_INPUT_LIBRARY,
LDPT_SET_EXTRA_LIBRARY_PATH
};
 
/* How many entries in the constant leading part of the tv array. */
static const size_t tv_header_size = ARRAY_SIZE (tv_header_tags);
 
/* Forward references. */
static bfd_boolean plugin_notice (struct bfd_link_info *,
struct bfd_link_hash_entry *, bfd *,
asection *, bfd_vma, flagword, const char *);
 
#if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
#define RTLD_NOW 0 /* Dummy value. */
 
static void *
dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
{
return LoadLibrary (file);
}
 
static void *
dlsym (void *handle, const char *name)
{
return GetProcAddress (handle, name);
}
 
static int
dlclose (void *handle)
{
FreeLibrary (handle);
return 0;
}
 
#endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */
 
#ifndef HAVE_DLFCN_H
static const char *
dlerror (void)
{
return "";
}
#endif
 
/* Helper function for exiting with error status. */
static int
set_plugin_error (const char *plugin)
{
error_plugin = plugin;
return -1;
}
 
/* Test if an error occurred. */
static bfd_boolean
plugin_error_p (void)
{
return error_plugin != NULL;
}
 
/* Return name of plugin which caused an error if any. */
const char *
plugin_error_plugin (void)
{
return error_plugin ? error_plugin : _("<no plugin>");
}
 
/* Handle -plugin arg: find and load plugin, or return error. */
void
plugin_opt_plugin (const char *plugin)
{
plugin_t *newplug;
 
newplug = xmalloc (sizeof *newplug);
memset (newplug, 0, sizeof *newplug);
newplug->name = plugin;
newplug->dlhandle = dlopen (plugin, RTLD_NOW);
if (!newplug->dlhandle)
einfo (_("%P%F: %s: error loading plugin: %s\n"), plugin, dlerror ());
 
/* Chain on end, so when we run list it is in command-line order. */
*plugins_tail_chain_ptr = newplug;
plugins_tail_chain_ptr = &newplug->next;
 
/* Record it as current plugin for receiving args. */
last_plugin = newplug;
last_plugin_args_tail_chain_ptr = &newplug->args;
}
 
/* Accumulate option arguments for last-loaded plugin, or return
error if none. */
int
plugin_opt_plugin_arg (const char *arg)
{
plugin_arg_t *newarg;
 
if (!last_plugin)
return set_plugin_error (_("<no plugin>"));
 
newarg = xmalloc (sizeof *newarg);
newarg->arg = arg;
newarg->next = NULL;
 
/* Chain on end to preserve command-line order. */
*last_plugin_args_tail_chain_ptr = newarg;
last_plugin_args_tail_chain_ptr = &newarg->next;
last_plugin->n_args++;
return 0;
}
 
/* Create a dummy BFD. */
bfd *
plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
{
bfd *abfd;
 
bfd_use_reserved_id = 1;
abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL),
srctemplate);
if (abfd != NULL)
{
abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
if (bfd_make_writable (abfd)
&& bfd_copy_private_bfd_data (srctemplate, abfd))
{
flagword flags;
 
/* Create section to own the symbols. */
flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE);
if (bfd_make_section_anyway_with_flags (abfd, ".text", flags))
return abfd;
}
}
einfo (_("could not create dummy IR bfd: %F%E\n"));
return NULL;
}
 
/* Check if the BFD passed in is an IR dummy object file. */
static bfd_boolean
is_ir_dummy_bfd (const bfd *abfd)
{
/* ABFD can sometimes legitimately be NULL, e.g. when called from one
of the linker callbacks for a symbol in the *ABS* or *UND* sections.
Likewise, the usrdata field may be NULL if ABFD was added by the
backend without a corresponding input statement, as happens e.g.
when processing DT_NEEDED dependencies. */
return (abfd
&& abfd->usrdata
&& ((lang_input_statement_type *)(abfd->usrdata))->flags.claimed);
}
 
/* Helpers to convert between BFD and GOLD symbol formats. */
static enum ld_plugin_status
asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym,
const struct ld_plugin_symbol *ldsym)
{
flagword flags = BSF_NO_FLAGS;
struct bfd_section *section;
 
asym->the_bfd = abfd;
asym->name = (ldsym->version
? concat (ldsym->name, "@", ldsym->version, (const char *) NULL)
: ldsym->name);
asym->value = 0;
switch (ldsym->def)
{
case LDPK_WEAKDEF:
flags = BSF_WEAK;
/* FALLTHRU */
case LDPK_DEF:
flags |= BSF_GLOBAL;
if (ldsym->comdat_key)
{
char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key,
(const char *) NULL);
section = bfd_get_section_by_name (abfd, name);
if (section != NULL)
free (name);
else
{
flagword sflags;
 
sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY
| SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE
| SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD);
section = bfd_make_section_anyway_with_flags (abfd, name, sflags);
if (section == NULL)
return LDPS_ERR;
}
}
else
section = bfd_get_section_by_name (abfd, ".text");
break;
 
case LDPK_WEAKUNDEF:
flags = BSF_WEAK;
/* FALLTHRU */
case LDPK_UNDEF:
section = bfd_und_section_ptr;
break;
 
case LDPK_COMMON:
flags = BSF_GLOBAL;
section = bfd_com_section_ptr;
asym->value = ldsym->size;
/* For ELF targets, set alignment of common symbol to 1. */
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
}
break;
 
default:
return LDPS_ERR;
}
asym->flags = flags;
asym->section = section;
 
/* Visibility only applies on ELF targets. */
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
{
elf_symbol_type *elfsym = elf_symbol_from (abfd, asym);
unsigned char visibility;
 
if (!elfsym)
einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name);
switch (ldsym->visibility)
{
default:
einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"),
ldsym->visibility);
case LDPV_DEFAULT:
visibility = STV_DEFAULT;
break;
case LDPV_PROTECTED:
visibility = STV_PROTECTED;
break;
case LDPV_INTERNAL:
visibility = STV_INTERNAL;
break;
case LDPV_HIDDEN:
visibility = STV_HIDDEN;
break;
}
elfsym->internal_elf_sym.st_other
= (visibility | (elfsym->internal_elf_sym.st_other
& ~ELF_ST_VISIBILITY (-1)));
}
 
return LDPS_OK;
}
 
/* Register a claim-file handler. */
static enum ld_plugin_status
register_claim_file (ld_plugin_claim_file_handler handler)
{
ASSERT (called_plugin);
called_plugin->claim_file_handler = handler;
return LDPS_OK;
}
 
/* Register an all-symbols-read handler. */
static enum ld_plugin_status
register_all_symbols_read (ld_plugin_all_symbols_read_handler handler)
{
ASSERT (called_plugin);
called_plugin->all_symbols_read_handler = handler;
return LDPS_OK;
}
 
/* Register a cleanup handler. */
static enum ld_plugin_status
register_cleanup (ld_plugin_cleanup_handler handler)
{
ASSERT (called_plugin);
called_plugin->cleanup_handler = handler;
return LDPS_OK;
}
 
/* Add symbols from a plugin-claimed input file. */
static enum ld_plugin_status
add_symbols (void *handle, int nsyms, const struct ld_plugin_symbol *syms)
{
asymbol **symptrs;
bfd *abfd = handle;
int n;
 
ASSERT (called_plugin);
symptrs = xmalloc (nsyms * sizeof *symptrs);
for (n = 0; n < nsyms; n++)
{
enum ld_plugin_status rv;
asymbol *bfdsym;
 
bfdsym = bfd_make_empty_symbol (abfd);
symptrs[n] = bfdsym;
rv = asymbol_from_plugin_symbol (abfd, bfdsym, syms + n);
if (rv != LDPS_OK)
return rv;
}
bfd_set_symtab (abfd, symptrs, nsyms);
return LDPS_OK;
}
 
/* Get the input file information with an open (possibly re-opened)
file descriptor. */
static enum ld_plugin_status
get_input_file (const void *handle ATTRIBUTE_UNUSED,
struct ld_plugin_input_file *file ATTRIBUTE_UNUSED)
{
ASSERT (called_plugin);
return LDPS_ERR;
}
 
/* Release the input file. */
static enum ld_plugin_status
release_input_file (const void *handle ATTRIBUTE_UNUSED)
{
ASSERT (called_plugin);
return LDPS_ERR;
}
 
/* Return TRUE if a defined symbol might be reachable from outside the
universe of claimed objects. */
static inline bfd_boolean
is_visible_from_outside (struct ld_plugin_symbol *lsym,
struct bfd_link_hash_entry *blhe)
{
struct bfd_sym_chain *sym;
 
if (link_info.relocatable)
return TRUE;
if (link_info.export_dynamic || !link_info.executable)
{
/* Check if symbol is hidden by version script. */
if (bfd_hide_sym_by_version (link_info.version_info,
blhe->root.string))
return FALSE;
/* Only ELF symbols really have visibility. */
if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
{
struct elf_link_hash_entry *el = (struct elf_link_hash_entry *)blhe;
int vis = ELF_ST_VISIBILITY (el->other);
return vis == STV_DEFAULT || vis == STV_PROTECTED;
}
/* On non-ELF targets, we can safely make inferences by considering
what visibility the plugin would have liked to apply when it first
sent us the symbol. During ELF symbol processing, visibility only
ever becomes more restrictive, not less, when symbols are merged,
so this is a conservative estimate; it may give false positives,
declaring something visible from outside when it in fact would
not have been, but this will only lead to missed optimisation
opportunities during LTRANS at worst; it will not give false
negatives, which can lead to the disastrous conclusion that the
related symbol is IRONLY. (See GCC PR46319 for an example.) */
return (lsym->visibility == LDPV_DEFAULT
|| lsym->visibility == LDPV_PROTECTED);
}
 
for (sym = &entry_symbol; sym != NULL; sym = sym->next)
if (sym->name
&& strcmp (sym->name, blhe->root.string) == 0)
return TRUE;
 
return FALSE;
}
 
/* Get the symbol resolution info for a plugin-claimed input file. */
static enum ld_plugin_status
get_symbols (const void *handle, int nsyms, struct ld_plugin_symbol *syms,
int def_ironly_exp)
{
const bfd *abfd = handle;
int n;
 
ASSERT (called_plugin);
for (n = 0; n < nsyms; n++)
{
struct bfd_link_hash_entry *blhe;
asection *owner_sec;
int res;
 
if (syms[n].def != LDPK_UNDEF)
blhe = bfd_link_hash_lookup (link_info.hash, syms[n].name,
FALSE, FALSE, TRUE);
else
blhe = bfd_wrapped_link_hash_lookup (link_info.output_bfd, &link_info,
syms[n].name, FALSE, FALSE, TRUE);
if (!blhe)
{
res = LDPR_UNKNOWN;
goto report_symbol;
}
 
/* Determine resolution from blhe type and symbol's original type. */
if (blhe->type == bfd_link_hash_undefined
|| blhe->type == bfd_link_hash_undefweak)
{
res = LDPR_UNDEF;
goto report_symbol;
}
if (blhe->type != bfd_link_hash_defined
&& blhe->type != bfd_link_hash_defweak
&& blhe->type != bfd_link_hash_common)
{
/* We should not have a new, indirect or warning symbol here. */
einfo ("%P%F: %s: plugin symbol table corrupt (sym type %d)\n",
called_plugin->name, blhe->type);
}
 
/* Find out which section owns the symbol. Since it's not undef,
it must have an owner; if it's not a common symbol, both defs
and weakdefs keep it in the same place. */
owner_sec = (blhe->type == bfd_link_hash_common
? blhe->u.c.p->section
: blhe->u.def.section);
 
 
/* If it was originally undefined or common, then it has been
resolved; determine how. */
if (syms[n].def == LDPK_UNDEF
|| syms[n].def == LDPK_WEAKUNDEF
|| syms[n].def == LDPK_COMMON)
{
if (owner_sec->owner == link_info.output_bfd)
res = LDPR_RESOLVED_EXEC;
else if (owner_sec->owner == abfd)
res = LDPR_PREVAILING_DEF_IRONLY;
else if (is_ir_dummy_bfd (owner_sec->owner))
res = LDPR_RESOLVED_IR;
else if (owner_sec->owner != NULL
&& (owner_sec->owner->flags & DYNAMIC) != 0)
res = LDPR_RESOLVED_DYN;
else
res = LDPR_RESOLVED_EXEC;
}
 
/* Was originally def, or weakdef. Does it prevail? If the
owner is the original dummy bfd that supplied it, then this
is the definition that has prevailed. */
else if (owner_sec->owner == link_info.output_bfd)
res = LDPR_PREEMPTED_REG;
else if (owner_sec->owner == abfd)
res = LDPR_PREVAILING_DEF_IRONLY;
 
/* Was originally def, weakdef, or common, but has been pre-empted. */
else if (is_ir_dummy_bfd (owner_sec->owner))
res = LDPR_PREEMPTED_IR;
else
res = LDPR_PREEMPTED_REG;
 
if (res == LDPR_PREVAILING_DEF_IRONLY)
{
/* We need to know if the sym is referenced from non-IR files. Or
even potentially-referenced, perhaps in a future final link if
this is a partial one, perhaps dynamically at load-time if the
symbol is externally visible. */
if (blhe->non_ir_ref)
res = LDPR_PREVAILING_DEF;
else if (is_visible_from_outside (&syms[n], blhe))
res = def_ironly_exp;
}
 
report_symbol:
syms[n].resolution = res;
if (report_plugin_symbols)
einfo (_("%P: %B: symbol `%s' "
"definition: %d, visibility: %d, resolution: %d\n"),
abfd, syms[n].name,
syms[n].def, syms[n].visibility, res);
}
return LDPS_OK;
}
 
static enum ld_plugin_status
get_symbols_v1 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
{
return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF);
}
 
static enum ld_plugin_status
get_symbols_v2 (const void *handle, int nsyms, struct ld_plugin_symbol *syms)
{
return get_symbols (handle, nsyms, syms, LDPR_PREVAILING_DEF_IRONLY_EXP);
}
 
/* Add a new (real) input file generated by a plugin. */
static enum ld_plugin_status
add_input_file (const char *pathname)
{
ASSERT (called_plugin);
if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_file_enum,
NULL))
return LDPS_ERR;
return LDPS_OK;
}
 
/* Add a new (real) library required by a plugin. */
static enum ld_plugin_status
add_input_library (const char *pathname)
{
ASSERT (called_plugin);
if (!lang_add_input_file (xstrdup (pathname), lang_input_file_is_l_enum,
NULL))
return LDPS_ERR;
return LDPS_OK;
}
 
/* Set the extra library path to be used by libraries added via
add_input_library. */
static enum ld_plugin_status
set_extra_library_path (const char *path)
{
ASSERT (called_plugin);
ldfile_add_library_path (xstrdup (path), FALSE);
return LDPS_OK;
}
 
/* Issue a diagnostic message from a plugin. */
static enum ld_plugin_status
message (int level, const char *format, ...)
{
va_list args;
va_start (args, format);
 
switch (level)
{
case LDPL_INFO:
vfinfo (stdout, format, args, FALSE);
putchar ('\n');
break;
case LDPL_WARNING:
vfinfo (stdout, format, args, TRUE);
putchar ('\n');
break;
case LDPL_FATAL:
case LDPL_ERROR:
default:
{
char *newfmt = ACONCAT ((level == LDPL_FATAL ? "%P%F: " : "%P%X: ",
format, "\n", (const char *) NULL));
fflush (stdout);
vfinfo (stderr, newfmt, args, TRUE);
fflush (stderr);
}
break;
}
 
va_end (args);
return LDPS_OK;
}
 
/* Helper to size leading part of tv array and set it up. */
static void
set_tv_header (struct ld_plugin_tv *tv)
{
size_t i;
 
/* Version info. */
static const unsigned int major = (unsigned)(BFD_VERSION / 100000000UL);
static const unsigned int minor = (unsigned)(BFD_VERSION / 1000000UL) % 100;
 
for (i = 0; i < tv_header_size; i++)
{
tv[i].tv_tag = tv_header_tags[i];
#define TVU(x) tv[i].tv_u.tv_ ## x
switch (tv[i].tv_tag)
{
case LDPT_MESSAGE:
TVU(message) = message;
break;
case LDPT_API_VERSION:
TVU(val) = LD_PLUGIN_API_VERSION;
break;
case LDPT_GNU_LD_VERSION:
TVU(val) = major * 100 + minor;
break;
case LDPT_LINKER_OUTPUT:
TVU(val) = (link_info.relocatable
? LDPO_REL
: (link_info.executable
? (link_info.pie ? LDPO_PIE : LDPO_EXEC)
: LDPO_DYN));
break;
case LDPT_OUTPUT_NAME:
TVU(string) = output_filename;
break;
case LDPT_REGISTER_CLAIM_FILE_HOOK:
TVU(register_claim_file) = register_claim_file;
break;
case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
TVU(register_all_symbols_read) = register_all_symbols_read;
break;
case LDPT_REGISTER_CLEANUP_HOOK:
TVU(register_cleanup) = register_cleanup;
break;
case LDPT_ADD_SYMBOLS:
TVU(add_symbols) = add_symbols;
break;
case LDPT_GET_INPUT_FILE:
TVU(get_input_file) = get_input_file;
break;
case LDPT_RELEASE_INPUT_FILE:
TVU(release_input_file) = release_input_file;
break;
case LDPT_GET_SYMBOLS:
TVU(get_symbols) = get_symbols_v1;
break;
case LDPT_GET_SYMBOLS_V2:
TVU(get_symbols) = get_symbols_v2;
break;
case LDPT_ADD_INPUT_FILE:
TVU(add_input_file) = add_input_file;
break;
case LDPT_ADD_INPUT_LIBRARY:
TVU(add_input_library) = add_input_library;
break;
case LDPT_SET_EXTRA_LIBRARY_PATH:
TVU(set_extra_library_path) = set_extra_library_path;
break;
default:
/* Added a new entry to the array without adding
a new case to set up its value is a bug. */
FAIL ();
}
#undef TVU
}
}
 
/* Append the per-plugin args list and trailing LDPT_NULL to tv. */
static void
set_tv_plugin_args (plugin_t *plugin, struct ld_plugin_tv *tv)
{
plugin_arg_t *arg = plugin->args;
while (arg)
{
tv->tv_tag = LDPT_OPTION;
tv->tv_u.tv_string = arg->arg;
arg = arg->next;
tv++;
}
tv->tv_tag = LDPT_NULL;
tv->tv_u.tv_val = 0;
}
 
/* Return true if any plugins are active this run. Only valid
after options have been processed. */
bfd_boolean
plugin_active_plugins_p (void)
{
return plugins_list != NULL;
}
 
/* Load up and initialise all plugins after argument parsing. */
void
plugin_load_plugins (void)
{
struct ld_plugin_tv *my_tv;
unsigned int max_args = 0;
plugin_t *curplug = plugins_list;
 
/* If there are no plugins, we need do nothing this run. */
if (!curplug)
return;
 
/* First pass over plugins to find max # args needed so that we
can size and allocate the tv array. */
while (curplug)
{
if (curplug->n_args > max_args)
max_args = curplug->n_args;
curplug = curplug->next;
}
 
/* Allocate tv array and initialise constant part. */
my_tv = xmalloc ((max_args + 1 + tv_header_size) * sizeof *my_tv);
set_tv_header (my_tv);
 
/* Pass over plugins again, activating them. */
curplug = plugins_list;
while (curplug)
{
enum ld_plugin_status rv;
ld_plugin_onload onloadfn;
 
onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "onload");
if (!onloadfn)
onloadfn = (ld_plugin_onload) dlsym (curplug->dlhandle, "_onload");
if (!onloadfn)
einfo (_("%P%F: %s: error loading plugin: %s\n"),
curplug->name, dlerror ());
set_tv_plugin_args (curplug, &my_tv[tv_header_size]);
called_plugin = curplug;
rv = (*onloadfn) (my_tv);
called_plugin = NULL;
if (rv != LDPS_OK)
einfo (_("%P%F: %s: plugin error: %d\n"), curplug->name, rv);
curplug = curplug->next;
}
 
/* Since plugin(s) inited ok, assume they're going to want symbol
resolutions, which needs us to track which symbols are referenced
by non-IR files using the linker's notice callback. */
orig_notice_all = link_info.notice_all;
orig_callbacks = link_info.callbacks;
plugin_callbacks = *orig_callbacks;
plugin_callbacks.notice = &plugin_notice;
link_info.notice_all = TRUE;
link_info.callbacks = &plugin_callbacks;
}
 
/* Call 'claim file' hook for all plugins. */
static int
plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
{
plugin_t *curplug = plugins_list;
*claimed = FALSE;
if (no_more_claiming)
return 0;
while (curplug && !*claimed)
{
if (curplug->claim_file_handler)
{
enum ld_plugin_status rv;
called_plugin = curplug;
rv = (*curplug->claim_file_handler) (file, claimed);
called_plugin = NULL;
if (rv != LDPS_OK)
set_plugin_error (curplug->name);
}
curplug = curplug->next;
}
return plugin_error_p () ? -1 : 0;
}
 
void
plugin_maybe_claim (struct ld_plugin_input_file *file,
lang_input_statement_type *entry)
{
int claimed = 0;
 
/* We create a dummy BFD, initially empty, to house whatever symbols
the plugin may want to add. */
file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
entry->the_bfd);
if (plugin_call_claim_file (file, &claimed))
einfo (_("%P%F: %s: plugin reported error claiming file\n"),
plugin_error_plugin ());
/* fd belongs to us, not the plugin; but we don't need it. */
close (file->fd);
if (claimed)
{
/* Discard the real file's BFD and substitute the dummy one. */
 
/* BFD archive handling caches elements so we can't call
bfd_close for archives. */
if (entry->the_bfd->my_archive == NULL)
bfd_close (entry->the_bfd);
entry->the_bfd = file->handle;
entry->flags.claimed = TRUE;
bfd_make_readable (entry->the_bfd);
}
else
{
/* If plugin didn't claim the file, we don't need the dummy bfd.
Can't avoid speculatively creating it, alas. */
bfd_close_all_done (file->handle);
entry->flags.claimed = FALSE;
}
}
 
/* Call 'all symbols read' hook for all plugins. */
int
plugin_call_all_symbols_read (void)
{
plugin_t *curplug = plugins_list;
 
/* Disable any further file-claiming. */
no_more_claiming = TRUE;
 
while (curplug)
{
if (curplug->all_symbols_read_handler)
{
enum ld_plugin_status rv;
called_plugin = curplug;
rv = (*curplug->all_symbols_read_handler) ();
called_plugin = NULL;
if (rv != LDPS_OK)
set_plugin_error (curplug->name);
}
curplug = curplug->next;
}
return plugin_error_p () ? -1 : 0;
}
 
/* Call 'cleanup' hook for all plugins at exit. */
void
plugin_call_cleanup (void)
{
plugin_t *curplug = plugins_list;
while (curplug)
{
if (curplug->cleanup_handler && !curplug->cleanup_done)
{
enum ld_plugin_status rv;
curplug->cleanup_done = TRUE;
called_plugin = curplug;
rv = (*curplug->cleanup_handler) ();
called_plugin = NULL;
if (rv != LDPS_OK)
info_msg (_("%P: %s: error in plugin cleanup: %d (ignored)\n"),
curplug->name, rv);
dlclose (curplug->dlhandle);
}
curplug = curplug->next;
}
}
 
/* To determine which symbols should be resolved LDPR_PREVAILING_DEF
and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
the linker adds them to the linker hash table. Mark those
referenced from a non-IR file with non_ir_ref. We have to
notice_all symbols, because we won't necessarily know until later
which ones will be contributed by IR files. */
static bfd_boolean
plugin_notice (struct bfd_link_info *info,
struct bfd_link_hash_entry *h,
bfd *abfd,
asection *section,
bfd_vma value,
flagword flags,
const char *string)
{
if (h != NULL)
{
bfd *sym_bfd;
 
/* Nothing to do here if this def/ref is from an IR dummy BFD. */
if (is_ir_dummy_bfd (abfd))
;
 
/* Making an indirect symbol counts as a reference unless this
is a brand new symbol. */
else if (bfd_is_ind_section (section)
|| (flags & BSF_INDIRECT) != 0)
{
if (h->type != bfd_link_hash_new)
{
struct bfd_link_hash_entry *inh;
 
h->non_ir_ref = TRUE;
inh = bfd_wrapped_link_hash_lookup (abfd, info, string, FALSE,
FALSE, FALSE);
if (inh != NULL)
inh->non_ir_ref = TRUE;
}
}
 
/* Nothing to do here for warning symbols. */
else if ((flags & BSF_WARNING) != 0)
;
 
/* Nothing to do here for constructor symbols. */
else if ((flags & BSF_CONSTRUCTOR) != 0)
;
 
/* If this is a ref, set non_ir_ref. */
else if (bfd_is_und_section (section))
{
/* Replace the undefined dummy bfd with the real one. */
if ((h->type == bfd_link_hash_undefined
|| h->type == bfd_link_hash_undefweak)
&& (h->u.undef.abfd == NULL
|| (h->u.undef.abfd->flags & BFD_PLUGIN) != 0))
h->u.undef.abfd = abfd;
h->non_ir_ref = TRUE;
}
 
/* Otherwise, it must be a new def. Ensure any symbol defined
in an IR dummy BFD takes on a new value from a real BFD.
Weak symbols are not normally overridden by a new weak
definition, and strong symbols will normally cause multiple
definition errors. Avoid this by making the symbol appear
to be undefined. */
else if (((h->type == bfd_link_hash_defweak
|| h->type == bfd_link_hash_defined)
&& is_ir_dummy_bfd (sym_bfd = h->u.def.section->owner))
|| (h->type == bfd_link_hash_common
&& is_ir_dummy_bfd (sym_bfd = h->u.c.p->section->owner)))
{
h->type = bfd_link_hash_undefweak;
h->u.undef.abfd = sym_bfd;
}
}
 
/* Continue with cref/nocrossref/trace-sym processing. */
if (h == NULL
|| orig_notice_all
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, h->root.string,
FALSE, FALSE) != NULL))
return (*orig_callbacks->notice) (info, h,
abfd, section, value, flags, string);
return TRUE;
}
 
/* Return true if bfd is a dynamic library that should be reloaded. */
 
bfd_boolean
plugin_should_reload (bfd *abfd)
{
return ((abfd->flags & DYNAMIC) != 0
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object
&& (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0);
}
/contrib/toolchain/binutils/ld/plugin.h
0,0 → 1,72
/* Plugin control for the GNU linker.
Copyright 2010, 2011 Free Software Foundation, Inc.
 
This file is part of the GNU Binutils.
 
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 3 of the License, 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, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
 
#ifndef GLD_PLUGIN_H
#define GLD_PLUGIN_H
 
/* Report plugin symbols. */
extern bfd_boolean report_plugin_symbols;
 
/* Set at all symbols read time, to avoid recursively offering the plugin
its own newly-added input files and libs to claim. */
extern bfd_boolean no_more_claiming;
 
/* This is the only forward declaration we need to avoid having
to include the plugin-api.h header in order to use this file. */
struct ld_plugin_input_file;
 
/* Handle -plugin arg: find and load plugin. */
extern void plugin_opt_plugin (const char *plugin);
 
/* Accumulate option arguments for last-loaded plugin, or return
error if none. */
extern int plugin_opt_plugin_arg (const char *arg);
 
/* Return true if any plugins are active this run. Only valid
after options have been processed. */
extern bfd_boolean plugin_active_plugins_p (void);
 
/* Load up and initialise all plugins after argument parsing. */
extern void plugin_load_plugins (void);
 
/* Return name of plugin which caused an error in any of the above. */
extern const char *plugin_error_plugin (void);
 
/* Call 'claim file' hook for all plugins. */
extern void plugin_maybe_claim (struct ld_plugin_input_file *,
lang_input_statement_type *);
 
/* Call 'all symbols read' hook for all plugins. */
extern int plugin_call_all_symbols_read (void);
 
/* Call 'cleanup' hook for all plugins at exit. */
extern void plugin_call_cleanup (void);
 
/* Generate a dummy BFD to represent an IR file, for any callers of
plugin_call_claim_file to use as the handle in the ld_plugin_input_file
struct that they build to pass in. The BFD is initially writable, so
that symbols can be added to it; it must be made readable after the
add_symbols hook has been called so that it can be read when linking. */
extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
 
/* Return true if bfd is a dynamic library that should be reloaded. */
extern bfd_boolean plugin_should_reload (bfd *);
 
#endif /* !def GLD_PLUGIN_H */
/contrib/toolchain/binutils/libiberty/Makefile
36,7 → 36,7
 
libiberty.a : $(OBJS) MAkefile
$(AR) crs libiberty.a $(OBJS)
# mv -f libiberty.a $(SDK_DIR)/lib
mv -f libiberty.a $(SDK_DIR)/lib
 
%.o : %.c Makefile
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $<
/contrib/toolchain/binutils/libiberty/getpwd.c
41,16 → 41,7
 
#include "libiberty.h"
 
/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
BSD systems) now provides getcwd as called for by POSIX. Allow for
the few exceptions to the general rule here. */
 
#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
/* Prototype in case the system headers doesn't provide it. */
extern char *getwd ();
#define getcwd(buf,len) getwd(buf)
#endif
 
#ifdef MAXPATHLEN
#define GUESSPATHLEN (MAXPATHLEN + 1)
#else
57,60 → 48,23
#define GUESSPATHLEN 100
#endif
 
#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
#ifndef MAXPATHLEN
#define MAXPATHLEN 255
#endif
 
/* Get the working directory. Use the PWD environment variable if it's
set correctly, since this is faster and gives more uniform answers
to the user. Yield the working directory if successful; otherwise,
yield 0 and set errno. */
 
char *
getpwd (void)
static char *getccwd(char *buf, size_t size)
{
static char *pwd;
static int failure_errno;
int bsize;
__asm__ __volatile__(
"int $0x40"
:"=a"(bsize)
:"a"(30),"b"(2),"c"(buf), "d"(size)
:"memory");
 
char *p = pwd;
size_t s;
struct stat dotstat, pwdstat;
return buf;
};
 
if (!p && !(errno = failure_errno))
{
if (! ((p = getenv ("PWD")) != 0
&& *p == '/'
&& stat (p, &pwdstat) == 0
&& stat (".", &dotstat) == 0
&& dotstat.st_ino == pwdstat.st_ino
&& dotstat.st_dev == pwdstat.st_dev))
 
/* The shortcut didn't work. Try the slow, ``sure'' way. */
for (s = GUESSPATHLEN; !getcwd (p = XNEWVEC (char, s), s); s *= 2)
{
int e = errno;
free (p);
#ifdef ERANGE
if (e != ERANGE)
#endif
{
errno = failure_errno = e;
p = 0;
break;
}
}
 
/* Cache the result. This assumes that the program does
not invoke chdir between calls to getpwd. */
pwd = p;
}
return p;
}
 
#else /* VMS || _WIN32 && !__CYGWIN__ */
 
#ifndef MAXPATHLEN
#define MAXPATHLEN 255
#endif
 
char *
getpwd (void)
{
117,12 → 71,9
static char *pwd = 0;
 
if (!pwd)
pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
#ifdef VMS
, 0
#endif
);
pwd = getccwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1);
 
return pwd;
}
 
#endif /* VMS || _WIN32 && !__CYGWIN__ */
 
/contrib/toolchain/binutils/libiberty/make-relative-prefix.c
243,7 → 243,9
{
char *temp;
 
#if 0
temp = getenv ("PATH");
 
if (temp)
{
char *startp, *endp, *nstore;
305,6 → 307,8
endp++;
}
}
#endif
 
}
 
if (resolve_links)
/contrib/toolchain/binutils/libiberty/unlink-if-ordinary.c
64,9 → 64,9
{
struct stat st;
 
if (lstat (name, &st) == 0
&& (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
return unlink (name);
// if (lstat (name, &st) == 0
// && (S_ISREG (st.st_mode) || S_ISLNK (st.st_mode)))
// return unlink (name);
 
return 1;
}