aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:22 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:22 -0800
commit7a80622f69812ca3262d2027c07a4ed0c0242945 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src
parentee6008996aa701ad2a50d5d6b1529c9e2c2724c1 (diff)
downloadplatform_external_elfutils-7a80622f69812ca3262d2027c07a4ed0c0242945.tar.gz
platform_external_elfutils-7a80622f69812ca3262d2027c07a4ed0c0242945.tar.bz2
platform_external_elfutils-7a80622f69812ca3262d2027c07a4ed0c0242945.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog188
-rw-r--r--src/Makefile638
-rw-r--r--src/Makefile.am130
-rw-r--r--src/Makefile.in638
-rw-r--r--src/elf32-i386.script215
-rw-r--r--src/elflint.c2578
-rw-r--r--src/i386_ld.c891
-rw-r--r--src/ld.c1520
-rw-r--r--src/ld.h1073
-rw-r--r--src/ldgeneric.c6376
-rw-r--r--src/ldlex.c2663
-rw-r--r--src/ldlex.l343
-rw-r--r--src/ldscript.c2220
-rw-r--r--src/ldscript.h116
-rw-r--r--src/ldscript.y764
-rw-r--r--src/libld_elf_i386.map7
-rw-r--r--src/nm.c1302
-rw-r--r--src/none_ld.c1
-rw-r--r--src/readelf.c4541
-rw-r--r--src/sectionhash.c69
-rw-r--r--src/sectionhash.h23
-rw-r--r--src/size.c698
-rw-r--r--src/strip.c1769
-rw-r--r--src/symbolhash.c29
-rw-r--r--src/symbolhash.h24
-rw-r--r--src/unaligned.h98
-rw-r--r--src/versionhash.c28
-rw-r--r--src/versionhash.h22
-rw-r--r--src/xelf.h387
-rw-r--r--src/ylwrap154
30 files changed, 0 insertions, 29505 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
deleted file mode 100644
index e5b44049..00000000
--- a/src/ChangeLog
+++ /dev/null
@@ -1,188 +0,0 @@
-2004-09-25 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c: Make compile with gcc 4.0.
- * strip.c: Likewise.
-
-2004-08-16 Ulrich Drepper <drepper@redhat.com>
-
- * strip.c (handle_elf): Rewrite dynamic memory handling to use of
- allocate to work around gcc 3.4 bug.
-
-2004-01-25 Ulrich Drepper <drepper@redhat.com>
-
- * ldlex.l (invalid_char): Better error message.
-
-2004-01-23 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c: Print SHT_GNU_LIBLIST sections.
-
- * none_ld.c: New file.
-
-2004-01-21 Ulrich Drepper <drepper@redhat.com>
-
- * Makefile.am: Enable building of machine specific linker.
-
-2004-01-20 Ulrich Drepper <drepper@redhat.com>
-
- * Makefile.am: Support building with mudflap.
-
- * i386_ld.c: Fix warnings gcc 3.4 spits out.
- * ldgeneric.c: Likewise.
- * ldscript.y: Likewise.
- * readelf.c: Likewise.
- * strip.c: Likewise.
-
- * readelf.c (print_debug_line_section): Determine address size
- correctly.
-
-2004-01-19 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (print_phdr): Show which sections are covered by the
- PT_GNU_RELRO entry.
-
- * elflint.c (check_program_header): Check PT_GNU_RELRO entry.
-
- * readelf.c (print_debug_macinfo_section): Implement.
-
-2004-01-18 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (print_debug_line_section): Implement.
-
-2004-01-17 Ulrich Drepper <drepper@redhat.com>
-
- * src/elflint.c: Use PACKAGE_NAME instead of PACKAGE.
- * src/ld.c: Likewise.
- * src/nm.c: Likewise.
- * src/readelf.c: Likewise.
- * src/size.c: Likewise.
- * src/strip.c: Likewise.
-
- * strip.c: Add a few more unlikely. Reduce scope of some variables.
-
- * Makefile.am: Support building with mudflap.
-
-2004-01-16 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (print_debug_info_section): Free dies memory.
-
- * readelf.c: Print .debug_info section content.
-
-2004-01-13 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (print_shdr): Add support for SHF_ORDERED and SHF_EXCLUDE.
-
-2004-01-12 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (print_debug_aranges): Implement using libdw.
-
-2004-01-11 Ulrich Drepper <drepper@redhat.com>
-
- * nm.c: Adjust for Dwarf_Files type and dwarf_lineno interface change.
-
- * readelf.c: Use libdw instead of libdwarf. Not all of the old
- behavior is available yet.
- * Makefile.am: Link readelf with libdw. Remove libdwarf include path.
-
-2004-01-09 Ulrich Drepper <drepper@redhat.com>
-
- * nm.c (get_local_names): Adjust call to dwarf_nextcu.
-
- * nm.c: Implement getting information about local variables.
-
-2004-01-07 Ulrich Drepper <drepper@redhat.com>
-
- * nm.c: Read also debug information for local symbols.
-
-2004-01-05 Ulrich Drepper <drepper@redhat.com>
-
- * nm.c: Shuffle dwarf handling code around so the maximum column
- width can be computed ahead of printing. Avoid collection symbols
- which are not printed anyway.
-
- * nm.c: Rewrite dwarf handling to use libdw.
- * Makefile.am (AM_CFLAGS): Add -std parameter.
- (INCLUDES): Find header in libdw subdir.
- (nm_LDADD): Replace libdwarf with libdw.
-
- * elflint.c: Update copyright year.
- * readelf.c: Likewise.
- * size.c: Likewise.
- * strip.c: Likewise.
- * nm.c: Likewise.
-
-2003-12-31 Ulrich Drepper <drepper@redhat.com>
-
- * strip.c (process_file): Close file before returning.
-
-2003-11-19 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (handle_dynamic): Make column for tag name wider.
-
-2003-09-29 Ulrich Drepper <drepper@redhat.com>
-
- * readelf.c (handle_dynamic): Always terminate tag name with a space.
-
-2003-09-25 Ulrich Drepper <drepper@redhat.com>
-
- * strip.c (process_file): Don't mmap the input file, we modify the
- data structures and don't want the change end up on disk.
-
-2003-09-23 Jakub Jelinek <jakub@redhat.com>
-
- * unaligned.h (union u_2ubyte_unaligned,
- union u_4ubyte_unaligned, union u_8ubyte_unaligned): Add
- packed attribute.
- (add_2ubyte_unaligned, add_4ubyte_unaligned,
- add_8ubyte_unaligned): Avoid nesting bswap_NN macros.
- Read/store value through _ptr->u instead of *_ptr.
-
-2003-09-22 Ulrich Drepper <drepper@redhat.com>
-
- * size.c (show_sysv): Change type of maxlen to int.
-
- * strip.c (handle_elf): Handle the 64-bit archs which is 64-bit
- buckets.
-
- * i386_ld.c: Many many fixes and extensions.
- * ld.c: Likewise.
- * ldgeneric.c: Likewise.
-
-2003-08-16 Ulrich Drepper <drepper@redhat.com>
-
- * ldgeneric.c (check_definition): Don't add symbol on dso_list if
- the reference is from another DSO.
-
-2003-08-15 Ulrich Drepper <drepper@redhat.com>
-
- * ldgeneric.c (find_entry_point): It is no fatal error if no entry
- point is found when creating a DSO.
-
-2003-08-14 Ulrich Drepper <drepper@redhat.com>
-
- * ld.c (main): Always call FLAG_UNRESOLVED.
- * ldgeneric.c (ld_generic_flag_unresolved): Only complain about
- undefined symbols if not creating DSO or ld_state.nodefs is not set.
-
-2003-08-13 Ulrich Drepper <drepper@redhat.com>
-
- * Makefile.in: Depend on libebl.a, not libebl.so.
-
- * ld.c (main): Mark stream for linker script as locked by caller.
- (read_version_script): Likewise.
- * ldlex.c: Define fread and fwrite to _unlocked variant.
-
- * i386_ld.c (elf_i386_finalize_plt): Replace #ifdefs with uses of
- target_bswap_32.
- * unaligned.h: Define target_bswap_16, target_bswap_32, and
- target_bswap_64.
- (store_2ubyte_unaligned, store_4ubyte_unaligned,
- store_8ubyte_unaligned): Define using new macros.
-
-2003-08-12 Ulrich Drepper <drepper@redhat.com>
-
- * i386_ld.c (elf_i386_finalize_plt): Use packed structs to access
- possibly unaligned memory. Support use of big endian machines.
-
-2003-08-11 Ulrich Drepper <drepper@redhat.com>
-
- * Moved to CVS archive.
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index f147eee2..00000000
--- a/src/Makefile
+++ /dev/null
@@ -1,638 +0,0 @@
-# Makefile.in generated by automake 1.9.2 from Makefile.am.
-# src/Makefile. Generated from Makefile.in by configure.
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-
-
-
-
-SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c readelf.c size.c strip.c
-
-srcdir = .
-top_srcdir = ..
-
-pkgdatadir = $(datadir)/elfutils
-pkglibdir = $(libdir)/elfutils
-pkgincludedir = $(includedir)/elfutils
-top_builddir = ..
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-INSTALL = /usr/bin/install -c
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = i686-pc-linux-gnu
-host_triplet = i686-pc-linux-gnu
-bin_PROGRAMS = readelf$(EXEEXT) nm$(EXEEXT) size$(EXEEXT) \
- strip$(EXEEXT) ld$(EXEEXT) elflint$(EXEEXT)
-noinst_PROGRAMS = $(am__EXEEXT_1)
-#am__append_1 = libld_elf.a
-subdir = src
-DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in ChangeLog ldlex.c ldscript.c ylwrap
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
- $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
- $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
- $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-LIBRARIES = $(noinst_LIBRARIES)
-AR = ar
-ARFLAGS = cru
-libld_elf_a_AR = $(AR) $(ARFLAGS)
-libld_elf_a_LIBADD =
-am_libld_elf_a_OBJECTS = $(base_cpu)_ld.$(OBJEXT)
-libld_elf_a_OBJECTS = $(am_libld_elf_a_OBJECTS)
-libld_elf_i386_pic_a_AR = $(AR) $(ARFLAGS)
-libld_elf_i386_pic_a_LIBADD =
-libld_elf_i386_pic_a_OBJECTS = $(am_libld_elf_i386_pic_a_OBJECTS)
-am__installdirs = "$(DESTDIR)$(bindir)"
-binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-am__EXEEXT_1 = libld_elf_i386.so$(EXEEXT)
-PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
-elflint_SOURCES = elflint.c
-elflint_OBJECTS = elflint.$(OBJEXT)
-am__DEPENDENCIES_1 = ../libebl/libebl.a
-am__DEPENDENCIES_2 = ../libelf/libelf.so
-#am__DEPENDENCIES_2 = ../libelf/libelf.a
-am__DEPENDENCIES_3 = ../lib/libeu.a
-elflint_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3)
-am_ld_OBJECTS = ld.$(OBJEXT) ldgeneric.$(OBJEXT) ldlex.$(OBJEXT) \
- ldscript.$(OBJEXT) symbolhash.$(OBJEXT) sectionhash.$(OBJEXT) \
- versionhash.$(OBJEXT)
-ld_OBJECTS = $(am_ld_OBJECTS)
-#am__DEPENDENCIES_4 = libld_elf.a
-ld_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_libld_elf_i386_so_OBJECTS =
-libld_elf_i386_so_OBJECTS = $(am_libld_elf_i386_so_OBJECTS)
-libld_elf_i386_so_LDADD = $(LDADD)
-nm_SOURCES = nm.c
-nm_OBJECTS = nm.$(OBJEXT)
-am__DEPENDENCIES_5 = ../libdw/libdw.so
-#am__DEPENDENCIES_5 = ../libdw/libdw.a
-nm_DEPENDENCIES = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-readelf_SOURCES = readelf.c
-readelf_OBJECTS = readelf.$(OBJEXT)
-readelf_DEPENDENCIES = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-size_SOURCES = size.c
-size_OBJECTS = size.$(OBJEXT)
-size_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-strip_SOURCES = strip.c
-strip_OBJECTS = strip.$(OBJEXT)
-strip_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3)
-DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/config/depcomp
-am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
-YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
-SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \
- elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c \
- readelf.c size.c strip.c
-DIST_SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \
- elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c \
- readelf.c size.c strip.c
-HEADERS = $(noinst_HEADERS)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run aclocal-1.9
-AMDEP_FALSE = #
-AMDEP_TRUE =
-AMTAR = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run tar
-AUTOCONF = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run autoconf
-AUTOHEADER = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run autoheader
-AUTOMAKE = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run automake-1.9
-AWK = gawk
-CC = gcc
-CCDEPMODE = depmode=gcc3
-CFLAGS = -g -O2
-CPP = gcc -E
-CPPFLAGS =
-CYGPATH_W = echo
-DATADIRNAME = ${prefix}/share
-DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H $(YYDEBUG) \
- -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\"
-
-DEPDIR = .deps
-ECHO_C =
-ECHO_N = -n
-ECHO_T =
-EGREP = grep -E
-EXEEXT =
-GMSGFMT = /usr/bin/msgfmt
-INSTALL_DATA = ${INSTALL} -m 644
-INSTALL_PROGRAM = ${INSTALL}
-INSTALL_SCRIPT = ${INSTALL}
-INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
-INTLLIBS =
-LDFLAGS =
-LEX = flex
-LEXLIB = -lfl
-LEX_OUTPUT_ROOT = lex.yy
-LIBICONV = -liconv
-LIBINTL =
-LIBOBJS =
-LIBS =
-LOCALEDIR = ${prefix}/share
-LTLIBICONV = -liconv
-LTLIBINTL =
-LTLIBOBJS =
-MAKEINFO = ${SHELL} /work/elfutils/stock/elfutils-0.97/config/missing --run makeinfo
-MKINSTALLDIRS = config/mkinstalldirs
-MSGFMT = /usr/bin/msgfmt
-MSGMERGE = /usr/bin/msgmerge
-MUDFLAP_FALSE =
-MUDFLAP_TRUE = #
-NATIVE_LD_FALSE =
-NATIVE_LD_TRUE = #
-OBJEXT = o
-PACKAGE = elfutils
-PACKAGE_BUGREPORT = http://bugzilla.redhat.com/bugzilla/
-PACKAGE_NAME = Red Hat elfutils
-PACKAGE_STRING = Red Hat elfutils 0.97
-PACKAGE_TARNAME = elfutils
-PACKAGE_VERSION = 0.97
-PATH_SEPARATOR = :
-POSUB = po
-RANLIB = ranlib
-SET_MAKE =
-SHELL = /bin/sh
-STRIP =
-USE_NLS = yes
-VERSION = 0.97
-XGETTEXT = /usr/bin/xgettext
-YACC = bison -y -d
-ac_ct_CC = gcc
-ac_ct_RANLIB = ranlib
-ac_ct_STRIP =
-am__fastdepCC_FALSE = #
-am__fastdepCC_TRUE =
-am__include = include
-am__leading_dot = .
-am__quote =
-am__tar = ${AMTAR} chof - "$$tardir"
-am__untar = ${AMTAR} xf -
-base_cpu = none
-bindir = ${exec_prefix}/bin
-build = i686-pc-linux-gnu
-build_alias =
-build_cpu = i686
-build_os = linux-gnu
-build_vendor = pc
-datadir = ${prefix}/share
-exec_prefix = ${prefix}
-host = i686-pc-linux-gnu
-host_alias =
-host_cpu = i686
-host_os = linux-gnu
-host_vendor = pc
-includedir = ${prefix}/include
-infodir = ${prefix}/info
-install_sh = /work/elfutils/stock/elfutils-0.97/config/install-sh
-libdir = ${exec_prefix}/lib
-libexecdir = ${exec_prefix}/libexec
-localstatedir = ${prefix}/var
-mandir = ${prefix}/man
-mkdir_p = mkdir -p --
-oldincludedir = /usr/include
-prefix = /work/elfutils/google/linux-install-elfutils-0.97/
-program_transform_name = s,x,x,
-sbindir = ${exec_prefix}/sbin
-sharedstatedir = ${prefix}/com
-sysconfdir = ${prefix}/etc
-target_alias =
-AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
- $(if $($(*F)_no_Werror),,-Werror) $(native_ld_cflags)
-
-#AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
-# $(native_ld_cflags)
-
-#AM_LDFLAGS = -fmudflap
-INCLUDES = -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl -I$(srcdir)/../lib -I$(srcdir)/../libdw -I..
-AM_YFLAGS = -pld
-AM_LFLAGS = -Pld -olex.yy.c
-native_ld = @native_ld@
-ld_dsos = libld_elf_i386_pic.a
-noinst_LIBRARIES = libld_elf.a $(ld_dsos)
-#noinst_LIBRARIES = libld_elf.a
-#native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu)
-ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \
- versionhash.c
-
-noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \
- ldscript.h xelf.h unaligned.h
-
-EXTRA_DIST = elf32-i386.script libld_elf_i386.map $(ld_modules)
-ld_modules = i386_ld.c
-libdw = ../libdw/libdw.so
-#libdw = ../libdw/libdw.a
-libelf = ../libelf/libelf.so
-#libelf = ../libelf/libelf.a
-libebl = ../libebl/libebl.a
-libeu = ../lib/libeu.a
-readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-size_LDADD = $(libelf) $(libeu)
-strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl $(am__append_1)
-ld_LDFLAGS = -rdynamic
-elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-ldlex_no_Werror = yes
-
-# Machine-specific linker code.
-libld_elf_a_SOURCES = $(base_cpu)_ld.c
-libld_elf_i386_pic_a_SOURCES =
-am_libld_elf_i386_pic_a_OBJECTS = i386_ld.os
-libld_elf_i386_so_SOURCES =
-CLEANFILES = none_ld.os $(ld_modules:.c=.os)
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .l .o .obj .y
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnits src/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-clean-noinstLIBRARIES:
- -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libld_elf.a: $(libld_elf_a_OBJECTS) $(libld_elf_a_DEPENDENCIES)
- -rm -f libld_elf.a
- $(libld_elf_a_AR) libld_elf.a $(libld_elf_a_OBJECTS) $(libld_elf_a_LIBADD)
- $(RANLIB) libld_elf.a
-libld_elf_i386_pic.a: $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_DEPENDENCIES)
- -rm -f libld_elf_i386_pic.a
- $(libld_elf_i386_pic_a_AR) libld_elf_i386_pic.a $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_LIBADD)
- $(RANLIB) libld_elf_i386_pic.a
-install-binPROGRAMS: $(bin_PROGRAMS)
- @$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
- else :; fi; \
- done
-
-uninstall-binPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
- rm -f "$(DESTDIR)$(bindir)/$$f"; \
- done
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-clean-noinstPROGRAMS:
- -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
-elflint$(EXEEXT): $(elflint_OBJECTS) $(elflint_DEPENDENCIES)
- @rm -f elflint$(EXEEXT)
- $(LINK) $(elflint_LDFLAGS) $(elflint_OBJECTS) $(elflint_LDADD) $(LIBS)
-ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES)
- @rm -f ld$(EXEEXT)
- $(LINK) $(ld_LDFLAGS) $(ld_OBJECTS) $(ld_LDADD) $(LIBS)
-nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES)
- @rm -f nm$(EXEEXT)
- $(LINK) $(nm_LDFLAGS) $(nm_OBJECTS) $(nm_LDADD) $(LIBS)
-readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES)
- @rm -f readelf$(EXEEXT)
- $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS)
-size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES)
- @rm -f size$(EXEEXT)
- $(LINK) $(size_LDFLAGS) $(size_OBJECTS) $(size_LDADD) $(LIBS)
-strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES)
- @rm -f strip$(EXEEXT)
- $(LINK) $(strip_LDFLAGS) $(strip_OBJECTS) $(strip_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-include ./$(DEPDIR)/$(base_cpu)_ld.Po
-include ./$(DEPDIR)/elflint.Po
-include ./$(DEPDIR)/ld.Po
-include ./$(DEPDIR)/ldgeneric.Po
-include ./$(DEPDIR)/ldlex.Po
-include ./$(DEPDIR)/ldscript.Po
-include ./$(DEPDIR)/nm.Po
-include ./$(DEPDIR)/readelf.Po
-include ./$(DEPDIR)/sectionhash.Po
-include ./$(DEPDIR)/size.Po
-include ./$(DEPDIR)/strip.Po
-include ./$(DEPDIR)/symbolhash.Po
-include ./$(DEPDIR)/versionhash.Po
-
-.c.o:
- if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
- then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
-# source='$<' object='$@' libtool=no \
-# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
-# $(COMPILE) -c $<
-
-.c.obj:
- if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
- then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
-# source='$<' object='$@' libtool=no \
-# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
-# $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.l.c:
- $(LEXCOMPILE) $<
- sed '/^#/ s|$(LEX_OUTPUT_ROOT)\.c|$@|' $(LEX_OUTPUT_ROOT).c >$@
- rm -f $(LEX_OUTPUT_ROOT).c
-
-.y.c:
- $(YACCCOMPILE) $<
- if test -f y.tab.h; then \
- to=`echo "$*_H" | sed \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
- -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`; \
- sed -e "/^#/!b" -e "s/Y_TAB_H/$$to/g" -e "s|y\.tab\.h|$*.h|" \
- y.tab.h >$*.ht; \
- rm -f y.tab.h; \
- if cmp -s $*.ht $*.h; then \
- rm -f $*.ht ;\
- else \
- mv $*.ht $*.h; \
- fi; \
- fi
- if test -f y.output; then \
- mv y.output $*.output; \
- fi
- sed '/^#/ s|y\.tab\.c|$@|' y.tab.c >$@t && mv $@t $@
- rm -f y.tab.c
-uninstall-info-am:
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
- fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
- list='$(DISTFILES)'; for file in $$list; do \
- case $$file in \
- $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
- $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
- esac; \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test "$$dir" != "$$file" && test "$$dir" != "."; then \
- dir="/$$dir"; \
- $(mkdir_p) "$(distdir)$$dir"; \
- else \
- dir=''; \
- fi; \
- if test -d $$d/$$file; then \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
-installdirs:
- for dir in "$(DESTDIR)$(bindir)"; do \
- test -z "$$dir" || $(mkdir_p) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
- -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
- -rm -f ldlex.c
- -rm -f ldscript.c
-clean: clean-am
-
-clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \
- clean-noinstPROGRAMS mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-exec-am: install-binPROGRAMS
-
-install-info: install-info-am
-
-install-man:
-
-installcheck-am: installcheck-binPROGRAMS
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-binPROGRAMS uninstall-info-am
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
- clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \
- distclean distclean-compile distclean-generic distclean-tags \
- distdir dvi dvi-am html html-am info info-am install \
- install-am install-binPROGRAMS install-data install-data-am \
- install-exec install-exec-am install-info install-info-am \
- install-man install-strip installcheck installcheck-am \
- installcheck-binPROGRAMS installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
- uninstall-am uninstall-binPROGRAMS uninstall-info-am
-
-
-ldlex.o: ldscript.c
-ldscript.h: ldscript.c
-libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map
- $(CC) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
- $(libelf) $(libeu) \
- -Wl,--version-script,$(srcdir)/libld_elf_i386.map
-
-%.os: %.c %.o
- if $(filter-out -fmudflap,$(COMPILE)) -c -o $@ -fpic -DPIC -DSHARED \
- -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
- `test -f '$<' || echo '$(srcdir)/'`$<; \
- then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
- rm -f "$(DEPDIR)/$*.Tpo"; \
- else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
- fi
-
-# Special rule to make it possible to define libld_elf_a_SOURCES as we do.
-# Otherwise make would complain.
-.deps/none_ld.Po: none_ld.os
- -:
-
-installcheck-binPROGRAMS: $(bin_PROGRAMS)
- bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
- case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
- *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
- esac; \
- f=`echo "$$p" | \
- sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- for opt in --help --version; do \
- if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
- $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
- && test -n "`cat c$${pid}_.out`" \
- && test -z "`cat c$${pid}_.err`"; then :; \
- else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
- done; \
- done; rm -f c$${pid}_.???; exit $$bad
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 7b957eb5..00000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,130 +0,0 @@
-## Process this file with automake to create Makefile.in
-## Configure input file for elfutils.
-##
-## Copyright (C) 1996-2002, 2003, 2004 Red Hat, Inc.
-##
-## This program is Open Source software; you can redistribute it and/or
-## modify it under the terms of the Open Software License version 1.0 as
-## published by the Open Source Initiative.
-##
-## You should have received a copy of the Open Software License along
-## with this program; if not, you may obtain a copy of the Open Software
-## License version 1.0 from http://www.opensource.org/licenses/osl.php or
-## by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
-## 3001 King Ranch Road, Ukiah, CA 95482.
-##
-DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H $(YYDEBUG) \
- -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\"
-if MUDFLAP
-AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
- $(native_ld_cflags)
-else
-AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
- $(if $($(*F)_no_Werror),,-Werror) $(native_ld_cflags)
-endif
-if MUDFLAP
-AM_LDFLAGS = -fmudflap
-endif
-INCLUDES = -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl -I$(srcdir)/../lib -I$(srcdir)/../libdw -I..
-
-YACC = @YACC@ -d
-AM_YFLAGS = -pld
-AM_LFLAGS = -Pld -olex.yy.c
-## Uncomment to enable debugging of linker script parser
-##YYDEBUG = -DYYDEBUG=1
-
-native_ld = @native_ld@
-base_cpu = @base_cpu@
-
-bin_PROGRAMS = readelf nm size strip ld elflint
-
-
-ld_dsos = libld_elf_i386_pic.a
-if NATIVE_LD
-noinst_LIBRARIES = libld_elf.a
-native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu)
-else
-noinst_LIBRARIES = libld_elf.a $(ld_dsos)
-noinst_PROGRAMS = $(ld_dsos:_pic.a=.so)
-endif
-
-
-ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \
- versionhash.c
-
-noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \
- ldscript.h xelf.h unaligned.h
-
-EXTRA_DIST = elf32-i386.script libld_elf_i386.map $(ld_modules)
-ld_modules = i386_ld.c
-
-if MUDFLAP
-libdw = ../libdw/libdw.a
-libelf = ../libelf/libelf.a
-else
-libdw = ../libdw/libdw.so
-libelf = ../libelf/libelf.so
-endif
-libebl = ../libebl/libebl.a
-libeu = ../lib/libeu.a
-
-readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-size_LDADD = $(libelf) $(libeu)
-strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-if NATIVE_LD
-ld_LDADD += libld_elf.a
-endif
-ld_LDFLAGS = -rdynamic
-elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-
-ldlex.o: ldscript.c
-ldlex_no_Werror = yes
-ldscript.h: ldscript.c
-
-# Machine-specific linker code.
-libld_elf_a_SOURCES = $(base_cpu)_ld.c
-
-libld_elf_i386_pic_a_SOURCES =
-am_libld_elf_i386_pic_a_OBJECTS = i386_ld.os
-
-libld_elf_i386_so_SOURCES =
-libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map
- $(CC) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
- $(libelf) $(libeu) \
- -Wl,--version-script,$(srcdir)/libld_elf_i386.map
-
-
-%.os: %.c %.o
- if $(filter-out -fmudflap,$(COMPILE)) -c -o $@ -fpic -DPIC -DSHARED \
- -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
- `test -f '$<' || echo '$(srcdir)/'`$<; \
- then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
- rm -f "$(DEPDIR)/$*.Tpo"; \
- else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
- fi
-
-# Special rule to make it possible to define libld_elf_a_SOURCES as we do.
-# Otherwise make would complain.
-.deps/none_ld.Po: none_ld.os
- -:
-
-
-installcheck-binPROGRAMS: $(bin_PROGRAMS)
- bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
- case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
- *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
- esac; \
- f=`echo "$$p" | \
- sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- for opt in --help --version; do \
- if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
- $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
- && test -n "`cat c$${pid}_.out`" \
- && test -z "`cat c$${pid}_.err`"; then :; \
- else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
- done; \
- done; rm -f c$${pid}_.???; exit $$bad
-
-CLEANFILES = none_ld.os $(ld_modules:.c=.os)
diff --git a/src/Makefile.in b/src/Makefile.in
deleted file mode 100644
index 0eb72237..00000000
--- a/src/Makefile.in
+++ /dev/null
@@ -1,638 +0,0 @@
-# Makefile.in generated by automake 1.9.2 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-
-
-SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c readelf.c size.c strip.c
-
-srcdir = @srcdir@
-top_srcdir = @top_srcdir@
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-top_builddir = ..
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-INSTALL = @INSTALL@
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-build_triplet = @build@
-host_triplet = @host@
-bin_PROGRAMS = readelf$(EXEEXT) nm$(EXEEXT) size$(EXEEXT) \
- strip$(EXEEXT) ld$(EXEEXT) elflint$(EXEEXT)
-@NATIVE_LD_FALSE@noinst_PROGRAMS = $(am__EXEEXT_1)
-@NATIVE_LD_TRUE@am__append_1 = libld_elf.a
-subdir = src
-DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in ChangeLog ldlex.c ldscript.c ylwrap
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
- $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/lib-ld.m4 \
- $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
- $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES =
-LIBRARIES = $(noinst_LIBRARIES)
-AR = ar
-ARFLAGS = cru
-libld_elf_a_AR = $(AR) $(ARFLAGS)
-libld_elf_a_LIBADD =
-am_libld_elf_a_OBJECTS = $(base_cpu)_ld.$(OBJEXT)
-libld_elf_a_OBJECTS = $(am_libld_elf_a_OBJECTS)
-libld_elf_i386_pic_a_AR = $(AR) $(ARFLAGS)
-libld_elf_i386_pic_a_LIBADD =
-libld_elf_i386_pic_a_OBJECTS = $(am_libld_elf_i386_pic_a_OBJECTS)
-am__installdirs = "$(DESTDIR)$(bindir)"
-binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-am__EXEEXT_1 = libld_elf_i386.so$(EXEEXT)
-PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
-elflint_SOURCES = elflint.c
-elflint_OBJECTS = elflint.$(OBJEXT)
-am__DEPENDENCIES_1 = ../libebl/libebl.a
-@MUDFLAP_FALSE@am__DEPENDENCIES_2 = ../libelf/libelf.so
-@MUDFLAP_TRUE@am__DEPENDENCIES_2 = ../libelf/libelf.a
-am__DEPENDENCIES_3 = ../lib/libeu.a
-elflint_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3)
-am_ld_OBJECTS = ld.$(OBJEXT) ldgeneric.$(OBJEXT) ldlex.$(OBJEXT) \
- ldscript.$(OBJEXT) symbolhash.$(OBJEXT) sectionhash.$(OBJEXT) \
- versionhash.$(OBJEXT)
-ld_OBJECTS = $(am_ld_OBJECTS)
-@NATIVE_LD_TRUE@am__DEPENDENCIES_4 = libld_elf.a
-ld_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_libld_elf_i386_so_OBJECTS =
-libld_elf_i386_so_OBJECTS = $(am_libld_elf_i386_so_OBJECTS)
-libld_elf_i386_so_LDADD = $(LDADD)
-nm_SOURCES = nm.c
-nm_OBJECTS = nm.$(OBJEXT)
-@MUDFLAP_FALSE@am__DEPENDENCIES_5 = ../libdw/libdw.so
-@MUDFLAP_TRUE@am__DEPENDENCIES_5 = ../libdw/libdw.a
-nm_DEPENDENCIES = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-readelf_SOURCES = readelf.c
-readelf_OBJECTS = readelf.$(OBJEXT)
-readelf_DEPENDENCIES = $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-size_SOURCES = size.c
-size_OBJECTS = size.$(OBJEXT)
-size_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_3)
-strip_SOURCES = strip.c
-strip_OBJECTS = strip.$(OBJEXT)
-strip_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_3)
-DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
-depcomp = $(SHELL) $(top_srcdir)/config/depcomp
-am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
-YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
-SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \
- elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c \
- readelf.c size.c strip.c
-DIST_SOURCES = $(libld_elf_a_SOURCES) $(libld_elf_i386_pic_a_SOURCES) \
- elflint.c $(ld_SOURCES) $(libld_elf_i386_so_SOURCES) nm.c \
- readelf.c size.c strip.c
-HEADERS = $(noinst_HEADERS)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMDEP_FALSE = @AMDEP_FALSE@
-AMDEP_TRUE = @AMDEP_TRUE@
-AMTAR = @AMTAR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CYGPATH_W = @CYGPATH_W@
-DATADIRNAME = @DATADIRNAME@
-DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H $(YYDEBUG) \
- -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\"
-
-DEPDIR = @DEPDIR@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-GMSGFMT = @GMSGFMT@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-INTLLIBS = @INTLLIBS@
-LDFLAGS = @LDFLAGS@
-LEX = @LEX@
-LEXLIB = @LEXLIB@
-LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
-LIBICONV = @LIBICONV@
-LIBINTL = @LIBINTL@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LOCALEDIR = @LOCALEDIR@
-LTLIBICONV = @LTLIBICONV@
-LTLIBINTL = @LTLIBINTL@
-LTLIBOBJS = @LTLIBOBJS@
-MAKEINFO = @MAKEINFO@
-MKINSTALLDIRS = @MKINSTALLDIRS@
-MSGFMT = @MSGFMT@
-MSGMERGE = @MSGMERGE@
-MUDFLAP_FALSE = @MUDFLAP_FALSE@
-MUDFLAP_TRUE = @MUDFLAP_TRUE@
-NATIVE_LD_FALSE = @NATIVE_LD_FALSE@
-NATIVE_LD_TRUE = @NATIVE_LD_TRUE@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-POSUB = @POSUB@
-RANLIB = @RANLIB@
-SET_MAKE = @SET_MAKE@
-SHELL = @SHELL@
-STRIP = @STRIP@
-USE_NLS = @USE_NLS@
-VERSION = @VERSION@
-XGETTEXT = @XGETTEXT@
-YACC = @YACC@ -d
-ac_ct_CC = @ac_ct_CC@
-ac_ct_RANLIB = @ac_ct_RANLIB@
-ac_ct_STRIP = @ac_ct_STRIP@
-am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
-am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-base_cpu = @base_cpu@
-bindir = @bindir@
-build = @build@
-build_alias = @build_alias@
-build_cpu = @build_cpu@
-build_os = @build_os@
-build_vendor = @build_vendor@
-datadir = @datadir@
-exec_prefix = @exec_prefix@
-host = @host@
-host_alias = @host_alias@
-host_cpu = @host_cpu@
-host_os = @host_os@
-host_vendor = @host_vendor@
-includedir = @includedir@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-@MUDFLAP_FALSE@AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
-@MUDFLAP_FALSE@ $(if $($(*F)_no_Werror),,-Werror) $(native_ld_cflags)
-
-@MUDFLAP_TRUE@AM_CFLAGS = -Wall -Wshadow -std=gnu99 \
-@MUDFLAP_TRUE@ $(native_ld_cflags)
-
-@MUDFLAP_TRUE@AM_LDFLAGS = -fmudflap
-INCLUDES = -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl -I$(srcdir)/../lib -I$(srcdir)/../libdw -I..
-AM_YFLAGS = -pld
-AM_LFLAGS = -Pld -olex.yy.c
-native_ld = @native_ld@
-ld_dsos = libld_elf_i386_pic.a
-@NATIVE_LD_FALSE@noinst_LIBRARIES = libld_elf.a $(ld_dsos)
-@NATIVE_LD_TRUE@noinst_LIBRARIES = libld_elf.a
-@NATIVE_LD_TRUE@native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu)
-ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \
- versionhash.c
-
-noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \
- ldscript.h xelf.h unaligned.h
-
-EXTRA_DIST = elf32-i386.script libld_elf_i386.map $(ld_modules)
-ld_modules = i386_ld.c
-@MUDFLAP_FALSE@libdw = ../libdw/libdw.so
-@MUDFLAP_TRUE@libdw = ../libdw/libdw.a
-@MUDFLAP_FALSE@libelf = ../libelf/libelf.so
-@MUDFLAP_TRUE@libelf = ../libelf/libelf.a
-libebl = ../libebl/libebl.a
-libeu = ../lib/libeu.a
-readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) -ldl
-size_LDADD = $(libelf) $(libeu)
-strip_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-ld_LDADD = $(libebl) $(libelf) $(libeu) -ldl $(am__append_1)
-ld_LDFLAGS = -rdynamic
-elflint_LDADD = $(libebl) $(libelf) $(libeu) -ldl
-ldlex_no_Werror = yes
-
-# Machine-specific linker code.
-libld_elf_a_SOURCES = $(base_cpu)_ld.c
-libld_elf_i386_pic_a_SOURCES =
-am_libld_elf_i386_pic_a_OBJECTS = i386_ld.os
-libld_elf_i386_so_SOURCES =
-CLEANFILES = none_ld.os $(ld_modules:.c=.os)
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .l .o .obj .y
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnits src/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-clean-noinstLIBRARIES:
- -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
-libld_elf.a: $(libld_elf_a_OBJECTS) $(libld_elf_a_DEPENDENCIES)
- -rm -f libld_elf.a
- $(libld_elf_a_AR) libld_elf.a $(libld_elf_a_OBJECTS) $(libld_elf_a_LIBADD)
- $(RANLIB) libld_elf.a
-libld_elf_i386_pic.a: $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_DEPENDENCIES)
- -rm -f libld_elf_i386_pic.a
- $(libld_elf_i386_pic_a_AR) libld_elf_i386_pic.a $(libld_elf_i386_pic_a_OBJECTS) $(libld_elf_i386_pic_a_LIBADD)
- $(RANLIB) libld_elf_i386_pic.a
-install-binPROGRAMS: $(bin_PROGRAMS)
- @$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
- else :; fi; \
- done
-
-uninstall-binPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
- rm -f "$(DESTDIR)$(bindir)/$$f"; \
- done
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-
-clean-noinstPROGRAMS:
- -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
-elflint$(EXEEXT): $(elflint_OBJECTS) $(elflint_DEPENDENCIES)
- @rm -f elflint$(EXEEXT)
- $(LINK) $(elflint_LDFLAGS) $(elflint_OBJECTS) $(elflint_LDADD) $(LIBS)
-ld$(EXEEXT): $(ld_OBJECTS) $(ld_DEPENDENCIES)
- @rm -f ld$(EXEEXT)
- $(LINK) $(ld_LDFLAGS) $(ld_OBJECTS) $(ld_LDADD) $(LIBS)
-nm$(EXEEXT): $(nm_OBJECTS) $(nm_DEPENDENCIES)
- @rm -f nm$(EXEEXT)
- $(LINK) $(nm_LDFLAGS) $(nm_OBJECTS) $(nm_LDADD) $(LIBS)
-readelf$(EXEEXT): $(readelf_OBJECTS) $(readelf_DEPENDENCIES)
- @rm -f readelf$(EXEEXT)
- $(LINK) $(readelf_LDFLAGS) $(readelf_OBJECTS) $(readelf_LDADD) $(LIBS)
-size$(EXEEXT): $(size_OBJECTS) $(size_DEPENDENCIES)
- @rm -f size$(EXEEXT)
- $(LINK) $(size_LDFLAGS) $(size_OBJECTS) $(size_LDADD) $(LIBS)
-strip$(EXEEXT): $(strip_OBJECTS) $(strip_DEPENDENCIES)
- @rm -f strip$(EXEEXT)
- $(LINK) $(strip_LDFLAGS) $(strip_OBJECTS) $(strip_LDADD) $(LIBS)
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/$(base_cpu)_ld.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elflint.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ld.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldgeneric.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldlex.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldscript.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readelf.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sectionhash.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/size.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strip.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symbolhash.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/versionhash.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.l.c:
- $(LEXCOMPILE) $<
- sed '/^#/ s|$(LEX_OUTPUT_ROOT)\.c|$@|' $(LEX_OUTPUT_ROOT).c >$@
- rm -f $(LEX_OUTPUT_ROOT).c
-
-.y.c:
- $(YACCCOMPILE) $<
- if test -f y.tab.h; then \
- to=`echo "$*_H" | sed \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
- -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`; \
- sed -e "/^#/!b" -e "s/Y_TAB_H/$$to/g" -e "s|y\.tab\.h|$*.h|" \
- y.tab.h >$*.ht; \
- rm -f y.tab.h; \
- if cmp -s $*.ht $*.h; then \
- rm -f $*.ht ;\
- else \
- mv $*.ht $*.h; \
- fi; \
- fi
- if test -f y.output; then \
- mv y.output $*.output; \
- fi
- sed '/^#/ s|y\.tab\.c|$@|' y.tab.c >$@t && mv $@t $@
- rm -f y.tab.c
-uninstall-info-am:
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
- fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
- list='$(DISTFILES)'; for file in $$list; do \
- case $$file in \
- $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
- $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
- esac; \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test "$$dir" != "$$file" && test "$$dir" != "."; then \
- dir="/$$dir"; \
- $(mkdir_p) "$(distdir)$$dir"; \
- else \
- dir=''; \
- fi; \
- if test -d $$d/$$file; then \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
-check: check-am
-all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(HEADERS)
-installdirs:
- for dir in "$(DESTDIR)$(bindir)"; do \
- test -z "$$dir" || $(mkdir_p) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
- -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
- -rm -f ldlex.c
- -rm -f ldscript.c
-clean: clean-am
-
-clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \
- clean-noinstPROGRAMS mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-exec-am: install-binPROGRAMS
-
-install-info: install-info-am
-
-install-man:
-
-installcheck-am: installcheck-binPROGRAMS
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-binPROGRAMS uninstall-info-am
-
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
- clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS ctags \
- distclean distclean-compile distclean-generic distclean-tags \
- distdir dvi dvi-am html html-am info info-am install \
- install-am install-binPROGRAMS install-data install-data-am \
- install-exec install-exec-am install-info install-info-am \
- install-man install-strip installcheck installcheck-am \
- installcheck-binPROGRAMS installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
- uninstall-am uninstall-binPROGRAMS uninstall-info-am
-
-
-ldlex.o: ldscript.c
-ldscript.h: ldscript.c
-libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map
- $(CC) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
- $(libelf) $(libeu) \
- -Wl,--version-script,$(srcdir)/libld_elf_i386.map
-
-%.os: %.c %.o
- if $(filter-out -fmudflap,$(COMPILE)) -c -o $@ -fpic -DPIC -DSHARED \
- -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
- `test -f '$<' || echo '$(srcdir)/'`$<; \
- then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
- rm -f "$(DEPDIR)/$*.Tpo"; \
- else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
- fi
-
-# Special rule to make it possible to define libld_elf_a_SOURCES as we do.
-# Otherwise make would complain.
-.deps/none_ld.Po: none_ld.os
- -:
-
-installcheck-binPROGRAMS: $(bin_PROGRAMS)
- bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
- case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
- *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
- esac; \
- f=`echo "$$p" | \
- sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- for opt in --help --version; do \
- if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
- $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
- && test -n "`cat c$${pid}_.out`" \
- && test -z "`cat c$${pid}_.err`"; then :; \
- else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
- done; \
- done; rm -f c$${pid}_.???; exit $$bad
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/src/elf32-i386.script b/src/elf32-i386.script
deleted file mode 100644
index d62333ac..00000000
--- a/src/elf32-i386.script
+++ /dev/null
@@ -1,215 +0,0 @@
-ENTRY(_start);
-
-SEARCH_DIR(/lib);
-SEARCH_DIR(/usr/lib);
-SEARCH_DIR(/usr/local/lib);
-SEARCH_DIR(/usr/i686-pc-linux-gnu/lib);
-
-INTERP(/lib/ld-linux.so.2);
-
-PAGESIZE(4k);
-
-SEGMENT [RX]
-{
-#ifdef SHARED
- . = SIZEOF_HEADERS;
-#else
- . = 0x08048000 + SIZEOF_HEADERS;
-#endif
-
- .interp;
- .hash;
- .dynsym;
- .dynstr;
- .gnu.version;
- .gnu.version_d;
- .gnu.version_r;
- .rel.dyn;
- .rel.plt;
- .init { KEEP (*(.init)) }
- .plt;
- .text
- {
- *(.text)
- *(.text.*)
- *(.stub)
- *(.gnu.warning)
- *(.gnu.linkonce.t.*)
- }
- .fini { KEEP (*(.fini)) }
- PROVIDE (__etext = .);
- PROVIDE (_etext = .);
- PROVIDE (etext = .);
- .rodata
- {
- *(.rodata)
- *(.rodata.*)
- *(.gnu.linkonce.r.*)
- }
- .rodata1;
- . = ALIGN(32 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array
- {
- *(.preinit_array)
- }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array
- {
- *(.init_array)
- }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array
- {
- *(.fini_array)
- }
- PROVIDE (__fini_array_end = .);
-}
-
-SEGMENT [RW]
-{
- .sdata2
- {
- *(.sdata2)
- *(.sdata2.*)
- *(.gnu.linkonce.s2.*)
- }
- .sbss2
- {
- *(.sbss2)
- *(.sbss2.*)
- *(.gnu.linkonce.sb2.*)
- }
- /* Adjust the address for the data segment. We want to adjust up to
- the same address within the page on the next page up. */
- . = ALIGN(PAGESIZE) + (. & (PAGESIZE - 1));
- .data
- {
- *(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- }
- .data1;
- .eh_frame
- {
- KEEP (*(.eh_frame))
- }
- .gcc_except_table;
- .ctors
- {
- /* gcc uses crtbegin.o to find the start of
- the constructors, so we make sure it is
- first. Because this is a wildcard, it
- doesn't matter if the user does not
- actually link against crtbegin.o; the
- linker won't look for a file to match a
- wildcard. The wildcard also means that it
- doesn't matter which directory crtbegin.o
- is in. */
- KEEP (*crtbegin.o(.ctors))
- /* We don't want to include the .ctor section from
- from the crtend.o file until after the sorted ctors.
- The .ctor section from the crtend file contains the
- end of ctors marker and it must be last */
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- }
- .dtors
- {
- KEEP (*crtbegin.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- }
- .jcr;
- .got
- {
- *(.got.plt)
- *(.got)
- }
- .dynamic;
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata
- {
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
- }
- _edata = .;
- PROVIDE (edata = .);
- __bss_start = .;
- .sbss
- {
- PROVIDE (__sbss_start = .);
- PROVIDE (___sbss_start = .);
- *(.dynsbss)
- *(.sbss)
- *(.sbss.*)
- *(.gnu.linkonce.sb.*)
- *(.scommon)
- PROVIDE (__sbss_end = .);
- PROVIDE (___sbss_end = .);
- }
- .bss
- {
- *(.dynbss)
- *(.bss)
- *(.bss.*)
- *(.gnu.linkonce.b.*)
- *(COMMON)
- /* Align here to ensure that the .bss section occupies space up to
- _end. Align after .bss to ensure correct alignment even if the
- .bss section disappears because there are no input sections. */
- . = ALIGN(32 / 8);
- }
- . = ALIGN(32 / 8);
- _end = .;
- PROVIDE (end = .);
-}
-
-SEGMENT []
-{
- /* Stabs debugging sections. */
- .stab;
- .stabstr;
- .stab.excl;
- .stab.exclstr;
- .stab.index;
- .stab.indexstr;
- .comment;
- /* DWARF debug sections.
- Symbols in the DWARF debugging sections are relative to the beginning
- of the section so we begin them at 0. */
- /* DWARF 1 */
- .debug;
- .line;
- /* GNU DWARF 1 extensions */
- .debug_srcinfo;
- .debug_sfnames;
- /* DWARF 1.1 and DWARF 2 */
- .debug_aranges;
- .debug_pubnames;
- /* DWARF 2 */
- .debug_info
- {
- *(.debug_info)
- *(.gnu.linkonce.wi.*)
- }
- .debug_abbrev;
- .debug_line;
- .debug_frame;
- .debug_str;
- .debug_loc;
- .debug_macinfo;
- /* SGI/MIPS DWARF 2 extensions */
- .debug_weaknames;
- .debug_funcnames;
- .debug_typenames;
- .debug_varnames;
- /* These must appear regardless of . */
-}
diff --git a/src/elflint.c b/src/elflint.c
deleted file mode 100644
index d66cdd13..00000000
--- a/src/elflint.c
+++ /dev/null
@@ -1,2578 +0,0 @@
-/* Pedantic checking of ELF files compliance with gABI/psABI spec.
- Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <assert.h>
-#include <byteswap.h>
-#include <endian.h>
-#include <error.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <libebl.h>
-#include <libintl.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include <elf-knowledge.h>
-#include <system.h>
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-
-#define ARGP_strict 300
-#define ARGP_gnuld 301
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
-
- { "strict", ARGP_strict, NULL, 0,
- N_("Be extremely strict, flag level 2 features.") },
- { "quiet", 'q', NULL, 0, N_("Do not print anything if successful") },
- { "gnu-ld", ARGP_gnuld, NULL, 0,
- N_("Binary has been created with GNU ld and is therefore known to be \
-broken in certain ways") },
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("\
-Pedantic checking of ELF files compliance with gABI/psABI spec.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("FILE...");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help
-};
-
-
-/* Declarations of local functions. */
-static void process_file (int fd, Elf *elf, const char *prefix,
- const char *suffix, const char *fname, size_t size,
- bool only_one);
-static void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
- const char *fname, size_t size, bool only_one);
-
-/* Report an error. */
-#define ERROR(str, args...) \
- do { \
- printf (str, ##args); \
- ++error_count; \
- } while (0)
-static int error_count;
-
-/* True if we should perform very strict testing. */
-static bool be_strict;
-
-/* True if no message is to be printed if the run is succesful. */
-static bool be_quiet;
-
-/* True if binary is assumed to be generated with GNU ld. */
-static bool gnuld;
-
-/* Index of section header string table. */
-static uint32_t shstrndx;
-
-/* Array to count references in section groups. */
-static int *scnref;
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- bool only_one;
-
- /* Set locale. */
- setlocale (LC_ALL, "");
-
- /* Initialize the message catalog. */
- textdomain (PACKAGE);
-
- /* Parse and process arguments. */
- argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- /* If no ELF file is given punt. */
- if (remaining >= argc)
- {
- argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
- program_invocation_short_name);
- exit (1);
- }
-
- /* Before we start tell the ELF library which version we are using. */
- elf_version (EV_CURRENT);
-
- /* Now process all the files given at the command line. */
- only_one = remaining + 1 == argc;
- do
- {
- int fd;
- Elf *elf;
-
- /* Open the file. */
- fd = open (argv[remaining], O_RDONLY);
- if (fd == -1)
- {
- error (0, errno, gettext ("cannot open input file"));
- continue;
- }
-
- /* Create an `Elf' descriptor. */
- elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- ERROR (gettext ("cannot generate Elf descriptor: %s\n"),
- elf_errmsg (-1));
- else
- {
- unsigned int prev_error_count = error_count;
- struct stat64 st;
-
- if (fstat64 (fd, &st) != 0)
- {
- printf ("cannot stat '%s': %m\n", argv[remaining]);
- close (fd);
- continue;
- }
-
- process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
- only_one);
-
- /* Now we can close the descriptor. */
- if (elf_end (elf) != 0)
- ERROR (gettext ("error while closing Elf descriptor: %s\n"),
- elf_errmsg (-1));
-
- if (prev_error_count == error_count && !be_quiet)
- puts (gettext ("No errors"));
- }
-
- close (fd);
- }
- while (++remaining < argc);
-
- return error_count != 0;
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case ARGP_strict:
- be_strict = true;
- break;
-
- case 'q':
- be_quiet = true;
- break;
-
- case ARGP_gnuld:
- gnuld = true;
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "elflint (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* Process one file. */
-static void
-process_file (int fd, Elf *elf, const char *prefix, const char *suffix,
- const char *fname, size_t size, bool only_one)
-{
- /* We can handle two types of files: ELF files and archives. */
- Elf_Kind kind = elf_kind (elf);
-
- switch (kind)
- {
- case ELF_K_ELF:
- /* Yes! It's an ELF file. */
- process_elf_file (elf, prefix, suffix, fname, size, only_one);
- break;
-
- case ELF_K_AR:
- {
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char new_prefix[prefix_len + 1 + fname_len];
- char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
- char *cp = new_prefix;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = '(';
- strcpy (stpcpy (new_suffix, suffix), ")");
- }
- else
- new_suffix[0] = '\0';
- memcpy (cp, fname, fname_len);
-
- /* It's an archive. We process each file in it. */
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- kind = elf_kind (subelf);
-
- /* Call this function recursively. */
- if (kind == ELF_K_ELF || kind == ELF_K_AR)
- {
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
- assert (arhdr != NULL);
-
- process_file (fd, subelf, new_prefix, new_suffix,
- arhdr->ar_name, arhdr->ar_size, false);
- }
-
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (elf_end (subelf) != 0)
- ERROR (gettext (" error while freeing sub-ELF descriptor: %s\n"),
- elf_errmsg (-1));
- }
- }
- break;
-
- default:
- /* We cannot do anything. */
- ERROR (gettext ("\
-Not an ELF file - it has the wrong magic bytes at the start"));
- break;
- }
-}
-
-
-static const char *
-section_name (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
-
- return elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
-}
-
-
-static const int valid_e_machine[] =
- {
- EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
- EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
- EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
- EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
- EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
- EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
- EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
- EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
- EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
- EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
- EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA
- };
-#define nvalid_e_machine \
- (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
-
-
-/* Number of sections. */
-static unsigned int shnum;
-
-
-static void
-check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
-{
- char buf[512];
- size_t cnt;
-
- /* Check e_ident field. */
- if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
- ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
- if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
- ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
- if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
- ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
- if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
- ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
- && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
- ERROR (gettext ("e_ident[%d] == %d is no known class\n"),
- EI_CLASS, ehdr->e_ident[EI_CLASS]);
-
- if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
- && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
- ERROR (gettext ("e_ident[%d] == %d is no known data encoding\n"),
- EI_DATA, ehdr->e_ident[EI_DATA]);
-
- if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
- ERROR (gettext ("unknown ELF header version number e_ident[%d] == %d\n"),
- EI_VERSION, ehdr->e_ident[EI_VERSION]);
-
- /* We currently don't handle any OS ABIs. */
- if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE)
- ERROR (gettext ("unsupported OS ABI e_ident[%d] == \"%s\"\n"),
- EI_OSABI,
- ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
-
- /* No ABI versions other than zero supported either. */
- if (ehdr->e_ident[EI_ABIVERSION] != 0)
- ERROR (gettext ("unsupport ABI version e_ident[%d] == %d\n"),
- EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
-
- for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
- if (ehdr->e_ident[cnt] != 0)
- ERROR (gettext ("e_ident[%zu] is not zero\n"), cnt);
-
- /* Check the e_type field. */
- if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
- && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
- ERROR (gettext ("unknown object file type %d\n"), ehdr->e_type);
-
- /* Check the e_machine field. */
- for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
- if (valid_e_machine[cnt] == ehdr->e_machine)
- break;
- if (cnt == nvalid_e_machine)
- ERROR (gettext ("unknown machine type %d\n"), ehdr->e_machine);
-
- /* Check the e_version field. */
- if (ehdr->e_version != EV_CURRENT)
- ERROR (gettext ("unknown object file version\n"));
-
- /* Check the e_phoff and e_phnum fields. */
- if (ehdr->e_phoff == 0)
- {
- if (ehdr->e_phnum != 0)
- ERROR (gettext ("invalid program header offset\n"));
- else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
- ERROR (gettext ("\
-executables and DSOs cannot have zero program header offset\n"));
- }
- else if (ehdr->e_phnum == 0)
- ERROR (gettext ("invalid number of program header entries\n"));
-
- /* Check the e_shoff field. */
- shnum = ehdr->e_shnum;
- shstrndx = ehdr->e_shstrndx;
- if (ehdr->e_shoff == 0)
- {
- if (ehdr->e_shnum != 0)
- ERROR (gettext ("invalid section header table offset\n"));
- else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
- && ehdr->e_type != ET_CORE)
- ERROR (gettext ("section header table must be present\n"));
- }
- else
- {
- if (ehdr->e_shnum == 0)
- {
- /* Get the header of the zeroth section. The sh_size field
- might contain the section number. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
- if (shdr != NULL)
- {
- /* The error will be reported later. */
- if (shdr->sh_size == 0)
- ERROR (gettext ("\
-invalid number of section header table entries\n"));
- else
- shnum = shdr->sh_size;
- }
- }
-
- if (ehdr->e_shstrndx == SHN_XINDEX)
- {
- /* Get the header of the zeroth section. The sh_size field
- might contain the section number. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
- if (shdr != NULL)
- {
- /* The error will be reported later. */
- if (shdr->sh_link >= shnum)
- ERROR (gettext ("invalid section header index\n"));
- else
- shstrndx = shdr->sh_link;
- }
- }
- else if (shstrndx >= shnum)
- ERROR (gettext ("invalid section header index\n"));
- }
-
- /* Check the e_flags field. */
- if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
- ERROR (gettext ("invalid machine flags: %s\n"),
- ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
-
- /* Check e_ehsize, e_phentsize, and e_shentsize fields. */
- if (gelf_getclass (ebl->elf) == ELFCLASS32)
- {
- if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
- ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
-
- if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
- ERROR (gettext ("invalid program header size: %hd\n"),
- ehdr->e_phentsize);
- else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
- ERROR (gettext ("invalid program header position or size\n"));
-
- if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
- ERROR (gettext ("invalid section header size: %hd\n"),
- ehdr->e_shentsize);
- else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
- ERROR (gettext ("invalid section header position or size\n"));
- }
- else if (gelf_getclass (ebl->elf) == ELFCLASS64)
- {
- if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
- ERROR (gettext ("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
-
- if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
- ERROR (gettext ("invalid program header size: %hd\n"),
- ehdr->e_phentsize);
- else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
- ERROR (gettext ("invalid program header position or size\n"));
-
- if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
- ERROR (gettext ("invalid section header size: %hd\n"),
- ehdr->e_shentsize);
- else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
- ERROR (gettext ("invalid section header position or size\n"));
- }
-}
-
-
-/* Check that there is a section group section with index < IDX which
- contains section IDX and that there is exactly one. */
-static void
-check_scn_group (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- if (scnref[idx] == 0)
- {
- /* No reference so far. Search following sections, maybe the
- order is wrong. */
- size_t cnt;
-
- for (cnt = idx + 1; cnt < shnum; ++cnt)
- {
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- Elf_Data *data;
- Elf32_Word *grpdata;
- size_t inner;
-
- scn = elf_getscn (ebl->elf, cnt);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- /* We cannot get the section header so we cannot check it.
- The error to get the section header will be shown
- somewhere else. */
- continue;
-
- if (shdr->sh_type != SHT_GROUP)
- continue;
-
- data = elf_getdata (scn, NULL);
- if (data == NULL || data->d_size < sizeof (Elf32_Word))
- /* Cannot check the section. */
- continue;
-
- grpdata = (Elf32_Word *) data->d_buf;
- for (inner = 1; inner < data->d_size / sizeof (Elf32_Word); ++inner)
- if (grpdata[inner] == (Elf32_Word) idx)
- goto out;
- }
-
- out:
- if (cnt == shnum)
- ERROR (gettext ("\
-section [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
- idx, section_name (ebl, ehdr, idx));
- else
- ERROR (gettext ("\
-section [%2d] '%s': section group [%2zu] '%s' does not preceed group member\n"),
- idx, section_name (ebl, ehdr, idx),
- cnt, section_name (ebl, ehdr, cnt));
- }
-}
-
-
-static void
-check_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- bool no_xndx_warned = false;
- int no_pt_tls = 0;
-
- Elf_Scn *scn = elf_getscn (ebl->elf, idx);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- GElf_Shdr strshdr_mem;
- GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &strshdr_mem);
- if (shdr == NULL || strshdr == NULL)
- return;
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- if (strshdr->sh_type != SHT_STRTAB)
- ERROR (gettext ("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
- shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link),
- idx, section_name (ebl, ehdr, idx));
-
- /* Search for an extended section index table section. */
- size_t cnt;
- GElf_Shdr xndxshdr_mem;
- GElf_Shdr *xndxshdr = NULL;
- Elf_Data *xndxdata = NULL;
- Elf32_Word xndxscnidx = 0;
- for (cnt = 1; cnt < shnum; ++cnt)
- if (cnt != (size_t) idx)
- {
- Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
- xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
- xndxdata = elf_getdata (xndxscn, NULL);
- xndxscnidx = elf_ndxscn (xndxscn);
-
- if (xndxshdr == NULL || xndxdata == NULL)
- continue;
-
- if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
- && xndxshdr->sh_link == (GElf_Word) idx)
- break;
- }
- if (cnt == shnum)
- {
- xndxshdr = NULL;
- xndxdata = NULL;
- }
-
- if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
- ERROR (gettext ("\
-section [%2zu] '%s': entry size is does not match ElfXX_Sym\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- /* Test the zeroth entry. */
- GElf_Sym sym_mem;
- Elf32_Word xndx;
- GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
- if (sym == NULL)
- ERROR (gettext ("section [%2d] '%s': cannot get symbol %d: %s\n"),
- idx, section_name (ebl, ehdr, idx), 0, elf_errmsg (-1));
- else
- {
- if (sym->st_name != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_name");
- if (sym->st_value != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_value");
- if (sym->st_size != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_size");
- if (sym->st_info != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_info");
- if (sym->st_other != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_other");
- if (sym->st_shndx != 0)
- ERROR (gettext ("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
- idx, section_name (ebl, ehdr, idx), "st_shndx");
- if (xndxdata != NULL && xndx != 0)
- ERROR (gettext ("\
-section [%2d] '%s': XINDEX for zeroth entry not zero\n"),
- xndxscnidx, section_name (ebl, ehdr, xndxscnidx));
- }
-
- for (cnt = 1; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
- if (sym == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get symbol %zu: %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
- continue;
- }
-
- const char *name = NULL;
- if (sym->st_name >= strshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: invalid name value\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- else
- {
- name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
- assert (name != NULL);
- }
-
- if (sym->st_shndx == SHN_XINDEX)
- {
- if (xndxdata == NULL)
- {
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: too large section index but no extended section index section\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- no_xndx_warned = true;
- }
- else if (xndx < SHN_LORESERVE)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
- xndxscnidx, section_name (ebl, ehdr, xndxscnidx), cnt,
- xndx);
- }
- else if ((sym->st_shndx >= SHN_LORESERVE
- // && sym->st_shndx <= SHN_HIRESERVE always true
- && sym->st_shndx != SHN_ABS
- && sym->st_shndx != SHN_COMMON)
- || (sym->st_shndx >= shnum
- && (sym->st_shndx < SHN_LORESERVE
- /* || sym->st_shndx > SHN_HIRESERVE always false */)))
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: invalid section index\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- else
- xndx = sym->st_shndx;
-
- if (GELF_ST_TYPE (sym->st_info) >= STT_NUM)
- ERROR (gettext ("section [%2d] '%s': symbol %zu: unknown type\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (GELF_ST_BIND (sym->st_info) >= STB_NUM)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: unknown symbol binding\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (xndx == SHN_COMMON)
- {
- /* Common symbols can only appear in relocatable files. */
- if (ehdr->e_type != ET_REL)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- if (cnt < shdr->sh_info)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
- else if (xndx > 0 && xndx < shnum)
- {
- GElf_Shdr destshdr_mem;
- GElf_Shdr *destshdr;
-
- destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
- if (destshdr != NULL)
- {
- if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
- {
- if ((sym->st_value - destshdr->sh_addr) > destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: st_value out of bounds\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- else if ((sym->st_value - destshdr->sh_addr + sym->st_size)
- > destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- }
- else
- {
- if ((destshdr->sh_flags & SHF_TLS) == 0)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
-
- if (ehdr->e_type == ET_REL)
- {
- /* For object files the symbol value must fall
- into the section. */
- if (sym->st_value > destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- else if (sym->st_value + sym->st_size
- > destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- }
- else
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr = NULL;
- int pcnt;
-
- for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
- {
- phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
- if (phdr != NULL && phdr->p_type == PT_TLS)
- break;
- }
-
- if (pcnt == ehdr->e_phnum)
- {
- if (no_pt_tls++ == 0)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
- else
- {
- if (sym->st_value
- < destshdr->sh_offset - phdr->p_offset)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- else if (sym->st_value
- > (destshdr->sh_offset - phdr->p_offset
- + destshdr->sh_size))
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- else if (sym->st_value + sym->st_size
- > (destshdr->sh_offset - phdr->p_offset
- + destshdr->sh_size))
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- (int) xndx, section_name (ebl, ehdr, xndx));
- }
- }
- }
- }
- }
-
- if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
- {
- if (cnt >= shdr->sh_info)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: local symbol outside range described in sh_info\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
- else
- {
- if (cnt < shdr->sh_info)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: non-local symbol outside range described in sh_info\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
-
- if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
- ERROR (gettext ("\
-section [%2d] '%s': symbol %zu: non-local section symbol\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (name != NULL)
- {
- if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
- {
- /* Check that address and size match the global offset
- table. We have to locate the GOT by searching for a
- section named ".got". */
- Elf_Scn *gscn = NULL;
-
- while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
- {
- GElf_Shdr gshdr_mem;
- GElf_Shdr *gshdr = gelf_getshdr (gscn, &gshdr_mem);
- assert (gshdr != NULL);
-
- const char *sname = elf_strptr (ebl->elf, ehdr->e_shstrndx,
- gshdr->sh_name);
- if (sname != NULL && strcmp (sname, ".got") == 0)
- {
- /* Found it. */
- if (sym->st_value != gshdr->sh_addr)
- /* This test is more strict than the psABIs
- which usually allow the symbol to be in the
- middle of the .got section, allowing
- negative offsets. */
- ERROR (gettext ("\
-section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match .got section address %#" PRIx64 "\n"),
- idx, section_name (ebl, ehdr, idx),
- (uint64_t) sym->st_value,
- (uint64_t) gshdr->sh_addr);
-
- if (sym->st_size != gshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match .got section size %" PRIu64 "\n"),
- idx, section_name (ebl, ehdr, idx),
- (uint64_t) sym->st_size,
- (uint64_t) gshdr->sh_size);
-
- break;
- }
- }
-
- if (gscn == NULL)
- ERROR (gettext ("\
-section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
- idx, section_name (ebl, ehdr, idx));
- }
- else if (strcmp (name, "_DYNAMIC") == 0)
- {
- /* Check that address and size match the dynamic
- section. We locate the dynamic section via the
- program header entry. */
- int pcnt;
-
- for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
-
- if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
- {
- if (sym->st_value != phdr->p_vaddr)
- ERROR (gettext ("\
-section [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
- idx, section_name (ebl, ehdr, idx),
- (uint64_t) sym->st_value,
- (uint64_t) phdr->p_vaddr);
-
- if (sym->st_size != phdr->p_memsz)
- ERROR (gettext ("\
-section [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
- idx, section_name (ebl, ehdr, idx),
- (uint64_t) sym->st_size,
- (uint64_t) phdr->p_memsz);
-
- break;
- }
- }
- }
- }
- }
-}
-
-
-static bool
-is_rel_dyn (Ebl *ebl, GElf_Ehdr *ehdr, int idx, GElf_Shdr *shdr, bool rela)
-{
- /* If this is no executable or DSO it cannot be a .rel.dyn section. */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- return false;
-
- /* Check the section name. Unfortunately necessary. */
- if (strcmp (section_name (ebl, ehdr, idx), rela ? ".rela.dyn" : ".rel.dyn"))
- return false;
-
- /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
- entry can be present as well. */
- Elf_Scn *scn = NULL;
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- GElf_Shdr rcshdr_mem;
- const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
- assert (rcshdr != NULL);
-
- if (rcshdr->sh_type == SHT_DYNAMIC)
- {
- /* Found the dynamic section. Look through it. */
- Elf_Data *d = elf_getdata (scn, NULL);
- int cnt;
-
- for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
- {
- GElf_Dyn dyn_mem;
- GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
- assert (dyn != NULL);
-
- if (dyn->d_tag == DT_RELCOUNT)
- {
- /* Found it. One last check: does the number
- specified number of relative relocations exceed
- the total number of relocations? */
- if (dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
- ERROR (gettext ("\
-section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
- idx, section_name (ebl, ehdr, idx),
- (int) dyn->d_un.d_val);
- }
- }
-
- break;
- }
- }
-
- return true;
-}
-
-
-static void
-check_rela (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- Elf_Data *data;
- GElf_Shdr destshdr_mem;
- GElf_Shdr *destshdr = NULL;
- size_t cnt;
- bool reldyn = false;
- bool known_broken = gnuld;
-
- scn = elf_getscn (ebl->elf, idx);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- return;
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- /* Check whether the link to the section we relocate is reasonable. */
- if (shdr->sh_info >= shnum)
- ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
- idx, section_name (ebl, ehdr, idx));
- else
- {
- destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
- &destshdr_mem);
- if (destshdr != NULL)
- {
- if(destshdr->sh_type != SHT_PROGBITS
- && destshdr->sh_type != SHT_NOBITS)
- {
- reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
- if (!reldyn)
- ERROR (gettext ("\
-section [%2d] '%s': invalid destination section type\n"),
- idx, section_name (ebl, ehdr, idx));
- else
- {
- /* There is no standard, but we require that .rela.dyn
- sections have a sh_info value of zero. */
- if (shdr->sh_info != 0)
- ERROR (gettext ("\
-section [%2d] '%s': sh_info should be zero\n"),
- idx, section_name (ebl, ehdr, idx));
- }
- }
-
- if ((destshdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
- ERROR (gettext ("\
-section [%2d] '%s': no relocations for merge-able sections possible\n"),
- idx, section_name (ebl, ehdr, idx));
- }
- }
-
- if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT))
- ERROR (gettext ("\
-section [%2d] '%s': section entry size does not match ElfXX_Rela\n"),
- idx, section_name (ebl, ehdr, idx));
-
- Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
- Elf_Data *symdata = elf_getdata (symscn, NULL);
-
- for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- GElf_Rela rela_mem;
- GElf_Rela *rela;
-
- rela = gelf_getrela (data, cnt, &rela_mem);
- if (rela == NULL)
- {
- ERROR (gettext ("\
-section [%2d] '%s': cannot get relocation %zu: %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
- continue;
- }
-
- if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (rela->r_info)))
- ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- else if (!ebl_reloc_valid_use (ebl, GELF_R_TYPE (rela->r_info)))
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (symshdr != NULL
- && ((GELF_R_SYM (rela->r_info) + 1)
- * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
- > symshdr->sh_size))
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: invalid symbol index\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (rela->r_info)))
- {
- const char *name;
- char buf[64];
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (rela->r_info),
- &sym_mem);
- if (sym != NULL
- /* Get the name for the symbol. */
- && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
- && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- ebl_reloc_type_name (ebl, GELF_R_SYM (rela->r_info),
- buf, sizeof (buf)));
- }
-
- if (reldyn)
- {
- // XXX TODO Check .rel.dyn section addresses.
- }
- else if (!known_broken)
- {
- if (destshdr != NULL
- && (rela->r_offset - destshdr->sh_addr) >= destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: offset out of bounds\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
- }
-}
-
-
-static void
-check_rel (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- Elf_Data *data;
- GElf_Shdr destshdr_mem;
- GElf_Shdr *destshdr = NULL;
- size_t cnt;
- bool reldyn = false;
- bool known_broken = gnuld;
-
- scn = elf_getscn (ebl->elf, idx);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- return;
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- /* Check whether the link to the section we relocate is reasonable. */
- if (shdr->sh_info >= shnum)
- ERROR (gettext ("section [%2d] '%s': invalid destination section index\n"),
- idx, section_name (ebl, ehdr, idx));
- else
- {
- destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
- &destshdr_mem);
- if (destshdr != NULL)
- {
- if (destshdr->sh_type != SHT_PROGBITS
- && destshdr->sh_type != SHT_NOBITS)
- {
- reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, false);
- if (!reldyn)
- ERROR (gettext ("\
-section [%2d] '%s': invalid destination section type\n"),
- idx, section_name (ebl, ehdr, idx));
- else
- {
- /* There is no standard, but we require that .rela.dyn
- sections have a sh_info value of zero. */
- if (shdr->sh_info != 0)
- ERROR (gettext ("\
-section [%2d] '%s': sh_info should be zero\n"),
- idx, section_name (ebl, ehdr, idx));
- }
- }
-
- if ((destshdr->sh_flags & (SHF_MERGE | SHF_STRINGS)) != 0)
- ERROR (gettext ("\
-section [%2d] '%s': no relocations for merge-able sections possible\n"),
- idx, section_name (ebl, ehdr, idx));
- }
- }
-
- if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT))
- ERROR (gettext ("\
-section [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
- idx, section_name (ebl, ehdr, idx));
-
- Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
- Elf_Data *symdata = elf_getdata (symscn, NULL);
-
- for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- GElf_Rel rel_mem;
- GElf_Rel *rel;
-
- rel = gelf_getrel (data, cnt, &rel_mem);
- if (rel == NULL)
- {
- ERROR (gettext ("\
-section [%2d] '%s': cannot get relocation %zu: %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
- continue;
- }
-
- if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)))
- ERROR (gettext ("section [%2d] '%s': relocation %zu: invalid type\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- else if (!ebl_reloc_valid_use (ebl, GELF_R_TYPE (rel->r_info)))
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (symshdr != NULL
- && ((GELF_R_SYM (rel->r_info) + 1)
- * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
- > symshdr->sh_size))
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: invalid symbol index\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (rel->r_info)))
- {
- const char *name;
- char buf[64];
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (rel->r_info),
- &sym_mem);
- if (sym != NULL
- /* Get the name for the symbol. */
- && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
- && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- ebl_reloc_type_name (ebl, GELF_R_SYM (rel->r_info),
- buf, sizeof (buf)));
- }
-
- if (reldyn)
- {
- // XXX TODO Check .rel.dyn section addresses.
- }
- else if (!known_broken)
- {
- if (destshdr != NULL
- && GELF_R_TYPE (rel->r_info) != 0
- && (rel->r_offset - destshdr->sh_addr) >= destshdr->sh_size)
- ERROR (gettext ("\
-section [%2d] '%s': relocation %zu: offset out of bounds\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
- }
- }
-}
-
-
-/* Number of dynamic sections. */
-static int ndynamic;
-
-
-static void
-check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- Elf_Data *data;
- GElf_Shdr strshdr_mem;
- GElf_Shdr *strshdr;
- size_t cnt;
- static const bool dependencies[DT_NUM][DT_NUM] =
- {
- [DT_NEEDED] = { [DT_STRTAB] = true },
- [DT_PLTRELSZ] = { [DT_JMPREL] = true },
- [DT_HASH] = { [DT_SYMTAB] = true },
- [DT_STRTAB] = { [DT_STRSZ] = true },
- [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_HASH] = true,
- [DT_SYMENT] = true },
- [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
- [DT_RELASZ] = { [DT_RELA] = true },
- [DT_RELAENT] = { [DT_RELA] = true },
- [DT_STRSZ] = { [DT_STRTAB] = true },
- [DT_SYMENT] = { [DT_SYMTAB] = true },
- [DT_SONAME] = { [DT_STRTAB] = true },
- [DT_RPATH] = { [DT_STRTAB] = true },
- [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
- [DT_RELSZ] = { [DT_REL] = true },
- [DT_RELENT] = { [DT_REL] = true },
- [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
- [DT_RUNPATH] = { [DT_STRTAB] = true },
- [DT_PLTREL] = { [DT_JMPREL] = true },
- [DT_PLTRELSZ] = { [DT_JMPREL] = true }
- };
- bool has_dt[DT_NUM];
- static const bool level2[DT_NUM] =
- {
- [DT_RPATH] = true,
- [DT_SYMBOLIC] = true,
- [DT_TEXTREL] = true,
- [DT_BIND_NOW] = true
- };
- static const bool mandatory[DT_NUM] =
- {
- [DT_NULL] = true,
- [DT_HASH] = true,
- [DT_STRTAB] = true,
- [DT_SYMTAB] = true,
- [DT_STRSZ] = true,
- [DT_SYMENT] = true
- };
- GElf_Addr reladdr = 0;
- GElf_Word relsz = 0;
- GElf_Addr pltreladdr = 0;
- GElf_Word pltrelsz = 0;
-
- memset (has_dt, '\0', sizeof (has_dt));
-
- if (++ndynamic == 2)
- ERROR (gettext ("more than one dynamic section present\n"));
-
- scn = elf_getscn (ebl->elf, idx);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- return;
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
- if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
- ERROR (gettext ("\
-section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
- shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_entsize != gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT))
- ERROR (gettext ("\
-section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_info != 0)
- ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
- idx, section_name (ebl, ehdr, idx));
-
- bool non_null_warned = false;
- for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- GElf_Dyn dyn_mem;
- GElf_Dyn *dyn;
-
- dyn = gelf_getdyn (data, cnt, &dyn_mem);
- if (dyn == NULL)
- {
- ERROR (gettext ("\
-section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt, elf_errmsg (-1));
- continue;
- }
-
- if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
- {
- ERROR (gettext ("\
-section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
- idx, section_name (ebl, ehdr, idx));
- non_null_warned = true;
- }
-
- if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
- ERROR (gettext ("section [%2d] '%s': entry %zu: unknown tag\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (dyn->d_tag < DT_NUM)
- {
- if (has_dt[dyn->d_tag]
- && dyn->d_tag != DT_NEEDED
- && dyn->d_tag != DT_NULL
- && dyn->d_tag != DT_POSFLAG_1)
- {
- char buf[50];
- ERROR (gettext ("\
-section [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- ebl_dynamic_tag_name (ebl, dyn->d_tag,
- buf, sizeof (buf)));
- }
-
- if (be_strict && level2[dyn->d_tag])
- {
- char buf[50];
- ERROR (gettext ("\
-section [%2d] '%s': entry %zu: level 2 tag %s used\n"),
- idx, section_name (ebl, ehdr, idx), cnt,
- ebl_dynamic_tag_name (ebl, dyn->d_tag,
- buf, sizeof (buf)));
- }
-
- has_dt[dyn->d_tag] = true;
- }
-
- if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
- && dyn->d_un.d_val != DT_RELA)
- ERROR (gettext ("\
-section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
- idx, section_name (ebl, ehdr, idx), cnt);
-
- if (dyn->d_tag == DT_REL)
- reladdr = dyn->d_un.d_ptr;
- if (dyn->d_tag == DT_RELSZ)
- relsz = dyn->d_un.d_val;
- if (dyn->d_tag == DT_JMPREL)
- pltreladdr = dyn->d_un.d_ptr;
- if (dyn->d_tag == DT_PLTRELSZ)
- pltrelsz = dyn->d_un.d_val;
- }
-
- for (cnt = 1; cnt < DT_NUM; ++cnt)
- if (has_dt[cnt])
- {
- int inner;
-
- for (inner = 0; inner < DT_NUM; ++inner)
- if (dependencies[cnt][inner] && ! has_dt[inner])
- {
- char buf1[50];
- char buf2[50];
-
- ERROR (gettext ("\
-section [%2d] '%s': contains %s entry but not %s\n"),
- idx, section_name (ebl, ehdr, idx),
- ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
- ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
- }
- }
- else
- {
- if (mandatory[cnt])
- {
- char buf[50];
- ERROR (gettext ("\
-section [%2d] '%s': mandatory tag %s not present\n"),
- idx, section_name (ebl, ehdr, idx),
- ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
- }
- }
-
- /* Check the rel/rela tags. At least one group must be available. */
- if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
- && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
- ERROR (gettext ("\
-section [%2d] '%s': not all of %s, %s, and %s are present\n"),
- idx, section_name (ebl, ehdr, idx),
- "DT_RELA", "DT_RELASZ", "DT_RELAENT");
-
- if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
- && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
- ERROR (gettext ("\
-section [%2d] '%s': not all of %s, %s, and %s are present\n"),
- idx, section_name (ebl, ehdr, idx),
- "DT_REL", "DT_RELSZ", "DT_RELENT");
-}
-
-
-static void
-check_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr;
- Elf_Scn *symscn;
- size_t cnt;
- Elf_Data *data;
- Elf_Data *symdata;
-
- scn = elf_getscn (ebl->elf, idx);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- return;
-
- symscn = elf_getscn (ebl->elf, shdr->sh_link);
- symshdr = gelf_getshdr (symscn, &symshdr_mem);
- if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
- ERROR (gettext ("\
-section [%2d] '%s': extended section index section not for symbol table\n"),
- idx, section_name (ebl, ehdr, idx));
- symdata = elf_getdata (symscn, NULL);
- if (symdata == NULL)
- ERROR (gettext ("cannot get data for symbol section\n"));
-
- if (shdr->sh_entsize != sizeof (Elf32_Word))
- ERROR (gettext ("\
-section [%2d] '%s': entry size does not match Elf32_Word\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (symshdr != NULL
- && (shdr->sh_size / shdr->sh_entsize
- < symshdr->sh_size / symshdr->sh_entsize))
- ERROR (gettext ("\
-section [%2d] '%s': extended index table too small for symbol table\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_info != 0)
- ERROR (gettext ("section [%2d] '%s': sh_info not zero\n"),
- idx, section_name (ebl, ehdr, idx));
-
- for (cnt = idx + 1; cnt < shnum; ++cnt)
- {
- GElf_Shdr rshdr_mem;
- GElf_Shdr *rshdr;
-
- rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
- if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
- && rshdr->sh_link == shdr->sh_link)
- {
- ERROR (gettext ("\
-section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
- idx, section_name (ebl, ehdr, idx),
- cnt, section_name (ebl, ehdr, cnt));
- break;
- }
- }
-
- data = elf_getdata (scn, NULL);
-
- if (*((Elf32_Word *) data->d_buf) != 0)
- ERROR (gettext ("symbol 0 should have zero extended section index\n"));
-
- for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
- {
- Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
-
- if (xndx != 0)
- {
- GElf_Sym sym_data;
- GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
- if (sym == NULL)
- {
- ERROR (gettext ("cannot get data for symbol %zu\n"), cnt);
- continue;
- }
-
- if (sym->st_shndx != SHN_XINDEX)
- ERROR (gettext ("\
-extended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
- (uint32_t) xndx);
- }
- }
-}
-
-
-static void
-check_hash (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
-{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- Elf_Data *data;
- Elf32_Word nbucket;
- Elf32_Word nchain;
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr;
-
- scn = elf_getscn (ebl->elf, idx);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- return;
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &symshdr_mem);
- if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
- ERROR (gettext ("\
-section [%2d] '%s': hash table not for dynamic symbol table\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_entsize != sizeof (Elf32_Word))
- ERROR (gettext ("\
-section [%2d] '%s': entry size does not match Elf32_Word\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if ((shdr->sh_flags & SHF_ALLOC) == 0)
- ERROR (gettext ("section [%2d] '%s': not marked to be allocated\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_size < 2 * shdr->sh_entsize)
- {
- ERROR (gettext ("\
-section [%2d] '%s': hash table has not even room for nbucket and nchain\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- nbucket = ((Elf32_Word *) data->d_buf)[0];
- nchain = ((Elf32_Word *) data->d_buf)[1];
-
- if (shdr->sh_size < (2 + nbucket + nchain) * shdr->sh_entsize)
- ERROR (gettext ("\
-section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
- idx, section_name (ebl, ehdr, idx), (long int) shdr->sh_size,
- (long int) ((2 + nbucket + nchain) * shdr->sh_entsize));
-
- if (symshdr != NULL)
- {
- size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
- size_t cnt;
-
- if (nchain < symshdr->sh_size / symshdr->sh_entsize)
- ERROR (gettext ("section [%2d] '%s': chain array not large enough\n"),
- idx, section_name (ebl, ehdr, idx));
-
- for (cnt = 2; cnt < 2 + nbucket; ++cnt)
- if (((Elf32_Word *) data->d_buf)[cnt] >= symsize)
- ERROR (gettext ("\
-section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
- idx, section_name (ebl, ehdr, idx), cnt - 2);
-
- for (; cnt < 2 + nbucket + nchain; ++cnt)
- if (((Elf32_Word *) data->d_buf)[cnt] >= symsize)
- ERROR (gettext ("\
-section [%2d] '%s': hash chain reference %zu out of bounds\n"),
- idx, section_name (ebl, ehdr, idx), cnt - 2 - nbucket);
- }
-}
-
-
-static void
-check_null (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
-{
-#define TEST(name, extra) \
- if (extra && shdr->sh_##name != 0) \
- ERROR (gettext ("section [%2d] '%s': nonzero sh_%s for NULL section\n"), \
- idx, section_name (ebl, ehdr, idx), #name)
-
- TEST (name, 1);
- TEST (flags, 1);
- TEST (addr, 1);
- TEST (offset, 1);
- TEST (size, idx != 0);
- TEST (link, idx != 0);
- TEST (info, 1);
- TEST (addralign, 1);
- TEST (entsize, 1);
-}
-
-
-static void
-check_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
-{
- if (ehdr->e_type != ET_REL)
- {
- ERROR (gettext ("\
-section [%2d] '%s': section groups only allowed in relocatable object files\n"),
- idx, section_name (ebl, ehdr, idx));
- return;
- }
-
- /* Check that sh_link is an index of a symbol table. */
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &symshdr_mem);
- if (symshdr == NULL)
- ERROR (gettext ("section [%2d] '%s': cannot get symbol table: %s\n"),
- idx, section_name (ebl, ehdr, idx), elf_errmsg (-1));
- else
- {
- if (symshdr->sh_type != SHT_SYMTAB)
- ERROR (gettext ("\
-section [%2d] '%s': section reference in sh_link is no symbol table\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
- 1, EV_CURRENT))
- ERROR (gettext ("\
-section [%2d] '%s': invalid symbol index in sh_info\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (shdr->sh_flags != 0)
- ERROR (gettext ("section [%2d] '%s': sh_flags not zero\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (be_strict
- && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
- ERROR (gettext ("section [%2d] '%s': sh_flags not set correctly\n"),
- idx, section_name (ebl, ehdr, idx));
- }
-
- Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
- if (data == NULL)
- ERROR (gettext ("section [%2d] '%s': cannot get data: %s\n"),
- idx, section_name (ebl, ehdr, idx), elf_errmsg (-1));
- else
- {
- size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
- size_t cnt;
- Elf32_Word val;
-
- if (data->d_size % elsize != 0)
- ERROR (gettext ("\
-section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
- idx, section_name (ebl, ehdr, idx));
-
- if (data->d_size < elsize)
- ERROR (gettext ("\
-section [%2d] '%s': section group without flags word\n"),
- idx, section_name (ebl, ehdr, idx));
- else if (be_strict)
- {
- if (data->d_size < 2 * elsize)
- ERROR (gettext ("\
-section [%2d] '%s': section group without member\n"),
- idx, section_name (ebl, ehdr, idx));
- else if (data->d_size < 3 * elsize)
- ERROR (gettext ("\
-section [%2d] '%s': section group with only one member\n"),
- idx, section_name (ebl, ehdr, idx));
- }
-
-#if ALLOW_UNALIGNED
- val = *((Elf32_Word *) data->d_buf);
-#else
- memcpy (&val, data->d_buf, elsize);
-#endif
- if ((val & ~GRP_COMDAT) != 0)
- ERROR (gettext ("section [%2d] '%s': unknown section group flags\n"),
- idx, section_name (ebl, ehdr, idx));
-
- for (cnt = elsize; cnt < data->d_size; cnt += elsize)
- {
-#if ALLOW_UNALIGNED
- val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
-#else
- memcpy (&val, (char *) data->d_buf + cnt, elsize);
-#endif
-
- if (val > shnum)
- ERROR (gettext ("\
-section [%2d] '%s': section index %Zu out of range\n"),
- idx, section_name (ebl, ehdr, idx), cnt / elsize);
- else
- {
- GElf_Shdr refshdr_mem;
- GElf_Shdr *refshdr;
-
- refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
- &refshdr_mem);
- if (refshdr == NULL)
- ERROR (gettext ("\
-section [%2d] '%s': cannot get section header for element %zu: %s\n"),
- idx, section_name (ebl, ehdr, idx), cnt / elsize,
- elf_errmsg (-1));
- else
- {
- if (refshdr->sh_type == SHT_GROUP)
- ERROR (gettext ("\
-section [%2d] '%s': section group contains another group [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx),
- val, section_name (ebl, ehdr, val));
-
- if ((refshdr->sh_flags & SHF_GROUP) == 0)
- ERROR (gettext ("\
-section [%2d] '%s': element %Zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
- idx, section_name (ebl, ehdr, idx), cnt / elsize,
- val, section_name (ebl, ehdr, val));
- }
-
- if (++scnref[val] == 2)
- ERROR (gettext ("\
-section [%2d] '%s' is contained in more than one section group\n"),
- val, section_name (ebl, ehdr, val));
- }
- }
- }
-}
-
-
-static bool has_loadable_segment;
-static bool has_interp_segment;
-
-static const struct
-{
- const char *name;
- size_t namelen;
- GElf_Word type;
- enum { unused, exact, atleast } attrflag;
- GElf_Word attr;
- GElf_Word attr2;
-} special_sections[] =
- {
- /* See figure 4-14 in the gABI. */
- { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
- { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".debug", 7, SHT_PROGBITS, exact, 0, 0 },
- { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
- { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
- { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
- { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
- { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
- { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
- { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
- { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
- { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
- { ".note", 6, SHT_NOTE, exact, 0, 0 },
- { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
- { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
- { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
- { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
- { ".rodata", 8, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
- { ".rodata1", 9, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
- { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
- { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
- { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
- { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
- { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
- { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
- { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
- { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }
- };
-#define nspecial_sections \
- (sizeof (special_sections) / sizeof (special_sections[0]))
-
-
-static const char *
-section_flags_string (GElf_Word flags, char *buf, size_t len)
-{
- static const struct
- {
- GElf_Word flag;
- const char *name;
- } known_flags[] =
- {
-#define NEWFLAG(name) { SHF_##name, #name }
- NEWFLAG (WRITE),
- NEWFLAG (ALLOC),
- NEWFLAG (EXECINSTR),
- NEWFLAG (MERGE),
- NEWFLAG (STRINGS),
- NEWFLAG (INFO_LINK),
- NEWFLAG (LINK_ORDER),
- NEWFLAG (OS_NONCONFORMING),
- NEWFLAG (GROUP),
- NEWFLAG (TLS)
- };
-#undef NEWFLAG
- const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
-
- char *cp = buf;
- size_t cnt;
-
- for (cnt = 0; cnt < nknown_flags; ++cnt)
- if (flags & known_flags[cnt].flag)
- {
- if (cp != buf && len > 1)
- {
- *cp++ = '|';
- --len;
- }
-
- size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
- cp = mempcpy (cp, known_flags[cnt].name, ncopy);
- len -= ncopy;
-
- flags ^= known_flags[cnt].flag;
- }
-
- if (flags != 0 || cp == buf)
- snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
-
- *cp = '\0';
-
- return buf;
-}
-
-
-static void
-check_versym (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
-{
- /* The number of elements in the version symbol table must be the
- same as the number of symbols. */
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &symshdr_mem);
- if (symshdr == NULL)
- /* The error has already been reported. */
- return;
-
- if (symshdr->sh_type != SHT_DYNSYM)
- {
- ERROR (gettext ("\
-section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
- idx, section_name (ebl, ehdr, idx),
- shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link));
- return;
- }
-
- if (shdr->sh_size / shdr->sh_entsize
- != symshdr->sh_size / symshdr->sh_entsize)
- ERROR (gettext ("\
-section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
- idx, section_name (ebl, ehdr, idx),
- shdr->sh_link, section_name (ebl, ehdr, shdr->sh_link));
-
- // XXX TODO A lot more tests
- // check value of the fields. local symbols must have zero entries.
- // nonlocal symbols refer to valid version. Check that version index
- // in bound.
-}
-
-
-static void
-check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
- size_t cnt;
- bool dot_interp_section = false;
-
- if (ehdr->e_shoff == 0)
- /* No section header. */
- return;
-
- /* Allocate array to count references in section groups. */
- scnref = (int *) xcalloc (shnum, sizeof (int));
-
- /* Check the zeroth section first. It must not have any contents
- and the section header must contain nonzero value at most in the
- sh_size and sh_link fields. */
- shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
- if (shdr == NULL)
- ERROR (gettext ("cannot get section header of zeroth section\n"));
- else
- {
- if (shdr->sh_name != 0)
- ERROR (gettext ("zeroth section has nonzero name\n"));
- if (shdr->sh_type != 0)
- ERROR (gettext ("zeroth section has nonzero type\n"));
- if (shdr->sh_flags != 0)
- ERROR (gettext ("zeroth section has nonzero flags\n"));
- if (shdr->sh_addr != 0)
- ERROR (gettext ("zeroth section has nonzero address\n"));
- if (shdr->sh_offset != 0)
- ERROR (gettext ("zeroth section has nonzero offset\n"));
- if (shdr->sh_info != 0)
- ERROR (gettext ("zeroth section has nonzero info field\n"));
- if (shdr->sh_addralign != 0)
- ERROR (gettext ("zeroth section has nonzero align value\n"));
- if (shdr->sh_entsize != 0)
- ERROR (gettext ("zeroth section has nonzero entry size value\n"));
-
- if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
- ERROR (gettext ("\
-zeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
-
- if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
- ERROR (gettext ("\
-zeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
- }
-
- for (cnt = 1; cnt < shnum; ++cnt)
- {
- Elf_Scn *scn;
-
- scn = elf_getscn (ebl->elf, cnt);
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- {
- ERROR (gettext ("\
-cannot get section header for section [%2zu] '%s': %s\n"),
- cnt, section_name (ebl, ehdr, cnt), elf_errmsg (-1));
- continue;
- }
-
- const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
-
- if (scnname == NULL)
- ERROR (gettext ("section [%2zu]: invalid name\n"), cnt);
- else
- {
- /* Check whether it is one of the special sections defined in
- the gABI. */
- size_t s;
- for (s = 0; s < nspecial_sections; ++s)
- if (strncmp (scnname, special_sections[s].name,
- special_sections[s].namelen) == 0)
- {
- char stbuf1[100];
- char stbuf2[100];
- char stbuf3[100];
-
- if (shdr->sh_type != special_sections[s].type)
- ERROR (gettext ("\
-section [%2d] '%s' has wrong type: expected %s, is %s\n"),
- (int) cnt, scnname,
- ebl_section_type_name (ebl, special_sections[s].type,
- stbuf1, sizeof (stbuf1)),
- ebl_section_type_name (ebl, shdr->sh_type,
- stbuf2, sizeof (stbuf2)));
-
- if (special_sections[s].attrflag == exact)
- {
- /* Except for the link order and group bit all the
- other bits should match exactly. */
- if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
- != special_sections[s].attr)
- ERROR (gettext ("\
-section [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
- cnt, scnname,
- section_flags_string (special_sections[s].attr,
- stbuf1, sizeof (stbuf1)),
- section_flags_string (shdr->sh_flags
- & ~SHF_LINK_ORDER,
- stbuf2, sizeof (stbuf2)));
- }
- else if (special_sections[s].attrflag == atleast)
- {
- if ((shdr->sh_flags & special_sections[s].attr)
- != special_sections[s].attr
- || ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
- | special_sections[s].attr
- | special_sections[s].attr2))
- != 0))
- ERROR (gettext ("\
-section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
- cnt, scnname,
- section_flags_string (special_sections[s].attr,
- stbuf1, sizeof (stbuf1)),
- section_flags_string (special_sections[s].attr2,
- stbuf2, sizeof (stbuf2)),
- section_flags_string (shdr->sh_flags
- & ~(SHF_LINK_ORDER
- | SHF_GROUP),
- stbuf3, sizeof (stbuf3)));
- }
-
- if (strcmp (scnname, ".interp") == 0)
- {
- dot_interp_section = true;
-
- if (ehdr->e_type == ET_REL)
- ERROR (gettext ("\
-section [%2zu] '%s' present in object file\n"),
- cnt, scnname);
-
- if ((shdr->sh_flags & SHF_ALLOC) != 0
- && !has_loadable_segment)
- ERROR (gettext ("\
-section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
- cnt, scnname);
- else if ((shdr->sh_flags & SHF_ALLOC) == 0
- && has_loadable_segment)
- ERROR (gettext ("\
-section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
- cnt, scnname);
- }
- else
- {
- if (strcmp (scnname, ".symtab_shndx") == 0
- && ehdr->e_type != ET_REL)
- ERROR (gettext ("\
-section [%2zu] '%s' is extension section index table in non-object file\n"),
- cnt, scnname);
-
- /* These sections must have the SHF_ALLOC flag set iff
- a loadable segment is available.
-
- .relxxx
- .strtab
- .symtab
- .symtab_shndx
-
- Check that if there is a reference from the
- loaded section these sections also have the
- ALLOC flag set. */
-#if 0
- // XXX TODO
- if ((shdr->sh_flags & SHF_ALLOC) != 0
- && !has_loadable_segment)
- ERROR (gettext ("\
-section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
- cnt, scnname);
- else if ((shdr->sh_flags & SHF_ALLOC) == 0
- && has_loadable_segment)
- ERROR (gettext ("\
-section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
- cnt, scnname);
-#endif
- }
-
- break;
- }
- }
-
- if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
- ERROR (gettext ("\
-section [%2zu] '%s': size not multiple of entry size\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
- ERROR (gettext ("cannot get section header\n"));
-
- if (shdr->sh_type >= SHT_NUM
- && shdr->sh_type != SHT_GNU_LIBLIST
- && shdr->sh_type != SHT_CHECKSUM
- && shdr->sh_type != SHT_GNU_verdef
- && shdr->sh_type != SHT_GNU_verneed
- && shdr->sh_type != SHT_GNU_versym)
- ERROR (gettext ("unsupported section type %d\n"), (int) shdr->sh_type);
-
-#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
- | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
- | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS)
- if (shdr->sh_flags & ~ALL_SH_FLAGS)
- ERROR (gettext ("section [%2zu] '%s' contain unknown flag(s) %d\n"),
- cnt, section_name (ebl, ehdr, cnt),
- (int) shdr->sh_flags & ~ALL_SH_FLAGS);
- else if (shdr->sh_flags & SHF_TLS)
- {
- // XXX Correct?
- if (shdr->sh_addr != 0 && !gnuld)
- ERROR (gettext ("\
-section [%2zu] '%s': thread-local data sections address not zero\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- // XXX TODO more tests!?
- }
-
- if (shdr->sh_link >= shnum)
- ERROR (gettext ("\
-section [%2zu] '%s': invalid section reference in link value\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
- ERROR (gettext ("\
-section [%2zu] '%s': invalid section reference in info value\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- if ((shdr->sh_flags & SHF_MERGE) == 0
- && (shdr->sh_flags & SHF_STRINGS) != 0
- && be_strict)
- ERROR (gettext ("\
-section [%2zu] '%s': strings flag set without merge flag\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
- ERROR (gettext ("\
-section [%2zu] '%s': merge flag set but entry size is zero\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- if (shdr->sh_flags & SHF_GROUP)
- check_scn_group (ebl, ehdr, cnt);
-
- if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0)
- {
- /* Make sure the section is contained in a loaded segment
- and that the initialization part matches NOBITS sections. */
- int pcnt;
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
- if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
- && ((phdr->p_type == PT_LOAD
- && (shdr->sh_flags & SHF_TLS) == 0)
- || (phdr->p_type == PT_TLS
- && (shdr->sh_flags & SHF_TLS) != 0))
- && phdr->p_offset <= shdr->sh_offset
- && phdr->p_offset + phdr->p_memsz > shdr->sh_offset)
- {
- /* Found the segment. */
- if (phdr->p_offset + phdr->p_memsz
- < shdr->sh_offset + shdr->sh_size)
- ERROR (gettext ("\
-section [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
- cnt, section_name (ebl, ehdr, cnt), pcnt);
-
- if (shdr->sh_type == SHT_NOBITS)
- {
- if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz)
- ERROR (gettext ("\
-section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
- cnt, section_name (ebl, ehdr, cnt), pcnt);
- }
- else
- {
- if (shdr->sh_offset >= phdr->p_offset + phdr->p_filesz)
- ERROR (gettext ("\
-section [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
- cnt, section_name (ebl, ehdr, cnt), pcnt);
- }
-
- break;
- }
-
- if (pcnt == ehdr->e_phnum)
- ERROR (gettext ("\
-section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
- cnt, section_name (ebl, ehdr, cnt));
- }
-
- if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
- ERROR (gettext ("\
-section [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
- cnt, section_name (ebl, ehdr, cnt));
-
- switch (shdr->sh_type)
- {
- case SHT_SYMTAB:
- case SHT_DYNSYM:
- check_symtab (ebl, ehdr, cnt);
- break;
-
- case SHT_RELA:
- check_rela (ebl, ehdr, cnt);
- break;
-
- case SHT_REL:
- check_rel (ebl, ehdr, cnt);
- break;
-
- case SHT_DYNAMIC:
- check_dynamic (ebl, ehdr, cnt);
- break;
-
- case SHT_SYMTAB_SHNDX:
- check_symtab_shndx (ebl, ehdr, cnt);
- break;
-
- case SHT_HASH:
- check_hash (ebl, ehdr, cnt);
- break;
-
- case SHT_NULL:
- check_null (ebl, ehdr, shdr, cnt);
- break;
-
- case SHT_GROUP:
- check_group (ebl, ehdr, shdr, cnt);
- break;
-
- case SHT_GNU_versym:
- check_versym (ebl, ehdr, shdr, cnt);
- break;
-
- default:
- /* Nothing. */
- break;
- }
- }
-
- if (has_interp_segment && !dot_interp_section)
- ERROR (gettext ("INTERP program header entry but no .interp section\n"));
-
- free (scnref);
-}
-
-
-static void
-check_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
-{
- if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
- && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- ERROR (gettext ("\
-phdr[%d]: no note entries defined for the type of file\n"),
- cnt);
-
- char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
-
- /* ELF64 files often use note section entries in the 32-bit format.
- The p_align field is set to 8 in case the 64-bit format is used.
- In case the p_align value is 0 or 4 the 32-bit format is
- used. */
- GElf_Xword align = phdr->p_align == 0 || phdr->p_align == 4 ? 4 : 8;
-#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
-
- GElf_Xword idx = 0;
- while (idx < phdr->p_filesz)
- {
- uint64_t namesz;
- uint64_t descsz;
- uint64_t type;
- uint32_t namesz32;
- uint32_t descsz32;
-
- if (align == 4)
- {
- uint32_t *ptr = (uint32_t *) (notemem + idx);
-
- if ((__BYTE_ORDER == __LITTLE_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- || (__BYTE_ORDER == __BIG_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
- {
- namesz32 = namesz = bswap_32 (*ptr);
- ++ptr;
- descsz32 = descsz = bswap_32 (*ptr);
- ++ptr;
- type = bswap_32 (*ptr);
- }
- else
- {
- namesz32 = namesz = *ptr++;
- descsz32 = descsz = *ptr++;
- type = *ptr;
- }
- }
- else
- {
- uint64_t *ptr = (uint64_t *) (notemem + idx);
- uint32_t *ptr32 = (uint32_t *) (notemem + idx);
-
- if ((__BYTE_ORDER == __LITTLE_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- || (__BYTE_ORDER == __BIG_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
- {
- namesz = bswap_64 (*ptr);
- ++ptr;
- descsz = bswap_64 (*ptr);
- ++ptr;
- type = bswap_64 (*ptr);
-
- namesz32 = bswap_32 (*ptr32);
- ++ptr32;
- descsz32 = bswap_32 (*ptr32);
- }
- else
- {
- namesz = *ptr++;
- descsz = *ptr++;
- type = *ptr;
-
- namesz32 = *ptr32++;
- descsz32 = *ptr32;
- }
- }
-
- if (idx + 3 * align > phdr->p_filesz
- || (idx + 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz)
- > phdr->p_filesz))
- {
- if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
- && idx + 3 * 4 <= phdr->p_filesz
- && (idx + 3 * 4 + ALIGNED_LEN (namesz32) + ALIGNED_LEN (descsz32)
- <= phdr->p_filesz))
- ERROR (gettext ("\
-phdr[%d]: note entries probably in form of a 32-bit ELF file\n"), cnt);
- else
- ERROR (gettext ("phdr[%d]: extra %zu bytes after last note\n"),
- cnt, (size_t) (phdr->p_filesz - idx));
- break;
- }
-
- /* Make sure it is one of the note types we know about. */
- if (ehdr->e_type == ET_CORE)
- {
- switch (type)
- {
- case NT_PRSTATUS:
- case NT_FPREGSET:
- case NT_PRPSINFO:
- case NT_TASKSTRUCT: /* NT_PRXREG on Solaris. */
- case NT_PLATFORM:
- case NT_AUXV:
- case NT_GWINDOWS:
- case NT_ASRS:
- case NT_PSTATUS:
- case NT_PSINFO:
- case NT_PRCRED:
- case NT_UTSNAME:
- case NT_LWPSTATUS:
- case NT_LWPSINFO:
- case NT_PRFPXREG:
- /* Known type. */
- break;
-
- default:
- ERROR (gettext ("\
-phdr[%d]: unknown core file note type %" PRIu64 " at offset %" PRIu64 "\n"),
- cnt, type, idx);
- }
- }
- else
- {
- if (type != NT_VERSION)
- ERROR (gettext ("\
-phdr[%d]: unknown object file note type %" PRIu64 " at offset %" PRIu64 "\n"),
- cnt, type, idx);
- }
-
- /* Move to the next entry. */
- idx += 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz);
-
- }
-
- gelf_freechunk (ebl->elf, notemem);
-}
-
-
-static void
-check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- if (ehdr->e_phoff == 0)
- return;
-
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
- && ehdr->e_type != ET_CORE)
- ERROR (gettext ("\
-only executables, shared objects, and core files can have program headers\n"));
-
- int num_pt_interp = 0;
- int num_pt_tls = 0;
- int num_pt_relro = 0;
-
- for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
- if (phdr == NULL)
- {
- ERROR (gettext ("cannot get program header entry %d: %s\n"),
- cnt, elf_errmsg (-1));
- continue;
- }
-
- if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
- && phdr->p_type != PT_GNU_STACK)
- ERROR (gettext ("\
-program header entry %d: unknown program header entry type\n"),
- cnt);
-
- if (phdr->p_type == PT_LOAD)
- has_loadable_segment = true;
- else if (phdr->p_type == PT_INTERP)
- {
- if (++num_pt_interp != 1)
- {
- if (num_pt_interp == 2)
- ERROR (gettext ("\
-more than one INTERP entry in program header\n"));
- }
- has_interp_segment = true;
- }
- else if (phdr->p_type == PT_TLS)
- {
- if (++num_pt_tls == 2)
- ERROR (gettext ("more than one TLS entry in program header\n"));
- }
- else if (phdr->p_type == PT_NOTE)
- check_note (ebl, ehdr, phdr, cnt);
- else if (phdr->p_type == PT_DYNAMIC
- && ehdr->e_type == ET_EXEC && ! has_interp_segment)
- ERROR (gettext ("static executable cannot have dynamic sections\n"));
- else if (phdr->p_type == PT_GNU_RELRO)
- {
- if (++num_pt_relro == 2)
- ERROR (gettext ("\
-more than one GNU_RELRO entry in program header\n"));
- else
- {
- /* Check that the region is in a writable segment. */
- int inner;
- for (inner = 0; inner < ehdr->e_phnum; ++inner)
- {
- GElf_Phdr phdr2_mem;
- GElf_Phdr *phdr2;
-
- phdr2 = gelf_getphdr (ebl->elf, cnt, &phdr2_mem);
- if (phdr2 == NULL)
- continue;
-
- if (phdr2->p_type == PT_LOAD
- && phdr->p_vaddr >= phdr2->p_vaddr
- && (phdr->p_vaddr + phdr->p_memsz
- <= phdr2->p_vaddr + phdr2->p_memsz))
- {
- if ((phdr2->p_flags & PF_W) == 0)
- ERROR (gettext ("\
-loadable segment GNU_RELRO applies to is not writable\n"));
- if ((phdr2->p_flags & PF_X) != 0)
- ERROR (gettext ("\
-loadable segment GNU_RELRO applies to is executable\n"));
- break;
- }
- }
-
- if (inner >= ehdr->e_phnum)
- ERROR (gettext ("\
-GNU_RELRO segment not contained in a loaded segment\n"));
- }
- }
-
- if (phdr->p_filesz > phdr->p_memsz)
- ERROR (gettext ("\
-program header entry %d: file size greater than memory size\n"),
- cnt);
-
- if (phdr->p_align > 1)
- {
- if (!powerof2 (phdr->p_align))
- ERROR (gettext ("\
-program header entry %d: alignment not a power of 2\n"), cnt);
- else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
- ERROR (gettext ("\
-program header entry %d: file offset and virtual address not module of alignment\n"), cnt);
- }
- }
-}
-
-
-/* Process one file. */
-static void
-process_elf_file (Elf *elf, const char *prefix, const char *suffix,
- const char *fname, size_t size, bool only_one)
-{
- /* Reset variables. */
- ndynamic = 0;
-
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- Ebl *ebl;
-
- /* Print the file name. */
- if (!only_one)
- {
- if (prefix != NULL)
- printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
- else
- printf ("\n%s:\n", fname);
- }
-
- if (ehdr == NULL)
- {
- ERROR (gettext ("cannot read ELF header: %s\n"), elf_errmsg (-1));
- return;
- }
-
- ebl = ebl_openbackend (elf);
- /* If there is no appropriate backend library we cannot test
- architecture and OS specific features. Any encountered extension
- is an error. */
-
- /* Go straight by the gABI, check all the parts in turn. */
- check_elf_header (ebl, ehdr, size);
-
- /* Check the program header. */
- check_program_header (ebl, ehdr);
-
- /* Next the section headers. It is OK if there are no section
- headers at all. */
- check_sections (ebl, ehdr);
-
- /* Free the resources. */
- ebl_closebackend (ebl);
-}
diff --git a/src/i386_ld.c b/src/i386_ld.c
deleted file mode 100644
index 28304ca0..00000000
--- a/src/i386_ld.c
+++ /dev/null
@@ -1,891 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <error.h>
-#include <libintl.h>
-#include <stdlib.h>
-#include <string.h>
-
-// XXX For debugging
-#include <stdio.h>
-
-#include <system.h>
-#include "ld.h"
-#include "list.h"
-/* x86 is little endian. */
-#define UNALIGNED_ACCESS_CLASS LITTLE_ENDIAN
-#include "unaligned.h"
-#include "xelf.h"
-
-
-/* The old callbacks. */
-static int (*old_open_outfile) (struct ld_state *, int, int, int);
-
-
-static int
-elf_i386_open_outfile (struct ld_state *statep, int machine, int klass,
- int data)
-{
- /* This backend only handles 32-bit object files. */
- /* XXX For now just use the generic backend. */
- return old_open_outfile (statep, EM_386, ELFCLASS32, ELFDATA2LSB);
-}
-
-
-/* Process relocations for the output in a relocatable file. This
- only means adjusting offset and symbol indices. */
-static void
-elf_i386_relocate_section (struct ld_state *statep, Elf_Scn *outscn,
- struct scninfo *firstp,
- const Elf32_Word *dblindirect)
-{
- struct scninfo *runp;
- Elf_Data *data;
-
- /* Iterate over all the input sections. Appropriate data buffers in the
- output sections were already created. I get them iteratively, too. */
- runp = firstp;
- data = NULL;
- do
- {
- Elf_Data *reltgtdata;
- Elf_Data *insymdata;
- Elf_Data *inxndxdata = NULL;
- size_t maxcnt;
- size_t cnt;
- const Elf32_Word *symindirect;
- struct symbol **symref;
- struct usedfiles *file = runp->fileinfo;
- XElf_Shdr *shdr = &SCNINFO_SHDR (runp->shdr);
-
- /* Get the output section data buffer for this input section. */
- data = elf_getdata (outscn, data);
- assert (data != NULL);
-
- /* Get the data for section in the input file this relocation
- section is relocating. Since these buffers are reused in the
- output modifying these buffers has the correct result. */
- reltgtdata = elf_getdata (file->scninfo[shdr->sh_info].scn, NULL);
-
- /* Get the data for the input section symbol table for this
- relocation section. */
- insymdata = elf_getdata (file->scninfo[shdr->sh_link].scn, NULL);
- assert (insymdata != NULL);
-
- /* And the extended section index table. */
- inxndxdata = runp->fileinfo->xndxdata;
-
- /* Number of relocations. */
- maxcnt = shdr->sh_size / shdr->sh_entsize;
-
- /* Array directing local symbol table offsets to output symbol
- table offsets. */
- symindirect = file->symindirect;
-
- /* References to the symbol records. */
- symref = file->symref;
-
- /* Iterate over all the relocations in the section. */
- for (cnt = 0; cnt < maxcnt; ++cnt)
- {
- XElf_Rel_vardef (rel);
- Elf32_Word si;
- XElf_Sym_vardef (sym);
- Elf32_Word xndx;
-
- /* Get the relocation data itself. x86 uses Rel
- relocations. In case we have to handle Rela as well the
- whole loop probably should be duplicated. */
- xelf_getrel (data, cnt, rel);
- assert (rel != NULL);
-
- /* Compute the symbol index in the output file. */
- si = symindirect[XELF_R_SYM (rel->r_info)];
- if (si == 0)
- {
- /* This happens if the symbol is locally undefined or
- superceded by some other definition. */
- assert (symref[XELF_R_SYM (rel->r_info)] != NULL);
- si = symref[XELF_R_SYM (rel->r_info)]->outsymidx;
- }
- /* Take reordering performed to sort the symbol table into
- account. */
- si = dblindirect[si];
-
- /* Get the symbol table entry. */
- xelf_getsymshndx (insymdata, inxndxdata, XELF_R_SYM (rel->r_info),
- sym, xndx);
- if (sym->st_shndx != SHN_XINDEX)
- xndx = sym->st_shndx;
- assert (xndx < SHN_LORESERVE || xndx > SHN_HIRESERVE);
-
- /* We fortunately don't have to do much. The relocations
- mostly get only updates of the offset. Only is a
- relocation referred to a section do we have to do
- something. In this case the reference to the sections
- has no direct equivalent since the part the input section
- contributes need not start at the same offset as in the
- input file. Therefore we have to adjust the addend which
- in the case of Rel relocations is in the target section
- itself. */
- if (XELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- Elf32_Word toadd;
-
- /* We expect here on R_386_32 relocations. */
- assert (XELF_R_TYPE (rel->r_info) == R_386_32);
-
- /* Avoid writing to the section memory if this is
- effectively a no-op since it might save a
- copy-on-write operation. */
- toadd = file->scninfo[xndx].offset;
- if (toadd != 0)
- add_4ubyte_unaligned (reltgtdata->d_buf + rel->r_offset,
- toadd);
- }
-
- /* Adjust the offset for the position of the input section
- content in the output section. */
- rel->r_offset += file->scninfo[shdr->sh_info].offset;
-
- /* And finally adjust the index of the symbol in the output
- symbol table. */
- rel->r_info = XELF_R_INFO (si, XELF_R_TYPE (rel->r_info));
-
- /* Store the result. */
- (void) xelf_update_rel (data, cnt, rel);
- }
-
- runp = runp->next;
- }
- while (runp != firstp);
-}
-
-
-/* Each PLT entry has 16 bytes. We need one entry as overhead for
- the code to set up the call into the runtime relocation. */
-#define PLT_ENTRY_SIZE 16
-
-static void
-elf_i386_initialize_plt (struct ld_state *statep, Elf_Scn *scn)
-{
- Elf_Data *data;
- XElf_Shdr_vardef (shdr);
-
- /* Change the entry size in the section header. */
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
- shdr->sh_entsize = PLT_ENTRY_SIZE;
- (void) xelf_update_shdr (scn, shdr);
-
- data = elf_newdata (scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot allocate PLT section: %s"),
- elf_errmsg (-1));
-
- /* We need one special PLT entry (performing the jump to the runtime
- relocation routines) and one for each function we call in a DSO. */
- data->d_size = (1 + statep->nplt) * PLT_ENTRY_SIZE;
- data->d_buf = xcalloc (1, data->d_size);
- data->d_align = 8;
- data->d_off = 0;
-
- statep->nplt_used = 1;
-}
-
-
-static void
-elf_i386_initialize_pltrel (struct ld_state *statep, Elf_Scn *scn)
-{
- Elf_Data *data;
-
- data = elf_newdata (scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot allocate PLTREL section: %s"),
- elf_errmsg (-1));
-
- /* One relocation per PLT entry. */
- data->d_size = statep->nplt * sizeof (Elf32_Rel);
- data->d_buf = xcalloc (1, data->d_size);
- data->d_type = ELF_T_REL;
- data->d_align = 4;
- data->d_off = 0;
-}
-
-
-static void
-elf_i386_initialize_got (struct ld_state *statep, Elf_Scn *scn)
-{
- Elf_Data *data;
-
- /* If we have no .plt we don't need the special entries we normally
- create for it. The other contents is created later. */
- if (statep->ngot + statep->nplt == 0)
- return;
-
- data = elf_newdata (scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot allocate GOT section: %s"),
- elf_errmsg (-1));
-
- /* We construct the .got section in pieces. Here we only add the data
- structures which are used by the PLT. This includes three reserved
- entries at the beginning (the first will contain a pointer to the
- .dynamic section), and one word for each PLT entry. */
- data->d_size = (3 + statep->ngot + statep->nplt) * sizeof (Elf32_Addr);
- data->d_buf = xcalloc (1, data->d_size);
- data->d_align = sizeof (Elf32_Addr);
- data->d_off = 0;
-}
-
-
-/* The first entry in an absolute procedure linkage table looks like
- this. See the SVR4 ABI i386 supplement to see how this works. */
-static const unsigned char elf_i386_plt0_entry[PLT_ENTRY_SIZE] =
-{
- 0xff, 0x35, /* pushl contents of address */
- 0, 0, 0, 0, /* replaced with address of .got + 4. */
- 0xff, 0x25, /* jmp indirect */
- 0, 0, 0, 0, /* replaced with address of .got + 8. */
- 0, 0, 0, 0 /* pad out to 16 bytes. */
-};
-
-/* Type describing the first PLT entry in non-PIC. */
-struct plt0_entry
-{
- /* First a 'push' of the second GOT entry. */
- unsigned char push_instr[2];
- uint32_t gotp4_addr;
- /* Second, a 'jmp indirect' to the third GOT entry. */
- unsigned char jmp_instr[2];
- uint32_t gotp8_addr;
- /* Padding. */
- unsigned char padding[4];
-} __attribute__ ((packed));
-
-/* The first entry in a PIC procedure linkage table look like this. */
-static const unsigned char elf_i386_pic_plt0_entry[PLT_ENTRY_SIZE] =
-{
- 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */
- 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */
- 0, 0, 0, 0 /* pad out to 16 bytes. */
-};
-
-/* Contents of all but the first PLT entry in executable. */
-static const unsigned char elf_i386_plt_entry[PLT_ENTRY_SIZE] =
-{
- 0xff, 0x25, /* jmp indirect */
- 0, 0, 0, 0, /* replaced with address of this symbol in .got. */
- 0x68, /* pushl immediate */
- 0, 0, 0, 0, /* replaced with offset into relocation table. */
- 0xe9, /* jmp relative */
- 0, 0, 0, 0 /* replaced with offset to start of .plt. */
-};
-
-/* Contents of all but the first PLT entry in DSOs. */
-static const unsigned char elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
-{
- 0xff, 0xa3, /* jmp *offset(%ebx) */
- 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */
- 0x68, /* pushl immediate */
- 0, 0, 0, 0, /* replaced with offset into relocation table. */
- 0xe9, /* jmp relative */
- 0, 0, 0, 0 /* replaced with offset to start of .plt. */
-};
-
-/* Type describing a PLT entry. */
-struct plt_entry
-{
- /* The first instruction is 'jmp indirect' or 'jmp *offset(%ebs)'. */
- unsigned char jmp_instr[2];
- uint32_t offset_got;
- /* The second instruction is 'push immediate'. */
- unsigned char push_instr;
- uint32_t push_imm;
- /* Finally a 'jmp relative'. */
- unsigned char jmp_instr2;
- uint32_t plt0_offset;
-} __attribute__ ((packed));
-
-
-static void
-elf_i386_finalize_plt (struct ld_state *statep, size_t nsym, size_t nsym_dyn)
-{
- Elf_Scn *scn;
- XElf_Shdr_vardef (shdr);
- Elf_Data *data;
- Elf_Data *symdata = NULL;
- Elf_Data *dynsymdata;
- size_t cnt;
- const bool build_dso = statep->file_type == dso_file_type;
-
- if (unlikely (statep->nplt + statep->ngot == 0))
- /* Nothing to be done. */
- return;
-
- /* Get the address of the got section. */
- scn = elf_getscn (statep->outelf, statep->gotscnidx);
- xelf_getshdr (scn, shdr);
- data = elf_getdata (scn, NULL);
- assert (shdr != NULL && data != NULL);
- Elf32_Addr gotaddr = shdr->sh_addr;
-
- /* Now create the initial values for the .got section. The first
- word contains the address of the .dynamic section. */
- xelf_getshdr (elf_getscn (statep->outelf, statep->dynamicscnidx), shdr);
- assert (shdr != NULL);
- ((Elf32_Word *) data->d_buf)[0] = shdr->sh_addr;
-
- /* The second and third entry are left empty for use by the dynamic
- linker. The following entries are pointers to the instructions
- following the initial jmp instruction in the corresponding PLT
- entry. Since the first PLT entry is special the first used one
- has the index 1. */
- scn = elf_getscn (statep->outelf, statep->pltscnidx);
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- dynsymdata = elf_getdata (elf_getscn (statep->outelf, statep->dynsymscnidx),
- NULL);
- assert (dynsymdata != NULL);
-
- if (statep->symscnidx != 0)
- {
- symdata = elf_getdata (elf_getscn (statep->outelf, statep->symscnidx),
- NULL);
- assert (symdata != NULL);
- }
-
- for (cnt = 0; cnt < statep->nplt; ++cnt)
- {
- assert ((4 + cnt) * sizeof (Elf32_Word) <= data->d_size);
-
- /* Address in the PLT. */
- Elf32_Addr pltentryaddr = shdr->sh_addr + (1 + cnt) * PLT_ENTRY_SIZE;
-
- /* Point the GOT entry at the PLT entry, after the initial jmp. */
- ((Elf32_Word *) data->d_buf)[3 + cnt] = pltentryaddr + 6;
-
- /* The value of the symbol is the address of the corresponding PLT
- entry. Store the address, also for the normal symbol table if
- this is necessary. */
- ((Elf32_Sym *) dynsymdata->d_buf)[1 + cnt].st_value = pltentryaddr;
-
- if (symdata != NULL)
- ((Elf32_Sym *) symdata->d_buf)[nsym - statep->nplt + cnt].st_value
- = pltentryaddr;
- }
-
- /* Create the .plt section. */
- scn = elf_getscn (statep->outelf, statep->pltscnidx);
- data = elf_getdata (scn, NULL);
- assert (data != NULL);
-
- /* Create the first entry. */
- assert (data->d_size >= PLT_ENTRY_SIZE);
- if (build_dso)
- /* Copy the entry. It's complete, no relocation needed. */
- memcpy (data->d_buf, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
- else
- {
- /* Copy the skeleton. */
- memcpy (data->d_buf, elf_i386_plt0_entry, PLT_ENTRY_SIZE);
-
- /* And fill in the addresses. */
- struct plt0_entry *addr = (struct plt0_entry *) data->d_buf;
- addr->gotp4_addr = target_bswap_32 (gotaddr + 4);
- addr->gotp8_addr = target_bswap_32 (gotaddr + 8);
- }
-
- /* For DSOs we need GOT offsets, otherwise the GOT address. */
- Elf32_Addr gotaddr_off = build_dso ? 0 : gotaddr;
-
- /* Create the remaining entries. */
- const unsigned char *plt_template
- = build_dso ? elf_i386_pic_plt_entry : elf_i386_plt_entry;
-
- for (cnt = 0; cnt < statep->nplt; ++cnt)
- {
- struct plt_entry *addr;
-
- /* Copy the template. */
- assert (data->d_size >= (2 + cnt) * PLT_ENTRY_SIZE);
- addr = (struct plt_entry *) ((char *) data->d_buf
- + (1 + cnt) * PLT_ENTRY_SIZE);
- memcpy (addr, plt_template, PLT_ENTRY_SIZE);
-
- /* And once more, fill in the addresses. First the address of
- this symbol in .got. */
- addr->offset_got = target_bswap_32 (gotaddr_off
- + (3 + cnt) * sizeof (Elf32_Addr));
- /* Offset into relocation table. */
- addr->push_imm = target_bswap_32 (cnt * sizeof (Elf32_Rel));
- /* Offset to start of .plt. */
- addr->plt0_offset = target_bswap_32 (-(2 + cnt) * PLT_ENTRY_SIZE);
- }
-
- /* Create the .rel.plt section data. It simply means relocations
- addressing the corresponding entry in the .got section. The
- section name is misleading. */
- scn = elf_getscn (statep->outelf, statep->pltrelscnidx);
- xelf_getshdr (scn, shdr);
- data = elf_getdata (scn, NULL);
- assert (shdr != NULL && data != NULL);
-
- /* Update the sh_link to point to the section being modified. We
- point it here (correctly) to the .got section. Some linkers
- (e.g., the GNU binutils linker) point to the .plt section. This
- is wrong since the .plt section isn't modified even though the
- name .rel.plt suggests that this is correct. */
- shdr->sh_link = statep->dynsymscnidx;
- shdr->sh_info = statep->gotscnidx;
- (void) xelf_update_shdr (scn, shdr);
-
- for (cnt = 0; cnt < statep->nplt; ++cnt)
- {
- XElf_Rel_vardef (rel);
-
- assert ((1 + cnt) * sizeof (Elf32_Rel) <= data->d_size);
- xelf_getrel_ptr (data, cnt, rel);
- rel->r_offset = gotaddr + (3 + cnt) * sizeof (Elf32_Addr);
- /* The symbol table entries for the functions from DSOs are at
- the end of the symbol table. */
- rel->r_info = XELF_R_INFO (1 + cnt, R_386_JMP_SLOT);
- (void) xelf_update_rel (data, cnt, rel);
- }
-}
-
-
-static int
-elf_i386_rel_type (struct ld_state *statep __attribute__ ((__unused__)))
-{
- /* ELF/i386 uses REL. */
- return DT_REL;
-}
-
-
-static void
-elf_i386_count_relocations (struct ld_state *statep, struct scninfo *scninfo)
-{
- /* We go through the list of input sections and count those relocations
- which are not handled by the linker. At the same time we have to
- see how many GOT entries we need and how much .bss space is needed
- for copy relocations. */
- Elf_Data *data = elf_getdata (scninfo->scn, NULL);
- XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
- size_t maxcnt = shdr->sh_size / shdr->sh_entsize;
- size_t relsize = 0;
- size_t cnt;
- struct symbol *sym;
-
- assert (shdr->sh_type == SHT_REL);
-
- for (cnt = 0; cnt < maxcnt; ++cnt)
- {
- XElf_Rel_vardef (rel);
-
- xelf_getrel (data, cnt, rel);
- /* XXX Should we complain about failing accesses? */
- if (rel != NULL)
- {
- int r_sym = XELF_R_SYM (rel->r_info);
-
- switch (XELF_R_TYPE (rel->r_info))
- {
- case R_386_GOT32:
- if (! scninfo->fileinfo->symref[r_sym]->defined)
- relsize += sizeof (Elf32_Rel);
-
- /* This relocation is not emitted in the output file but
- requires a GOT entry. */
- ++statep->ngot;
- ++statep->nrel_got;
-
- /* FALLTHROUGH */
-
- case R_386_GOTOFF:
- case R_386_GOTPC:
- statep->need_got = true;
- break;
-
- case R_386_32:
- case R_386_PC32:
- /* These relocations cause text relocations in DSOs. */
- if (linked_from_dso_p (scninfo, r_sym))
- {
- if (statep->file_type == dso_file_type)
- {
- relsize += sizeof (Elf32_Rel);
- statep->dt_flags |= DF_TEXTREL;
- }
- else
- {
- /* Non-function objects from a DSO need to get a
- copy relocation. */
- sym = scninfo->fileinfo->symref[r_sym];
-
- /* Only do this if we have not requested a copy
- relocation already. */
- if (unlikely (sym->type != STT_FUNC) && ! sym->need_copy)
- {
- sym->need_copy = 1;
- ++statep->ncopy;
- relsize += sizeof (Elf32_Rel);
- }
- }
- }
- else if (statep->file_type == dso_file_type
- && r_sym >= SCNINFO_SHDR (scninfo->fileinfo->scninfo[shdr->sh_link].shdr).sh_info
- && scninfo->fileinfo->symref[r_sym]->outdynsymidx != 0
- && XELF_R_TYPE (rel->r_info) == R_386_32)
- relsize += sizeof (Elf32_Rel);
- break;
-
- case R_386_PLT32:
- /* We might need a PLT entry. But we cannot say for sure
- here since one of the symbols might turn up being
- defined in the executable (if we create such a thing).
- If a DSO is created we still might use a local
- definition.
-
- If the symbol is not defined and we are not creating
- a statically linked binary, then we need in any case
- a PLT entry. */
- if (! scninfo->fileinfo->symref[r_sym]->defined)
- {
- assert (!statep->statically);
-
- sym = scninfo->fileinfo->symref[r_sym];
- sym->type = STT_FUNC;
- sym->in_dso = 1;
- sym->defined = 1;
-
- /* Remove from the list of unresolved symbols. */
- --statep->nunresolved;
- if (! sym->weak)
- --statep->nunresolved_nonweak;
- CDBL_LIST_DEL (statep->unresolved, sym);
-
- /* Add to the list of symbols we expect from a DSO. */
- ++statep->nplt;
- ++statep->nfrom_dso;
- CDBL_LIST_ADD_REAR (statep->from_dso, sym);
- }
- break;
-
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- case R_386_TLS_GD_32:
- case R_386_TLS_GD_PUSH:
- case R_386_TLS_GD_CALL:
- case R_386_TLS_GD_POP:
- case R_386_TLS_LDM_32:
- case R_386_TLS_LDM_PUSH:
- case R_386_TLS_LDM_CALL:
- case R_386_TLS_LDM_POP:
- case R_386_TLS_LDO_32:
- case R_386_TLS_IE_32:
- case R_386_TLS_LE_32:
- /* XXX */
- abort ();
- break;
-
- case R_386_NONE:
- /* Nothing to be done. */
- break;
-
- /* These relocation should never be generated by an
- assembler. */
- case R_386_COPY:
- case R_386_GLOB_DAT:
- case R_386_JMP_SLOT:
- case R_386_RELATIVE:
- case R_386_TLS_DTPMOD32:
- case R_386_TLS_DTPOFF32:
- case R_386_TLS_TPOFF32:
- /* Unknown relocation. */
- default:
- abort ();
- }
- }
- }
-
- scninfo->relsize = relsize;
-}
-
-
-static void
-elf_i386_create_relocations (struct ld_state *statep,
- const Elf32_Word *dblindirect)
-{
- /* Get the address of the got section. */
- Elf_Scn *pltscn = elf_getscn (statep->outelf, statep->pltscnidx);
- Elf32_Shdr *shdr = elf32_getshdr (pltscn);
- assert (shdr != NULL);
- Elf32_Addr pltaddr = shdr->sh_addr;
-
- Elf_Scn *gotscn = elf_getscn (statep->outelf, statep->gotscnidx);
- shdr = elf32_getshdr (gotscn);
- assert (shdr != NULL);
- Elf32_Addr gotaddr = shdr->sh_addr;
-
- Elf_Scn *reldynscn = elf_getscn (statep->outelf, statep->reldynscnidx);
- Elf_Data *reldyndata = elf_getdata (reldynscn, NULL);
-
- size_t nreldyn = 0;
-#define ngot_used (3 + statep->nplt + nreldyn)
-
- struct scninfo *first = statep->rellist->next;
- struct scninfo *runp = first;
- do
- {
- XElf_Shdr *rshdr = &SCNINFO_SHDR (runp->shdr);
- Elf_Data *reldata = elf_getdata (runp->scn, NULL);
- int nrels = rshdr->sh_size / rshdr->sh_entsize;
-
- /* We will need the following vlaues a couple of times. Help
- the compiler and improve readability. */
- struct symbol **symref = runp->fileinfo->symref;
- struct scninfo *scninfo = runp->fileinfo->scninfo;
-
- /* This is the offset of the input section we are looking at in
- the output file. */
- XElf_Addr inscnoffset = scninfo[rshdr->sh_info].offset;
-
- /* The target section. We use the data from the input file. */
- Elf_Data *data = elf_getdata (scninfo[rshdr->sh_info].scn, NULL);
-
- /* We cannot handle relocations against merge-able sections. */
- assert ((SCNINFO_SHDR (scninfo[rshdr->sh_link].shdr).sh_flags
- & SHF_MERGE) == 0);
-
- /* Cache the access to the symbol table data. */
- Elf_Data *symdata = elf_getdata (scninfo[rshdr->sh_link].scn, NULL);
-
- int cnt;
- for (cnt = 0; cnt < nrels; ++cnt)
- {
- XElf_Rel_vardef (rel);
- XElf_Rel *rel2;
- xelf_getrel (reldata, cnt, rel);
- assert (rel != NULL);
- XElf_Addr reladdr = inscnoffset + rel->r_offset;
- XElf_Addr value;
-
- size_t idx = XELF_R_SYM (rel->r_info);
- if (idx < runp->fileinfo->nlocalsymbols)
- {
- XElf_Sym_vardef (sym);
- xelf_getsym (symdata, idx, sym);
-
- /* The value just depends on the position of the referenced
- section in the output file and the addend. */
- value = scninfo[sym->st_shndx].offset + sym->st_value;
- }
- else if (symref[idx]->in_dso)
- {
- /* MERGE.VALUE contains the PLT index. We have to add 1 since
- there is this one special PLT entry at the beginning. */
- assert (symref[idx]->merge.value != 0
- || symref[idx]->type != STT_FUNC);
- value = pltaddr + symref[idx]->merge.value * PLT_ENTRY_SIZE;
- }
- else
- value = symref[idx]->merge.value;
-
- /* Address of the relocated memory in the data buffer. */
- void *relloc = (char *) data->d_buf + rel->r_offset;
-
- switch (XELF_R_TYPE (rel->r_info))
- {
- /* These three cases can be handled together since the
- symbol associated with the R_386_GOTPC relocation is
- _GLOBAL_OFFSET_TABLE_ which has a value corresponding
- to the address of the GOT and the address of the PLT
- entry required for R_386_PLT32 is computed above. */
- case R_386_PC32:
- case R_386_GOTPC:
- case R_386_PLT32:
- value -= reladdr;
- /* FALLTHROUGH */
-
- case R_386_32:
- if (linked_from_dso_p (scninfo, idx)
- && statep->file_type != dso_file_type
- && symref[idx]->type != STT_FUNC)
- {
- value = (ld_state.copy_section->offset
- + symref[idx]->merge.value);
-
- if (unlikely (symref[idx]->need_copy))
- {
- /* Add a relocation to initialize the GOT entry. */
- assert (symref[idx]->outdynsymidx != 0);
-#if NATIVE_ELF != 0
- xelf_getrel_ptr (reldyndata, nreldyn, rel2);
-#else
- rel2 = &rel_mem;
-#endif
- rel2->r_offset = value;
- rel2->r_info
- = XELF_R_INFO (symref[idx]->outdynsymidx, R_386_COPY);
- (void) xelf_update_rel (reldyndata, nreldyn, rel2);
- ++nreldyn;
-
- /* Update the symbol table record for the new
- address. */
- Elf32_Word symidx = symref[idx]->outdynsymidx;
- Elf_Scn *symscn = elf_getscn (statep->outelf,
- statep->dynsymscnidx);
- Elf_Data *outsymdata = elf_getdata (symscn, NULL);
- assert (outsymdata != NULL);
- XElf_Sym_vardef (sym);
- xelf_getsym (outsymdata, symidx, sym);
- sym->st_value = value;
- sym->st_shndx = statep->copy_section->outscnndx;
- (void) xelf_update_sym (outsymdata, symidx, sym);
-
- symidx = symref[idx]->outsymidx;
- if (symidx != 0)
- {
- symidx = statep->dblindirect[symidx];
- symscn = elf_getscn (statep->outelf,
- statep->symscnidx);
- outsymdata = elf_getdata (symscn, NULL);
- assert (outsymdata != NULL);
- xelf_getsym (outsymdata, symidx, sym);
- sym->st_value = value;
- sym->st_shndx = statep->copy_section->outscnndx;
- (void) xelf_update_sym (outsymdata, symidx, sym);
- }
-
- /* Remember that we set up the copy relocation. */
- symref[idx]->need_copy = 0;
- }
- }
- else if (statep->file_type == dso_file_type
- && idx >= SCNINFO_SHDR (scninfo[rshdr->sh_link].shdr).sh_info
- && symref[idx]->outdynsymidx != 0)
- {
-#if NATIVE_ELF != 0
- xelf_getrel_ptr (reldyndata, nreldyn, rel2);
-#else
- rel2 = &rel_mem;
-#endif
- rel2->r_offset = value;
- rel2->r_info
- = XELF_R_INFO (symref[idx]->outdynsymidx, R_386_32);
- (void) xelf_update_rel (reldyndata, nreldyn, rel2);
- ++nreldyn;
-
- value = 0;
- }
- add_4ubyte_unaligned (relloc, value);
- break;
-
- case R_386_GOT32:
- store_4ubyte_unaligned (relloc, ngot_used * sizeof (Elf32_Addr));
-
- /* Add a relocation to initialize the GOT entry. */
-#if NATIVE_ELF != 0
- xelf_getrel_ptr (reldyndata, nreldyn, rel2);
-#else
- rel2 = &rel_mem;
-#endif
- rel2->r_offset = gotaddr + ngot_used * sizeof (Elf32_Addr);
- rel2->r_info
- = XELF_R_INFO (symref[idx]->outdynsymidx, R_386_GLOB_DAT);
- (void) xelf_update_rel (reldyndata, nreldyn, rel2);
- ++nreldyn;
- break;
-
- case R_386_GOTOFF:
- add_4ubyte_unaligned (relloc, value - gotaddr);
- break;
-
- case R_386_32PLT:
- case R_386_TLS_TPOFF:
- case R_386_TLS_IE:
- case R_386_TLS_GOTIE:
- case R_386_TLS_LE:
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- case R_386_16:
- case R_386_PC16:
- case R_386_8:
- case R_386_PC8:
- case R_386_TLS_GD_32:
- case R_386_TLS_GD_PUSH:
- case R_386_TLS_GD_CALL:
- case R_386_TLS_GD_POP:
- case R_386_TLS_LDM_32:
- case R_386_TLS_LDM_PUSH:
- case R_386_TLS_LDM_CALL:
- case R_386_TLS_LDM_POP:
- case R_386_TLS_LDO_32:
- case R_386_TLS_IE_32:
- case R_386_TLS_LE_32:
- // XXX For now fall through
- printf("ignored relocation %d\n", (int) XELF_R_TYPE (rel->r_info));
- break;
-
- case R_386_NONE:
- /* Nothing to do. */
- break;
-
- case R_386_COPY:
- case R_386_JMP_SLOT:
- case R_386_RELATIVE:
- case R_386_GLOB_DAT:
- case R_386_TLS_DTPMOD32:
- case R_386_TLS_DTPOFF32:
- case R_386_TLS_TPOFF32:
- default:
- /* Should not happen. */
- abort ();
- }
- }
- }
- while ((runp = runp->next) != first);
-}
-
-
-int
-elf_i386_ld_init (struct ld_state *statep)
-{
- /* We have a few callbacks available. */
- old_open_outfile = statep->callbacks.open_outfile;
- statep->callbacks.open_outfile = elf_i386_open_outfile;
-
- statep->callbacks.relocate_section = elf_i386_relocate_section;
-
- statep->callbacks.initialize_plt = elf_i386_initialize_plt;
- statep->callbacks.initialize_pltrel = elf_i386_initialize_pltrel;
-
- statep->callbacks.initialize_got = elf_i386_initialize_got;
-
- statep->callbacks.finalize_plt = elf_i386_finalize_plt;
-
- statep->callbacks.rel_type = elf_i386_rel_type;
-
- statep->callbacks.count_relocations = elf_i386_count_relocations;
-
- statep->callbacks.create_relocations = elf_i386_create_relocations;
-
- return 0;
-}
diff --git a/src/ld.c b/src/ld.c
deleted file mode 100644
index a6b664f7..00000000
--- a/src/ld.c
+++ /dev/null
@@ -1,1520 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <assert.h>
-#include <error.h>
-#include <fcntl.h>
-#include <libelf.h>
-#include <libintl.h>
-#include <locale.h>
-#include <mcheck.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <system.h>
-#include "ld.h"
-#include "list.h"
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-
-/* Values for the various options. */
-enum
- {
- ARGP_whole_archive = 300,
- ARGP_no_whole_archive,
- ARGP_static,
- ARGP_dynamic,
- ARGP_pagesize,
- ARGP_rpath,
- ARGP_rpath_link,
- ARGP_runpath,
- ARGP_runpath_link,
- ARGP_version_script,
- ARGP_gc_sections,
- ARGP_no_gc_sections,
- ARGP_no_undefined,
- ARGP_conserve,
-#if YYDEBUG
- ARGP_yydebug,
-#endif
- };
-
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- /* XXX This list will be reordered and section names will be added.
- Just not right now. */
- { "whole-archive", ARGP_whole_archive, NULL, 0,
- N_("Include whole archives in the output from now on.") },
- { "no-whole-archive", ARGP_no_whole_archive, NULL, 0,
- N_("Stop including the whole arhives in the output.") },
-
- { "output", 'o', N_("FILE"), 0, N_("Place output in FILE.") },
-
- { NULL, 'O', N_("LEVEL"), OPTION_ARG_OPTIONAL,
- N_("Set optimization level to LEVEL.") },
-
- { "verbose", 'v', NULL, 0, N_("Verbose messages.") },
- { "trace", 't', NULL, 0, N_("Trace file opens.") },
- { "conserve-memory", ARGP_conserve, NULL, 0,
- N_("Trade speed for less memory usage") },
-
- { NULL, 'z', "KEYWORD", OPTION_HIDDEN, NULL },
- { "-z nodefaultlib", '\0', NULL, OPTION_DOC,
- N_("Object is marked to not use default search path at runtime.") },
- { "-z allextract", '\0', NULL, OPTION_DOC,
- N_("Same as --whole-archive.") },
- { "-z defaultextract", '\0', NULL, OPTION_DOC, N_("\
-Default rules of extracting from archive; weak references are not enough.") },
- { "-z weakextract", '\0', NULL, OPTION_DOC,
- N_("Weak references cause extraction from archive.") },
- { "-z muldefs", '\0', NULL, OPTION_DOC,
- N_("Allow multiple definitions; first is used.") },
- { "-z defs | nodefs", '\0', NULL, OPTION_DOC,
- N_("Disallow/allow undefined symbols in DSOs.") },
- { "no-undefined", ARGP_no_undefined, NULL, OPTION_HIDDEN, NULL },
- { "-z origin", '\0', NULL, OPTION_DOC,
- N_("Object requires immediate handling of $ORIGIN.") },
- { "-z now", '\0', NULL, OPTION_DOC,
- N_("Relocation will not be processed lazily.") },
- { "-z nodelete", '\0', NULL, OPTION_DOC,
- N_("Object cannot be unloaded at runtime.") },
- { "-z initfirst", '\0', NULL, OPTION_DOC,
- N_("Mark object to be initialized first.") },
- { "-z lazyload | nolazyload", '\0', NULL, OPTION_DOC,
- N_("Enable/disable lazy-loading flag for following dependencies.") },
- { "-z nodlopen", '\0', NULL, OPTION_DOC,
- N_("Mark object as not loadable with 'dlopen'.") },
- { "-z ignore | record", '\0', NULL, OPTION_DOC,
- N_("Ignore/record dependencies on unused DSOs.") },
- { "-z systemlibrary", '\0', NULL, OPTION_DOC,
- N_("Generated DSO will be a system library.") },
-
- { NULL, 'l', N_("FILE"), OPTION_HIDDEN, NULL },
-
- { NULL, '(', NULL, 0, N_("Start a group.") },
- { NULL, ')', NULL, 0, N_("End a group.") },
-
- { NULL, 'L', N_("PATH"), 0,
- N_("Add PATH to list of directories files are searched in.") },
-
- { NULL, 'c', N_("FILE"), 0, N_("Use linker script in FILE.") },
-
- { "entry", 'e', N_("ADDRESS"), 0, N_("Set entry point address.") },
-
- { "static", ARGP_static, NULL, OPTION_HIDDEN, NULL },
- { "-B static", ARGP_static, NULL, OPTION_DOC,
- N_("Do not link against shared libraries.") },
- { "dynamic", ARGP_dynamic, NULL, OPTION_HIDDEN, NULL },
- { "-B dynamic", ARGP_dynamic, NULL, OPTION_DOC,
- N_("Prefer linking against shared libraries.") },
-
- { "export-dynamic", 'E', NULL, 0, N_("Export all dynamic symbols.") },
-
- { "strip-all", 's', NULL, 0, N_("Strip all symbols.") },
- { "strip-debug", 'S', NULL, 0, N_("Strip debugging symbols.") },
-
- { "pagesize", ARGP_pagesize, "SIZE", 0,
- N_("Assume pagesize for the target system to be SIZE.") },
-
- { "rpath", ARGP_rpath, "PATH", OPTION_HIDDEN, NULL },
- { "rpath-link", ARGP_rpath_link, "PATH", OPTION_HIDDEN, NULL },
-
- { "runpath", ARGP_runpath, "PATH", 0, N_("Set runtime DSO search path.") },
- { "runpath-link", ARGP_runpath_link, "PATH", 0,
- N_("Set link time DSO search path.") },
-
- { NULL, 'i', NULL, 0, N_("Ignore LD_LIBRARY_PATH environment variable.") },
-
- { "version-script", ARGP_version_script, "FILE", 0,
- N_("Read version information from FILE.") },
-
- { "emulation", 'm', "NAME", 0, N_("Set emulation to NAME.") },
-
- { "shared", 'G', NULL, 0, N_("Generate dynamic shared object.") },
- { NULL, 'r', NULL, 0L, N_("Generate relocatable object.") },
-
- { NULL, 'B', "KEYWORD", OPTION_HIDDEN, "" },
- { "-B local", 'B', NULL, OPTION_DOC,
- N_("Causes symbol not assigned to a version be reduced to local.") },
-
- { "gc-sections", ARGP_gc_sections, NULL, 0, N_("Remove unused sections.") },
- { "no-gc-sections", ARGP_no_gc_sections, NULL, 0,
- N_("Don't remove unused sections.") },
-
- { "soname", 'h', "NAME", 0, N_("Set soname of shared object.") },
- { "dynamic-linker", 'I', "NAME", 0, N_("Set the dynamic linker name.") },
-
- { NULL, 'Q', "YN", OPTION_HIDDEN, NULL },
- { "-Q y | n", 'Q', NULL, OPTION_DOC,
- N_("Add/suppress addition indentifying link-editor to .comment section") },
-
-#if YYDEBUG
- { "yydebug", ARGP_yydebug, NULL, 0,
- N_("Select to get parser debug information") },
-#endif
-
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("Combine object and archive files.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("[FILE]...");
-
-/* Prototype for option handler. */
-static error_t parse_opt_1st (int key, char *arg, struct argp_state *state);
-static error_t parse_opt_2nd (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp_1st =
-{
- options, parse_opt_1st, args_doc, doc, NULL, more_help
-};
-static struct argp argp_2nd =
-{
- options, parse_opt_2nd, args_doc, doc, NULL, more_help
-};
-
-
-/* Linker state. This contains all global information. */
-struct ld_state ld_state;
-
-/* List of the input files. */
-static struct file_list
-{
- const char *name;
- struct file_list *next;
-} *input_file_list;
-
-/* If nonzero be verbose. */
-int verbose;
-
-/* If nonzero, trade speed for less memory/address space usage. */
-int conserve_memory;
-
-/* The emulation name to use. */
-static const char *emulation;
-
-/* Keep track of the nesting level. Even though we don't handle nested
- groups we still keep track to improve the error messages. */
-static int group_level;
-
-/* The last file we processed. */
-static struct usedfiles *last_file;
-
-/* The default linker script. */
-/* XXX We'll do this a bit different in the real solution. */
-static const char *linker_script = SRCDIR "/elf32-i386.script";
-
-/* Nonzero if an error occurred while loading the input files. */
-static int error_loading;
-
-
-/* Intermediate storage for the LD_LIBRARY_PATH information from the
- environment. */
-static char *ld_library_path1;
-
-/* Flag used to communicate with the scanner. */
-int ld_scan_version_script;
-
-/* Name of the input file. */
-const char *ldin_fname;
-
-/* Define by parser if required. */
-extern int lddebug;
-
-
-/* Prototypes for local functions. */
-static void parse_z_option (const char *arg);
-static void parse_z_option_2 (const char *arg);
-static void parse_B_option (const char *arg);
-static void parse_B_option_2 (const char *arg);
-static void determine_output_format (void);
-static void load_needed (void);
-static void collect_sections (void);
-static void add_rxxpath (struct pathelement **pathp, const char *str);
-static void gen_rxxpath_data (void);
-static void read_version_script (const char *fname);
-static void create_lscript_symbols (void);
-static void create_special_section_symbol (struct symbol **symp,
- const char *name);
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- int err;
-
-#ifndef NDEBUG
- /* Enable memory debugging. */
- mtrace ();
-#endif
-
- /* Sanity check. We always want to use the LFS functionality. */
- if (sizeof (off_t) != sizeof (off64_t))
- abort ();
-
- /* We use no threads here which can interfere with handling a stream. */
- __fsetlocking (stdin, FSETLOCKING_BYCALLER);
- __fsetlocking (stdout, FSETLOCKING_BYCALLER);
- __fsetlocking (stderr, FSETLOCKING_BYCALLER);
-
- /* Set locale. */
- setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- bindtextdomain (PACKAGE, LOCALEDIR);
-
- /* Initialize the message catalog. */
- textdomain (PACKAGE);
-
- /* Before we start tell the ELF library which version we are using. */
- elf_version (EV_CURRENT);
-
- /* The user can use the LD_LIBRARY_PATH environment variable to add
- additional lookup directories. */
- ld_library_path1 = getenv ("LD_LIBRARY_PATH");
-
- /* Initialize the memory handling. */
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
- obstack_init (&ld_state.smem);
-
- /* One quick pass over the parameters which allows us to scan for options
- with global effect which influence the rest of the processing. */
- argp_parse (&argp_1st, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
-
- /* We need at least one input file. */
- if (input_file_list == NULL)
- {
- error (0, 0, gettext ("At least one input file needed"));
- argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
- exit (EXIT_FAILURE);
- }
-
- /* Determine which ELF backend to use. */
- determine_output_format ();
-
- /* Prepare state. */
- err = ld_prepare_state (emulation);
- if (err != 0)
- error (EXIT_FAILURE, 0, gettext ("error while preparing linking"));
-
- /* XXX Read the linker script now. Since we later will have the linker
- script built in we don't go into trouble to make sure we handle GROUP
- statements in the script. This simply must not happen. */
- ldin = fopen (linker_script, "r");
- if (ldin == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot open linker script \"%s\""),
- linker_script);
- /* No need for locking. */
- __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
- ld_state.srcfiles = NULL;
- ldlineno = 1;
- ld_scan_version_script = 0;
- ldin_fname = linker_script;
- if (ldparse () != 0)
- /* Something went wrong during parsing. */
- exit (EXIT_FAILURE);
- fclose (ldin);
-
- /* We now might have a list of directories to look for libraries in
- named by the linker script. Put them in a different list so that
- they are searched after all paths given by the user on the
- command line. */
- ld_state.default_paths = ld_state.paths;
- ld_state.paths = ld_state.tailpaths = NULL;
-
- /* Get runpath/rpath information in usable form. */
- gen_rxxpath_data ();
-
- /* Parse and process arguments for real. */
- argp_parse (&argp_2nd, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
- /* All options should have been processed by the argp parser. */
- assert (remaining == argc);
-
- /* Process the last file. */
- while (last_file != NULL)
- /* Try to open the file. */
- error_loading |= FILE_PROCESS (-1, last_file, &ld_state, &last_file);
-
- /* Stop if there has been a problem while reading the input files. */
- if (error_loading)
- exit (error_loading);
-
- /* See whether all opened -( were closed. */
- if (group_level > 0)
- {
- error (0, 0, gettext ("-( without matching -)"));
- argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
- exit (EXIT_FAILURE);
- }
-
- /* When we create a relocatable file we don't have to look for the
- DT_NEEDED DSOs and we also don't test for undefined symbols. */
- if (ld_state.file_type != relocatable_file_type)
- {
- /* At this point we have loaded all the direct dependencies. What
- remains to be done is find the indirect dependencies. These are
- DSOs which are referenced by the DT_NEEDED entries in the DSOs
- which are direct dependencies. We have to transitively find and
- load all these dependencies. */
- load_needed ();
-
- /* At this point all object files and DSOs are read. If there
- are still undefined symbols left they might have to be
- synthesized from the linker script. */
- create_lscript_symbols ();
-
- /* Now that we have loaded all the object files we can determine
- whether we have any non-weak unresolved references left. If
- there are any we stop. If the user used the '-z nodefs' option
- and we are creating a DSO don't perform the tests. */
- if (FLAG_UNRESOLVED (&ld_state) != 0)
- exit (1);
- }
-
- /* Collect information about the relocations which will be carried
- forward into the output. We have to do this here and now since
- we need to know which sections have to be created. */
- if (ld_state.file_type != relocatable_file_type)
- {
- void *p ;
- struct scnhead *h;
-
- p = NULL;
- while ((h = ld_section_tab_iterate (&ld_state.section_tab, &p)) != NULL)
- if (h->type == SHT_REL || h->type == SHT_RELA)
- {
- struct scninfo *runp = h->last;
- do
- {
- /* If we are processing the relocations determine how
- many will be in the output file. Also determine
- how many GOT entries are needed. */
- COUNT_RELOCATIONS (&ld_state, runp);
-
- ld_state.relsize_total += runp->relsize;
- }
- while ((runp = runp->next) != h->last);
- }
- }
-
- /* Not part of the gABI, but part of every psABI: the symbols for the
- GOT section. Add the symbol if necessary. */
- if (ld_state.need_got)
- create_special_section_symbol (&ld_state.got_symbol,
- "_GLOBAL_OFFSET_TABLE_");
- /* Similarly for the _DYNAMIC symbol which points to the dynamic
- section. */
- if (dynamically_linked_p ())
- create_special_section_symbol (&ld_state.dyn_symbol, "_DYNAMIC");
-
- /* We are ready to start working on the output file. Not all
- information has been gather or created yet. This will be done as
- we go. Open the file now. */
- if (OPEN_OUTFILE (&ld_state, EM_NONE, ELFCLASSNONE, ELFDATANONE) != 0)
- exit (1);
-
- /* Create the sections which are generated by the linker and are not
- present in the input file. The output file must already have
- been opened since we need the ELF descriptor to deduce type
- sizes. */
- GENERATE_SECTIONS (&ld_state);
-
- /* At this point we have read all the files and know all the
- sections which have to be linked into the application. We do now
- create an array listing all the sections. We will than pass this
- array to a system specific function which can reorder it at will.
- The functions can also merge sections if this is what is
- wanted. */
- collect_sections ();
-
- /* Create the output sections now. This may requires sorting them
- first. */
- CREATE_SECTIONS (&ld_state);
-
- /* Create the output file data. Appropriate code for the selected
- output file type is called. */
- if (CREATE_OUTFILE (&ld_state) != 0)
- exit (1);
-
- /* Finalize the output file, write the data out. */
- err |= FINALIZE (&ld_state);
-
- /* Return with an non-zero exit status also if any error message has
- been printed. */
- return err | (error_message_count != 0);
-}
-
-
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-/* Quick scan of the parameter list for options with global effect. */
-static error_t
-parse_opt_1st (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'B':
- parse_B_option (arg);
- break;
-
- case 'c':
- linker_script = arg;
- break;
-
- case 'E':
- ld_state.export_all_dynamic = true;
- break;
-
- case 'G':
- if (ld_state.file_type != no_file_type)
- error (EXIT_FAILURE, 0,
- gettext ("only one option of -G and -r is allowed"));
- ld_state.file_type = dso_file_type;
-
- /* If we generate a DSO we have to export all symbols. */
- ld_state.export_all_dynamic = true;
- break;
-
- case 'h':
- ld_state.soname = arg;
- break;
-
- case 'i':
- /* Discard the LD_LIBRARY_PATH value we found. */
- ld_library_path1 = NULL;
- break;
-
- case 'I':
- ld_state.interp = arg;
- break;
-
- case 'm':
- if (emulation != NULL)
- error (EXIT_FAILURE, 0, gettext ("more than one '-m' parameter"));
- emulation = arg;
- break;
-
- case 'Q':
- if (arg[1] == '\0' && (arg[0] == 'y' || arg[0] == 'Y'))
- ld_state.add_ld_comment = true;
- else if (arg[1] == '\0' && (arg[0] == 'n' || arg[0] == 'N'))
- ld_state.add_ld_comment = true;
- else
- error (EXIT_FAILURE, 0, gettext ("unknown option `-%c %s'"), 'Q', arg);
- break;
-
- case 'r':
- if (ld_state.file_type != no_file_type)
- error (EXIT_FAILURE, 0,
- gettext ("only one option of -G and -r is allowed"));
- ld_state.file_type = relocatable_file_type;
- break;
-
- case 'S':
- ld_state.strip = strip_debug;
- break;
-
- case 't':
- ld_state.trace_files = true;
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- case 'z':
- /* The SysV linker used 'z' to pass various flags to the linker.
- We follow this. See 'parse_z_option' for the options we
- recognize. */
- parse_z_option (arg);
- break;
-
- case ARGP_pagesize:
- {
- char *endp;
- ld_state.pagesize = strtoul (arg, &endp, 0);
- if (*endp != '\0')
- {
- if (endp[1] == '\0' && tolower (*endp) == 'k')
- ld_state.pagesize *= 1024;
- else if (endp[1] == '\0' && tolower (*endp) == 'm')
- ld_state.pagesize *= 1024 * 1024;
- else
- {
- error (0, 0,
- gettext ("invalid page size value \"%s\": ignored"),
- arg);
- ld_state.pagesize = 0;
- }
- }
- }
- break;
-
- case ARGP_rpath:
- add_rxxpath (&ld_state.rpath, arg);
- break;
-
- case ARGP_rpath_link:
- add_rxxpath (&ld_state.rpath_link, arg);
- break;
-
- case ARGP_runpath:
- add_rxxpath (&ld_state.runpath, arg);
- break;
-
- case ARGP_runpath_link:
- add_rxxpath (&ld_state.runpath_link, arg);
- break;
-
- case ARGP_gc_sections:
- case ARGP_no_gc_sections:
- ld_state.gc_sections = key == ARGP_gc_sections;
- break;
-
- case 's':
- if (arg == NULL)
- {
- if (ld_state.strip == strip_all)
- ld_state.strip = strip_everything;
- else
- ld_state.strip = strip_all;
- break;
- }
- /* FALLTHROUGH */
-
- case 'e':
- case 'o':
- case 'O':
- case ARGP_whole_archive:
- case ARGP_no_whole_archive:
- case 'L':
- case '(':
- case ')':
- case 'l':
- case ARGP_static:
- case ARGP_dynamic:
- case ARGP_version_script:
- /* We'll handle these in the second pass. */
- break;
-
- case ARGP_KEY_ARG:
- {
- struct file_list *newp;
-
- newp = (struct file_list *) xmalloc (sizeof (struct file_list));
- newp->name = arg;
-#ifndef NDEBUG
- newp->next = NULL;
-#endif
- CSNGL_LIST_ADD_REAR (input_file_list, newp);
- }
- break;
-
-#if YYDEBUG
- case ARGP_yydebug:
- lddebug = 1;
- break;
-#endif
-
- case ARGP_no_undefined:
- ld_state.nodefs = false;
- break;
-
- case ARGP_conserve:
- conserve_memory = 1;
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-/* Handle program arguments for real. */
-static error_t
-parse_opt_2nd (int key, char *arg, struct argp_state *state)
-{
- static bool group_start_requested;
- static bool group_end_requested;
-
- switch (key)
- {
- case 'B':
- parse_B_option_2 (arg);
- break;
-
- case 'e':
- ld_state.entry = arg;
- break;
-
- case 'o':
- if (ld_state.outfname != NULL)
- {
- error (0, 0, gettext ("More than one output file name given."));
- see_help:
- argp_help (&argp_2nd, stderr, ARGP_HELP_SEE, "ld");
- exit (EXIT_FAILURE);
- }
- ld_state.outfname = arg;
- break;
-
- case 'O':
- if (arg == NULL)
- ld_state.optlevel = 1;
- else
- {
- char *endp;
- unsigned long int level = strtoul (arg, &endp, 10);
- if (*endp != '\0')
- {
- error (0, 0, gettext ("Invalid optimization level `%s'"), arg);
- goto see_help;
- }
- ld_state.optlevel = level;
- }
- break;
-
- case ARGP_whole_archive:
- ld_state.extract_rule = allextract;
- break;
- case ARGP_no_whole_archive:
- ld_state.extract_rule = defaultextract;
- break;
-
- case ARGP_static:
- case ARGP_dynamic:
- /* Enable/disable use for DSOs. */
- ld_state.statically = key == ARGP_static;
- break;
-
- case 'z':
- /* The SysV linker used 'z' to pass various flags to the linker.
- We follow this. See 'parse_z_option' for the options we
- recognize. */
- parse_z_option_2 (arg);
- break;
-
- case ARGP_version_script:
- read_version_script (arg);
- break;
-
- case 'L':
- /* Add a new search directory. */
- ld_new_searchdir (arg);
- break;
-
- case '(':
- /* Start a link group. We have to be able to determine the object
- file which is named next. Do this by remembering a pointer to
- the pointer which will point to the next object. */
- if (verbose && (group_start_requested || !group_end_requested))
- error (0, 0, gettext ("nested -( -) groups are not allowed"));
-
- /* Increment the nesting level. */
- ++group_level;
-
- /* Record group start. */
- group_start_requested = true;
- group_end_requested = false;
- break;
-
- case ')':
- /* End a link group. If there is no group open this is clearly
- a bug. If there is a group open insert a back reference
- pointer in the record for the last object of the group. If
- there is no new object or just one don't do anything. */
- if (!group_end_requested)
- {
- if (group_level == 0)
- {
- error (0, 0, gettext ("-) without matching -("));
- goto see_help;
- }
- }
- else
- last_file->group_end = true;
-
- if (group_level > 0)
- --group_level;
- break;
-
- case 'l':
- case ARGP_KEY_ARG:
- {
- while (last_file != NULL)
- /* Try to open the file. */
- error_loading |= FILE_PROCESS (-1, last_file, &ld_state, &last_file);
-
- last_file = ld_new_inputfile (arg,
- key == 'l'
- ? archive_file_type
- : relocatable_file_type);
- if (group_start_requested)
- {
- last_file->group_start = true;
-
- group_start_requested = false;
- group_end_requested = true;
- }
- }
- break;
-
- default:
- /* We can catch all other options here. They either have
- already been handled or, if the parameter was not correct,
- the error has been reported. */
- break;
- }
- return 0;
-}
-
-
-/* Load all the DSOs named as dependencies in other DSOs we already
- loaded. */
-static void
-load_needed (void)
-{
- struct usedfiles *first;
- struct usedfiles *runp;
-
- /* XXX There is one problem here: do we allow references from
- regular object files to be satisfied by these implicit
- dependencies? The old linker allows this and several libraries
- depend on this. Solaris' linker does not allow this; it provides
- the user with a comprehensive error message explaining the
- situation.
-
- XXX IMO the old ld behavior is correct since this is also how the
- dynamic linker will work. It will look for unresolved references
- in all loaded DSOs.
-
- XXX Should we add an option to get Solaris compatibility? */
- if (ld_state.needed == NULL)
- return;
-
- runp = first = ld_state.needed->next;
- do
- {
- struct usedfiles *ignore;
- struct usedfiles *next = runp->next;
- int err;
-
- err = FILE_PROCESS (-1, runp, &ld_state, &ignore);
- if (err != 0)
- /* Something went wrong. */
- exit (err);
-
- runp = next;
- }
- while (runp != first);
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "ld (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* There are a lot of -z options, parse them here. Some of them have
- to be parsed in the first pass, others must be handled in the
- second pass. */
-static void
-parse_z_option (const char *arg)
-{
- if (strcmp (arg, "nodefaultlib") == 0
- /* This is only meaningful if we create a DSO. */
- && ld_state.file_type == dso_file_type)
- ld_state.dt_flags_1 |= DF_1_NODEFLIB;
- else if (strcmp (arg, "muldefs") == 0)
- ld_state.muldefs = true;
- else if (strcmp (arg, "nodefs") == 0)
- ld_state.nodefs = true;
- else if (strcmp (arg, "defs") == 0)
- ld_state.nodefs = false;
- else if (strcmp (arg, "now") == 0)
- /* We could also set the DF_1_NOW flag in DT_FLAGS_1 but this isn't
- necessary. */
- ld_state.dt_flags |= DF_BIND_NOW;
- else if (strcmp (arg, "origin") == 0)
- /* We could also set the DF_1_ORIGIN flag in DT_FLAGS_1 but this isn't
- necessary. */
- ld_state.dt_flags |= DF_ORIGIN;
- else if (strcmp (arg, "nodelete") == 0
- /* This is only meaningful if we create a DSO. */
- && ld_state.file_type == dso_file_type)
- ld_state.dt_flags_1 |= DF_1_NODELETE;
- else if (strcmp (arg, "initfirst") == 0)
- ld_state.dt_flags_1 |= DF_1_INITFIRST;
- else if (strcmp (arg, "nodlopen") == 0
- /* This is only meaningful if we create a DSO. */
- && ld_state.file_type == dso_file_type)
- ld_state.dt_flags_1 |= DF_1_NOOPEN;
- else if (strcmp (arg, "ignore") == 0)
- ld_state.ignore_unused_dsos = true;
- else if (strcmp (arg, "record") == 0)
- ld_state.ignore_unused_dsos = false;
- else if (strcmp (arg, "systemlibrary") == 0)
- ld_state.is_system_library = true;
- else if (strcmp (arg, "allextract") != 0
- && strcmp (arg, "defaultextract") != 0
- && strcmp (arg, "weakextract") != 0
- && strcmp (arg, "lazyload") != 0
- && strcmp (arg, "nolazyload") != 0)
- error (0, 0, gettext ("unknown option `-%c %s'"), 'z', arg);
-}
-
-
-static void
-parse_z_option_2 (const char *arg)
-{
- if (strcmp (arg, "allextract") == 0)
- ld_state.extract_rule = allextract;
- else if (strcmp (arg, "defaultextract") == 0)
- ld_state.extract_rule = defaultextract;
- else if (strcmp (arg, "weakextract") == 0)
- ld_state.extract_rule = weakextract;
- else if (strcmp (arg, "lazyload") == 0)
- ld_state.lazyload = true;
- else if (strcmp (arg, "nolazyload") == 0)
- ld_state.lazyload = false;
-}
-
-
-/* There are a lot of -B options, parse them here. */
-static void
-parse_B_option (const char *arg)
-{
- if (strcmp (arg, "local") == 0)
- ld_state.default_bind_local = true;
- else if (strcmp (arg, "symbolic") != 0
- && strcmp (arg, "static") != 0
- && strcmp (arg, "dynamic") != 0)
- error (0, 0, gettext ("unknown option '-%c %s'"), 'B', arg);
-}
-
-
-/* The same functionality, but called in the second pass over the
- parameters. */
-static void
-parse_B_option_2 (const char *arg)
-{
- if (strcmp (arg, "static") == 0)
- ld_state.statically = true;
- else if (strcmp (arg, "dynamic") == 0)
- ld_state.statically = false;
- else if (strcmp (arg, "symbolic") == 0
- /* This is only meaningful if we create a DSO. */
- && ld_state.file_type == dso_file_type)
- ld_state.dt_flags |= DF_SYMBOLIC;
-}
-
-
-static void
-determine_output_format (void)
-{
- /* First change the 'input_file_list' variable in a simple
- single-linked list. */
- struct file_list *last = input_file_list;
- input_file_list = input_file_list->next;
- last->next = NULL;
-
- /* Determine the target configuration which we are supposed to use.
- The user can use the '-m' option to select one. If this is
- missing we are trying to load one file and determine the
- architecture from that. */
- if (emulation != NULL)
- {
- ld_state.ebl = ebl_openbackend_emulation (emulation);
-
- assert (ld_state.ebl != NULL);
- }
- else
- {
- /* Find an ELF input file and let it determine the ELf backend. */
- struct file_list *runp = input_file_list;
-
- while (runp != NULL)
- {
- int fd = open (runp->name, O_RDONLY);
- if (fd != -1)
- {
- int try (Elf *elf)
- {
- int result = 0;
-
- if (elf == NULL)
- return 0;
-
- if (elf_kind (elf) == ELF_K_ELF)
- {
- /* We have an ELF file. We now can find out
- what the output format should be. */
- XElf_Ehdr_vardef(ehdr);
-
- /* Get the ELF header of the object. */
- xelf_getehdr (elf, ehdr);
- if (ehdr != NULL)
- ld_state.ebl =
- ebl_openbackend_machine (ehdr->e_machine);
-
- result = 1;
- }
- else if (elf_kind (elf) == ELF_K_AR)
- {
- /* Try the archive members. This could
- potentially lead to wrong results if the
- archive contains files for more than one
- architecture. But this is the user's
- problem. */
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
-
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- cmd = elf_next (subelf);
-
- if (try (subelf) != 0)
- break;
- }
- }
-
- elf_end (elf);
-
- return result;
- }
-
- if (try (elf_begin (fd, ELF_C_READ_MMAP, NULL)) != 0)
- /* Found a file. */
- break;
- }
-
- runp = runp->next;
- }
-
- if (ld_state.ebl == NULL)
- {
- error (0, 0, gettext ("\
-could not find input file to determine output file format"));
- error (EXIT_FAILURE, 0, gettext ("\
-try again with an appropriate '-m' parameter"));
- }
- }
-
- /* We don't need the list of input files anymore. The second run over
- the parameters will handle them. */
- while (input_file_list != NULL)
- {
- struct file_list *oldp = input_file_list;
- input_file_list = input_file_list->next;
- free (oldp);
- }
-
- /* We also know now what kind of file we are supposed to create. If
- the user hasn't selected anythign we create and executable. */
- if (ld_state.file_type == no_file_type)
- ld_state.file_type = executable_file_type;
-}
-
-/* Add DIR to the list of directories searched for object files and
- libraries. */
-void
-ld_new_searchdir (const char *dir)
-{
- struct pathelement *newpath;
-
- newpath = (struct pathelement *)
- obstack_calloc (&ld_state.smem, sizeof (struct pathelement));
-
- newpath->pname = dir;
-
- /* Enqueue the file. */
- if (ld_state.tailpaths == NULL)
- ld_state.paths = ld_state.tailpaths = newpath;
- else
- {
- ld_state.tailpaths->next = newpath;
- ld_state.tailpaths = newpath;
- }
-}
-
-
-struct usedfiles *
-ld_new_inputfile (const char *fname, enum file_type type)
-{
- struct usedfiles *newfile = (struct usedfiles *)
- obstack_calloc (&ld_state.smem, sizeof (struct usedfiles));
-
- newfile->soname = newfile->fname = newfile->rfname = fname;
- newfile->file_type = type;
- newfile->extract_rule = ld_state.extract_rule;
- newfile->lazyload = ld_state.lazyload;
- newfile->status = not_opened;
-
- return newfile;
-}
-
-
-/* Create an array listing all the sections. We will than pass this
- array to a system specific function which can reorder it at will.
- The functions can also merge sections if this is what is
- wanted. */
-static void
-collect_sections (void)
-{
- void *p ;
- struct scnhead *h;
- size_t cnt;
-
- /* We have that many sections. At least for now. */
- ld_state.nallsections = ld_state.section_tab.filled;
-
- /* Allocate the array. We allocate one more entry than computed so
- far since we might need a new section for the copy relocations. */
- ld_state.allsections =
- (struct scnhead **) obstack_alloc (&ld_state.smem,
- (ld_state.nallsections + 1)
- * sizeof (struct scnhead *));
-
- /* Fill the array. We rely here on the hash table iterator to
- return the entries in the order they were added. */
- cnt = 0;
- p = NULL;
- while ((h = ld_section_tab_iterate (&ld_state.section_tab, &p)) != NULL)
- {
- struct scninfo *runp;
- bool used = false;
-
- if (h->kind == scn_normal)
- {
- runp = h->last;
- do
- {
- if (h->type == SHT_REL || h->type == SHT_RELA)
- {
- if (runp->used)
- /* This is a relocation section. If the section
- it is relocating is used in the result so must
- the relocation section. */
- runp->used
- = runp->fileinfo->scninfo[SCNINFO_SHDR (runp->shdr).sh_info].used;
- }
-
- /* Accumulate the result. */
- used |= runp->used;
-
- /* Next input section. */
- runp = runp->next;
- }
- while (runp != h->last);
-
- h->used = used;
- }
-
- ld_state.allsections[cnt++] = h;
- }
- ld_state.nusedsections = cnt;
-
- assert (cnt == ld_state.nallsections);
-}
-
-
-/* Add given path to the end of list. */
-static void
-add_rxxpath (struct pathelement **pathp, const char *str)
-{
- struct pathelement *newp;
-
- /* The path elements can in theory be freed after we read all the
- files. But the amount of memory we are talking about is small
- and the cost of free() calls is not neglectable. */
- newp = (struct pathelement *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- newp->pname = str;
- newp->exist = 0;
-#ifndef NDEBUG
- newp->next = NULL;
-#endif
-
- CSNGL_LIST_ADD_REAR (*pathp, newp);
-}
-
-
-/* Convert lists of possibly colon-separated directory lists into lists
- where each entry is for a single directory. */
-static void
-normalize_dirlist (struct pathelement **pathp)
-{
- struct pathelement *firstp = *pathp;
-
- do
- {
- const char *pname = (*pathp)->pname;
- const char *colonp = strchrnul (pname, ':');
-
- if (colonp != NULL)
- {
- struct pathelement *lastp = *pathp;
- struct pathelement *newp;
-
- while (1)
- {
- if (colonp == pname)
- lastp->pname = ".";
- else
- lastp->pname = obstack_strndup (&ld_state.smem, pname,
- colonp - pname);
-
- if (*colonp == '\0')
- break;
- pname = colonp + 1;
-
- newp = (struct pathelement *) obstack_alloc (&ld_state.smem,
- sizeof (*newp));
- newp->next = lastp->next;
- newp->exist = 0;
- lastp = lastp->next = newp;
-
- colonp = strchrnul (pname, ':');
- }
-
- pathp = &lastp->next;
- }
- else
- pathp = &(*pathp)->next;
- }
- while (*pathp != firstp);
-}
-
-
-/* Called after all parameters are parsed to bring the runpath/rpath
- information into a usable form. */
-static void
-gen_rxxpath_data (void)
-{
- char *ld_library_path2;
-
- /* Convert the information in true single-linked lists for easy use.
- At this point we also discard the rpath information if runpath
- information is provided. rpath is deprecated and should not be
- used (or ever be invented for that matter). */
- if (ld_state.rpath != NULL)
- {
- struct pathelement *endp = ld_state.rpath;
- ld_state.rpath = ld_state.rpath->next;
- endp->next = NULL;
- }
- if (ld_state.rpath_link != NULL)
- {
- struct pathelement *endp = ld_state.rpath_link;
- ld_state.rpath_link = ld_state.rpath_link->next;
- endp->next = NULL;
- }
-
- if (ld_state.runpath != NULL)
- {
- struct pathelement *endp = ld_state.runpath;
- ld_state.runpath = ld_state.runpath->next;
- endp->next = NULL;
-
- /* If rpath information is also available discard it.
- XXX Should there be a possibility to avoid this? */
- while (ld_state.rpath != NULL)
- {
- struct pathelement *old = ld_state.rpath;
- ld_state.rpath = ld_state.rpath->next;
- free (old);
- }
- }
- if (ld_state.runpath_link != NULL)
- {
- struct pathelement *endp = ld_state.runpath_link;
- ld_state.runpath_link = ld_state.runpath_link->next;
- endp->next = NULL;
-
- /* If rpath information is also available discard it.
- XXX Should there be a possibility to avoid this? */
- while (ld_state.rpath_link != NULL)
- {
- struct pathelement *old = ld_state.rpath_link;
- ld_state.rpath_link = ld_state.rpath_link->next;
- free (old);
- }
-
- /* The information in the strings in the list can actually be
- directory lists themselves, with entries separated by colons.
- Convert the list now to a list with one list entry for each
- directory. */
- normalize_dirlist (&ld_state.runpath_link);
- }
- else if (ld_state.rpath_link != NULL)
- /* Same as for the runpath_link above. */
- normalize_dirlist (&ld_state.rpath_link);
-
-
- /* As a related task, handle the LD_LIBRARY_PATH value here. First
- we have to possibly split the value found (if it contains a
- semicolon). Then we have to split the value in list of
- directories, i.e., split at the colons. */
- if (ld_library_path1 != NULL)
- {
- ld_library_path2 = strchr (ld_library_path1, ';');
- if (ld_library_path2 == NULL)
- {
- /* If no semicolon is present the directories are looked at
- after the -L parameters (-> ld_library_path2). */
- ld_library_path2 = ld_library_path1;
- ld_library_path1 = NULL;
- }
- else
- {
- /* NUL terminate the first part. */
- *ld_library_path2++ = '\0';
-
- /* Convert the string value in a list. */
- add_rxxpath (&ld_state.ld_library_path1, ld_library_path1);
- normalize_dirlist (&ld_state.ld_library_path1);
- }
-
- add_rxxpath (&ld_state.ld_library_path2, ld_library_path2);
- normalize_dirlist (&ld_state.ld_library_path2);
- }
-}
-
-
-static void
-read_version_script (const char *fname)
-{
- /* Open the file. The name is supposed to be the complete (relative
- or absolute) path. No search along a path will be performed. */
- ldin = fopen (fname, "r");
- if (ldin == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot read version script \"%s\""),
- fname);
- /* No need for locking. */
- __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
- /* Tell the parser that this is a version script. */
- ld_scan_version_script = 1;
-
- ldlineno = 1;
- ldin_fname = fname;
- if (ldparse () != 0)
- /* Something went wrong during parsing. */
- exit (EXIT_FAILURE);
-
- fclose (ldin);
-}
-
-
-static void
-create_lscript_symbols (void)
-{
- /* Walk through the data from the linker script and generate all the
- symbols which are required to be present and and those marked
- with PROVIDE if there is a undefined reference. */
- if (ld_state.output_segments == NULL)
- return;
-
- struct output_segment *segment = ld_state.output_segments->next;
- do
- {
- struct output_rule *orule;
-
- for (orule = segment->output_rules; orule != NULL; orule = orule->next)
- if (orule->tag == output_assignment
- /* The assignments to "." (i.e., the PC) have to be
- ignored here. */
- && strcmp (orule->val.assignment->variable, ".") != 0)
- {
- struct symbol *s = ld_state.unresolved;
-
- /* Check whether the symbol is needed. */
- if (likely (s != NULL))
- {
- struct symbol *first = s;
- const char *providename = orule->val.assignment->variable;
-
- /* Determine whether the provided symbol is still
- undefined. */
- // XXX TODO Loop inside a loop. Gag! Must rewrite. */
- do
- if (strcmp (s->name, providename) == 0)
- {
- /* Not defined but referenced. */
- if (unlikely (!s->defined))
- {
- /* Put on the list of symbols. First remove it from
- whatever list it currently is on. */
- CDBL_LIST_DEL (ld_state.unresolved, s);
- --ld_state.nunresolved;
- goto use_it;
- }
-
- if (unlikely (!orule->val.assignment->provide_flag))
- {
- /* The symbol is already defined and now again
- in the linker script. This is an error. */
- error (0, 0, gettext ("\
-duplicate definition of '%s' in linker script"),
- providename);
- goto next_rule;
- }
- }
- while ((s = s->next) != first);
- }
-
- /* If the symbol only has to be provided if it is needed,
- ignore it here since it is not undefined. */
- if (orule->val.assignment->provide_flag)
- continue;
-
- /* Allocate memory for this new symbol. */
- s = (struct symbol *)
- obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
- /* Initialize it. */
- s->name = orule->val.assignment->variable;
-
- /* Insert it into the symbol hash table. */
- unsigned long int hval = elf_hash (s->name);
- if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
- hval, s) != 0))
- {
- /* This means the symbol is defined somewhere else.
- Maybe it comes from a DSO or so. Get the
- definition. */
- free (s);
- struct symbol *old = ld_symbol_tab_find (&ld_state.symbol_tab,
- hval, s);
- assert (old != NULL);
- free (s);
-
- /* If this is a definition from the application itself
- this means a duplicate definition. */
- if (! old->in_dso)
- {
- error (0, 0, gettext ("\
-duplicate definition of '%s' in linker script"),
- s->name);
- goto next_rule;
- }
-
- /* We use the definition from the linker script. */
- s = old;
- }
-
- use_it:
- /* The symbol is (now) defined. */
- s->defined = 1;
- s->type = STT_NOTYPE;
-
- /* Add a reference to the symbol record. We will come
- across it when creating the output file. */
- orule->val.assignment->sym = s;
-
- SNGL_LIST_PUSH (ld_state.lscript_syms, s);
- ++ld_state.nlscript_syms;
-
- next_rule:
- ;
- }
-
- segment = segment->next;
- }
- while (segment != ld_state.output_segments->next);
-}
-
-
-/* Create creation of spection section symbols representing sections in the
- output file. This is done for symbols like _GLOBAL_OFFSET_TABLE_ and
- _DYNAMIC. */
-static void
-create_special_section_symbol (struct symbol **symp, const char *name)
-{
- if (*symp == NULL)
- {
- /* No symbol defined found yet. Create one. */
- struct symbol *newsym = (struct symbol *)
- obstack_calloc (&ld_state.smem, sizeof (*newsym));
-
- newsym->name = name;
- // XXX Should we mark the symbol hidden? They are hardly useful
- // used outside the current object.
-
- /* Add to the symbol table. */
- if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
- elf_hash (name), newsym) != 0))
- abort ();
-
- *symp = newsym;
- }
- else if ((*symp)->defined)
- /* Cannot happen. We do use this symbol from any input file. */
- abort ();
-
- (*symp)->defined = 1;
- (*symp)->type = STT_OBJECT;
-
- ++ld_state.nsymtab;
-}
diff --git a/src/ld.h b/src/ld.h
deleted file mode 100644
index 760ff125..00000000
--- a/src/ld.h
+++ /dev/null
@@ -1,1073 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifndef LD_H
-#define LD_H 1
-
-#include <dlfcn.h>
-#include <obstack.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include "xelf.h"
-
-
-/* Recommended size of the buffer passed to ld_strerror. */
-#define ERRBUFSIZE (512)
-
-/* Character used to introduce version name after symbol. */
-#define VER_CHR '@'
-
-
-/* Methods for handling archives. */
-enum extract_rule
- {
- defaultextract, /* Weak references don't cause archive member to
- be used. */
- weakextract, /* Weak references cause archive member to be
- extracted. */
- allextract /* Extract all archive members regardless of
- references (aka whole-archive). */
- };
-
-
-/* Type of output file. */
-enum file_type
- {
- no_file_type = 0, /* None selected so far. */
- executable_file_type, /* Executable. */
- dso_file_type, /* DSO. */
- dso_needed_file_type, /* DSO introduced by DT_NEEDED. */
- relocatable_file_type, /* Relocatable object file. */
- archive_file_type /* Archive (input only). */
- };
-
-
-struct usedfiles
-{
- /* The next file given at the command line. */
- struct usedfiles *next;
- /* Nonzero if this file is the beginning of a group. */
- bool group_start;
- /* Nonzero if this file is the end of a group. */
- bool group_end;
- /* Pointer to the beginning of the group. It is necessary to
- explain why we cannot simply use the 'next' pointer and have a
- circular single-linked list like in many cases. The problem is
- that the last archive of the group, if it is the last file of the
- group, contains the only existing pointer to the next file we
- have to look at. All files are initially connected via the
- 'next' pointer in a single-linked list. Therefore we cannot
- overwrite this value. It instead will be used once the group is
- handled and we go on processing the rest of the files. */
- struct usedfiles *group_backref;
-
- /* Name/path of the file. */
- const char *fname;
- /* Resolved file name. */
- const char *rfname;
- /* Name used as reference in DT_NEEDED entries. This is normally
- the SONAME. If it is missing it's normally the fname above. */
- const char *soname;
- /* Handle for the SONAME in the string table. */
- struct Ebl_Strent *sonameent;
-
- /* Help to identify duplicates. */
- dev_t dev;
- ino_t ino;
-
- enum
- {
- not_opened,
- opened,
- in_archive,
- closed
- } status;
-
- /* How to extract elements from archives. */
- enum extract_rule extract_rule;
-
- /* Lazy-loading rule. */
- bool lazyload;
-
- /* If this is a DSO the flag indicates whether the file is directly
- used in a reference. */
- bool used;
-
- /* If nonzero this is the archive sequence number which can be used to
- determine whether back refernces from -( -) or GROUP statements
- have to be followed. */
- int archive_seq;
-
- /* Pointer to the record for the archive containing this file. */
- struct usedfiles *archive_file;
-
- /* Type of file. We have to distinguish these types since they
- are searched for differently. */
- enum file_type file_type;
- /* This is the ELF library handle for this file. */
- Elf *elf;
-
- /* The ELF header. */
-#if NATIVE_ELF != 0
- XElf_Ehdr *ehdr;
-# define FILEINFO_EHDR(fi) (*(fi))
-#else
- XElf_Ehdr ehdr;
-# define FILEINFO_EHDR(fi) (fi)
-#endif
-
- /* Index of the section header string table section. We use a
- separate field and not the e_shstrndx field in the ELF header
- since in case of a file with more than 64000 sections the index
- might be stored in the section header of section zero. The
- elf_getshstrndx() function can find the value but it is too
- costly to repeat this call over and over. */
- size_t shstrndx;
-
- /* Info about the sections of the file. */
- struct scninfo
- {
- /* Handle for the section. Note that we can store a section
- handle here because the file is not changing. This together
- with the knowledge about the libelf library is enough for us to
- assume the section reference remains valid at all times. */
- Elf_Scn *scn;
- /* Section header. */
-#if NATIVE_ELF != 0
- XElf_Shdr *shdr;
-# define SCNINFO_SHDR(si) (*(si))
-#else
- XElf_Shdr shdr;
-# define SCNINFO_SHDR(si) (si)
-#endif
- /* Offset of this files section in the combined section. */
- XElf_Off offset;
- /* Index of the section in the output file. */
- Elf32_Word outscnndx;
- /* Index of the output section in the 'allsection' array. */
- Elf32_Word allsectionsidx;
- /* True if the section is used. */
- bool used;
- /* Section group number. This is the index of the SHT_GROUP section. */
- Elf32_Word grpid;
- /* Pointer back to the containing file information structure. */
- struct usedfiles *fileinfo;
- /* List of symbols in this section (set only for merge-able sections). */
- struct symbol *symbols;
- /* Size of relocations in this section. Only used for relocation
- sections. */
- size_t relsize;
- /* Pointer to next section which is put in the given output
- section. */
- struct scninfo *next;
- } *scninfo;
-
- /* List of section group sections. */
- struct scninfo *groups;
-
- /* The symbol table section.
-
- XXX Maybe support for more than one symbol table is needed. */
- Elf_Data *symtabdata;
- /* Extra section index table section. */
- Elf_Data *xndxdata;
- /* Dynamic symbol table section. */
- Elf_Data *dynsymtabdata;
- /* The version number section. */
- Elf_Data *versymdata;
- /* The defined versions. */
- Elf_Data *verdefdata;
- /* Number of versions defined. */
- size_t nverdef;
- /* True if the version with the given index number is used in the
- output. */
- XElf_Versym *verdefused;
- /* How many versions are used. */
- size_t nverdefused;
- /* Handle for name of the version. */
- struct Ebl_Strent **verdefent;
- /* The needed versions. */
- Elf_Data *verneeddata;
- /* String table section associated with the symbol table. */
- Elf32_Word symstridx;
- /* String table section associated with the dynamic symbol table. */
- Elf32_Word dynsymstridx;
- /* Number of entries in the symbol table. */
- size_t nsymtab;
- size_t nlocalsymbols;
- size_t ndynsymtab;
- /* Dynamic section. */
- Elf_Scn *dynscn;
-
- /* Indirection table for the symbols defined here. */
- Elf32_Word *symindirect;
- Elf32_Word *dynsymindirect;
- /* For undefined or common symbols we need a reference to the symbol
- record. */
- struct symbol **symref;
- struct symbol **dynsymref;
-
- /* This is the file descriptor. The value is -1 if the descriptor
- was already closed. This can happen if we needed file descriptors
- to open new files. */
- int fd;
- /* This flag is true if the descriptor was passed to the generic
- functions from somewhere else. This is an implementation detail;
- no machine-specific code must use this flag. */
- bool fd_passed;
-
- /* True if any of the sections is merge-able. */
- bool has_merge_sections;
-};
-
-
-/* Functions to test for the various types of files we handle. */
-static inline int
-ld_file_rel_p (struct usedfiles *file)
-{
- return (elf_kind (file->elf) == ELF_K_ELF
- && FILEINFO_EHDR (file->ehdr).e_type == ET_REL);
-}
-
-static inline int
-ld_file_dso_p (struct usedfiles *file)
-{
- return (elf_kind (file->elf) == ELF_K_ELF
- && FILEINFO_EHDR (file->ehdr).e_type == ET_DYN);
-}
-
-static inline int
-ld_file_ar_p (struct usedfiles *file)
-{
- return elf_kind (file->elf) == ELF_K_AR;
-}
-
-
-struct pathelement
-{
- /* The next path to search. */
- struct pathelement *next;
- /* The path name. */
- const char *pname;
- /* Larger than zero if the directory exists, smaller than zero if not,
- zero if it is not yet known. */
- int exist;
-};
-
-
-/* Forward declaration. */
-struct ld_state;
-
-
-/* Callback functions. */
-struct callbacks
-{
- /* Library names passed to the linker as -lXXX represent files named
- libXXX.YY. The YY part can have different forms, depending on the
- architecture. The generic set is .so and .a (in this order). */
- const char **(*lib_extensions) (struct ld_state *)
- __attribute__ ((__const__));
-#define LIB_EXTENSION(state) \
- DL_CALL_FCT ((state)->callbacks.lib_extensions, (state))
-
- /* Process the given file. If the file is not yet open, open it.
- The first parameter is a file descriptor for the file which can
- be -1 to indicate the file has not yet been found. The second
- parameter describes the file to be opened, the last one is the
- state of the linker which among other information contain the
- paths we look at.*/
- int (*file_process) (int fd, struct usedfiles *, struct ld_state *,
- struct usedfiles **);
-#define FILE_PROCESS(fd, file, state, nextp) \
- DL_CALL_FCT ((state)->callbacks.file_process, (fd, file, state, nextp))
-
- /* Close the given file. */
- int (*file_close) (struct usedfiles *, struct ld_state *);
-#define FILE_CLOSE(file, state) \
- DL_CALL_FCT ((state)->callbacks.file_close, (file, state))
-
- /* Create the output sections now. This requires knowledge about
- all the sections we will need. It may be necessary to sort the
- sections in the order they are supposed to appear in the
- executable. The sorting use many different kinds of information
- to optimize the resulting binary. Important is to respect
- segment boundaries and the needed alignment. The mode of the
- segments will be determined afterwards automatically by the
- output routines. */
- void (*create_sections) (struct ld_state *);
-#define CREATE_SECTIONS(state) \
- DL_CALL_FCT ((state)->callbacks.create_sections, (state))
-
- /* Determine whether we have any non-weak unresolved references left. */
- int (*flag_unresolved) (struct ld_state *);
-#define FLAG_UNRESOLVED(state) \
- DL_CALL_FCT ((state)->callbacks.flag_unresolved, (state))
-
- /* Create the sections which are generated by the linker and are not
- present in the input file. */
- void (*generate_sections) (struct ld_state *);
-#define GENERATE_SECTIONS(state) \
- DL_CALL_FCT ((state)->callbacks.generate_sections, (state))
-
- /* Open the output file. The file name is given or "a.out". We
- create as much of the ELF structure as possible. */
- int (*open_outfile) (struct ld_state *, int, int, int);
-#define OPEN_OUTFILE(state, machine, class, data) \
- DL_CALL_FCT ((state)->callbacks.open_outfile, (state, machine, class, data))
-
- /* Create the data for the output file. */
- int (*create_outfile) (struct ld_state *);
-#define CREATE_OUTFILE(state) \
- DL_CALL_FCT ((state)->callbacks.create_outfile, (state))
-
- /* Process a relocation section. */
- void (*relocate_section) (struct ld_state *, Elf_Scn *, struct scninfo *,
- const Elf32_Word *);
-#define RELOCATE_SECTION(state, outscn, first, dblindirect) \
- DL_CALL_FCT ((state)->callbacks.relocate_section, (state, outscn, first, \
- dblindirect))
-
- /* Allocate a data buffer for the relocations of the given output
- section. */
- void (*count_relocations) (struct ld_state *, struct scninfo *);
-#define COUNT_RELOCATIONS(state, scninfo) \
- DL_CALL_FCT ((state)->callbacks.count_relocations, (state, scninfo))
-
- /* Create relocations for executable or DSO. */
- void (*create_relocations) (struct ld_state *, const Elf32_Word *);
-#define CREATE_RELOCATIONS(state, dlbindirect) \
- DL_CALL_FCT ((state)->callbacks.create_relocations, (state, dblindirect))
-
- /* Finalize the output file. */
- int (*finalize) (struct ld_state *);
-#define FINALIZE(state) \
- DL_CALL_FCT ((state)->callbacks.finalize, (state))
-
- /* Check whether special section number is known. */
- bool (*special_section_number_p) (struct ld_state *, size_t);
-#define SPECIAL_SECTION_NUMBER_P(state, number) \
- DL_CALL_FCT ((state)->callbacks.special_section_number_p, (state, number))
-
- /* Check whether section type is known. */
- bool (*section_type_p) (struct ld_state *, XElf_Word);
-#define SECTION_TYPE_P(state, type) \
- DL_CALL_FCT ((state)->callbacks.section_type_p, (state, type))
-
- /* Return section flags for .dynamic section. */
- XElf_Xword (*dynamic_section_flags) (struct ld_state *);
-#define DYNAMIC_SECTION_FLAGS(state) \
- DL_CALL_FCT ((state)->callbacks.dynamic_section_flags, (state))
-
- /* Create the data structures for the .plt section and initialize it. */
- void (*initialize_plt) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_PLT(state, scn) \
- DL_CALL_FCT ((state)->callbacks.initialize_plt, (state, scn))
-
- /* Create the data structures for the .rel.plt section and initialize it. */
- void (*initialize_pltrel) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_PLTREL(state, scn) \
- DL_CALL_FCT ((state)->callbacks.initialize_pltrel, (state, scn))
-
- /* Finalize the .plt section the what belongs to them. */
- void (*finalize_plt) (struct ld_state *, size_t, size_t);
-#define FINALIZE_PLT(state, nsym, nsym_dyn) \
- DL_CALL_FCT ((state)->callbacks.finalize_plt, (state, nsym, nsym_dyn))
-
- /* Create the data structures for the .got section and initialize it. */
- void (*initialize_got) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_GOT(state, scn) \
- DL_CALL_FCT ((state)->callbacks.initialize_got, (state, scn))
-
- /* Return the tag corresponding to the native relocation type for
- the platform. */
- int (*rel_type) (struct ld_state *);
-#define REL_TYPE(state) \
- DL_CALL_FCT ((state)->callbacks.rel_type, (state))
-};
-
-
-/* Structure for symbol representation. This data structure is used a
- lot, so size is important. */
-struct symbol
-{
- /* Symbol name. */
- const char *name;
- /* Size of the object. */
- XElf_Xword size;
- /* Index of the symbol in the symbol table of the object. */
- size_t symidx;
- /* Index of the symbol in the symbol table of the output file. */
- size_t outsymidx;
-
- /* Description where the symbol is found/needed. */
- size_t scndx;
- struct usedfiles *file;
- /* Index of the symbol table. */
- Elf32_Word symscndx;
-
- /* Index of the symbol in the dynamic symbol table of the output
- file. Note that the value only needs to be 16 bit wide since
- there cannot be more sections in an executable or DSO. */
- unsigned int outdynsymidx:16;
-
- /* Type of the symbol. */
- unsigned int type:4;
- /* Various flags. */
- unsigned int defined:1;
- unsigned int common:1;
- unsigned int weak:1;
- unsigned int added:1;
- unsigned int merged:1;
- /* Nonzero if the symbol is on the from_dso list. */
- unsigned int on_dsolist:1;
- /* Nonzero if symbol needs copy relocation, reset when the
- relocation has been created. */
- unsigned int need_copy:1;
- unsigned int in_dso:1;
-
- union
- {
- /* Pointer to the handle created by the functions which create
- merged section contents. We use 'void *' because there are
- different implementations used. */
- void *handle;
- XElf_Addr value;
- } merge;
-
- /* Pointer to next/previous symbol on whatever list the symbol is. */
- struct symbol *next;
- struct symbol *previous;
- /* Pointer to next symbol of the same section (only set for merge-able
- sections). */
- struct symbol *next_in_scn;
-};
-
-
-/* Get the definition for the symbol table. */
-#include <symbolhash.h>
-
-/* Simple single linked list of file names. */
-struct filename_list
-{
- const char *name;
- struct usedfiles *real;
- struct filename_list *next;
- bool group_start;
- bool group_end;
-};
-
-
-/* Data structure to describe expression in linker script. */
-struct expression
-{
- enum expression_tag
- {
- exp_num,
- exp_sizeof_headers,
- exp_pagesize,
- exp_id,
- exp_mult,
- exp_div,
- exp_mod,
- exp_plus,
- exp_minus,
- exp_and,
- exp_or,
- exp_align
- } tag;
-
- union
- {
- uintmax_t num;
- struct expression *child;
- struct
- {
- struct expression *left;
- struct expression *right;
- } binary;
- const char *str;
- } val;
-};
-
-
-/* Data structure for section name with flags. */
-struct input_section_name
-{
- const char *name;
- bool sort_flag;
-};
-
-/* File name mask with section name. */
-struct filemask_section_name
-{
- const char *filemask;
- const char *excludemask;
- struct input_section_name *section_name;
- bool keep_flag;
-};
-
-/* Data structure for assignments. */
-struct assignment
-{
- const char *variable;
- struct expression *expression;
- struct symbol *sym;
- bool provide_flag;
-};
-
-
-/* Data structure describing input for an output section. */
-struct input_rule
-{
- enum
- {
- input_section,
- input_assignment
- } tag;
-
- union
- {
- struct assignment *assignment;
- struct filemask_section_name *section;
- } val;
-
- struct input_rule *next;
-};
-
-
-/* Data structure to describe output section. */
-struct output_section
-{
- const char *name;
- struct input_rule *input;
- XElf_Addr max_alignment;
- bool ignored;
-};
-
-
-/* Data structure to describe output file format. */
-struct output_rule
-{
- enum
- {
- output_section,
- output_assignment
- } tag;
-
- union
- {
- struct assignment *assignment;
- struct output_section section;
- } val;
-
- struct output_rule *next;
-};
-
-
-/* List of all the segments the linker script describes. */
-struct output_segment
-{
- int mode;
- struct output_rule *output_rules;
- struct output_segment *next;
-
- XElf_Off offset;
- XElf_Addr addr;
- XElf_Xword align;
-};
-
-
-/* List of identifiers. */
-struct id_list
-{
- union
- {
- enum id_type
- {
- id_str, /* Normal string. */
- id_all, /* "*", matches all. */
- id_wild /* Globbing wildcard string. */
- } id_type;
- struct
- {
- bool local;
- const char *versionname;
- } s;
- } u;
- const char *id;
- struct id_list *next;
-};
-
-
-/* Version information. */
-struct version
-{
- struct version *next;
- struct id_list *local_names;
- struct id_list *global_names;
- const char *versionname;
- const char *parentname;
-};
-
-
-/* Head for list of sections. */
-struct scnhead
-{
- /* Name of the sections. */
- const char *name;
-
- /* Accumulated flags for the sections. */
- XElf_Xword flags;
-
- /* Type of the sections. */
- XElf_Word type;
-
- /* Entry size. If there are differencs between the sections with
- the same name this field contains 1. */
- XElf_Word entsize;
-
- /* If non-NULL pointer to group signature. */
- const char *grp_signature;
-
- /* Maximum alignment for all sections. */
- XElf_Word align;
-
- /* Distinguish between normal sections coming from the input file
- and sections generated by the linker. */
- enum scn_kind
- {
- scn_normal, /* Section from the input file(s). */
- scn_dot_interp, /* Generated .interp section. */
- scn_dot_got, /* Generated .got section. */
- scn_dot_dynrel, /* Generated .rel.dyn section. */
- scn_dot_dynamic, /* Generated .dynamic section. */
- scn_dot_dynsym, /* Generated .dynsym section. */
- scn_dot_dynstr, /* Generated .dynstr section. */
- scn_dot_hash, /* Generated .hash section. */
- scn_dot_plt, /* Generated .plt section. */
- scn_dot_pltrel, /* Generated .rel.plt section. */
- scn_dot_version, /* Generated .gnu.version section. */
- scn_dot_version_r /* Generated .gnu.version_r section. */
- } kind;
-
- /* True is the section is used in the output. */
- bool used;
-
- /* Total size (only determined this way for relocation sections). */
- size_t relsize;
-
- /* Filled in by the section sorting to indicate which segment the
- section goes in. */
- int segment_nr;
-
- /* Index of the output section. We cannot store the section handle
- directly here since the handle is a pointer in a dynamically
- allocated table which might move if it becomes too small for all
- the sections. Using the index the correct value can be found at
- all times. */
- XElf_Word scnidx;
-
- /* Index of the STT_SECTION entry for this section in the symbol
- table. */
- XElf_Word scnsymidx;
-
- /* Address of the section in the output file. */
- XElf_Addr addr;
-
- /* Handle for the section name in the output file's section header
- string table. */
- struct Ebl_Strent *nameent;
-
- /* Tail of list of symbols for this section. Only set if the
- section is merge-able. */
- struct symbol *symbols;
-
- /* Pointer to last section. */
- struct scninfo *last;
-};
-
-
-/* Define hash table for sections. */
-#include <sectionhash.h>
-
-/* Define hash table for version symbols. */
-#include <versionhash.h>
-
-
-/* State of the linker. */
-struct ld_state
-{
- /* ELF backend library handle. */
- Ebl *ebl;
-
- /* List of all archives participating, in this order. */
- struct usedfiles *archives;
- /* End of the list. */
- struct usedfiles *tailarchives;
- /* If nonzero we are looking for the beginning of a group. */
- bool group_start_requested;
- /* Pointer to the archive starting the group. */
- struct usedfiles *group_start_archive;
-
- /* List of the DSOs we found. */
- struct usedfiles *dsofiles;
- /* Number of DSO files. */
- size_t ndsofiles;
- /* Ultimate list of object files which are linked in. */
- struct usedfiles *relfiles;
-
- /* List the DT_NEEDED DSOs. */
- struct usedfiles *needed;
-
- /* Temporary storage for the parser. */
- struct filename_list *srcfiles;
-
- /* List of all the paths to look at. */
- struct pathelement *paths;
- /* Tail of the list. */
- struct pathelement *tailpaths;
-
- /* User provided paths for lookup of DSOs. */
- struct pathelement *rpath;
- struct pathelement *rpath_link;
- struct pathelement *runpath;
- struct pathelement *runpath_link;
- struct Ebl_Strent *rxxpath_strent;
- int rxxpath_tag;
-
- /* From the environment variable LD_LIBRARY_PATH. */
- struct pathelement *ld_library_path1;
- struct pathelement *ld_library_path2;
-
- /* Name of the output file. */
- const char *outfname;
- /* Name of the temporary file we initially create. */
- const char *tempfname;
- /* File descriptor opened for the output file. */
- int outfd;
- /* The ELF descriptor for the output file. */
- Elf *outelf;
-
- /* Type of output file. */
- enum file_type file_type;
-
- /* Is this a system library or not. */
- bool is_system_library;
-
- /* Page size to be assumed for the binary. */
- size_t pagesize;
-
- /* Name of the interpreter for dynamically linked objects. */
- const char *interp;
- /* Index of the .interp section. */
- Elf32_Word interpscnidx;
-
- /* Optimization level. */
- unsigned long int optlevel;
-
- /* If true static linking is requested. */
- bool statically;
-
- /* How to extract elements from archives. */
- enum extract_rule extract_rule;
-
- /* Sequence number of the last archive we used. */
- int last_archive_used;
-
- /* If true print to stdout information about the files we are
- trying to open. */
- bool trace_files;
-
- /* If true multiple definitions are not considered an error; the
- first is used. */
- bool muldefs;
-
- /* If true undefined symbols when building DSOs are not fatal. */
- bool nodefs;
-
- /* If true add line indentifying link-editor to .comment section. */
- bool add_ld_comment;
-
- /* Stripping while linking. */
- enum
- {
- strip_none,
- strip_debug,
- strip_all,
- strip_everything
- } strip;
-
- /* The callback function vector. */
- struct callbacks callbacks;
-
- /* Name of the entry symbol. Can also be a numeric value. */
- const char *entry;
-
- /* The description of the segments in the output file. */
- struct output_segment *output_segments;
-
- /* List of the symbols we created from linker script definitions. */
- struct symbol *lscript_syms;
- size_t nlscript_syms;
-
- /* Table with known symbols. */
- ld_symbol_tab symbol_tab;
-
- /* Table with used sections. */
- ld_section_tab section_tab;
-
- /* The list of sections once we collected them. */
- struct scnhead **allsections;
- size_t nallsections;
- size_t nusedsections;
- size_t nnotesections;
-
- /* Beginning of the list of symbols which are still unresolved. */
- struct symbol *unresolved;
- /* Number of truely unresolved entries in the list. */
- size_t nunresolved;
- /* Number of truely unresolved, non-weak entries in the list. */
- size_t nunresolved_nonweak;
-
- /* List of common symbols. */
- struct symbol *common_syms;
- /* Section for the common symbols. */
- struct scninfo *common_section;
-
- /* List of symbols defined in DSOs and used in a relocatable file.
- DSO symbols not referenced in the relocatable files are not on
- the list. If a symbol is on the list the on_dsolist field in the
- 'struct symbol' is nonzero. */
- struct symbol *from_dso;
- /* Number of entries in from_dso. */
- size_t nfrom_dso;
- /* Number of entries in the dynamic symbol table. */
- size_t ndynsym;
- /* Number of PLT entries from DSO references. */
- size_t nplt;
- /* Number of PLT entries from DSO references. */
- size_t ngot;
- /* Number of copy relocations. */
- size_t ncopy;
- /* Section for copy relocations. */
- struct scninfo *copy_section;
-
- /* Keeping track of the number of symbols in the output file. */
- size_t nsymtab;
- size_t nlocalsymbols;
-
- /* Special symbols. */
- struct symbol *init_symbol;
- struct symbol *fini_symbol;
-
- /* The description of the segments in the output file as described
- in the default linker script. This information will be used in
- addition to the user-provided information. */
- struct output_segment *default_output_segments;
- /* Search paths added by the default linker script. */
- struct pathelement *default_paths;
-
-#ifndef BASE_ELF_NAME
- /* The handle of the ld backend library. */
- void *ldlib;
-#endif
-
- /* String table for the section headers. */
- struct Ebl_Strtab *shstrtab;
-
- /* True if output file should contain symbol table. */
- bool need_symtab;
- /* Symbol table section. */
- Elf32_Word symscnidx;
- /* Extended section table section. */
- Elf32_Word xndxscnidx;
- /* Symbol string table section. */
- Elf32_Word strscnidx;
-
- /* True if output file should contain dynamic symbol table. */
- bool need_dynsym;
- /* Dynamic symbol table section. */
- Elf32_Word dynsymscnidx;
- /* Dynamic symbol string table section. */
- Elf32_Word dynstrscnidx;
- /* Dynamic symbol hash table. */
- size_t hashscnidx;
-
- /* Procedure linkage table section. */
- Elf32_Word pltscnidx;
- /* Number of entries already in the PLT section. */
- size_t nplt_used;
- /* Relocation for procedure linkage table section. */
- Elf32_Word pltrelscnidx;
-
- /* Global offset table section. */
- Elf32_Word gotscnidx;
-
- /* This section will hole all non-PLT relocations. */
- Elf32_Word reldynscnidx;
-
- /* Index of the sections to handle versioning. */
- Elf32_Word versymscnidx;
- Elf32_Word verneedscnidx;
- /* XXX Should the following names be verneed...? */
- /* Number of version definitions in input DSOs used. */
- int nverdefused;
- /* Number of input DSOs using versioning. */
- int nverdeffile;
- /* Index of next version. */
- int nextveridx;
-
- /* Hash table for version symbol strings. Only strings without
- special characters are hashed here. */
- ld_version_str_tab version_str_tab;
- /* At most one of the following two variables is set to true if either
- global or local symbol binding is selected as the default. */
- bool default_bind_local;
- bool default_bind_global;
-
- /* True if only used sections are used. */
- bool gc_sections;
-
- /* Array to determine final index of symbol. */
- Elf32_Word *dblindirect;
-
- /* Section group handling. */
- struct scngroup
- {
- Elf32_Word outscnidx;
- int nscns;
- struct member
- {
- struct scnhead *scn;
- struct member *next;
- } *member;
- struct Ebl_Strent *nameent;
- struct symbol *symbol;
- struct scngroup *next;
- } *groups;
-
- /* True if the output file needs a .got section. */
- bool need_got;
- /* Number of relocations for GOT section caused. */
- size_t nrel_got;
-
- /* Number of entries needed in the .dynamic section. */
- int ndynamic;
- /* To keep track of added entries. */
- int ndynamic_filled;
- /* Index for the dynamic section. */
- Elf32_Word dynamicscnidx;
-
- /* Flags set in the DT_FLAGS word. */
- Elf32_Word dt_flags;
- /* Flags set in the DT_FLAGS_1 word. */
- Elf32_Word dt_flags_1;
- /* Flags set in the DT_FEATURE_1 word. */
- Elf32_Word dt_feature_1;
-
- /* Lazy-loading state for dependencies. */
- bool lazyload;
-
- /* True is DSOs which are not used in the linking process are not
- recorded. */
- bool ignore_unused_dsos;
-
-
- /* True if in executables all global symbols should be exported in
- the dynamic symbol table. */
- bool export_all_dynamic;
-
- /* If DSO is generated, this is the SONAME. */
- const char *soname;
-
- /* List of all relocation sections. */
- struct scninfo *rellist;
- /* Total size of non-PLT relocations. */
- size_t relsize_total;
-
- /* Record for the GOT symbol, if known. */
- struct symbol *got_symbol;
- /* Record for the dynamic section symbol, if known. */
- struct symbol *dyn_symbol;
-
- /* Obstack used for small objects which will not be deleted. */
- struct obstack smem;
-};
-
-
-/* The interface to the scanner. */
-
-/* Parser entry point. */
-extern int ldparse (void);
-
-/* The input file. */
-extern FILE *ldin;
-
-/* Name of the input file. */
-extern const char *ldin_fname;
-
-/* Current line number. Must be reset for a new file. */
-extern int ldlineno;
-
-/* If nonzero we are currently parsing a version script. */
-extern int ld_scan_version_script;
-
-/* Flags defined in ld.c. */
-extern int verbose;
-extern int conserve_memory;
-
-
-/* Linker state. This contains all global information. */
-extern struct ld_state ld_state;
-
-
-/* Generic ld helper functions. */
-
-/* Append a new directory to search libraries in. */
-extern void ld_new_searchdir (const char *dir);
-
-/* Append a new file to the list of input files. */
-extern struct usedfiles *ld_new_inputfile (const char *fname,
- enum file_type type);
-
-
-/* These are the generic implementations for the callbacks used by ld. */
-
-/* Initialize state object. This callback function is called after the
- parameters are parsed but before any file is searched for. */
-extern int ld_prepare_state (const char *emulation);
-
-
-/* Function to determine whether an object will be dynamically linked. */
-extern bool dynamically_linked_p (void);
-
-/* Helper functions for the architecture specific code. */
-
-/* Checked whether the symbol is undefined and referenced from a DSO. */
-extern bool linked_from_dso_p (struct scninfo *scninfo, int symidx);
-extern inline bool
-linked_from_dso_p (struct scninfo *scninfo, int symidx)
-{
- struct usedfiles *file = scninfo->fileinfo;
-
- /* If this symbol is not undefined in this file it cannot come from
- a DSO. */
- if (symidx < file->nlocalsymbols)
- return false;
-
- struct symbol *sym = file->symref[symidx];
-
- return sym->defined && sym->in_dso;
-}
-
-#endif /* ld.h */
diff --git a/src/ldgeneric.c b/src/ldgeneric.c
deleted file mode 100644
index a33e9fcc..00000000
--- a/src/ldgeneric.c
+++ /dev/null
@@ -1,6376 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <fnmatch.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <system.h>
-#include "ld.h"
-#include "list.h"
-
-
-/* Prototypes for local functions. */
-static const char **ld_generic_lib_extensions (struct ld_state *)
- __attribute__ ((__const__));
-static int ld_generic_file_close (struct usedfiles *fileinfo,
- struct ld_state *statep);
-static int ld_generic_file_process (int fd, struct usedfiles *fileinfo,
- struct ld_state *statep,
- struct usedfiles **nextp);
-static void ld_generic_generate_sections (struct ld_state *statep);
-static void ld_generic_create_sections (struct ld_state *statep);
-static int ld_generic_flag_unresolved (struct ld_state *statep);
-static int ld_generic_open_outfile (struct ld_state *statep, int machine,
- int class, int data);
-static int ld_generic_create_outfile (struct ld_state *statep);
-static void ld_generic_relocate_section (struct ld_state *statep,
- Elf_Scn *outscn,
- struct scninfo *firstp,
- const Elf32_Word *dblindirect);
-static int ld_generic_finalize (struct ld_state *statep);
-static bool ld_generic_special_section_number_p (struct ld_state *statep,
- size_t number);
-static bool ld_generic_section_type_p (struct ld_state *statep,
- XElf_Word type);
-static XElf_Xword ld_generic_dynamic_section_flags (struct ld_state *statep);
-static void ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn);
-static void ld_generic_initialize_pltrel (struct ld_state *statep,
- Elf_Scn *scn);
-static void ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn);
-static void ld_generic_finalize_plt (struct ld_state *statep, size_t nsym,
- size_t nsym_dyn);
-static int ld_generic_rel_type (struct ld_state *statep);
-static void ld_generic_count_relocations (struct ld_state *statep,
- struct scninfo *scninfo);
-static void ld_generic_create_relocations (struct ld_state *statep,
- const Elf32_Word *dblindirect);
-
-static int file_process2 (struct usedfiles *fileinfo);
-static void mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
- struct scninfo **grpscnp);
-
-
-/* Map symbol index to struct symbol record. */
-static struct symbol **ndxtosym;
-
-/* String table reference to all symbols in the symbol table. */
-static struct Ebl_Strent **symstrent;
-
-
-/* Check whether file associated with FD is a DSO. */
-static bool
-is_dso_p (int fd)
-{
- /* We have to read the 'e_type' field. It has the same size (16
- bits) in 32- and 64-bit ELF. */
- XElf_Half e_type;
-
- return (pread (fd, &e_type, sizeof (e_type), offsetof (XElf_Ehdr, e_type))
- == sizeof (e_type)
- && e_type == ET_DYN);
-}
-
-
-/* Print the complete name of a file, including the archive it is
- contained in. */
-static int
-print_file_name (FILE *s, struct usedfiles *fileinfo, int first_level,
- int newline)
-{
- int npar = 0;
-
- if (fileinfo->archive_file != NULL)
- {
- npar = print_file_name (s, fileinfo->archive_file, 0, 0) + 1;
- fputc_unlocked ('(', s);
- fputs_unlocked (fileinfo->rfname, s);
-
- if (first_level)
- while (npar-- > 0)
- fputc_unlocked (')', s);
- }
- else
- fputs_unlocked (fileinfo->rfname, s);
-
- if (first_level && newline)
- fputc_unlocked ('\n', s);
-
- return npar;
-}
-
-
-/* Function to determine whether an object will be dynamically linked. */
-bool
-dynamically_linked_p (void)
-{
- return (ld_state.file_type == dso_file_type || ld_state.nplt > 0
- || ld_state.ngot > 0);
-}
-
-
-bool
-linked_from_dso_p (struct scninfo *scninfo, int symidx)
-{
- struct usedfiles *file = scninfo->fileinfo;
-
- /* If this symbol is not undefined in this file it cannot come from
- a DSO. */
- if (symidx < file->nlocalsymbols)
- return false;
-
- struct symbol *sym = file->symref[symidx];
-
- return sym->defined && sym->in_dso;
-}
-
-
-/* Initialize state object. This callback function is called after the
- parameters are parsed but before any file is searched for. */
-int
-ld_prepare_state (const char *emulation)
-{
- /* When generating DSO we normally allow undefined symbols. */
- ld_state.nodefs = true;
-
- /* To be able to detect problems we add a .comment section entry by
- default. */
- ld_state.add_ld_comment = true;
-
- /* XXX We probably should find a better place for this. The index
- of the first user-defined version is 2. */
- ld_state.nextveridx = 2;
-
- /* Pick an not too small number for the initial size of the tables. */
- ld_symbol_tab_init (&ld_state.symbol_tab, 1027);
- ld_section_tab_init (&ld_state.section_tab, 67);
- ld_version_str_tab_init (&ld_state.version_str_tab, 67);
-
- /* Initialize the section header string table. */
- ld_state.shstrtab = ebl_strtabinit (true);
- if (ld_state.shstrtab == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot create string table"));
-
- /* Initialize the callbacks. These are the defaults, the appropriate
- backend can later install its own callbacks. */
- ld_state.callbacks.lib_extensions = ld_generic_lib_extensions;
- ld_state.callbacks.file_process = ld_generic_file_process;
- ld_state.callbacks.file_close = ld_generic_file_close;
- ld_state.callbacks.generate_sections = ld_generic_generate_sections;
- ld_state.callbacks.create_sections = ld_generic_create_sections;
- ld_state.callbacks.flag_unresolved = ld_generic_flag_unresolved;
- ld_state.callbacks.open_outfile = ld_generic_open_outfile;
- ld_state.callbacks.create_outfile = ld_generic_create_outfile;
- ld_state.callbacks.relocate_section = ld_generic_relocate_section;
- ld_state.callbacks.finalize = ld_generic_finalize;
- ld_state.callbacks.special_section_number_p =
- ld_generic_special_section_number_p;
- ld_state.callbacks.section_type_p = ld_generic_section_type_p;
- ld_state.callbacks.dynamic_section_flags = ld_generic_dynamic_section_flags;
- ld_state.callbacks.initialize_plt = ld_generic_initialize_plt;
- ld_state.callbacks.initialize_pltrel = ld_generic_initialize_pltrel;
- ld_state.callbacks.initialize_got = ld_generic_initialize_got;
- ld_state.callbacks.finalize_plt = ld_generic_finalize_plt;
- ld_state.callbacks.rel_type = ld_generic_rel_type;
- ld_state.callbacks.count_relocations = ld_generic_count_relocations;
- ld_state.callbacks.create_relocations = ld_generic_create_relocations;
-
-#ifndef BASE_ELF_NAME
- /* Find the ld backend library. Use EBL to determine the name if
- the user hasn't provided one on the command line. */
- if (emulation == NULL)
- {
- emulation = ebl_backend_name (ld_state.ebl);
- assert (emulation != NULL);
- }
- size_t emulation_len = strlen (emulation);
-
- /* Construct the file name. */
- char *fname = (char *) alloca (sizeof "libld_" - 1 + emulation_len
- + sizeof ".so");
- strcpy (mempcpy (stpcpy (fname, "libld_"), emulation, emulation_len), ".so");
-
- /* Try loading. */
- void *h = dlopen (fname, RTLD_LAZY);
- if (h == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot load ld backend library '%s': %s"),
- fname, dlerror ());
-
- /* Find the initializer. It must be present. */
- char *initname = (char *) alloca (emulation_len + sizeof "_ld_init");
- strcpy (mempcpy (initname, emulation, emulation_len), "_ld_init");
- int (*initfct) (struct ld_state *)
- = (int (*) (struct ld_state *)) dlsym (h, initname);
-
- if (initfct == NULL)
- error (EXIT_FAILURE, 0, gettext ("\
-cannot find init function in ld backend library '%s': %s"),
- fname, dlerror ());
-
- /* Store the handle. */
- ld_state.ldlib = h;
-
- /* Call the init function. */
- return initfct (&ld_state);
-#else
-# define INIT_FCT_NAME(base) _INIT_FCT_NAME(base)
-# define _INIT_FCT_NAME(base) base##_ld_init
- /* Declare and call the initialization function. */
- extern int INIT_FCT_NAME(BASE_ELF_NAME) (struct ld_state *);
- return INIT_FCT_NAME(BASE_ELF_NAME) (&ld_state);
-#endif
-}
-
-
-static int
-check_for_duplicate2 (struct usedfiles *newp, struct usedfiles *list)
-{
- struct usedfiles *first;
- struct usedfiles *prevp;
-
- if (list == NULL)
- return 0;
-
- prevp = list;
- list = first = list->next;
- do
- {
- /* When searching the needed list we might come across entries
- for files which are not yet opened. Stop then, there is
- nothing more to test. */
- if (likely (list->status == not_opened))
- break;
-
- if (unlikely (list->ino == newp->ino)
- && unlikely (list->dev == newp->dev))
- {
- close (newp->fd);
- newp->fd = -1;
- newp->status = closed;
- if (newp->file_type == relocatable_file_type)
- error (0, 0, gettext ("%s listed more than once as input"),
- newp->rfname);
-
- return 1;
- }
- list = list->next;
- }
- while (likely (list != first));
-
- return 0;
-}
-
-
-static int
-check_for_duplicate (struct usedfiles *newp)
-{
- struct stat st;
-
- if (unlikely (fstat (newp->fd, &st) < 0))
- {
- close (newp->fd);
- return errno;
- }
-
- newp->dev = st.st_dev;
- newp->ino = st.st_ino;
-
- return (check_for_duplicate2 (newp, ld_state.relfiles)
- || check_for_duplicate2 (newp, ld_state.dsofiles)
- || check_for_duplicate2 (newp, ld_state.needed));
-}
-
-
-/* Find a file along the path described in the state. */
-static int
-open_along_path2 (struct usedfiles *fileinfo, struct pathelement *path)
-{
- const char *fname = fileinfo->fname;
- size_t fnamelen = strlen (fname);
- int err = ENOENT;
- struct pathelement *firstp = path;
-
- if (path == NULL)
- /* Cannot find anything since we have no path. */
- return ENOENT;
-
- do
- {
- if (likely (path->exist >= 0))
- {
- /* Create the file name. */
- char *rfname = NULL;
- size_t dirlen = strlen (path->pname);
- int fd = -1;
-
- if (fileinfo->file_type == archive_file_type)
- {
- const char **exts = (ld_state.statically
- ? (const char *[2]) { ".a", NULL }
- : LIB_EXTENSION (&ld_state));
-
- /* We have to create the actual file name. We prepend "lib"
- and add one of the extensions the platform has. */
- while (*exts != NULL)
- {
- size_t extlen = strlen (*exts);
- rfname = (char *) alloca (dirlen + 5 + fnamelen + extlen);
- memcpy (mempcpy (stpcpy (mempcpy (rfname, path->pname,
- dirlen),
- "/lib"),
- fname, fnamelen),
- *exts, extlen + 1);
-
- fd = open (rfname, O_RDONLY);
- if (likely (fd != -1) || errno != ENOENT)
- {
- err = fd == -1 ? errno : 0;
- break;
- }
-
- /* Next extension. */
- ++exts;
- }
- }
- else
- {
- assert (fileinfo->file_type == dso_file_type
- || fileinfo->file_type == dso_needed_file_type);
-
- rfname = (char *) alloca (dirlen + 1 + fnamelen + 1);
- memcpy (stpcpy (mempcpy (rfname, path->pname, dirlen), "/"),
- fname, fnamelen + 1);
-
- fd = open (rfname, O_RDONLY);
- if (unlikely (fd == -1))
- err = errno;
- }
-
- if (likely (fd != -1))
- {
- /* We found the file. This also means the directory
- exists. */
- fileinfo->fd = fd;
- path->exist = 1;
-
- /* Check whether we have this file already loaded. */
- if (unlikely (check_for_duplicate (fileinfo) != 0))
- return EAGAIN;
-
- /* Make a copy of the name. */
- fileinfo->rfname = obstack_strdup (&ld_state.smem, rfname);
-
- if (unlikely (ld_state.trace_files))
- printf (fileinfo->file_type == archive_file_type
- ? gettext ("%s (for -l%s)\n")
- : gettext ("%s (for DT_NEEDED %s)\n"),
- rfname, fname);
-
- return 0;
- }
-
- /* The file does not exist. Maybe the whole directory doesn't.
- Check it unless we know it exists. */
- if (unlikely (path->exist == 0))
- {
- struct stat st;
-
- /* Keep only the directory name. Note that the path
- might be relative. This doesn't matter here. We do
- the test in any case even if there is the chance that
- somebody wants to change the programs working
- directory at some point which would make the result
- of this test void. Since changing the working
- directory is completely wrong we are not taking this
- case into account. */
- rfname[dirlen] = '\0';
- if (unlikely (stat (rfname, &st) < 0) || ! S_ISDIR (st.st_mode))
- /* The directory does not exist or the named file is no
- directory. */
- path->exist = -1;
- else
- path->exist = 1;
- }
- }
-
- /* Next path element. */
- path = path->next;
- }
- while (likely (err == ENOENT && path != firstp));
-
- return err;
-}
-
-
-static int
-open_along_path (struct usedfiles *fileinfo)
-{
- const char *fname = fileinfo->fname;
- int err = ENOENT;
-
- if (fileinfo->file_type == relocatable_file_type)
- {
- /* Only libraries are searched along the path. */
- fileinfo->fd = open (fname, O_RDONLY);
-
- if (likely (fileinfo->fd != -1))
- {
- /* We found the file. */
- if (unlikely (ld_state.trace_files))
- print_file_name (stdout, fileinfo, 1, 1);
-
- return check_for_duplicate (fileinfo);
- }
-
- /* If the name is an absolute path we are done. */
- err = errno;
- }
- else
- {
- /* If the user specified two parts to the LD_LIBRARY_PATH variable
- try the first part now. */
- err = open_along_path2 (fileinfo, ld_state.ld_library_path1);
-
- /* Try the user-specified path next. */
- if (err == ENOENT)
- err = open_along_path2 (fileinfo,
- fileinfo->file_type == archive_file_type
- ? ld_state.paths : ld_state.rpath_link);
-
- /* Then the second part of the LD_LIBRARY_PATH value. */
- if (unlikely (err == ENOENT))
- {
- err = open_along_path2 (fileinfo, ld_state.ld_library_path2);
-
- /* In case we look for a DSO handle now the RUNPATH. */
- if (err == ENOENT)
- {
- if (fileinfo->file_type == dso_file_type)
- err = open_along_path2 (fileinfo, ld_state.runpath_link);
-
- /* Finally the path from the default linker script. */
- if (err == ENOENT)
- err = open_along_path2 (fileinfo, ld_state.default_paths);
- }
- }
- }
-
- if (unlikely (err != 0)
- && (err != EAGAIN || fileinfo->file_type == relocatable_file_type))
- error (0, err, gettext ("cannot open %s"), fileinfo->fname);
-
- return err;
-}
-
-
-static void
-check_type_and_size (const XElf_Sym *sym, struct usedfiles *fileinfo,
- struct symbol *oldp)
-{
- /* We check the type and size of the symbols. In both cases the
- information can be missing (size is zero, type is STT_NOTYPE) in
- which case we issue no warnings. Otherwise everything must
- match. If the type does not match there is no point in checking
- the size. */
-
- if (XELF_ST_TYPE (sym->st_info) != STT_NOTYPE && oldp->type != STT_NOTYPE
- && unlikely (oldp->type != XELF_ST_TYPE (sym->st_info)))
- {
- char buf1[64];
- char buf2[64];
-
- error (0, 0, gettext ("\
-Warning: type of `%s' changed from %s in %s to %s in %s"),
- oldp->name,
- ebl_symbol_type_name (ld_state.ebl, oldp->type,
- buf1, sizeof (buf1)),
- oldp->file->rfname,
- ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
- buf2, sizeof (buf2)),
- fileinfo->rfname);
- }
- else if (XELF_ST_TYPE (sym->st_info) == STT_OBJECT
- && oldp->size != 0
- && unlikely (oldp->size != sym->st_size))
- error (0, 0, gettext ("\
-Warning: size of `%s' changed from %" PRIu64 " in %s to %" PRIu64 " in %s"),
- oldp->name, (uint64_t) oldp->size, oldp->file->rfname,
- (uint64_t) sym->st_size, fileinfo->rfname);
-}
-
-
-static int
-check_definition (const XElf_Sym *sym, size_t symidx,
- struct usedfiles *fileinfo, struct symbol *oldp)
-{
- int result = 0;
- bool old_in_dso = FILEINFO_EHDR (oldp->file->ehdr).e_type == ET_DYN;
- bool new_in_dso = FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN;
- bool use_new_def = false;
-
- if (sym->st_shndx != SHN_UNDEF
- && (! oldp->defined
- || (sym->st_shndx != SHN_COMMON && oldp->common && ! new_in_dso)
- || (old_in_dso && ! new_in_dso)))
- {
- /* We found a definition for a previously undefined symbol or a
- real definition for a previous common-only definition or a
- redefinition of a symbol definition in an object file
- previously defined in a DSO. First perform some tests which
- will show whether the common is really matching the
- definition. */
- check_type_and_size (sym, fileinfo, oldp);
-
- /* We leave the next element intact to not interrupt the list
- with the unresolved symbols. Whoever walks the list will
- have to check the `defined' flag. But we remember that this
- list element is not unresolved anymore. */
- if (! oldp->defined)
- {
- /* Remove from the list. */
- --ld_state.nunresolved;
- if (! oldp->weak)
- --ld_state.nunresolved_nonweak;
- CDBL_LIST_DEL (ld_state.unresolved, oldp);
- }
- else if (oldp->common)
- /* Remove from the list. */
- CDBL_LIST_DEL (ld_state.common_syms, oldp);
-
- /* Use the values of the definition from now on. */
- use_new_def = true;
- }
- else if (sym->st_shndx != SHN_UNDEF
- && unlikely (! oldp->common)
- && oldp->defined
- && sym->st_shndx != SHN_COMMON
- /* Multiple definitions are no fatal errors if the -z muldefs flag
- is used. We don't warn about the multiple definition unless we
- are told to be verbose. */
- && (!ld_state.muldefs || verbose)
- && ! old_in_dso && fileinfo->file_type == relocatable_file_type)
- {
- /* We have a double definition. This is a problem. */
- char buf[64];
- XElf_Sym_vardef (oldsym);
- struct usedfiles *oldfile;
- const char *scnname;
- Elf32_Word xndx;
- size_t shndx;
- size_t shnum;
-
- if (elf_getshnum (fileinfo->elf, &shnum) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot determine number of sections: %s"),
- elf_errmsg (-1));
-
- /* XXX Use only ebl_section_name. */
- if (sym->st_shndx < SHN_LORESERVE // || sym->st_shndx > SHN_HIRESERVE
- && sym->st_shndx < shnum)
- scnname = elf_strptr (fileinfo->elf,
- fileinfo->shstrndx,
- SCNINFO_SHDR (fileinfo->scninfo[sym->st_shndx].shdr).sh_name);
- else
- // XXX extended section
- scnname = ebl_section_name (ld_state.ebl, sym->st_shndx, 0,
- buf, sizeof (buf), NULL, shnum);
-
- /* XXX Print source file and line number. */
- print_file_name (stderr, fileinfo, 1, 0);
- fprintf (stderr,
- gettext ("(%s+%#" PRIx64 "): multiple definition of %s `%s'\n"),
- scnname,
- (uint64_t) sym->st_value,
- ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
- buf, sizeof (buf)),
- oldp->name);
-
- oldfile = oldp->file;
- xelf_getsymshndx (oldfile->symtabdata, oldfile->xndxdata, oldp->symidx,
- oldsym, xndx);
- if (oldsym == NULL)
- /* This should never happen since the same call
- succeeded before. */
- abort ();
-
- shndx = oldsym->st_shndx;
- if (unlikely (oldsym->st_shndx == SHN_XINDEX))
- shndx = xndx;
-
- /* XXX Use only ebl_section_name. */
- if (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
- scnname = elf_strptr (oldfile->elf,
- oldfile->shstrndx,
- SCNINFO_SHDR (oldfile->scninfo[shndx].shdr).sh_name);
- else
- scnname = ebl_section_name (ld_state.ebl, oldsym->st_shndx, shndx, buf,
- sizeof (buf), NULL, shnum);
-
- /* XXX Print source file and line number. */
- print_file_name (stderr, oldfile, 1, 0);
- fprintf (stderr, gettext ("(%s+%#" PRIx64 "): first defined here\n"),
- scnname, (uint64_t) oldsym->st_value);
-
- if (likely (!ld_state.muldefs))
- result = 1;
- }
- else if (old_in_dso && fileinfo->file_type == relocatable_file_type
- && sym->st_shndx != SHN_UNDEF)
- /* We use the definition from a normal relocatable file over the
- definition in a DSO. This is what the dynamic linker would
- do, too. */
- use_new_def = true;
- else if (old_in_dso && !new_in_dso && oldp->defined && !oldp->on_dsolist)
- {
- CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
- ++ld_state.nfrom_dso;
-
- /* If the object is a function we allocate a PLT entry,
- otherwise only a GOT entry. */
- if (oldp->type == STT_FUNC)
- ++ld_state.nplt;
- else
- ++ld_state.ngot;
-
- oldp->on_dsolist = 1;
- }
- else if (oldp->common && sym->st_shndx == SHN_COMMON)
- {
- /* The symbol size is the largest of all common definitions. */
- oldp->size = MAX (oldp->size, sym->st_size);
- /* Similarly for the alignment. */
- oldp->merge.value = MAX (oldp->merge.value, sym->st_value);
- }
-
- if (unlikely (use_new_def))
- {
- /* Adjust the symbol record appropriately and remove
- the symbol from the list of symbols which are taken from DSOs. */
- if (old_in_dso && fileinfo->file_type == relocatable_file_type)
- {
- CDBL_LIST_DEL (ld_state.from_dso, oldp);
- --ld_state.nfrom_dso;
-
- if (likely (oldp->type == STT_FUNC))
- --ld_state.nplt;
- else
- --ld_state.ngot;
-
- oldp->on_dsolist = 0;
- }
-
- /* Use the values of the definition from now on. */
- oldp->size = sym->st_size;
- oldp->type = XELF_ST_TYPE (sym->st_info);
- oldp->symidx = symidx;
- oldp->scndx = sym->st_shndx;
- //oldp->symscndx = THESYMSCNDX must be passed;
- oldp->file = fileinfo;
- oldp->defined = 1;
- oldp->in_dso = new_in_dso;
- oldp->common = sym->st_shndx == SHN_COMMON;
- if (likely (fileinfo->file_type == relocatable_file_type))
- {
- /* If the definition comes from a DSO we pertain the weak flag
- and it's indicating whether the reference is weak or not. */
- oldp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
-
- if (sym->st_shndx != SHN_COMMON)
- {
- struct scninfo *ignore;
- mark_section_used (&fileinfo->scninfo[sym->st_shndx],
- sym->st_shndx, &ignore);
- }
- }
-
- /* Add to the list of symbols used from DSOs if necessary. */
- if (new_in_dso && !old_in_dso)
- {
- CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
- ++ld_state.nfrom_dso;
-
- /* If the object is a function we allocate a PLT entry,
- otherwise only a GOT entry. */
- if (oldp->type == STT_FUNC)
- ++ld_state.nplt;
- else
- ++ld_state.ngot;
-
- oldp->on_dsolist = 1;
- }
- else if (sym->st_shndx == SHN_COMMON)
- {
- /* Store the alignment. */
- oldp->merge.value = sym->st_value;
-
- CDBL_LIST_ADD_REAR (ld_state.common_syms, oldp);
- }
- }
-
- return result;
-}
-
-
-static struct scninfo *
-find_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
- Elf_Data **datap)
-{
- struct scninfo *runp;
-
- for (runp = fileinfo->groups; runp != NULL; runp = runp->next)
- if (!runp->used)
- {
- Elf32_Word *grpref;
- size_t cnt;
- Elf_Data *data;
-
- data = elf_getdata (runp->scn, NULL);
- if (data == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("%s: cannot get section group data: %s"),
- fileinfo->fname, elf_errmsg (-1));
-
- /* There cannot be another data block. */
- assert (elf_getdata (runp->scn, data) == NULL);
-
- grpref = (Elf32_Word *) data->d_buf;
- cnt = data->d_size / sizeof (Elf32_Word);
- /* Note that we stop after looking at index 1 since index 0
- contains the flags for the section group. */
- while (cnt > 1)
- if (grpref[--cnt] == shndx)
- {
- *datap = data;
- return runp;
- }
- }
-
- /* If we come here no section group contained the given section
- despite the SHF_GROUP flag. This is an error in the input
- file. */
- error (EXIT_FAILURE, 0, gettext ("\
-%s: section '%s' with group flag set does not belong to any group"),
- fileinfo->fname,
- elf_strptr (fileinfo->elf, fileinfo->shstrndx,
- SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_name));
- return NULL;
-}
-
-
-/* Mark all sections which belong to the same group as section SHNDX
- as used. */
-static void
-mark_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
- struct scninfo **grpscnp)
-{
- /* First locate the section group. There can be several (many) of
- them. */
- size_t cnt;
- Elf32_Word *grpref;
- Elf_Data *data;
- struct scninfo *grpscn = find_section_group (fileinfo, shndx, &data);
- *grpscnp = grpscn;
-
- /* Mark all the sections as used.
-
- XXX Two possible problems here:
-
- - the gABI says "The section must be referenced by a section of type
- SHT_GROUP". I hope everybody reads this as "exactly one section".
-
- - section groups are also useful to mark the debugging section which
- belongs to a text section. Unconditionally adding debugging sections
- is therefore probably not what is wanted if stripping is required. */
-
- /* Mark the section group as handled. */
- grpscn->used = true;
-
- grpref = (Elf32_Word *) data->d_buf;
- cnt = data->d_size / sizeof (Elf32_Word);
- while (cnt > 1)
- {
- Elf32_Word idx = grpref[--cnt];
- XElf_Shdr *shdr = &SCNINFO_SHDR (fileinfo->scninfo[idx].shdr);
-
- if (fileinfo->scninfo[idx].grpid != 0)
- error (EXIT_FAILURE, 0, gettext ("\
-%s: section [%2d] '%s' is in more than one section group"),
- fileinfo->fname, (int) idx,
- elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name));
-
- fileinfo->scninfo[idx].grpid = grpscn->grpid;
-
- if (ld_state.strip == strip_none
- /* If we are stripping, remove debug sections. */
- || (!ebl_debugscn_p (ld_state.ebl,
- elf_strptr (fileinfo->elf, fileinfo->shstrndx,
- shdr->sh_name))
- /* And the relocation sections for the debug sections. */
- && ((shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
- || !ebl_debugscn_p (ld_state.ebl,
- elf_strptr (fileinfo->elf,
- fileinfo->shstrndx,
- SCNINFO_SHDR (fileinfo->scninfo[shdr->sh_info].shdr).sh_name)))))
- {
- struct scninfo *ignore;
-
- mark_section_used (&fileinfo->scninfo[idx], idx, &ignore);
- }
- }
-}
-
-
-static void
-mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
- struct scninfo **grpscnp)
-{
- if (likely (scninfo->used))
- /* Nothing to be done. */
- return;
-
- /* We need this section. */
- scninfo->used = true;
-
- /* Make sure the section header has been read from the file. */
- XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
-#if NATIVE_ELF
- if (unlikely (scninfo->shdr == NULL))
-#else
- if (unlikely (scninfo->shdr.sh_type == SHT_NULL))
-#endif
- {
-#if NATIVE_ELF != 0
- shdr = xelf_getshdr (scninfo->scn, scninfo->shdr);
-#else
- xelf_getshdr_copy (scninfo->scn, shdr, scninfo->shdr);
-#endif
- if (unlikely (shdr == NULL))
- /* Something is very wrong. The calling code will notice it
- soon and print a message. */
- return;
- }
-
- /* Handle section linked by 'sh_link'. */
- if (unlikely (shdr->sh_link != 0))
- {
- struct scninfo *ignore;
- mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_link],
- shdr->sh_link, &ignore);
- }
-
- /* Handle section linked by 'sh_info'. */
- if (unlikely (shdr->sh_info != 0) && (shdr->sh_flags & SHF_INFO_LINK))
- {
- struct scninfo *ignore;
- mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_info],
- shdr->sh_info, &ignore);
- }
-
- if (unlikely (shdr->sh_flags & SHF_GROUP) && ld_state.gc_sections)
- /* Find the section group which contains this section. */
- mark_section_group (scninfo->fileinfo, shndx, grpscnp);
-}
-
-
-/* We collect all sections in a hashing table. All sections with the
- same name are collected in a list. Note that we do not determine
- which sections are finally collected in the same output section
- here. This would be terribly inefficient. It will be done later. */
-static void
-add_section (struct usedfiles *fileinfo, struct scninfo *scninfo)
-{
- struct scnhead *queued;
- struct scnhead search;
- unsigned long int hval;
- XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
- struct scninfo *grpscn = NULL;
- Elf_Data *grpscndata = NULL;
-
- /* See whether we can determine right away whether we need this
- section in the output.
-
- XXX I assume here that --gc-sections only affects extraction
- from an archive. If it also affects objects files given on
- the command line then somebody must explain to me how the
- dependency analysis should work. Should the entry point be
- the root? What if it is a numeric value? */
- if (!scninfo->used
- && (ld_state.strip == strip_none
- || (shdr->sh_flags & SHF_ALLOC) != 0
- || shdr->sh_type == SHT_NOTE
- || (shdr->sh_type == SHT_PROGBITS
- && strcmp (elf_strptr (fileinfo->elf,
- fileinfo->shstrndx,
- shdr->sh_name), ".comment") == 0))
- && (fileinfo->status != in_archive || !ld_state.gc_sections))
- /* Mark as used and handle reference recursively if necessary. */
- mark_section_used (scninfo, elf_ndxscn (scninfo->scn), &grpscn);
-
- if ((shdr->sh_flags & SHF_GROUP) && grpscn == NULL)
- /* Determine the symbol which name constitutes the signature
- for the section group. */
- grpscn = find_section_group (fileinfo, elf_ndxscn (scninfo->scn),
- &grpscndata);
- assert (grpscn == NULL || grpscn->symbols->name != NULL);
-
- /* Determine the section name. */
- search.name = elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name);
- search.type = shdr->sh_type;
- search.flags = shdr->sh_flags;
- search.entsize = shdr->sh_entsize;
- search.grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
- search.kind = scn_normal;
- hval = elf_hash (search.name);
-
- /* Find already queued sections. */
- queued = ld_section_tab_find (&ld_state.section_tab, hval, &search);
- if (queued != NULL)
- {
- bool is_comdat = false;
-
- /* If this section is part of a COMDAT section group we simply
- ignore it since we already have a copy. */
- if (unlikely (shdr->sh_flags & SHF_GROUP))
- {
- /* Get the data of the section group section. */
- if (grpscndata == NULL)
- {
- grpscndata = elf_getdata (grpscn->scn, NULL);
- assert (grpscndata != NULL);
- }
-
- /* XXX Possibly unaligned memory access. */
- is_comdat = ((Elf32_Word *) grpscndata->d_buf)[0] & GRP_COMDAT;
- }
-
- if (!is_comdat)
- {
- /* No COMDAT section, we use the data. */
- scninfo->next = queued->last->next;
- queued->last = queued->last->next = scninfo;
-
- queued->flags = SH_FLAGS_COMBINE (queued->flags, shdr->sh_flags);
- queued->align = MAX (queued->align, shdr->sh_addralign);
- }
- }
- else
- {
- /* We do not use obstacks here since the memory might be
- deallocated. */
- queued = (struct scnhead *) xcalloc (sizeof (struct scnhead), 1);
- queued->kind = scn_normal;
- queued->name = search.name;
- queued->type = shdr->sh_type;
- queued->flags = shdr->sh_flags;
- queued->align = shdr->sh_addralign;
- queued->entsize = shdr->sh_entsize;
- queued->grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
- queued->segment_nr = ~0;
- queued->last = scninfo->next = scninfo;
-
- /* Add to the hash table and possibly overwrite existing value. */
- ld_section_tab_insert (&ld_state.section_tab, hval, queued);
- }
-}
-
-
-static int
-add_relocatable_file (struct usedfiles *fileinfo, int secttype)
-{
- size_t scncnt;
- size_t cnt;
- Elf_Data *symtabdata = NULL;
- Elf_Data *xndxdata = NULL;
- Elf_Data *versymdata = NULL;
- Elf_Data *verdefdata = NULL;
- Elf_Data *verneeddata = NULL;
- size_t symstridx = 0;
- size_t nsymbols = 0;
- size_t nlocalsymbols = 0;
- bool has_merge_sections = false;
-
- /* Prerequisites. */
- assert (fileinfo->elf != NULL);
-
- /* Allocate memory for the sections. */
- if (unlikely (elf_getshnum (fileinfo->elf, &scncnt) < 0))
- error (EXIT_FAILURE, 0,
- gettext ("cannot determine number of sections: %s"),
- elf_errmsg (-1));
-
- fileinfo->scninfo = (struct scninfo *)
- obstack_calloc (&ld_state.smem, scncnt * sizeof (struct scninfo));
-
- /* Read all the section headers and find the symbol table. Note
- that we don't skip the section with index zero. Even though the
- section itself is always empty the section header contains
- informaton for the case when the section index for the section
- header string table is too large to fit in the ELF header. */
- for (cnt = 0; cnt < scncnt; ++cnt)
- {
- /* Store the handle for the section. */
- fileinfo->scninfo[cnt].scn = elf_getscn (fileinfo->elf, cnt);
-
- /* Get the ELF section header and data. */
- XElf_Shdr *shdr;
-#if NATIVE_ELF != 0
- if (fileinfo->scninfo[cnt].shdr == NULL)
-#else
- if (fileinfo->scninfo[cnt].shdr.sh_type == SHT_NULL)
-#endif
- {
-#if NATIVE_ELF != 0
- shdr = xelf_getshdr (fileinfo->scninfo[cnt].scn,
- fileinfo->scninfo[cnt].shdr);
-#else
- xelf_getshdr_copy (fileinfo->scninfo[cnt].scn, shdr,
- fileinfo->scninfo[cnt].shdr);
-#endif
- if (shdr == NULL)
- {
- /* This should never happen. */
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
- }
- else
- shdr = &SCNINFO_SHDR (fileinfo->scninfo[cnt].shdr);
-
- Elf_Data *data = elf_getdata (fileinfo->scninfo[cnt].scn, NULL);
-
- /* Check whether this section is marked as merge-able. */
- has_merge_sections |= (shdr->sh_flags & SHF_MERGE) != 0;
-
- /* Get the ELF section header and data. */
- /* Make the file structure available. */
- fileinfo->scninfo[cnt].fileinfo = fileinfo;
-
- if (unlikely (shdr->sh_type == SHT_SYMTAB)
- || unlikely (shdr->sh_type == SHT_DYNSYM))
- {
- if (shdr->sh_type == SHT_SYMTAB)
- {
- assert (fileinfo->symtabdata == NULL);
- fileinfo->symtabdata = data;
- fileinfo->nsymtab = shdr->sh_size / shdr->sh_entsize;
- fileinfo->nlocalsymbols = shdr->sh_info;
- fileinfo->symstridx = shdr->sh_link;
- }
- else
- {
- assert (fileinfo->dynsymtabdata == NULL);
- fileinfo->dynsymtabdata = data;
- fileinfo->ndynsymtab = shdr->sh_size / shdr->sh_entsize;
- fileinfo->dynsymstridx = shdr->sh_link;
- }
-
- /* If we are looking for the normal symbol table we just
- found it. */
- if (secttype == shdr->sh_type)
- {
- assert (symtabdata == NULL);
- symtabdata = data;
- symstridx = shdr->sh_link;
- nsymbols = shdr->sh_size / shdr->sh_entsize;
- nlocalsymbols = shdr->sh_info;
- }
- }
- else if (unlikely (shdr->sh_type == SHT_SYMTAB_SHNDX))
- {
- assert (xndxdata == NULL);
- fileinfo->xndxdata = xndxdata = data;
- }
- else if (unlikely (shdr->sh_type == SHT_GNU_versym))
- {
- assert (versymdata == 0);
- fileinfo->versymdata = versymdata = data;
- }
- else if (unlikely (shdr->sh_type == SHT_GNU_verdef))
- {
- size_t nversions;
-
- assert (verdefdata == 0);
- fileinfo->verdefdata = verdefdata = data;
-
- /* Allocate the arrays flagging the use of the version and
- to track of allocated names. */
- fileinfo->nverdef = nversions = shdr->sh_info;
- /* We have NVERSIONS + 1 because the indeces used to access the
- sectino start with one; zero represents local binding. */
- fileinfo->verdefused = (XElf_Versym *)
- obstack_calloc (&ld_state.smem,
- sizeof (XElf_Versym) * (nversions + 1));
- fileinfo->verdefent = (struct Ebl_Strent **)
- obstack_alloc (&ld_state.smem,
- sizeof (struct Ebl_Strent *) * (nversions + 1));
- }
- else if (unlikely (shdr->sh_type == SHT_GNU_verneed))
- {
- assert (verneeddata == 0);
- fileinfo->verneeddata = verneeddata = data;
- }
- else if (unlikely (shdr->sh_type == SHT_DYNAMIC))
- {
- assert (fileinfo->dynscn == NULL);
- fileinfo->dynscn = fileinfo->scninfo[cnt].scn;
- }
- else if (unlikely (shdr->sh_type == SHT_GROUP))
- {
- Elf_Scn *symscn;
- XElf_Shdr_vardef (symshdr);
- Elf_Data *symdata;
-
- if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL)
- error (EXIT_FAILURE, 0, gettext ("\
-%s: only files of type ET_REL might contain section groups"),
- fileinfo->fname);
-
- fileinfo->scninfo[cnt].next = fileinfo->groups;
- fileinfo->scninfo[cnt].grpid = cnt;
- fileinfo->groups = &fileinfo->scninfo[cnt];
-
- /* Determine the signature. We create a symbol record for
- it. Only the name element is important. */
- fileinfo->scninfo[cnt].symbols = (struct symbol *)
- obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
- symscn = elf_getscn (fileinfo->elf, shdr->sh_link);
- xelf_getshdr (symscn, symshdr);
- symdata = elf_getdata (symscn, NULL);
- if (symshdr != NULL)
- {
- XElf_Sym_vardef (sym);
-
- /* We don't need the section index and therefore we don't
- have to use 'xelf_getsymshndx'. */
- xelf_getsym (symdata, shdr->sh_info, sym);
- if (sym != NULL)
- {
- struct symbol *symbol = fileinfo->scninfo[cnt].symbols;
-
- symbol->name = elf_strptr (fileinfo->elf, symshdr->sh_link,
- sym->st_name);
- symbol->symidx = shdr->sh_info;
- symbol->file = fileinfo;
- }
- }
- if (fileinfo->scninfo[cnt].symbols->name == NULL)
- error (EXIT_FAILURE, 0, gettext ("\
-%s: cannot determine signature of section group [%2zd] '%s': %s"),
- fileinfo->fname,
- elf_ndxscn (fileinfo->scninfo[cnt].scn),
- elf_strptr (fileinfo->elf, fileinfo->shstrndx,
- shdr->sh_name),
- elf_errmsg (-1));
-
- /* The 'used' flag is used to indicate when the information
- in the section group is used to mark all other sections
- as used. So it must not be true yet. */
- assert (fileinfo->scninfo[cnt].used == false);
- }
- else if (! SECTION_TYPE_P (&ld_state, shdr->sh_type)
- && unlikely ((shdr->sh_flags & SHF_OS_NONCONFORMING) != 0))
- /* According to the gABI it is a fatal error if the file contains
- a section with unknown type and the SHF_OS_NONCONFORMING flag
- set. */
- error (EXIT_FAILURE, 0,
- gettext ("%s: section '%s' has unknown type: %d"),
- fileinfo->fname,
- elf_strptr (fileinfo->elf, fileinfo->shstrndx,
- shdr->sh_name),
- (int) shdr->sh_type);
- /* We don't have to add a few section types here. These will be
- generated from scratch for the new output file. We also
- don't add the sections of DSOs here since these sections are
- not used in the resulting object file. */
- else if (likely (fileinfo->file_type == relocatable_file_type)
- && likely (cnt > 0)
- && likely (shdr->sh_type == SHT_PROGBITS
- || shdr->sh_type == SHT_RELA
- || shdr->sh_type == SHT_REL
- || shdr->sh_type == SHT_NOTE
- || shdr->sh_type == SHT_NOBITS
- || shdr->sh_type == SHT_INIT_ARRAY
- || shdr->sh_type == SHT_FINI_ARRAY
- || shdr->sh_type == SHT_PREINIT_ARRAY))
- add_section (fileinfo, &fileinfo->scninfo[cnt]);
- }
-
- /* Handle the symbols. Record defined and undefined symbols in the
- hash table. In theory there can be a file without any symbol
- table. */
- if (likely (symtabdata != NULL))
- {
- /* In case this file contains merge-able sections we have to
- locate the symbols which are in these sections. */
- fileinfo->has_merge_sections = has_merge_sections;
- if (likely (has_merge_sections))
- {
- fileinfo->symref = (struct symbol **)
- obstack_calloc (&ld_state.smem,
- nsymbols * sizeof (struct symbol *));
-
- /* Only handle the local symbols here. */
- for (cnt = 0; cnt < nlocalsymbols; ++cnt)
- {
- Elf32_Word shndx;
- XElf_Sym_vardef (sym);
-
- xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
- if (sym == NULL)
- {
- /* This should never happen. */
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
-
- if (likely (shndx != SHN_XINDEX))
- shndx = sym->st_shndx;
- else if (unlikely (shndx == 0))
- {
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
-
- if (XELF_ST_TYPE (sym->st_info) != STT_SECTION
- && (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
- && (SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
- & SHF_MERGE))
- {
- /* Create a symbol record for this symbol and add it
- to the list for this section. */
- struct symbol *newp;
-
- newp = (struct symbol *)
- obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
- newp->symidx = cnt;
- newp->scndx = shndx;
- newp->file = fileinfo;
- fileinfo->symref[cnt] = newp;
-
- if (fileinfo->scninfo[shndx].symbols == NULL)
- fileinfo->scninfo[shndx].symbols = newp->next_in_scn
- = newp;
- else
- {
- newp->next_in_scn
- = fileinfo->scninfo[shndx].symbols->next_in_scn;
- fileinfo->scninfo[shndx].symbols
- = fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
- }
- }
- }
- }
- else
- /* Create array with pointers to the symbol definitions. Note
- that we only allocate memory for the non-local symbols
- since we have no merge-able sections. But we store the
- pointer as if it was for the whole symbol table. This
- saves some memory. */
- fileinfo->symref = (struct symbol **)
- obstack_calloc (&ld_state.smem, ((nsymbols - nlocalsymbols)
- * sizeof (struct symbol *)))
- - nlocalsymbols;
-
- /* Don't handle local symbols here. It's either not necessary
- at all or has already happened. */
- for (cnt = nlocalsymbols; cnt < nsymbols; ++cnt)
- {
- XElf_Sym_vardef (sym);
- Elf32_Word shndx;
- xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
-
- if (sym == NULL)
- {
- /* This should never happen. */
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
-
- if (likely (shndx != SHN_XINDEX))
- shndx = sym->st_shndx;
- else if (unlikely (shndx == 0))
- {
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
-
- /* We ignore ABS symbols from DSOs. */
- // XXX Is this correct?
- if (unlikely (shndx == SHN_ABS) && secttype == SHT_DYNSYM)
- continue;
-
- /* If the DSO uses symbols determine whether this is the default
- version. Otherwise we'll ignore the symbol. */
- if (versymdata != NULL)
- {
- XElf_Versym versym;
-
- if (xelf_getversym_copy (versymdata, cnt, versym) == NULL)
- /* XXX Should we handle faulty input files more graceful? */
- assert (! "xelf_getversym failed");
-
- if ((versym & 0x8000) != 0)
- /* Ignore the symbol, it's not the default version. */
- continue;
- }
-
- /* See whether we know anything about this symbol. */
- struct symbol search;
- search.name = elf_strptr (fileinfo->elf, symstridx, sym->st_name);
- unsigned long int hval = elf_hash (search.name);
-
- /* We ignore the symbols the linker generates. This are
- _GLOBAL_OFFSET_TABLE_, _DYNAMIC. */
- // XXX This loop is hot and the following tests hardly ever match.
- // XXX Maybe move the tests somewhere they are executed less often.
- if (((unlikely (hval == 165832675)
- && strcmp (search.name, "_DYNAMIC") == 0)
- || (unlikely (hval == 102264335)
- && strcmp (search.name, "_GLOBAL_OFFSET_TABLE_") == 0))
- && sym->st_shndx != SHN_UNDEF
- /* If somebody defines such a variable in a relocatable we
- don't ignore it. Let the user get what s/he deserves. */
- && fileinfo->file_type != relocatable_file_type)
- continue;
-
- struct symbol *oldp = ld_symbol_tab_find (&ld_state.symbol_tab,
- hval, &search);
- struct symbol *newp;
- if (likely (oldp == NULL))
- {
- /* No symbol of this name know. Add it. */
- newp = (struct symbol *) obstack_alloc (&ld_state.smem,
- sizeof (*newp));
- newp->name = search.name;
- newp->size = sym->st_size;
- newp->type = XELF_ST_TYPE (sym->st_info);
- newp->symidx = cnt;
- newp->outsymidx = 0;
- newp->outdynsymidx = 0;
- newp->scndx = shndx;
- newp->file = fileinfo;
- newp->defined = newp->scndx != SHN_UNDEF;
- newp->common = newp->scndx == SHN_COMMON;
- newp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
- newp->added = 0;
- newp->merged = 0;
- newp->need_copy = 0;
- newp->on_dsolist = 0;
- newp->in_dso = secttype == SHT_DYNSYM;
- newp->next_in_scn = NULL;
-#ifndef NDEBUG
- newp->next = NULL;
- newp->previous = NULL;
-#endif
-
- if (newp->scndx == SHN_UNDEF)
- {
- CDBL_LIST_ADD_REAR (ld_state.unresolved, newp);
- ++ld_state.nunresolved;
- if (! newp->weak)
- ++ld_state.nunresolved_nonweak;
- }
- else if (newp->scndx == SHN_COMMON)
- {
- /* Store the alignment requirement. */
- newp->merge.value = sym->st_value;
-
- CDBL_LIST_ADD_REAR (ld_state.common_syms, newp);
- }
-
- /* Insert the new symbol. */
- if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
- hval, newp) != 0))
- /* This cannot happen. */
- abort ();
-
- fileinfo->symref[cnt] = newp;
-
- /* We have a few special symbols to recognize. The symbols
- _init and _fini are the initialization and finalization
- functions respectively. They have to be made known in
- the dynamic section and therefore we have to find out
- now whether these functions exist or not. */
- if (hval == 6685956 && strcmp (newp->name, "_init") == 0)
- ld_state.init_symbol = newp;
- else if (hval == 6672457 && strcmp (newp->name, "_fini") == 0)
- ld_state.fini_symbol = newp;
- }
- else if (unlikely (check_definition (sym, cnt, fileinfo, oldp) != 0))
- /* A fatal error (multiple definition of a symbol)
- occurred, no need to continue. */
- return 1;
- else
- /* Use the previously allocated symbol record. It has
- been updated in check_definition(), if necessary. */
- newp = fileinfo->symref[cnt] = oldp;
-
- /* Mark the section the symbol we need comes from as used. */
- if (shndx != SHN_UNDEF
- && (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE))
- {
- struct scninfo *ignore;
-
-#ifndef NDEBUG
- size_t shnum;
- assert (elf_getshnum (fileinfo->elf, &shnum) == 0);
- assert (shndx < shnum);
-#endif
-
- /* Mark section (and all dependencies) as used. */
- mark_section_used (&fileinfo->scninfo[shndx], shndx, &ignore);
-
- /* Check whether the section is merge-able. In this case we
- have to record the symbol. */
- if (SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
- & SHF_MERGE)
- {
- if (fileinfo->scninfo[shndx].symbols == NULL)
- fileinfo->scninfo[shndx].symbols = newp->next_in_scn
- = newp;
- else
- {
- newp->next_in_scn
- = fileinfo->scninfo[shndx].symbols->next_in_scn;
- fileinfo->scninfo[shndx].symbols
- = fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
- }
- }
- }
- }
-
- /* This file is used. */
- if (likely (fileinfo->file_type == relocatable_file_type))
- {
- if (unlikely (ld_state.relfiles == NULL))
- ld_state.relfiles = fileinfo->next = fileinfo;
- else
- {
- fileinfo->next = ld_state.relfiles->next;
- ld_state.relfiles = ld_state.relfiles->next = fileinfo;
- }
-
- /* Update some summary information in the state structure. */
- ld_state.nsymtab += fileinfo->nsymtab;
- ld_state.nlocalsymbols += fileinfo->nlocalsymbols;
- }
- else if (likely (fileinfo->file_type == dso_file_type))
- {
- CSNGL_LIST_ADD_REAR (ld_state.dsofiles, fileinfo);
- ++ld_state.ndsofiles;
-
- if (fileinfo->lazyload)
- /* We have to create another dynamic section entry for the
- DT_POSFLAG_1 entry.
-
- XXX Once more functionality than the lazyloading flag
- are suppported the test must be extended. */
- ++ld_state.ndsofiles;
- }
- }
-
- return 0;
-}
-
-
-int
-ld_handle_filename_list (struct filename_list *fnames)
-{
- struct filename_list *runp;
- int res = 0;
-
- for (runp = fnames; runp != NULL; runp = runp->next)
- {
- struct usedfiles *curp;
-
- /* Create a record for the new file. */
- curp = runp->real = ld_new_inputfile (runp->name, relocatable_file_type);
-
- /* Set flags for group handling. */
- runp->real->group_start = runp->group_start;
- runp->real->group_end = runp->group_end;
-
- /* Read the file and everything else which comes up, including
- handling groups. */
- do
- res |= FILE_PROCESS (-1, curp, &ld_state, &curp);
- while (curp != NULL);
- }
-
- /* Free the list. */
- while (fnames != NULL)
- {
- runp = fnames;
- fnames = fnames->next;
- free (runp);
- }
-
- return res;
-}
-
-
-/* Handle opening of the given file with ELF descriptor. */
-static int
-open_elf (struct usedfiles *fileinfo, Elf *elf)
-{
- int res = 0;
-
- if (elf == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get descriptor for ELF file (%s:%d): %s\n"),
- __FILE__, __LINE__, elf_errmsg (-1));
-
- if (unlikely (elf_kind (elf) == ELF_K_NONE))
- {
- struct filename_list *fnames;
-
- /* We don't have to look at this file again. */
- fileinfo->status = closed;
-
- /* Let's see whether this is a linker script. */
- if (fileinfo->fd != -1)
- /* Create a stream from the file handle we know. */
- ldin = fdopen (fileinfo->fd, "r");
- else
- {
- /* Get the memory for the archive member. */
- char *content;
- size_t contentsize;
-
- /* Get the content of the file. */
- content = elf_rawfile (elf, &contentsize);
- if (content == NULL)
- {
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- return 1;
- }
-
- /* The content of the file is available in memory. Read the
- memory region as a stream. */
- ldin = fmemopen (content, contentsize, "r");
- }
-
- /* No need for locking. */
- __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
- if (ldin == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot open \"%s\""),
- fileinfo->rfname);
-
- /* Parse the file. If it is a linker script no problems will be
- reported. */
- ld_state.srcfiles = NULL;
- ldlineno = 1;
- ld_scan_version_script = 0;
- ldin_fname = fileinfo->rfname;
- res = ldparse ();
-
- fclose (ldin);
- if (fileinfo->fd != -1 && !fileinfo->fd_passed)
- {
- /* We won't need the file descriptor again. */
- close (fileinfo->fd);
- fileinfo->fd = -1;
- }
-
- elf_end (elf);
-
- if (unlikely (res != 0))
- /* Something went wrong during parsing. */
- return 1;
-
- /* This is no ELF file. */
- fileinfo->elf = NULL;
-
- /* Now we have to handle eventual INPUT and GROUP statements in
- the script. Read the files mentioned. */
- fnames = ld_state.srcfiles;
- if (fnames != NULL)
- {
- struct filename_list *oldp;
-
- /* Convert the list into a normal single-linked list. */
- oldp = fnames;
- fnames = fnames->next;
- oldp->next = NULL;
-
- /* Remove the list from the state structure. */
- ld_state.srcfiles = NULL;
-
- if (unlikely (ld_handle_filename_list (fnames) != 0))
- return 1;
- }
-
- return 0;
- }
-
- /* Store the file info. */
- fileinfo->elf = elf;
-
- /* The file is ready for action. */
- fileinfo->status = opened;
-
- return 0;
-}
-
-
-static int
-add_whole_archive (struct usedfiles *fileinfo)
-{
- Elf *arelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP_PRIVATE;
- int res = 0;
-
- while ((arelf = elf_begin (fileinfo->fd, cmd, fileinfo->elf)) != NULL)
- {
- Elf_Arhdr *arhdr = elf_getarhdr (arelf);
- struct usedfiles *newp;
-
- if (arhdr == NULL)
- abort ();
-
- /* Just to be sure; since these are no files in the archive
- these names should never be returned. */
- assert (strcmp (arhdr->ar_name, "/") != 0);
- assert (strcmp (arhdr->ar_name, "//") != 0);
-
- newp = ld_new_inputfile (arhdr->ar_name, relocatable_file_type);
- newp->archive_file = fileinfo;
-
- if (unlikely (ld_state.trace_files))
- print_file_name (stdout, newp, 1, 1);
-
- /* This shows that this file is contained in an archive. */
- newp->fd = -1;
- /* Store the ELF descriptor. */
- newp->elf = arelf;
- /* Show that we are open for business. */
- newp->status = opened;
-
- /* Proces the file, add all the symbols etc. */
- res = file_process2 (newp);
- if (unlikely (res != 0))
- break;
-
- /* Advance to the next archive element. */
- cmd = elf_next (arelf);
- }
-
- return res;
-}
-
-
-static int
-extract_from_archive (struct usedfiles *fileinfo)
-{
- static int archive_seq;
- int res = 0;
-
- /* This is an archive we are not using completely. Give it a
- unique number. */
- fileinfo->archive_seq = ++archive_seq;
-
- /* If there are no unresolved symbols don't do anything. */
- if ((likely (ld_state.extract_rule == defaultextract)
- && ld_state.nunresolved_nonweak == 0)
- || (unlikely (ld_state.extract_rule == weakextract)
- && ld_state.nunresolved == 0))
- return 0;
-
- Elf_Arsym *syms;
- size_t nsyms;
-
- /* Get all the symbols. */
- syms = elf_getarsym (fileinfo->elf, &nsyms);
- if (syms == NULL)
- {
- cannot_read_archive:
- error (0, 0, gettext ("cannot read archive `%s': %s"),
- fileinfo->rfname, elf_errmsg (-1));
-
- /* We cannot use this archive anymore. */
- fileinfo->status = closed;
-
- return 1;
- }
-
- /* Now add all the symbols to the hash table. Note that there
- can potentially be duplicate definitions. We'll always use
- the first definition. */
- // XXX Is this a compatible behavior?
- bool any_used;
- int nround = 0;
- do
- {
- any_used = false;
-
- size_t cnt;
- for (cnt = 0; cnt < nsyms; ++cnt)
- {
- struct symbol search = { .name = syms[cnt].as_name };
- struct symbol *sym = ld_symbol_tab_find (&ld_state.symbol_tab,
- syms[cnt].as_hash, &search);
- if (sym != NULL && ! sym->defined)
- {
- /* The symbol is referenced and not defined. */
- Elf *arelf;
- Elf_Arhdr *arhdr;
- struct usedfiles *newp;
-
- /* Find the archive member for this symbol. */
- if (unlikely (elf_rand (fileinfo->elf, syms[cnt].as_off)
- != syms[cnt].as_off))
- goto cannot_read_archive;
-
- /* Note: no test of a failing 'elf_begin' call. That's fine
- since 'elf'getarhdr' will report the problem. */
- arelf = elf_begin (fileinfo->fd, ELF_C_READ_MMAP_PRIVATE,
- fileinfo->elf);
- arhdr = elf_getarhdr (arelf);
- if (arhdr == NULL)
- goto cannot_read_archive;
-
- /* We have all the information and an ELF handle for the
- archive member. Create the normal data structure for
- a file now. */
- newp = ld_new_inputfile (obstack_strdup (&ld_state.smem,
- arhdr->ar_name),
- relocatable_file_type);
- newp->archive_file = fileinfo;
-
- if (unlikely (ld_state.trace_files))
- print_file_name (stdout, newp, 1, 1);
-
- /* This shows that this file is contained in an archive. */
- newp->fd = -1;
- /* Store the ELF descriptor. */
- newp->elf = arelf;
- /* Show that we are open for business. */
- newp->status = in_archive;
-
- /* Now read the file and add all the symbols. */
- res = file_process2 (newp);
- if (unlikely (res != 0))
- return res;
-
- any_used = true;
- }
- }
-
- if (++nround == 1)
- {
- /* This is an archive therefore it must have a number. */
- assert (fileinfo->archive_seq != 0);
- ld_state.last_archive_used = fileinfo->archive_seq;
- }
- }
- while (any_used);
-
- return res;
-}
-
-
-static int
-file_process2 (struct usedfiles *fileinfo)
-{
- int res;
-
- if (likely (elf_kind (fileinfo->elf) == ELF_K_ELF))
- {
- /* The first time we get here we read the ELF header. */
-#if NATIVE_ELF != 0
- if (likely (fileinfo->ehdr == NULL))
-#else
- if (likely (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_NONE))
-#endif
- {
- XElf_Ehdr *ehdr;
-#if NATIVE_ELF != 0
- ehdr = xelf_getehdr (fileinfo->elf, fileinfo->ehdr);
-#else
- xelf_getehdr_copy (fileinfo->elf, ehdr, fileinfo->ehdr);
-#endif
- if (ehdr == NULL)
- {
- fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
- fileinfo->rfname, __FILE__, __LINE__);
- fileinfo->status = closed;
- return 1;
- }
-
- if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL
- && unlikely (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_DYN))
- /* XXX Add ebl* function to query types which are allowed
- to link in. */
- {
- char buf[64];
-
- print_file_name (stderr, fileinfo, 1, 0);
- fprintf (stderr,
- gettext ("file of type %s cannot be linked in\n"),
- ebl_object_type_name (ld_state.ebl,
- FILEINFO_EHDR (fileinfo->ehdr).e_type,
- buf, sizeof (buf)));
- fileinfo->status = closed;
- return 1;
- }
-
- /* Determine the section header string table section index. */
- if (unlikely (elf_getshstrndx (fileinfo->elf, &fileinfo->shstrndx)
- < 0))
- {
- fprintf (stderr, gettext ("\
-%s: cannot get section header string table index: %s\n"),
- fileinfo->rfname, elf_errmsg (-1));
- fileinfo->status = closed;
- return 1;
- }
- }
-
- /* Now handle the different types of files. */
- if (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_REL)
- {
- /* Add all the symbol. Relocatable files have symbol
- tables. */
- res = add_relocatable_file (fileinfo, SHT_SYMTAB);
- }
- else
- {
- bool has_l_name = fileinfo->file_type == archive_file_type;
-
- assert (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN);
-
- /* If the file is a DT_NEEDED dependency then the type is
- already correctly specified. */
- if (fileinfo->file_type != dso_needed_file_type)
- fileinfo->file_type = dso_file_type;
-
- /* We cannot use DSOs when generating relocatable objects. */
- if (ld_state.file_type == relocatable_file_type)
- {
- error (0, 0, gettext ("\
-cannot use DSO '%s' when generating relocatable object file"),
- fileinfo->fname);
- return 1;
- }
-
- /* Add all the symbols. For DSOs we are looking at the
- dynamic symbol table. */
- res = add_relocatable_file (fileinfo, SHT_DYNSYM);
-
- /* We always have to have a dynamic section. */
- assert (fileinfo->dynscn != NULL);
-
- /* We have to remember the dependencies for this object. It
- is necessary to look them up. */
- XElf_Shdr_vardef (dynshdr);
- xelf_getshdr (fileinfo->dynscn, dynshdr);
-
- Elf_Data *dyndata = elf_getdata (fileinfo->dynscn, NULL);
- /* XXX Should we flag the failure to get the dynamic section? */
- if (dynshdr != NULL)
- {
- int cnt = dynshdr->sh_size / dynshdr->sh_entsize;
- XElf_Dyn_vardef (dyn);
-
- while (--cnt >= 0)
- {
- xelf_getdyn (dyndata, cnt, dyn);
- if (dyn != NULL)
- {
- if(dyn->d_tag == DT_NEEDED)
- {
- struct usedfiles *newp;
-
- newp = ld_new_inputfile (elf_strptr (fileinfo->elf,
- dynshdr->sh_link,
- dyn->d_un.d_val),
- dso_needed_file_type);
-
- /* Enqueue the newly found dependencies. */
- // XXX Check that there not already a file with the
- // same name.
- CSNGL_LIST_ADD_REAR (ld_state.needed, newp);
- }
- else if (dyn->d_tag == DT_SONAME)
- {
- /* We use the DT_SONAME (this is what's there
- for). */
- fileinfo->soname = elf_strptr (fileinfo->elf,
- dynshdr->sh_link,
- dyn->d_un.d_val);
- has_l_name = false;
- }
- }
- }
- }
-
- /* Construct the file name if the DSO has no SONAME and the
- file name comes from a -lXX parameter on the comment
- line. */
- if (unlikely (has_l_name))
- {
- /* The FNAME is the parameter the user specified on the
- command line. We prepend "lib" and append ".so". */
- size_t len = strlen (fileinfo->fname) + 7;
- char *newp;
-
- newp = (char *) obstack_alloc (&ld_state.smem, len);
- strcpy (stpcpy (stpcpy (newp, "lib"), fileinfo->fname), ".so");
-
- fileinfo->soname = newp;
- }
- }
- }
- else if (likely (elf_kind (fileinfo->elf) == ELF_K_AR))
- {
- if (unlikely (ld_state.extract_rule == allextract))
- /* Which this option enabled we have to add all the object
- files in the archive. */
- res = add_whole_archive (fileinfo);
- else if (ld_state.file_type == relocatable_file_type)
- {
- /* When generating a relocatable object we don't find files
- in archives. */
- if (verbose)
- error (0, 0, gettext ("input file '%s' ignored"), fileinfo->fname);
-
- res = 0;
- }
- else
- /* Extract only the members from the archive which are
- currently referenced by unresolved symbols. */
- res = extract_from_archive (fileinfo);
- }
- else
- /* This should never happen, we know about no other types. */
- abort ();
-
- return res;
-}
-
-
-/* Process a given file. The first parameter is a file descriptor for
- the file which can be -1 to indicate the file has not yet been
- found. The second parameter describes the file to be opened, the
- last one is the state of the linker which among other information
- contain the paths we look at. */
-static int
-ld_generic_file_process (int fd, struct usedfiles *fileinfo,
- struct ld_state *statep, struct usedfiles **nextp)
-{
- int res = 0;
-
- /* By default we go to the next file in the list. */
- *nextp = fileinfo->next;
-
- /* Set the flag to signal we are looking for a group start. */
- if (unlikely (fileinfo->group_start))
- {
- ld_state.group_start_requested = true;
- fileinfo->group_start = false;
- }
-
- /* If the file isn't open yet, open it now. */
- if (likely (fileinfo->status == not_opened))
- {
- bool fd_passed = true;
-
- if (likely (fd == -1))
- {
- /* Find the file ourselves. */
- int err = open_along_path (fileinfo);
- if (unlikely (err != 0))
- /* We allow libraries and DSOs to be named more than once.
- Don't report an error to the caller. */
- return err == EAGAIN ? 0 : err;
-
- fd_passed = false;
- }
- else
- fileinfo->fd = fd;
-
- /* Remember where we got the descriptor from. */
- fileinfo->fd_passed = fd_passed;
-
- /* We found the file. Now test whether it is a file type we can
- handle.
-
- XXX Do we have to have the ability to start from a given
- position in the search path again to look for another file if
- the one found has not the right type? */
- res = open_elf (fileinfo, elf_begin (fileinfo->fd,
- is_dso_p (fileinfo->fd)
- ? ELF_C_READ_MMAP
- : ELF_C_READ_MMAP_PRIVATE, NULL));
- if (unlikely (res != 0))
- return res;
- }
-
- /* Now that we have opened the file start processing it. */
- if (likely (fileinfo->status != closed))
- res = file_process2 (fileinfo);
-
- /* Determine which file to look at next. */
- if (unlikely (fileinfo->group_backref != NULL))
- {
- /* We only go back if an archive other than the one we would go
- back to has been used in the last round. */
- if (ld_state.last_archive_used > fileinfo->group_backref->archive_seq)
- {
- *nextp = fileinfo->group_backref;
- ld_state.last_archive_used = 0;
- }
- else
- {
- /* If we come here this means that the archives we read so
- far are not needed anymore. We can free some of the data
- now. */
- struct usedfiles *runp = ld_state.archives;
-
- do
- {
- /* We don't need the ELF descriptor anymore. Unless there
- are no files from the archive used this will not free
- the whole file but only some data structures. */
- elf_end (runp->elf);
- runp->elf = NULL;
-
- runp = runp->next;
- }
- while (runp != fileinfo->next);
- }
- }
- else if (unlikely (fileinfo->group_end))
- {
- /* This is the end of a group. We possibly of to go back.
- Determine which file we would go back to and see whether it
- makes sense. If there has not been an archive we don't have
- to do anything. */
- if (!ld_state.group_start_requested)
- {
- if (ld_state.group_start_archive != ld_state.tailarchives)
- /* The loop would include more than one archive, add the
- pointer. */
- {
- *nextp = ld_state.tailarchives->group_backref =
- ld_state.group_start_archive;
- ld_state.last_archive_used = 0;
- }
- else
- /* We might still have to go back to the beginning of the
- group if since the last archive other files have been
- added. But we go back exactly once. */
- if (ld_state.tailarchives != fileinfo)
- {
- *nextp = ld_state.group_start_archive;
- ld_state.last_archive_used = 0;
- }
- }
-
- /* Clear the flags. */
- ld_state.group_start_requested = false;
- fileinfo->group_end = false;
- }
-
- return res;
-}
-
-
-/* Library names passed to the linker as -lXX represent files named
- libXX.YY. The YY part can have different forms, depending on the
- platform. The generic set is .so and .a (in this order). */
-static const char **
-ld_generic_lib_extensions (struct ld_state *statep __attribute__ ((__unused__)))
-{
- static const char *exts[] =
- {
- ".so", ".a", NULL
- };
-
- return exts;
-}
-
-
-/* Flag unresolved symbols. */
-static int
-ld_generic_flag_unresolved (struct ld_state *statep)
-{
- int retval = 0;
-
- if (ld_state.nunresolved_nonweak > 0)
- {
- /* Go through the list and determine the unresolved symbols. */
- struct symbol *first;
- struct symbol *s;
-
- s = first = ld_state.unresolved->next;
- do
- {
- if (! s->defined && ! s->weak)
- {
- /* Two special symbol we recognize: the symbol for the
- GOT and the dynamic section. */
- if (strcmp (s->name, "_GLOBAL_OFFSET_TABLE_") == 0
- || strcmp (s->name, "_DYNAMIC") == 0)
- {
- /* We will have to fill in more information later. */
- ld_state.need_got = true;
-
- /* Remember that we found it. */
- if (s->name[1] == 'G')
- ld_state.got_symbol = s;
- else
- ld_state.dyn_symbol = s;
- }
- else if (ld_state.file_type != dso_file_type || !ld_state.nodefs)
- {
- /* XXX The error message should get better. It should use
- the debugging information if present to tell where in the
- sources the undefined reference is. */
- error (0, 0, gettext ("undefined symbol `%s' in %s"),
- s->name, s->file->fname);
-
- retval = 1;
- }
- }
-
- /* We cannot decide here what to do with undefined
- references which will come from DSO since we do not know
- what kind of symbol we expect. Only when looking at the
- relocations we can see whether we need a PLT entry or
- only a GOT entry. */
-
- s = s->next;
- }
- while (s != first);
- }
-
- return retval;
-}
-
-
-/* Close the given file. */
-static int
-ld_generic_file_close (struct usedfiles *fileinfo, struct ld_state *statep)
-{
- /* Close the ELF descriptor. */
- elf_end (fileinfo->elf);
-
- /* If we have opened the file descriptor close it. But we might
- have done this already in which case FD is -1. */
- if (!fileinfo->fd_passed && fileinfo->fd != -1)
- close (fileinfo->fd);
-
- /* We allocated the resolved file name. */
- if (fileinfo->fname != fileinfo->rfname)
- free ((char *) fileinfo->rfname);
-
- return 0;
-}
-
-
-static void
-new_generated_scn (enum scn_kind kind, const char *name, int type, int flags,
- int entsize, int align)
-{
- struct scnhead *newp;
-
- newp = (struct scnhead *) obstack_calloc (&ld_state.smem,
- sizeof (struct scnhead));
- newp->kind = kind;
- newp->name = name;
- newp->nameent = ebl_strtabadd (ld_state.shstrtab, name, 0);
- newp->type = type;
- newp->flags = flags;
- newp->entsize = entsize;
- newp->align = align;
- newp->grp_signature = NULL;
- newp->used = true;
-
- /* All is well. Create now the data for the section and insert it
- into the section table. */
- ld_section_tab_insert (&ld_state.section_tab, elf_hash (name), newp);
-}
-
-
-/* Create the sections which are generated by the linker and are not
- present in the input file. */
-static void
-ld_generic_generate_sections (struct ld_state *statep)
-{
- /* The relocation section type. */
- int rel_type = REL_TYPE (&ld_state) == DT_REL ? SHT_REL : SHT_RELA;
-
- /* When building dynamically linked object we have to include a
- section containing a string describing the interpreter. This
- should be at the very beginning of the file together with the
- other information the ELF loader (kernel or wherever) has to look
- at. We put it as the first section in the file.
-
- We also have to create the dynamic segment which is a special
- section the dynamic linker locates through an entry in the
- program header. */
- if (dynamically_linked_p ())
- {
- int ndt_needed;
- /* Use any versioning (defined or required)? */
- bool use_versioning = false;
- /* Use version requirements? */
- bool need_version = false;
-
- /* First the .interp section. */
- new_generated_scn (scn_dot_interp, ".interp", SHT_PROGBITS, SHF_ALLOC,
- 0, 1);
-
- /* Now the .dynamic section. */
- new_generated_scn (scn_dot_dynamic, ".dynamic", SHT_DYNAMIC,
- DYNAMIC_SECTION_FLAGS (&ld_state),
- xelf_fsize (ld_state.outelf, ELF_T_DYN, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
- /* We will need in any case the dynamic symbol table (even in
- the unlikely case that no symbol is exported or referenced
- from a DSO). */
- ld_state.need_dynsym = true;
- new_generated_scn (scn_dot_dynsym, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
- xelf_fsize (ld_state.outelf, ELF_T_SYM, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
- /* It comes with a string table. */
- new_generated_scn (scn_dot_dynstr, ".dynstr", SHT_STRTAB, SHF_ALLOC,
- 0, 1);
- /* And a hashing table. */
- // XXX For Linux/Alpha we need other sizes unless they change...
- new_generated_scn (scn_dot_hash, ".hash", SHT_HASH, SHF_ALLOC,
- sizeof (Elf32_Word), sizeof (Elf32_Word));
-
- /* By default we add all DSOs provided on the command line. If
- the user added '-z ignore' to the command line we only add
- those which are actually used. */
- ndt_needed = ld_state.ignore_unused_dsos ? 0 : ld_state.ndsofiles;
-
- /* Create the section associated with the PLT if necessary. */
- if (ld_state.nplt > 0)
- {
- /* Create the .plt section. */
- /* XXX We might need a function which returns the section flags. */
- new_generated_scn (scn_dot_plt, ".plt", SHT_PROGBITS,
- SHF_ALLOC | SHF_EXECINSTR,
- /* XXX Is the size correct? */
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
- /* Create the relocation section for the .plt. This is always
- separate even if the other relocation sections are combined. */
- new_generated_scn (scn_dot_pltrel, ".rel.plt", rel_type, SHF_ALLOC,
- rel_type == SHT_REL
- ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
- : xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
- /* This means we will also need the .got section. */
- ld_state.need_got = true;
-
- /* Mark all used DSOs as used. Determine whether any referenced
- object uses symbol versioning. */
- if (ld_state.from_dso != NULL)
- {
- struct symbol *srunp = ld_state.from_dso;
-
- do
- {
- srunp->file->used = true;
-
- if (srunp->file->verdefdata != NULL)
- {
- XElf_Versym versym;
-
- /* The input DSO uses versioning. */
- use_versioning = true;
- /* We reference versions. */
- need_version = true;
-
- if (xelf_getversym_copy (srunp->file->versymdata,
- srunp->symidx, versym) == NULL)
- assert (! "xelf_getversym failed");
-
- /* We cannot link explicitly with an older
- version of a symbol. */
- assert ((versym & 0x8000) == 0);
- /* We cannot reference local (index 0) or plain
- global (index 1) versions. */
- assert (versym > 1);
-
- /* Check whether we have already seen the
- version and if not add it to the referenced
- versions in the output file. */
- if (! srunp->file->verdefused[versym])
- {
- srunp->file->verdefused[versym] = 1;
-
- if (++srunp->file->nverdefused == 1)
- /* Count the file if it is using versioning. */
- ++ld_state.nverdeffile;
- ++ld_state.nverdefused;
- }
- }
- }
- while ((srunp = srunp->next) != ld_state.from_dso);
- }
-
- /* Create the sections used to record version dependencies. */
- if (need_version)
- new_generated_scn (scn_dot_version_r, ".gnu.version_r",
- SHT_GNU_verneed, SHF_ALLOC, 0,
- xelf_fsize (ld_state.outelf, ELF_T_WORD, 1));
-
- /* Now count the used DSOs since this is what the user
- wants. */
- ndt_needed = 0;
- if (ld_state.ndsofiles > 0)
- {
- struct usedfiles *frunp = ld_state.dsofiles;
-
- do
- if (! ld_state.ignore_unused_dsos || frunp->used)
- {
- ++ndt_needed;
- if (frunp->lazyload)
- /* We have to create another dynamic section
- entry for the DT_POSFLAG_1 entry.
-
- XXX Once more functionality than the
- lazyloading flag are suppported the test
- must be extended. */
- ++ndt_needed;
- }
- while ((frunp = frunp->next) != ld_state.dsofiles);
- }
- }
-
- if (use_versioning)
- new_generated_scn (scn_dot_version, ".gnu.version", SHT_GNU_versym,
- SHF_ALLOC,
- xelf_fsize (ld_state.outelf, ELF_T_HALF, 1),
- xelf_fsize (ld_state.outelf, ELF_T_HALF, 1));
-
- /* We need some entries all the time. */
- ld_state.ndynamic = (7 + (ld_state.runpath != NULL
- || ld_state.rpath != NULL)
- + ndt_needed
- + (ld_state.init_symbol != NULL ? 1 : 0)
- + (ld_state.fini_symbol != NULL ? 1 : 0)
- + (use_versioning ? 1 : 0)
- + (need_version ? 2 : 0)
- + (ld_state.nplt > 0 ? 4 : 0)
- + (ld_state.relsize_total > 0 ? 3 : 0));
- }
-
- /* When creating a relocatable file or when we are not stripping the
- output file we create a symbol table. */
- ld_state.need_symtab = (ld_state.file_type == relocatable_file_type
- || ld_state.strip == strip_none);
-
- /* Add the .got section if needed. */
- if (ld_state.need_got)
- /* XXX We might need a function which returns the section flags. */
- new_generated_scn (scn_dot_got, ".got", SHT_PROGBITS,
- SHF_ALLOC | SHF_WRITE,
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
- /* Add the .rel.dyn section. */
- if (ld_state.relsize_total > 0)
- new_generated_scn (scn_dot_dynrel, ".rel.dyn", rel_type, SHF_ALLOC,
- rel_type == SHT_REL
- ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
- : xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
- xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-}
-
-
-/* Callback function registered with on_exit to make sure the temporary
- files gets removed if something goes wrong. */
-static void
-remove_tempfile (int status, void *arg)
-{
- if (status != 0 && ld_state.tempfname != NULL)
- unlink (ld_state.tempfname);
-}
-
-
-/* Create the output file. The file name is given or "a.out". We
- create as much of the ELF structure as possible. */
-static int
-ld_generic_open_outfile (struct ld_state *statep, int machine, int klass,
- int data)
-{
- /* We do not create the new file right away with the final name.
- This would destroy an existing file with this name before a
- replacement is finalized. We create instead a temporary file in
- the same directory. */
- if (ld_state.outfname == NULL)
- ld_state.outfname = "a.out";
-
- size_t outfname_len = strlen (ld_state.outfname);
- char *tempfname = (char *) obstack_alloc (&ld_state.smem,
- outfname_len + sizeof (".XXXXXX"));
- ld_state.tempfname = tempfname;
-
- int fd;
- int try = 0;
- while (1)
- {
- strcpy (mempcpy (tempfname, ld_state.outfname, outfname_len), ".XXXXXX");
-
- /* The useof mktemp() here is fine. We do not want to use
- mkstemp() since then the umask isn't used. And the output
- file will have these permissions anyhow. Any intruder could
- change the file later if it would be possible now. */
- if (mktemp (tempfname) != NULL
- && (fd = open (tempfname, O_RDWR | O_EXCL | O_CREAT | O_NOFOLLOW,
- ld_state.file_type == relocatable_file_type
- ? DEFFILEMODE : ACCESSPERMS)) != -1)
- break;
-
- /* Failed this round. We keep trying a number of times. */
- if (++try >= 10)
- error (EXIT_FAILURE, errno, gettext ("cannot create output file"));
- }
- ld_state.outfd = fd;
-
- /* Make sure we remove the temporary file in case something goes
- wrong. */
- on_exit (remove_tempfile, NULL);
-
- /* Create the ELF file data for the output file. */
- Elf *elf = ld_state.outelf = elf_begin (fd,
- conserve_memory
- ? ELF_C_WRITE : ELF_C_WRITE_MMAP,
- NULL);
- if (elf == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create ELF descriptor for output file: %s"),
- elf_errmsg (-1));
-
- /* Create the basic data structures. */
- if (! xelf_newehdr (elf, klass))
- /* Couldn't create the ELF header. Very bad. */
- error (EXIT_FAILURE, 0,
- gettext ("could not create ELF header for output file: %s"),
- elf_errmsg (-1));
-
- /* And get the current header so that we can modify it. */
- XElf_Ehdr_vardef (ehdr);
- xelf_getehdr (elf, ehdr);
- assert (ehdr != NULL);
-
- /* Set the machine type. */
- ehdr->e_machine = machine;
-
- /* Modify it according to the info we have here and now. */
- if (ld_state.file_type == executable_file_type)
- ehdr->e_type = ET_EXEC;
- else if (ld_state.file_type == dso_file_type)
- ehdr->e_type = ET_DYN;
- else
- {
- assert (ld_state.file_type == relocatable_file_type);
- ehdr->e_type = ET_REL;
- }
-
- /* Set the ELF version. */
- ehdr->e_version = EV_CURRENT;
-
- /* Set the endianness. */
- ehdr->e_ident[EI_DATA] = data;
-
- /* Write the ELF header information back. */
- (void) xelf_update_ehdr (elf, ehdr);
-
- return 0;
-}
-
-
-/* We compute the offsets of the various copied objects and the total
- size of the memory needed. */
-// XXX The method used here is simple: go from front to back and pack
-// the objects in this order. A more space efficient way would
-// actually trying to pack the objects as dense as possible. But this
-// is more expensive.
-static void
-compute_copy_reloc_offset (XElf_Shdr *shdr)
-{
- struct symbol *runp = ld_state.from_dso;
- assert (runp != NULL);
-
- XElf_Off maxalign = 1;
- XElf_Off offset = 0;
-
- do
- if (runp->need_copy)
- {
- /* Determine alignment for the symbol. */
- // XXX The question is how? The symbol record itself does not
- // have the information. So we have to be conservative and
- // assume the alignment of the section the symbol is in.
-
- // XXX We can be more precise. Use the offset from the beginning
- // of the section and determine the largest power of two with
- // module zero.
- XElf_Off symalign = MAX (SCNINFO_SHDR (runp->file->scninfo[runp->scndx].shdr).sh_addralign, 1);
- /* Keep track of the maximum alignment requirement. */
- maxalign = MAX (maxalign, symalign);
-
- /* Align current position. */
- offset = (offset + symalign - 1) & ~(symalign - 1);
-
- runp->merge.value = offset;
-
- offset += runp->size;
- }
- while ((runp = runp->next) != ld_state.from_dso);
-
- shdr->sh_type = SHT_NOBITS;
- shdr->sh_size = offset;
- shdr->sh_addralign = maxalign;
-}
-
-
-static void
-compute_common_symbol_offset (XElf_Shdr *shdr)
-{
- struct symbol *runp = ld_state.common_syms;
- assert (runp != NULL);
-
- XElf_Off maxalign = 1;
- XElf_Off offset = 0;
-
- do
- {
- /* Determine alignment for the symbol. */
- XElf_Off symalign = runp->merge.value;
-
- /* Keep track of the maximum alignment requirement. */
- maxalign = MAX (maxalign, symalign);
-
- /* Align current position. */
- offset = (offset + symalign - 1) & ~(symalign - 1);
-
- runp->merge.value = offset;
-
- offset += runp->size;
- }
- while ((runp = runp->next) != ld_state.common_syms);
-
- shdr->sh_type = SHT_NOBITS;
- shdr->sh_size = offset;
- shdr->sh_addralign = maxalign;
-}
-
-
-static void
-sort_sections_generic (void)
-{
- /* XXX TBI */
- abort ();
-}
-
-
-static int
-match_section (const char *osectname, struct filemask_section_name *sectmask,
- struct scnhead **scnhead, bool new_section, size_t segment_nr)
-{
- struct scninfo *prevp;
- struct scninfo *runp;
- struct scninfo *notused;
-
- if (fnmatch (sectmask->section_name->name, (*scnhead)->name, 0) != 0)
- /* The section name does not match. */
- return new_section;
-
- /* If this is a section generated by the linker it doesn't contain
- the regular information (i.e., input section data etc) and must
- be handle special. */
- if ((*scnhead)->kind != scn_normal)
- {
- (*scnhead)->name = osectname;
- (*scnhead)->segment_nr = segment_nr;
-
- /* We have to count note section since they get their own
- program header entry. */
- if ((*scnhead)->type == SHT_NOTE)
- ++ld_state.nnotesections;
-
- ld_state.allsections[ld_state.nallsections++] = (*scnhead);
- return true;
- }
-
- /* Now we have to match the file names of the input files. Some of
- the sections here might not match. */
- runp = (*scnhead)->last->next;
- prevp = (*scnhead)->last;
- notused = NULL;
-
- do
- {
- /* Base of the file name the section comes from. */
- const char *brfname = basename (runp->fileinfo->rfname);
-
- /* If the section isn't used, the name doesn't match the positive
- inclusion list or the name does match the negative inclusion
- list, ignore the section. */
- if (!runp->used
- || (sectmask->filemask != NULL
- && fnmatch (sectmask->filemask, brfname, 0) != 0)
- || (sectmask->excludemask != NULL
- && fnmatch (sectmask->excludemask, brfname, 0) == 0))
- {
- /* This file does not match the file name masks. */
- if (notused == NULL)
- notused = runp;
-
- prevp = runp;
- runp = runp->next;
- if (runp == notused)
- runp = NULL;
- }
- /* The section fulfills all requirements, add it to the output
- file with the correct section name etc. */
- else
- {
- struct scninfo *found = runp;
-
- /* Remove this input section data buffer from the list. */
- if (prevp != runp)
- runp = prevp->next = runp->next;
- else
- {
- free (*scnhead);
- *scnhead = NULL;
- runp = NULL;
- }
-
- /* Create a new section for the output file if the 'new_section'
- flag says so. Otherwise append the buffer to the last
- section which we created in one of the last calls. */
- if (new_section)
- {
- struct scnhead *newp;
-
- newp = (struct scnhead *) obstack_calloc (&ld_state.smem,
- sizeof (*newp));
- newp->kind = scn_normal;
- newp->name = osectname;
- newp->type = SCNINFO_SHDR (found->shdr).sh_type;
- newp->flags = SCNINFO_SHDR (found->shdr).sh_flags;
- newp->segment_nr = segment_nr;
- newp->last = found->next = found;
- newp->used = true;
- newp->relsize = found->relsize;
- newp->entsize = SCNINFO_SHDR (found->shdr).sh_entsize;
-
- /* We have to count note section since they get their own
- program header entry. */
- if (newp->type == SHT_NOTE)
- ++ld_state.nnotesections;
-
- ld_state.allsections[ld_state.nallsections++] = newp;
- new_section = false;
- }
- else
- {
- struct scnhead *queued;
-
- queued = ld_state.allsections[ld_state.nallsections - 1];
-
- found->next = queued->last->next;
- queued->last = queued->last->next = found;
-
- /* If the linker script forces us to add incompatible
- sections together do so. But reflect this in the
- type and flags of the resulting file. */
- if (queued->type != SCNINFO_SHDR (found->shdr).sh_type)
- /* XXX Any better choice? */
- queued->type = SHT_PROGBITS;
- if (queued->flags != SCNINFO_SHDR (found->shdr).sh_flags)
- queued->flags = ebl_sh_flags_combine (ld_state.ebl,
- queued->flags,
- SCNINFO_SHDR (found->shdr).sh_flags);
-
- /* Accumulate the relocation section size. */
- queued->relsize += found->relsize;
- }
- }
- }
- while (runp != NULL);
-
- return new_section;
-}
-
-
-static void
-sort_sections_lscript (void)
-{
- struct scnhead *temp[ld_state.nallsections];
-
- /* Make a copy of the section head pointer array. */
- memcpy (temp, ld_state.allsections,
- ld_state.nallsections * sizeof (temp[0]));
- size_t nallsections = ld_state.nallsections;
-
- /* Convert the output segment list in a single-linked list. */
- struct output_segment *segment = ld_state.output_segments->next;
- ld_state.output_segments->next = NULL;
- ld_state.output_segments = segment;
-
- /* Put the sections in the correct order in the array in the state
- structure. This might involve merging of sections and also
- renaming the containing section in the output file. */
- ld_state.nallsections = 0;
- size_t segment_nr;
- size_t last_writable = ~0;
- for (segment_nr = 0; segment != NULL; segment = segment->next, ++segment_nr)
- {
- struct output_rule *orule;
-
- for (orule = segment->output_rules; orule != NULL; orule = orule->next)
- if (orule->tag == output_section)
- {
- struct input_rule *irule;
- bool new_section = true;
-
- for (irule = orule->val.section.input; irule != NULL;
- irule = irule->next)
- if (irule->tag == input_section)
- {
- size_t cnt;
-
- for (cnt = 0; cnt < nallsections; ++cnt)
- if (temp[cnt] != NULL)
- new_section =
- match_section (orule->val.section.name,
- irule->val.section, &temp[cnt],
- new_section, segment_nr);
- }
- }
-
- if ((segment->mode & PF_W) != 0)
- last_writable = ld_state.nallsections - 1;
- }
-
- /* In case we have to create copy relocations or we have common
- symbols, find the last writable segment and add one more data
- block. It will be a NOBITS block and take up no disk space.
- This is why it is important to get the last block. */
- if (ld_state.ncopy > 0 || ld_state.common_syms != NULL)
- {
- if (last_writable == ~0)
- error (EXIT_FAILURE, 0, "no writable segment");
-
- if (ld_state.allsections[last_writable]->type != SHT_NOBITS)
- {
- /* Make room in the ALLSECTIONS array for a new section.
- There is guaranteed room in the array. We add the new
- entry after the last writable section. */
- ++last_writable;
- memmove (&ld_state.allsections[last_writable + 1],
- &ld_state.allsections[last_writable],
- (ld_state.nallsections - last_writable)
- * sizeof (ld_state.allsections[0]));
-
- ld_state.allsections[last_writable] = (struct scnhead *)
- obstack_calloc (&ld_state.smem, sizeof (struct scnhead));
-
- /* Name for the new section. */
- ld_state.allsections[last_writable]->name = ".bss";
- /* Type: NOBITS. */
- ld_state.allsections[last_writable]->type = SHT_NOBITS;
- /* Same segment as the last writable section. */
- ld_state.allsections[last_writable]->segment_nr
- = ld_state.allsections[last_writable - 1]->segment_nr;
- }
- }
-
- /* Create common symbol data block. */
- if (ld_state.ncopy > 0)
- {
-#if NATIVE_ELF
- struct scninfo *si = (struct scninfo *)
- obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr));
- si->shdr = (XElf_Shdr *) (si + 1);
-#else
- struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem,
- sizeof (*si));
-#endif
-
- /* Get the information regarding the symbols with copy relocations. */
- compute_copy_reloc_offset (&SCNINFO_SHDR (si->shdr));
-
- /* This section is needed. */
- si->used = true;
- /* Remember for later the section data structure. */
- ld_state.copy_section = si;
-
- if (likely (ld_state.allsections[last_writable]->last != NULL))
- {
- si->next = ld_state.allsections[last_writable]->last->next;
- ld_state.allsections[last_writable]->last->next = si;
- ld_state.allsections[last_writable]->last = si;
- }
- else
- ld_state.allsections[last_writable]->last = si->next = si;
- }
-
- /* Create common symbol data block. */
- if (ld_state.common_syms != NULL)
- {
-#if NATIVE_ELF
- struct scninfo *si = (struct scninfo *)
- obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr));
- si->shdr = (XElf_Shdr *) (si + 1);
-#else
- struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem,
- sizeof (*si));
-#endif
-
- /* Get the information regarding the symbols with copy relocations. */
- compute_common_symbol_offset (&SCNINFO_SHDR (si->shdr));
-
- /* This section is needed. */
- si->used = true;
- /* Remember for later the section data structure. */
- ld_state.common_section = si;
-
- if (likely (ld_state.allsections[last_writable]->last != NULL))
- {
- si->next = ld_state.allsections[last_writable]->last->next;
- ld_state.allsections[last_writable]->last->next = si;
- ld_state.allsections[last_writable]->last = si;
- }
- else
- ld_state.allsections[last_writable]->last = si->next = si;
- }
-}
-
-
-/* Create the output sections now. This requires knowledge about all
- the sections we will need. It may be necessary to sort sections in
- the order they are supposed to appear in the executable. The
- sorting use many different kinds of information to optimize the
- resulting binary. Important is to respect segment boundaries and
- the needed alignment. The mode of the segments will be determined
- afterwards automatically by the output routines.
-
- The generic sorting routines work in one of two possible ways:
-
- - if a linker script specifies the sections to be used in the
- output and assigns them to a segment this information is used;
-
- - otherwise the linker will order the sections based on permissions
- and some special knowledge about section names.*/
-static void
-ld_generic_create_sections (struct ld_state *statep)
-{
- struct scngroup *groups;
- size_t cnt;
-
- /* For relocatable object we don't have to bother sorting the
- sections and we do want to preserve the relocation sections as
- they appear in the input files. */
- if (ld_state.file_type != relocatable_file_type)
- {
- /* Collect all the relocation sections. They are handled
- separately. */
- struct scninfo *list = NULL;
- for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
- if ((ld_state.allsections[cnt]->type == SHT_REL
- || ld_state.allsections[cnt]->type == SHT_RELA)
- /* The generated relocation sections are not of any
- interest here. */
- && ld_state.allsections[cnt]->last != NULL)
- {
- if (list == NULL)
- list = ld_state.allsections[cnt]->last;
- else
- {
- /* Merge the sections list. */
- struct scninfo *first = list->next;
- list->next = ld_state.allsections[cnt]->last->next;
- ld_state.allsections[cnt]->last->next = first;
- list = ld_state.allsections[cnt]->last;
- }
-
- /* Remove the entry from the section list. */
- ld_state.allsections[cnt] = NULL;
- }
- ld_state.rellist = list;
-
- if (ld_state.output_segments == NULL)
- /* Sort using builtin rules. */
- sort_sections_generic ();
- else
- sort_sections_lscript ();
- }
-
- /* Now iterate over the input sections and create the sections in the
- order they are required in the output file. */
- for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
- {
- struct scnhead *head = ld_state.allsections[cnt];
- Elf_Scn *scn;
- XElf_Shdr_vardef (shdr);
-
- /* Don't handle unused sections. */
- if (!head->used)
- continue;
-
- /* We first have to create the section group if necessary.
- Section group sections must come (in section index order)
- before any of the section contained. This all is necessary
- only for relocatable object as other object types are not
- allowed to contain section groups. */
- if (ld_state.file_type == relocatable_file_type
- && unlikely (head->flags & SHF_GROUP))
- {
- /* There is at least one section which is contained in a
- section group in the input file. This means we must
- create a section group here as well. The only problem is
- that not all input files have to have to same kind of
- partitioning of the sections. I.e., sections A and B in
- one input file and sections B and C in another input file
- can be in one group. That will result in a group
- containing the sections A, B, and C in the output
- file. */
- struct scninfo *runp;
- Elf32_Word here_groupidx = 0;
- struct scngroup *here_group;
- struct member *newp;
-
- /* First check whether any section is already in a group.
- In this case we have to add this output section, too. */
- runp = head->last;
- do
- {
- assert (runp->grpid != 0);
-
- here_groupidx = runp->fileinfo->scninfo[runp->grpid].outscnndx;
- if (here_groupidx != 0)
- break;
- }
- while ((runp = runp->next) != head->last);
-
- if (here_groupidx == 0)
- {
- /* We need a new section group section. */
- scn = elf_newscn (ld_state.outelf);
- xelf_getshdr (scn, shdr);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- here_group = (struct scngroup *) xmalloc (sizeof (*here_group));
- here_group->outscnidx = here_groupidx = elf_ndxscn (scn);
- here_group->nscns = 0;
- here_group->member = NULL;
- here_group->next = ld_state.groups;
- /* Pick a name for the section. To keep it meaningful
- we use a name used in the input files. If the
- section group in the output file should contain
- section which were in section groups of different
- names in the input files this is the users
- problem. */
- here_group->nameent
- = ebl_strtabadd (ld_state.shstrtab,
- elf_strptr (runp->fileinfo->elf,
- runp->fileinfo->shstrndx,
- SCNINFO_SHDR (runp->shdr).sh_name),
- 0);
- /* Signature symbol. */
- here_group->symbol
- = runp->fileinfo->scninfo[runp->grpid].symbols;
-
- ld_state.groups = here_group;
- }
- else
- {
- /* Search for the group with this index. */
- here_group = ld_state.groups;
- while (here_group->outscnidx != here_groupidx)
- here_group = here_group->next;
- }
-
- /* Add the new output section. */
- newp = (struct member *) alloca (sizeof (*newp));
- newp->scn = head;
-#ifndef NDT_NEEDED
- newp->next = NULL;
-#endif
- CSNGL_LIST_ADD_REAR (here_group->member, newp);
- ++here_group->nscns;
-
- /* Store the section group index in all input files. */
- runp = head->last;
- do
- {
- assert (runp->grpid != 0);
-
- if (runp->fileinfo->scninfo[runp->grpid].outscnndx == 0)
- runp->fileinfo->scninfo[runp->grpid].outscnndx = here_groupidx;
- else
- assert (runp->fileinfo->scninfo[runp->grpid].outscnndx
- == here_groupidx);
- }
- while ((runp = runp->next) != head->last);
- }
-
- /* We'll use this section so get it's name in the section header
- string table. */
- if (head->kind == scn_normal)
- head->nameent = ebl_strtabadd (ld_state.shstrtab, head->name, 0);
-
- /* Create a new section in the output file and add all data
- from all the sections we read. */
- scn = elf_newscn (ld_state.outelf);
- head->scnidx = elf_ndxscn (scn);
- xelf_getshdr (scn, shdr);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- assert (head->type != SHT_NULL);
- assert (head->type != SHT_SYMTAB);
- assert (head->type != SHT_DYNSYM || head->kind != scn_normal);
- assert (head->type != SHT_STRTAB || head->kind != scn_normal);
- assert (head->type != SHT_GROUP);
- shdr->sh_type = head->type;
- shdr->sh_flags = head->flags;
- shdr->sh_addralign = head->align;
- shdr->sh_entsize = head->entsize;
- assert (shdr->sh_entsize != 0 || (shdr->sh_flags & SHF_MERGE) == 0);
- (void) xelf_update_shdr (scn, shdr);
-
- /* We have to know the section index of the dynamic symbol table
- right away. */
- if (head->kind == scn_dot_dynsym)
- ld_state.dynsymscnidx = elf_ndxscn (scn);
- }
-
- /* Actually create the section group sections. */
- groups = ld_state.groups;
- while (groups != NULL)
- {
- Elf_Scn *scn;
- Elf_Data *data;
- Elf32_Word *grpdata;
- struct member *runp;
-
- scn = elf_getscn (ld_state.outelf, groups->outscnidx);
- assert (scn != NULL);
-
- data = elf_newdata (scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- data->d_size = (groups->nscns + 1) * sizeof (Elf32_Word);
- data->d_buf = grpdata = (Elf32_Word *) xmalloc (data->d_size);
- data->d_type = ELF_T_WORD;
- data->d_version = EV_CURRENT;
- data->d_off = 0;
- /* XXX What better to use? */
- data->d_align = sizeof (Elf32_Word);
-
- /* The first word in the section is the flag word. */
- /* XXX Set COMDATA flag is necessary. */
- grpdata[0] = 0;
-
- runp = groups->member->next;
- cnt = 1;
- do
- /* Fill in the index of the section. */
- grpdata[cnt++] = runp->scn->scnidx;
- while ((runp = runp->next) != groups->member->next);
-
- groups = groups->next;
- }
-}
-
-
-static bool
-reduce_symbol_p (XElf_Sym *sym, struct Ebl_Strent *strent)
-{
- const char *str;
- const char *version;
- struct id_list search;
- struct id_list *verp;
- bool result = ld_state.default_bind_local;
-
- if (XELF_ST_BIND (sym->st_info) == STB_LOCAL || sym->st_shndx == SHN_UNDEF)
- /* We don't have to do anything to local symbols here. */
- /* XXX Any section value in [SHN_LORESERVER,SHN_XINDEX) need
- special treatment? */
- return false;
-
- /* XXX Handle other symbol bindings. */
- assert (XELF_ST_BIND (sym->st_info) == STB_GLOBAL
- || XELF_ST_BIND (sym->st_info) == STB_WEAK);
-
- str = ebl_string (strent);
- version = strchr (str, VER_CHR);
- if (version != NULL)
- {
- search.id = strndupa (str, version - str);
- if (*++version == VER_CHR)
- /* Skip the second '@' signalling a default definition. */
- ++version;
- }
- else
- {
- search.id = str;
- version = "";
- }
-
- verp = ld_version_str_tab_find (&ld_state.version_str_tab,
- elf_hash (search.id), &search);
- while (verp != NULL)
- {
- /* We have this symbol in the version hash table. Now match the
- version name. */
- if (strcmp (verp->u.s.versionname, version) == 0)
- /* Match! */
- return verp->u.s.local;
-
- verp = verp->next;
- }
-
- /* XXX Add test for wildcard version symbols. */
-
- return result;
-}
-
-
-static XElf_Addr
-eval_expression (struct expression *expr, XElf_Addr addr)
-{
- XElf_Addr val = ~((XElf_Addr) 0);
-
- switch (expr->tag)
- {
- case exp_num:
- val = expr->val.num;
- break;
-
- case exp_sizeof_headers:
- {
- /* The 'elf_update' call determine the offset of the first
- section. The the size of the header. */
- XElf_Shdr_vardef (shdr);
-
- xelf_getshdr (elf_getscn (ld_state.outelf, 1), shdr);
- assert (shdr != NULL);
-
- val = shdr->sh_offset;
- }
- break;
-
- case exp_pagesize:
- val = ld_state.pagesize;
- break;
-
- case exp_id:
- /* We are here computing only address expressions. It seems not
- to be necessary to handle any variable but ".". Let's avoid
- the complication. If it turns up to be needed we can add
- it. */
- if (strcmp (expr->val.str, ".") != 0)
- error (EXIT_FAILURE, 0, gettext ("\
-address computation expression contains variable '%s'"),
- expr->val.str);
-
- val = addr;
- break;
-
- case exp_mult:
- val = (eval_expression (expr->val.binary.left, addr)
- * eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_div:
- val = (eval_expression (expr->val.binary.left, addr)
- / eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_mod:
- val = (eval_expression (expr->val.binary.left, addr)
- % eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_plus:
- val = (eval_expression (expr->val.binary.left, addr)
- + eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_minus:
- val = (eval_expression (expr->val.binary.left, addr)
- - eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_and:
- val = (eval_expression (expr->val.binary.left, addr)
- & eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_or:
- val = (eval_expression (expr->val.binary.left, addr)
- | eval_expression (expr->val.binary.right, addr));
- break;
-
- case exp_align:
- val = eval_expression (expr->val.child, addr);
- if ((val & (val - 1)) != 0)
- error (EXIT_FAILURE, 0, gettext ("argument '%" PRIuMAX "' of ALIGN in address computation expression is no power of two"),
- (uintmax_t) val);
- val = (addr + val - 1) & ~(val - 1);
- break;
- }
-
- return val;
-}
-
-
-/* Find a good as possible size for the hash table so that all the
- non-zero entries in HASHCODES don't collide too much and the table
- isn't too large. There is no exact formular for this so we use a
- heuristic. Depending on the optimization level the search is
- longer or shorter. */
-static size_t
-optimal_bucket_size (Elf32_Word *hashcodes, size_t maxcnt, int optlevel)
-{
- size_t minsize;
- size_t maxsize;
- size_t bestsize;
- uint64_t bestcost;
- size_t size;
- uint32_t *counts;
- uint32_t *lengths;
-
- if (maxcnt == 0)
- return 0;
-
- /* When we are not optimizing we run only very few tests. */
- if (optlevel <= 0)
- {
- minsize = maxcnt;
- maxsize = maxcnt + 10000 / maxcnt;
- }
- else
- {
- /* Does not make much sense to start with a smaller table than
- one which has at least four collisions. */
- minsize = MAX (1, maxcnt / 4);
- /* We look for a best fit in the range of up to eigth times the
- number of elements. */
- maxsize = 2 * maxcnt + (6 * MIN (optlevel, 100) * maxcnt) / 100;
- }
- bestsize = maxcnt;
- bestcost = UINT_MAX;
-
- /* Array for counting the collisions and chain lengths. */
- counts = (uint32_t *) xmalloc ((maxcnt + 1 + maxsize) * sizeof (uint32_t));
- lengths = &counts[maxcnt + 1];
-
- for (size = minsize; size <= maxsize; ++size)
- {
- size_t inner;
- uint64_t cost;
- uint32_t maxlength;
- uint64_t success;
- uint32_t acc;
- double factor;
-
- memset (lengths, '\0', size * sizeof (uint32_t));
- memset (counts, '\0', (maxcnt + 1) * sizeof (uint32_t));
-
- /* Determine how often each hash bucket is used. */
- for (inner = 0; inner < maxcnt; ++inner)
- ++lengths[hashcodes[inner] % size];
-
- /* Determine the lengths. */
- maxlength = 0;
- for (inner = 0; inner < size; ++inner)
- {
- ++counts[lengths[inner]];
-
- if (lengths[inner] > maxlength)
- maxlength = lengths[inner];
- }
-
- /* Determine successful lookup length. */
- acc = 0;
- success = 0;
- for (inner = 0; inner <= maxlength; ++inner)
- {
- acc += inner;
- success += counts[inner] * acc;
- }
-
- /* We can compute two factors now: the average length of a
- positive search and the average length of a negative search.
- We count the number of comparisons which have to look at the
- names themselves. Recognizing that the chain ended is not
- accounted for since it's almost for free.
-
- Which lookup is more important depends on the kind of DSO.
- If it is a system DSO like libc it is expected that most
- lookups succeed. Otherwise most lookups fail. */
- if (ld_state.is_system_library)
- factor = (1.0 * (double) success / (double) maxcnt
- + 0.3 * (double) maxcnt / (double) size);
- else
- factor = (0.3 * (double) success / (double) maxcnt
- + 1.0 * (double) maxcnt / (double) size);
-
- /* Combine the lookup cost factor. The 1/16th addend adds
- penalties for too large table sizes. */
- cost = (2 + maxcnt + size) * (factor + 1.0 / 16.0);
-
-#if 0
- printf ("maxcnt = %d, size = %d, cost = %Ld, success = %g, fail = %g, factor = %g\n",
- maxcnt, size, cost, (double) success / (double) maxcnt, (double) maxcnt / (double) size, factor);
-#endif
-
- /* Compare with current best results. */
- if (cost < bestcost)
- {
- bestcost = cost;
- bestsize = size;
- }
- }
-
- free (counts);
-
- return bestsize;
-}
-
-
-static XElf_Addr
-find_entry_point (void)
-{
- XElf_Addr result;
-
- if (ld_state.entry != NULL)
- {
- struct symbol search = { .name = ld_state.entry };
- struct symbol *syment;
-
- syment = ld_symbol_tab_find (&ld_state.symbol_tab,
- elf_hash (ld_state.entry), &search);
- if (syment != NULL && syment->defined)
- {
- /* We found the symbol. */
- Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf,
- ld_state.symscnidx), NULL);
-
- XElf_Sym_vardef (sym);
-
- sym = NULL;
- if (data != NULL)
- xelf_getsym (data, ld_state.dblindirect[syment->outsymidx], sym);
-
- if (sym == NULL && ld_state.need_dynsym && syment->outdynsymidx != 0)
- {
- /* Use the dynamic symbol table if available. */
- data = elf_getdata (elf_getscn (ld_state.outelf,
- ld_state.dynsymscnidx), NULL);
-
- sym = NULL;
- if (data != NULL)
- xelf_getsym (data, syment->outdynsymidx, sym);
- }
-
- if (sym != NULL)
- return sym->st_value;
-
- /* XXX What to do if the output has no non-dynamic symbol
- table and the dynamic symbol table does not contain the
- symbol? */
- assert (ld_state.need_symtab);
- assert (ld_state.symscnidx != 0);
- }
- }
-
- /* We couldn't find the symbol or none was given. Use the first
- address of the ".text" section then. */
-
-
- result = 0;
-
- /* In DSOs this is no fatal error. They usually have no entry
- points. In this case we set the entry point to zero, which makes
- sure it will always fail. */
- if (ld_state.file_type == executable_file_type)
- {
- if (ld_state.entry != NULL)
- error (0, 0, gettext ("\
-cannot find entry symbol \"%s\": defaulting to %#0*" PRIx64),
- ld_state.entry,
- xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18,
- (uint64_t) result);
- else
- error (0, 0, gettext ("\
-no entry symbol specified: defaulting to %#0*" PRIx64),
- xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18,
- (uint64_t) result);
- }
-
- return result;
-}
-
-
-static void
-fillin_special_symbol (struct symbol *symst, size_t scnidx, size_t nsym,
- Elf_Data *symdata, struct Ebl_Strtab *strtab)
-{
- assert (ld_state.file_type != relocatable_file_type);
-
- XElf_Sym_vardef (sym);
- xelf_getsym_ptr (symdata, nsym, sym);
-
- /* The name offset will be filled in later. */
- sym->st_name = 0;
- /* Traditionally: globally visible. */
- sym->st_info = XELF_ST_INFO (STB_GLOBAL, symst->type);
- /* No special visibility or so. */
- sym->st_other = 0;
- /* Reference to the GOT or dynamic section. Since the GOT and
- dynamic section are only created for executables and DSOs it
- cannot be that the section index is too large. */
- assert (scnidx != 0);
- assert (scnidx < SHN_LORESERVE || scnidx == SHN_ABS);
- sym->st_shndx = scnidx;
- /* We want the beginning of the section. */
- sym->st_value = 0;
-
- /* Determine the size of the section. */
- if (scnidx != SHN_ABS)
- {
- Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf, scnidx),
- NULL);
- assert (data != NULL);
- sym->st_size = data->d_size;
- /* Make sure there is no second data block. */
- assert (elf_getdata (elf_getscn (ld_state.outelf, scnidx), data)
- == NULL);
- }
-
- /* Insert symbol into the symbol table. Note that we do not have to
- use xelf_update_symshdx. */
- (void) xelf_update_sym (symdata, nsym, sym);
-
- /* Cross-references. */
- ndxtosym[nsym] = symst;
- symst->outsymidx = nsym;
-
- /* Add the name to the string table. */
- symstrent[nsym] = ebl_strtabadd (strtab, symst->name, 0);
-}
-
-
-static void
-new_dynamic_entry (Elf_Data *data, int idx, XElf_Sxword tag, XElf_Addr val)
-{
- XElf_Dyn_vardef (dyn);
- xelf_getdyn_ptr (data, idx, dyn);
- dyn->d_tag = tag;
- dyn->d_un.d_ptr = val;
- (void) xelf_update_dyn (data, idx, dyn);
-}
-
-
-static void
-allocate_version_names (struct usedfiles *runp, struct Ebl_Strtab *dynstrtab)
-{
- /* If this DSO has no versions skip it. */
- if (runp->status != opened || runp->verdefdata == NULL)
- return;
-
- /* Add the object name. */
- int offset = 0;
- while (1)
- {
- XElf_Verdef_vardef (def);
- XElf_Verdaux_vardef (aux);
-
- /* Get data at the next offset. */
- xelf_getverdef (runp->verdefdata, offset, def);
- assert (def != NULL);
- xelf_getverdaux (runp->verdefdata, offset + def->vd_aux, aux);
- assert (aux != NULL);
-
- assert (def->vd_ndx <= runp->nverdef);
- if (def->vd_ndx == 1 || runp->verdefused[def->vd_ndx] != 0)
- {
- runp->verdefent[def->vd_ndx]
- = ebl_strtabadd (dynstrtab, elf_strptr (runp->elf,
- runp->dynsymstridx,
- aux->vda_name), 0);
-
- if (def->vd_ndx > 1)
- runp->verdefused[def->vd_ndx] = ld_state.nextveridx++;
- }
-
- if (def->vd_next == 0)
- /* That were all versions. */
- break;
-
- offset += def->vd_next;
- }
-}
-
-
-XElf_Off
-create_verneed_data (XElf_Off offset, Elf_Data *verneeddata,
- struct usedfiles *runp, int *ntotal)
-{
- size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1);
- size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1);
- int need_offset;
- bool filled = false;
- GElf_Verneed verneed;
- GElf_Vernaux vernaux;
- int ndef = 0;
-size_t cnt;
-
- /* If this DSO has no versions skip it. */
- if (runp->nverdefused == 0)
- return offset;
-
- /* We fill in the Verneed record last. Remember the
- offset. */
- need_offset = offset;
- offset += verneed_size;
-
- for (cnt = 2; cnt <= runp->nverdef; ++cnt)
- if (runp->verdefused[cnt] != 0)
- {
- assert (runp->verdefent[cnt] != NULL);
-
- if (filled)
- {
- vernaux.vna_next = vernaux_size;
- (void) gelf_update_vernaux (verneeddata, offset,
- &vernaux);
- offset += vernaux_size;
- }
-
- vernaux.vna_hash
- = elf_hash (ebl_string (runp->verdefent[cnt]));
- vernaux.vna_flags = 0;
- vernaux.vna_other = runp->verdefused[cnt];
- vernaux.vna_name = ebl_strtaboffset (runp->verdefent[cnt]);
- filled = true;
- ++ndef;
- }
-
- assert (filled);
- vernaux.vna_next = 0;
- (void) gelf_update_vernaux (verneeddata, offset, &vernaux);
- offset += vernaux_size;
-
- verneed.vn_version = VER_NEED_CURRENT;
- verneed.vn_cnt = ndef;
- verneed.vn_file = ebl_strtaboffset (runp->verdefent[1]);
- /* The first auxiliary entry is always found directly
- after the verneed entry. */
- verneed.vn_aux = verneed_size;
- verneed.vn_next = --*ntotal > 0 ? offset - need_offset : 0;
- (void) gelf_update_verneed (verneeddata, need_offset,
- &verneed);
-
- return offset;
-}
-
-
-/* Create the output file.
-
- For relocatable files what basically has to happen is that all
- sections from all input files are written into the output file.
- Sections with the same name are combined (offsets adjusted
- accordingly). The symbol tables are combined in one single table.
- When stripping certain symbol table entries are omitted.
-
- For executables (shared or not) we have to create the program header,
- additional sections like the .interp, eventually (in addition) create
- a dynamic symbol table and a dynamic section. Also the relocations
-have to be processed differently. */
-static int
-ld_generic_create_outfile (struct ld_state *statep)
-{
- struct scnlist
- {
- size_t scnidx;
- struct scninfo *scninfo;
- struct scnlist *next;
- };
- struct scnlist *rellist = NULL;
- size_t cnt;
- Elf_Scn *symscn = NULL;
- Elf_Scn *xndxscn = NULL;
- Elf_Scn *strscn = NULL;
- struct Ebl_Strtab *strtab = NULL;
- struct Ebl_Strtab *dynstrtab = NULL;
- XElf_Shdr_vardef (shdr);
- Elf_Data *data;
- Elf_Data *symdata = NULL;
- Elf_Data *xndxdata = NULL;
- struct usedfiles *file;
- size_t nsym;
- size_t nsym_local;
- size_t nsym_allocated;
- size_t nsym_dyn = 0;
- Elf32_Word *dblindirect = NULL;
-#ifndef NDEBUG
- bool need_xndx;
-#endif
- Elf_Scn *shstrtab_scn;
- size_t shstrtab_ndx;
- XElf_Ehdr_vardef (ehdr);
- struct Ebl_Strent *symtab_ent = NULL;
- struct Ebl_Strent *xndx_ent = NULL;
- struct Ebl_Strent *strtab_ent = NULL;
- struct Ebl_Strent *shstrtab_ent;
- struct scngroup *groups;
- Elf_Scn *dynsymscn = NULL;
- Elf_Data *dynsymdata = NULL;
- Elf_Data *dynstrdata = NULL;
- Elf32_Word *hashcodes = NULL;
- size_t nsym_dyn_allocated = 0;
- Elf_Scn *versymscn = NULL;
- Elf_Data *versymdata = NULL;
-
- if (ld_state.need_symtab)
- {
- /* First create the symbol table. We need the symbol section itself
- and the string table for it. */
- symscn = elf_newscn (ld_state.outelf);
- ld_state.symscnidx = elf_ndxscn (symscn);
- symdata = elf_newdata (symscn);
- if (symdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create symbol table for output file: %s"),
- elf_errmsg (-1));
-
- symdata->d_type = ELF_T_SYM;
- /* This is an estimated size, but it will definitely cap the real value.
- We might have to adjust the number later. */
- nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot
- + ld_state.nusedsections + ld_state.nlscript_syms);
- symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
- nsym_allocated);
-
- /* Optionally the extended section table. */
- /* XXX Is SHN_LORESERVE correct? Do we need some other sections? */
- if (unlikely (ld_state.nusedsections >= SHN_LORESERVE))
- {
- xndxscn = elf_newscn (ld_state.outelf);
- ld_state.xndxscnidx = elf_ndxscn (xndxscn);
-
- xndxdata = elf_newdata (xndxscn);
- if (xndxdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create symbol table for output file: %s"),
- elf_errmsg (-1));
-
- /* The following relies on the fact that Elf32_Word and Elf64_Word
- have the same size. */
- xndxdata->d_type = ELF_T_WORD;
- /* This is an estimated size, but it will definitely cap the
- real value. we might have to adjust the number later. */
- xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD,
- nsym_allocated);
- /* The first entry is left empty, clear it here and now. */
- xndxdata->d_buf = memset (xmalloc (xndxdata->d_size), '\0',
- xelf_fsize (ld_state.outelf, ELF_T_WORD,
- 1));
- xndxdata->d_off = 0;
- /* XXX Should use an ebl function. */
- xndxdata->d_align = sizeof (Elf32_Word);
- }
- }
- else
- {
- assert (ld_state.need_dynsym);
-
- /* First create the symbol table. We need the symbol section itself
- and the string table for it. */
- symscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx);
- symdata = elf_newdata (symscn);
- if (symdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create symbol table for output file: %s"),
- elf_errmsg (-1));
-
- symdata->d_version = EV_CURRENT;
- symdata->d_type = ELF_T_SYM;
- /* This is an estimated size, but it will definitely cap the real value.
- We might have to adjust the number later. */
- nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot
- - ld_state.nlocalsymbols + ld_state.nlscript_syms);
- symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
- nsym_allocated);
- }
-
- /* The first entry is left empty, clear it here and now. */
- symdata->d_buf = memset (xmalloc (symdata->d_size), '\0',
- xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
- symdata->d_off = 0;
- /* XXX This is ugly but how else can it be done. */
- symdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
- /* Allocate another array to keep track of the handles for the symbol
- names. */
- symstrent = (struct Ebl_Strent **) xcalloc (nsym_allocated,
- sizeof (struct Ebl_Strent *));
-
- /* By starting at 1 we effectively add a null entry. */
- nsym = 1;
-
- /* Iteration over all sections. */
- for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
- {
- struct scnhead *head = ld_state.allsections[cnt];
- Elf_Scn *scn;
- struct scninfo *runp;
- XElf_Off offset;
- Elf32_Word xndx;
-
- /* Don't handle unused sections at all. */
- if (!head->used)
- continue;
-
- /* Get the section handle. */
- scn = elf_getscn (ld_state.outelf, head->scnidx);
-
- if (unlikely (head->kind == scn_dot_interp))
- {
- Elf_Data *outdata = elf_newdata (scn);
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* This is the string we'll put in the section. */
- const char *interp = ld_state.interp ?: "/lib/ld.so.1";
-
- /* Create the section data. */
- outdata->d_buf = (void *) interp;
- outdata->d_size = strlen (interp) + 1;
- outdata->d_type = ELF_T_BYTE;
- outdata->d_off = 0;
- outdata->d_align = 1;
- outdata->d_version = EV_CURRENT;
-
- /* Remember the index of this section. */
- ld_state.interpscnidx = head->scnidx;
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_got))
- {
- /* Remember the index of this section. */
- ld_state.gotscnidx = elf_ndxscn (scn);
-
- /* Give the backend the change to initialize the section. */
- INITIALIZE_GOT (&ld_state, scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_dynrel))
- {
- Elf_Data *outdata;
-
- outdata = elf_newdata (scn);
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- outdata->d_size = ld_state.relsize_total;
- outdata->d_buf = xmalloc (outdata->d_size);
- outdata->d_type = (REL_TYPE (&ld_state) == DT_REL
- ? ELF_T_REL : ELF_T_RELA);
- outdata->d_off = 0;
- outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
- /* Remember the index of this section. */
- ld_state.reldynscnidx = elf_ndxscn (scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_dynamic))
- {
- /* Only create the data for now. */
- Elf_Data *outdata;
-
- /* Account for a few more entries we have to add. */
- if (ld_state.dt_flags != 0)
- ++ld_state.ndynamic;
- if (ld_state.dt_flags_1 != 0)
- ++ld_state.ndynamic;
- if (ld_state.dt_feature_1 != 0)
- ++ld_state.ndynamic;
-
- outdata = elf_newdata (scn);
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* Create the section data. */
- outdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_DYN,
- ld_state.ndynamic);
- outdata->d_buf = xcalloc (1, outdata->d_size);
- outdata->d_type = ELF_T_DYN;
- outdata->d_off = 0;
- outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
- /* Remember the index of this section. */
- ld_state.dynamicscnidx = elf_ndxscn (scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_dynsym))
- {
- /* We already know the section index. */
- assert (ld_state.dynsymscnidx == elf_ndxscn (scn));
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_dynstr))
- {
- /* Remember the index of this section. */
- ld_state.dynstrscnidx = elf_ndxscn (scn);
-
- /* Create the string table. */
- dynstrtab = ebl_strtabinit (true);
-
- /* XXX TBI
- We have to add all the strings which are needed in the
- dynamic section here. This means DT_FILTER,
- DT_AUXILIARY, ... entries. */
- if (ld_state.ndsofiles > 0)
- {
- struct usedfiles *frunp = ld_state.dsofiles;
-
- do
- if (! ld_state.ignore_unused_dsos || frunp->used)
- frunp->sonameent = ebl_strtabadd (dynstrtab, frunp->soname,
- 0);
- while ((frunp = frunp->next) != ld_state.dsofiles);
- }
-
-
- /* Add the runtime path information. The strings are stored
- in the .dynstr section. If both rpath and runpath are defined
- the runpath information is used. */
- if (ld_state.runpath != NULL || ld_state.rpath != NULL)
- {
- struct pathelement *startp;
- struct pathelement *prunp;
- int tag;
- size_t len;
- char *str;
- char *cp;
-
- if (ld_state.runpath != NULL)
- {
- startp = ld_state.runpath;
- tag = DT_RUNPATH;
- }
- else
- {
- startp = ld_state.rpath;
- tag = DT_RPATH;
- }
-
- /* Determine how long the string will be. */
- for (len = 0, prunp = startp; prunp != NULL; prunp = prunp->next)
- len += strlen (prunp->pname) + 1;
-
- cp = str = (char *) obstack_alloc (&ld_state.smem, len);
- /* Copy the string. */
- for (prunp = startp; prunp != NULL; prunp = prunp->next)
- {
- cp = stpcpy (cp, prunp->pname);
- *cp++ = ':';
- }
- /* Remove the last colon. */
- cp[-1] = '\0';
-
- /* Remember the values until we can generate the dynamic
- section. */
- ld_state.rxxpath_strent = ebl_strtabadd (dynstrtab, str, len);
- ld_state.rxxpath_tag = tag;
- }
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_hash))
- {
- /* Remember the index of this section. */
- ld_state.hashscnidx = elf_ndxscn (scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_plt))
- {
- /* Remember the index of this section. */
- ld_state.pltscnidx = elf_ndxscn (scn);
-
- /* Give the backend the change to initialize the section. */
- INITIALIZE_PLT (&ld_state, scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_pltrel))
- {
- /* Remember the index of this section. */
- ld_state.pltrelscnidx = elf_ndxscn (scn);
-
- /* Give the backend the change to initialize the section. */
- INITIALIZE_PLTREL (&ld_state, scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_version))
- {
- /* Remember the index of this section. */
- ld_state.versymscnidx = elf_ndxscn (scn);
-
- continue;
- }
-
- if (unlikely (head->kind == scn_dot_version_r))
- {
- /* Remember the index of this section. */
- ld_state.verneedscnidx = elf_ndxscn (scn);
-
- continue;
- }
-
- /* If we come here we must be handling a normal section. */
- assert (head->kind == scn_normal);
-
- /* Create an STT_SECTION entry in the symbol table. But not for
- the symbolic symbol table. */
- if (ld_state.need_symtab)
- {
- /* XXX Can we be cleverer and do this only if needed? */
- XElf_Sym_vardef (sym);
-
- /* Optimization ahead: in the native linker we get a pointer
- to the final location so that the following code writes
- directly in the correct place. Otherwise we write into
- the local variable first. */
- xelf_getsym_ptr (symdata, nsym, sym);
-
- /* Usual section symbol: local, no specific information,
- except the section index. The offset here is zero, the
- start address will later be added. */
- sym->st_name = 0;
- sym->st_info = XELF_ST_INFO (STB_LOCAL, STT_SECTION);
- sym->st_other = 0;
- sym->st_value = 0;
- sym->st_size = 0;
- /* In relocatable files the section index can be too big for
- the ElfXX_Sym struct. we have to deal with the extended
- symbol table. */
- if (likely (head->scnidx < SHN_LORESERVE))
- {
- sym->st_shndx = head->scnidx;
- xndx = 0;
- }
- else
- {
- sym->st_shndx = SHN_XINDEX;
- xndx = head->scnidx;
- }
- /* Commit the change. See the optimization above, this does
- not change the symbol table entry. But the extended
- section index table entry is always written, if there is
- such a table. */
- assert (nsym < nsym_allocated);
- xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 0);
-
- /* Remember the symbol's index in the symbol table. */
- head->scnsymidx = nsym++;
- }
-
- if (head->type == SHT_REL || head->type == SHT_RELA)
- {
- /* Remember that we have to fill in the symbol table section
- index. */
- if (ld_state.file_type == relocatable_file_type)
- {
- struct scnlist *newp;
-
- newp = (struct scnlist *) alloca (sizeof (*newp));
- newp->scnidx = head->scnidx;
- newp->scninfo = head->last->next;
-#ifndef NDEBUG
- newp->next = NULL;
-#endif
- SNGL_LIST_PUSH (rellist, newp);
- }
- else
- {
- /* When we create an executable or a DSO we don't simply
- copy the existing relocations. Instead many will be
- resolved, others will be converted. Create a data buffer
- large enough to contain the contents which we will fill
- in later. */
- int type = head->type == SHT_REL ? ELF_T_REL : ELF_T_RELA;
-
- data = elf_newdata (scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- data->d_size = xelf_fsize (ld_state.outelf, type, head->relsize);
- data->d_buf = xcalloc (data->d_size, 1);
- data->d_type = type;
- data->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
- data->d_off = 0;
-
- continue;
- }
- }
-
- /* Recognize string and merge flag and handle them. */
- if (head->flags & SHF_MERGE)
- {
- /* We merge the contents of the sections. For this we do
- not look at the contents of section directly. Instead we
- look at the symbols of the section. */
- Elf_Data *outdata;
-
- /* Concatenate the lists of symbols for all sections.
-
- XXX In case any input section has no symbols associated
- (this happens for debug sections) we cannot use this
- method. Implement parsing the other debug sections and
- find the string pointers. For now we don't merge. */
- runp = head->last->next;
- if (runp->symbols == NULL)
- {
- head->flags &= ~SHF_MERGE;
- goto no_merge;
- }
- head->symbols = runp->symbols;
-
- while ((runp = runp->next) != head->last->next)
- {
- if (runp->symbols == NULL)
- {
- head->flags &= ~SHF_MERGE;
- head->symbols = NULL;
- goto no_merge;
- }
-
- struct symbol *oldhead = head->symbols->next_in_scn;
-
- head->symbols->next_in_scn = runp->symbols->next_in_scn;
- runp->symbols->next_in_scn = oldhead;
- head->symbols = runp->symbols;
- }
-
- /* Create the output section. */
- outdata = elf_newdata (scn);
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* We use different merging algorithms for performance
- reasons. We can easily handle single-byte and
- wchar_t-wide character strings. All other cases (which
- really should happen in real life) are handled by the
- generic code. */
- if (SCNINFO_SHDR (head->last->shdr).sh_entsize == 1
- && (head->flags & SHF_STRINGS))
- {
- /* Simple, single-byte string matching. */
- struct Ebl_Strtab *mergestrtab;
- struct symbol *symrunp;
- Elf_Data *locsymdata = NULL;
- Elf_Data *locdata = NULL;
-
- mergestrtab = ebl_strtabinit (false);
-
- symrunp = head->symbols->next_in_scn;
- file = NULL;
- do
- {
- /* Accelarate the loop. We cache the file
- information since it might very well be the case
- that the previous entry was from the same
- file. */
- if (symrunp->file != file)
- {
- /* Remember the file. */
- file = symrunp->file;
- /* Symbol table data from that file. */
- locsymdata = file->symtabdata;
- /* String section data. */
- locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
- NULL);
- assert (locdata != NULL);
- /* While we are at it, remember the output
- section. If we don't access the string data
- section the section won't be in the output
- file. So it is sufficient to do the work
- here. */
- file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
- }
-
- /* Get the symbol information. This provides us the
- offset into the string data section. */
- XElf_Sym_vardef (sym);
- xelf_getsym (locsymdata, symrunp->symidx, sym);
- assert (sym != NULL);
-
- /* Get the data from the file. Note that we access
- the raw section data; no endian-ness issues with
- single-byte strings. */
- symrunp->merge.handle
- = ebl_strtabadd (mergestrtab,
- (char *) locdata->d_buf + sym->st_value,
- 0);
- }
- while ((symrunp = symrunp->next_in_scn)
- != head->symbols->next_in_scn);
-
- /* All strings have been added. Create the final table. */
- ebl_strtabfinalize (mergestrtab, outdata);
-
- /* Compute the final offsets in the section. */
- symrunp = runp->symbols;
- do
- {
- symrunp->merge.value
- = ebl_strtaboffset (symrunp->merge.handle);
- symrunp->merged = 1;
- }
- while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
- /* We don't need the string table anymore. */
- ebl_strtabfree (mergestrtab);
- }
- else if (likely (SCNINFO_SHDR (head->last->shdr).sh_entsize
- == sizeof (wchar_t))
- && likely (head->flags & SHF_STRINGS))
- {
- /* Simple, wchar_t string merging. */
- struct Ebl_WStrtab *mergestrtab;
- struct symbol *symrunp;
- Elf_Data *locsymdata = NULL;
- Elf_Data *locdata = NULL;
-
- mergestrtab = ebl_wstrtabinit (false);
-
- symrunp = runp->symbols;
- file = NULL;
- do
- {
- /* Accelarate the loop. We cache the file
- information since it might very well be the case
- that the previous entry was from the same
- file. */
- if (symrunp->file != file)
- {
- /* Remember the file. */
- file = symrunp->file;
- /* Symbol table data from that file. */
- locsymdata = file->symtabdata;
- /* String section data. */
- locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
- NULL);
- assert (locdata != NULL);
-
- /* While we are at it, remember the output
- section. If we don't access the string data
- section the section won't be in the output
- file. So it is sufficient to do the work
- here. */
- file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
- }
-
- /* Get the symbol information. This provides us the
- offset into the string data section. */
- XElf_Sym_vardef (sym);
- xelf_getsym (locsymdata, symrunp->symidx, sym);
- assert (sym != NULL);
-
- /* Get the data from the file. Using the raw
- section data here is possible since we don't
- interpret the string themselves except for
- looking for the wide NUL character. The NUL
- character has fortunately the same representation
- regardless of the byte order. */
- symrunp->merge.handle
- = ebl_wstrtabadd (mergestrtab,
- (wchar_t *) ((char *) locdata->d_buf
- + sym->st_value), 0);
- }
- while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
- /* All strings have been added. Create the final table. */
- ebl_wstrtabfinalize (mergestrtab, outdata);
-
- /* Compute the final offsets in the section. */
- symrunp = runp->symbols;
- do
- {
- symrunp->merge.value
- = ebl_wstrtaboffset (symrunp->merge.handle);
- symrunp->merged = 1;
- }
- while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
- /* We don't need the string table anymore. */
- ebl_wstrtabfree (mergestrtab);
- }
- else
- {
- /* Non-standard merging. */
- struct Ebl_GStrtab *mergestrtab;
- struct symbol *symrunp;
- Elf_Data *locsymdata = NULL;
- Elf_Data *locdata = NULL;
- /* If this is no string section the length of each "string"
- is always one. */
- unsigned int len = (head->flags & SHF_STRINGS) ? 0 : 1;
-
- /* This is the generic string table functionality. Much
- slower than the specialized code. */
- mergestrtab
- = ebl_gstrtabinit (SCNINFO_SHDR (head->last->shdr).sh_entsize,
- false);
-
- symrunp = runp->symbols;
- file = NULL;
- do
- {
- /* Accelarate the loop. We cache the file
- information since it might very well be the case
- that the previous entry was from the same
- file. */
- if (symrunp->file != file)
- {
- /* Remember the file. */
- file = symrunp->file;
- /* Symbol table data from that file. */
- locsymdata = file->symtabdata;
- /* String section data. */
- locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
- NULL);
- assert (locdata != NULL);
-
- /* While we are at it, remember the output
- section. If we don't access the string data
- section the section won't be in the output
- file. So it is sufficient to do the work
- here. */
- file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
- }
-
- /* Get the symbol information. This provides us the
- offset into the string data section. */
- XElf_Sym_vardef (sym);
- xelf_getsym (locsymdata, symrunp->symidx, sym);
- assert (sym != NULL);
-
- /* Get the data from the file. Using the raw
- section data here is possible since we don't
- interpret the string themselves except for
- looking for the wide NUL character. The NUL
- character has fortunately the same representation
- regardless of the byte order. */
- symrunp->merge.handle
- = ebl_gstrtabadd (mergestrtab,
- (char *) locdata->d_buf + sym->st_value,
- len);
- }
- while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
- /* Create the final table. */
- ebl_gstrtabfinalize (mergestrtab, outdata);
-
- /* Compute the final offsets in the section. */
- symrunp = runp->symbols;
- do
- {
- symrunp->merge.value
- = ebl_gstrtaboffset (symrunp->merge.handle);
- symrunp->merged = 1;
- }
- while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
- /* We don't need the string table anymore. */
- ebl_gstrtabfree (mergestrtab);
- }
- }
- else
- {
- no_merge:
- assert (head->scnidx == elf_ndxscn (scn));
-
- /* It is important to start with the first list entry (and
- not just any one) to add the sections in the correct
- order. */
- runp = head->last->next;
- offset = 0;
- do
- {
- Elf_Data *outdata = elf_newdata (scn);
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* Exceptional case: if we synthesize a data block SCN
- is NULL and the sectio header info must be for a
- SHT_NOBITS block and the size and alignment are
- filled in. */
- if (likely (runp->scn != NULL))
- {
- data = elf_getdata (runp->scn, NULL);
- assert (data != NULL);
-
- /* We reuse the data buffer in the input file. */
- *outdata = *data;
-
- /* Given that we read the input file from disk we know there
- cannot be another data part. */
- assert (elf_getdata (runp->scn, data) == NULL);
- }
- else
- {
- /* Must be a NOBITS section. */
- assert (SCNINFO_SHDR (runp->shdr).sh_type == SHT_NOBITS);
-
- outdata->d_buf = NULL; /* Not needed. */
- outdata->d_type = ELF_T_BYTE;
- outdata->d_version = EV_CURRENT;
- outdata->d_size = SCNINFO_SHDR (runp->shdr).sh_size;
- outdata->d_align = SCNINFO_SHDR (runp->shdr).sh_addralign;
- }
-
- XElf_Off align = MAX (1, outdata->d_align);
- assert (powerof2 (align));
- offset = ((offset + align - 1) & ~(align - 1));
-
- runp->offset = offset;
- runp->outscnndx = head->scnidx;
- runp->allsectionsidx = cnt;
-
- outdata->d_off = offset;
-
- offset += outdata->d_size;
- }
- while ((runp = runp->next) != head->last->next);
-
- /* If necessary add the additional line to the .comment section. */
- if (ld_state.add_ld_comment
- && head->flags == 0
- && head->type == SHT_PROGBITS
- && strcmp (head->name, ".comment") == 0
- && head->entsize == 0)
- {
- Elf_Data *outdata = elf_newdata (scn);
-
- if (outdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- outdata->d_buf = (void *) "\0ld (Red Hat " PACKAGE ") " VERSION;
- outdata->d_size = strlen ((char *) outdata->d_buf + 1) + 2;
- outdata->d_off = offset;
- outdata->d_type = ELF_T_BYTE;
- outdata->d_align = 1;
- }
- /* XXX We should create a .comment section if none exists.
- This requires that we early on detect that no such
- section exists. This should probably be implemented
- together with some merging of the section contents.
- Currently identical entries are not merged. */
- }
- }
-
- /* The table we collect the strings in. */
- strtab = ebl_strtabinit (true);
- if (strtab == NULL)
- error (EXIT_FAILURE, errno, gettext ("cannot create string table"));
-
-
-#ifndef NDEBUG
- /* Keep track of the use of the XINDEX. */
- need_xndx = false;
-#endif
-
- /* We we generate a normal symbol table for an executable and the
- --export-dynamic option is not given, we need an extra table
- which keeps track of the symbol entry belonging to the symbol
- table entry. Note that EXPORT_ALL_DYNAMIC is always set if we
- generate a DSO so we do not have to test this separately. */
- ndxtosym = (struct symbol **) xcalloc (nsym_allocated,
- sizeof (struct symbol));
-
- /* Create the special symbol for the GOT section. */
- if (ld_state.got_symbol != NULL)
- {
- assert (nsym < nsym_allocated);
- fillin_special_symbol (ld_state.got_symbol, ld_state.gotscnidx,
- nsym++, symdata, strtab);
- }
-
- /* Similarly for the dynamic section symbol. */
- if (ld_state.dyn_symbol != NULL)
- {
- assert (nsym < nsym_allocated);
- fillin_special_symbol (ld_state.dyn_symbol, ld_state.dynamicscnidx,
- nsym++, symdata, strtab);
- }
-
- /* Create symbol table entries for the symbols defined in the linker
- script. */
- if (ld_state.lscript_syms != NULL)
- {
- struct symbol *rsym = ld_state.lscript_syms;
- do
- {
- assert (nsym < nsym_allocated);
- fillin_special_symbol (rsym, SHN_ABS, nsym++, symdata, strtab);
- }
- while ((rsym = rsym->next) != NULL);
- }
-
- /* Iterate over all input files to collect the symbols. */
- file = ld_state.relfiles->next;
- symdata = elf_getdata (elf_getscn (ld_state.outelf, ld_state.symscnidx),
- NULL);
- do
- {
- size_t maxcnt;
- Elf_Data *insymdata;
- Elf_Data *inxndxdata;
-
- /* There must be no dynamic symbol table when creating
- relocatable files. */
- assert (ld_state.file_type != relocatable_file_type
- || file->dynsymtabdata == NULL);
-
- insymdata = file->symtabdata;
- assert (insymdata != NULL);
- inxndxdata = file->xndxdata;
-
- maxcnt = file->nsymtab;
-
- file->symindirect = (Elf32_Word *) xcalloc (maxcnt, sizeof (Elf32_Word));
-
- /* The dynamic symbol table does not contain local symbols. So
- we skip those entries. */
- for (cnt = ld_state.need_symtab ? 1 : file->nlocalsymbols; cnt < maxcnt;
- ++cnt)
- {
- XElf_Sym_vardef (sym);
- Elf32_Word xndx;
- struct symbol *defp = NULL;
-
- xelf_getsymshndx (insymdata, inxndxdata, cnt, sym, xndx);
- assert (sym != NULL);
-
- if (unlikely (XELF_ST_TYPE (sym->st_info) == STT_SECTION))
- {
- /* Section symbols should always be local but who knows... */
- if (ld_state.need_symtab)
- {
- /* Determine the real section index in the source file.
- Use the XINDEX section content if necessary. We don't
- add this information to the dynamic symbol table. */
- if (sym->st_shndx != SHN_XINDEX)
- xndx = sym->st_shndx;
-
- assert (file->scninfo[xndx].allsectionsidx
- < ld_state.nallsections);
- file->symindirect[cnt] = ld_state.allsections[file->scninfo[xndx].allsectionsidx]->scnsymidx;
- /* Note that the resulting index can be zero here. There is
- no guarantee that the output file will contain all the
- sections the input file did. */
- }
- continue;
- }
-
- if ((ld_state.strip >= strip_all || !ld_state.need_symtab)
- /* XXX Do we need these entries? */
- && XELF_ST_TYPE (sym->st_info) == STT_FILE)
- continue;
-
-#if NATIVE_ELF != 0
- /* Copy old data. */
- XElf_Sym *sym2 = sym;
- assert (nsym < nsym_allocated);
- xelf_getsym (symdata, nsym, sym);
- *sym = *sym2;
-#endif
-
- if (sym->st_shndx != SHN_UNDEF
- && (sym->st_shndx < SHN_LORESERVE
- || sym->st_shndx == SHN_XINDEX))
- {
- /* If we are creating an executable with no normal
- symbol table and we do not export all symbols and
- this symbol is not defined in a DSO as well, ignore
- it. */
- if (!ld_state.export_all_dynamic && !ld_state.need_symtab)
- {
- assert (cnt >= file->nlocalsymbols);
- defp = file->symref[cnt];
- assert (defp != NULL);
-
- if (!defp->in_dso)
- /* Ignore it. */
- continue;
- }
-
- /* Determine the real section index in the source file. Use
- the XINDEX section content if necessary. */
- if (sym->st_shndx != SHN_XINDEX)
- xndx = sym->st_shndx;
-
- sym->st_value += file->scninfo[xndx].offset;
-
- assert (file->scninfo[xndx].outscnndx < SHN_LORESERVE
- || file->scninfo[xndx].outscnndx > SHN_HIRESERVE);
- if (unlikely (file->scninfo[xndx].outscnndx > SHN_LORESERVE))
- {
- /* It is not possible to have an extended section index
- table for the dynamic symbol table. */
- if (!ld_state.need_symtab)
- error (EXIT_FAILURE, 0, gettext ("\
-section index too large in dynamic symbol table"));
-
- assert (xndxdata != NULL);
- sym->st_shndx = SHN_XINDEX;
- xndx = file->scninfo[xndx].outscnndx;
-#ifndef NDEBUG
- need_xndx = true;
-#endif
- }
- else
- {
- sym->st_shndx = file->scninfo[xndx].outscnndx;
- xndx = 0;
- }
- }
- else if (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_UNDEF)
- {
- /* Check whether we have a (real) definition for this
- symbol. If this is the case we skip this symbol
- table entry. */
- assert (cnt >= file->nlocalsymbols);
- defp = file->symref[cnt];
- assert (defp != NULL);
-
- assert (sym->st_shndx != SHN_COMMON || defp->defined);
-
- if ((sym->st_shndx == SHN_COMMON && !defp->common)
- || (sym->st_shndx == SHN_UNDEF && defp->defined)
- || defp->added)
- /* Ignore this symbol table entry, there is a
- "better" one or we already added it. */
- continue;
-
- /* Remember that we already added this symbol. */
- defp->added = 1;
-
- /* Adjust the section number for common symbols. */
- if (sym->st_shndx == SHN_COMMON)
- {
- sym->st_value = (ld_state.common_section->offset
- + file->symref[cnt]->merge.value);
- assert (ld_state.common_section->outscnndx < SHN_LORESERVE);
- sym->st_shndx = ld_state.common_section->outscnndx;
- xndx = 0;
- }
- }
- else if (unlikely (sym->st_shndx != SHN_ABS))
- {
- if (SPECIAL_SECTION_NUMBER_P (&ld_state, sym->st_shndx))
- /* XXX Add code to handle machine specific special
- sections. */
- abort ();
- }
-
- /* Add the symbol name to the string table. If the user
- chooses the highest level of stripping avoid adding names
- for local symbols in the string table. */
- if (sym->st_name != 0
- && (ld_state.strip < strip_everything
- || XELF_ST_BIND (sym->st_info) != STB_LOCAL))
- symstrent[nsym] = ebl_strtabadd (strtab,
- elf_strptr (file->elf,
- file->symstridx,
- sym->st_name), 0);
-
- /* Once we know the name this field will get the correct
- offset. For now set it to zero which means no name
- associated. */
- sym->st_name = 0;
-
- /* If we had to merge sections we have a completely new
- offset for the symbol. */
- if (file->has_merge_sections && file->symref[cnt] != NULL
- && file->symref[cnt]->merged)
- sym->st_value = file->symref[cnt]->merge.value;
-
- /* Create the record in the output sections. */
- assert (nsym < nsym_allocated);
- xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 0);
-
- /* Add the reference to the symbol record in case we need it.
- Find the symbol if this has not happened yet. We do
- not need the information for local symbols. */
- if (defp == NULL && cnt >= file->nlocalsymbols)
- {
- defp = file->symref[cnt];
- assert (defp != NULL);
- }
-
- /* Store the reference to the symbol record. The
- sorting code will have to keep this array in the
- correct order, too. */
- ndxtosym[nsym] = defp;
-
- /* One more entry finished. */
- if (cnt >= file->nlocalsymbols)
- {
- assert (file->symref[cnt]->outsymidx == 0);
- file->symref[cnt]->outsymidx = nsym;
- }
- file->symindirect[cnt] = nsym++;
- }
- }
- while ((file = file->next) != ld_state.relfiles->next);
- /* Make sure we didn't create the extended section index table for
- nothing. */
- assert (xndxdata == NULL || need_xndx);
-
-
- /* Create the version related sections. */
- if (ld_state.verneedscnidx != 0)
- {
- /* We know the number of input files and total number of
- referenced versions. This allows us to allocate the memory
- and then we iterate over the DSOs to get the version
- information. */
- struct usedfiles *runp;
-
- runp = ld_state.dsofiles->next;
- do
- allocate_version_names (runp, dynstrtab);
- while ((runp = runp->next) != ld_state.dsofiles->next);
-
- if (ld_state.needed != NULL)
- {
- runp = ld_state.needed->next;
- do
- allocate_version_names (runp, dynstrtab);
- while ((runp = runp->next) != ld_state.needed->next);
- }
- }
-
- /* At this point we should hide symbols and so on. */
- if (ld_state.default_bind_local || ld_state.version_str_tab.filled > 0)
- /* XXX Add one more test when handling of wildcard symbol names
- is supported. */
- {
- /* Check all non-local symbols whether they are on the export list. */
- bool any_reduced = false;
-
- for (cnt = 1; cnt < nsym; ++cnt)
- {
- XElf_Sym_vardef (sym);
-
- /* Note that we don't have to use 'xelf_getsymshndx' since we
- only need the binding and the symbol name. */
- xelf_getsym (symdata, cnt, sym);
- assert (sym != NULL);
-
- if (reduce_symbol_p (sym, symstrent[cnt]))
- {
- sym->st_info = XELF_ST_INFO (STB_LOCAL,
- XELF_ST_TYPE (sym->st_info));
- (void) xelf_update_sym (symdata, cnt, sym);
-
- /* Show that we don't need this string anymore. */
- if (ld_state.strip == strip_everything)
- {
- symstrent[cnt] = NULL;
- any_reduced = true;
- }
- }
- }
-
- if (unlikely (any_reduced))
- {
- /* Since we will not write names of local symbols in the
- output file and we have reduced the binding of some
- symbols the string table previously constructed contains
- too many string. Correct it. */
- struct Ebl_Strtab *newp = ebl_strtabinit (true);
-
- for (cnt = 1; cnt < nsym; ++cnt)
- if (symstrent[cnt] != NULL)
- symstrent[cnt] = ebl_strtabadd (newp,
- ebl_string (symstrent[cnt]), 0);
-
- ebl_strtabfree (strtab);
- strtab = newp;
- }
- }
-
- /* Add the references to DSOs. We can add these entries this late
- (after sorting out versioning) because references to DSOs are not
- effected. */
- if (ld_state.from_dso != NULL)
- {
- struct symbol *runp;
- size_t plt_base = nsym + ld_state.nfrom_dso - ld_state.nplt;
- size_t plt_idx = 0;
- size_t obj_idx = 0;
-
- assert (ld_state.nfrom_dso >= ld_state.nplt);
- runp = ld_state.from_dso;
- do
- {
- // XXX What about functions which are only referenced via
- // pointers and not PLT entries? Can we distinguish such uses?
- size_t idx;
- if (runp->type == STT_FUNC)
- {
- /* Store the PLT entry number. */
- runp->merge.value = plt_idx + 1;
- idx = plt_base + plt_idx++;
- }
- else
- idx = nsym + obj_idx++;
-
- XElf_Sym_vardef (sym);
- xelf_getsym_ptr (symdata, idx, sym);
-
- sym->st_value = 0;
- sym->st_size = runp->size;
- sym->st_info = XELF_ST_INFO (runp->weak ? STB_WEAK : STB_GLOBAL,
- runp->type);
- sym->st_other = STV_DEFAULT;
- sym->st_shndx = SHN_UNDEF;
-
- /* Create the record in the output sections. */
- xelf_update_symshndx (symdata, xndxdata, idx, sym, 0, 0);
-
- const char *name = runp->name;
- size_t namelen = 0;
-
- if (runp->file->verdefdata != NULL)
- {
- // XXX Is it useful to add the versym value to struct symbol?
- XElf_Versym versym;
-
- (void) xelf_getversym_copy (runp->file->versymdata, runp->symidx,
- versym);
-
- /* One can only link with the default version. */
- assert ((versym & 0x8000) == 0);
-
- const char *versname
- = ebl_string (runp->file->verdefent[versym]);
-
- size_t versname_len = strlen (versname) + 1;
- namelen = strlen (name) + versname_len + 2;
- char *newp = (char *) obstack_alloc (&ld_state.smem, namelen);
- memcpy (stpcpy (stpcpy (newp, name), "@@"),
- versname, versname_len);
- name = newp;
- }
-
- symstrent[idx] = ebl_strtabadd (strtab, name, namelen);
-
- /* Record the initial index in the symbol table. */
- runp->outsymidx = idx;
-
- /* Remember the symbol record this ELF symbol came from. */
- ndxtosym[idx] = runp;
- }
- while ((runp = runp->next) != ld_state.from_dso);
-
- assert (nsym + obj_idx == plt_base);
- assert (plt_idx == ld_state.nplt);
- nsym = plt_base + plt_idx;
- }
-
- /* Now we know how many symbols will be in the output file. Adjust
- the count in the section data. */
- symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym);
- if (unlikely (xndxdata != NULL))
- xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD, nsym);
-
- /* Create the symbol string table section. */
- strscn = elf_newscn (ld_state.outelf);
- ld_state.strscnidx = elf_ndxscn (strscn);
- data = elf_newdata (strscn);
- xelf_getshdr (strscn, shdr);
- if (data == NULL || shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* Create a compact string table, allocate the memory for it, and
- fill in the section data information. */
- ebl_strtabfinalize (strtab, data);
-
- shdr->sh_type = SHT_STRTAB;
- assert (shdr->sh_entsize == 0);
-
- if (unlikely (xelf_update_shdr (strscn, shdr) == 0))
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section for output file: %s"),
- elf_errmsg (-1));
-
- /* Fill in the offsets of the symbol names. */
- for (cnt = 1; cnt < nsym; ++cnt)
- if (symstrent[cnt] != NULL)
- {
- XElf_Sym_vardef (sym);
-
- /* Note that we don't have to use 'xelf_getsymshndx' since we don't
- modify the section index. */
- xelf_getsym (symdata, cnt, sym);
- /* This better worked, we did it before. */
- assert (sym != NULL);
- sym->st_name = ebl_strtaboffset (symstrent[cnt]);
- (void) xelf_update_sym (symdata, cnt, sym);
- }
-
- /* Since we are going to reorder the symbol table but still have to
- be able to find the new position based on the old one (since the
- latter is stored in 'symindirect' information of the input file
- data structure) we have to create yet another indirection
- table. */
- ld_state.dblindirect = dblindirect
- = (Elf32_Word *) xmalloc (nsym * sizeof (Elf32_Word));
-
- /* Sort the symbol table so that the local symbols come first. */
- /* XXX We don't use stable sorting here. It seems not necessary and
- would be more expensive. If it turns out to be necessary this can
- be fixed easily. */
- nsym_local = 1;
- cnt = nsym - 1;
- while (nsym_local < cnt)
- {
- XElf_Sym_vardef (locsym);
- Elf32_Word locxndx;
- XElf_Sym_vardef (globsym);
- Elf32_Word globxndx;
-
- do
- {
- xelf_getsymshndx (symdata, xndxdata, nsym_local, locsym, locxndx);
- /* This better works. */
- assert (locsym != NULL);
-
- if (XELF_ST_BIND (locsym->st_info) != STB_LOCAL
- && (ld_state.need_symtab || ld_state.export_all_dynamic))
- {
- do
- {
- xelf_getsymshndx (symdata, xndxdata, cnt, globsym, globxndx);
- /* This better works. */
- assert (globsym != NULL);
-
- if (unlikely (XELF_ST_BIND (globsym->st_info) == STB_LOCAL))
- {
- /* We swap the two entries. */
-#if NATIVE_ELF != 0
- /* Since we directly modify the data in the ELF
- data structure we have to make a copy of one
- of the entries. */
- XElf_Sym locsym_copy = *locsym;
- locsym = &locsym_copy;
-#endif
- xelf_update_symshndx (symdata, xndxdata, nsym_local,
- globsym, globxndx, 1);
- xelf_update_symshndx (symdata, xndxdata, cnt,
- locsym, locxndx, 1);
-
- /* Also swap the cross references. */
- dblindirect[nsym_local] = cnt;
- dblindirect[cnt] = nsym_local;
-
- /* And the entries for the symbol names. */
- struct Ebl_Strent *strtmp = symstrent[nsym_local];
- symstrent[nsym_local] = symstrent[cnt];
- symstrent[cnt] = strtmp;
-
- /* And the mapping from symbol table entry to
- struct symbol record. */
- struct symbol *symtmp = ndxtosym[nsym_local];
- ndxtosym[nsym_local] = ndxtosym[cnt];
- ndxtosym[cnt] = symtmp;
-
- /* Go to the next entry. */
- ++nsym_local;
- --cnt;
-
- break;
- }
-
- dblindirect[cnt] = cnt;
- }
- while (nsym_local < --cnt);
-
- break;
- }
-
- dblindirect[nsym_local] = nsym_local;
- }
- while (++nsym_local < cnt);
- }
-
- /* The symbol 'nsym_local' is currently pointing to might be local,
- too. Check and increment the variable if this is the case. */
- if (likely (nsym_local < nsym))
- {
- XElf_Sym_vardef (locsym);
-
- /* This entry isn't moved. */
- dblindirect[nsym_local] = nsym_local;
-
- /* Note that it is OK to not use 'xelf_getsymshndx' here. */
- xelf_getsym (symdata, nsym_local, locsym);
- /* This better works. */
- assert (locsym != NULL);
-
- if (XELF_ST_BIND (locsym->st_info) == STB_LOCAL)
- ++nsym_local;
- }
-
-
- /* We need the versym array right away to keep track of the version
- symbols. */
- if (ld_state.versymscnidx != 0)
- {
- /* We allocate more memory than we need since the array is morroring
- the dynamic symbol table and not the normal symbol table. I.e.,
- no local symbols are present. */
- versymscn = elf_getscn (ld_state.outelf, ld_state.versymscnidx);
- versymdata = elf_newdata (versymscn);
- if (versymdata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create versioning section: %s"),
- elf_errmsg (-1));
-
- versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
- nsym - nsym_local + 1);
- versymdata->d_buf = xcalloc (1, versymdata->d_size);
- versymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_HALF, 1);
- versymdata->d_off = 0;
- versymdata->d_type = ELF_T_HALF;
- }
-
-
- /* If we have to construct the dynamic symbol table we must not include
- the local symbols. If the normal symbol has to be emitted as well
- we haven't done anything else yet and we can construct it from
- scratch now. */
- if (unlikely (!ld_state.need_symtab))
- {
- /* Note that the following code works even if there is no entry
- to remove since the zeroth entry is always local. */
- size_t reduce = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_local - 1);
-
- XElf_Sym_vardef (nullsym);
- xelf_getsym_ptr (symdata, nsym_local - 1, nullsym);
-
- /* Note that we don't have to use 'xelf_update_symshndx' since
- this is the dynamic symbol table we write. */
- (void) xelf_update_sym (symdata, nsym_local - 1,
- memset (nullsym, '\0', sizeof (*nullsym)));
-
- /* Update the buffer pointer and size in the output data. */
- symdata->d_buf = (char *) symdata->d_buf + reduce;
- symdata->d_size -= reduce;
-
- /* Add the version symbol information. */
- if (versymdata != NULL)
- {
- nsym_dyn = 1;
- for (cnt = nsym_local; cnt < nsym; ++cnt, ++nsym_dyn)
- {
- struct symbol *symp = ndxtosym[cnt];
-
- if (symp->file->versymdata != NULL)
- {
- GElf_Versym versym;
-
- gelf_getversym (symp->file->versymdata, symp->symidx,
- &versym);
-
- (void) gelf_update_versym (versymdata, nsym_dyn,
- &symp->file->verdefused[versym]);
- }
- }
- }
-
- /* Since we only created the dynamic symbol table the number of
- dynamic symbols is the total number of symbols. */
- nsym_dyn = nsym - nsym_local + 1;
-
- /* XXX TBI. Create whatever data structure is missing. */
- abort ();
- }
- else if (ld_state.need_dynsym)
- {
- /* Create the dynamic symbol table section data along with the
- string table. We look at all non-local symbols we found for
- the normal symbol table and add those. */
- dynsymscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx);
- dynsymdata = elf_newdata (dynsymscn);
-
- dynstrdata = elf_newdata (elf_getscn (ld_state.outelf,
- ld_state.dynstrscnidx));
- if (dynsymdata == NULL || dynstrdata == NULL)
- error (EXIT_FAILURE, 0, gettext ("\
-cannot create dynamic symbol table for output file: %s"),
- elf_errmsg (-1));
-
- nsym_dyn_allocated = nsym - nsym_local + 1;
- dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
- nsym_dyn_allocated);
- dynsymdata->d_buf = memset (xmalloc (dynsymdata->d_size), '\0',
- xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
- dynsymdata->d_type = ELF_T_SYM;
- dynsymdata->d_off = 0;
- dynsymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
- /* We need one more array which contains the hash codes of the
- symbol names. */
- hashcodes = (Elf32_Word *) xcalloc (nsym_dyn_allocated,
- sizeof (Elf32_Word));
-
- /* We have and empty entry at the beginning. */
- nsym_dyn = 1;
-
- /* We don't mix PLT symbols and others. */
- size_t plt_idx = 1;
- size_t obj_idx = 1 + ld_state.nplt;
-
- /* Populate the table. */
- for (cnt = nsym_local; cnt < nsym; ++cnt)
- {
- XElf_Sym_vardef (sym);
-
- xelf_getsym (symdata, cnt, sym);
- assert (sym != NULL);
-
- if (sym->st_shndx == SHN_XINDEX)
- error (EXIT_FAILURE, 0, gettext ("\
-section index too large in dynamic symbol table"));
-
- /* We do not add the symbol to the dynamic symbol table if
-
- - the symbol is for a file
- - it is not externally visible (internal, hidden)
- - if export_all_dynamic is not set and is only defined in
- the executable (i.e., it is defined, but not (also) in
- in DSO)
-
- Set symstrent[cnt] to NULL in case an entry is ignored. */
- if (XELF_ST_TYPE (sym->st_info) == STT_FILE
- || XELF_ST_VISIBILITY (sym->st_other) == STV_INTERNAL
- || XELF_ST_VISIBILITY (sym->st_other) == STV_HIDDEN
- || (!ndxtosym[cnt]->in_dso && ndxtosym[cnt]->defined))
- {
- symstrent[cnt] = NULL;
- continue;
- }
-
- size_t idx;
- if (ndxtosym[cnt]->in_dso && ndxtosym[cnt]->type == STT_FUNC)
- {
- idx = plt_idx++;
- assert (idx < 1 + ld_state.nplt);
- }
- else
- {
- idx = obj_idx++;
- assert (idx < nsym_dyn_allocated);
- }
-
- /* Add the version information. */
- if (versymdata != NULL)
- {
- struct symbol *symp = ndxtosym[cnt];
-
- if (symp->file->verdefdata != NULL)
- {
- GElf_Versym versym;
-
- gelf_getversym (symp->file->versymdata, symp->symidx,
- &versym);
-
- (void) gelf_update_versym (versymdata, idx,
- &symp->file->verdefused[versym]);
- }
- else
- {
- /* XXX Add support for version definitions. */
- GElf_Versym global = VER_NDX_GLOBAL;
- (void) gelf_update_versym (versymdata, idx, &global);
- }
- }
-
- /* Store the index of the symbol in the dynamic symbol table. */
- ndxtosym[cnt]->outdynsymidx = idx;
-
- /* Create a new string table entry. */
- const char *str = ndxtosym[cnt]->name;
- symstrent[cnt] = ebl_strtabadd (dynstrtab, str, 0);
- hashcodes[idx] = elf_hash (str);
- ++nsym_dyn;
- }
- assert (nsym_dyn == obj_idx);
- assert (ld_state.nplt + 1 == plt_idx);
-
- /* Update the information about the symbol section. */
- if (versymdata != NULL)
- {
- /* Correct the size now that we know how many entries the
- dynamic symbol table has. */
- versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
- nsym_dyn);
-
- /* Add the reference to the symbol table. */
- xelf_getshdr (versymscn, shdr);
- assert (shdr != NULL);
-
- shdr->sh_link = ld_state.dynsymscnidx;
-
- (void) xelf_update_shdr (versymscn, shdr);
- }
- }
-
- if (ld_state.file_type != relocatable_file_type)
- {
- size_t nbucket;
- Elf32_Word *bucket;
- Elf32_Word *chain;
- size_t nchain;
- Elf_Scn *hashscn;
- Elf_Data *hashdata;
-
- /* Finalize the dynamic string table. */
- ebl_strtabfinalize (dynstrtab, dynstrdata);
-
- /* Determine the "optimal" bucket size. */
- nbucket = optimal_bucket_size (hashcodes, nsym_dyn, ld_state.optlevel);
-
- /* Create the .hash section data structures. */
- assert (ld_state.hashscnidx != 0);
- hashscn = elf_getscn (ld_state.outelf, ld_state.hashscnidx);
- xelf_getshdr (hashscn, shdr);
- hashdata = elf_newdata (hashscn);
- if (shdr == NULL || hashdata == NULL)
- error (EXIT_FAILURE, 0, gettext ("\
-cannot create hash table section for output file: %s"),
- elf_errmsg (-1));
-
- shdr->sh_link = ld_state.dynsymscnidx;
- (void) xelf_update_shdr (hashscn, shdr);
-
- hashdata->d_size = (2 + nsym_dyn + nbucket) * sizeof (Elf32_Word);
- hashdata->d_buf = xcalloc (1, hashdata->d_size);
- hashdata->d_align = sizeof (Elf32_Word);
- hashdata->d_type = ELF_T_WORD;
- hashdata->d_off = 0;
-
- ((Elf32_Word *) hashdata->d_buf)[0] = nbucket;
- ((Elf32_Word *) hashdata->d_buf)[1] = nsym_dyn;
- bucket = &((Elf32_Word *) hashdata->d_buf)[2];
- chain = &((Elf32_Word *) hashdata->d_buf)[2 + nbucket];
-
- /* Haven't yet filled in any chain value. */
- nchain = 0;
-
- /* Now put the names in. */
- for (cnt = nsym_local; cnt < nsym; ++cnt)
- if (symstrent[cnt] != NULL)
- {
- XElf_Sym_vardef (sym);
- size_t hashidx;
- size_t dynidx = ndxtosym[cnt]->outdynsymidx;
-
-#if NATIVE_ELF != 0
- XElf_Sym *osym;
- memcpy (xelf_getsym (dynsymdata, dynidx, sym),
- xelf_getsym (symdata, cnt, osym),
- sizeof (XElf_Sym));
-#else
- xelf_getsym (symdata, cnt, sym);
- assert (sym != NULL);
-#endif
-
- sym->st_name = ebl_strtaboffset (symstrent[cnt]);
-
- (void) xelf_update_sym (dynsymdata, dynidx, sym);
-
- /* Add to the hash table. */
- hashidx = hashcodes[dynidx] % nbucket;
- if (bucket[hashidx] == 0)
- bucket[hashidx] = dynidx;
- else
- {
- hashidx = bucket[hashidx];
- while (chain[hashidx] != 0)
- hashidx = chain[hashidx];
-
- chain[hashidx] = dynidx;
- }
- }
-
- free (hashcodes);
-
- /* We don't need the map from the symbol table index to the symbol
- structure anymore. */
- free (ndxtosym);
-
- /* Create the required version section. */
- if (ld_state.verneedscnidx != 0)
- {
- Elf_Scn *verneedscn;
- Elf_Data *verneeddata;
- struct usedfiles *runp;
- size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1);
- size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1);
- size_t offset;
- int ntotal;
-
- verneedscn = elf_getscn (ld_state.outelf, ld_state.verneedscnidx);
- xelf_getshdr (verneedscn, shdr);
- verneeddata = elf_newdata (verneedscn);
- if (shdr == NULL || verneeddata == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create versioning data: %s"),
- elf_errmsg (-1));
-
- verneeddata->d_size = (ld_state.nverdeffile * verneed_size
- + ld_state.nverdefused * vernaux_size);
- verneeddata->d_buf = xmalloc (verneeddata->d_size);
- verneeddata->d_type = ELF_T_VNEED;
- verneeddata->d_align = xelf_fsize (ld_state.outelf, ELF_T_WORD, 1);
- verneeddata->d_off = 0;
-
- offset = 0;
- ntotal = ld_state.nverdeffile;
- runp = ld_state.dsofiles->next;
- do
- {
- offset = create_verneed_data (offset, verneeddata, runp,
- &ntotal);
- runp = runp->next;
- }
- while (ntotal > 0 && runp != ld_state.dsofiles->next);
-
- if (ntotal > 0)
- {
- runp = ld_state.needed->next;
- do
- {
- offset = create_verneed_data (offset, verneeddata, runp,
- &ntotal);
- runp = runp->next;
- }
- while (ntotal > 0 && runp != ld_state.needed->next);
- }
-
- assert (offset == verneeddata->d_size);
-
- /* Add the needed information to the section header. */
- shdr->sh_link = ld_state.dynstrscnidx;
- shdr->sh_info = ld_state.nverdeffile;
- (void) xelf_update_shdr (verneedscn, shdr);
- }
-
- /* Adjust the section size. */
- dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_dyn);
- if (versymdata != NULL)
- versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
- nsym_dyn);
-
- /* Add the remaining information to the section header. */
- xelf_getshdr (dynsymscn, shdr);
- /* There is always exactly one local symbol. */
- shdr->sh_info = 1;
- /* Reference the string table. */
- shdr->sh_link = ld_state.dynstrscnidx;
- /* Write the updated info back. */
- (void) xelf_update_shdr (dynsymscn, shdr);
- }
- else
- /* We don't need the map from the symbol table index to the symbol
- structure anymore. */
- free (ndxtosym);
-
- /* We don't need the string table anymore. */
- free (symstrent);
-
- /* Remember the total number of symbols in the dynamic symbol table. */
- ld_state.ndynsym = nsym_dyn;
-
- /* Fill in the section header information. */
- symscn = elf_getscn (ld_state.outelf, ld_state.symscnidx);
- xelf_getshdr (symscn, shdr);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create symbol table for output file: %s"),
- elf_errmsg (-1));
-
- shdr->sh_type = SHT_SYMTAB;
- shdr->sh_link = ld_state.strscnidx;
- shdr->sh_info = nsym_local;
- shdr->sh_entsize = xelf_fsize (ld_state.outelf, ELF_T_SYM, 1);
-
- (void) xelf_update_shdr (symscn, shdr);
-
-
- /* Add names for the generated sections. */
- if (ld_state.symscnidx != 0)
- symtab_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab", 8);
- if (ld_state.xndxscnidx != 0)
- xndx_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab_shndx", 14);
- if (ld_state.strscnidx != 0)
- strtab_ent = ebl_strtabadd (ld_state.shstrtab, ".strtab", 8);
- /* At this point we would have to test for failures in the
- allocation. But we skip this. First, the problem will be caught
- latter when doing more allocations for the section header table.
- Even if this would not be the case all that would happen is that
- the section names are empty. The binary would still be usable if
- it is an executable or a DSO. Not adding the test here saves
- quite a bit of code. */
-
-
- /* Finally create the section for the section header string table. */
- shstrtab_scn = elf_newscn (ld_state.outelf);
- shstrtab_ndx = elf_ndxscn (shstrtab_scn);
- if (unlikely (shstrtab_ndx == SHN_UNDEF))
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section header string section: %s"),
- elf_errmsg (-1));
-
- /* Add the name of the section to the string table. */
- shstrtab_ent = ebl_strtabadd (ld_state.shstrtab, ".shstrtab", 10);
- if (unlikely (shstrtab_ent == NULL))
- error (EXIT_FAILURE, errno,
- gettext ("cannot create section header string section"));
-
- /* Finalize the section header string table. */
- data = elf_newdata (shstrtab_scn);
- if (data == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section header string section: %s"),
- elf_errmsg (-1));
- ebl_strtabfinalize (ld_state.shstrtab, data);
-
- /* Now we know the string offsets for all section names. */
- for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
- if (ld_state.allsections[cnt]->scnidx != 0)
- {
- Elf_Scn *scn;
-
- scn = elf_getscn (ld_state.outelf, ld_state.allsections[cnt]->scnidx);
-
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- shdr->sh_name = ebl_strtaboffset (ld_state.allsections[cnt]->nameent);
-
- if (xelf_update_shdr (scn, shdr) == 0)
- assert (0);
- }
-
- /* Add the names for the generated sections to the respective
- section headers. */
- if (symtab_ent != NULL)
- {
- Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.symscnidx);
-
- xelf_getshdr (scn, shdr);
- /* This cannot fail, we already accessed the header before. */
- assert (shdr != NULL);
-
- shdr->sh_name = ebl_strtaboffset (symtab_ent);
-
- (void) xelf_update_shdr (scn, shdr);
- }
- if (xndx_ent != NULL)
- {
- Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.xndxscnidx);
-
- xelf_getshdr (scn, shdr);
- /* This cannot fail, we already accessed the header before. */
- assert (shdr != NULL);
-
- shdr->sh_name = ebl_strtaboffset (xndx_ent);
-
- (void) xelf_update_shdr (scn, shdr);
- }
- if (strtab_ent != NULL)
- {
- Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.strscnidx);
-
- xelf_getshdr (scn, shdr);
- /* This cannot fail, we already accessed the header before. */
- assert (shdr != NULL);
-
- shdr->sh_name = ebl_strtaboffset (strtab_ent);
-
- (void) xelf_update_shdr (scn, shdr);
- }
-
- /* And the section header table section itself. */
- xelf_getshdr (shstrtab_scn, shdr);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section header string section: %s"),
- elf_errmsg (-1));
-
- shdr->sh_name = ebl_strtaboffset (shstrtab_ent);
- shdr->sh_type = SHT_STRTAB;
-
- if (unlikely (xelf_update_shdr (shstrtab_scn, shdr) == 0))
- error (EXIT_FAILURE, 0,
- gettext ("cannot create section header string section: %s"),
- elf_errmsg (-1));
-
-
- /* Add the correct section header info to the section group sections. */
- groups = ld_state.groups;
- while (groups != NULL)
- {
- Elf_Scn *scn;
- struct scngroup *oldp;
- Elf32_Word si;
-
- scn = elf_getscn (ld_state.outelf, groups->outscnidx);
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- shdr->sh_name = ebl_strtaboffset (groups->nameent);
- shdr->sh_type = SHT_GROUP;
- shdr->sh_flags = 0;
- shdr->sh_link = ld_state.symscnidx;
- shdr->sh_entsize = sizeof (Elf32_Word);
-
- /* Determine the index for the signature symbol. */
- si = groups->symbol->file->symindirect[groups->symbol->symidx];
- if (si == 0)
- {
- assert (groups->symbol->file->symref[groups->symbol->symidx]
- != NULL);
- si = groups->symbol->file->symref[groups->symbol->symidx]->outsymidx;
- assert (si != 0);
- }
- shdr->sh_info = ld_state.dblindirect[si];
-
- (void) xelf_update_shdr (scn, shdr);
-
- oldp = groups;
- groups = groups->next;
- free (oldp);
- }
-
-
- if (ld_state.file_type != relocatable_file_type)
- {
- size_t nphdr;
- XElf_Addr addr;
- struct output_segment *segment;
- Elf_Scn *scn;
- Elf32_Word nsec;
- XElf_Phdr_vardef (phdr);
-
- /* Every executable needs a program header. The number of entries
- varies. One exists for each segment. Each SHT_NOTE section gets
- one, too. For dynamically linked executables we have to create
- one for the program header, the interpreter, and the dynamic
- section. First count the number of segments.
-
- XXX Determine whether the segment is non-empty. */
- nphdr = 0;
- segment = ld_state.output_segments;
- while (segment != NULL)
- {
- ++nphdr;
- segment = segment->next;
- }
-
- /* Add the number of SHT_NOTE sections. We counted them earlier. */
- nphdr += ld_state.nnotesections;
-
- /* If we create a DSO or the file is linked against DSOs we have three
- more entries: INTERP, PHDR, DYNAMIC. */
- if (dynamically_linked_p ())
- nphdr += 3;
-
- /* Create the program header structure. */
- if (xelf_newphdr (ld_state.outelf, nphdr) == 0)
- error (EXIT_FAILURE, 0, gettext ("cannot create program header: %s"),
- elf_errmsg (-1));
-
-
- /* Determine the section sizes and offsets. We have to do this
- to be able to determine the memory layout (which normally
- differs from the file layout). */
- if (elf_update (ld_state.outelf, ELF_C_NULL) == -1)
- error (EXIT_FAILURE, 0, gettext ("while determining file layout: %s"),
- elf_errmsg (-1));
-
-
- /* Now determine the memory addresses of all the sections and
- segments. */
- nsec = 0;
- scn = elf_getscn (ld_state.outelf, ld_state.allsections[nsec]->scnidx);
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- /* The address we start with is the offset of the first (not
- zeroth) section. */
- addr = shdr->sh_offset;
-
- /* The index of the first loadable segment. */
- nphdr = 1 + (dynamically_linked_p () == true) * 2;
-
- segment = ld_state.output_segments;
- while (segment != NULL)
- {
- struct output_rule *orule;
- bool first_section = true;
- XElf_Off nobits_size = 0;
- XElf_Off memsize = 0;
-
- /* the minimum alignment is a page size. */
- segment->align = ld_state.pagesize;
-
- for (orule = segment->output_rules; orule != NULL;
- orule = orule->next)
- if (orule->tag == output_section)
- {
- XElf_Off oldoff;
-
- /* See whether this output rule corresponds to the next
- section. Yes, this is a pointer comparison. */
- if (ld_state.allsections[nsec]->name
- != orule->val.section.name)
- /* No, ignore this output rule. */
- continue;
-
- /* We assign addresses only in segments which are actually
- loaded. */
- if (segment->mode != 0)
- {
- /* Adjust the offset of the input sections. */
- struct scninfo *isect;
- struct scninfo *first;
-
- isect = first = ld_state.allsections[nsec]->last;
- if (isect != NULL)
- do
- isect->offset += addr;
- while ((isect = isect->next) != first);
-
- /* Set the address of current section. */
- shdr->sh_addr = addr;
-
- /* Write the result back. */
- (void) xelf_update_shdr (scn, shdr);
-
- /* Remember the address. */
- ld_state.allsections[nsec]->addr = addr;
- }
-
- if (first_section)
- {
- /* The first segment starts at offset zero. */
- if (segment == ld_state.output_segments)
- {
- segment->offset = 0;
- segment->addr = addr - shdr->sh_offset;
- }
- else
- {
- segment->offset = shdr->sh_offset;
- segment->addr = addr;
- }
-
- /* Determine the maximum alignment requirement. */
- segment->align = MAX (segment->align, shdr->sh_addralign);
-
- first_section = false;
- }
-
- memsize = shdr->sh_offset - segment->offset + shdr->sh_size;
- if (nobits_size != 0 && shdr->sh_type != SHT_NOTE)
- error (EXIT_FAILURE, 0, gettext ("\
-internal error: nobits section follows nobits section"));
- if (shdr->sh_type == SHT_NOBITS)
- nobits_size += shdr->sh_size;
-
- /* Determine the new address which is computed using
- the difference of the offsets on the sections. Note
- that this assumes that the sections following each
- other in the section header table are also
- consecutive in the file. This is true here because
- libelf constructs files this way. */
- oldoff = shdr->sh_offset;
-
- if (++nsec >= ld_state.nallsections)
- break;
-
- scn = elf_getscn (ld_state.outelf,
- ld_state.allsections[nsec]->scnidx);
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- /* This is the new address resulting from the offsets
- in the file. */
- assert (oldoff <= shdr->sh_offset);
- addr += shdr->sh_offset - oldoff;
- }
- else
- {
- assert (orule->tag == output_assignment);
-
- if (strcmp (orule->val.assignment->variable, ".") == 0)
- /* This is a change of the address. */
- addr = eval_expression (orule->val.assignment->expression,
- addr);
- else if (orule->val.assignment->sym != NULL)
- {
- /* This symbol is used. Update the symbol table
- entry. */
- XElf_Sym_vardef (sym);
- size_t idx;
-
- /* Note that we do not have to use
- xelf_getsymshndx since we only update the
- symbol address, not the section
- information. */
- idx = dblindirect[orule->val.assignment->sym->outsymidx];
- xelf_getsym (symdata, idx, sym);
- sym->st_value = addr;
- (void) xelf_update_sym (symdata, idx, sym);
-
- idx = orule->val.assignment->sym->outdynsymidx;
- if (idx != 0)
- {
- assert (dynsymdata != NULL);
- xelf_getsym (dynsymdata, idx, sym);
- sym->st_value = addr;
- (void) xelf_update_sym (dynsymdata, idx, sym);
- }
- }
- }
-
- /* Store the segment parameter for loadable segments. */
- if (segment->mode != 0)
- {
- xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr);
-
- phdr->p_type = PT_LOAD;
- phdr->p_offset = segment->offset;
- phdr->p_vaddr = segment->addr;
- phdr->p_paddr = phdr->p_vaddr;
- phdr->p_filesz = memsize - nobits_size;
- phdr->p_memsz = memsize;
- phdr->p_flags = segment->mode;
- phdr->p_align = segment->align;
-
- (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr);
- ++nphdr;
- }
-
- segment = segment->next;
- }
-
- /* Create the other program header entries. */
- xelf_getehdr (ld_state.outelf, ehdr);
- assert (ehdr != NULL);
-
- xelf_getphdr_ptr (ld_state.outelf, 1, phdr);
- phdr->p_type = PT_PHDR;
- phdr->p_offset = ehdr->e_phoff;
- phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset;
- phdr->p_paddr = phdr->p_vaddr;
- phdr->p_filesz = ehdr->e_phnum * ehdr->e_phentsize;
- phdr->p_memsz = phdr->p_filesz;
- phdr->p_flags = 0; /* No need to set PF_R or so. */
- phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
- (void) xelf_update_phdr (ld_state.outelf, 0, phdr);
-
-
- /* Adjust the addresses in the addresses of the symbol according
- to the load addresses of the sections. */
- if (ld_state.need_symtab)
- for (cnt = 1; cnt < nsym; ++cnt)
- {
- XElf_Sym_vardef (sym);
- Elf32_Word shndx;
-
- xelf_getsymshndx (symdata, xndxdata, cnt, sym, shndx);
- assert (sym != NULL);
-
- if (sym->st_shndx != SHN_XINDEX)
- shndx = sym->st_shndx;
-
- if ((shndx > SHN_UNDEF && shndx < SHN_LORESERVE)
- || shndx > SHN_HIRESERVE)
- {
- /* Note we subtract 1 from the section index since ALLSECTIONS
- does not store the dummy section with offset zero. */
- sym->st_value += ld_state.allsections[shndx - 1]->addr;
-
- /* We don't have to use 'xelf_update_symshndx' since the
- section number doesn't change. */
- (void) xelf_update_sym (symdata, cnt, sym);
- }
- }
-
- if (ld_state.need_dynsym)
- for (cnt = 1; cnt < nsym_dyn; ++cnt)
- {
- XElf_Sym_vardef (sym);
-
- xelf_getsym (dynsymdata, cnt, sym);
- assert (sym != NULL);
-
- if (sym->st_shndx > SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
- {
- /* Note we subtract 1 from the section index since ALLSECTIONS
- does not store the dummy section with offset zero. */
- sym->st_value += ld_state.allsections[sym->st_shndx - 1]->addr;
-
- /* We don't have to use 'xelf_update_symshndx' since the
- section number doesn't change. */
- (void) xelf_update_sym (dynsymdata, cnt, sym);
- }
- }
-
-
- /* Now is a good time to determine the values of all the symbols
- we encountered. */
- // XXX This loop is very inefficient. The hash tab iterator also
- // returns all symbols in DSOs.
- struct symbol *se;
- void *p = NULL;
- while ((se = ld_symbol_tab_iterate (&ld_state.symbol_tab, &p)) != NULL)
- if (! se->in_dso)
- {
- XElf_Sym_vardef (sym);
-
- addr = 0;
-
- if (se->outdynsymidx != 0)
- {
- xelf_getsym (dynsymdata, se->outdynsymidx, sym);
- assert (sym != NULL);
- addr = sym->st_value;
- }
- else if (se->outsymidx != 0)
- {
- assert (dblindirect[se->outsymidx] != 0);
- xelf_getsym (symdata, dblindirect[se->outsymidx], sym);
- assert (sym != NULL);
- addr = sym->st_value;
- }
- else
- abort ();
-
- se->merge.value = addr;
- }
-
- /* Complete the header of the .rel.dyn/.rela.dyn section. Point
- to the symbol table. The sh_info field is left zero since
- there is no specific section the contained relocations are
- for. */
- if (ld_state.reldynscnidx != 0)
- {
- assert (ld_state.dynsymscnidx != 0);
- scn = elf_getscn (ld_state.outelf, ld_state.reldynscnidx);
- xelf_getshdr (scn, shdr);
- assert (shdr != NULL);
-
- shdr->sh_link = ld_state.dynsymscnidx;
-
- (void) xelf_update_shdr (scn, shdr);
- }
-
- /* Fill in the dynamic segment/section. */
- if (dynamically_linked_p ())
- {
- Elf_Scn *outscn;
-
- assert (ld_state.interpscnidx != 0);
- xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.interpscnidx),
- shdr);
- assert (shdr != NULL);
-
- /* The interpreter string. */
- // XXX Do we need to support files (DSOs) without interpreters?
- xelf_getphdr_ptr (ld_state.outelf, 1, phdr);
- phdr->p_type = PT_INTERP;
- phdr->p_offset = shdr->sh_offset;
- phdr->p_vaddr = shdr->sh_addr;
- phdr->p_paddr = phdr->p_vaddr;
- phdr->p_filesz = shdr->sh_size;
- phdr->p_memsz = phdr->p_filesz;
- phdr->p_flags = 0; /* No need to set PF_R or so. */
- phdr->p_align = 1; /* It's a string. */
-
- (void) xelf_update_phdr (ld_state.outelf, 1, phdr);
-
- /* The pointer to the dynamic section. We this we need to
- get the information for the dynamic section first. */
- assert (ld_state.dynamicscnidx);
- outscn = elf_getscn (ld_state.outelf, ld_state.dynamicscnidx);
- xelf_getshdr (outscn, shdr);
- assert (shdr != NULL);
-
- xelf_getphdr_ptr (ld_state.outelf, 2, phdr);
- phdr->p_type = PT_DYNAMIC;
- phdr->p_offset = shdr->sh_offset;
- phdr->p_vaddr = shdr->sh_addr;
- phdr->p_paddr = phdr->p_vaddr;
- phdr->p_filesz = shdr->sh_size;
- phdr->p_memsz = phdr->p_filesz;
- phdr->p_flags = 0; /* No need to set PF_R or so. */
- phdr->p_align = shdr->sh_addralign;
-
- (void) xelf_update_phdr (ld_state.outelf, 2, phdr);
-
- /* Fill in the reference to the .dynstr section. */
- assert (ld_state.dynstrscnidx != 0);
- shdr->sh_link = ld_state.dynstrscnidx;
- (void) xelf_update_shdr (outscn, shdr);
-
- /* And fill the remaining entries. */
- Elf_Data *dyndata = elf_getdata (outscn, NULL);
- assert (dyndata != NULL);
-
- /* Add the DT_NEEDED entries. */
- if (ld_state.ndsofiles > 0)
- {
- struct usedfiles *runp = ld_state.dsofiles->next;
-
- do
- if (! ld_state.ignore_unused_dsos || runp->used)
- {
- /* Add the position-dependent flag if necessary. */
- if (runp->lazyload)
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_POSFLAG_1, DF_P1_LAZYLOAD);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_NEEDED,
- ebl_strtaboffset (runp->sonameent));
- }
- while ((runp = runp->next) != ld_state.dsofiles->next);
- }
-
- /* We can finish the DT_RUNPATH/DT_RPATH entries now. */
- if (ld_state.rxxpath_strent != NULL)
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- ld_state.rxxpath_tag,
- ebl_strtaboffset (ld_state.rxxpath_strent));
-
- /* Reference to initialization and finalization functions. */
- // XXX This code depends on symbol table being relocated.
- if (ld_state.init_symbol != NULL)
- {
- XElf_Sym_vardef (sym);
-
- if (ld_state.need_symtab)
- xelf_getsym (symdata,
- dblindirect[ld_state.init_symbol->outsymidx],
- sym);
- else
- xelf_getsym (dynsymdata, ld_state.init_symbol->outdynsymidx,
- sym);
- assert (sym != NULL);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_INIT, sym->st_value);
- }
- if (ld_state.fini_symbol != NULL)
- {
- XElf_Sym_vardef (sym);
-
- if (ld_state.need_symtab)
- xelf_getsym (symdata,
- dblindirect[ld_state.fini_symbol->outsymidx],
- sym);
- else
- xelf_getsym (dynsymdata, ld_state.fini_symbol->outdynsymidx,
- sym);
- assert (sym != NULL);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_FINI, sym->st_value);
- }
- // XXX Support init,fini,preinit arrays
-
- /* The hash table which comes with dynamic symbol table. */
- xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.hashscnidx),
- shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_HASH,
- shdr->sh_addr);
-
- /* Reference to the symbol table section. */
- assert (ld_state.dynsymscnidx != 0);
- xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynsymscnidx),
- shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMTAB,
- shdr->sh_addr);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMENT,
- xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
-
- /* And the string table which comes with it. */
- xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynstrscnidx),
- shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRTAB,
- shdr->sh_addr);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRSZ,
- shdr->sh_size);
-
- /* Add the entries related to the .plt. */
- if (ld_state.nplt > 0)
- {
- xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.gotscnidx),
- shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- // XXX This should probably be machine
- // dependent.
- DT_PLTGOT, shdr->sh_addr);
-
- xelf_getshdr (elf_getscn (ld_state.outelf,
- ld_state.pltrelscnidx), shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_PLTRELSZ, shdr->sh_size);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_JMPREL, shdr->sh_addr);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_PLTREL, REL_TYPE (statep));
- }
-
- if (ld_state.relsize_total > 0)
- {
- int rel = REL_TYPE (statep);
- xelf_getshdr (elf_getscn (ld_state.outelf,
- ld_state.reldynscnidx), shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- rel, shdr->sh_addr);
-
- /* Trick ahead. Use arithmetic to get the right tag.
- We check the validity of this assumption in the asserts. */
- assert (DT_RELASZ - DT_RELA == 1);
- assert (DT_RELSZ - DT_REL == 1);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- rel + 1, shdr->sh_size);
-
- /* Similar for the entry size tag. */
- assert (DT_RELAENT - DT_RELA == 2);
- assert (DT_RELENT - DT_REL == 2);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- rel + 2,
- rel == DT_REL
- ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
- : xelf_fsize (ld_state.outelf, ELF_T_RELA,
- 1));
- }
-
- if (ld_state.verneedscnidx != 0)
- {
- xelf_getshdr (elf_getscn (ld_state.outelf,
- ld_state.verneedscnidx), shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_VERNEED, shdr->sh_addr);
-
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_VERNEEDNUM, ld_state.nverdeffile);
- }
-
- if (ld_state.versymscnidx != 0)
- {
- xelf_getshdr (elf_getscn (ld_state.outelf,
- ld_state.versymscnidx), shdr);
- assert (shdr != NULL);
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_VERSYM, shdr->sh_addr);
- }
-
- /* We always create the DT_DEBUG entry. */
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_DEBUG, 0);
- assert (ld_state.ndynamic_filled < ld_state.ndynamic);
-
- /* Add the flag words if necessary. */
- if (ld_state.dt_flags != 0)
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FLAGS,
- ld_state.dt_flags);
-
- /* Create entry for the DT_FLAGS_1 flag. */
- if (ld_state.dt_flags_1 != 0)
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_FLAGS_1, ld_state.dt_flags_1);
-
- /* Create entry for the DT_FEATURE_1 flag. */
- if (ld_state.dt_feature_1 != 0)
- new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
- DT_FEATURE_1, ld_state.dt_feature_1);
-
- assert (ld_state.ndynamic_filled <= ld_state.ndynamic);
- }
- }
-
-
- // XXX The following code isn't nice. We use two different
- // mechanisms to handle relocations, one for relocatable files, one
- // for executables and DSOs. Maybe this is the best method but also
- // maybe it can be somewhat unified.
-
- /* Now that we created the symbol table we can add the reference to
- it in the sh_link field of the section headers of the relocation
- sections. */
- while (rellist != NULL)
- {
- assert (ld_state.file_type == relocatable_file_type);
- Elf_Scn *outscn;
-
- outscn = elf_getscn (ld_state.outelf, rellist->scnidx);
- xelf_getshdr (outscn, shdr);
- /* This must not fail since we did it before. */
- assert (shdr != NULL);
-
- /* Remember the symbol table which belongs to the relocation section. */
- shdr->sh_link = ld_state.symscnidx;
-
- /* And the reference to the section which is relocated by this
- relocation section. We use the info from the first input
- section but all records should have the same information. */
- shdr->sh_info =
- rellist->scninfo->fileinfo->scninfo[SCNINFO_SHDR (rellist->scninfo->shdr).sh_info].outscnndx;
-
-
- /* Perform the actual relocations. We only have to adjust
- offsets and symbol indices. */
- RELOCATE_SECTION (statep, outscn, rellist->scninfo, dblindirect);
-
- /* Store the changes. */
- (void) xelf_update_shdr (outscn, shdr);
-
- /* Up to the next relocation section. */
- rellist = rellist->next;
- }
-
- if (ld_state.rellist != NULL)
- {
- assert (ld_state.file_type != relocatable_file_type);
- /* Create the relocations for the output file. */
- CREATE_RELOCATIONS (statep, dblindirect);
- }
-
-
- /* We need the ELF header once more. */
- xelf_getehdr (ld_state.outelf, ehdr);
- assert (ehdr != NULL);
-
- /* Set the section header string table index. */
- if (likely (shstrtab_ndx < SHN_HIRESERVE)
- && likely (shstrtab_ndx != SHN_XINDEX))
- ehdr->e_shstrndx = shstrtab_ndx;
- else
- {
- /* We have to put the section index in the sh_link field of the
- zeroth section header. */
- Elf_Scn *scn = elf_getscn (ld_state.outelf, 0);
-
- xelf_getshdr (scn, shdr);
- if (unlikely (shdr == NULL))
- error (EXIT_FAILURE, 0,
- gettext ("cannot get header of 0th section: %s"),
- elf_errmsg (-1));
-
- shdr->sh_link = shstrtab_ndx;
-
- (void) xelf_update_shdr (scn, shdr);
-
- ehdr->e_shstrndx = SHN_XINDEX;
- }
-
- if (ld_state.file_type != relocatable_file_type)
- /* DSOs and executables have to define the entry point symbol. */
- ehdr->e_entry = find_entry_point ();
-
- if (unlikely (xelf_update_ehdr (ld_state.outelf, ehdr) == 0))
- error (EXIT_FAILURE, 0,
- gettext ("cannot update ELF header: %s"),
- elf_errmsg (-1));
-
-
- /* Free the data which we don't need anymore. */
- free (ld_state.dblindirect);
-
-
- /* Finalize the .plt section the what belongs to them. */
- FINALIZE_PLT (statep, nsym, nsym_dyn);
-
- return 0;
-}
-
-
-/* This is a function which must be specified in all backends. */
-static void
-ld_generic_relocate_section (struct ld_state *statep, Elf_Scn *outscn,
- struct scninfo *firstp,
- const Elf32_Word *dblindirect)
-{
- error (EXIT_FAILURE, 0, gettext ("\
-linker backend didn't specify function to relocate section"));
- /* NOTREACHED */
-}
-
-
-/* Finalize the output file. */
-static int
-ld_generic_finalize (struct ld_state *statep)
-{
- /* Write out the ELF file data. */
- if (elf_update (ld_state.outelf, ELF_C_WRITE) == -1)
- error (EXIT_FAILURE, 0, gettext ("while writing output file: %s"),
- elf_errmsg (-1));
-
- /* Free the resources. */
- if (elf_end (ld_state.outelf) != 0)
- error (EXIT_FAILURE, 0, gettext ("while finishing output file: %s"),
- elf_errmsg (-1));
-
- /* Get the file status of the temporary file. */
- struct stat temp_st;
- if (fstat (ld_state.outfd, &temp_st) != 0)
- error (EXIT_FAILURE, errno, gettext ("cannot stat output file"));
-
- /* Now it's time to rename the file. Remove an old existing file
- first. */
- if (rename (ld_state.tempfname, ld_state.outfname) != 0)
- /* Something went wrong. */
- error (EXIT_FAILURE, errno, gettext ("cannot rename output file"));
-
- /* Make sure the output file is really the one we created. */
- struct stat new_st;
- if (stat (ld_state.outfname, &new_st) != 0
- || new_st.st_ino != temp_st.st_ino
- || new_st.st_dev != temp_st.st_dev)
- {
- /* Wow, somebody overwrote the output file, probably some intruder. */
- unlink (ld_state.outfname);
- error (EXIT_FAILURE, 0, gettext ("\
-WARNING: temporary output file overwritten before linking finished"));
- }
-
- /* Close the file descriptor. */
- (void) close (ld_state.outfd);
-
- /* Signal the cleanup handler that the file is correctly created. */
- ld_state.tempfname = NULL;
-
- return 0;
-}
-
-
-static bool
-ld_generic_special_section_number_p (struct ld_state *statep, size_t number)
-{
- /* There are no special section numbers in the gABI. */
- return false;
-}
-
-
-static bool
-ld_generic_section_type_p (struct ld_state *statep, GElf_Word type)
-{
- if ((type >= SHT_NULL && type < SHT_NUM)
- /* XXX Enable the following two when implemented. */
- // || type == SHT_GNU_LIBLIST
- // || type == SHT_CHECKSUM
- /* XXX Eventually include SHT_SUNW_move, SHT_SUNW_COMDAT, and
- SHT_SUNW_syminfo. */
- || (type >= SHT_GNU_verdef && type <= SHT_GNU_versym))
- return true;
-
- return false;
-}
-
-
-static XElf_Xword
-ld_generic_dynamic_section_flags (struct ld_state *statep)
-{
- /* By default the .dynamic section is writable (and is of course
- loaded). Few architecture differ from this. */
- return SHF_ALLOC | SHF_WRITE;
-}
-
-
-static void
-ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "initialize_plt");
-}
-
-
-static void
-ld_generic_initialize_pltrel (struct ld_state *statep, Elf_Scn *scn)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "initialize_pltrel");
-}
-
-
-static void
-ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "initialize_got");
-}
-
-
-static void
-ld_generic_finalize_plt (struct ld_state *statep, size_t nsym, size_t nsym_dyn)
-{
- /* By default we assume that nothing has to be done. */
-}
-
-
-static int
-ld_generic_rel_type (struct ld_state *statep)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "rel_type");
- /* Just to keep the compiler calm. */
- return 0;
-}
-
-
-static void
-ld_generic_count_relocations (struct ld_state *statep, struct scninfo *scninfo)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "count_relocations");
-}
-
-
-static void
-ld_generic_create_relocations (struct ld_state *statep,
- const Elf32_Word *dblindirect)
-{
- /* This cannot be implemented generally. There should have been a
- machine dependent implementation and we should never have arrived
- here. */
- error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
- "create_relocations");
-}
diff --git a/src/ldlex.c b/src/ldlex.c
deleted file mode 100644
index e0bf0a5f..00000000
--- a/src/ldlex.c
+++ /dev/null
@@ -1,2663 +0,0 @@
-#define yy_create_buffer ld_create_buffer
-#define yy_delete_buffer ld_delete_buffer
-#define yy_scan_buffer ld_scan_buffer
-#define yy_scan_string ld_scan_string
-#define yy_scan_bytes ld_scan_bytes
-#define yy_flex_debug ld_flex_debug
-#define yy_init_buffer ld_init_buffer
-#define yy_flush_buffer ld_flush_buffer
-#define yy_load_buffer_state ld_load_buffer_state
-#define yy_switch_to_buffer ld_switch_to_buffer
-#define yyin ldin
-#define yyleng ldleng
-#define yylex ldlex
-#define yyout ldout
-#define yyrestart ldrestart
-#define yytext ldtext
-#define yylineno ldlineno
-
-#line 20 "ldlex.c"
-/* A lexical scanner generated by flex */
-
-/* Scanner skeleton version:
- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
- */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-
-#include <stdio.h>
-#include <unistd.h>
-
-
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
-#endif
-#endif
-
-
-#ifdef __cplusplus
-
-#include <stdlib.h>
-
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_PROTOS
-#define YY_USE_CONST
-
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
-
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#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. */
-#define YY_BUF_SIZE 16384
-
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-
-extern int yyleng;
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator). This
- * avoids problems with code like:
- *
- * if ( condition_holds )
- * yyless( 5 );
- * else
- * do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- *yy_cp = yy_hold_char; \
- YY_RESTORE_YY_MORE_OFFSET \
- yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
- YY_DO_BEFORE_ACTION; /* set up yytext again */ \
- } \
- while ( 0 )
-
-#define unput(c) yyunput( c, yytext_ptr )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-typedef unsigned int yy_size_t;
-
-
-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.
- */
- int 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;
-
- /* 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
- };
-
-static YY_BUFFER_STATE yy_current_buffer = 0;
-
-/* 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".
- */
-#define YY_CURRENT_BUFFER yy_current_buffer
-
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-
-static int yy_n_chars; /* number of characters read into yy_ch_buf */
-
-
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1; /* 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 YY_PROTO(( FILE *input_file ));
-
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
-
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
-
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
-static void yy_flex_free YY_PROTO(( void * ));
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_is_interactive = is_interactive; \
- }
-
-#define yy_set_bol(at_bol) \
- { \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_at_bol = at_bol; \
- }
-
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
-
-
-#define YY_USES_REJECT
-
-#define yywrap() 1
-#define YY_SKIP_YYWRAP
-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 YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( 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 = (int) (yy_cp - yy_bp); \
- yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 49
-#define YY_END_OF_BUFFER 50
-static yyconst short int yy_acclist[373] =
- { 0,
- 50, 48, 49, 47, 48, 49, 47, 49, 40, 48,
- 49, 41, 48, 49, 31, 48, 49, 32, 48, 49,
- 38, 45, 48, 49, 36, 48, 49, 43, 48, 49,
- 37, 48, 49, 45, 48, 49, 39, 48, 49, 44,
- 45, 48, 49, 44, 45, 48, 49, 33, 48, 49,
- 34, 48, 49, 35, 48, 49, 45, 48, 49, 45,
- 48, 49, 45, 48, 49, 45, 48, 49, 45, 48,
- 49, 45, 48, 49, 45, 48, 49, 45, 48, 49,
- 45, 48, 49, 45, 48, 49, 48, 49, 48, 49,
- 45, 48, 49, 45, 48, 49, 29, 48, 49, 42,
-
- 48, 49, 30, 48, 49, 48, 49, 9, 49, 9,
- 49, 47, 45, 46, 45, 46, 10, 46, 44, 45,
- 46, 44, 45, 46, 44, 45, 46, 45, 46, 44,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 28, 45,
- 46, 45, 46, 44, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
-
- 44, 45, 46, 45, 46, 45, 46, 45, 46, 45,
- 46, 45, 46, 45, 46, 18, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 26, 45, 46, 45, 46, 45, 46, 45, 46, 11,
- 45, 46, 12, 45, 46, 45, 46, 15, 45, 46,
- 16, 45, 46, 45, 46, 45, 46, 45, 46, 45,
- 46, 45, 46, 45, 46, 45, 46, 45, 46, 45,
- 46, 45, 46, 45, 46, 17, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 45, 46, 45, 46, 19, 2, 6, 45, 46, 45,
-
- 46, 45, 46, 22, 45, 46, 45, 46, 24, 45,
- 46, 45, 46, 27, 45, 46, 14, 4, 1, 8,
- 5, 45, 46, 45, 46, 21, 45, 46, 45, 46,
- 45, 46, 45, 46, 45, 46, 45, 46, 45, 46,
- 3, 7, 45, 46, 45, 46, 23, 45, 46, 45,
- 46, 45, 46, 45, 46, 45, 46, 13, 45, 46,
- 45, 46, 45, 46, 20, 45, 46, 45, 46, 25,
- 45, 46
- } ;
-
-static yyconst short int yy_accept[212] =
- { 0,
- 1, 1, 1, 1, 1, 2, 4, 7, 9, 12,
- 15, 18, 21, 25, 28, 31, 34, 37, 40, 44,
- 48, 51, 54, 57, 60, 63, 66, 69, 72, 75,
- 78, 81, 84, 87, 89, 91, 94, 97, 100, 103,
- 106, 108, 110, 112, 113, 114, 115, 117, 119, 122,
- 125, 128, 130, 133, 135, 137, 139, 141, 143, 145,
- 147, 149, 151, 153, 155, 157, 159, 159, 160, 162,
- 164, 164, 164, 164, 164, 167, 169, 171, 173, 175,
- 177, 179, 181, 183, 185, 187, 189, 191, 193, 195,
- 197, 197, 199, 201, 201, 201, 201, 201, 201, 201,
-
- 204, 206, 208, 210, 212, 214, 216, 219, 221, 223,
- 225, 227, 229, 231, 234, 236, 236, 238, 240, 240,
- 240, 240, 240, 240, 240, 240, 240, 243, 246, 248,
- 251, 254, 256, 258, 260, 262, 264, 266, 268, 270,
- 272, 274, 274, 274, 274, 274, 274, 274, 274, 274,
- 276, 279, 281, 283, 285, 287, 289, 291, 293, 295,
- 296, 296, 297, 297, 297, 297, 298, 298, 298, 300,
- 302, 304, 307, 309, 312, 314, 317, 318, 318, 319,
- 320, 320, 321, 322, 324, 326, 329, 331, 333, 333,
- 333, 335, 337, 339, 341, 342, 343, 345, 347, 350,
-
- 352, 354, 356, 358, 361, 363, 365, 368, 370, 373,
- 373
- } ;
-
-static yyconst int yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 1, 4, 1, 5, 6, 1, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 16,
- 16, 16, 16, 16, 16, 17, 17, 18, 19, 1,
- 20, 1, 21, 1, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 13, 31, 32, 33, 34, 35, 36,
- 13, 37, 38, 39, 40, 41, 42, 43, 44, 45,
- 46, 47, 48, 1, 49, 1, 50, 51, 52, 53,
-
- 54, 55, 56, 13, 57, 13, 58, 59, 58, 60,
- 61, 13, 13, 13, 62, 13, 13, 13, 13, 63,
- 13, 13, 64, 65, 66, 47, 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 int yy_meta[67] =
- { 0,
- 1, 2, 2, 1, 1, 1, 2, 2, 3, 1,
- 1, 1, 3, 1, 3, 3, 3, 2, 2, 1,
- 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, 2, 1, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 2, 1, 2
- } ;
-
-static yyconst short int yy_base[215] =
- { 0,
- 0, 218, 0, 216, 219, 2141, 65, 67, 2141, 2141,
- 2141, 2141, 0, 2141, 2141, 2141, 70, 208, 135, 62,
- 2141, 2141, 2141, 0, 70, 127, 158, 171, 192, 211,
- 260, 309, 215, 46, 0, 269, 273, 2141, 2141, 2141,
- 42, 2141, 43, 70, 0, 0, 330, 0, 48, 322,
- 333, 382, 385, 434, 437, 458, 471, 520, 507, 529,
- 558, 564, 613, 609, 616, 647, 67, 2141, 666, 670,
- 47, 160, 59, 158, 90, 703, 722, 725, 756, 760,
- 789, 793, 822, 828, 851, 862, 873, 886, 907, 926,
- 89, 945, 964, 65, 159, 158, 67, 157, 153, 985,
-
- 1004, 1008, 1039, 1042, 1073, 1076, 1107, 1111, 1130, 1161,
- 1165, 1169, 1198, 1205, 1227, 155, 1234, 1256, 144, 143,
- 139, 140, 137, 127, 112, 113, 1263, 1285, 1292, 1296,
- 1325, 1329, 1336, 1365, 1386, 1389, 1420, 1441, 1444, 1465,
- 1494, 106, 151, 83, 79, 77, 154, 61, 59, 1500,
- 1503, 1534, 1553, 1556, 1587, 1590, 1609, 1640, 1644, 2141,
- 58, 2141, 160, 162, 54, 2141, 169, 174, 1648, 1677,
- 1698, 1701, 1722, 1735, 1757, 1766, 2141, 43, 2141, 2141,
- 37, 2141, 2141, 1779, 1788, 1801, 1810, 1832, 177, 181,
- 1839, 1861, 1868, 1892, 2141, 2141, 1901, 1905, 1936, 1945,
-
- 1958, 1980, 1989, 2002, 2011, 2024, 2047, 2055, 2068, 2141,
- 2131, 76, 2134, 2137
- } ;
-
-static yyconst short int yy_def[215] =
- { 0,
- 210, 1, 211, 211, 210, 210, 210, 210, 210, 210,
- 210, 210, 212, 210, 210, 210, 213, 214, 213, 19,
- 210, 210, 210, 212, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 210, 214, 19, 19, 210, 210, 210,
- 210, 210, 210, 210, 212, 214, 19, 214, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 210, 210, 19, 19,
- 210, 210, 210, 210, 52, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 210, 19, 19, 210, 210, 210, 210, 210, 210, 19,
-
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 210, 19, 19, 210, 210,
- 210, 210, 210, 210, 210, 210, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 210, 210, 210, 210, 210, 210, 210, 210, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 19, 19,
- 19, 19, 19, 19, 19, 19, 210, 210, 210, 210,
- 210, 210, 210, 19, 19, 19, 19, 19, 210, 210,
- 19, 19, 19, 19, 210, 210, 19, 19, 19, 19,
-
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 210, 210, 210, 210
- } ;
-
-static yyconst short int yy_nxt[2208] =
- { 0,
- 6, 7, 8, 6, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 20, 21, 22, 23,
- 24, 25, 17, 17, 17, 26, 17, 27, 17, 28,
- 29, 17, 17, 17, 30, 31, 17, 32, 17, 17,
- 33, 17, 17, 17, 17, 34, 35, 6, 17, 17,
- 17, 17, 17, 17, 17, 36, 17, 17, 37, 17,
- 17, 17, 17, 38, 39, 40, 44, 44, 44, 44,
- 46, 44, 44, 46, 46, 46, 50, 50, 45, 46,
- 46, 46, 67, 46, 47, 47, 47, 67, 67, 46,
- 47, 190, 53, 68, 53, 71, 73, 189, 72, 74,
-
- 47, 54, 47, 91, 47, 94, 95, 181, 91, 91,
- 47, 178, 47, 168, 68, 167, 46, 97, 98, 53,
- 100, 119, 100, 123, 47, 116, 120, 47, 124, 165,
- 116, 116, 47, 164, 46, 46, 68, 163, 46, 46,
- 46, 47, 47, 47, 46, 46, 46, 100, 46, 49,
- 49, 50, 162, 162, 46, 166, 166, 47, 161, 47,
- 55, 179, 179, 180, 180, 51, 149, 51, 148, 56,
- 182, 182, 47, 47, 47, 183, 183, 52, 195, 195,
- 147, 46, 196, 196, 47, 47, 47, 47, 47, 47,
- 47, 146, 51, 145, 57, 144, 143, 52, 142, 46,
-
- 47, 47, 68, 47, 58, 126, 47, 47, 47, 125,
- 122, 121, 99, 47, 96, 47, 48, 59, 210, 43,
- 47, 41, 47, 210, 47, 47, 47, 47, 47, 47,
- 47, 47, 210, 47, 47, 210, 210, 210, 210, 210,
- 66, 47, 210, 47, 210, 47, 210, 47, 210, 47,
- 60, 210, 210, 47, 47, 210, 210, 47, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 47, 210,
- 210, 210, 47, 47, 47, 47, 47, 47, 210, 210,
- 210, 61, 210, 47, 47, 47, 210, 47, 47, 47,
- 47, 210, 47, 210, 210, 210, 62, 210, 210, 47,
-
- 210, 47, 47, 47, 210, 47, 210, 210, 210, 210,
- 210, 47, 210, 210, 210, 47, 210, 47, 210, 210,
- 210, 210, 47, 47, 47, 47, 47, 69, 210, 210,
- 47, 47, 210, 70, 63, 47, 50, 50, 64, 47,
- 210, 47, 210, 65, 47, 47, 47, 47, 47, 47,
- 210, 47, 53, 210, 53, 210, 210, 210, 210, 210,
- 47, 210, 47, 47, 47, 47, 47, 210, 210, 210,
- 210, 47, 47, 210, 210, 47, 210, 210, 210, 53,
- 210, 210, 210, 210, 47, 210, 210, 47, 210, 210,
- 47, 210, 47, 210, 210, 47, 75, 75, 75, 47,
-
- 47, 47, 210, 75, 75, 75, 75, 75, 75, 210,
- 210, 210, 47, 210, 47, 47, 210, 47, 210, 210,
- 210, 210, 210, 210, 47, 210, 210, 47, 210, 210,
- 210, 75, 75, 75, 75, 75, 75, 210, 210, 47,
- 210, 210, 47, 210, 47, 210, 210, 47, 47, 47,
- 47, 47, 47, 47, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 76, 47, 210, 47, 47, 210, 47,
- 210, 210, 47, 47, 47, 77, 47, 210, 210, 47,
- 210, 78, 210, 210, 210, 47, 47, 47, 47, 210,
- 47, 47, 210, 210, 47, 210, 47, 210, 210, 47,
-
- 47, 47, 210, 47, 210, 79, 210, 210, 210, 210,
- 210, 210, 210, 47, 210, 47, 210, 210, 210, 210,
- 47, 47, 47, 47, 210, 210, 210, 210, 47, 210,
- 210, 210, 82, 47, 47, 47, 47, 47, 210, 47,
- 210, 210, 210, 47, 47, 47, 210, 210, 210, 47,
- 47, 210, 47, 210, 210, 80, 210, 210, 81, 47,
- 210, 47, 47, 210, 47, 210, 210, 83, 210, 47,
- 210, 47, 47, 47, 47, 210, 210, 47, 47, 47,
- 47, 210, 47, 210, 210, 84, 47, 210, 47, 210,
- 47, 47, 210, 210, 47, 210, 47, 210, 85, 210,
-
- 47, 210, 210, 210, 210, 210, 47, 210, 210, 210,
- 210, 210, 210, 210, 210, 47, 210, 210, 210, 210,
- 47, 47, 210, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 210, 86, 210, 210, 210, 210, 47,
- 87, 47, 210, 47, 210, 47, 47, 210, 47, 210,
- 210, 47, 89, 88, 210, 47, 210, 210, 47, 210,
- 210, 47, 47, 47, 210, 210, 47, 210, 210, 210,
- 47, 47, 210, 47, 210, 47, 210, 47, 47, 47,
- 47, 47, 47, 90, 47, 47, 47, 210, 210, 47,
- 210, 210, 210, 210, 210, 210, 47, 210, 47, 210,
-
- 47, 210, 47, 210, 47, 210, 210, 210, 47, 47,
- 210, 210, 47, 210, 210, 210, 210, 47, 47, 47,
- 210, 93, 210, 47, 210, 210, 92, 47, 47, 210,
- 101, 210, 47, 47, 210, 47, 47, 47, 47, 47,
- 47, 47, 210, 210, 210, 47, 210, 210, 210, 210,
- 210, 210, 47, 210, 47, 47, 103, 47, 102, 210,
- 47, 210, 210, 210, 47, 47, 210, 47, 210, 210,
- 47, 47, 47, 210, 47, 47, 47, 210, 210, 47,
- 210, 210, 47, 210, 47, 210, 47, 47, 47, 210,
- 47, 210, 47, 210, 210, 104, 210, 210, 47, 105,
-
- 210, 210, 47, 47, 47, 47, 210, 47, 47, 47,
- 210, 210, 210, 47, 106, 210, 210, 47, 47, 47,
- 210, 47, 47, 47, 210, 47, 210, 210, 107, 210,
- 210, 47, 210, 210, 210, 47, 47, 47, 47, 210,
- 210, 210, 47, 47, 47, 210, 47, 210, 210, 210,
- 47, 47, 47, 109, 47, 47, 210, 108, 47, 210,
- 47, 210, 210, 210, 47, 47, 47, 47, 210, 210,
- 47, 210, 210, 210, 210, 210, 47, 47, 47, 47,
- 210, 47, 210, 47, 47, 47, 210, 47, 47, 47,
- 47, 110, 47, 47, 47, 210, 210, 210, 111, 210,
-
- 47, 47, 47, 47, 47, 112, 210, 210, 47, 210,
- 210, 113, 210, 47, 210, 47, 47, 210, 47, 47,
- 210, 47, 47, 47, 47, 210, 210, 210, 47, 210,
- 47, 210, 210, 210, 210, 47, 210, 47, 210, 47,
- 47, 47, 47, 47, 210, 114, 210, 210, 47, 47,
- 210, 210, 210, 210, 210, 210, 47, 210, 47, 47,
- 47, 47, 210, 115, 47, 210, 210, 210, 47, 47,
- 210, 210, 210, 210, 210, 47, 210, 47, 47, 47,
- 47, 210, 210, 47, 210, 210, 210, 47, 47, 210,
- 210, 210, 210, 210, 47, 117, 47, 210, 210, 47,
-
- 47, 47, 47, 210, 210, 210, 47, 47, 210, 210,
- 210, 210, 210, 118, 210, 47, 210, 47, 47, 47,
- 47, 47, 47, 47, 47, 210, 47, 47, 210, 210,
- 210, 210, 210, 210, 47, 210, 47, 127, 47, 210,
- 47, 210, 47, 210, 210, 210, 47, 47, 210, 210,
- 47, 128, 210, 47, 47, 47, 47, 47, 47, 210,
- 210, 47, 210, 210, 210, 47, 47, 210, 210, 47,
- 47, 47, 47, 210, 47, 210, 210, 130, 129, 210,
- 210, 47, 210, 210, 47, 210, 210, 47, 47, 47,
- 47, 47, 47, 210, 210, 210, 47, 210, 210, 47,
-
- 210, 47, 210, 47, 47, 47, 47, 210, 47, 210,
- 210, 131, 132, 210, 210, 47, 210, 210, 47, 210,
- 210, 47, 47, 47, 210, 47, 47, 47, 210, 210,
- 47, 210, 210, 47, 210, 47, 210, 47, 47, 47,
- 210, 47, 210, 47, 47, 47, 47, 210, 210, 47,
- 133, 210, 210, 47, 210, 210, 210, 210, 210, 210,
- 47, 210, 47, 210, 47, 210, 210, 134, 47, 47,
- 210, 210, 47, 47, 210, 47, 47, 47, 210, 47,
- 47, 47, 210, 47, 47, 47, 210, 47, 136, 210,
- 135, 47, 47, 47, 137, 47, 210, 47, 210, 47,
-
- 210, 47, 210, 47, 210, 210, 210, 47, 210, 210,
- 210, 47, 47, 47, 47, 210, 210, 210, 47, 47,
- 47, 47, 47, 47, 210, 210, 47, 47, 47, 210,
- 47, 47, 138, 210, 210, 47, 210, 47, 210, 210,
- 47, 47, 47, 47, 210, 210, 210, 47, 47, 47,
- 47, 210, 210, 210, 210, 47, 139, 47, 210, 47,
- 47, 210, 47, 210, 47, 210, 47, 47, 210, 47,
- 47, 47, 47, 210, 210, 210, 47, 47, 47, 47,
- 210, 210, 210, 140, 47, 210, 47, 210, 47, 47,
- 210, 47, 210, 47, 210, 47, 47, 210, 47, 47,
-
- 47, 47, 210, 210, 210, 47, 47, 47, 47, 210,
- 47, 47, 47, 47, 141, 47, 150, 47, 47, 210,
- 47, 210, 47, 210, 47, 47, 47, 47, 47, 210,
- 210, 210, 210, 210, 47, 210, 210, 210, 47, 47,
- 47, 47, 47, 47, 47, 47, 210, 47, 210, 47,
- 47, 47, 47, 47, 47, 47, 210, 47, 47, 47,
- 210, 47, 210, 210, 151, 210, 47, 47, 47, 210,
- 210, 47, 210, 210, 152, 210, 210, 210, 47, 47,
- 47, 47, 47, 210, 210, 210, 47, 47, 210, 210,
- 210, 47, 210, 47, 153, 47, 210, 47, 47, 210,
-
- 47, 47, 47, 47, 47, 47, 210, 47, 210, 210,
- 154, 210, 210, 210, 210, 210, 47, 155, 47, 47,
- 210, 47, 47, 210, 210, 210, 210, 47, 47, 210,
- 210, 47, 210, 210, 47, 47, 47, 210, 210, 210,
- 210, 210, 210, 47, 210, 210, 47, 210, 47, 210,
- 47, 47, 47, 156, 210, 47, 47, 47, 47, 47,
- 47, 210, 47, 210, 210, 210, 210, 157, 210, 210,
- 210, 47, 210, 47, 47, 210, 47, 47, 158, 47,
- 47, 47, 47, 47, 210, 210, 47, 210, 210, 210,
- 210, 210, 210, 210, 210, 47, 210, 47, 47, 210,
-
- 210, 47, 210, 47, 210, 210, 47, 47, 47, 47,
- 47, 160, 210, 210, 47, 47, 47, 47, 47, 47,
- 210, 210, 47, 159, 47, 169, 47, 47, 210, 210,
- 47, 210, 47, 47, 210, 47, 47, 210, 210, 210,
- 210, 210, 47, 210, 210, 47, 210, 210, 47, 47,
- 47, 47, 210, 210, 210, 210, 47, 47, 210, 210,
- 47, 210, 47, 210, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 210, 210, 210, 47, 210, 210, 210,
- 210, 172, 170, 47, 210, 47, 47, 210, 47, 210,
- 210, 47, 210, 210, 210, 47, 47, 171, 47, 210,
-
- 210, 47, 47, 47, 47, 47, 47, 210, 210, 210,
- 47, 210, 210, 47, 210, 47, 210, 47, 47, 47,
- 47, 210, 47, 47, 47, 47, 210, 210, 174, 47,
- 210, 210, 47, 210, 210, 173, 210, 210, 210, 47,
- 210, 47, 210, 210, 47, 210, 210, 47, 210, 47,
- 210, 47, 47, 210, 47, 47, 47, 175, 47, 47,
- 47, 177, 47, 47, 47, 210, 47, 210, 210, 210,
- 47, 47, 47, 176, 47, 210, 47, 210, 47, 210,
- 47, 210, 47, 210, 210, 210, 47, 210, 210, 210,
- 47, 47, 47, 47, 210, 210, 184, 47, 210, 210,
-
- 210, 47, 47, 185, 210, 47, 47, 47, 210, 47,
- 47, 210, 47, 47, 47, 47, 47, 47, 210, 47,
- 210, 210, 210, 186, 210, 210, 210, 210, 47, 210,
- 47, 47, 210, 47, 47, 210, 47, 47, 47, 47,
- 47, 210, 210, 47, 210, 210, 187, 210, 210, 47,
- 47, 47, 47, 210, 47, 47, 210, 210, 47, 210,
- 47, 210, 210, 47, 47, 47, 210, 47, 210, 210,
- 210, 47, 47, 47, 210, 210, 210, 47, 210, 47,
- 47, 47, 47, 210, 47, 188, 210, 47, 210, 47,
- 210, 210, 47, 47, 47, 47, 47, 47, 47, 47,
-
- 210, 210, 47, 47, 47, 191, 210, 210, 47, 47,
- 210, 47, 210, 210, 47, 47, 47, 47, 47, 47,
- 47, 47, 192, 47, 47, 47, 47, 210, 47, 210,
- 47, 47, 210, 47, 210, 210, 47, 210, 210, 193,
- 47, 47, 47, 47, 210, 47, 47, 47, 47, 210,
- 47, 210, 47, 47, 47, 47, 210, 194, 47, 210,
- 210, 210, 47, 47, 47, 210, 210, 47, 197, 47,
- 210, 47, 47, 210, 47, 47, 47, 47, 210, 210,
- 210, 47, 47, 47, 47, 210, 210, 210, 210, 47,
- 210, 47, 210, 47, 47, 210, 47, 198, 47, 210,
-
- 47, 47, 210, 47, 199, 210, 47, 47, 47, 210,
- 47, 210, 210, 200, 210, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 210, 210, 210, 210,
- 47, 47, 201, 47, 47, 47, 210, 202, 210, 210,
- 210, 210, 210, 47, 210, 210, 210, 47, 210, 47,
- 47, 47, 47, 210, 47, 210, 210, 210, 47, 47,
- 47, 47, 47, 47, 210, 210, 47, 47, 47, 203,
- 210, 210, 47, 47, 47, 47, 210, 47, 47, 210,
- 210, 210, 210, 204, 210, 210, 210, 47, 47, 210,
- 47, 210, 210, 47, 47, 47, 47, 210, 47, 210,
-
- 47, 205, 47, 47, 47, 47, 210, 47, 210, 210,
- 47, 210, 47, 210, 206, 47, 47, 47, 47, 47,
- 47, 47, 47, 210, 210, 47, 47, 47, 210, 210,
- 210, 47, 47, 210, 47, 210, 210, 47, 47, 47,
- 47, 47, 47, 47, 47, 210, 47, 210, 210, 207,
- 210, 47, 210, 47, 47, 210, 47, 210, 210, 47,
- 208, 47, 47, 47, 47, 210, 47, 210, 47, 47,
- 47, 47, 210, 47, 210, 210, 210, 47, 210, 47,
- 210, 47, 47, 47, 47, 47, 47, 47, 210, 47,
- 210, 210, 209, 210, 210, 210, 210, 47, 47, 210,
-
- 47, 210, 210, 210, 47, 210, 210, 210, 210, 47,
- 47, 210, 47, 210, 210, 210, 210, 47, 210, 210,
- 210, 210, 210, 210, 210, 47, 210, 210, 210, 210,
- 47, 42, 42, 42, 47, 210, 47, 46, 210, 46,
- 5, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
-
- 210, 210, 210, 210, 210, 210, 210
- } ;
-
-static yyconst short int yy_chk[2208] =
- { 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, 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, 7, 7, 8, 8,
- 17, 44, 44, 17, 17, 17, 20, 20, 212, 17,
- 17, 17, 34, 17, 25, 25, 25, 34, 34, 17,
- 49, 181, 20, 34, 20, 41, 43, 178, 41, 43,
-
- 25, 25, 25, 67, 20, 71, 71, 165, 67, 67,
- 49, 161, 25, 149, 67, 148, 17, 73, 73, 20,
- 75, 94, 75, 97, 20, 91, 94, 25, 97, 146,
- 91, 91, 25, 145, 17, 19, 91, 144, 19, 19,
- 19, 26, 26, 26, 19, 19, 19, 75, 19, 19,
- 19, 19, 143, 143, 19, 147, 147, 26, 142, 26,
- 26, 163, 163, 164, 164, 19, 126, 19, 125, 26,
- 167, 167, 27, 27, 27, 168, 168, 19, 189, 189,
- 124, 19, 190, 190, 26, 28, 28, 28, 27, 26,
- 27, 123, 19, 122, 27, 121, 120, 19, 119, 19,
-
- 27, 28, 116, 28, 28, 99, 29, 29, 29, 98,
- 96, 95, 74, 28, 72, 27, 18, 29, 5, 4,
- 27, 2, 29, 0, 29, 30, 30, 30, 28, 33,
- 33, 33, 0, 28, 29, 0, 0, 0, 0, 0,
- 33, 30, 0, 30, 0, 33, 0, 33, 0, 29,
- 30, 0, 0, 30, 29, 0, 0, 33, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 30, 0,
- 0, 0, 33, 30, 31, 31, 31, 33, 0, 0,
- 0, 31, 0, 36, 36, 36, 0, 37, 37, 37,
- 31, 0, 31, 0, 0, 0, 31, 0, 0, 36,
-
- 0, 36, 31, 37, 0, 37, 0, 0, 0, 0,
- 0, 36, 0, 0, 0, 37, 0, 31, 0, 0,
- 0, 0, 31, 32, 32, 32, 36, 36, 0, 0,
- 37, 36, 0, 37, 32, 37, 50, 50, 32, 32,
- 0, 32, 0, 32, 47, 47, 47, 51, 51, 51,
- 0, 32, 50, 0, 50, 0, 0, 0, 0, 0,
- 47, 0, 47, 51, 50, 51, 32, 0, 0, 0,
- 0, 32, 47, 0, 0, 51, 0, 0, 0, 50,
- 0, 0, 0, 0, 50, 0, 0, 47, 0, 0,
- 51, 0, 47, 0, 0, 51, 52, 52, 52, 53,
-
- 53, 53, 0, 52, 52, 52, 52, 52, 52, 0,
- 0, 0, 52, 0, 52, 53, 0, 53, 0, 0,
- 0, 0, 0, 0, 52, 0, 0, 53, 0, 0,
- 0, 52, 52, 52, 52, 52, 52, 0, 0, 52,
- 0, 0, 53, 0, 52, 0, 0, 53, 54, 54,
- 54, 55, 55, 55, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 54, 54, 0, 54, 55, 0, 55,
- 0, 0, 56, 56, 56, 55, 54, 0, 0, 55,
- 0, 56, 0, 0, 0, 57, 57, 57, 56, 0,
- 56, 54, 0, 0, 55, 0, 54, 0, 0, 55,
-
- 56, 57, 0, 57, 0, 57, 0, 0, 0, 0,
- 0, 0, 0, 57, 0, 56, 0, 0, 0, 0,
- 56, 59, 59, 59, 0, 0, 0, 0, 57, 0,
- 0, 0, 59, 57, 58, 58, 58, 59, 0, 59,
- 0, 0, 0, 60, 60, 60, 0, 0, 0, 59,
- 58, 0, 58, 0, 0, 58, 0, 0, 58, 60,
- 0, 60, 58, 0, 59, 0, 0, 60, 0, 59,
- 0, 60, 61, 61, 61, 0, 0, 58, 62, 62,
- 62, 0, 58, 0, 0, 61, 60, 0, 61, 0,
- 61, 60, 0, 0, 62, 0, 62, 0, 62, 0,
-
- 61, 0, 0, 0, 0, 0, 62, 0, 0, 0,
- 0, 0, 0, 0, 0, 61, 0, 0, 0, 0,
- 61, 62, 0, 64, 64, 64, 62, 63, 63, 63,
- 65, 65, 65, 0, 63, 0, 0, 0, 0, 64,
- 63, 64, 0, 63, 0, 63, 65, 0, 65, 0,
- 0, 64, 65, 64, 0, 63, 0, 0, 65, 0,
- 0, 66, 66, 66, 0, 0, 64, 0, 0, 0,
- 63, 64, 0, 65, 0, 63, 0, 66, 65, 66,
- 69, 69, 69, 66, 70, 70, 70, 0, 0, 66,
- 0, 0, 0, 0, 0, 0, 69, 0, 69, 0,
-
- 70, 0, 70, 0, 66, 0, 0, 0, 69, 66,
- 0, 0, 70, 0, 0, 0, 0, 76, 76, 76,
- 0, 70, 0, 69, 0, 0, 69, 70, 69, 0,
- 76, 0, 70, 76, 0, 76, 77, 77, 77, 78,
- 78, 78, 0, 0, 0, 76, 0, 0, 0, 0,
- 0, 0, 77, 0, 77, 78, 78, 78, 77, 0,
- 76, 0, 0, 0, 77, 76, 0, 78, 0, 0,
- 79, 79, 79, 0, 80, 80, 80, 0, 0, 77,
- 0, 0, 78, 0, 77, 0, 79, 78, 79, 0,
- 80, 0, 80, 0, 0, 79, 0, 0, 79, 80,
-
- 0, 0, 80, 81, 81, 81, 0, 82, 82, 82,
- 0, 0, 0, 79, 81, 0, 0, 80, 79, 81,
- 0, 81, 80, 82, 0, 82, 0, 0, 82, 0,
- 0, 81, 0, 0, 0, 82, 83, 83, 83, 0,
- 0, 0, 84, 84, 84, 0, 81, 0, 0, 0,
- 82, 81, 83, 84, 83, 82, 0, 83, 84, 0,
- 84, 0, 0, 0, 83, 85, 85, 85, 0, 0,
- 84, 0, 0, 0, 0, 0, 86, 86, 86, 83,
- 0, 85, 0, 85, 83, 84, 0, 87, 87, 87,
- 84, 85, 86, 85, 86, 0, 0, 0, 86, 0,
-
- 88, 88, 88, 87, 86, 87, 0, 0, 85, 0,
- 0, 88, 0, 85, 0, 87, 88, 0, 88, 86,
- 0, 89, 89, 89, 86, 0, 0, 0, 88, 0,
- 87, 0, 0, 0, 0, 87, 0, 89, 0, 89,
- 90, 90, 90, 88, 0, 89, 0, 0, 88, 89,
- 0, 0, 0, 0, 0, 0, 90, 0, 90, 92,
- 92, 92, 0, 90, 89, 0, 0, 0, 90, 89,
- 0, 0, 0, 0, 0, 92, 0, 92, 93, 93,
- 93, 0, 0, 90, 0, 0, 0, 92, 90, 0,
- 0, 0, 0, 0, 93, 92, 93, 0, 0, 100,
-
- 100, 100, 92, 0, 0, 0, 93, 92, 0, 0,
- 0, 0, 0, 93, 0, 100, 0, 100, 101, 101,
- 101, 93, 102, 102, 102, 0, 93, 100, 0, 0,
- 0, 0, 0, 0, 101, 0, 101, 101, 102, 0,
- 102, 0, 100, 0, 0, 0, 101, 100, 0, 0,
- 102, 102, 0, 103, 103, 103, 104, 104, 104, 0,
- 0, 101, 0, 0, 0, 102, 101, 0, 0, 103,
- 102, 103, 104, 0, 104, 0, 0, 104, 103, 0,
- 0, 103, 0, 0, 104, 0, 0, 105, 105, 105,
- 106, 106, 106, 0, 0, 0, 103, 0, 0, 104,
-
- 0, 103, 0, 105, 104, 105, 106, 0, 106, 0,
- 0, 105, 106, 0, 0, 105, 0, 0, 106, 0,
- 0, 107, 107, 107, 0, 108, 108, 108, 0, 0,
- 105, 0, 0, 106, 0, 105, 0, 107, 106, 107,
- 0, 108, 0, 108, 109, 109, 109, 0, 0, 107,
- 108, 0, 0, 108, 0, 0, 0, 0, 0, 0,
- 109, 0, 109, 0, 107, 0, 0, 109, 108, 107,
- 0, 0, 109, 108, 0, 110, 110, 110, 0, 111,
- 111, 111, 0, 112, 112, 112, 0, 109, 111, 0,
- 110, 110, 109, 110, 112, 111, 0, 111, 0, 112,
-
- 0, 112, 0, 110, 0, 0, 0, 111, 0, 0,
- 0, 112, 113, 113, 113, 0, 0, 0, 110, 114,
- 114, 114, 111, 110, 0, 0, 112, 111, 113, 0,
- 113, 112, 113, 0, 0, 114, 0, 114, 0, 0,
- 113, 115, 115, 115, 0, 0, 0, 114, 117, 117,
- 117, 0, 0, 0, 0, 113, 115, 115, 0, 115,
- 113, 0, 114, 0, 117, 0, 117, 114, 0, 115,
- 118, 118, 118, 0, 0, 0, 117, 127, 127, 127,
- 0, 0, 0, 117, 115, 0, 118, 0, 118, 115,
- 0, 117, 0, 127, 0, 127, 117, 0, 118, 128,
-
- 128, 128, 0, 0, 0, 127, 129, 129, 129, 0,
- 130, 130, 130, 118, 118, 128, 129, 128, 118, 0,
- 127, 0, 129, 0, 129, 127, 130, 128, 130, 0,
- 0, 0, 0, 0, 129, 0, 0, 0, 130, 131,
- 131, 131, 128, 132, 132, 132, 0, 128, 0, 129,
- 133, 133, 133, 130, 129, 131, 0, 131, 130, 132,
- 0, 132, 0, 0, 132, 0, 133, 131, 133, 0,
- 0, 132, 0, 0, 133, 0, 0, 0, 133, 134,
- 134, 134, 131, 0, 0, 0, 132, 131, 0, 0,
- 0, 132, 0, 133, 134, 134, 0, 134, 133, 0,
-
- 135, 135, 135, 136, 136, 136, 0, 134, 0, 0,
- 135, 0, 0, 0, 0, 0, 135, 136, 135, 136,
- 0, 136, 134, 0, 0, 0, 0, 134, 135, 0,
- 0, 136, 0, 0, 137, 137, 137, 0, 0, 0,
- 0, 0, 0, 135, 0, 0, 136, 0, 135, 0,
- 137, 136, 137, 137, 0, 138, 138, 138, 139, 139,
- 139, 0, 137, 0, 0, 0, 0, 138, 0, 0,
- 0, 138, 0, 138, 139, 0, 139, 137, 139, 140,
- 140, 140, 137, 138, 0, 0, 139, 0, 0, 0,
- 0, 0, 0, 0, 0, 140, 0, 140, 138, 0,
-
- 0, 139, 0, 138, 0, 0, 139, 140, 141, 141,
- 141, 141, 0, 0, 150, 150, 150, 151, 151, 151,
- 0, 0, 140, 140, 141, 150, 141, 140, 0, 0,
- 150, 0, 150, 151, 0, 151, 141, 0, 0, 0,
- 0, 0, 150, 0, 0, 151, 0, 0, 152, 152,
- 152, 141, 0, 0, 0, 0, 141, 150, 0, 0,
- 151, 0, 150, 0, 152, 151, 152, 153, 153, 153,
- 154, 154, 154, 0, 0, 0, 152, 0, 0, 0,
- 0, 154, 152, 153, 0, 153, 154, 0, 154, 0,
- 0, 152, 0, 0, 0, 153, 152, 153, 154, 0,
-
- 0, 155, 155, 155, 156, 156, 156, 0, 0, 0,
- 153, 0, 0, 154, 0, 153, 0, 155, 154, 155,
- 156, 0, 156, 157, 157, 157, 0, 0, 156, 155,
- 0, 0, 156, 0, 0, 155, 0, 0, 0, 157,
- 0, 157, 0, 0, 155, 0, 0, 156, 0, 155,
- 0, 157, 156, 0, 158, 158, 158, 157, 159, 159,
- 159, 159, 169, 169, 169, 0, 157, 0, 0, 0,
- 158, 157, 158, 158, 159, 0, 159, 0, 169, 0,
- 169, 0, 158, 0, 0, 0, 159, 0, 0, 0,
- 169, 170, 170, 170, 0, 0, 169, 158, 0, 0,
-
- 0, 159, 158, 170, 0, 169, 159, 170, 0, 170,
- 169, 0, 171, 171, 171, 172, 172, 172, 0, 170,
- 0, 0, 0, 171, 0, 0, 0, 0, 171, 0,
- 171, 172, 0, 172, 170, 0, 173, 173, 173, 170,
- 171, 0, 0, 172, 0, 0, 173, 0, 0, 174,
- 174, 174, 173, 0, 173, 171, 0, 0, 172, 0,
- 171, 0, 0, 172, 173, 174, 0, 174, 0, 0,
- 0, 175, 175, 175, 0, 0, 0, 174, 0, 173,
- 176, 176, 176, 0, 173, 175, 0, 175, 0, 175,
- 0, 0, 174, 184, 184, 184, 176, 174, 176, 175,
-
- 0, 0, 185, 185, 185, 184, 0, 0, 176, 184,
- 0, 184, 0, 0, 175, 186, 186, 186, 185, 175,
- 185, 184, 185, 176, 187, 187, 187, 0, 176, 0,
- 185, 186, 0, 186, 0, 0, 184, 0, 0, 187,
- 187, 184, 187, 186, 0, 185, 188, 188, 188, 0,
- 185, 0, 187, 191, 191, 191, 0, 188, 186, 0,
- 0, 0, 188, 186, 188, 0, 0, 187, 191, 191,
- 0, 191, 187, 0, 188, 192, 192, 192, 0, 0,
- 0, 191, 193, 193, 193, 0, 0, 0, 0, 188,
- 0, 192, 0, 192, 188, 0, 191, 192, 193, 0,
-
- 193, 191, 0, 192, 193, 0, 194, 194, 194, 0,
- 193, 0, 0, 194, 0, 197, 197, 197, 192, 198,
- 198, 198, 194, 192, 194, 193, 0, 0, 0, 0,
- 193, 197, 197, 197, 194, 198, 0, 198, 0, 0,
- 0, 0, 0, 197, 0, 0, 0, 198, 0, 194,
- 199, 199, 199, 0, 194, 0, 0, 0, 197, 200,
- 200, 200, 198, 197, 0, 0, 199, 198, 199, 200,
- 0, 0, 201, 201, 201, 200, 0, 200, 199, 0,
- 0, 0, 0, 201, 0, 0, 0, 200, 201, 0,
- 201, 0, 0, 199, 202, 202, 202, 0, 199, 0,
-
- 201, 202, 200, 203, 203, 203, 0, 200, 0, 0,
- 202, 0, 202, 0, 203, 201, 204, 204, 204, 203,
- 201, 203, 202, 0, 0, 205, 205, 205, 0, 0,
- 0, 203, 204, 0, 204, 0, 0, 202, 206, 206,
- 206, 205, 202, 205, 204, 0, 203, 0, 0, 205,
- 0, 203, 0, 205, 206, 0, 206, 0, 0, 204,
- 206, 207, 207, 207, 204, 0, 206, 0, 205, 208,
- 208, 208, 0, 205, 0, 0, 0, 207, 0, 207,
- 0, 206, 209, 209, 209, 208, 206, 208, 0, 207,
- 0, 0, 208, 0, 0, 0, 0, 208, 209, 0,
-
- 209, 0, 0, 0, 207, 0, 0, 0, 0, 207,
- 209, 0, 208, 0, 0, 0, 0, 208, 0, 0,
- 0, 0, 0, 0, 0, 209, 0, 0, 0, 0,
- 209, 211, 211, 211, 213, 0, 213, 214, 0, 214,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, 210,
-
- 210, 210, 210, 210, 210, 210, 210
- } ;
-
-static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
-static char *yy_full_match;
-static int yy_lp;
-#define REJECT \
-{ \
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
-yy_cp = yy_full_match; /* restore poss. backed-over text */ \
-++yy_lp; \
-goto find_rule; \
-}
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "/home/drepper/gnu/elfutils/src/ldlex.l"
-#define INITIAL 0
-#line 2 "/home/drepper/gnu/elfutils/src/ldlex.l"
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <elf.h>
-#include <error.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-#include "ldscript.h"
-
-/* We sure use no threads to read the stream, so use the _unlocked
- variants of the functions. */
-#undef getc
-#define getc(s) getc_unlocked (s)
-#undef ferror
-#define ferror(s) ferror_unlocked (s)
-#undef fread
-#define fread(b, m, n, s) fread_unlocked (b, m, n, s)
-#undef fwrite
-#define fwrite(b, m, n, s) fwrite_unlocked (b, m, n, s)
-
-/* Defined in ld.c. */
-extern int ld_scan_version_script;
-
-#define MAX_PREPDEPTH 20
-static enum prepstate
-{
- prep_normal,
- skip_if,
- skip_to_endif
-} prepstate[MAX_PREPDEPTH];
-static int prepdepth;
-
-static void eat_comment (void);
-static void eat_to_eol (bool empty);
-static int attrib_convert (int c);
-static void push_state (enum prepstate);
-static int pop_state (void);
-static int handle_ifdef (void);
-static void invalid_char (int ch);
-#define YY_NEVER_INTERACTIVE 1
-#define IGNORE 1
-
-#line 1061 "ldlex.c"
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
-#else
-extern int yywrap YY_PROTO(( void ));
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
-#else
-static int input YY_PROTO(( void ));
-#endif
-#endif
-
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
-#endif
-
-#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
-#endif
-
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines. This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#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 (void) 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->yy_is_interactive ) \
- { \
- int c = '*', 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 if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
- && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
-#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
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
-
-/* 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 \
- if ( yyleng > 0 ) \
- yy_current_buffer->yy_at_bol = \
- (yytext[yyleng - 1] == '\n'); \
- YY_USER_ACTION
-
-YY_DECL
- {
- register yy_state_type yy_current_state;
- register char *yy_cp = NULL, *yy_bp = NULL;
- register int yy_act;
-
-#line 79 "/home/drepper/gnu/elfutils/src/ldlex.l"
-
- if (unlikely (ld_scan_version_script))
- {
- ld_scan_version_script = -1;
- return kVERSION_SCRIPT;
- }
-
-#line 1223 "ldlex.c"
-
- if ( yy_init )
- {
- yy_init = 0;
-
-#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 )
- yy_current_buffer =
- 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_current_state += YY_AT_BOL();
- yy_state_ptr = yy_state_buf;
- *yy_state_ptr++ = yy_current_state;
-yy_match:
- do
- {
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*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 >= 211 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- *yy_state_ptr++ = yy_current_state;
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 2141 );
-
-yy_find_action:
- yy_current_state = *--yy_state_ptr;
- yy_lp = yy_accept[yy_current_state];
-find_rule: /* we branch to this label when backing up */
- for ( ; ; ) /* until we find what rule we matched */
- {
- if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
- {
- yy_act = yy_acclist[yy_lp];
- {
- yy_full_match = yy_cp;
- break;
- }
- }
- --yy_cp;
- yy_current_state = *--yy_state_ptr;
- yy_lp = yy_accept[yy_current_state];
- }
-
- YY_DO_BEFORE_ACTION;
-
- if ( yy_act != YY_END_OF_BUFFER )
- {
- int yyl;
- for ( yyl = 0; yyl < yyleng; ++yyl )
- if ( yytext[yyl] == '\n' )
- ++yylineno;
- }
-
-do_action: /* This label is used only to access EOF actions. */
-
-
- switch ( yy_act )
- { /* beginning of action switch */
-case 1:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 6;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 86 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ BEGIN (handle_ifdef ()); }
- YY_BREAK
-case 2:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 5;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 87 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (true);
- push_state (skip_to_endif);
- BEGIN (IGNORE); }
- YY_BREAK
-case 3:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 8;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 90 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (false);
- push_state (skip_to_endif);
- BEGIN (IGNORE); }
- YY_BREAK
-case 4:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 6;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 93 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (true) ; }
- YY_BREAK
-case 5:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 6;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 95 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (false);
- push_state (skip_to_endif); }
- YY_BREAK
-case 6:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 5;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 97 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (true);
- assert (prepdepth > 0);
- if (prepstate[prepdepth - 1] == skip_if)
- {
- /* Back to normal processing. */
- assert (prepdepth == 1);
- BEGIN (pop_state ());
- }
- }
- YY_BREAK
-case 7:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 8;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 106 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ assert (prepdepth > 0);
- if (prepstate[prepdepth - 1] == skip_if)
- {
- /* Maybe this symbol is defined. */
- pop_state ();
- BEGIN (handle_ifdef ());
- }
- }
- YY_BREAK
-case 8:
-*yy_cp = yy_hold_char; /* undo effects of setting up yytext */
-yy_c_buf_p = yy_cp = yy_bp + 6;
-YY_DO_BEFORE_ACTION; /* set up yytext again */
-YY_RULE_SETUP
-#line 114 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_to_eol (true);
- BEGIN (pop_state ()); }
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 116 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ /* nothing */ }
- YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 119 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ eat_comment (); }
- YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 121 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kALIGN; }
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 122 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kENTRY; }
- YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 123 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kEXCLUDE_FILE; }
- YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 124 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kGLOBAL; }
- YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 125 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kGROUP; }
- YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 126 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kINPUT; }
- YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 127 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kINTERP; }
- YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 128 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kKEEP; }
- YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 129 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kLOCAL; }
- YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 130 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kOUTPUT_FORMAT; }
- YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 131 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kPAGESIZE; }
- YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 132 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kPROVIDE; }
- YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 133 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kSEARCH_DIR; }
- YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 134 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kSEGMENT; }
- YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 135 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kSIZEOF_HEADERS; }
- YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 136 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kSORT; }
- YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 137 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return kVERSION; }
- YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 139 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ int cnt = 1 ;
- ldlval.num = 0;
- while (cnt < yyleng - 1)
- ldlval.num |= attrib_convert (yytext[cnt++]);
- return kMODE; }
- YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 145 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '{'; }
- YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 146 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '}'; }
- YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 147 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '('; }
- YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 148 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return ')'; }
- YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 149 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return ':'; }
- YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 150 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return ';'; }
- YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 151 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '='; }
- YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 152 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.op = exp_plus; return kADD_OP; }
- YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 153 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.op = exp_minus; return kADD_OP; }
- YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 154 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '*'; }
- YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 155 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.op = exp_div; return kMUL_OP; }
- YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 156 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.op = exp_mod; return kMUL_OP; }
- YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 157 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '&'; }
- YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 158 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return '|'; }
- YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 160 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ return ','; }
- YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 162 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ char *endp;
- ldlval.num = strtoumax (yytext, &endp, 0);
- if (*endp != '\0')
- {
- if (tolower (*endp) == 'k')
- ldlval.num *= 1024;
- else
- {
- assert (tolower (*endp) == 'm');
- ldlval.num *= 1024 * 1024;
- }
- }
- return kNUM; }
- YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 176 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.str = obstack_strndup (&ld_state.smem,
- yytext, yyleng);
- return kID; }
- YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 180 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ ldlval.str = obstack_strndup (&ld_state.smem,
- yytext, yyleng);
- return kFILENAME; }
- YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 184 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ /* IGNORE */ }
- YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 186 "/home/drepper/gnu/elfutils/src/ldlex.l"
-{ invalid_char (*yytext); }
- YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 188 "/home/drepper/gnu/elfutils/src/ldlex.l"
-ECHO;
- YY_BREAK
-#line 1625 "ldlex.c"
- case YY_STATE_EOF(INITIAL):
- case YY_STATE_EOF(IGNORE):
- yyterminate();
-
- 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->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->yy_n_chars;
- yy_current_buffer->yy_input_file = yyin;
- yy_current_buffer->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->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->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()
- {
- register char *dest = yy_current_buffer->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->yy_ch_buf[yy_n_chars + 1] )
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--end of buffer missed" );
-
- if ( yy_current_buffer->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->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->yy_n_chars = yy_n_chars = 0;
-
- else
- {
- int num_to_read =
- yy_current_buffer->yy_buf_size - number_to_move - 1;
-
- while ( num_to_read <= 0 )
- { /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
- YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
-
- /* 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 )
- {
- int 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. */
- yy_flex_realloc( (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->yy_buf_size -
- number_to_move - 1;
-#endif
- }
-
- if ( num_to_read > YY_READ_BUF_SIZE )
- num_to_read = YY_READ_BUF_SIZE;
-
- /* Read in more data. */
- YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
- yy_n_chars, num_to_read );
-
- yy_current_buffer->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->yy_buffer_status =
- YY_BUFFER_EOF_PENDING;
- }
- }
-
- else
- ret_val = EOB_ACT_CONTINUE_SCAN;
-
- yy_n_chars += number_to_move;
- yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
- yytext_ptr = &yy_current_buffer->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()
- {
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
- yy_current_state = yy_start;
- yy_current_state += YY_AT_BOL();
- yy_state_ptr = yy_state_buf;
- *yy_state_ptr++ = yy_current_state;
-
- 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);
- 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 >= 211 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- *yy_state_ptr++ = yy_current_state;
- }
-
- 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 );
- */
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
- {
- register int yy_is_jam;
-
- register YY_CHAR yy_c = 1;
- 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 >= 211 )
- 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 == 210);
- if ( ! yy_is_jam )
- *yy_state_ptr++ = yy_current_state;
-
- return yy_is_jam ? 0 : yy_current_state;
- }
-
-
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
- {
- register char *yy_cp = yy_c_buf_p;
-
- /* undo effects of setting up yytext */
- *yy_cp = yy_hold_char;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- { /* need to shift things up to make room */
- /* +2 for EOB chars. */
- register int number_to_move = yy_n_chars + 2;
- register char *dest = &yy_current_buffer->yy_ch_buf[
- yy_current_buffer->yy_buf_size + 2];
- register char *source =
- &yy_current_buffer->yy_ch_buf[number_to_move];
-
- while ( source > yy_current_buffer->yy_ch_buf )
- *--dest = *--source;
-
- yy_cp += (int) (dest - source);
- yy_bp += (int) (dest - source);
- yy_current_buffer->yy_n_chars =
- yy_n_chars = yy_current_buffer->yy_buf_size;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- YY_FATAL_ERROR( "flex scanner push-back overflow" );
- }
-
- *--yy_cp = (char) c;
-
- if ( c == '\n' )
- --yylineno;
-
- yytext_ptr = yy_bp;
- yy_hold_char = *yy_cp;
- yy_c_buf_p = yy_cp;
- }
-#endif /* ifndef YY_NO_UNPUT */
-
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput()
-#else
-static int input()
-#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->yy_ch_buf[yy_n_chars] )
- /* This was really a NUL. */
- *yy_c_buf_p = '\0';
-
- else
- { /* need more input */
- int 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 );
-
- /* fall through */
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( yywrap() )
- return EOF;
-
- 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;
-
- yy_current_buffer->yy_at_bol = (c == '\n');
- if ( yy_current_buffer->yy_at_bol )
- ++yylineno;
-
- return c;
- }
-#endif /* YY_NO_INPUT */
-
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
- {
- if ( ! yy_current_buffer )
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
-
- yy_init_buffer( yy_current_buffer, input_file );
- yy_load_buffer_state();
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
- {
- 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->yy_buf_pos = yy_c_buf_p;
- yy_current_buffer->yy_n_chars = yy_n_chars;
- }
-
- yy_current_buffer = 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;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
- {
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
- yyin = yy_current_buffer->yy_input_file;
- yy_hold_char = *yy_c_buf_p;
- }
-
-
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
- {
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) yy_flex_alloc( 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 *) yy_flex_alloc( 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;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
- {
- if ( ! b )
- return;
-
- if ( b == yy_current_buffer )
- yy_current_buffer = (YY_BUFFER_STATE) 0;
-
- if ( b->yy_is_our_buffer )
- yy_flex_free( (void *) b->yy_ch_buf );
-
- yy_flex_free( (void *) b );
- }
-
-
-
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
-
-
- {
- yy_flush_buffer( b );
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
-#if YY_ALWAYS_INTERACTIVE
- b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
- b->yy_is_interactive = 0;
-#else
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-
- {
- 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();
- }
-
-
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
- {
- 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) yy_flex_alloc( 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;
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
- {
- int len;
- for ( len = 0; yy_str[len]; ++len )
- ;
-
- return yy_scan_bytes( yy_str, len );
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
- {
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
- buf = (char *) yy_flex_alloc( n );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
-
- buf[len] = buf[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;
- }
-#endif
-
-
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
- {
- if ( yy_start_stack_ptr >= yy_start_stack_depth )
- {
- yy_size_t new_size;
-
- yy_start_stack_depth += YY_START_STACK_INCR;
- new_size = yy_start_stack_depth * sizeof( int );
-
- if ( ! yy_start_stack )
- yy_start_stack = (int *) yy_flex_alloc( new_size );
-
- else
- yy_start_stack = (int *) yy_flex_realloc(
- (void *) yy_start_stack, new_size );
-
- if ( ! yy_start_stack )
- YY_FATAL_ERROR(
- "out of memory expanding start-condition stack" );
- }
-
- yy_start_stack[yy_start_stack_ptr++] = YY_START;
-
- BEGIN(new_state);
- }
-#endif
-
-
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
- {
- if ( --yy_start_stack_ptr < 0 )
- YY_FATAL_ERROR( "start-condition stack underflow" );
-
- BEGIN(yy_start_stack[yy_start_stack_ptr]);
- }
-#endif
-
-
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
- {
- return yy_start_stack[yy_start_stack_ptr - 1];
- }
-#endif
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
-#else
-static void yy_fatal_error( msg )
-char msg[];
-#endif
- {
- (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. */ \
- yytext[yyleng] = yy_hold_char; \
- yy_c_buf_p = yytext + n; \
- yy_hold_char = *yy_c_buf_p; \
- *yy_c_buf_p = '\0'; \
- yyleng = n; \
- } \
- while ( 0 )
-
-
-/* Internal utility routines. */
-
-#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
- {
- register int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
- }
-#endif
-
-#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
- {
- register int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
- }
-#endif
-
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
- {
- return (void *) malloc( size );
- }
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
- {
- /* 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 );
- }
-
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
- {
- free( ptr );
- }
-
-#if YY_MAIN
-int main()
- {
- yylex();
- return 0;
- }
-#endif
-#line 188 "/home/drepper/gnu/elfutils/src/ldlex.l"
-
-
-static void
-eat_comment (void)
-{
- while (1)
- {
- int c = input ();
-
- while (c != '*' && c != EOF)
- c = input ();
-
- if (c == '*')
- {
- c = input ();
- while (c == '*')
- c = input ();
- if (c == '/')
- break;
- }
-
- if (c == EOF)
- {
- /* XXX Use the setjmp buffer and signal EOF in comment */
- error (0, 0, gettext ("EOF in comment"));
- break;
- }
- }
-}
-
-
-static void
-eat_to_eol (bool empty)
-{
- bool warned = false;
-
- while (1)
- {
- int c = input ();
-
- if (c == EOF)
- break;
- if (c == '\n')
- {
- ++yylineno;
- break;
- }
-
- if (empty && ! isspace (c) && ! warned)
- {
- error (0, 0, gettext ("%d: garbage at end of line"), yylineno);
- warned = true;
- }
- }
-}
-
-
-static int
-attrib_convert (int c)
-{
- if (c == 'X')
- return PF_X;
- if (c == 'W')
- return PF_W;
- assert (c == 'R');
- return PF_R;
-}
-
-
-static void
-push_state (enum prepstate state)
-{
- if (prepdepth >= MAX_PREPDEPTH)
- error (EXIT_FAILURE, 0, gettext ("%d: conditionals nested too deep"),
- yylineno);
-
- prepstate[prepdepth++] = state;
-}
-
-
-static int
-pop_state (void)
-{
- if (prepdepth == 0)
- error (0, 0, gettext ("%d: unexpected #endif"), yylineno);
- else
- --prepdepth;
-
- return prepdepth == 0 ? INITIAL : IGNORE;
-}
-
-
-static int
-handle_ifdef (void)
-{
- char idbuf[50];
- char *id = idbuf;
- size_t idlen = 0;
- size_t idmax = sizeof (idbuf);
- bool ignore_ws = true;
- bool defined = false;
- int result;
-
- while (1)
- {
- int c = input ();
-
- if (isspace (c) && ignore_ws)
- continue;
-
- if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
- && (idlen == 0 || c < '0' || c > '9'))
- {
- unput (c);
- break;
- }
-
- if (idlen == idmax)
- {
- char *newp = (char *) alloca (idmax *= 2);
- id = memcpy (newp, id, idlen);
- }
-
- id[idlen++] = c;
- ignore_ws = false;
- }
-
- /* XXX Compare in a better way. */
- if (idlen == 6 && strncmp (id, "SHARED", 6) == 0)
- defined = ld_state.file_type == dso_file_type;
-
- if (defined)
- result = INITIAL;
- else
- {
- push_state (skip_if);
- result = IGNORE;
- }
-
- return result;
-}
-
-
-static void
-invalid_char (int ch)
-{
- error (0, 0, (isascii (ch)
- ? gettext ("invalid character '%c' at line %d; ignored")
- : gettext ("invalid character '\\%o' at line %d; ignored")),
- ch, yylineno);
-}
-
-
-// Local Variables:
-// mode: C
-// End:
diff --git a/src/ldlex.l b/src/ldlex.l
deleted file mode 100644
index 06ea6237..00000000
--- a/src/ldlex.l
+++ /dev/null
@@ -1,343 +0,0 @@
-%{
-/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <elf.h>
-#include <error.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-#include "ldscript.h"
-
-/* We sure use no threads to read the stream, so use the _unlocked
- variants of the functions. */
-#undef getc
-#define getc(s) getc_unlocked (s)
-#undef ferror
-#define ferror(s) ferror_unlocked (s)
-#undef fread
-#define fread(b, m, n, s) fread_unlocked (b, m, n, s)
-#undef fwrite
-#define fwrite(b, m, n, s) fwrite_unlocked (b, m, n, s)
-
-/* Defined in ld.c. */
-extern int ld_scan_version_script;
-
-#define MAX_PREPDEPTH 20
-static enum prepstate
-{
- prep_normal,
- skip_if,
- skip_to_endif
-} prepstate[MAX_PREPDEPTH];
-static int prepdepth;
-
-static void eat_comment (void);
-static void eat_to_eol (bool empty);
-static int attrib_convert (int c);
-static void push_state (enum prepstate);
-static int pop_state (void);
-static int handle_ifdef (void);
-static void invalid_char (int ch);
-%}
-
-ID [a-zA-Z0-9_.*?]+
-FILENAMECHAR1 [a-zA-Z0-9_/.\\~]
-FILENAMECHAR [^][{}[:space:]():;]+
-HEX 0[xX][0-9a-fA-F]+[kKmM]?
-OCT 0[0-7]*[kKmM]?
-DEC [0-9]+[kKmM]?
-WHITE [[:space:]]+
-
-%option yylineno
-%option never-interactive
-%option noyywrap
-
-%x IGNORE
-
-%%
- if (unlikely (ld_scan_version_script))
- {
- ld_scan_version_script = -1;
- return kVERSION_SCRIPT;
- }
-
-^"#"ifdef/[[:space:]] { BEGIN (handle_ifdef ()); }
-^"#"else/[[:space:]\n] { eat_to_eol (true);
- push_state (skip_to_endif);
- BEGIN (IGNORE); }
-^"#"elifdef/[[:space:]] { eat_to_eol (false);
- push_state (skip_to_endif);
- BEGIN (IGNORE); }
-^"#"endif/[[:space:]\n] { eat_to_eol (true) ; }
-
-<IGNORE>^"#"ifdef/[[:space:]\n] { eat_to_eol (false);
- push_state (skip_to_endif); }
-<IGNORE>^"#"else/[[:space:]\n] { eat_to_eol (true);
- assert (prepdepth > 0);
- if (prepstate[prepdepth - 1] == skip_if)
- {
- /* Back to normal processing. */
- assert (prepdepth == 1);
- BEGIN (pop_state ());
- }
- }
-<IGNORE>^"#"elifdef/[[:space:]] { assert (prepdepth > 0);
- if (prepstate[prepdepth - 1] == skip_if)
- {
- /* Maybe this symbol is defined. */
- pop_state ();
- BEGIN (handle_ifdef ());
- }
- }
-<IGNORE>^"#"endif/[[:space:]\n] { eat_to_eol (true);
- BEGIN (pop_state ()); }
-<IGNORE>.|\n { /* nothing */ }
-
-
-"/*" { eat_comment (); }
-
-ALIGN { return kALIGN; }
-ENTRY { return kENTRY; }
-EXCLUDE_FILE { return kEXCLUDE_FILE; }
-"global:" { return kGLOBAL; }
-GROUP { return kGROUP; }
-INPUT { return kINPUT; }
-INTERP { return kINTERP; }
-KEEP { return kKEEP; }
-"local:" { return kLOCAL; }
-OUTPUT_FORMAT { return kOUTPUT_FORMAT; }
-PAGESIZE { return kPAGESIZE; }
-PROVIDE { return kPROVIDE; }
-SEARCH_DIR { return kSEARCH_DIR; }
-SEGMENT { return kSEGMENT; }
-SIZEOF_HEADERS { return kSIZEOF_HEADERS; }
-SORT { return kSORT; }
-VERSION { return kVERSION; }
-
-"["([RWX]){0,3}"]" { int cnt = 1 ;
- ldlval.num = 0;
- while (cnt < yyleng - 1)
- ldlval.num |= attrib_convert (yytext[cnt++]);
- return kMODE; }
-
-"{" { return '{'; }
-"}" { return '}'; }
-"(" { return '('; }
-")" { return ')'; }
-":" { return ':'; }
-";" { return ';'; }
-"=" { return '='; }
-"+" { ldlval.op = exp_plus; return kADD_OP; }
-"-" { ldlval.op = exp_minus; return kADD_OP; }
-"*" { return '*'; }
-"/" { ldlval.op = exp_div; return kMUL_OP; }
-"%" { ldlval.op = exp_mod; return kMUL_OP; }
-"&" { return '&'; }
-"|" { return '|'; }
-
-"," { return ','; }
-
-{HEX}|{OCT}|{DEC} { char *endp;
- ldlval.num = strtoumax (yytext, &endp, 0);
- if (*endp != '\0')
- {
- if (tolower (*endp) == 'k')
- ldlval.num *= 1024;
- else
- {
- assert (tolower (*endp) == 'm');
- ldlval.num *= 1024 * 1024;
- }
- }
- return kNUM; }
-
-{ID} { ldlval.str = obstack_strndup (&ld_state.smem,
- yytext, yyleng);
- return kID; }
-
-{FILENAMECHAR1}{FILENAMECHAR} { ldlval.str = obstack_strndup (&ld_state.smem,
- yytext, yyleng);
- return kFILENAME; }
-
-{WHITE} { /* IGNORE */ }
-
-. { invalid_char (*yytext); }
-
-%%
-
-static void
-eat_comment (void)
-{
- while (1)
- {
- int c = input ();
-
- while (c != '*' && c != EOF)
- c = input ();
-
- if (c == '*')
- {
- c = input ();
- while (c == '*')
- c = input ();
- if (c == '/')
- break;
- }
-
- if (c == EOF)
- {
- /* XXX Use the setjmp buffer and signal EOF in comment */
- error (0, 0, gettext ("EOF in comment"));
- break;
- }
- }
-}
-
-
-static void
-eat_to_eol (bool empty)
-{
- bool warned = false;
-
- while (1)
- {
- int c = input ();
-
- if (c == EOF)
- break;
- if (c == '\n')
- {
- ++yylineno;
- break;
- }
-
- if (empty && ! isspace (c) && ! warned)
- {
- error (0, 0, gettext ("%d: garbage at end of line"), yylineno);
- warned = true;
- }
- }
-}
-
-
-static int
-attrib_convert (int c)
-{
- if (c == 'X')
- return PF_X;
- if (c == 'W')
- return PF_W;
- assert (c == 'R');
- return PF_R;
-}
-
-
-static void
-push_state (enum prepstate state)
-{
- if (prepdepth >= MAX_PREPDEPTH)
- error (EXIT_FAILURE, 0, gettext ("%d: conditionals nested too deep"),
- yylineno);
-
- prepstate[prepdepth++] = state;
-}
-
-
-static int
-pop_state (void)
-{
- if (prepdepth == 0)
- error (0, 0, gettext ("%d: unexpected #endif"), yylineno);
- else
- --prepdepth;
-
- return prepdepth == 0 ? INITIAL : IGNORE;
-}
-
-
-static int
-handle_ifdef (void)
-{
- char idbuf[50];
- char *id = idbuf;
- size_t idlen = 0;
- size_t idmax = sizeof (idbuf);
- bool ignore_ws = true;
- bool defined = false;
- int result;
-
- while (1)
- {
- int c = input ();
-
- if (isspace (c) && ignore_ws)
- continue;
-
- if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
- && (idlen == 0 || c < '0' || c > '9'))
- {
- unput (c);
- break;
- }
-
- if (idlen == idmax)
- {
- char *newp = (char *) alloca (idmax *= 2);
- id = memcpy (newp, id, idlen);
- }
-
- id[idlen++] = c;
- ignore_ws = false;
- }
-
- /* XXX Compare in a better way. */
- if (idlen == 6 && strncmp (id, "SHARED", 6) == 0)
- defined = ld_state.file_type == dso_file_type;
-
- if (defined)
- result = INITIAL;
- else
- {
- push_state (skip_if);
- result = IGNORE;
- }
-
- return result;
-}
-
-
-static void
-invalid_char (int ch)
-{
- error (0, 0, (isascii (ch)
- ? gettext ("invalid character '%c' at line %d; ignored")
- : gettext ("invalid character '\\%o' at line %d; ignored")),
- ch, yylineno);
-}
-
-
-// Local Variables:
-// mode: C
-// End:
diff --git a/src/ldscript.c b/src/ldscript.c
deleted file mode 100644
index 0f70ca95..00000000
--- a/src/ldscript.c
+++ /dev/null
@@ -1,2220 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875c. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* 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
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 0
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-/* If NAME_PREFIX is specified substitute the variables and functions
- names. */
-#define yyparse ldparse
-#define yylex ldlex
-#define yyerror lderror
-#define yylval ldlval
-#define yychar ldchar
-#define yydebug lddebug
-#define yynerrs ldnerrs
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- kADD_OP = 258,
- kALIGN = 259,
- kENTRY = 260,
- kEXCLUDE_FILE = 261,
- kFILENAME = 262,
- kGLOBAL = 263,
- kGROUP = 264,
- kID = 265,
- kINPUT = 266,
- kINTERP = 267,
- kKEEP = 268,
- kLOCAL = 269,
- kMODE = 270,
- kMUL_OP = 271,
- kNUM = 272,
- kOUTPUT_FORMAT = 273,
- kPAGESIZE = 274,
- kPROVIDE = 275,
- kSEARCH_DIR = 276,
- kSEGMENT = 277,
- kSIZEOF_HEADERS = 278,
- kSORT = 279,
- kVERSION = 280,
- kVERSION_SCRIPT = 281,
- ADD_OP = 282,
- MUL_OP = 283
- };
-#endif
-#define kADD_OP 258
-#define kALIGN 259
-#define kENTRY 260
-#define kEXCLUDE_FILE 261
-#define kFILENAME 262
-#define kGLOBAL 263
-#define kGROUP 264
-#define kID 265
-#define kINPUT 266
-#define kINTERP 267
-#define kKEEP 268
-#define kLOCAL 269
-#define kMODE 270
-#define kMUL_OP 271
-#define kNUM 272
-#define kOUTPUT_FORMAT 273
-#define kPAGESIZE 274
-#define kPROVIDE 275
-#define kSEARCH_DIR 276
-#define kSEGMENT 277
-#define kSIZEOF_HEADERS 278
-#define kSORT 279
-#define kVERSION 280
-#define kVERSION_SCRIPT 281
-#define ADD_OP 282
-#define MUL_OP 283
-
-
-
-
-/* Copy the first part of user declarations. */
-#line 1 "/home/drepper/gnu/elfutils/src/ldscript.y"
-
-/* Parser for linker scripts.
- Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <error.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-
-/* The error handler. */
-static void yyerror (const char *s);
-
-/* Some helper functions we need to construct the data structures
- describing information from the file. */
-static struct expression *new_expr (int tag);
-static struct input_section_name *new_input_section_name (const char *name,
- bool sort_flag);
-static struct input_rule *new_input_rule (int tag);
-static struct output_rule *new_output_rule (int tag);
-static struct assignment *new_assignment (const char *variable,
- struct expression *expression,
- bool provide_flag);
-static void new_segment (int mode, struct output_rule *output_rule);
-static struct filename_list *new_filename_listelem (const char *string);
-static void add_inputfiles (struct filename_list *fnames);
-static struct id_list *new_id_listelem (const char *str);
-static struct version *new_version (struct id_list *local,
- struct id_list *global);
-static struct version *merge_versions (struct version *one,
- struct version *two);
-static void add_versions (struct version *versions);
-
-extern int yylex (void);
-
-
-/* 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
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 58 "/home/drepper/gnu/elfutils/src/ldscript.y"
-typedef union YYSTYPE {
- uintmax_t num;
- enum expression_tag op;
- char *str;
- struct expression *expr;
- struct input_section_name *sectionname;
- struct filemask_section_name *filemask_section_name;
- struct input_rule *input_rule;
- struct output_rule *output_rule;
- struct assignment *assignment;
- struct filename_list *filename_list;
- struct version *version;
- struct id_list *id_list;
-} YYSTYPE;
-/* Line 191 of yacc.c. */
-#line 213 "ldscript.c"
-# 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 214 of yacc.c. */
-#line 225 "ldscript.c"
-
-#if ! defined (yyoverflow) || YYERROR_VERBOSE
-
-# ifndef YYFREE
-# define YYFREE free
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# endif
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# define YYSTACK_ALLOC alloca
-# endif
-# else
-# if defined (alloca) || defined (_ALLOCA_H)
-# define YYSTACK_ALLOC alloca
-# else
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# 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
-{
- short 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 (short) + 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 \
- { \
- register YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (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 (0)
-
-#endif
-
-#if defined (__STDC__) || defined (__cplusplus)
- typedef signed char yysigned_char;
-#else
- typedef short yysigned_char;
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 30
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 198
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 39
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 22
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 62
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 146
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 283
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const unsigned char 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, 28, 2,
- 32, 33, 30, 2, 38, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 34,
- 2, 37, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 35, 27, 36, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 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, 29, 31
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const unsigned char yyprhs[] =
-{
- 0, 0, 3, 5, 8, 11, 13, 19, 25, 31,
- 37, 43, 49, 54, 59, 64, 69, 72, 74, 77,
- 82, 85, 89, 96, 99, 101, 103, 108, 111, 117,
- 119, 124, 129, 130, 135, 139, 143, 147, 151, 155,
- 159, 161, 163, 165, 167, 171, 173, 175, 176, 179,
- 181, 186, 192, 199, 202, 204, 207, 210, 214, 217,
- 219, 221, 223
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yysigned_char yyrhs[] =
-{
- 40, 0, -1, 41, -1, 26, 54, -1, 41, 42,
- -1, 42, -1, 5, 32, 10, 33, 34, -1, 21,
- 32, 59, 33, 34, -1, 19, 32, 17, 33, 34,
- -1, 12, 32, 59, 33, 34, -1, 22, 15, 35,
- 43, 36, -1, 22, 1, 35, 43, 36, -1, 9,
- 32, 52, 33, -1, 11, 32, 52, 33, -1, 25,
- 35, 54, 36, -1, 18, 32, 59, 33, -1, 43,
- 44, -1, 44, -1, 45, 34, -1, 10, 35, 46,
- 36, -1, 10, 34, -1, 10, 37, 51, -1, 20,
- 32, 10, 37, 51, 33, -1, 46, 47, -1, 47,
- -1, 48, -1, 13, 32, 48, 33, -1, 45, 34,
- -1, 60, 32, 50, 49, 33, -1, 10, -1, 24,
- 32, 10, 33, -1, 6, 32, 59, 33, -1, -1,
- 4, 32, 51, 33, -1, 32, 51, 33, -1, 51,
- 30, 51, -1, 51, 16, 51, -1, 51, 3, 51,
- -1, 51, 28, 51, -1, 51, 27, 51, -1, 17,
- -1, 10, -1, 23, -1, 19, -1, 52, 53, 59,
- -1, 59, -1, 38, -1, -1, 54, 55, -1, 55,
- -1, 35, 56, 36, 34, -1, 59, 35, 56, 36,
- 34, -1, 59, 35, 56, 36, 59, 34, -1, 56,
- 57, -1, 57, -1, 8, 58, -1, 14, 58, -1,
- 58, 60, 34, -1, 60, 34, -1, 7, -1, 10,
- -1, 59, -1, 30, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const unsigned short yyrline[] =
-{
- 0, 128, 128, 129, 133, 134, 137, 142, 146, 151,
- 156, 160, 166, 177, 179, 181, 185, 190, 194, 199,
- 211, 235, 237, 241, 246, 250, 255, 262, 269, 280,
- 282, 286, 289, 292, 297, 299, 305, 311, 317, 323,
- 329, 334, 339, 341, 345, 351, 355, 356, 359, 364,
- 368, 374, 380, 389, 391, 395, 397, 402, 408, 412,
- 414, 418, 420
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[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", "kADD_OP", "kALIGN", "kENTRY",
- "kEXCLUDE_FILE", "kFILENAME", "kGLOBAL", "kGROUP", "kID", "kINPUT",
- "kINTERP", "kKEEP", "kLOCAL", "kMODE", "kMUL_OP", "kNUM",
- "kOUTPUT_FORMAT", "kPAGESIZE", "kPROVIDE", "kSEARCH_DIR", "kSEGMENT",
- "kSIZEOF_HEADERS", "kSORT", "kVERSION", "kVERSION_SCRIPT", "'|'", "'&'",
- "ADD_OP", "'*'", "MUL_OP", "'('", "')'", "';'", "'{'", "'}'", "'='",
- "','", "$accept", "script_or_version", "file", "content",
- "outputsections", "outputsection", "assignment", "inputsections",
- "inputsection", "sectionname", "sort_opt_name", "exclude_opt", "expr",
- "filename_id_list", "comma_opt", "versionlist", "version",
- "version_stmt_list", "version_stmt", "filename_id_star_list",
- "filename_id", "filename_id_star", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const unsigned short 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, 124, 38, 282,
- 42, 283, 40, 41, 59, 123, 125, 61, 44
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const unsigned char yyr1[] =
-{
- 0, 39, 40, 40, 41, 41, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 43, 43, 44, 44,
- 44, 45, 45, 46, 46, 47, 47, 47, 48, 49,
- 49, 50, 50, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 52, 52, 53, 53, 54, 54,
- 55, 55, 55, 56, 56, 57, 57, 58, 58, 59,
- 59, 60, 60
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const unsigned char yyr2[] =
-{
- 0, 2, 1, 2, 2, 1, 5, 5, 5, 5,
- 5, 5, 4, 4, 4, 4, 2, 1, 2, 4,
- 2, 3, 6, 2, 1, 1, 4, 2, 5, 1,
- 4, 4, 0, 4, 3, 3, 3, 3, 3, 3,
- 1, 1, 1, 1, 3, 1, 1, 0, 2, 1,
- 4, 5, 6, 2, 1, 2, 2, 3, 2, 1,
- 1, 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 unsigned char yydefact[] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 59, 60, 0, 3, 49, 0,
- 1, 4, 0, 47, 45, 47, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 54, 48, 0, 0,
- 12, 46, 0, 13, 0, 15, 0, 0, 0, 0,
- 0, 17, 0, 0, 14, 62, 55, 61, 0, 56,
- 0, 53, 0, 6, 44, 9, 8, 7, 20, 0,
- 0, 0, 11, 16, 18, 10, 0, 58, 50, 0,
- 60, 0, 0, 0, 24, 25, 0, 0, 41, 40,
- 43, 42, 0, 21, 0, 57, 51, 0, 0, 27,
- 19, 23, 32, 0, 0, 0, 0, 0, 0, 0,
- 0, 52, 0, 0, 0, 0, 34, 37, 36, 39,
- 38, 35, 0, 26, 0, 29, 0, 0, 33, 22,
- 0, 0, 28, 31, 0, 30
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const short yydefgoto[] =
-{
- -1, 11, 12, 13, 60, 61, 62, 93, 94, 95,
- 137, 124, 103, 33, 52, 27, 28, 45, 46, 66,
- 67, 96
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -41
-static const short yypact[] =
-{
- 107, -28, -20, -13, 34, 77, 85, 88, 91, 33,
- 38, 123, 125, -41, 117, 52, 52, 52, 52, 114,
- 52, 100, 103, 38, -41, -41, 96, 38, -41, 110,
- -41, -41, 115, 64, -41, 67, 116, 118, 120, 127,
- 1, 1, 28, 84, 84, 36, -41, -41, 96, 128,
- -41, -41, 52, -41, 129, -41, 130, 131, 105, 134,
- 75, -41, 133, 79, -41, -41, 84, -41, 135, 84,
- 136, -41, 41, -41, -41, -41, -41, -41, -41, 83,
- 48, 151, -41, -41, -41, -41, 137, -41, -41, 44,
- 138, 140, 139, 17, -41, -41, 142, 144, -41, -41,
- -41, -41, 48, 54, 141, -41, -41, 143, 84, -41,
- -41, -41, 162, 48, -2, 48, 48, 48, 48, 48,
- 48, -41, 146, 148, 97, 6, -41, 54, 54, 58,
- 53, -1, 13, -41, 52, -41, 149, 150, -41, -41,
- 152, 172, -41, -41, 153, -41
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const short yypgoto[] =
-{
- -41, -41, -41, 175, 147, -40, 29, -41, 98, 76,
- -41, -41, 39, 173, -41, 167, -24, 145, 15, 154,
- -10, 32
-};
-
-/* 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 -1
-static const unsigned char yytable[] =
-{
- 29, 115, 115, 47, 14, 34, 34, 36, 37, 115,
- 39, 58, 15, 29, 116, 116, 115, 29, 47, 16,
- 83, 59, 116, 83, 24, 117, 118, 90, 119, 116,
- 91, 126, 29, 117, 118, 24, 119, 59, 25, 138,
- 117, 118, 74, 119, 43, 24, 139, 65, 25, 43,
- 44, 24, 97, 110, 25, 44, 115, 115, 98, 24,
- 71, 115, 25, 26, 64, 99, 17, 100, 23, 116,
- 116, 101, 70, 26, 116, 68, 68, 89, 106, 107,
- 102, 117, 118, 119, 119, 58, 118, 71, 119, 58,
- 24, 24, 21, 90, 25, 59, 91, 50, 86, 59,
- 53, 86, 51, 59, 43, 51, 22, 135, 92, 18,
- 44, 82, 1, 65, 65, 85, 2, 19, 3, 4,
- 20, 136, 92, 30, 140, 5, 6, 32, 7, 8,
- 1, 38, 9, 10, 2, 40, 3, 4, 41, 78,
- 79, 114, 80, 5, 6, 48, 7, 8, 49, 54,
- 9, 55, 125, 56, 127, 128, 129, 130, 131, 132,
- 57, 104, 73, 75, 76, 77, 81, 84, 123, 87,
- 88, 105, 108, 109, 112, 80, 113, 121, 120, 133,
- 134, 141, 144, 142, 122, 143, 145, 31, 63, 35,
- 42, 111, 0, 72, 0, 0, 0, 0, 69
-};
-
-static const short yycheck[] =
-{
- 10, 3, 3, 27, 32, 15, 16, 17, 18, 3,
- 20, 10, 32, 23, 16, 16, 3, 27, 42, 32,
- 60, 20, 16, 63, 7, 27, 28, 10, 30, 16,
- 13, 33, 42, 27, 28, 7, 30, 20, 10, 33,
- 27, 28, 52, 30, 8, 7, 33, 30, 10, 8,
- 14, 7, 4, 36, 10, 14, 3, 3, 10, 7,
- 45, 3, 10, 35, 36, 17, 32, 19, 35, 16,
- 16, 23, 36, 35, 16, 43, 44, 36, 34, 89,
- 32, 27, 28, 30, 30, 10, 28, 72, 30, 10,
- 7, 7, 1, 10, 10, 20, 13, 33, 66, 20,
- 33, 69, 38, 20, 8, 38, 15, 10, 79, 32,
- 14, 36, 5, 30, 30, 36, 9, 32, 11, 12,
- 32, 24, 93, 0, 134, 18, 19, 10, 21, 22,
- 5, 17, 25, 26, 9, 35, 11, 12, 35, 34,
- 35, 102, 37, 18, 19, 35, 21, 22, 33, 33,
- 25, 33, 113, 33, 115, 116, 117, 118, 119, 120,
- 33, 10, 34, 34, 34, 34, 32, 34, 6, 34,
- 34, 34, 32, 34, 32, 37, 32, 34, 37, 33,
- 32, 32, 10, 33, 108, 33, 33, 12, 41, 16,
- 23, 93, -1, 48, -1, -1, -1, -1, 44
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const unsigned char yystos[] =
-{
- 0, 5, 9, 11, 12, 18, 19, 21, 22, 25,
- 26, 40, 41, 42, 32, 32, 32, 32, 32, 32,
- 32, 1, 15, 35, 7, 10, 35, 54, 55, 59,
- 0, 42, 10, 52, 59, 52, 59, 59, 17, 59,
- 35, 35, 54, 8, 14, 56, 57, 55, 35, 33,
- 33, 38, 53, 33, 33, 33, 33, 33, 10, 20,
- 43, 44, 45, 43, 36, 30, 58, 59, 60, 58,
- 36, 57, 56, 34, 59, 34, 34, 34, 34, 35,
- 37, 32, 36, 44, 34, 36, 60, 34, 34, 36,
- 10, 13, 45, 46, 47, 48, 60, 4, 10, 17,
- 19, 23, 32, 51, 10, 34, 34, 59, 32, 34,
- 36, 47, 32, 32, 51, 3, 16, 27, 28, 30,
- 37, 34, 48, 6, 50, 51, 33, 51, 51, 51,
- 51, 51, 51, 33, 32, 10, 24, 49, 33, 33,
- 59, 32, 33, 33, 10, 33
-};
-
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
-#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; \
- goto yybackup; \
- } \
- else \
- { \
- yyerror ("syntax error: cannot back up");\
- YYERROR; \
- } \
-while (0)
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-/* YYLLOC_DEFAULT -- Compute the default location (before the actions
- are run). */
-
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- ((Current).first_line = (Rhs)[1].first_line, \
- (Current).first_column = (Rhs)[1].first_column, \
- (Current).last_line = (Rhs)[N].last_line, \
- (Current).last_column = (Rhs)[N].last_column)
-#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 (0)
-
-# define YYDSYMPRINT(Args) \
-do { \
- if (yydebug) \
- yysymprint Args; \
-} while (0)
-
-# define YYDSYMPRINTF(Title, Token, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yysymprint (stderr, \
- Token, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (0)
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_stack_print (short *bottom, short *top)
-#else
-static void
-yy_stack_print (bottom, top)
- short *bottom;
- short *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (/* Nothing. */; 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 (0)
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yy_reduce_print (int yyrule)
-#else
-static void
-yy_reduce_print (yyrule)
- int yyrule;
-#endif
-{
- int yyi;
- unsigned int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
- yyrule - 1, yylno);
- /* Print the symbols being reduced, and their result. */
- for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
- YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
- YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (Rule); \
-} while (0)
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YYDSYMPRINT(Args)
-# define YYDSYMPRINTF(Title, Token, 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
- SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#if defined (YYMAXDEPTH) && YYMAXDEPTH == 0
-# undef YYMAXDEPTH
-#endif
-
-#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. */
-static YYSIZE_T
-# if defined (__STDC__) || defined (__cplusplus)
-yystrlen (const char *yystr)
-# else
-yystrlen (yystr)
- const char *yystr;
-# endif
-{
- register const char *yys = yystr;
-
- while (*yys++ != '\0')
- continue;
-
- return yys - yystr - 1;
-}
-# 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. */
-static char *
-# if defined (__STDC__) || defined (__cplusplus)
-yystpcpy (char *yydest, const char *yysrc)
-# else
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-# endif
-{
- register char *yyd = yydest;
- register const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-#endif /* !YYERROR_VERBOSE */
-
-
-
-#if YYDEBUG
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yysymprint (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- if (yytype < YYNTOKENS)
- {
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-# ifdef YYPRINT
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# endif
- }
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- switch (yytype)
- {
- default:
- break;
- }
- YYFPRINTF (yyoutput, ")");
-}
-
-#endif /* ! YYDEBUG */
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-#if defined (__STDC__) || defined (__cplusplus)
-static void
-yydestruct (int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yytype, yyvaluep)
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- /* Pacify ``unused variable'' warnings. */
- (void) yyvaluep;
-
- 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 lookahead symbol. */
-int yychar;
-
-/* The semantic value of the lookahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-# if defined (__STDC__) || defined (__cplusplus)
-int yyparse (void *YYPARSE_PARAM)
-# else
-int yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-# endif
-#else /* ! YYPARSE_PARAM */
-#if defined (__STDC__) || defined (__cplusplus)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-
- register int yystate;
- register int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Lookahead token as an internal (translated) token number. */
- int yytoken = 0;
-
- /* 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. */
- short yyssa[YYINITDEPTH];
- short *yyss = yyssa;
- register short *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK (yyvsp--, yyssp--)
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
-
- /* When reducing, the number of symbols on the RHS of the reduced
- rule. */
- int yylen;
-
- 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;
- short *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 ("parser stack overflow",
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyoverflowlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyoverflowlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- short *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyoverflowlab;
- 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 lookahead token if we need one and don't already have one. */
-/* yyresume: */
-
- /* First try to decide what to do without reference to lookahead token. */
-
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead 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);
- YYDSYMPRINTF ("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;
-
- /* Shift the lookahead token. */
- YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken]));
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- yystate = yyn;
- 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 3:
-#line 130 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { add_versions (yyvsp[0].version); }
- break;
-
- case 6:
-#line 138 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- if (likely (ld_state.entry == NULL))
- ld_state.entry = yyvsp[-2].str;
- }
- break;
-
- case 7:
-#line 143 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- ld_new_searchdir (yyvsp[-2].str);
- }
- break;
-
- case 8:
-#line 147 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- if (likely (ld_state.pagesize == 0))
- ld_state.pagesize = yyvsp[-2].num;
- }
- break;
-
- case 9:
-#line 152 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- if (likely (ld_state.interp == NULL))
- ld_state.interp = yyvsp[-2].str;
- }
- break;
-
- case 10:
-#line 157 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- new_segment (yyvsp[-3].num, yyvsp[-1].output_rule);
- }
- break;
-
- case 11:
-#line 161 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- fputs_unlocked (gettext ("mode for segment invalid\n"),
- stderr);
- new_segment (0, yyvsp[-1].output_rule);
- }
- break;
-
- case 12:
-#line 167 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- /* First little optimization. If there is only one
- file in the group don't do anything. */
- if (yyvsp[-1].filename_list != yyvsp[-1].filename_list->next)
- {
- yyvsp[-1].filename_list->next->group_start = 1;
- yyvsp[-1].filename_list->group_end = 1;
- }
- add_inputfiles (yyvsp[-1].filename_list);
- }
- break;
-
- case 13:
-#line 178 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { add_inputfiles (yyvsp[-1].filename_list); }
- break;
-
- case 14:
-#line 180 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { add_versions (yyvsp[-1].version); }
- break;
-
- case 15:
-#line 182 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { /* XXX TODO */ }
- break;
-
- case 16:
-#line 186 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[0].output_rule->next = yyvsp[-1].output_rule->next;
- yyval.output_rule = yyvsp[-1].output_rule->next = yyvsp[0].output_rule;
- }
- break;
-
- case 17:
-#line 191 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.output_rule = yyvsp[0].output_rule; }
- break;
-
- case 18:
-#line 195 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.output_rule = new_output_rule (output_assignment);
- yyval.output_rule->val.assignment = yyvsp[-1].assignment;
- }
- break;
-
- case 19:
-#line 200 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.output_rule = new_output_rule (output_section);
- yyval.output_rule->val.section.name = yyvsp[-3].str;
- yyval.output_rule->val.section.input = yyvsp[-1].input_rule->next;
- if (ld_state.strip == strip_debug
- && ebl_debugscn_p (ld_state.ebl, yyvsp[-3].str))
- yyval.output_rule->val.section.ignored = true;
- else
- yyval.output_rule->val.section.ignored = false;
- yyvsp[-1].input_rule->next = NULL;
- }
- break;
-
- case 20:
-#line 212 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- /* This is a short cut for "ID { *(ID) }". */
- yyval.output_rule = new_output_rule (output_section);
- yyval.output_rule->val.section.name = yyvsp[-1].str;
- yyval.output_rule->val.section.input = new_input_rule (input_section);
- yyval.output_rule->val.section.input->next = NULL;
- yyval.output_rule->val.section.input->val.section =
- (struct filemask_section_name *)
- obstack_alloc (&ld_state.smem,
- sizeof (struct filemask_section_name));
- yyval.output_rule->val.section.input->val.section->filemask = NULL;
- yyval.output_rule->val.section.input->val.section->excludemask = NULL;
- yyval.output_rule->val.section.input->val.section->section_name =
- new_input_section_name (yyvsp[-1].str, false);
- yyval.output_rule->val.section.input->val.section->keep_flag = false;
- if (ld_state.strip == strip_debug
- && ebl_debugscn_p (ld_state.ebl, yyvsp[-1].str))
- yyval.output_rule->val.section.ignored = true;
- else
- yyval.output_rule->val.section.ignored = false;
- }
- break;
-
- case 21:
-#line 236 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.assignment = new_assignment (yyvsp[-2].str, yyvsp[0].expr, false); }
- break;
-
- case 22:
-#line 238 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.assignment = new_assignment (yyvsp[-3].str, yyvsp[-1].expr, true); }
- break;
-
- case 23:
-#line 242 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[0].input_rule->next = yyvsp[-1].input_rule->next;
- yyval.input_rule = yyvsp[-1].input_rule->next = yyvsp[0].input_rule;
- }
- break;
-
- case 24:
-#line 247 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.input_rule = yyvsp[0].input_rule; }
- break;
-
- case 25:
-#line 251 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.input_rule = new_input_rule (input_section);
- yyval.input_rule->val.section = yyvsp[0].filemask_section_name;
- }
- break;
-
- case 26:
-#line 256 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[-1].filemask_section_name->keep_flag = true;
-
- yyval.input_rule = new_input_rule (input_section);
- yyval.input_rule->val.section = yyvsp[-1].filemask_section_name;
- }
- break;
-
- case 27:
-#line 263 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.input_rule = new_input_rule (input_assignment);
- yyval.input_rule->val.assignment = yyvsp[-1].assignment;
- }
- break;
-
- case 28:
-#line 270 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.filemask_section_name = (struct filemask_section_name *)
- obstack_alloc (&ld_state.smem, sizeof (*yyval.filemask_section_name));
- yyval.filemask_section_name->filemask = yyvsp[-4].str;
- yyval.filemask_section_name->excludemask = yyvsp[-2].str;
- yyval.filemask_section_name->section_name = yyvsp[-1].sectionname;
- yyval.filemask_section_name->keep_flag = false;
- }
- break;
-
- case 29:
-#line 281 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.sectionname = new_input_section_name (yyvsp[0].str, false); }
- break;
-
- case 30:
-#line 283 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.sectionname = new_input_section_name (yyvsp[-1].str, true); }
- break;
-
- case 31:
-#line 287 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = yyvsp[-1].str; }
- break;
-
- case 32:
-#line 289 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = NULL; }
- break;
-
- case 33:
-#line 293 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_align);
- yyval.expr->val.child = yyvsp[-1].expr;
- }
- break;
-
- case 34:
-#line 298 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.expr = yyvsp[-1].expr; }
- break;
-
- case 35:
-#line 300 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_mult);
- yyval.expr->val.binary.left = yyvsp[-2].expr;
- yyval.expr->val.binary.right = yyvsp[0].expr;
- }
- break;
-
- case 36:
-#line 306 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (yyvsp[-1].op);
- yyval.expr->val.binary.left = yyvsp[-2].expr;
- yyval.expr->val.binary.right = yyvsp[0].expr;
- }
- break;
-
- case 37:
-#line 312 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (yyvsp[-1].op);
- yyval.expr->val.binary.left = yyvsp[-2].expr;
- yyval.expr->val.binary.right = yyvsp[0].expr;
- }
- break;
-
- case 38:
-#line 318 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_and);
- yyval.expr->val.binary.left = yyvsp[-2].expr;
- yyval.expr->val.binary.right = yyvsp[0].expr;
- }
- break;
-
- case 39:
-#line 324 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_or);
- yyval.expr->val.binary.left = yyvsp[-2].expr;
- yyval.expr->val.binary.right = yyvsp[0].expr;
- }
- break;
-
- case 40:
-#line 330 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_num);
- yyval.expr->val.num = yyvsp[0].num;
- }
- break;
-
- case 41:
-#line 335 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyval.expr = new_expr (exp_id);
- yyval.expr->val.str = yyvsp[0].str;
- }
- break;
-
- case 42:
-#line 340 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.expr = new_expr (exp_sizeof_headers); }
- break;
-
- case 43:
-#line 342 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.expr = new_expr (exp_pagesize); }
- break;
-
- case 44:
-#line 346 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- struct filename_list *newp = new_filename_listelem (yyvsp[0].str);
- newp->next = yyvsp[-2].filename_list->next;
- yyval.filename_list = yyvsp[-2].filename_list->next = newp;
- }
- break;
-
- case 45:
-#line 352 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.filename_list = new_filename_listelem (yyvsp[0].str); }
- break;
-
- case 48:
-#line 360 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[0].version->next = yyvsp[-1].version->next;
- yyval.version = yyvsp[-1].version->next = yyvsp[0].version;
- }
- break;
-
- case 49:
-#line 365 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.version = yyvsp[0].version; }
- break;
-
- case 50:
-#line 369 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[-2].version->versionname = "";
- yyvsp[-2].version->parentname = NULL;
- yyval.version = yyvsp[-2].version;
- }
- break;
-
- case 51:
-#line 375 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[-2].version->versionname = yyvsp[-4].str;
- yyvsp[-2].version->parentname = NULL;
- yyval.version = yyvsp[-2].version;
- }
- break;
-
- case 52:
-#line 381 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- yyvsp[-3].version->versionname = yyvsp[-5].str;
- yyvsp[-3].version->parentname = yyvsp[-1].str;
- yyval.version = yyvsp[-3].version;
- }
- break;
-
- case 53:
-#line 390 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.version = merge_versions (yyvsp[-1].version, yyvsp[0].version); }
- break;
-
- case 54:
-#line 392 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.version = yyvsp[0].version; }
- break;
-
- case 55:
-#line 396 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.version = new_version (NULL, yyvsp[0].id_list); }
- break;
-
- case 56:
-#line 398 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.version = new_version (yyvsp[0].id_list, NULL); }
- break;
-
- case 57:
-#line 403 "/home/drepper/gnu/elfutils/src/ldscript.y"
- {
- struct id_list *newp = new_id_listelem (yyvsp[-1].str);
- newp->next = yyvsp[-2].id_list->next;
- yyval.id_list = yyvsp[-2].id_list->next = newp;
- }
- break;
-
- case 58:
-#line 409 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.id_list = new_id_listelem (yyvsp[-1].str); }
- break;
-
- case 59:
-#line 413 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = yyvsp[0].str; }
- break;
-
- case 60:
-#line 415 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = yyvsp[0].str; }
- break;
-
- case 61:
-#line 419 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = yyvsp[0].str; }
- break;
-
- case 62:
-#line 421 "/home/drepper/gnu/elfutils/src/ldscript.y"
- { yyval.str = NULL; }
- break;
-
-
- }
-
-/* Line 1000 of yacc.c. */
-#line 1654 "ldscript.c"
-
- yyvsp -= yylen;
- yyssp -= yylen;
-
-
- 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
- yyn = yypact[yystate];
-
- if (YYPACT_NINF < yyn && yyn < YYLAST)
- {
- YYSIZE_T yysize = 0;
- int yytype = YYTRANSLATE (yychar);
- const char* yyprefix;
- char *yymsg;
- int yyx;
-
- /* 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;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 0;
-
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
- yycount += 1;
- if (yycount == 5)
- {
- yysize = 0;
- break;
- }
- }
- yysize += (sizeof ("syntax error, unexpected ")
- + yystrlen (yytname[yytype]));
- yymsg = (char *) YYSTACK_ALLOC (yysize);
- if (yymsg != 0)
- {
- char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
- yyp = yystpcpy (yyp, yytname[yytype]);
-
- if (yycount < 5)
- {
- yyprefix = ", expecting ";
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- yyp = yystpcpy (yyp, yyprefix);
- yyp = yystpcpy (yyp, yytname[yyx]);
- yyprefix = " or ";
- }
- }
- yyerror (yymsg);
- YYSTACK_FREE (yymsg);
- }
- else
- yyerror ("syntax error; also virtual memory exhausted");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror ("syntax error");
- }
-
-
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse lookahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* If at end of input, pop the error token,
- then the rest of the stack, then return failure. */
- if (yychar == YYEOF)
- for (;;)
- {
- YYPOPSTACK;
- if (yyssp == yyss)
- YYABORT;
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[*yyssp], yyvsp);
- }
- }
- else
- {
- YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc);
- yydestruct (yytoken, &yylval);
- yychar = YYEMPTY;
-
- }
- }
-
- /* Else will try to reuse lookahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
-#ifdef __GNUC__
- /* Pacify GCC when the user code never invokes YYERROR and the label
- yyerrorlab therefore never appears in user code. */
- if (0)
- goto yyerrorlab;
-#endif
-
- yyvsp -= yylen;
- yyssp -= yylen;
- 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;
-
- YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp);
- yydestruct (yystos[yystate], yyvsp);
- YYPOPSTACK;
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- YYDPRINTF ((stderr, "Shifting error token, "));
-
- *++yyvsp = yylval;
-
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here. |
-`----------------------------------------------*/
-yyoverflowlab:
- yyerror ("parser stack overflow");
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
- return yyresult;
-}
-
-
-#line 424 "/home/drepper/gnu/elfutils/src/ldscript.y"
-
-
-static void
-yyerror (const char *s)
-{
- error (0, 0, (ld_scan_version_script
- ? gettext ("while reading version script '%s': %s at line %d")
- : gettext ("while reading linker script '%s': %s at line %d")),
- ldin_fname, gettext (s), ldlineno);
-}
-
-
-static struct expression *
-new_expr (int tag)
-{
- struct expression *newp = (struct expression *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->tag = tag;
- return newp;
-}
-
-
-static struct input_section_name *
-new_input_section_name (const char *name, bool sort_flag)
-{
- struct input_section_name *newp = (struct input_section_name *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->name = name;
- newp->sort_flag = sort_flag;
- return newp;
-}
-
-
-static struct input_rule *
-new_input_rule (int tag)
-{
- struct input_rule *newp = (struct input_rule *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->tag = tag;
- newp->next = newp;
- return newp;
-}
-
-
-static struct output_rule *
-new_output_rule (int tag)
-{
- struct output_rule *newp = (struct output_rule *)
- memset (obstack_alloc (&ld_state.smem, sizeof (*newp)),
- '\0', sizeof (*newp));
-
- newp->tag = tag;
- newp->next = newp;
- return newp;
-}
-
-
-static struct assignment *
-new_assignment (const char *variable, struct expression *expression,
- bool provide_flag)
-{
- struct assignment *newp = (struct assignment *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->variable = variable;
- newp->expression = expression;
- newp->sym = NULL;
- newp->provide_flag = provide_flag;
-
- /* Insert the symbol into a hash table. We will later have to matc*/
- return newp;
-}
-
-
-static void
-new_segment (int mode, struct output_rule *output_rule)
-{
- struct output_segment *newp;
-
- newp
- = (struct output_segment *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- newp->mode = mode;
- newp->next = newp;
-
- newp->output_rules = output_rule->next;
- output_rule->next = NULL;
-
- /* Enqueue the output segment description. */
- if (ld_state.output_segments == NULL)
- ld_state.output_segments = newp;
- else
- {
- newp->next = ld_state.output_segments->next;
- ld_state.output_segments = ld_state.output_segments->next = newp;
- }
-
- /* If the output file should be stripped of all symbol set the flag
- in the structures of all output sections. */
- if (mode == 0 && ld_state.strip == strip_all)
- {
- struct output_rule *runp;
-
- for (runp = newp->output_rules; runp != NULL; runp = runp->next)
- if (runp->tag == output_section)
- runp->val.section.ignored = true;
- }
-}
-
-
-static struct filename_list *
-new_filename_listelem (const char *string)
-{
- struct filename_list *newp;
-
- /* We use calloc and not the obstack since this object can be freed soon. */
- newp = (struct filename_list *) xcalloc (1, sizeof (*newp));
- newp->name = string;
- newp->next = newp;
- return newp;
-}
-
-
-static void
-add_inputfiles (struct filename_list *fnames)
-{
- assert (fnames != NULL);
-
- if (ld_state.srcfiles == NULL)
- ld_state.srcfiles = fnames;
- else
- {
- struct filename_list *first = ld_state.srcfiles->next;
-
- ld_state.srcfiles->next = fnames->next;
- fnames->next = first;
- ld_state.srcfiles->next = fnames;
- }
-}
-
-
-static _Bool
-special_char_p (const char *str)
-{
- while (*str != '\0')
- {
- if (__builtin_expect (*str == '*', 0)
- || __builtin_expect (*str == '?', 0)
- || __builtin_expect (*str == '[', 0))
- return true;
-
- ++str;
- }
-
- return false;
-}
-
-
-static struct id_list *
-new_id_listelem (const char *str)
-{
- struct id_list *newp;
-
- newp = (struct id_list *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- if (str == NULL)
- newp->u.id_type = id_all;
- else if (__builtin_expect (special_char_p (str), false))
- newp->u.id_type = id_wild;
- else
- newp->u.id_type = id_str;
- newp->id = str;
- newp->next = newp;
-
- return newp;
-}
-
-
-static struct version *
-new_version (struct id_list *local, struct id_list *global)
-{
- struct version *newp;
-
- newp = (struct version *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- newp->next = newp;
- newp->local_names = local;
- newp->global_names = global;
- newp->versionname = NULL;
- newp->parentname = NULL;
-
- return newp;
-}
-
-
-static struct version *
-merge_versions (struct version *one, struct version *two)
-{
- assert (two->local_names == NULL || two->global_names == NULL);
-
- if (two->local_names != NULL)
- {
- if (one->local_names == NULL)
- one->local_names = two->local_names;
- else
- {
- two->local_names->next = one->local_names->next;
- one->local_names = one->local_names->next = two->local_names;
- }
- }
- else
- {
- if (one->global_names == NULL)
- one->global_names = two->global_names;
- else
- {
- two->global_names->next = one->global_names->next;
- one->global_names = one->global_names->next = two->global_names;
- }
- }
-
- return one;
-}
-
-
-static void
-add_id_list (const char *versionname, struct id_list *runp, _Bool local)
-{
- struct id_list *lastp = runp;
-
- if (runp == NULL)
- /* Nothing to do. */
- return;
-
- /* Convert into a simple single-linked list. */
- runp = runp->next;
- assert (runp != NULL);
- lastp->next = NULL;
-
- do
- if (runp->u.id_type == id_str)
- {
- struct id_list *curp;
- struct id_list *defp;
- unsigned long int hval = elf_hash (runp->id);
-
- curp = runp;
- runp = runp->next;
-
- defp = ld_version_str_tab_find (&ld_state.version_str_tab, hval, curp);
- if (defp != NULL)
- {
- /* There is already a version definition for this symbol. */
- while (strcmp (defp->u.s.versionname, versionname) != 0)
- {
- if (defp->next == NULL)
- {
- /* No version like this so far. */
- defp->next = curp;
- curp->u.s.local = local;
- curp->u.s.versionname = versionname;
- curp->next = NULL;
- defp = NULL;
- break;
- }
-
- defp = defp->next;
- }
-
- if (defp != NULL && defp->u.s.local != local)
- error (EXIT_FAILURE, 0, versionname[0] == '\0'
- ? gettext ("\
-symbol '%s' in declared both local and global for unnamed version")
- : gettext ("\
-symbol '%s' in declared both local and global for version '%s'"),
- runp->id, versionname);
- }
- else
- {
- /* This is the first version definition for this symbol. */
- ld_version_str_tab_insert (&ld_state.version_str_tab, hval, curp);
-
- curp->u.s.local = local;
- curp->u.s.versionname = versionname;
- curp->next = NULL;
- }
- }
- else if (runp->u.id_type == id_all)
- {
- if (local)
- {
- if (ld_state.default_bind_global)
- error (EXIT_FAILURE, 0,
- gettext ("default visibility set as local and global"));
- ld_state.default_bind_local = true;
- }
- else
- {
- if (ld_state.default_bind_local)
- error (EXIT_FAILURE, 0,
- gettext ("default visibility set as local and global"));
- ld_state.default_bind_global = true;
- }
-
- runp = runp->next;
- }
- else
- {
- assert (runp->u.id_type == id_wild);
- /* XXX TBI */
- abort ();
- }
- while (runp != NULL);
-}
-
-
-static void
-add_versions (struct version *versions)
-{
- struct version *lastp = versions;
-
- if (versions == NULL)
- return;
-
- /* Convert into a simple single-linked list. */
- versions = versions->next;
- assert (versions != NULL);
- lastp->next = NULL;
-
- do
- {
- struct version *oldp;
-
- add_id_list (versions->versionname, versions->local_names, true);
- add_id_list (versions->versionname, versions->global_names, false);
-
- oldp = versions;
- versions = versions->next;
- }
- while (versions != NULL);
-}
-
diff --git a/src/ldscript.h b/src/ldscript.h
deleted file mode 100644
index 6464d8da..00000000
--- a/src/ldscript.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* A Bison parser, made by GNU Bison 1.875c. */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 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 {
- kADD_OP = 258,
- kALIGN = 259,
- kENTRY = 260,
- kEXCLUDE_FILE = 261,
- kFILENAME = 262,
- kGLOBAL = 263,
- kGROUP = 264,
- kID = 265,
- kINPUT = 266,
- kINTERP = 267,
- kKEEP = 268,
- kLOCAL = 269,
- kMODE = 270,
- kMUL_OP = 271,
- kNUM = 272,
- kOUTPUT_FORMAT = 273,
- kPAGESIZE = 274,
- kPROVIDE = 275,
- kSEARCH_DIR = 276,
- kSEGMENT = 277,
- kSIZEOF_HEADERS = 278,
- kSORT = 279,
- kVERSION = 280,
- kVERSION_SCRIPT = 281,
- ADD_OP = 282,
- MUL_OP = 283
- };
-#endif
-#define kADD_OP 258
-#define kALIGN 259
-#define kENTRY 260
-#define kEXCLUDE_FILE 261
-#define kFILENAME 262
-#define kGLOBAL 263
-#define kGROUP 264
-#define kID 265
-#define kINPUT 266
-#define kINTERP 267
-#define kKEEP 268
-#define kLOCAL 269
-#define kMODE 270
-#define kMUL_OP 271
-#define kNUM 272
-#define kOUTPUT_FORMAT 273
-#define kPAGESIZE 274
-#define kPROVIDE 275
-#define kSEARCH_DIR 276
-#define kSEGMENT 277
-#define kSIZEOF_HEADERS 278
-#define kSORT 279
-#define kVERSION 280
-#define kVERSION_SCRIPT 281
-#define ADD_OP 282
-#define MUL_OP 283
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-#line 58 "/home/drepper/gnu/elfutils/src/ldscript.y"
-typedef union YYSTYPE {
- uintmax_t num;
- enum expression_tag op;
- char *str;
- struct expression *expr;
- struct input_section_name *sectionname;
- struct filemask_section_name *filemask_section_name;
- struct input_rule *input_rule;
- struct output_rule *output_rule;
- struct assignment *assignment;
- struct filename_list *filename_list;
- struct version *version;
- struct id_list *id_list;
-} YYSTYPE;
-/* Line 1275 of yacc.c. */
-#line 108 "ldscript.h"
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE ldlval;
-
-
-
diff --git a/src/ldscript.y b/src/ldscript.y
deleted file mode 100644
index 8f68078d..00000000
--- a/src/ldscript.y
+++ /dev/null
@@ -1,764 +0,0 @@
-%{
-/* Parser for linker scripts.
- Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <error.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-
-/* The error handler. */
-static void yyerror (const char *s);
-
-/* Some helper functions we need to construct the data structures
- describing information from the file. */
-static struct expression *new_expr (int tag);
-static struct input_section_name *new_input_section_name (const char *name,
- bool sort_flag);
-static struct input_rule *new_input_rule (int tag);
-static struct output_rule *new_output_rule (int tag);
-static struct assignment *new_assignment (const char *variable,
- struct expression *expression,
- bool provide_flag);
-static void new_segment (int mode, struct output_rule *output_rule);
-static struct filename_list *new_filename_listelem (const char *string);
-static void add_inputfiles (struct filename_list *fnames);
-static struct id_list *new_id_listelem (const char *str);
-static struct version *new_version (struct id_list *local,
- struct id_list *global);
-static struct version *merge_versions (struct version *one,
- struct version *two);
-static void add_versions (struct version *versions);
-
-extern int yylex (void);
-%}
-
-%union {
- uintmax_t num;
- enum expression_tag op;
- char *str;
- struct expression *expr;
- struct input_section_name *sectionname;
- struct filemask_section_name *filemask_section_name;
- struct input_rule *input_rule;
- struct output_rule *output_rule;
- struct assignment *assignment;
- struct filename_list *filename_list;
- struct version *version;
- struct id_list *id_list;
-}
-
-%token kADD_OP
-%token kALIGN
-%token kENTRY
-%token kEXCLUDE_FILE
-%token <str> kFILENAME
-%token kGLOBAL
-%token kGROUP
-%token <str> kID
-%token kINPUT
-%token kINTERP
-%token kKEEP
-%token kLOCAL
-%token <num> kMODE
-%token kMUL_OP
-%token <num> kNUM
-%token kOUTPUT_FORMAT
-%token kPAGESIZE
-%token kPROVIDE
-%token kSEARCH_DIR
-%token kSEGMENT
-%token kSIZEOF_HEADERS
-%token kSORT
-%token kVERSION
-%token kVERSION_SCRIPT
-
-%left '|'
-%left '&'
-%left ADD_OP
-%left MUL_OP '*'
-
-%type <op> kADD_OP
-%type <op> kMUL_OP
-%type <str> filename_id
-%type <str> filename_id_star
-%type <str> exclude_opt
-%type <expr> expr
-%type <sectionname> sort_opt_name
-%type <filemask_section_name> sectionname
-%type <input_rule> inputsection
-%type <input_rule> inputsections
-%type <output_rule> outputsection
-%type <output_rule> outputsections
-%type <assignment> assignment
-%type <filename_list> filename_id_list
-%type <version> versionlist
-%type <version> version
-%type <version> version_stmt_list
-%type <version> version_stmt
-%type <id_list> filename_id_star_list
-
-%expect 16
-
-%%
-
-script_or_version:
- file
- | kVERSION_SCRIPT versionlist
- { add_versions ($2); }
- ;
-
-file: file content
- | content
- ;
-
-content: kENTRY '(' kID ')' ';'
- {
- if (likely (ld_state.entry == NULL))
- ld_state.entry = $3;
- }
- | kSEARCH_DIR '(' filename_id ')' ';'
- {
- ld_new_searchdir ($3);
- }
- | kPAGESIZE '(' kNUM ')' ';'
- {
- if (likely (ld_state.pagesize == 0))
- ld_state.pagesize = $3;
- }
- | kINTERP '(' filename_id ')' ';'
- {
- if (likely (ld_state.interp == NULL))
- ld_state.interp = $3;
- }
- | kSEGMENT kMODE '{' outputsections '}'
- {
- new_segment ($2, $4);
- }
- | kSEGMENT error '{' outputsections '}'
- {
- fputs_unlocked (gettext ("mode for segment invalid\n"),
- stderr);
- new_segment (0, $4);
- }
- | kGROUP '(' filename_id_list ')'
- {
- /* First little optimization. If there is only one
- file in the group don't do anything. */
- if ($3 != $3->next)
- {
- $3->next->group_start = 1;
- $3->group_end = 1;
- }
- add_inputfiles ($3);
- }
- | kINPUT '(' filename_id_list ')'
- { add_inputfiles ($3); }
- | kVERSION '{' versionlist '}'
- { add_versions ($3); }
- | kOUTPUT_FORMAT '(' filename_id ')'
- { /* XXX TODO */ }
- ;
-
-outputsections: outputsections outputsection
- {
- $2->next = $1->next;
- $$ = $1->next = $2;
- }
- | outputsection
- { $$ = $1; }
- ;
-
-outputsection: assignment ';'
- {
- $$ = new_output_rule (output_assignment);
- $$->val.assignment = $1;
- }
- | kID '{' inputsections '}'
- {
- $$ = new_output_rule (output_section);
- $$->val.section.name = $1;
- $$->val.section.input = $3->next;
- if (ld_state.strip == strip_debug
- && ebl_debugscn_p (ld_state.ebl, $1))
- $$->val.section.ignored = true;
- else
- $$->val.section.ignored = false;
- $3->next = NULL;
- }
- | kID ';'
- {
- /* This is a short cut for "ID { *(ID) }". */
- $$ = new_output_rule (output_section);
- $$->val.section.name = $1;
- $$->val.section.input = new_input_rule (input_section);
- $$->val.section.input->next = NULL;
- $$->val.section.input->val.section =
- (struct filemask_section_name *)
- obstack_alloc (&ld_state.smem,
- sizeof (struct filemask_section_name));
- $$->val.section.input->val.section->filemask = NULL;
- $$->val.section.input->val.section->excludemask = NULL;
- $$->val.section.input->val.section->section_name =
- new_input_section_name ($1, false);
- $$->val.section.input->val.section->keep_flag = false;
- if (ld_state.strip == strip_debug
- && ebl_debugscn_p (ld_state.ebl, $1))
- $$->val.section.ignored = true;
- else
- $$->val.section.ignored = false;
- }
- ;
-
-assignment: kID '=' expr
- { $$ = new_assignment ($1, $3, false); }
- | kPROVIDE '(' kID '=' expr ')'
- { $$ = new_assignment ($3, $5, true); }
- ;
-
-inputsections: inputsections inputsection
- {
- $2->next = $1->next;
- $$ = $1->next = $2;
- }
- | inputsection
- { $$ = $1; }
- ;
-
-inputsection: sectionname
- {
- $$ = new_input_rule (input_section);
- $$->val.section = $1;
- }
- | kKEEP '(' sectionname ')'
- {
- $3->keep_flag = true;
-
- $$ = new_input_rule (input_section);
- $$->val.section = $3;
- }
- | assignment ';'
- {
- $$ = new_input_rule (input_assignment);
- $$->val.assignment = $1;
- }
- ;
-
-sectionname: filename_id_star '(' exclude_opt sort_opt_name ')'
- {
- $$ = (struct filemask_section_name *)
- obstack_alloc (&ld_state.smem, sizeof (*$$));
- $$->filemask = $1;
- $$->excludemask = $3;
- $$->section_name = $4;
- $$->keep_flag = false;
- }
- ;
-
-sort_opt_name: kID
- { $$ = new_input_section_name ($1, false); }
- | kSORT '(' kID ')'
- { $$ = new_input_section_name ($3, true); }
- ;
-
-exclude_opt: kEXCLUDE_FILE '(' filename_id ')'
- { $$ = $3; }
- |
- { $$ = NULL; }
- ;
-
-expr: kALIGN '(' expr ')'
- {
- $$ = new_expr (exp_align);
- $$->val.child = $3;
- }
- | '(' expr ')'
- { $$ = $2; }
- | expr '*' expr
- {
- $$ = new_expr (exp_mult);
- $$->val.binary.left = $1;
- $$->val.binary.right = $3;
- }
- | expr kMUL_OP expr
- {
- $$ = new_expr ($2);
- $$->val.binary.left = $1;
- $$->val.binary.right = $3;
- }
- | expr kADD_OP expr
- {
- $$ = new_expr ($2);
- $$->val.binary.left = $1;
- $$->val.binary.right = $3;
- }
- | expr '&' expr
- {
- $$ = new_expr (exp_and);
- $$->val.binary.left = $1;
- $$->val.binary.right = $3;
- }
- | expr '|' expr
- {
- $$ = new_expr (exp_or);
- $$->val.binary.left = $1;
- $$->val.binary.right = $3;
- }
- | kNUM
- {
- $$ = new_expr (exp_num);
- $$->val.num = $1;
- }
- | kID
- {
- $$ = new_expr (exp_id);
- $$->val.str = $1;
- }
- | kSIZEOF_HEADERS
- { $$ = new_expr (exp_sizeof_headers); }
- | kPAGESIZE
- { $$ = new_expr (exp_pagesize); }
- ;
-
-filename_id_list: filename_id_list comma_opt filename_id
- {
- struct filename_list *newp = new_filename_listelem ($3);
- newp->next = $1->next;
- $$ = $1->next = newp;
- }
- | filename_id
- { $$ = new_filename_listelem ($1); }
- ;
-
-comma_opt: ','
- |
- ;
-
-versionlist: versionlist version
- {
- $2->next = $1->next;
- $$ = $1->next = $2;
- }
- | version
- { $$ = $1; }
- ;
-
-version: '{' version_stmt_list '}' ';'
- {
- $2->versionname = "";
- $2->parentname = NULL;
- $$ = $2;
- }
- | filename_id '{' version_stmt_list '}' ';'
- {
- $3->versionname = $1;
- $3->parentname = NULL;
- $$ = $3;
- }
- | filename_id '{' version_stmt_list '}' filename_id ';'
- {
- $3->versionname = $1;
- $3->parentname = $5;
- $$ = $3;
- }
- ;
-
-version_stmt_list:
- version_stmt_list version_stmt
- { $$ = merge_versions ($1, $2); }
- | version_stmt
- { $$ = $1; }
- ;
-
-version_stmt: kGLOBAL filename_id_star_list
- { $$ = new_version (NULL, $2); }
- | kLOCAL filename_id_star_list
- { $$ = new_version ($2, NULL); }
- ;
-
-filename_id_star_list:
- filename_id_star_list filename_id_star ';'
- {
- struct id_list *newp = new_id_listelem ($2);
- newp->next = $1->next;
- $$ = $1->next = newp;
- }
- | filename_id_star ';'
- { $$ = new_id_listelem ($1); }
- ;
-
-filename_id: kFILENAME
- { $$ = $1; }
- | kID
- { $$ = $1; }
- ;
-
-filename_id_star: filename_id
- { $$ = $1; }
- | '*'
- { $$ = NULL; }
- ;
-
-%%
-
-static void
-yyerror (const char *s)
-{
- error (0, 0, (ld_scan_version_script
- ? gettext ("while reading version script '%s': %s at line %d")
- : gettext ("while reading linker script '%s': %s at line %d")),
- ldin_fname, gettext (s), ldlineno);
-}
-
-
-static struct expression *
-new_expr (int tag)
-{
- struct expression *newp = (struct expression *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->tag = tag;
- return newp;
-}
-
-
-static struct input_section_name *
-new_input_section_name (const char *name, bool sort_flag)
-{
- struct input_section_name *newp = (struct input_section_name *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->name = name;
- newp->sort_flag = sort_flag;
- return newp;
-}
-
-
-static struct input_rule *
-new_input_rule (int tag)
-{
- struct input_rule *newp = (struct input_rule *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->tag = tag;
- newp->next = newp;
- return newp;
-}
-
-
-static struct output_rule *
-new_output_rule (int tag)
-{
- struct output_rule *newp = (struct output_rule *)
- memset (obstack_alloc (&ld_state.smem, sizeof (*newp)),
- '\0', sizeof (*newp));
-
- newp->tag = tag;
- newp->next = newp;
- return newp;
-}
-
-
-static struct assignment *
-new_assignment (const char *variable, struct expression *expression,
- bool provide_flag)
-{
- struct assignment *newp = (struct assignment *)
- obstack_alloc (&ld_state.smem, sizeof (*newp));
-
- newp->variable = variable;
- newp->expression = expression;
- newp->sym = NULL;
- newp->provide_flag = provide_flag;
-
- /* Insert the symbol into a hash table. We will later have to matc*/
- return newp;
-}
-
-
-static void
-new_segment (int mode, struct output_rule *output_rule)
-{
- struct output_segment *newp;
-
- newp
- = (struct output_segment *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- newp->mode = mode;
- newp->next = newp;
-
- newp->output_rules = output_rule->next;
- output_rule->next = NULL;
-
- /* Enqueue the output segment description. */
- if (ld_state.output_segments == NULL)
- ld_state.output_segments = newp;
- else
- {
- newp->next = ld_state.output_segments->next;
- ld_state.output_segments = ld_state.output_segments->next = newp;
- }
-
- /* If the output file should be stripped of all symbol set the flag
- in the structures of all output sections. */
- if (mode == 0 && ld_state.strip == strip_all)
- {
- struct output_rule *runp;
-
- for (runp = newp->output_rules; runp != NULL; runp = runp->next)
- if (runp->tag == output_section)
- runp->val.section.ignored = true;
- }
-}
-
-
-static struct filename_list *
-new_filename_listelem (const char *string)
-{
- struct filename_list *newp;
-
- /* We use calloc and not the obstack since this object can be freed soon. */
- newp = (struct filename_list *) xcalloc (1, sizeof (*newp));
- newp->name = string;
- newp->next = newp;
- return newp;
-}
-
-
-static void
-add_inputfiles (struct filename_list *fnames)
-{
- assert (fnames != NULL);
-
- if (ld_state.srcfiles == NULL)
- ld_state.srcfiles = fnames;
- else
- {
- struct filename_list *first = ld_state.srcfiles->next;
-
- ld_state.srcfiles->next = fnames->next;
- fnames->next = first;
- ld_state.srcfiles->next = fnames;
- }
-}
-
-
-static _Bool
-special_char_p (const char *str)
-{
- while (*str != '\0')
- {
- if (__builtin_expect (*str == '*', 0)
- || __builtin_expect (*str == '?', 0)
- || __builtin_expect (*str == '[', 0))
- return true;
-
- ++str;
- }
-
- return false;
-}
-
-
-static struct id_list *
-new_id_listelem (const char *str)
-{
- struct id_list *newp;
-
- newp = (struct id_list *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- if (str == NULL)
- newp->u.id_type = id_all;
- else if (__builtin_expect (special_char_p (str), false))
- newp->u.id_type = id_wild;
- else
- newp->u.id_type = id_str;
- newp->id = str;
- newp->next = newp;
-
- return newp;
-}
-
-
-static struct version *
-new_version (struct id_list *local, struct id_list *global)
-{
- struct version *newp;
-
- newp = (struct version *) obstack_alloc (&ld_state.smem, sizeof (*newp));
- newp->next = newp;
- newp->local_names = local;
- newp->global_names = global;
- newp->versionname = NULL;
- newp->parentname = NULL;
-
- return newp;
-}
-
-
-static struct version *
-merge_versions (struct version *one, struct version *two)
-{
- assert (two->local_names == NULL || two->global_names == NULL);
-
- if (two->local_names != NULL)
- {
- if (one->local_names == NULL)
- one->local_names = two->local_names;
- else
- {
- two->local_names->next = one->local_names->next;
- one->local_names = one->local_names->next = two->local_names;
- }
- }
- else
- {
- if (one->global_names == NULL)
- one->global_names = two->global_names;
- else
- {
- two->global_names->next = one->global_names->next;
- one->global_names = one->global_names->next = two->global_names;
- }
- }
-
- return one;
-}
-
-
-static void
-add_id_list (const char *versionname, struct id_list *runp, _Bool local)
-{
- struct id_list *lastp = runp;
-
- if (runp == NULL)
- /* Nothing to do. */
- return;
-
- /* Convert into a simple single-linked list. */
- runp = runp->next;
- assert (runp != NULL);
- lastp->next = NULL;
-
- do
- if (runp->u.id_type == id_str)
- {
- struct id_list *curp;
- struct id_list *defp;
- unsigned long int hval = elf_hash (runp->id);
-
- curp = runp;
- runp = runp->next;
-
- defp = ld_version_str_tab_find (&ld_state.version_str_tab, hval, curp);
- if (defp != NULL)
- {
- /* There is already a version definition for this symbol. */
- while (strcmp (defp->u.s.versionname, versionname) != 0)
- {
- if (defp->next == NULL)
- {
- /* No version like this so far. */
- defp->next = curp;
- curp->u.s.local = local;
- curp->u.s.versionname = versionname;
- curp->next = NULL;
- defp = NULL;
- break;
- }
-
- defp = defp->next;
- }
-
- if (defp != NULL && defp->u.s.local != local)
- error (EXIT_FAILURE, 0, versionname[0] == '\0'
- ? gettext ("\
-symbol '%s' in declared both local and global for unnamed version")
- : gettext ("\
-symbol '%s' in declared both local and global for version '%s'"),
- runp->id, versionname);
- }
- else
- {
- /* This is the first version definition for this symbol. */
- ld_version_str_tab_insert (&ld_state.version_str_tab, hval, curp);
-
- curp->u.s.local = local;
- curp->u.s.versionname = versionname;
- curp->next = NULL;
- }
- }
- else if (runp->u.id_type == id_all)
- {
- if (local)
- {
- if (ld_state.default_bind_global)
- error (EXIT_FAILURE, 0,
- gettext ("default visibility set as local and global"));
- ld_state.default_bind_local = true;
- }
- else
- {
- if (ld_state.default_bind_local)
- error (EXIT_FAILURE, 0,
- gettext ("default visibility set as local and global"));
- ld_state.default_bind_global = true;
- }
-
- runp = runp->next;
- }
- else
- {
- assert (runp->u.id_type == id_wild);
- /* XXX TBI */
- abort ();
- }
- while (runp != NULL);
-}
-
-
-static void
-add_versions (struct version *versions)
-{
- struct version *lastp = versions;
-
- if (versions == NULL)
- return;
-
- /* Convert into a simple single-linked list. */
- versions = versions->next;
- assert (versions != NULL);
- lastp->next = NULL;
-
- do
- {
- struct version *oldp;
-
- add_id_list (versions->versionname, versions->local_names, true);
- add_id_list (versions->versionname, versions->global_names, false);
-
- oldp = versions;
- versions = versions->next;
- }
- while (versions != NULL);
-}
diff --git a/src/libld_elf_i386.map b/src/libld_elf_i386.map
deleted file mode 100644
index 703af6d8..00000000
--- a/src/libld_elf_i386.map
+++ /dev/null
@@ -1,7 +0,0 @@
-ELFUTILS_1.0 {
- global:
- elf_i386_ld_init;
-
- local:
- *;
-};
diff --git a/src/nm.c b/src/nm.c
deleted file mode 100644
index 1a297054..00000000
--- a/src/nm.c
+++ /dev/null
@@ -1,1302 +0,0 @@
-/* Print information from ELF file in human-readable form.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2000.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <ar.h>
-#include <argp.h>
-#include <assert.h>
-#include <ctype.h>
-#include <dwarf.h>
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <libdw.h>
-#include <libebl.h>
-#include <libintl.h>
-#include <locale.h>
-#include <mcheck.h>
-#include <obstack.h>
-#include <search.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include <system.h>
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-
-/* Values for the parameters which have no short form. */
-#define OPT_DEFINED 0x100
-#define OPT_MARK_WEAK 0x101
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
- { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
- { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
- 0 },
- { "dynamic", 'D', NULL, 0,
- N_("Display dynamic symbols instead of normal symbols"), 0 },
- { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
- { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
- { "print-armap", 's', NULL, 0,
- N_("Include index for symbols from archive members"), 0 },
-
- { NULL, 0, NULL, 0, N_("Output format:"), 0 },
- { "print-file-name", 'A', NULL, 0,
- N_("Print name of the input file before every symbol"), 0 },
- { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
- { "format", 'f', "FORMAT", 0,
- N_("Use the output format FORMAT. FORMAT can be `bsd', `sysv' or `posix'. The default is `sysv'"),
- 0 },
- { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
- { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
- { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
- { "mark-weak", OPT_MARK_WEAK, NULL, 0, N_("Mark weak symbols"), 0 },
- { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
-
- { NULL, 0, NULL, 0, N_("Output options:"), 0 },
- { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
- 0 },
- { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
- { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
- { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
- { NULL, 0, NULL, 0, NULL, 0 }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("List symbols from FILEs (a.out by default).");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("[FILE...]");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help, NULL
-};
-
-
-/* Print symbols in file named FNAME. */
-static int process_file (const char *fname, bool more_than_one);
-
-/* Handle content of archive. */
-static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
- const char *suffix);
-
-/* Handle ELF file. */
-static int handle_elf (Elf *elf, const char *prefix, const char *fname,
- const char *suffix);
-
-
-#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
-
-
-/* Internal representation of symbols. */
-typedef struct GElf_SymX
-{
- GElf_Sym sym;
- Elf32_Word xndx;
- char *where;
-} GElf_SymX;
-
-
-/* User-selectable options. */
-
-/* The selected output format. */
-static enum
-{
- format_sysv = 0,
- format_bsd,
- format_posix
-} format;
-
-/* Print defined, undefined, or both? */
-static bool hide_undefined;
-static bool hide_defined;
-
-/* Print local symbols also? */
-static bool hide_local;
-
-/* Nonzero if full filename should precede every symbol. */
-static bool print_file_name;
-
-/* If true print size of defined symbols in BSD format. */
-static bool print_size;
-
-/* If true print archive index. */
-static bool print_armap;
-
-/* If true reverse sorting. */
-static bool reverse_sort;
-
-/* Type of the section we are printing. */
-static GElf_Word symsec_type = SHT_SYMTAB;
-
-/* Sorting selection. */
-static enum
-{
- sort_name = 0,
- sort_numeric,
- sort_nosort
-} sort;
-
-/* Radix for printed numbers. */
-static enum
-{
- radix_hex = 0,
- radix_decimal,
- radix_octal
-} radix;
-
-/* If nonzero weak symbols are distinguished from global symbols by adding
- a `*' after the identifying letter for the symbol class and type. */
-static bool mark_weak;
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- int result = 0;
-
- /* Make memory leak detection possible. */
- mtrace ();
-
- /* We use no threads here which can interfere with handling a stream. */
- (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
- (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
- (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
-
- /* Set locale. */
- (void) setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- (void) bindtextdomain (PACKAGE, LOCALEDIR);
-
- /* Initialize the message catalog. */
- (void) textdomain (PACKAGE);
-
- /* Parse and process arguments. */
- (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- /* Tell the library which version we are expecting. */
- (void) elf_version (EV_CURRENT);
-
- if (remaining == argc)
- /* The user didn't specify a name so we use a.out. */
- result = process_file ("a.out", false);
- else
- {
- /* Process all the remaining files. */
- const bool more_than_one = remaining + 1 < argc;
-
- do
- result |= process_file (argv[remaining], more_than_one);
- while (++remaining < argc);
- }
-
- return result;
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, /*@unused@*/ struct argp_state *state)
-{
- fprintf (stream, "nm (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, /*@unused@*/ struct argp_state *state)
-{
- switch (key)
- {
- case 'a':
- /* XXX */
- break;
-
- case 'f':
- if (strcmp (arg, "bsd") == 0)
- format = format_bsd;
- else if (strcmp (arg, "posix") == 0)
- format = format_posix;
- else
- /* Be bug compatible. The BFD implementation also defaulted to
- using the SysV format if nothing else matches. */
- format = format_sysv;
- break;
-
- case 'g':
- hide_local = true;
- break;
-
- case 'n':
- sort = sort_numeric;
- break;
-
- case 'p':
- sort = sort_nosort;
- break;
-
- case 't':
- if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
- radix = radix_decimal;
- else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
- radix = radix_octal;
- else
- radix = radix_hex;
- break;
-
- case 'u':
- hide_undefined = false;
- hide_defined = true;
- break;
-
- case 'A':
- case 'o':
- print_file_name = true;
- break;
-
- case 'B':
- format = format_bsd;
- break;
-
- case 'D':
- symsec_type = SHT_DYNSYM;
- break;
-
- case 'P':
- format = format_posix;
- break;
-
- case OPT_DEFINED:
- hide_undefined = true;
- hide_defined = false;
- break;
-
- case OPT_MARK_WEAK:
- mark_weak = true;
- break;
-
- case 'S':
- print_size = true;
- break;
-
- case 's':
- print_armap = true;
- break;
-
- case 'r':
- reverse_sort = true;
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-static char *
-more_help (int key, const char *text, /*@unused@*/ void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-/* Open the file and determine the type. */
-static int
-process_file (const char *fname, bool more_than_one)
-{
- /* Open the file. */
- int fd = open (fname, O_RDONLY);
- if (fd == -1)
- {
- error (0, errno, fname);
- return 1;
- }
-
- /* Now get the ELF descriptor. */
- Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf != NULL)
- {
- if (elf_kind (elf) == ELF_K_ELF)
- {
- int result = handle_elf (elf, more_than_one ? "" : NULL,
- fname, NULL);
-
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
-
- if (close (fd) != 0)
- error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
-
- return result;
- }
- else if (elf_kind (elf) == ELF_K_AR)
- {
- int result = handle_ar (fd, elf, NULL, fname, NULL);
-
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
-
- if (close (fd) != 0)
- error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
-
- return result;
- }
-
- /* We cannot handle this type. Close the descriptor anyway. */
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
- }
-
- error (0, 0, gettext ("%s: File format not recognized"), fname);
-
- return 1;
-}
-
-
-static int
-handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
- const char *suffix)
-{
- size_t fname_len = strlen (fname) + 1;
- size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
- char new_prefix[prefix_len + fname_len + 2];
- size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
- char new_suffix[suffix_len + 2];
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
- int result = 0;
-
- char *cp = new_prefix;
- if (prefix != NULL)
- cp = stpcpy (cp, prefix);
- cp = stpcpy (cp, fname);
- stpcpy (cp, "[");
-
- cp = new_suffix;
- if (suffix != NULL)
- cp = stpcpy (cp, suffix);
- stpcpy (cp, "]");
-
- /* First print the archive index if this is wanted. */
- if (print_armap)
- {
- Elf_Arsym *arsym = elf_getarsym (elf, NULL);
-
- if (arsym != NULL)
- {
- Elf_Arhdr *arhdr = NULL;
- size_t arhdr_off = 0; /* Note: 0 is no valid offset. */
-
- puts (gettext("\nArchive index:"));
-
- while (arsym->as_off != 0)
- {
- if (arhdr_off != arsym->as_off
- && (elf_rand (elf, arsym->as_off) != arsym->as_off
- || (subelf = elf_begin (fd, cmd, elf)) == NULL
- || (arhdr = elf_getarhdr (subelf)) == NULL))
- {
- error (0, 0, gettext ("invalid offset %zu for symbol %s"),
- arsym->as_off, arsym->as_name);
- continue;
- }
-
- printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
-
- ++arsym;
- }
-
- if (elf_rand (elf, SARMAG) != SARMAG)
- {
- error (0, 0,
- gettext ("cannot reset archive offset to beginning"));
- return 1;
- }
- }
- }
-
- /* Process all the files contained in the archive. */
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- /* The the header for this element. */
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
-
- /* Skip over the index entries. */
- if (strcmp (arhdr->ar_name, "/") != 0
- && strcmp (arhdr->ar_name, "//") != 0)
- {
- if (elf_kind (subelf) == ELF_K_ELF)
- result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
- new_suffix);
- else if (elf_kind (subelf) == ELF_K_AR)
- result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
- new_suffix);
- else
- {
- error (0, 0, gettext ("%s%s%s: file format not recognized"),
- new_prefix, arhdr->ar_name, new_suffix);
- result = 1;
- }
- }
-
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (elf_end (subelf) != 0)
- INTERNAL_ERROR (fname);
- }
-
- return result;
-}
-
-
-/* Mapping of radix and binary class to length. */
-static const int length_map[2][3] =
-{
- [ELFCLASS32 - 1] =
- {
- [radix_hex] = 8,
- [radix_decimal] = 10,
- [radix_octal] = 11
- },
- [ELFCLASS64 - 1] =
- {
- [radix_hex] = 16,
- [radix_decimal] = 20,
- [radix_octal] = 22
- }
-};
-
-
-struct global_name
-{
- Dwarf_Global global;
- const char *name;
-};
-
-
-static int
-global_compare (const void *p1, const void *p2)
-{
- const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
- const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
-
- return strcmp (g1->name, g2->name);
-}
-
-
-static void *global_root;
-
-
-static int
-get_global (Dwarf *dbg, Dwarf_Global *global, void *arg)
-{
- tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
- sizeof (Dwarf_Global)),
- &global_root, global_compare);
-
- return DWARF_CB_OK;
-}
-
-
-struct local_name
-{
- const char *name;
- const char *file;
- Dwarf_Word lineno;
- Dwarf_Addr lowpc;
- Dwarf_Addr highpc;
-};
-
-
-static int
-local_compare (const void *p1, const void *p2)
-{
- struct local_name *g1 = (struct local_name *) p1;
- struct local_name *g2 = (struct local_name *) p2;
- int result;
-
- result = strcmp (g1->name, g2->name);
- if (result == 0)
- {
- if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
- {
- /* g2 is contained in g1. Update the data. */
- g2->lowpc = g1->lowpc;
- g2->highpc = g1->highpc;
- result = 0;
- }
- else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
- {
- /* g1 is contained in g2. Update the data. */
- g1->lowpc = g2->lowpc;
- g1->highpc = g2->highpc;
- result = 0;
- }
- else
- result = g1->lowpc < g2->lowpc ? -1 : 1;
- }
-
- return result;
-}
-
-
-static int
-get_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
-{
- Dwarf_Attribute locattr_mem;
- Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
- if (locattr == NULL)
- return 1;
-
- Dwarf_Loc *loc;
- size_t nloc;
- if (dwarf_getloclist (locattr, &loc, &nloc) != 0)
- return 1;
-
- /* Interpret the location expressions. */
- // XXX For now just the simple one:
- if (nloc == 1 && loc[0].atom == DW_OP_addr)
- {
- *lowpc = *highpc = loc[0].number;
- return 0;
- }
-
- return 1;
-}
-
-
-
-static void *local_root;
-
-
-static void
-get_local_names (Ebl *ebl, Dwarf *dbg)
-{
- Dwarf_Off offset = 0;
- Dwarf_Off old_offset;
- size_t hsize;
-
- while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
- NULL) == 0)
- {
- Dwarf_Die cudie_mem;
- Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
-
- /* If we cannot get the CU DIE there is no need to go on with
- this CU. */
- if (cudie == NULL)
- continue;
- /* This better be a CU DIE. */
- if (dwarf_tag (cudie) != DW_TAG_compile_unit)
- continue;
-
- /* Get the line information. */
- Dwarf_Files *files;
- size_t nfiles;
- if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
- continue;
-
- Dwarf_Die die_mem;
- Dwarf_Die *die = &die_mem;
- if (dwarf_child (cudie, die) == 0)
- /* Iterate over all immediate children of the CU DIE. */
- do
- {
- int tag = dwarf_tag (die);
- if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
- continue;
-
- /* We are interested in five attributes: name, decl_file,
- decl_line, low_pc, and high_pc. */
- Dwarf_Attribute attr_mem;
- Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
- const char *name = dwarf_formstring (attr);
- if (name == NULL)
- continue;
-
- Dwarf_Word fileidx;
- attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
- if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
- continue;
-
- Dwarf_Word lineno;
- attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
- if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
- continue;
-
- Dwarf_Addr lowpc;
- Dwarf_Addr highpc;
- if (tag == DW_TAG_subprogram)
- {
- if (dwarf_lowpc (die, &lowpc) != 0
- || dwarf_highpc (die, &highpc) != 0)
- continue;
- }
- else
- {
- if (get_var_range (die, &lowpc, &highpc) != 0)
- continue;
- }
-
- /* We have all the information. Create a record. */
- struct local_name *newp
- = (struct local_name *) xmalloc (sizeof (*newp));
- newp->name = name;
- newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
- newp->lineno = lineno;
- newp->lowpc = lowpc;
- newp->highpc = highpc;
-
- /* Since we cannot deallocate individual memory we do not test
- for duplicates in the tree. This should not happen anyway. */
- if (tsearch (newp, &local_root, local_compare) == NULL)
- error (EXIT_FAILURE, errno,
- gettext ("cannot create search tree"));
- }
- while (dwarf_siblingof (die, die) == 0);
- }
-}
-
-
-/* Show symbols in SysV format. */
-static void
-show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
- const char *prefix, const char *fname, const char *fullname,
- GElf_SymX *syms, size_t nsyms, int longest_name,
- int longest_where)
-{
- size_t shnum;
- if (elf_getshnum (ebl->elf, &shnum) < 0)
- INTERNAL_ERROR (fullname);
-
- bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
- const char **scnnames;
- if (scnnames_malloced)
- scnnames = (const char **) xmalloc (sizeof (const char *) * shnum);
- else
- scnnames = (const char **) alloca (sizeof (const char *) * shnum);
- /* Get the section header string table index. */
- size_t shstrndx;
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* Cache the section names. */
- Elf_Scn *scn = NULL;
- size_t cnt = 1;
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
-
- assert (elf_ndxscn (scn) == cnt++);
-
- scnnames[elf_ndxscn (scn)]
- = elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (scn, &shdr_mem)->sh_name);
- }
-
- int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
-
- /* We always print this prolog. */
- if (prefix == NULL || 1)
- printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
- else
- printf (gettext ("\n\nSymbols from %s[%s]:\n\n"), prefix, fname);
-
- /* The header line. */
- printf (gettext ("%*s%-*s %-*s Class Type %-*s %*s Section\n\n"),
- print_file_name ? (int) strlen (fullname) + 1: 0, "",
- longest_name, sgettext ("sysv|Name"),
- /* TRANS: the "sysv|" parts makes the string unique. */
- digits, sgettext ("sysv|Value"),
- /* TRANS: the "sysv|" parts makes the string unique. */
- digits, sgettext ("sysv|Size"),
- /* TRANS: the "sysv|" parts makes the string unique. */
- longest_where, sgettext ("sysv|Line"));
-
- /* Which format string to use (different radix for numbers). */
- const char *fmtstr;
- if (radix == radix_hex)
- fmtstr = "%-*s|%0*" PRIx64 "|%-6s|%-8s|%*" PRIx64 "|%*s|%s\n";
- else if (radix == radix_decimal)
- fmtstr = "%-*s|%*" PRId64 "|%-6s|%-8s|%*" PRId64 "|%*s|%s\n";
- else
- fmtstr = "%-*s|%0*" PRIo64 "|%-6s|%-8s|%*" PRIo64 "|%*s|%s\n";
-
- /* Iterate over all symbols. */
- for (cnt = 0; cnt < nsyms; ++cnt)
- {
- const char *symstr = elf_strptr (ebl->elf, strndx,
- syms[cnt].sym.st_name);
- char symbindbuf[50];
- char symtypebuf[50];
- char secnamebuf[1024];
-
- /* If we have to precede the line with the file name. */
- if (print_file_name)
- {
- fputs_unlocked (fullname, stdout);
- putchar_unlocked (':');
- }
-
- /* Print the actual string. */
- printf (fmtstr,
- longest_name, symstr,
- digits, syms[cnt].sym.st_value,
- ebl_symbol_binding_name (ebl,
- GELF_ST_BIND (syms[cnt].sym.st_info),
- symbindbuf, sizeof (symbindbuf)),
- ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
- symtypebuf, sizeof (symtypebuf)),
- digits, syms[cnt].sym.st_size, longest_where, syms[cnt].where,
- ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
- secnamebuf, sizeof (secnamebuf), scnnames,
- shnum));
- }
-
- if (scnnames_malloced)
- free (scnnames);
-}
-
-
-static char
-class_type_char (GElf_Sym *sym)
-{
- int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
-
- /* XXX Add support for architecture specific types and classes. */
- if (sym->st_shndx == SHN_ABS)
- return local_p ? 'a' : 'A';
-
- if (sym->st_shndx == SHN_UNDEF)
- /* Undefined symbols must be global. */
- return 'U';
-
- char result = "NDTSFB "[GELF_ST_TYPE (sym->st_info)];
-
- return local_p ? tolower (result) : result;
-}
-
-
-static void
-show_symbols_bsd (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
- const char *prefix, const char *fname, const char *fullname,
- GElf_SymX *syms, size_t nsyms)
-{
- int digits = length_map[gelf_getclass (elf) - 1][radix];
-
- if (prefix != NULL && ! print_file_name)
- printf ("\n%s:\n", fname);
-
- static const char *const fmtstrs[] =
- {
- [radix_hex] = "%0*" PRIx64 " %c%s %s\n",
- [radix_decimal] = "%*" PRId64 " %c%s %s\n",
- [radix_octal] = "%0*" PRIo64 " %c%s %s\n"
- };
- static const char *const sfmtstrs[] =
- {
- [radix_hex] = "%2$0*1$" PRIx64 " %7$0*6$" PRIx64 " %3$c%4$s %5$s\n",
- [radix_decimal] = "%2$*1$" PRId64 " %7$*6$" PRId64 " %3$c%4$s %5$s\n",
- [radix_octal] = "%2$0*1$" PRIo64 " %7$0*6$" PRIo64 " %3$c%4$s %5$s\n"
- };
-
- /* Iterate over all symbols. */
- for (size_t cnt = 0; cnt < nsyms; ++cnt)
- {
- const char *symstr = elf_strptr (elf, strndx, syms[cnt].sym.st_name);
-
- /* Printing entries with a zero-length name makes the output
- not very well parseable. Since these entries don't carry
- much information we leave them out. */
- if (symstr[0] == '\0')
- continue;
-
- /* If we have to precede the line with the file name. */
- if (print_file_name)
- {
- fputs_unlocked (fullname, stdout);
- putchar_unlocked (':');
- }
-
- if (syms[cnt].sym.st_shndx == SHN_UNDEF)
- printf ("%*s U%s %s\n",
- digits, "",
- mark_weak
- ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
- ? "*" : " ")
- : "",
- elf_strptr (elf, strndx, syms[cnt].sym.st_name));
- else
- printf (print_size ? sfmtstrs[radix] : fmtstrs[radix],
- digits, syms[cnt].sym.st_value,
- class_type_char (&syms[cnt].sym),
- mark_weak
- ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
- ? "*" : " ")
- : "",
- elf_strptr (elf, strndx, syms[cnt].sym.st_name),
- digits, (uint64_t) syms[cnt].sym.st_size);
- }
-}
-
-
-static void
-show_symbols_posix (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
- const char *prefix, const char *fname,
- const char *fullname, GElf_SymX *syms, size_t nsyms)
-{
- if (prefix != NULL && ! print_file_name)
- printf ("%s:\n", fullname);
-
- const char *fmtstr;
- if (radix == radix_hex)
- fmtstr = "%s %c%s %0*" PRIx64 " %0*" PRIx64 "\n";
- else if (radix == radix_decimal)
- fmtstr = "%s %c%s %*" PRId64 " %*" PRId64 "\n";
- else
- fmtstr = "%s %c%s %0*" PRIo64 " %0*" PRIo64 "\n";
-
- int digits = length_map[gelf_getclass (elf) - 1][radix];
-
- /* Iterate over all symbols. */
- for (size_t cnt = 0; cnt < nsyms; ++cnt)
- {
- const char *symstr = elf_strptr (elf, strndx, syms[cnt].sym.st_name);
-
- /* Printing entries with a zero-length name makes the output
- not very well parseable. Since these entries don't carry
- much information we leave them out. */
- if (symstr[0] == '\0')
- continue;
-
- /* If we have to precede the line with the file name. */
- if (print_file_name)
- {
- fputs_unlocked (fullname, stdout);
- putchar_unlocked (':');
- putchar_unlocked (' ');
- }
-
- printf (fmtstr,
- symstr,
- class_type_char (&syms[cnt].sym),
- mark_weak
- ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK ? "*" : " ")
- : "",
- digits, syms[cnt].sym.st_value,
- digits, syms[cnt].sym.st_size);
- }
-}
-
-
-/* Maximum size of memory we allocate on the stack. */
-#define MAX_STACK_ALLOC 65536
-
-static void
-show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
- GElf_Shdr *shdr, const char *prefix, const char *fname,
- const char *fullname)
-{
- int sort_by_name (const void *p1, const void *p2)
- {
- GElf_SymX *s1 = (GElf_SymX *) p1;
- GElf_SymX *s2 = (GElf_SymX *) p2;
- int result;
-
- result = strcmp (elf_strptr (ebl->elf, shdr->sh_link, s1->sym.st_name),
- elf_strptr (ebl->elf, shdr->sh_link, s2->sym.st_name));
-
- return reverse_sort ? -result : result;
- }
-
- int sort_by_address (const void *p1, const void *p2)
- {
- GElf_SymX *s1 = (GElf_SymX *) p1;
- GElf_SymX *s2 = (GElf_SymX *) p2;
-
- int result = (s1->sym.st_value < s2->sym.st_value
- ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
-
- return reverse_sort ? -result : result;
- }
-
- /* Get the section header string table index. */
- size_t shstrndx;
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* The section is that large. */
- size_t size = shdr->sh_size;
- /* One entry is this large. */
- size_t entsize = shdr->sh_entsize;
-
- /* Consistency checks. */
- if (entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, ehdr->e_version))
- error (0, 0,
- gettext ("%s: entry size in section `%s' is not what we expect"),
- fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
- else if (size % entsize != 0)
- error (0, 0,
- gettext ("%s: size of section `%s' is not multiple of entry size"),
- fullname, elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
-
- /* Compute number of entries. Handle buggy entsize values. */
- size_t nentries = size / (entsize ?: 1);
-
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
- struct obstack whereob;
- obstack_init (&whereob);
-
- /* Get a DWARF debugging descriptor. It's no problem if this isn't
- possible. We just won't print any line number information. */
- Dwarf *dbg = NULL;
- if (format == format_sysv)
- {
- dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
- if (dbg != NULL)
- {
- (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
-
- get_local_names (ebl, dbg);
- }
- }
-
- /* Allocate the memory.
-
- XXX We can use a dirty trick here. Since GElf_Sym == Elf64_Sym we
- can use the data memory instead of copying again if what we read
- is a 64 bit file. */
- GElf_SymX *sym_mem;
- if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
- sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
- else
- sym_mem = (GElf_SymX *) xmalloc (nentries * sizeof (GElf_SymX));
-
- /* Get the data of the section. */
- Elf_Data *data = elf_getdata (scn, NULL);
- Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
- if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
- INTERNAL_ERROR (fullname);
-
- /* Iterate over all symbols. */
- int longest_name = 4;
- int longest_where = 4;
- size_t nentries_used = 0;
- for (size_t cnt = 0; cnt < nentries; ++cnt)
- {
- GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
- &sym_mem[nentries_used].sym,
- &sym_mem[nentries_used].xndx);
- if (sym == NULL)
- INTERNAL_ERROR (fullname);
-
- /* Filter out administrative symbols without a name and those
- deselected by ther user with command line options. */
- if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
- || (hide_defined && sym->st_shndx != SHN_UNDEF)
- || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
- continue;
-
- sym_mem[nentries_used].where = "";
- if (format == format_sysv)
- {
- const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
- sym->st_name);
-
- longest_name = MAX ((size_t) longest_name, strlen (symstr));
-
- if (sym->st_shndx != SHN_UNDEF
- && GELF_ST_BIND (sym->st_info) != STB_LOCAL
- && global_root != NULL)
- {
- Dwarf_Global fake = { .name = symstr };
- Dwarf_Global **found = tfind (&fake, &global_root,
- global_compare);
- if (found != NULL)
- {
- Dwarf_Die die_mem;
- Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
- &die_mem);
-
- Dwarf_Die cudie_mem;
- Dwarf_Die *cudie = NULL;
-
- Dwarf_Addr lowpc;
- Dwarf_Addr highpc;
- if (die != NULL
- && dwarf_lowpc (die, &lowpc) == 0
- && lowpc <= sym->st_value
- && dwarf_highpc (die, &highpc) == 0
- && highpc > sym->st_value)
- cudie = dwarf_offdie (dbg, (*found)->cu_offset,
- &cudie_mem);
- if (cudie != NULL)
- {
- Dwarf_Line *line = dwarf_getsrc_die (cudie,
- sym->st_value);
- if (line != NULL)
- {
- /* We found the line. */
- int lineno;
- (void) dwarf_lineno (line, &lineno);
- int n;
- n = obstack_printf (&whereob, "%s:%d%c",
- basename (dwarf_linesrc (line,
- NULL,
- NULL)),
- lineno, '\0');
- sym_mem[nentries_used].where
- = obstack_finish (&whereob);
-
- /* The return value of obstack_print included the
- NUL byte, so subtract one. */
- if (--n > (int) longest_where)
- longest_where = (size_t) n;
- }
- }
- }
- }
-
- /* Try to find the symol among the local symbols. */
- if (sym_mem[nentries_used].where[0] == '\0')
- {
- struct local_name fake =
- {
- .name = symstr,
- .lowpc = sym->st_value,
- .highpc = sym->st_value,
- };
- struct local_name **found = tfind (&fake, &local_root,
- local_compare);
- if (found != NULL)
- {
- /* We found the line. */
- int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
- basename ((*found)->file),
- (*found)->lineno,
- '\0');
- sym_mem[nentries_used].where = obstack_finish (&whereob);
-
- /* The return value of obstack_print included the
- NUL byte, so subtract one. */
- if (--n > (int) longest_where)
- longest_where = (size_t) n;
- }
- }
- }
-
- /* We use this entry. */
- ++nentries_used;
- }
- /* Now we know the exact number. */
- nentries = nentries_used;
-
- /* Sort the entries according to the users wishes. */
- if (sort == sort_name)
- qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
- else if (sort == sort_numeric)
- qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
-
- /* Finally print according to the users selection. */
- switch (format)
- {
- case format_sysv:
- show_symbols_sysv (ebl, shdr->sh_link, prefix, fname,
- fullname, sym_mem, nentries, longest_name,
- longest_where);
- break;
-
- case format_bsd:
- show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname,
- fullname, sym_mem, nentries);
- break;
-
- case format_posix:
- default:
- assert (format == format_posix);
- show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fname,
- fullname, sym_mem, nentries);
- break;
- }
-
- /* Free all memory. */
- if (nentries * sizeof (GElf_Sym) >= MAX_STACK_ALLOC)
- free (sym_mem);
-
- obstack_free (&whereob, NULL);
-
- if (dbg != NULL)
- {
- tdestroy (global_root, free);
- global_root = NULL;
-
- tdestroy (local_root, free);
- local_root = NULL;
-
- (void) dwarf_end (dbg);
- }
-}
-
-
-static int
-handle_elf (Elf *elf, const char *prefix, const char *fname,
- const char *suffix)
-{
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
- size_t fname_len = strlen (fname) + 1;
- char fullname[prefix_len + 1 + fname_len + suffix_len];
- char *cp = fullname;
- Elf_Scn *scn = NULL;
- int any = 0;
- int result = 0;
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr;
- Ebl *ebl;
-
- /* Get the backend for this object file type. */
- ebl = ebl_openbackend (elf);
-
- /* We need the ELF header in a few places. */
- ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr == NULL)
- INTERNAL_ERROR (fullname);
-
- /* If we are asked to print the dynamic symbol table and this is
- executable or dynamic executable, fail. */
- if (symsec_type == SHT_DYNSYM
- && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- {
- /* XXX Add machine specific object file types. */
- error (0, 0, gettext ("%s%s%s%s: Invalid operation"),
- prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
- result = 1;
- goto out;
- }
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- cp = mempcpy (cp, prefix, prefix_len);
- cp = mempcpy (cp, fname, fname_len);
- if (suffix != NULL)
- memcpy (cp - 1, suffix, suffix_len + 1);
-
- /* Find the symbol table.
-
- XXX Can there be more than one? Do we print all? Currently we do. */
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr == NULL)
- INTERNAL_ERROR (fullname);
-
- if (shdr->sh_type == symsec_type)
- {
- Elf_Scn *xndxscn = NULL;
-
- /* We have a symbol table. First make sure we remember this. */
- any = 1;
-
- /* Look for an extended section index table for this section. */
- if (symsec_type == SHT_SYMTAB)
- {
- size_t scnndx = elf_ndxscn (scn);
-
- while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
- {
- GElf_Shdr xndxshdr_mem;
- GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
-
- if (xndxshdr == NULL)
- INTERNAL_ERROR (fullname);
-
- if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
- && xndxshdr->sh_link == scnndx)
- break;
- }
- }
-
- show_symbols (ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
- fullname);
- }
- }
-
- if (! any)
- {
- error (0, 0, gettext ("%s%s%s: no symbols"),
- prefix ?: "", prefix ? ":" : "", fname);
- result = 1;
- }
-
- out:
- /* Close the ELF backend library descriptor. */
- ebl_closebackend (ebl);
-
- return result;
-}
diff --git a/src/none_ld.c b/src/none_ld.c
deleted file mode 100644
index fb0f0fb2..00000000
--- a/src/none_ld.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Nothing here. This is just a testimony of automake inflexibility. */
diff --git a/src/readelf.c b/src/readelf.c
deleted file mode 100644
index 6129e29d..00000000
--- a/src/readelf.c
+++ /dev/null
@@ -1,4541 +0,0 @@
-/* Print information from ELF file in human-readable form.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 1999.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <assert.h>
-#include <dwarf.h>
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <langinfo.h>
-#include <libdw.h>
-#include <libebl.h>
-#include <libintl.h>
-#include <locale.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include <system.h>
-#include "../libdw/libdwP.h"
-#include "../libdw/memory-access.h"
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { NULL, 0, NULL, 0, N_("Output selection:") },
- { "all", 'a', NULL, 0, N_("Equivalent to: -h -l") },
- { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment") },
- { "file-header", 'h', NULL, 0, N_("Display the ELF file header") },
- { "histogram", 'I', NULL, 0,
- N_("Display histogram of bucket list lengths") },
- { "program-headers", 'l', NULL, 0, N_("Display the program headers") },
- { "relocs", 'r', NULL, 0, N_("Display relocations") },
- { "section-headers", 'S', NULL, 0, N_("Display the sections' header") },
- { "symbols", 's', NULL, 0, N_("Display the symbol table") },
- { "version-info", 'V', NULL, 0, N_("Display versioning information") },
- { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
- N_("Display DWARF section content. SECTION can be one of abbrev, "
- "aranges, frame, info, loc, line, pubnames, str, or macinfo.") },
- { "notes", 'n', NULL, 0, N_("Display the core notes") },
- { "arch-specific", 'A', NULL, 0,
- N_("Display architecture specific information (if any)") },
-
- { NULL, 0, NULL, 0, N_("Output control:") },
-
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("\
-Print information from ELF file in human-readable form.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("FILE...");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help
-};
-
-
-/* Flags set by the option controlling the output. */
-
-/* True if any of the control options is set. */
-static bool any_control_option;
-
-/* True if dynamic segment should be printed. */
-static bool print_dynamic_table;
-
-/* True if the file header should be printed. */
-static bool print_file_header;
-
-/* True if the program headers should be printed. */
-static bool print_program_header;
-
-/* True if relocations should be printed. */
-static bool print_relocations;
-
-/* True if the section headers should be printed. */
-static bool print_section_header;
-
-/* True if the symbol table should be printed. */
-static bool print_symbol_table;
-
-/* True if the version information should be printed. */
-static bool print_version_info;
-
-/* True if section groups should be printed. */
-static bool print_section_groups;
-
-/* True if bucket list length histogram should be printed. */
-static bool print_histogram;
-
-/* True if the architecture specific data should be printed. */
-static bool print_arch;
-
-/* True if note section content should be printed. */
-static bool print_notes;
-
-/* Select printing of debugging sections. */
-static enum section_e
-{
- section_abbrev = 1, /* .debug_abbrev */
- section_aranges = 2, /* .debug_aranges */
- section_frame = 4, /* .debug_frame or .eh_frame */
- section_info = 8, /* .debug_info */
- section_line = 16, /* .debug_line */
- section_loc = 32, /* .debug_loc */
- section_pubnames = 64,/* .debug_pubnames */
- section_str = 128, /* .debug_str */
- section_macinfo = 256,/* .debug_macinfo */
- section_all = (section_abbrev | section_aranges | section_frame
- | section_info | section_line | section_loc
- | section_pubnames | section_str | section_macinfo)
-} print_debug_sections;
-
-/* Number of sections in the file. */
-static size_t shnum;
-
-
-/* Declarations of local functions. */
-static void process_file (int fd, Elf *elf, const char *prefix,
- const char *fname, bool only_one);
-static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
- bool only_one);
-static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
-static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type);
-static void handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr);
-static void handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr);
-static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
-static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr);
-static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
-static void print_liblist (Ebl *ebl, GElf_Ehdr *ehdr);
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- bool only_one;
-
- /* Set locale. */
- setlocale (LC_ALL, "");
-
- /* Initialize the message catalog. */
- textdomain (PACKAGE);
-
- /* Parse and process arguments. */
- argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- /* If no control option or no ELF file is given punt. */
- if ((any_control_option == 0 && print_debug_sections == 0)
- || remaining >= argc)
- {
- argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
- program_invocation_short_name);
- exit (1);
- }
-
- /* Before we start tell the ELF library which version we are using. */
- elf_version (EV_CURRENT);
-
- /* Now process all the files given at the command line. */
- only_one = remaining + 1 == argc;
- do
- {
- int fd;
- Elf *elf;
-
- /* Open the file. */
- fd = open (argv[remaining], O_RDONLY);
- if (fd == -1)
- {
- error (0, errno, gettext ("cannot open input file"));
- continue;
- }
-
- /* Create an `Elf' descriptor. */
- elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"),
- elf_errmsg (-1));
- else
- {
- process_file (fd, elf, NULL, argv[remaining], only_one);
-
- /* Now we can close the descriptor. */
- if (elf_end (elf) != 0)
- error (0, 0, gettext ("error while closing Elf descriptor: %s"),
- elf_errmsg (-1));
- }
-
- close (fd);
- }
- while (++remaining < argc);
-
- return error_message_count != 0;
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'a':
- print_file_header = true;
- print_program_header = true;
- print_relocations = true;
- print_section_header = true;
- print_symbol_table = true;
- print_version_info = true;
- print_dynamic_table = true;
- print_section_groups = true;
- print_histogram = true;
- print_arch = true;
- print_notes = true;
- any_control_option = true;
- break;
- case 'A':
- print_arch = true;
- any_control_option = true;
- break;
- case 'd':
- print_dynamic_table = true;
- any_control_option = true;
- break;
- case 'g':
- print_section_groups = true;
- any_control_option = true;
- break;
- case 'h':
- print_file_header = true;
- any_control_option = true;
- break;
- case 'I':
- print_histogram = true;
- any_control_option = true;
- break;
- case 'l':
- print_program_header = true;
- any_control_option = true;
- break;
- case 'n':
- print_notes = true;
- any_control_option = true;
- break;
- case 'r':
- print_relocations = true;
- any_control_option = true;
- break;
- case 'S':
- print_section_header = true;
- any_control_option = true;
- break;
- case 's':
- print_symbol_table = true;
- any_control_option = true;
- break;
- case 'V':
- print_version_info = true;
- any_control_option = true;
- break;
- case 'w':
- if (arg == NULL)
- print_debug_sections = section_all;
- else if (strcmp (arg, "abbrev") == 0)
- print_debug_sections |= section_abbrev;
- else if (strcmp (arg, "aranges") == 0)
- print_debug_sections |= section_aranges;
- else if (strcmp (arg, "frame") == 0)
- print_debug_sections |= section_frame;
- else if (strcmp (arg, "info") == 0)
- print_debug_sections |= section_info;
- else if (strcmp (arg, "loc") == 0)
- print_debug_sections |= section_loc;
- else if (strcmp (arg, "line") == 0)
- print_debug_sections |= section_line;
- else if (strcmp (arg, "pubnames") == 0)
- print_debug_sections |= section_pubnames;
- else if (strcmp (arg, "str") == 0)
- print_debug_sections |= section_str;
- else if (strcmp (arg, "macinfo") == 0)
- print_debug_sections |= section_macinfo;
- else
- {
- fprintf (stderr, gettext ("Unknown DWARF debug section `%s'.\n"),
- arg);
- argp_help (&argp, stderr, ARGP_HELP_SEE,
- program_invocation_short_name);
- exit (1);
- }
- break;
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "readelf (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* Process one file. */
-static void
-process_file (int fd, Elf *elf, const char *prefix, const char *fname,
- bool only_one)
-{
- /* We can handle two types of files: ELF files and archives. */
- Elf_Kind kind = elf_kind (elf);
- struct stat64 st;
-
- switch (kind)
- {
- case ELF_K_ELF:
- /* Yes! It's an ELF file. */
- process_elf_file (elf, prefix, fname, only_one);
- break;
-
- case ELF_K_AR:
- {
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char new_prefix[prefix_len + 1 + fname_len];
- char *cp = new_prefix;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
-
- /* It's an archive. We process each file in it. */
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- kind = elf_kind (subelf);
-
- /* Call this function recursively. */
- if (kind == ELF_K_ELF || kind == ELF_K_AR)
- {
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
- assert (arhdr != NULL);
-
- process_file (fd, subelf, new_prefix, arhdr->ar_name, false);
- }
-
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (elf_end (subelf) != 0)
- error (0, 0,
- gettext (" error while freeing sub-ELF descriptor: %s\n"),
- elf_errmsg (-1));
- }
- }
- break;
-
- default:
- if (fstat64 (fd, &st) != 0)
- error (0, errno, gettext ("cannot stat input file"));
- else if (st.st_size == 0)
- error (0, 0, gettext ("input file is empty"));
- else
- /* We cannot do anything. */
- error (0, 0, gettext ("\
-Not an ELF file - it has the wrong magic bytes at the start"));
- break;
- }
-}
-
-
-/* Process one file. */
-static void
-process_elf_file (Elf *elf, const char *prefix, const char *fname,
- bool only_one)
-{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- Ebl *ebl;
-
- /* Print the file name. */
- if (!only_one)
- {
- if (prefix != NULL)
- printf ("\n%s(%s):\n\n", prefix, fname);
- else
- printf ("\n%s:\n\n", fname);
- }
-
- if (ehdr == NULL)
- {
- error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
- return;
- }
-
- ebl = ebl_openbackend (elf);
- if (ebl == NULL)
- {
- error (0, errno, gettext ("cannot create EBL handle"));
- return;
- }
-
- /* Determine the number of sections. */
- if (elf_getshnum (ebl->elf, &shnum) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot determine number of sections: %s"),
- elf_errmsg (-1));
-
- if (print_file_header)
- print_ehdr (ebl, ehdr);
- if (print_section_header)
- print_shdr (ebl, ehdr);
- if (print_program_header)
- print_phdr (ebl, ehdr);
- if (print_section_groups)
- print_scngrp (ebl, ehdr);
- if (print_dynamic_table)
- print_dynamic (ebl, ehdr);
- if (print_relocations)
- print_relocs (ebl, ehdr);
- if (print_histogram)
- handle_hash (ebl, ehdr);
- if (print_symbol_table)
- print_symtab (ebl, ehdr, SHT_DYNSYM);
- if (print_version_info)
- print_verinfo (ebl, ehdr);
- if (print_symbol_table)
- print_symtab (ebl, ehdr, SHT_SYMTAB);
- if (print_arch)
- print_liblist (ebl, ehdr);
- if (print_debug_sections != 0)
- print_debug (ebl, ehdr);
- if (print_notes)
- handle_notes (ebl, ehdr);
-
- ebl_closebackend (ebl);
-}
-
-
-/* Print file type. */
-static void
-print_file_type (unsigned short int e_type)
-{
- if (e_type <= ET_CORE)
- {
- static const char *knowntypes[] =
- {
- N_("NONE (None)"),
- N_("REL (Relocatable file)"),
- N_("EXEC (Executable file)"),
- N_("DYN (Shared object file)"),
- N_("CORE (Core file)")
- };
- puts (gettext (knowntypes[e_type]));
- }
- else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
- printf (gettext ("OS Specific: (%x)\n"), e_type);
- else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
- printf (gettext ("Processor Specific: (%x)\n"), e_type);
- else
- puts ("???");
-}
-
-
-/* Print ELF header. */
-static void
-print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- char buf[512];
- size_t cnt;
-
- fputs_unlocked (gettext ("ELF Header:\n Magic: "), stdout);
- for (cnt = 0; cnt < EI_NIDENT; ++cnt)
- printf (" %02hhx", ehdr->e_ident[cnt]);
-
- printf (gettext ("\n Class: %s\n"),
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
- : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
- : "\?\?\?");
-
- printf (gettext (" Data: %s\n"),
- ehdr->e_ident[EI_DATA] == ELFDATA2LSB
- ? "2's complement, little endian"
- : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
- ? "2's complement, big endian" : "\?\?\?");
-
- printf (gettext (" Version: %hhd %s\n"),
- ehdr->e_ident[EI_VERSION],
- ehdr->e_ident[EI_VERSION] == EV_CURRENT ? gettext ("(current)")
- : "(\?\?\?)");
-
- printf (gettext (" OS/ABI: %s\n"),
- ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
-
- printf (gettext (" ABI Version: %hhd\n"),
- ehdr->e_ident[EI_ABIVERSION]);
-
- fputs_unlocked (gettext (" Type: "), stdout);
- print_file_type (ehdr->e_type);
-
- printf (gettext (" Machine: %s\n"), ebl->name);
-
- printf (gettext (" Version: %d %s\n"),
- ehdr->e_version,
- ehdr->e_version == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
-
- printf (gettext (" Entry point address: %#" PRIx64 "\n"),
- ehdr->e_entry);
-
- printf (gettext (" Start of program headers: %" PRId64 " %s\n"),
- ehdr->e_phoff, gettext ("(bytes into file)"));
-
- printf (gettext (" Start of section headers: %" PRId64 " %s\n"),
- ehdr->e_shoff, gettext ("(bytes into file)"));
-
- printf (gettext (" Flags: %s\n"),
- ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
-
- printf (gettext (" Size of this header: %" PRId16 " %s\n"),
- ehdr->e_ehsize, gettext ("(bytes)"));
-
- printf (gettext (" Size of program header entries: %" PRId16 " %s\n"),
- ehdr->e_phentsize, gettext ("(bytes)"));
-
- printf (gettext (" Number of program headers entries: %" PRId16 "\n"),
- ehdr->e_phnum);
-
- printf (gettext (" Size of section header entries: %" PRId16 " %s\n"),
- ehdr->e_shentsize, gettext ("(bytes)"));
-
- printf (gettext (" Number of section headers entries: %" PRId16),
- ehdr->e_shnum);
- if (ehdr->e_shnum == 0)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
- if (shdr != NULL)
- printf (gettext (" (%" PRIu32 " in [0].sh_size)"),
- (uint32_t) shdr->sh_size);
- else
- fputs_unlocked (gettext (" ([0] not available)"), stdout);
- }
- fputc_unlocked ('\n', stdout);
-
- if (ehdr->e_shstrndx == SHN_XINDEX)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
- if (shdr != NULL)
- /* We managed to get the zeroth section. */
- snprintf (buf, sizeof (buf), gettext (" (%" PRIu32 " in [0].sh_link)"),
- (uint32_t) shdr->sh_link);
- else
- {
- strncpy (buf, gettext (" ([0] not available)"), sizeof (buf));
- buf[sizeof (buf) - 1] = '\0';
- }
-
- printf (gettext (" Section header string table index: XINDEX%s\n\n"),
- buf);
- }
- else
- printf (gettext (" Section header string table index: %" PRId16 "\n\n"),
- ehdr->e_shstrndx);
-}
-
-
-static const char *
-get_visibility_type (int value)
-{
- switch (value)
- {
- case STV_DEFAULT:
- return "DEFAULT";
- case STV_INTERNAL:
- return "INTERNAL";
- case STV_HIDDEN:
- return "HIDDEN";
- case STV_PROTECTED:
- return "PROTECTED";
- default:
- return "???";
- }
-}
-
-
-/* Print the section headers. */
-static void
-print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- size_t cnt;
- size_t shstrndx;
-
- if (! print_file_header)
- printf (gettext ("\
-There are %d section headers, starting at offset %#" PRIx64 ":\n\
-\n"),
- ehdr->e_shnum, ehdr->e_shoff);
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- puts (gettext ("Section Headers:"));
-
- if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
- puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
- else
- puts (gettext ("[Nr] Name Type Addr Off Size ES Flags Lk Inf Al"));
-
- for (cnt = 0; cnt < shnum; ++cnt)
- {
- char buf[128];
- char flagbuf[20];
- char *cp;
- Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- if (scn == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
- elf_errmsg (-1));
-
- /* Get the section header. */
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"),
- elf_errmsg (-1));
-
- cp = flagbuf;
- if (shdr->sh_flags & SHF_WRITE)
- *cp++ = 'W';
- if (shdr->sh_flags & SHF_ALLOC)
- *cp++ = 'A';
- if (shdr->sh_flags & SHF_EXECINSTR)
- *cp++ = 'X';
- if (shdr->sh_flags & SHF_MERGE)
- *cp++ = 'M';
- if (shdr->sh_flags & SHF_STRINGS)
- *cp++ = 'S';
- if (shdr->sh_flags & SHF_INFO_LINK)
- *cp++ = 'I';
- if (shdr->sh_flags & SHF_LINK_ORDER)
- *cp++ = 'L';
- if (shdr->sh_flags & SHF_OS_NONCONFORMING)
- *cp++ = 'N';
- if (shdr->sh_flags & SHF_GROUP)
- *cp++ = 'G';
- if (shdr->sh_flags & SHF_TLS)
- *cp++ = 'T';
- if (shdr->sh_flags & SHF_ORDERED)
- *cp++ = 'O';
- if (shdr->sh_flags & SHF_EXCLUDE)
- *cp++ = 'E';
- *cp = '\0';
-
- printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
- " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
- " %2" PRId64 "\n",
- cnt,
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name)
- ?: "<corrupt>",
- ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
- shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
- shdr->sh_addralign);
- }
-
- fputc_unlocked ('\n', stdout);
-}
-
-
-/* Print the program header. */
-static void
-print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- size_t cnt;
- size_t shstrndx;
-
- if (ehdr->e_phnum == 0)
- /* No program header, this is OK in relocatable objects. */
- return;
-
- puts (gettext ("Program Headers:"));
- if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
- puts (gettext ("\
- Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
- else
- puts (gettext ("\
- Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align"));
-
- /* Process all program headers. */
- bool has_relro = false;
- GElf_Addr relro_from = 0;
- GElf_Addr relro_to = 0;
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- char buf[128];
- GElf_Phdr mem;
- GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
-
- /* If for some reason the header cannot be returned show this. */
- if (phdr == NULL)
- {
- puts (" ???");
- continue;
- }
-
- printf (" %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
- " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
- ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
- phdr->p_offset,
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
- ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
- phdr->p_filesz,
- phdr->p_memsz,
- phdr->p_flags & PF_R ? 'R' : ' ',
- phdr->p_flags & PF_W ? 'W' : ' ',
- phdr->p_flags & PF_X ? 'E' : ' ',
- phdr->p_align);
-
- if (phdr->p_type == PT_INTERP)
- {
- /* We can show the user the name of the interpreter. */
- size_t maxsize;
- char *filedata = elf_rawfile (ebl->elf, &maxsize);
-
- if (filedata != NULL && phdr->p_offset < maxsize)
- printf (gettext ("\t[Requesting program interpreter: %s]\n"),
- filedata + phdr->p_offset);
- }
- else if (phdr->p_type == PT_GNU_RELRO)
- {
- has_relro = true;
- relro_from = phdr->p_vaddr;
- relro_to = relro_from + phdr->p_memsz;
- }
- }
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- puts (gettext ("\n Section to Segment mapping:\n Segment Sections..."));
-
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
- size_t inner;
-
- /* Print the segment number. */
- printf (" %2.2zu ", cnt);
-
- /* This must not happen. */
- if (phdr == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot get program header: %s"),
- elf_errmsg (-1));
-
- /* Iterate over the sections. */
- bool in_relro = false;
- for (inner = 1; inner < shnum; ++inner)
- {
- Elf_Scn *scn = elf_getscn (ebl->elf, inner);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr;
-
- /* It should not happen. */
- if (scn == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot get section: %s"),
- elf_errmsg (-1));
-
- /* Get the section header. */
- shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header: %s"),
- elf_errmsg (-1));
-
- if (shdr->sh_size > 0
- /* Compare allocated sections by VMA, unallocated
- sections by file offset. */
- && (shdr->sh_flags & SHF_ALLOC
- ? (shdr->sh_addr >= phdr->p_vaddr
- && (shdr->sh_addr + shdr->sh_size
- <= phdr->p_vaddr + phdr->p_memsz))
- : (shdr->sh_offset >= phdr->p_offset
- && (shdr->sh_offset + shdr->sh_size
- <= phdr->p_offset + phdr->p_filesz))))
- {
- if (has_relro && !in_relro
- && shdr->sh_addr >= relro_from
- && shdr->sh_addr + shdr->sh_size <= relro_to)
- {
- fputs_unlocked (" [RELRO:", stdout);
- in_relro = true;
- }
- else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
- {
- fputs_unlocked ("]", stdout);
- in_relro = false;
- }
- else if (has_relro && in_relro
- && shdr->sh_addr + shdr->sh_size > relro_to)
- fputs_unlocked ("] <RELRO:", stdout);
-
- printf (" %s",
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
-
- /* Signal that this sectin is only partially covered. */
- if (has_relro && in_relro
- && shdr->sh_addr + shdr->sh_size > relro_to)
- {
- fputs_unlocked (">", stdout);
- in_relro = false;
- }
- }
- }
- if (in_relro)
- fputs_unlocked ("]", stdout);
-
- /* Finish the line. */
- fputc_unlocked ('\n', stdout);
- }
-}
-
-
-static void
-handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- Elf_Data *data;
- Elf32_Word *grpref;
- Elf_Scn *symscn;
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr;
- Elf_Data *symdata;
- GElf_Sym sym_mem;
- size_t cnt;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
-
- symscn = elf_getscn (ebl->elf, shdr->sh_link);
- symshdr = gelf_getshdr (symscn, &symshdr_mem);
- symdata = elf_getdata (symscn, NULL);
-
- if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
- || symdata == NULL)
- return;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- grpref = (Elf32_Word *) data->d_buf;
-
- printf ((grpref[0] & GRP_COMDAT)
- ? ngettext ("\
-\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
- "\
-\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
- data->d_size / sizeof (Elf32_Word) - 1)
- : ngettext ("\
-\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
-\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
- data->d_size / sizeof (Elf32_Word) - 1),
- elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- elf_strptr (ebl->elf, symshdr->sh_link,
- gelf_getsym (symdata, shdr->sh_info, &sym_mem)->st_name)
- ?: gettext ("<INVALID SYMBOL>"),
- data->d_size / sizeof (Elf32_Word) - 1);
-
- for (cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
- {
- GElf_Shdr grpshdr_mem;
- GElf_Shdr *grpshdr;
-
- grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
- &grpshdr_mem);
-
- if (grpshdr == NULL)
- printf (gettext (" [%2u] <INVALID SECTION>\n"), grpref[cnt]);
- else
- printf (" [%2u] %s\n",
- grpref[cnt],
- elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)
- ?: gettext ("<INVALID SECTION>"));
- }
-}
-
-
-static void
-print_scngrp (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find all relocation sections and handle them. */
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is a symbol table. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL && shdr->sh_type == SHT_GROUP)
- handle_scngrp (ebl, ehdr, scn, shdr);
- }
-}
-
-
-static const struct flags
-{
- int mask;
- const char *str;
-} dt_flags[] =
- {
- { DF_ORIGIN, "ORIGIN" },
- { DF_SYMBOLIC, "SYMBOLIC" },
- { DF_TEXTREL, "TEXTREL" },
- { DF_BIND_NOW, "BIND_NOW" },
- { DF_STATIC_TLS, "STATIC_TLS" }
- };
-static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
-
-static const struct flags dt_flags_1[] =
- {
- { DF_1_NOW, "NOW" },
- { DF_1_GLOBAL, "GLOBAL" },
- { DF_1_GROUP, "GROUP" },
- { DF_1_NODELETE, "NODELETE" },
- { DF_1_LOADFLTR, "LOADFLTR" },
- { DF_1_INITFIRST, "INITFIRST" },
- { DF_1_NOOPEN, "NOOPEN" },
- { DF_1_ORIGIN, "ORIGIN" },
- { DF_1_DIRECT, "DIRECT" },
- { DF_1_TRANS, "TRANS" },
- { DF_1_INTERPOSE, "INTERPOSE" },
- { DF_1_NODEFLIB, "NODEFLIB" },
- { DF_1_NODUMP, "NODUMP" },
- { DF_1_CONFALT, "CONFALT" },
- { DF_1_ENDFILTEE, "ENDFILTEE" },
- { DF_1_DISPRELDNE, "DISPRELDNE" },
- { DF_1_DISPRELPND, "DISPRELPND" },
- };
-static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
-
-static const struct flags dt_feature_1[] =
- {
- { DTF_1_PARINIT, "PARINIT" },
- { DTF_1_CONFEXP, "CONFEXP" }
- };
-static const int ndt_feature_1 = (sizeof (dt_feature_1)
- / sizeof (dt_feature_1[0]));
-
-static const struct flags dt_posflag_1[] =
- {
- { DF_P1_LAZYLOAD, "LAZYLOAD" },
- { DF_P1_GROUPPERM, "GROUPPERM" }
- };
-static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
- / sizeof (dt_posflag_1[0]));
-
-
-static void
-print_flags (int class, GElf_Xword d_val, const struct flags *flags,
- int nflags)
-{
- bool first = true;
- int cnt;
-
- for (cnt = 0; cnt < nflags; ++cnt)
- if (d_val & flags[cnt].mask)
- {
- if (!first)
- putchar_unlocked (' ');
- fputs_unlocked (flags[cnt].str, stdout);
- d_val &= ~flags[cnt].mask;
- first = false;
- }
-
- if (d_val != 0)
- {
- if (!first)
- putchar_unlocked (' ');
- printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
- }
-
- putchar_unlocked ('\n');
-}
-
-
-static void
-print_dt_flags (int class, GElf_Xword d_val)
-{
- print_flags (class, d_val, dt_flags, ndt_flags);
-}
-
-
-static void
-print_dt_flags_1 (int class, GElf_Xword d_val)
-{
- print_flags (class, d_val, dt_flags_1, ndt_flags_1);
-}
-
-
-static void
-print_dt_feature_1 (int class, GElf_Xword d_val)
-{
- print_flags (class, d_val, dt_feature_1, ndt_feature_1);
-}
-
-
-static void
-print_dt_posflag_1 (int class, GElf_Xword d_val)
-{
- print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
-}
-
-
-static void
-handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- int class = gelf_getclass (ebl->elf);
- GElf_Shdr glink;
- Elf_Data *data;
- size_t cnt;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- printf (ngettext ("\
-\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- "\
-\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- shdr->sh_size / shdr->sh_entsize),
- (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
- class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
- shdr->sh_offset,
- (int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
- fputs_unlocked (gettext (" Type Value\n"), stdout);
-
- for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- char buf[64];
- GElf_Dyn dynmem;
- GElf_Dyn *dyn;
-
- dyn = gelf_getdyn (data, cnt, &dynmem);
- if (dyn == NULL)
- break;
-
- printf (" %-17s ",
- ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
-
- switch (dyn->d_tag)
- {
- case DT_NULL:
- case DT_DEBUG:
- case DT_BIND_NOW:
- case DT_TEXTREL:
- /* No further output. */
- fputc ('\n', stdout);
- break;
-
- case DT_NEEDED:
- printf (gettext ("Shared library: [%s]\n"),
- elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
- break;
-
- case DT_SONAME:
- printf (gettext ("Library soname: [%s]\n"),
- elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
- break;
-
- case DT_RPATH:
- printf (gettext ("Library rpath: [%s]\n"),
- elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
- break;
-
- case DT_RUNPATH:
- printf (gettext ("Library runpath: [%s]\n"),
- elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val));
- break;
-
- case DT_PLTRELSZ:
- case DT_RELASZ:
- case DT_STRSZ:
- case DT_RELSZ:
- case DT_RELAENT:
- case DT_SYMENT:
- case DT_RELENT:
- case DT_PLTPADSZ:
- case DT_MOVEENT:
- case DT_MOVESZ:
- case DT_INIT_ARRAYSZ:
- case DT_FINI_ARRAYSZ:
- case DT_SYMINSZ:
- case DT_SYMINENT:
- case DT_GNU_CONFLICTSZ:
- case DT_GNU_LIBLISTSZ:
- printf (gettext ("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
- break;
-
- case DT_VERDEFNUM:
- case DT_VERNEEDNUM:
- case DT_RELACOUNT:
- case DT_RELCOUNT:
- printf ("%" PRId64 "\n", dyn->d_un.d_val);
- break;
-
- case DT_PLTREL:
- puts (ebl_dynamic_tag_name (ebl, dyn->d_un.d_val, NULL, 0));
- break;
-
- case DT_FLAGS:
- print_dt_flags (class, dyn->d_un.d_val);
- break;
-
- case DT_FLAGS_1:
- print_dt_flags_1 (class, dyn->d_un.d_val);
- break;
-
- case DT_FEATURE_1:
- print_dt_feature_1 (class, dyn->d_un.d_val);
- break;
-
- case DT_POSFLAG_1:
- print_dt_posflag_1 (class, dyn->d_un.d_val);
- break;
-
- default:
- printf ("%#0*" PRIx64 "\n",
- class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
- break;
- }
- }
-}
-
-
-/* Print the dynamic segment. */
-static void
-print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find all relocation sections and handle them. */
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is a symbol table. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
- {
- handle_dynamic (ebl, ehdr, scn, shdr);
- break;
- }
- }
-}
-
-
-/* Print relocations. */
-static void
-print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find all relocation sections and handle them. */
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is a symbol table. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL)
- {
- if (shdr->sh_type == SHT_REL)
- handle_relocs_rel (ebl, ehdr, scn, shdr);
- else if (shdr->sh_type == SHT_RELA)
- handle_relocs_rela (ebl, ehdr, scn, shdr);
- }
- }
-}
-
-
-/* Handle a relocation section. */
-static void
-handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- int class = gelf_getclass (ebl->elf);
- int nentries = shdr->sh_size / shdr->sh_entsize;
- int cnt;
- Elf_Data *data;
- Elf_Scn *symscn;
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr;
- Elf_Data *symdata;
- GElf_Shdr destshdr_mem;
- GElf_Shdr *destshdr;
- Elf_Scn *xndxscn;
- Elf_Data *xndxdata = NULL;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the symbol table information. */
- symscn = elf_getscn (ebl->elf, shdr->sh_link);
- symshdr = gelf_getshdr (symscn, &symshdr_mem);
- symdata = elf_getdata (symscn, NULL);
-
- /* Get the section header of the section the relocations are for. */
- destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
- &destshdr_mem);
-
- if (symshdr == NULL || symdata == NULL || destshdr == NULL)
- {
- printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
- shdr->sh_offset);
- return;
- }
-
- /* Search for the optional extended section index table. */
- xndxscn = NULL;
- while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
- {
- GElf_Shdr xndxshdr_mem;
- GElf_Shdr *xndxshdr;
-
- xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
- if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
- && xndxshdr->sh_link == elf_ndxscn (symscn))
- {
- /* Found it. */
- xndxdata = elf_getdata (xndxscn, NULL);
- break;
- }
- }
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- if (shdr->sh_info != 0)
- printf (ngettext ("\
-\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
- "\
-\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
- nentries),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- (unsigned int) shdr->sh_info,
- elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
- shdr->sh_offset,
- nentries);
- else
- /* The .rel.dyn section does not refer to a specific section but
- instead of section index zero. Do not try to print a section
- name. */
- printf (ngettext ("\
-\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
- "\
-\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
- nentries),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- shdr->sh_offset,
- nentries);
- fputs_unlocked (class == ELFCLASS32
- ? gettext ("\
- Offset Type Value Name\n")
- : gettext ("\
- Offset Type Value Name\n"),
- stdout);
-
- for (cnt = 0; cnt < nentries; ++cnt)
- {
- GElf_Rel relmem;
- GElf_Rel *rel;
-
- rel = gelf_getrel (data, cnt, &relmem);
- if (rel != NULL)
- {
- char buf[128];
- GElf_Sym symmem;
- GElf_Sym *sym;
- Elf32_Word xndx;
-
- sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
- &symmem, &xndx);
- if (sym == NULL)
- printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- gettext ("INVALID SYMBOL"),
- (long int) GELF_R_SYM (rel->r_info));
- else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
- else
- {
- destshdr = gelf_getshdr (elf_getscn (ebl->elf,
- sym->st_shndx == SHN_XINDEX
- ? xndx : sym->st_shndx),
- &destshdr_mem);
-
- if (shdr == NULL)
- printf (" %#0*" PRIx64 " %-20s <%s %ld>\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- gettext ("INVALID SECTION"),
- (long int) (sym->st_shndx == SHN_XINDEX
- ? xndx : sym->st_shndx));
- else
- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
- }
- }
- }
-}
-
-
-/* Handle a relocation section. */
-static void
-handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- int class = gelf_getclass (ebl->elf);
- int nentries = shdr->sh_size / shdr->sh_entsize;
-
- /* Get the data of the section. */
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the symbol table information. */
- Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
- Elf_Data *symdata = elf_getdata (symscn, NULL);
-
- /* Get the section header of the section the relocations are for. */
- GElf_Shdr destshdr_mem;
- GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
- &destshdr_mem);
-
- if (symshdr == NULL || symdata == NULL || destshdr == NULL)
- {
- printf (gettext ("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
- shdr->sh_offset);
- return;
- }
-
- /* Search for the optional extended section index table. */
- Elf_Data *xndxdata = NULL;
- Elf_Scn *xndxscn = NULL;
- while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
- {
- GElf_Shdr xndxshdr_mem;
- GElf_Shdr *xndxshdr;
-
- xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
- if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
- && xndxshdr->sh_link == elf_ndxscn (symscn))
- {
- /* Found it. */
- xndxdata = elf_getdata (xndxscn, NULL);
- break;
- }
- }
-
- /* Get the section header string table index. */
- size_t shstrndx;
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- printf (ngettext ("\
-\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
- "\
-\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
- nentries),
- elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- (unsigned int) shdr->sh_info,
- elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
- shdr->sh_offset,
- nentries);
- fputs_unlocked (class == ELFCLASS32
- ? gettext ("\
- Offset Type Value Addend Name\n")
- : gettext ("\
- Offset Type Value Addend Name\n"),
- stdout);
-
- for (int cnt = 0; cnt < nentries; ++cnt)
- {
- GElf_Rela relmem;
- GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
- if (rel != NULL)
- {
- char buf[64];
- GElf_Sym symmem;
- GElf_Sym *sym;
- Elf32_Word xndx;
-
- sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (rel->r_info),
- &symmem, &xndx);
-
- if (sym == NULL)
- printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- gettext ("INVALID SYMBOL"),
- (long int) GELF_R_SYM (rel->r_info));
- else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
- printf ("\
- %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- rel->r_addend,
- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
- else
- {
- destshdr = gelf_getshdr (elf_getscn (ebl->elf,
- sym->st_shndx == SHN_XINDEX
- ? xndx : sym->st_shndx),
- &destshdr_mem);
-
- if (shdr == NULL)
- printf (" %#0*" PRIx64 " %-15s <%s %ld>\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- gettext ("INVALID SECTION"),
- (long int) (sym->st_shndx == SHN_XINDEX
- ? xndx : sym->st_shndx));
- else
- printf ("\
- %#0*" PRIx64 " %-15s %#0*" PRIx64 " +%5" PRId64 " %s\n",
- class == ELFCLASS32 ? 10 : 18, rel->r_offset,
- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
- /* Avoid the leading R_ which isn't carrying any
- information. */
- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
- buf, sizeof (buf)) + 2
- : gettext ("<INVALID RELOC>"),
- class == ELFCLASS32 ? 10 : 18, sym->st_value,
- rel->r_addend,
- elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
- }
- }
- }
-}
-
-
-/* Print the program header. */
-static void
-print_symtab (Ebl *ebl, GElf_Ehdr *ehdr, int type)
-{
- /* Find the symbol table(s). For this we have to search through the
- section table. */
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is a symbol table. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
- handle_symtab (ebl, ehdr, scn, shdr);
- }
-}
-
-
-static void
-handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- Elf_Data *versym_data = NULL;
- Elf_Data *verneed_data = NULL;
- Elf_Data *verdef_data = NULL;
- Elf_Data *xndx_data = NULL;
- Elf_Scn *runscn;
- Elf_Data *data;
- int class = gelf_getclass (ebl->elf);
- unsigned int nsyms;
- unsigned int cnt;
- Elf32_Word verneed_stridx = 0;
- Elf32_Word verdef_stridx = 0;
- GElf_Shdr glink;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Find out whether we have other sections we might need. */
- runscn = NULL;
- while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
- {
- GElf_Shdr runshdr_mem;
- GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
-
- if (runshdr != NULL)
- {
- if (runshdr->sh_type == SHT_GNU_versym
- && runshdr->sh_link == elf_ndxscn (scn))
- /* Bingo, found the version information. Now get the data. */
- versym_data = elf_getdata (runscn, NULL);
- else if (runshdr->sh_type == SHT_GNU_verneed)
- {
- /* This is the information about the needed versions. */
- verneed_data = elf_getdata (runscn, NULL);
- verneed_stridx = runshdr->sh_link;
- }
- else if (runshdr->sh_type == SHT_GNU_verdef)
- {
- /* This is the information about the defined versions. */
- verdef_data = elf_getdata (runscn, NULL);
- verdef_stridx = runshdr->sh_link;
- }
- else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
- && runshdr->sh_link == elf_ndxscn (scn))
- /* Extended section index. */
- xndx_data = elf_getdata (runscn, NULL);
- }
- }
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* Now we can compute the number of entries in the section. */
- nsyms = data->d_size / (class == ELFCLASS32
- ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
-
- printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
- "\nSymbol table [%2u] '%s' contains %u entries:\n",
- nsyms),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
- printf (ngettext (" %lu local symbol String table: [%2u] '%s'\n",
- " %lu local symbols String table: [%2u] '%s'\n",
- shdr->sh_info),
- (unsigned long int) shdr->sh_info,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
-
- fputs_unlocked (class == ELFCLASS32
- ? gettext ("\
- Num: Value Size Type Bind Vis Ndx Name\n")
- : gettext ("\
- Num: Value Size Type Bind Vis Ndx Name\n"),
- stdout);
-
- for (cnt = 0; cnt < nsyms; ++cnt)
- {
- char typebuf[64];
- char bindbuf[64];
- char scnbuf[64];
- Elf32_Word xndx;
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsymshndx (data, xndx_data, cnt, &sym_mem, &xndx);
-
- if (sym == NULL)
- continue;
-
- /* Determine the real section index. */
- if (sym->st_shndx != SHN_XINDEX)
- xndx = sym->st_shndx;
-
- printf (gettext ("\
-%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
- cnt,
- class == ELFCLASS32 ? 8 : 16,
- sym->st_value,
- sym->st_size,
- ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
- typebuf, sizeof (typebuf)),
- ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
- bindbuf, sizeof (bindbuf)),
- get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
- ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
- sizeof (scnbuf), NULL, shnum),
- elf_strptr (ebl->elf, shdr->sh_link, sym->st_name));
-
- if (versym_data != NULL)
- {
- /* Get the version information. */
- GElf_Versym versym_mem;
- GElf_Versym *versym;
-
- versym = gelf_getversym (versym_data, cnt, &versym_mem);
-
- if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
- {
- bool is_nobits = false;
- bool check_def = xndx != SHN_UNDEF;
-
- if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
- {
- GElf_Shdr symshdr_mem;
- GElf_Shdr *symshdr =
- gelf_getshdr (elf_getscn (ebl->elf, xndx), &symshdr_mem);
-
- is_nobits = (symshdr != NULL
- && symshdr->sh_type == SHT_NOBITS);
- }
-
- if (is_nobits || ! check_def)
- {
- /* We must test both. */
- GElf_Verneed verneed_mem;
- GElf_Verneed *verneed;
- GElf_Vernaux vernaux_mem;
- GElf_Vernaux *vernaux = NULL;
- size_t vn_offset = 0;
-
- verneed = gelf_getverneed (verneed_data, 0, &verneed_mem);
- while (verneed != NULL)
- {
- size_t vna_offset = vn_offset;
-
- vernaux = gelf_getvernaux (verneed_data,
- vna_offset += verneed->vn_aux,
- &vernaux_mem);
- while (vernaux != NULL
- && vernaux->vna_other != *versym
- && vernaux->vna_next != 0)
- {
- /* Update the offset. */
- vna_offset += vernaux->vna_next;
-
- vernaux = (vernaux->vna_next == 0
- ? NULL
- : gelf_getvernaux (verneed_data,
- vna_offset,
- &vernaux_mem));
- }
-
- /* Check whether we found the version. */
- if (vernaux != NULL && vernaux->vna_other == *versym)
- /* Found it. */
- break;
-
- vn_offset += verneed->vn_next;
- verneed = (verneed->vn_next == 0
- ? NULL
- : gelf_getverneed (verneed_data, vn_offset,
- &verneed_mem));
- }
-
- if (vernaux != NULL && vernaux->vna_other == *versym)
- {
- printf ("@%s (%u)",
- elf_strptr (ebl->elf, verneed_stridx,
- vernaux->vna_name),
- (unsigned int) vernaux->vna_other);
- check_def = 0;
- }
- else if (! is_nobits)
- error (0, 0, gettext ("bad dynamic symbol"));
- else
- check_def = 1;
- }
-
- if (check_def && *versym != 0x8001)
- {
- /* We must test both. */
- GElf_Verdef verdef_mem;
- GElf_Verdef *verdef;
- size_t vd_offset = 0;
-
- verdef = gelf_getverdef (verdef_data, 0, &verdef_mem);
- while (verdef != NULL)
- {
- if (verdef->vd_ndx == (*versym & 0x7fff))
- /* Found the definition. */
- break;
-
- vd_offset += verdef->vd_next;
- verdef = (verdef->vd_next == 0
- ? NULL
- : gelf_getverdef (verdef_data, vd_offset,
- &verdef_mem));
- }
-
- if (verdef != NULL)
- {
- GElf_Verdaux verdaux_mem;
- GElf_Verdaux *verdaux;
-
- verdaux = gelf_getverdaux (verdef_data,
- vd_offset + verdef->vd_aux,
- &verdaux_mem);
-
- if (verdaux != NULL)
- printf ((*versym & 0x8000) ? "@%s" : "@@%s",
- elf_strptr (ebl->elf, verdef_stridx,
- verdaux->vda_name));
- }
- }
- }
- }
-
- putchar ('\n');
- }
-}
-
-
-/* Print version information. */
-static void
-print_verinfo (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find the version information sections. For this we have to
- search through the section table. */
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is part of the versioning handling. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL)
- {
- if (shdr->sh_type == SHT_GNU_verneed)
- handle_verneed (ebl, ehdr, scn, shdr);
- else if (shdr->sh_type == SHT_GNU_verdef)
- handle_verdef (ebl, ehdr, scn, shdr);
- else if (shdr->sh_type == SHT_GNU_versym)
- handle_versym (ebl, ehdr, scn, shdr);
- }
- }
-}
-
-
-static const char *
-get_ver_flags (unsigned int flags)
-{
- static char buf[32];
- char *endp;
-
- if (flags == 0)
- return gettext ("none");
-
- if (flags & VER_FLG_BASE)
- endp = stpcpy (buf, "BASE ");
- else
- endp = buf;
-
- if (flags & VER_FLG_WEAK)
- {
- if (endp != buf)
- endp = stpcpy (endp, "| ");
-
- endp = stpcpy (endp, "WEAK ");
- }
-
- if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK))
- {
- strncpy (endp, gettext ("| <unknown>"), buf + sizeof (buf) - endp);
- buf[sizeof (buf) - 1] = '\0';
- }
-
- return buf;
-}
-
-
-static void
-handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- Elf_Data *data;
- int class = gelf_getclass (ebl->elf);
- GElf_Shdr glink;
- int cnt;
- unsigned int offset;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- printf (ngettext ("\
-\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- "\
-\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- shdr->sh_info),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
- class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
- shdr->sh_offset,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
-
- offset = 0;
- for (cnt = shdr->sh_info; --cnt >= 0; )
- {
- GElf_Verneed needmem;
- GElf_Verneed *need;
- unsigned int auxoffset;
- int cnt2;
-
- /* Get the data at the next offset. */
- need = gelf_getverneed (data, offset, &needmem);
- if (need == NULL)
- break;
-
- printf (gettext (" %#06x: Version: %hu File: %s Cnt: %hu\n"),
- offset, (unsigned short int) need->vn_version,
- elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
- (unsigned short int) need->vn_cnt);
-
- auxoffset = offset + need->vn_aux;
- for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
- {
- GElf_Vernaux auxmem;
- GElf_Vernaux *aux;
-
- aux = gelf_getvernaux (data, auxoffset, &auxmem);
- if (aux == NULL)
- break;
-
- printf (gettext (" %#06x: Name: %s Flags: %s Version: %hu\n"),
- auxoffset,
- elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
- get_ver_flags (aux->vna_flags),
- (unsigned short int) aux->vna_other);
-
- auxoffset += aux->vna_next;
- }
-
- /* Find the next offset. */
- offset += need->vn_next;
- }
-}
-
-
-static void
-handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- Elf_Data *data;
- int class = gelf_getclass (ebl->elf);
- GElf_Shdr glink;
- int cnt;
- unsigned int offset;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- printf (ngettext ("\
-\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- "\
-\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- shdr->sh_info),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- shdr->sh_info,
- class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
- shdr->sh_offset,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
-
- offset = 0;
- for (cnt = shdr->sh_info; --cnt >= 0; )
- {
- GElf_Verdef defmem;
- GElf_Verdef *def;
- GElf_Verdaux auxmem;
- GElf_Verdaux *aux;
- unsigned int auxoffset;
- int cnt2;
-
- /* Get the data at the next offset. */
- def = gelf_getverdef (data, offset, &defmem);
- if (def == NULL)
- break;
-
- auxoffset = offset + def->vd_aux;
- aux = gelf_getverdaux (data, auxoffset, &auxmem);
- if (aux == NULL)
- break;
-
- printf (gettext ("\
- %#06x: Version: %hd Flags: %s Index: %hd Cnt: %hd Name: %s\n"),
- offset, def->vd_version,
- get_ver_flags (def->vd_flags),
- def->vd_ndx,
- def->vd_cnt,
- elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
-
- auxoffset += aux->vda_next;
- for (cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
- {
- aux = gelf_getverdaux (data, auxoffset, &auxmem);
- if (aux == NULL)
- break;
-
- printf (gettext (" %#06x: Parent %d: %s\n"),
- auxoffset, cnt2,
- elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
-
- auxoffset += aux->vda_next;
- }
-
- /* Find the next offset. */
- offset += def->vd_next;
- }
-}
-
-
-static void
-handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
-{
- Elf_Data *data;
- int class = gelf_getclass (ebl->elf);
- Elf_Scn *verscn;
- GElf_Shdr glink;
- Elf_Scn *defscn;
- Elf_Scn *needscn;
- const char **vername;
- const char **filename;
- size_t nvername;
- unsigned int cnt;
- size_t shstrndx;
-
- /* Get the data of the section. */
- data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* We have to find the version definition section and extract the
- version names. */
- defscn = NULL;
- needscn = NULL;
-
- verscn = NULL;
- while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
- {
- GElf_Shdr vershdr_mem;
- GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
-
- if (vershdr != NULL)
- {
- if (vershdr->sh_type == SHT_GNU_verdef)
- defscn = verscn;
- else if (vershdr->sh_type == SHT_GNU_verneed)
- needscn = verscn;
- }
- }
-
- if (defscn != NULL || needscn != NULL)
- {
- /* We have a version information (better should have). Now get
- the version names. First find the maximum version number. */
- nvername = 0;
- if (defscn != NULL)
- {
- /* Run through the version definitions and find the highest
- index. */
- unsigned int offset = 0;
- Elf_Data *defdata;
- GElf_Shdr defshdrmem;
- GElf_Shdr *defshdr;
-
- defdata = elf_getdata (defscn, NULL);
- if (defdata == NULL)
- return;
-
- defshdr = gelf_getshdr (defscn, &defshdrmem);
- if (defshdr == NULL)
- return;
-
- for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
- {
- GElf_Verdef defmem;
- GElf_Verdef *def;
-
- /* Get the data at the next offset. */
- def = gelf_getverdef (defdata, offset, &defmem);
- if (def == NULL)
- break;
-
- nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
-
- offset += def->vd_next;
- }
- }
- if (needscn != NULL)
- {
- unsigned int offset = 0;
- Elf_Data *needdata;
- GElf_Shdr needshdrmem;
- GElf_Shdr *needshdr;
-
- needdata = elf_getdata (needscn, NULL);
- if (needdata == NULL)
- return;
-
- needshdr = gelf_getshdr (needscn, &needshdrmem);
- if (needshdr == NULL)
- return;
-
- for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
- {
- GElf_Verneed needmem;
- GElf_Verneed *need;
- unsigned int auxoffset;
- int cnt2;
-
- /* Get the data at the next offset. */
- need = gelf_getverneed (needdata, offset, &needmem);
- if (need == NULL)
- break;
-
- /* Run through the auxiliary entries. */
- auxoffset = offset + need->vn_aux;
- for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
- {
- GElf_Vernaux auxmem;
- GElf_Vernaux *aux;
-
- aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
- if (aux == NULL)
- break;
-
- nvername = MAX (nvername,
- (size_t) (aux->vna_other & 0x7fff));
-
- auxoffset += aux->vna_next;
- }
-
- offset += need->vn_next;
- }
- }
-
- /* This is the number of versions we know about. */
- ++nvername;
-
- /* Allocate the array. */
- vername = (const char **) alloca (nvername * sizeof (const char *));
- filename = (const char **) alloca (nvername * sizeof (const char *));
-
- /* Run through the data structures again and collect the strings. */
- if (defscn != NULL)
- {
- /* Run through the version definitions and find the highest
- index. */
- unsigned int offset = 0;
- Elf_Data *defdata;
- GElf_Shdr defshdrmem;
- GElf_Shdr *defshdr;
-
- defdata = elf_getdata (defscn, NULL);
- if (defdata == NULL)
- return;
-
- defshdr = gelf_getshdr (defscn, &defshdrmem);
- if (defshdr == NULL)
- return;
-
- for (cnt = 0; cnt < defshdr->sh_info; ++cnt)
- {
- GElf_Verdef defmem;
- GElf_Verdef *def;
- GElf_Verdaux auxmem;
- GElf_Verdaux *aux;
-
- /* Get the data at the next offset. */
- def = gelf_getverdef (defdata, offset, &defmem);
- if (def == NULL)
- break;
-
- aux = gelf_getverdaux (defdata, offset + def->vd_aux, &auxmem);
- if (aux == NULL)
- break;
-
- vername[def->vd_ndx & 0x7fff]
- = elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
- filename[def->vd_ndx & 0x7fff] = NULL;
-
- offset += def->vd_next;
- }
- }
- if (needscn != NULL)
- {
- unsigned int offset = 0;
- Elf_Data *needdata;
- GElf_Shdr needshdrmem;
- GElf_Shdr *needshdr;
-
- needdata = elf_getdata (needscn, NULL);
- if (needdata == NULL)
- return;
-
- needshdr = gelf_getshdr (needscn, &needshdrmem);
- if (needshdr == NULL)
- return;
-
- for (cnt = 0; cnt < needshdr->sh_info; ++cnt)
- {
- GElf_Verneed needmem;
- GElf_Verneed *need;
- unsigned int auxoffset;
- int cnt2;
-
- /* Get the data at the next offset. */
- need = gelf_getverneed (needdata, offset, &needmem);
- if (need == NULL)
- break;
-
- /* Run through the auxiliary entries. */
- auxoffset = offset + need->vn_aux;
- for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
- {
- GElf_Vernaux auxmem;
- GElf_Vernaux *aux;
-
- aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
- if (aux == NULL)
- break;
-
- vername[aux->vna_other & 0x7fff]
- = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
- filename[aux->vna_other & 0x7fff]
- = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
-
- auxoffset += aux->vna_next;
- }
-
- offset += need->vn_next;
- }
- }
- }
- else
- {
- vername = NULL;
- nvername = 1;
- filename = NULL;
- }
-
- /* Print the header. */
- printf (ngettext ("\
-\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
- "\
-\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'",
- shdr->sh_size / shdr->sh_entsize),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- (int) (shdr->sh_size / shdr->sh_entsize),
- class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
- shdr->sh_offset,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
-
- /* Now we can finally look at the actual contents of this section. */
- for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
- {
- GElf_Versym symmem;
- GElf_Versym *sym;
- ssize_t n;
-
- if (cnt % 2 == 0)
- printf ("\n %4d:", cnt);
-
- sym = gelf_getversym (data, cnt, &symmem);
- if (sym == NULL)
- break;
-
- switch (*sym)
- {
- case 0:
- fputs_unlocked (gettext (" 0 *local* "),
- stdout);
- break;
-
- case 1:
- fputs_unlocked (gettext (" 1 *global* "),
- stdout);
- break;
-
- default:
- n = printf ("%4d%c%s",
- *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
- (unsigned int) (*sym & 0x7fff) < nvername
- ? vername[*sym & 0x7fff] : "???");
- if ((unsigned int) (*sym & 0x7fff) < nvername
- && filename[*sym & 0x7fff] != NULL)
- n += printf ("(%s)", filename[*sym & 0x7fff]);
- printf ("%*s", MAX (0, 33 - (int) n), " ");
- break;
- }
- }
- putchar ('\n');
-}
-
-
-static void
-handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find the symbol table(s). For this we have to search through the
- section table. */
- Elf_Scn *scn = NULL;
- size_t shstrndx;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is a symbol table. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL && shdr->sh_type == SHT_HASH)
- {
- Elf_Data *data = elf_getdata (scn, NULL);
- Elf32_Word nbucket;
- Elf32_Word nchain;
- Elf32_Word *bucket;
- Elf32_Word *chain;
- uint32_t *lengths;
- uint32_t *counts;
- Elf32_Word cnt;
- Elf32_Word maxlength = 0;
- Elf32_Word nsyms = 0;
- uint64_t nzero_counts = 0;
- GElf_Shdr glink;
-
- if (data == NULL)
- {
- error (0, 0, gettext ("cannot get data for section %d: %s"),
- (int) elf_ndxscn (scn), elf_errmsg (-1));
- continue;
- }
-
- nbucket = ((Elf32_Word *) data->d_buf)[0];
- nchain = ((Elf32_Word *) data->d_buf)[1];
- bucket = &((Elf32_Word *) data->d_buf)[2];
- chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
-
- printf (ngettext ("\
-\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- "\
-\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- nbucket),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- (int) nbucket,
- gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
- shdr->sh_addr,
- shdr->sh_offset,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf,
- shdr->sh_link),
- &glink)->sh_name));
-
- lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
-
- for (cnt = 0; cnt < nbucket; ++cnt)
- if (bucket[cnt] != 0)
- {
- Elf32_Word inner;
-
- inner = bucket[cnt];
- while (inner > 0 && inner < nchain)
- {
- ++nsyms;
- if (maxlength < ++lengths[cnt])
- ++maxlength;
-
- inner = chain[inner];
- }
- }
-
- counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
-
- for (cnt = 0; cnt < nbucket; ++cnt)
- ++counts[lengths[cnt]];
-
- if (nbucket > 0)
- {
- uint64_t success = 0;
- Elf32_Word acc;
-
- puts (gettext (" Length Number % of total Coverage"));
- printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
- counts[0], (counts[0] * 100.0) / nbucket);
-
- for (cnt = 1; cnt <= maxlength; ++cnt)
- {
- nzero_counts += counts[cnt] * cnt;
- printf (gettext ("\
-%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
- (int) cnt,
- counts[cnt], (counts[cnt] * 100.0) / nbucket,
- (nzero_counts * 100.0) / nsyms);
- }
-
- acc = 0;
- for (cnt = 1; cnt <= maxlength; ++cnt)
- {
- acc += cnt;
- success += counts[cnt] * acc;
- }
-
- printf (gettext ("\
- Average number of tests: successful lookup: %f\n\
- unsuccessful lookup: %f\n"),
- (double) success / (double) nzero_counts,
- (double) nzero_counts / (double) nbucket);
- }
-
- free (counts);
- free (lengths);
- }
- }
-}
-
-
-static void
-print_liblist (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find the library list sections. For this we have to search
- through the section table. */
- Elf_Scn *scn = NULL;
-
- /* Get the section header string table index. */
- size_t shstrndx;
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
- {
- int nentries = shdr->sh_size / shdr->sh_entsize;
- printf (ngettext ("\
-\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
- "\
-\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
- nentries),
- elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- shdr->sh_offset,
- nentries);
-
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- return;
-
- puts (gettext ("\
- Library Time Stamp Checksum Version Flags"));
-
- for (int cnt = 0; cnt < nentries; ++cnt)
- {
- GElf_Lib lib_mem;
- GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
- if (lib == NULL)
- continue;
-
- time_t t = (time_t) lib->l_time_stamp;
- struct tm *tm = gmtime (&t);
- if (tm == NULL)
- continue;
-
- printf (" [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
- cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- (unsigned int) lib->l_checksum,
- (unsigned int) lib->l_version,
- (unsigned int) lib->l_flags);
- }
- }
- }
-}
-
-
-static const char *
-dwarf_tag_string (unsigned int tag)
-{
- static const char *known_tags[] =
- {
- [DW_TAG_array_type] = "array_type",
- [DW_TAG_class_type] = "class_type",
- [DW_TAG_entry_point] = "entry_point",
- [DW_TAG_enumeration_type] = "enumeration_type",
- [DW_TAG_formal_parameter] = "formal_parameter",
- [DW_TAG_imported_declaration] = "imported_declaration",
- [DW_TAG_label] = "label",
- [DW_TAG_lexical_block] = "lexical_block",
- [DW_TAG_member] = "member",
- [DW_TAG_pointer_type] = "pointer_type",
- [DW_TAG_reference_type] = "reference_type",
- [DW_TAG_compile_unit] = "compile_unit",
- [DW_TAG_string_type] = "string_type",
- [DW_TAG_structure_type] = "structure_type",
- [DW_TAG_subroutine_type] = "subroutine_type",
- [DW_TAG_typedef] = "typedef",
- [DW_TAG_union_type] = "union_type",
- [DW_TAG_unspecified_parameters] = "unspecified_parameters",
- [DW_TAG_variant] = "variant",
- [DW_TAG_common_block] = "common_block",
- [DW_TAG_common_inclusion] = "common_inclusion",
- [DW_TAG_inheritance] = "inheritance",
- [DW_TAG_inlined_subroutine] = "inlined_subroutine",
- [DW_TAG_module] = "module",
- [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
- [DW_TAG_set_type] = "set_type",
- [DW_TAG_subrange_type] = "subrange_type",
- [DW_TAG_with_stmt] = "with_stmt",
- [DW_TAG_access_declaration] = "access_declaration",
- [DW_TAG_base_type] = "base_type",
- [DW_TAG_catch_block] = "catch_block",
- [DW_TAG_const_type] = "const_type",
- [DW_TAG_constant] = "constant",
- [DW_TAG_enumerator] = "enumerator",
- [DW_TAG_file_type] = "file_type",
- [DW_TAG_friend] = "friend",
- [DW_TAG_namelist] = "namelist",
- [DW_TAG_namelist_item] = "namelist_item",
- [DW_TAG_packed_type] = "packed_type",
- [DW_TAG_subprogram] = "subprogram",
- [DW_TAG_template_type_param] = "template_type_param",
- [DW_TAG_template_value_param] = "template_value_param",
- [DW_TAG_thrown_type] = "thrown_type",
- [DW_TAG_try_block] = "try_block",
- [DW_TAG_variant_part] = "variant_part",
- [DW_TAG_variable] = "variable",
- [DW_TAG_volatile_type] = "volatile_type",
- };
- const unsigned int nknown_tags = (sizeof (known_tags)
- / sizeof (known_tags[0]));
- static char buf[40];
- const char *result = NULL;
-
- if (tag < nknown_tags)
- result = known_tags[tag];
-
- if (result == NULL)
- /* There are a few known extensions. */
- switch (tag)
- {
- case DW_TAG_MIPS_loop:
- result = "MIPS_loop";
- break;
-
- case DW_TAG_format_label:
- result = "format_label";
- break;
-
- case DW_TAG_function_template:
- result = "function_template";
- break;
-
- case DW_TAG_class_template:
- result = "class_template";
- break;
-
- default:
- if (tag < DW_TAG_lo_user)
- snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
- else
- snprintf (buf, sizeof buf, gettext ("unknown user tag %hx"), tag);
- result = buf;
- break;
- }
-
- return result;
-}
-
-
-static const char *
-dwarf_attr_string (unsigned int attrnum)
-{
- static const char *known_attrs[] =
- {
- [DW_AT_sibling] = "sibling",
- [DW_AT_location] = "location",
- [DW_AT_name] = "name",
- [DW_AT_ordering] = "ordering",
- [DW_AT_subscr_data] = "subscr_data",
- [DW_AT_byte_size] = "byte_size",
- [DW_AT_bit_offset] = "bit_offset",
- [DW_AT_bit_size] = "bit_size",
- [DW_AT_element_list] = "element_list",
- [DW_AT_stmt_list] = "stmt_list",
- [DW_AT_low_pc] = "low_pc",
- [DW_AT_high_pc] = "high_pc",
- [DW_AT_language] = "language",
- [DW_AT_member] = "member",
- [DW_AT_discr] = "discr",
- [DW_AT_discr_value] = "discr_value",
- [DW_AT_visibility] = "visibility",
- [DW_AT_import] = "import",
- [DW_AT_string_length] = "string_length",
- [DW_AT_common_reference] = "common_reference",
- [DW_AT_comp_dir] = "comp_dir",
- [DW_AT_const_value] = "const_value",
- [DW_AT_containing_type] = "containing_type",
- [DW_AT_default_value] = "default_value",
- [DW_AT_inline] = "inline",
- [DW_AT_is_optional] = "is_optional",
- [DW_AT_lower_bound] = "lower_bound",
- [DW_AT_producer] = "producer",
- [DW_AT_prototyped] = "prototyped",
- [DW_AT_return_addr] = "return_addr",
- [DW_AT_start_scope] = "start_scope",
- [DW_AT_stride_size] = "stride_size",
- [DW_AT_upper_bound] = "upper_bound",
- [DW_AT_abstract_origin] = "abstract_origin",
- [DW_AT_accessibility] = "accessibility",
- [DW_AT_address_class] = "address_class",
- [DW_AT_artificial] = "artificial",
- [DW_AT_base_types] = "base_types",
- [DW_AT_calling_convention] = "calling_convention",
- [DW_AT_count] = "count",
- [DW_AT_data_member_location] = "data_member_location",
- [DW_AT_decl_column] = "decl_column",
- [DW_AT_decl_file] = "decl_file",
- [DW_AT_decl_line] = "decl_line",
- [DW_AT_declaration] = "declaration",
- [DW_AT_discr_list] = "discr_list",
- [DW_AT_encoding] = "encoding",
- [DW_AT_external] = "external",
- [DW_AT_frame_base] = "frame_base",
- [DW_AT_friend] = "friend",
- [DW_AT_identifier_case] = "identifier_case",
- [DW_AT_macro_info] = "macro_info",
- [DW_AT_namelist_items] = "namelist_items",
- [DW_AT_priority] = "priority",
- [DW_AT_segment] = "segment",
- [DW_AT_specification] = "specification",
- [DW_AT_static_link] = "static_link",
- [DW_AT_type] = "type",
- [DW_AT_use_location] = "use_location",
- [DW_AT_variable_parameter] = "variable_parameter",
- [DW_AT_virtuality] = "virtuality",
- [DW_AT_vtable_elem_location] = "vtable_elem_location"
- };
- const unsigned int nknown_attrs = (sizeof (known_attrs)
- / sizeof (known_attrs[0]));
- static char buf[40];
- const char *result = NULL;
-
- if (attrnum < nknown_attrs)
- result = known_attrs[attrnum];
-
- if (result == NULL)
- /* There are a few known extensions. */
- switch (attrnum)
- {
- case DW_AT_MIPS_fde:
- result = "MIPS_fde";
- break;
-
- case DW_AT_MIPS_loop_begin:
- result = "MIPS_loop_begin";
- break;
-
- case DW_AT_MIPS_tail_loop_begin:
- result = "MIPS_tail_loop_begin";
- break;
-
- case DW_AT_MIPS_epilog_begin:
- result = "MIPS_epilog_begin";
- break;
-
- case DW_AT_MIPS_loop_unroll_factor:
- result = "MIPS_loop_unroll_factor";
- break;
-
- case DW_AT_MIPS_software_pipeline_depth:
- result = "MIPS_software_pipeline_depth";
- break;
-
- case DW_AT_MIPS_linkage_name:
- result = "MIPS_linkage_name";
- break;
-
- case DW_AT_MIPS_stride:
- result = "MIPS_stride";
- break;
-
- case DW_AT_MIPS_abstract_name:
- result = "MIPS_abstract_name";
- break;
-
- case DW_AT_MIPS_clone_origin:
- result = "MIPS_clone_origin";
- break;
-
- case DW_AT_MIPS_has_inlines:
- result = "MIPS_has_inlines";
- break;
-
- case DW_AT_MIPS_stride_byte:
- result = "MIPS_stride_byte";
- break;
-
- case DW_AT_MIPS_stride_elem:
- result = "MIPS_stride_elem";
- break;
-
- case DW_AT_MIPS_ptr_dopetype:
- result = "MIPS_ptr_dopetype";
- break;
-
- case DW_AT_MIPS_allocatable_dopetype:
- result = "MIPS_allocatable_dopetype";
- break;
-
- case DW_AT_MIPS_assumed_shape_dopetype:
- result = "MIPS_assumed_shape_dopetype";
- break;
-
- case DW_AT_MIPS_assumed_size:
- result = "MIPS_assumed_size";
- break;
-
- case DW_AT_sf_names:
- result = "sf_names";
- break;
-
- case DW_AT_src_info:
- result = "src_info";
- break;
-
- case DW_AT_mac_info:
- result = "mac_info";
- break;
-
- case DW_AT_src_coords:
- result = "src_coords";
- break;
-
- case DW_AT_body_begin:
- result = "body_begin";
- break;
-
- case DW_AT_body_end:
- result = "body_end";
- break;
-
- default:
- if (attrnum < DW_AT_lo_user)
- snprintf (buf, sizeof buf, gettext ("unknown attribute %hx"),
- attrnum);
- else
- snprintf (buf, sizeof buf, gettext ("unknown user attribute %hx"),
- attrnum);
- result = buf;
- break;
- }
-
- return result;
-}
-
-
-static const char *
-dwarf_form_string (unsigned int form)
-{
- static const char *known_forms[] =
- {
- [DW_FORM_addr] = "addr",
- [DW_FORM_block2] = "block2",
- [DW_FORM_block4] = "block4",
- [DW_FORM_data2] = "data2",
- [DW_FORM_data4] = "data4",
- [DW_FORM_data8] = "data8",
- [DW_FORM_string] = "string",
- [DW_FORM_block] = "block",
- [DW_FORM_block1] = "block1",
- [DW_FORM_data1] = "data1",
- [DW_FORM_flag] = "flag",
- [DW_FORM_sdata] = "sdata",
- [DW_FORM_strp] = "strp",
- [DW_FORM_udata] = "udata",
- [DW_FORM_ref_addr] = "ref_addr",
- [DW_FORM_ref1] = "ref1",
- [DW_FORM_ref2] = "ref2",
- [DW_FORM_ref4] = "ref4",
- [DW_FORM_ref8] = "ref8",
- [DW_FORM_ref_udata] = "ref_udata",
- [DW_FORM_indirect] = "indirect"
- };
- const unsigned int nknown_forms = (sizeof (known_forms)
- / sizeof (known_forms[0]));
- static char buf[40];
- const char *result = NULL;
-
- if (form < nknown_forms)
- result = known_forms[form];
-
- if (result == NULL)
- snprintf (buf, sizeof buf, gettext ("unknown form %" PRIx64),
- (uint64_t) form);
-
- return result;
-}
-
-
-static const char *
-dwarf_lang_string (unsigned int lang)
-{
- static const char *known[] =
- {
- [DW_LANG_C89] = "ISO C89",
- [DW_LANG_C] = "C",
- [DW_LANG_Ada83] = "Ada83",
- [DW_LANG_C_plus_plus ] = "C++",
- [DW_LANG_Cobol74] = "Cobol74",
- [DW_LANG_Cobol85] = "Cobol85",
- [DW_LANG_Fortran77] = "Fortran77",
- [DW_LANG_Fortran90] = "Fortran90",
- [DW_LANG_Pascal83] = "Pascal83",
- [DW_LANG_Modula2] = "Modula2",
- [DW_LANG_Java] = "Java",
- [DW_LANG_C99] = "ISO C99",
- [DW_LANG_Ada95] = "Ada95",
- [DW_LANG_Fortran95] = "Fortran95",
- [DW_LANG_PL1] = "PL1"
- };
-
- if (lang < sizeof (known) / sizeof (known[0]))
- return known[lang];
- else if (lang == DW_LANG_Mips_Assembler)
- /* This language tag is used for assembler in general. */
- return "Assembler";
-
- if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
- {
- static char buf[100];
- snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
- return buf;
- }
-
- return "???";
-}
-
-
-static void
-print_ops (Dwarf *dbg, int level, unsigned int addrsize, Dwarf_Word len,
- unsigned char *data)
-{
- static const char *known[] =
- {
- [DW_OP_addr] = "addr",
- [DW_OP_deref] = "deref",
- [DW_OP_const1u] = "const1u",
- [DW_OP_const1s] = "const1s",
- [DW_OP_const2u] = "const2u",
- [DW_OP_const2s] = "const2s",
- [DW_OP_const4u] = "const4u",
- [DW_OP_const4s] = "const4s",
- [DW_OP_const8u] = "const8u",
- [DW_OP_const8s] = "const8s",
- [DW_OP_constu] = "constu",
- [DW_OP_consts] = "consts",
- [DW_OP_dup] = "dup",
- [DW_OP_drop] = "drop",
- [DW_OP_over] = "over",
- [DW_OP_pick] = "pick",
- [DW_OP_swap] = "swap",
- [DW_OP_rot] = "rot",
- [DW_OP_xderef] = "xderef",
- [DW_OP_abs] = "abs",
- [DW_OP_and] = "and",
- [DW_OP_div] = "div",
- [DW_OP_minus] = "minus",
- [DW_OP_mod] = "mod",
- [DW_OP_mul] = "mul",
- [DW_OP_neg] = "neg",
- [DW_OP_not] = "not",
- [DW_OP_or] = "or",
- [DW_OP_plus] = "plus",
- [DW_OP_plus_uconst] = "plus_uconst",
- [DW_OP_shl] = "shl",
- [DW_OP_shr] = "shr",
- [DW_OP_shra] = "shra",
- [DW_OP_xor] = "xor",
- [DW_OP_bra] = "bra",
- [DW_OP_eq] = "eq",
- [DW_OP_ge] = "ge",
- [DW_OP_gt] = "gt",
- [DW_OP_le] = "le",
- [DW_OP_lt] = "lt",
- [DW_OP_ne] = "ne",
- [DW_OP_skip] = "skip",
- [DW_OP_lit0] = "lit0",
- [DW_OP_lit1] = "lit1",
- [DW_OP_lit2] = "lit2",
- [DW_OP_lit3] = "lit3",
- [DW_OP_lit4] = "lit4",
- [DW_OP_lit5] = "lit5",
- [DW_OP_lit6] = "lit6",
- [DW_OP_lit7] = "lit7",
- [DW_OP_lit8] = "lit8",
- [DW_OP_lit9] = "lit9",
- [DW_OP_lit10] = "lit10",
- [DW_OP_lit11] = "lit11",
- [DW_OP_lit12] = "lit12",
- [DW_OP_lit13] = "lit13",
- [DW_OP_lit14] = "lit14",
- [DW_OP_lit15] = "lit15",
- [DW_OP_lit16] = "lit16",
- [DW_OP_lit17] = "lit17",
- [DW_OP_lit18] = "lit18",
- [DW_OP_lit19] = "lit19",
- [DW_OP_lit20] = "lit20",
- [DW_OP_lit21] = "lit21",
- [DW_OP_lit22] = "lit22",
- [DW_OP_lit23] = "lit23",
- [DW_OP_lit24] = "lit24",
- [DW_OP_lit25] = "lit25",
- [DW_OP_lit26] = "lit26",
- [DW_OP_lit27] = "lit27",
- [DW_OP_lit28] = "lit28",
- [DW_OP_lit29] = "lit29",
- [DW_OP_lit30] = "lit30",
- [DW_OP_lit31] = "lit31",
- [DW_OP_reg0] = "reg0",
- [DW_OP_reg1] = "reg1",
- [DW_OP_reg2] = "reg2",
- [DW_OP_reg3] = "reg3",
- [DW_OP_reg4] = "reg4",
- [DW_OP_reg5] = "reg5",
- [DW_OP_reg6] = "reg6",
- [DW_OP_reg7] = "reg7",
- [DW_OP_reg8] = "reg8",
- [DW_OP_reg9] = "reg9",
- [DW_OP_reg10] = "reg10",
- [DW_OP_reg11] = "reg11",
- [DW_OP_reg12] = "reg12",
- [DW_OP_reg13] = "reg13",
- [DW_OP_reg14] = "reg14",
- [DW_OP_reg15] = "reg15",
- [DW_OP_reg16] = "reg16",
- [DW_OP_reg17] = "reg17",
- [DW_OP_reg18] = "reg18",
- [DW_OP_reg19] = "reg19",
- [DW_OP_reg20] = "reg20",
- [DW_OP_reg21] = "reg21",
- [DW_OP_reg22] = "reg22",
- [DW_OP_reg23] = "reg23",
- [DW_OP_reg24] = "reg24",
- [DW_OP_reg25] = "reg25",
- [DW_OP_reg26] = "reg26",
- [DW_OP_reg27] = "reg27",
- [DW_OP_reg28] = "reg28",
- [DW_OP_reg29] = "reg29",
- [DW_OP_reg30] = "reg30",
- [DW_OP_reg31] = "reg31",
- [DW_OP_breg0] = "breg0",
- [DW_OP_breg1] = "breg1",
- [DW_OP_breg2] = "breg2",
- [DW_OP_breg3] = "breg3",
- [DW_OP_breg4] = "breg4",
- [DW_OP_breg5] = "breg5",
- [DW_OP_breg6] = "breg6",
- [DW_OP_breg7] = "breg7",
- [DW_OP_breg8] = "breg8",
- [DW_OP_breg9] = "breg9",
- [DW_OP_breg10] = "breg10",
- [DW_OP_breg11] = "breg11",
- [DW_OP_breg12] = "breg12",
- [DW_OP_breg13] = "breg13",
- [DW_OP_breg14] = "breg14",
- [DW_OP_breg15] = "breg15",
- [DW_OP_breg16] = "breg16",
- [DW_OP_breg17] = "breg17",
- [DW_OP_breg18] = "breg18",
- [DW_OP_breg19] = "breg19",
- [DW_OP_breg20] = "breg20",
- [DW_OP_breg21] = "breg21",
- [DW_OP_breg22] = "breg22",
- [DW_OP_breg23] = "breg23",
- [DW_OP_breg24] = "breg24",
- [DW_OP_breg25] = "breg25",
- [DW_OP_breg26] = "breg26",
- [DW_OP_breg27] = "breg27",
- [DW_OP_breg28] = "breg28",
- [DW_OP_breg29] = "breg29",
- [DW_OP_breg30] = "breg30",
- [DW_OP_breg31] = "breg31",
- [DW_OP_regx] = "regx",
- [DW_OP_fbreg] = "fbreg",
- [DW_OP_bregx] = "bregx",
- [DW_OP_piece] = "piece",
- [DW_OP_deref_size] = "deref_size",
- [DW_OP_xderef_size] = "xderef_size",
- [DW_OP_nop] = "nop",
- [DW_OP_push_object_address] = "push_object_address",
- [DW_OP_call2] = "call2",
- [DW_OP_call4] = "call4",
- [DW_OP_call_ref] = "call_ref",
- };
-
- Dwarf_Word offset = 0;
- while (len-- > 0)
- {
- size_t op = *((unsigned char *) data);
- ++data;
-
- switch (op)
- {
- case DW_OP_call_ref:
- case DW_OP_addr:;
- /* Address operand. */
- Dwarf_Word addr;
- if (addrsize == 4)
- addr = read_4ubyte_unaligned (dbg, data);
- else
- {
- assert (addrsize == 8);
- addr = read_8ubyte_unaligned (dbg, data);
- }
- data += addrsize;
- len -= addrsize;
-
- printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", (uintmax_t) addr);
- offset += 1 + addrsize;
- break;
-
- case DW_OP_deref_size: /* XXX Correct? */
- case DW_OP_xderef_size: /* XXX Correct? */
- case DW_OP_pick:
- case DW_OP_const1u:
- printf (" %*s [%4" PRIuMAX "] %s %" PRIu8 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", *((uint8_t *) data));
- ++data;
- --len;
- offset += 2;
- break;
-
- case DW_OP_const2u:
- printf (" %*s [%4" PRIuMAX "] %s %" PRIu16 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
- len -= 2;
- data += 2;
- offset += 3;
- break;
-
- case DW_OP_const4u:
- printf (" %*s [%4" PRIuMAX "] %s %" PRIu32 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
- len -= 4;
- data += 4;
- offset += 5;
- break;
-
- case DW_OP_const8u:
- printf (" %*s [%4" PRIuMAX "] %s %" PRIu64 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
- len -= 8;
- data += 8;
- offset += 9;
- break;
-
- case DW_OP_const1s:
- printf (" %*s [%4" PRIuMAX "] %s %" PRId8 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", *((int8_t *) data));
- ++data;
- --len;
- offset += 2;
- break;
-
- case DW_OP_const2s:
- printf (" %*s [%4" PRIuMAX "] %s %" PRId16 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
- len -= 2;
- data += 2;
- offset += 3;
- break;
-
- case DW_OP_const4s:
- printf (" %*s [%4" PRIuMAX "] %s %" PRId32 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
- len -= 4;
- data += 4;
- offset += 5;
- break;
-
- case DW_OP_const8s:
- printf (" %*s [%4" PRIuMAX "] %s %" PRId64 "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
- len -= 8;
- data += 8;
- offset += 9;
- break;
-
- case DW_OP_piece: /* XXX Correct? */
- case DW_OP_regx:
- case DW_OP_plus_uconst:
- case DW_OP_constu:;
- unsigned char *start = data;
- unsigned int uleb;
- get_uleb128 (uleb, data);
- printf (" %*s [%4" PRIuMAX "] %s %u\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", uleb);
- len -= data - start;
- offset += 1 + (data - start);
- break;
-
- case DW_OP_fbreg:
- case DW_OP_breg0 ... DW_OP_breg31:
- case DW_OP_consts:
- start = data;
- unsigned int sleb;
- get_sleb128 (sleb, data);
- printf (" %*s [%4" PRIuMAX "] %s %d\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", sleb);
- len -= data - start;
- offset += 1 + (data - start);
- break;
-
- case DW_OP_bregx:
- start = data;
- get_uleb128 (uleb, data);
- get_sleb128 (sleb, data);
- printf (" %*s [%4" PRIuMAX "] %s %u %d\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???", uleb, sleb);
- len -= data - start;
- offset += 1 + (data - start);
- break;
-
- case DW_OP_call2:
- case DW_OP_call4:
- case DW_OP_skip:
- case DW_OP_bra:
- printf (" %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???",
- (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
- len -= 2;
- data += 2;
- offset += 3;
- break;
-
- default:
- /* No Operand. */
- printf (" %*s [%4" PRIuMAX "] %s\n",
- (int) (20 + level * 2), "", (uintmax_t) offset,
- known[op] ?: "???");
- ++offset;
- break;
- }
- }
-}
-
-
-static void
-print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
- " [ Code]\n"),
- ".debug_abbrev", (uint64_t) shdr->sh_offset);
-
- Dwarf_Off offset = 0;
- while (1)
- {
- size_t length;
- Dwarf_Abbrev abbrev;
-
- if (dwarf_offabbrev (dbg, offset, &length, &abbrev) != 0)
- {
- printf (gettext (" *** error while reading abbreviation: %s\n"),
- dwarf_errmsg (-1));
- break;
- }
-
- if (length == 1)
- /* This is the NUL byte at the end of the section. */
- break;
-
- /* We know these calls can never fail. */
- unsigned int code = dwarf_getabbrevcode (&abbrev);
- unsigned int tag = dwarf_getabbrevtag (&abbrev);
- int has_children = dwarf_abbrevhaschildren (&abbrev);
-
- printf (gettext (" [%5u] offset: %" PRId64
- ", children: %s, tag: %s\n"),
- code, (int64_t) offset,
- has_children ? gettext ("yes") : gettext ("no"),
- dwarf_tag_string (tag));
-
- size_t cnt = 0;
- unsigned int name;
- unsigned int form;
- Dwarf_Off enoffset;
- while (dwarf_getabbrevattr (&abbrev, cnt, &name, &form, &enoffset) == 0)
- {
- printf (" attr: %s, form: %s, offset: %#" PRIx64 "\n",
- dwarf_attr_string (name), dwarf_form_string (form),
- (uint64_t) enoffset);
-
- ++cnt;
- }
-
- offset += length;
- }
-}
-
-
-/* Print content of DWARF .debug_aranges section. We fortunately do
- not have to know a bit about the structure of the section, libdwarf
- takes care of it. */
-static void
-print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- Dwarf_Aranges *aranges;
- size_t cnt;
- if (dwarf_getaranges (dbg, &aranges, &cnt) != 0)
- {
- error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
- dwarf_errmsg (-1));
- return;
- }
-
- printf (ngettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entry:\n",
- "\
-\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
- cnt),
- ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
-
- /* Compute floor(log16(cnt)). */
- size_t tmp = cnt;
- int digits = 1;
- while (tmp >= 16)
- {
- ++digits;
- tmp >>= 4;
- }
-
- for (size_t n = 0; n < cnt; ++n)
- {
- Dwarf_Arange *runp = dwarf_onearange (aranges, n);
- if (runp == NULL)
- {
- printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
- return;
- }
-
- Dwarf_Addr start;
- Dwarf_Word length;
- Dwarf_Off offset;
-
- if (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)
- printf (gettext (" [%*zu] ???\n"), digits, n);
- else
- printf (gettext (" [%*zu] start: %0#*" PRIx64
- ", length: %5" PRIu64 ", CU DIE offset: %6"
- PRId64 "\n"),
- digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
- (uint64_t) start, (uint64_t) length, (int64_t) offset);
- }
-}
-
-
-static void
-print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
-}
-
-
-struct attrcb_args
-{
- Dwarf *dbg;
- int level;
- unsigned int addrsize;
- Dwarf_Off cu_offset;
-};
-
-
-static int
-attr_callback (Dwarf_Attribute *attrp, void *arg)
-{
- struct attrcb_args *cbargs = (struct attrcb_args *) arg;
- const int level = cbargs->level;
-
- unsigned int attr = dwarf_whatattr (attrp);
- if (unlikely (attr == 0))
- {
- error (0, 0, gettext ("cannot get attribute code: %s"),
- dwarf_errmsg (-1));
- return DWARF_CB_ABORT;
- }
-
- unsigned int form = dwarf_whatform (attrp);
- if (unlikely (form == 0))
- {
- error (0, 0, gettext ("cannot get attribute form: %s"),
- dwarf_errmsg (-1));
- return DWARF_CB_ABORT;
- }
-
- switch (form)
- {
- case DW_FORM_addr:;
- Dwarf_Addr addr;
- if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
- {
- attrval_out:
- error (0, 0, gettext ("cannot get attribute value: %s"),
- dwarf_errmsg (-1));
- return DWARF_CB_ABORT;
- }
- printf (" %*s%-20s %#0*" PRIxMAX "\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- (int) (cbargs->addrsize * 2), (uintmax_t) addr);
- break;
-
- case DW_FORM_indirect:
- case DW_FORM_strp:
- case DW_FORM_string:;
- const char *str = dwarf_formstring (attrp);
- if (unlikely (str == NULL))
- goto attrval_out;
- printf (" %*s%-20s \"%s\"\n",
- (int) (level * 2), "", dwarf_attr_string (attr), str);
- break;
-
- case DW_FORM_ref_addr:
- case DW_FORM_ref_udata:
- case DW_FORM_ref8:
- case DW_FORM_ref4:
- case DW_FORM_ref2:
- case DW_FORM_ref1:;
- Dwarf_Off ref;
- if (unlikely (dwarf_formref (attrp, &ref) != 0))
- goto attrval_out;
-
- printf (" %*s%-20s [%6" PRIxMAX "]\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) (ref + cbargs->cu_offset));
- break;
-
- case DW_FORM_udata:
- case DW_FORM_sdata:
- case DW_FORM_data8:
- case DW_FORM_data4:
- case DW_FORM_data2:
- case DW_FORM_data1:;
- Dwarf_Word num;
- if (unlikely (dwarf_formudata (attrp, &num) != 0))
- goto attrval_out;
-
- if (attr == DW_AT_language)
- {
- printf (" %*s%-20s %s (%d)\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- dwarf_lang_string (num), (int) num);
- break;
- }
-
- printf (" %*s%-20s %" PRIuMAX "\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) num);
- break;
-
- case DW_FORM_flag:;
- bool flag;
- if (unlikely (dwarf_formflag (attrp, &flag) != 0))
- goto attrval_out;
-
- printf (" %*s%-20s %s\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- nl_langinfo (flag ? YESSTR : NOSTR));
- break;
-
- case DW_FORM_block4:
- case DW_FORM_block2:
- case DW_FORM_block1:
- case DW_FORM_block:;
- Dwarf_Block block;
- if (unlikely (dwarf_formblock (attrp, &block) != 0))
- goto attrval_out;
-
- printf (" %*s%-20s %" PRIxMAX " byte block\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) block.length);
-
- if (attr == DW_AT_data_member_location)
- print_ops (cbargs->dbg, level, cbargs->addrsize, block.length,
- block.data);
- break;
-
- default:
- printf (" %*s%-20s [form: %d] ???\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- (int) form);
- break;
- }
-
- return DWARF_CB_OK;
-}
-
-
-static void
-print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
- ".debug_info", (uint64_t) shdr->sh_offset);
-
- /* If the section is empty we don't have to do anything. */
- if (shdr->sh_size == 0)
- return;
-
- size_t maxdies = 20;
- Dwarf_Die *dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
-
- Dwarf_Off offset = 0;
-
- /* New compilation unit. */
- size_t cuhl;
- //Dwarf_Half version;
- Dwarf_Off abbroffset;
- uint8_t addrsize;
- uint8_t offsize;
- Dwarf_Off nextcu;
- next_cu:
- if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
- &offsize) != 0)
- goto do_return;
-
- printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
- " Version: %" PRIu16 ", Abbreviation section offset: %"
- PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
- (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
-
-
- struct attrcb_args args;
- args.dbg = dbg;
- args.addrsize = addrsize;
- args.cu_offset = offset;
-
- offset += cuhl;
-
- int level = 0;
-
- if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
- {
- error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
- " in section '%s': %s"),
- (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
- goto do_return;
- }
-
- do
- {
- offset = dwarf_dieoffset (&dies[level]);
- if (offset == -1l)
- {
- error (0, 0, gettext ("cannot get DIE offset: %s"),
- dwarf_errmsg (-1));
- goto do_return;
- }
-
- int tag = dwarf_tag (&dies[level]);
- if (tag == DW_TAG_invalid)
- {
- error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
- " in section '%s': %s"),
- (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
- goto do_return;
- }
-
- static const char *const lowtags[] =
- {
- [DW_TAG_array_type] = "array_type",
- [DW_TAG_class_type] = "class_type",
- [DW_TAG_entry_point] = "entry_point",
- [DW_TAG_enumeration_type] = "enumeration_type",
- [DW_TAG_formal_parameter] = "formal_parameter",
- [DW_TAG_imported_declaration] = "imported_declaration",
- [DW_TAG_label] = "label",
- [DW_TAG_lexical_block] = "lexical_block",
- [DW_TAG_member] = "member",
- [DW_TAG_pointer_type] = "pointer_type",
- [DW_TAG_reference_type] = "reference_type",
- [DW_TAG_compile_unit] = "compile_unit",
- [DW_TAG_string_type] = "string_type",
- [DW_TAG_structure_type] = "structure_type",
- [DW_TAG_subroutine_type] = "subroutine_type",
- [DW_TAG_typedef] = "typedef",
- [DW_TAG_union_type] = "union_type",
- [DW_TAG_unspecified_parameters] = "unspecified_parameters",
- [DW_TAG_variant] = "variant",
- [DW_TAG_common_block] = "common_block",
- [DW_TAG_common_inclusion] = "common_inclusion",
- [DW_TAG_inheritance] = "inheritance",
- [DW_TAG_inlined_subroutine] = "inlined_subroutine",
- [DW_TAG_module] = "module",
- [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
- [DW_TAG_set_type] = "set_type",
- [DW_TAG_subrange_type] = "subrange_type",
- [DW_TAG_with_stmt] = "with_stmt",
- [DW_TAG_access_declaration] = "access_declaration",
- [DW_TAG_base_type] = "base_type",
- [DW_TAG_catch_block] = "catch_block",
- [DW_TAG_const_type] = "const_type",
- [DW_TAG_constant] = "constant",
- [DW_TAG_enumerator] = "enumerator",
- [DW_TAG_file_type] = "file_type",
- [DW_TAG_friend] = "friend",
- [DW_TAG_namelist] = "namelist",
- [DW_TAG_namelist_item] = "namelist_item",
- [DW_TAG_packed_type] = "packed_type",
- [DW_TAG_subprogram] = "subprogram",
- [DW_TAG_template_type_param] = "template_type_param",
- [DW_TAG_template_value_param] = "template_value_param",
- [DW_TAG_thrown_type] = "thrown_type",
- [DW_TAG_try_block] = "try_block",
- [DW_TAG_variant_part] = "variant_part",
- [DW_TAG_variable] = "variable",
- [DW_TAG_volatile_type] = "volatile_type"
- };
-
- const char *tagstr;
- switch (tag)
- {
- case DW_TAG_lo_user:
- tagstr = "lo_user";
- break;
-
- case DW_TAG_MIPS_loop:
- tagstr = "MIPS_loop";
- break;
-
- case DW_TAG_format_label:
- tagstr = "format_label";
- break;
-
- case DW_TAG_function_template:
- tagstr = "function_template";
- break;
-
- case DW_TAG_class_template:
- tagstr = "class_template";
- break;
- case DW_TAG_hi_user:
- tagstr = "hi_user";
- break;
-
- default:
- if (tag < sizeof (lowtags) / sizeof (lowtags[0]))
- tagstr = lowtags[tag];
- else
- tagstr = "???";
- break;
- }
-
- printf (" [%6" PRIx64 "] %*s%s\n",
- (uint64_t) offset, (int) (level * 2), "", tagstr);
-
- /* Print the attribute values. */
- args.level = level;
- (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
-
- /* Make room for the next level's DIE. */
- if (level + 1 == maxdies)
- dies = (Dwarf_Die *) xrealloc (dies,
- (maxdies += 10)
- * sizeof (Dwarf_Die));
-
- int res = dwarf_child (&dies[level], &dies[level + 1]);
- if (res > 0)
- {
- while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
- if (level-- == 0)
- break;
-
- if (res == -1)
- {
- error (0, 0, gettext ("cannot get next DIE: %s\n"),
- dwarf_errmsg (-1));
- goto do_return;
- }
- }
- else if (unlikely (res < 0))
- {
- error (0, 0, gettext ("cannot get next DIE: %s"),
- dwarf_errmsg (-1));
- goto do_return;
- }
- else
- ++level;
- }
- while (level >= 0);
-
- offset = nextcu;
- if (offset != 0)
- goto next_cu;
-
- do_return:
- free (dies);
-}
-
-
-static void
-print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_line", (uint64_t) shdr->sh_offset);
-
- if (shdr->sh_size == 0)
- return;
-
- /* There is no functionality in libdw to read the information in the
- way it is represented here. Hardcode the decoder. */
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL || data->d_buf == NULL)
- {
- error (0, 0, gettext ("cannot get line data section data: %s"),
- elf_errmsg (-1));
- return;
- }
-
- const unsigned char *linep = (const unsigned char *) data->d_buf;
- const unsigned char *lineendp;
-
- while (linep
- < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
- {
- size_t start_offset = linep - (const unsigned char *) data->d_buf;
-
- Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
- unsigned int length = 4;
- if (unlikely (unit_length == 0xffffffff))
- {
- if (unlikely (linep + 8 > lineendp))
- {
- invalid_data:
- error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), ".debug_line");
- return;
- }
- unit_length = read_8ubyte_unaligned_inc (dbg, linep);
- length = 8;
- }
-
- /* Check whether we have enough room in the section. */
- if (unit_length < 2 + length + 5 * 1
- || unlikely (linep + unit_length > lineendp))
- goto invalid_data;
- lineendp = linep + unit_length;
-
- /* The next element of the header is the version identifier. */
- uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
-
- /* Next comes the header length. */
- Dwarf_Word header_length;
- if (length == 4)
- header_length = read_4ubyte_unaligned_inc (dbg, linep);
- else
- header_length = read_8ubyte_unaligned_inc (dbg, linep);
- //const unsigned char *header_start = linep;
-
- /* Next the minimum instruction length. */
- uint_fast8_t minimum_instr_len = *linep++;
-
- /* Then the flag determining the default value of the is_stmt
- register. */
- uint_fast8_t default_is_stmt = *linep++;
-
- /* Now the line base. */
- int_fast8_t line_base = *((const int_fast8_t *) linep);
- ++linep;
-
- /* And the line range. */
- uint_fast8_t line_range = *linep++;
-
- /* The opcode base. */
- uint_fast8_t opcode_base = *linep++;
-
- /* Print what we got so far. */
- printf (gettext ("\n"
- " Length: %" PRIu64 "\n"
- " DWARF version: %" PRIuFAST16 "\n"
- " Prologue length: %" PRIu64 "\n"
- " Minimum instruction length: %" PRIuFAST8 "\n"
- " Initial value if '%s': %" PRIuFAST8 "\n"
- " Line base: %" PRIdFAST8 "\n"
- " Line range: %" PRIuFAST8 "\n"
- " Opcode base: %" PRIuFAST8 "\n"
- "\n"
- "Opcodes:\n"),
- (uint64_t) unit_length, version, (uint64_t) header_length,
- minimum_instr_len, "is_stmt", default_is_stmt, line_base,
- line_range, opcode_base);
-
- if (unlikely (linep + opcode_base - 1 >= lineendp))
- goto invalid_data;
- int opcode_base_l10 = 1;
- unsigned int tmp = opcode_base;
- while (tmp > 10)
- {
- tmp /= 10;
- ++opcode_base_l10;
- }
- const uint8_t *standard_opcode_lengths = linep - 1;
- for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
- printf (ngettext (" [%*" PRIuFAST8 "] %hhu argument\n",
- " [%*" PRIuFAST8 "] %hhu arguments\n",
- (int) linep[cnt - 1]),
- opcode_base_l10, cnt, linep[cnt - 1]);
- linep += opcode_base - 1;
- if (unlikely (linep >= lineendp))
- goto invalid_data;
-
- puts (gettext ("\nDirectory table:"));
- while (*linep != 0)
- {
- unsigned char *endp = memchr (linep, '\0', lineendp - linep);
- if (endp == NULL)
- goto invalid_data;
-
- printf (" %s\n", (char *) linep);
-
- linep = endp + 1;
- }
- /* Skip the final NUL byte. */
- ++linep;
-
- if (unlikely (linep >= lineendp))
- goto invalid_data;
- puts (gettext ("\nFile name table:\n"
- " Entry Dir Time Size Name"));
- for (unsigned int cnt = 1; *linep != 0; ++cnt)
- {
- /* First comes the file name. */
- char *fname = (char *) linep;
- unsigned char *endp = memchr (fname, '\0', lineendp - linep);
- if (endp == NULL)
- goto invalid_data;
- linep = endp + 1;
-
- /* Then the index. */
- unsigned int diridx;
- get_uleb128 (diridx, linep);
-
- /* Next comes the modification time. */
- unsigned int mtime;
- get_uleb128 (mtime, linep);
-
- /* Finally the length of the file. */
- unsigned int fsize;
- get_uleb128 (fsize, linep);
-
- printf (" %-5u %-5u %-9u %-9u %s\n",
- cnt, diridx, mtime, fsize, fname);
- }
- /* Skip the final NUL byte. */
- ++linep;
-
- puts (gettext ("\nLine number statements:"));
- Dwarf_Word address = 0;
- size_t line = 1;
- uint_fast8_t is_stmt = default_is_stmt;
-
- /* Default address value, in case we do not find the CU. */
- size_t address_size
- = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
-
- /* Determine the CU this block is for. */
- Dwarf_Off cuoffset;
- Dwarf_Off ncuoffset = 0;
- size_t hsize;
- while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
- NULL, NULL, NULL) == 0)
- {
- Dwarf_Die cudie;
- if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
- continue;
- Dwarf_Attribute stmt_list;
- if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
- continue;
- Dwarf_Word lineoff;
- if (dwarf_formudata (&stmt_list, &lineoff) != 0)
- continue;
- if (lineoff == start_offset)
- {
- /* Found the CU. */
- address_size = cudie.cu->address_size;
- break;
- }
- }
-
- while (linep < lineendp)
- {
- unsigned int u128;
- int s128;
-
- /* Read the opcode. */
- unsigned int opcode = *linep++;
-
- /* Is this a special opcode? */
- if (likely (opcode >= opcode_base))
- {
- /* Yes. Handling this is quite easy since the opcode value
- is computed with
-
- opcode = (desired line increment - line_base)
- + (line_range * address advance) + opcode_base
- */
- int line_increment = (line_base
- + (opcode - opcode_base) % line_range);
- unsigned int address_increment = (minimum_instr_len
- * ((opcode - opcode_base)
- / line_range));
-
- /* Perform the increments. */
- line += line_increment;
- address += address_increment;
-
- printf (gettext ("\
- special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"),
- opcode, address_increment, (uint64_t) address,
- line_increment, line);
- }
- else if (opcode == 0)
- {
- /* This an extended opcode. */
- if (unlikely (linep + 2 > lineendp))
- goto invalid_data;
-
- /* The length. */
- unsigned int len = *linep++;
-
- if (unlikely (linep + len > lineendp))
- goto invalid_data;
-
- /* The sub-opcode. */
- opcode = *linep++;
-
- printf (gettext (" extended opcode %u: "), opcode);
-
- switch (opcode)
- {
- case DW_LNE_end_sequence:
- puts (gettext ("end of sequence"));
-
- /* Reset the registers we care about. */
- address = 0;
- line = 1;
- is_stmt = default_is_stmt;
- break;
-
- case DW_LNE_set_address:
- if (address_size == 4)
- address = read_4ubyte_unaligned_inc (dbg, linep);
- else
- address = read_8ubyte_unaligned_inc (dbg, linep);
- printf (gettext ("set address to %#" PRIx64 "\n"),
- (uint64_t) address);
- break;
-
- case DW_LNE_define_file:
- {
- char *fname = (char *) linep;
- unsigned char *endp = memchr (linep, '\0',
- lineendp - linep);
- if (endp == NULL)
- goto invalid_data;
- linep = endp + 1;
-
- unsigned int diridx;
- get_uleb128 (diridx, linep);
- Dwarf_Word mtime;
- get_uleb128 (mtime, linep);
- Dwarf_Word filelength;
- get_uleb128 (filelength, linep);
-
- printf (gettext ("\
-define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
- diridx, (uint64_t) mtime, (uint64_t) filelength,
- fname);
- }
- break;
-
- default:
- /* Unknown, ignore it. */
- puts (gettext ("unknown opcode"));
- linep += len - 1;
- break;
- }
- }
- else if (opcode <= DW_LNS_set_epilog_begin)
- {
- /* This is a known standard opcode. */
- switch (opcode)
- {
- case DW_LNS_copy:
- /* Takes no argument. */
- puts (gettext (" copy"));
- break;
-
- case DW_LNS_advance_pc:
- /* Takes one uleb128 parameter which is added to the
- address. */
- get_uleb128 (u128, linep);
- address += minimum_instr_len * u128;
- printf (gettext ("\
- advance address by %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
- break;
-
- case DW_LNS_advance_line:
- /* Takes one sleb128 parameter which is added to the
- line. */
- get_sleb128 (s128, linep);
- line += s128;
- printf (gettext ("\
- advance line by constant %d to %" PRId64 "\n"),
- s128, (int64_t) line);
- break;
-
- case DW_LNS_set_file:
- /* Takes one uleb128 parameter which is stored in file. */
- get_uleb128 (u128, linep);
- printf (gettext (" set file to %" PRIu64 "\n"),
- (uint64_t) u128);
- break;
-
- case DW_LNS_set_column:
- /* Takes one uleb128 parameter which is stored in column. */
- if (unlikely (standard_opcode_lengths[opcode] != 1))
- goto invalid_data;
-
- get_uleb128 (u128, linep);
- printf (gettext (" set column to %" PRIu64 "\n"),
- (uint64_t) u128);
- break;
-
- case DW_LNS_negate_stmt:
- /* Takes no argument. */
- is_stmt = 1 - is_stmt;
- printf (gettext (" set '%s' to %" PRIuFAST8 "\n"),
- "is_stmt", is_stmt);
- break;
-
- case DW_LNS_set_basic_block:
- /* Takes no argument. */
- puts (gettext (" set basic block flag"));
- break;
-
- case DW_LNS_const_add_pc:
- /* Takes no argument. */
- u128 = (minimum_instr_len
- * ((255 - opcode_base) / line_range));
- address += u128;
- printf (gettext ("\
- advance address by constant %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
- break;
-
- case DW_LNS_fixed_advance_pc:
- /* Takes one 16 bit parameter which is added to the
- address. */
- if (unlikely (standard_opcode_lengths[opcode] != 1))
- goto invalid_data;
-
- u128 = read_2ubyte_unaligned_inc (dbg, linep);
- address += u128;
- printf (gettext ("\
- advance address by fixed value %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
- break;
-
- case DW_LNS_set_prologue_end:
- /* Takes no argument. */
- puts (gettext (" set prologue end flag"));
- break;
-
- case DW_LNS_set_epilog_begin:
- /* Takes no argument. */
- puts (gettext (" set epilogue begin flag"));
- break;
- }
- }
- else
- {
- /* This is a new opcode the generator but not we know about.
- Read the parameters associated with it but then discard
- everything. Read all the parameters for this opcode. */
- printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
- " unknown opcode with %" PRIu8 " parameters:",
- standard_opcode_lengths[opcode]),
- standard_opcode_lengths[opcode]);
- for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
- {
- get_uleb128 (u128, linep);
- if (n != standard_opcode_lengths[opcode])
- putc_unlocked (',', stdout);
- printf (" %u", u128);
- }
-
- /* Next round, ignore this opcode. */
- continue;
- }
- }
- }
-
- /* There must only be one data block. */
- assert (elf_getdata (scn, data) == NULL);
-}
-
-
-static void
-print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_loc", (uint64_t) shdr->sh_offset);
-
- // XXX add something
-}
-
-
-struct mac_culist
-{
- Dwarf_Die die;
- Dwarf_Off offset;
- Dwarf_Files *files;
- struct mac_culist *next;
-};
-
-
-static int
-mac_compare (const void *p1, const void *p2)
-{
- struct mac_culist *m1 = (struct mac_culist *) p1;
- struct mac_culist *m2 = (struct mac_culist *) p2;
-
- if (m1->offset < m2->offset)
- return -1;
- if (m1->offset > m2->offset)
- return 1;
- return 0;
-}
-
-
-static void
-print_debug_macinfo_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_macinfo", (uint64_t) shdr->sh_offset);
- putc_unlocked ('\n', stdout);
-
- /* There is no function in libdw to iterate over the raw content of
- the section but it is easy enough to do. */
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL || data->d_buf == NULL)
- {
- error (0, 0, gettext ("cannot get macro information section data: %s"),
- elf_errmsg (-1));
- return;
- }
-
- /* Get the source file information for all CUs. */
- Dwarf_Off offset;
- Dwarf_Off ncu = 0;
- size_t hsize;
- struct mac_culist *culist = NULL;
- size_t nculist = 0;
- while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
- {
- Dwarf_Die cudie;
- if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
- continue;
-
- Dwarf_Attribute attr;
- if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
- continue;
-
- Dwarf_Word macoff;
- if (dwarf_formudata (&attr, &macoff) != 0)
- continue;
-
- struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
- newp->die = cudie;
- newp->offset = macoff;
- newp->files = NULL;
- newp->next = culist;
- culist = newp;
- ++nculist;
- }
-
- /* Convert the list into an array for easier consumption. */
- struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
- * sizeof (*cus));
- /* Add sentinel. */
- cus[nculist].offset = data->d_size;
- if (nculist > 0)
- {
- for (size_t cnt = nculist - 1; culist != NULL; --cnt)
- {
- assert (cnt < nculist);
- cus[cnt] = *culist;
- culist = culist->next;
- }
-
- /* Sort the array according to the offset in the .debug_macinfo
- section. Note we keep the sentinel at the end. */
- qsort (cus, nculist, sizeof (*cus), mac_compare);
- }
-
- const unsigned char *readp = (const unsigned char *) data->d_buf;
- const unsigned char *readendp = readp + data->d_size;
- int level = 1;
-
- while (readp < readendp)
- {
- unsigned int opcode = *readp++;
- unsigned int u128;
- unsigned int u128_2;
- const unsigned char *endp;
-
- switch (opcode)
- {
- case DW_MACINFO_define:
- case DW_MACINFO_undef:
- case DW_MACINFO_vendor_ext:
- /* For the first two opcodes the parameters are
- line, string
- For the latter
- number, string.
- We can treat these cases together. */
- get_uleb128 (u128, readp);
-
- endp = memchr (readp, '\0', readendp - readp);
- if (endp == NULL)
- {
- printf (gettext ("\
-%*s*** non-terminated string at end of section"),
- level, "");
- return;
- }
-
- if (opcode == DW_MACINFO_define)
- printf ("%*s#define %s, line %u\n",
- level, "", (char *) readp, u128);
- else if (opcode == DW_MACINFO_undef)
- printf ("%*s#undef %s, line %u\n",
- level, "", (char *) readp, u128);
- else
- printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
-
- readp = endp + 1;
- break;
-
- case DW_MACINFO_start_file:
- /* The two parameters are line and file index, in this order. */
- get_uleb128 (u128, readp);
- get_uleb128 (u128_2, readp);
-
- /* Find the CU DIE for this file. */
- ptrdiff_t macoff = readp - (const unsigned char *) data->d_buf;
- const char *fname = "???";
- if (macoff >= cus[0].offset)
- {
- while (macoff >= cus[1].offset)
- ++cus;
-
- if (cus[0].files == NULL
- && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
- cus[0].files = (Dwarf_Files *) -1l;
-
- if (cus[0].files != (Dwarf_Files *) -1l)
- fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
- ?: "???");
- }
-
- printf ("%*sstart_file %u, [%u] %s\n",
- level, "", u128, u128_2, fname);
- ++level;
- break;
-
- case DW_MACINFO_end_file:
- --level;
- printf ("%*send_file\n", level, "");
- /* Nothing more to do. */
- break;
-
- default:
- // XXX gcc seems to generate files with a trailing zero.
- if (opcode != 0 || readp != readendp)
- printf ("%*s*** invalid opcode %u\n", level, "", opcode);
- break;
- }
- }
-}
-
-
-/* Callback for printing global names. */
-static int
-print_pubnames (Dwarf *dbg, Dwarf_Global *global, void *arg)
-{
- int *np = (int *) arg;
-
- printf (gettext (" [%5d] DIE offset: %6" PRId64
- ", CU DIE offset: %6" PRId64 ", name: %s\n"),
- (*np)++, global->die_offset, global->cu_offset, global->name);
-
- return 0;
-}
-
-
-/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
-static void
-print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_pubnames", (uint64_t) shdr->sh_offset);
-
- int n = 0;
- (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
-}
-
-/* Print the content of the DWARF string section '.debug_str'. */
-static void
-print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
-{
- /* Compute floor(log16(shdr->sh_size)). */
- GElf_Addr tmp = shdr->sh_size;
- int digits = 1;
- while (tmp >= 16)
- {
- ++digits;
- tmp >>= 4;
- }
- digits = MAX (4, digits);
-
- printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
- " %*s String\n"),
- ".debug_str", (uint64_t) shdr->sh_offset,
- /* TRANS: the debugstr| prefix makes the string unique. */
- digits + 2, sgettext ("debugstr|Offset"));
-
- Dwarf_Off offset = 0;
- while (offset < shdr->sh_size)
- {
- size_t len;
- const char *str = dwarf_getstring (dbg, offset, &len);
- if (str == NULL)
- {
- printf (gettext (" *** error while reading strings: %s\n"),
- dwarf_errmsg (-1));
- break;
- }
-
- printf (" [%*" PRIx64 "] \"%s\"\n", digits, (uint64_t) offset, str);
-
- offset += len + 1;
- }
-}
-
-
-static void
-print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- /* Find the version information sections. For this we have to
- search through the section table. */
- Dwarf *dbg;
- Elf_Scn *scn;
- size_t shstrndx;
-
- /* Before we start the real work get a debug context descriptor. */
- dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
- if (dbg == NULL)
- {
- error (0, 0, gettext ("cannot get debug context descriptor: %s"),
- dwarf_errmsg (-1));
- return;
- }
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- scn = NULL;
- while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
- {
- /* Handle the section if it is part of the versioning handling. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr != NULL || shdr->sh_type != SHT_PROGBITS)
- {
- static const struct
- {
- const char *name;
- enum section_e bitmask;
- void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
- } debug_sections[] =
- {
-#define NEW_SECTION(name) \
- { ".debug_" #name, section_##name, print_debug_##name##_section }
- NEW_SECTION (abbrev),
- NEW_SECTION (aranges),
- NEW_SECTION (frame),
- NEW_SECTION (info),
- NEW_SECTION (line),
- NEW_SECTION (loc),
- NEW_SECTION (pubnames),
- NEW_SECTION (str),
- NEW_SECTION (macinfo),
- { ".eh_frame", section_frame, print_debug_frame_section }
- };
- const int ndebug_sections = (sizeof (debug_sections)
- / sizeof (debug_sections[0]));
- const char *name = elf_strptr (ebl->elf, shstrndx,
- shdr->sh_name);
- int n;
-
- for (n = 0; n < ndebug_sections; ++n)
- if (strcmp (name, debug_sections[n].name) == 0)
- {
- if (print_debug_sections & debug_sections[n].bitmask)
- debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
- break;
- }
- }
- }
-
- /* We are done with the DWARF handling. */
- dwarf_end (dbg);
-}
-
-
-static void
-handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
-{
- int class = gelf_getclass (ebl->elf);
- size_t cnt;
-
- /* We have to look through the program header to find the note
- sections. There can be more than one. */
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr mem;
- GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
-
- if (phdr == NULL || phdr->p_type != PT_NOTE)
- /* Not what we are looking for. */
- continue;
-
- printf (gettext ("\
-\nNote segment of %" PRId64 " bytes at offset %#0" PRIx64 ":\n"),
- phdr->p_filesz, phdr->p_offset);
-
- char *notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
- if (notemem == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get content of note section: %s"),
- elf_errmsg (-1));
-
- fputs_unlocked (gettext (" Owner Data size Type\n"), stdout);
-
-
- /* Handle the note section content. It consists of one or more
- entries each of which consists of five parts:
-
- - a 32-bit name length
- - a 32-bit descriptor length
- - a 32-bit type field
- - the NUL-terminated name, length as specified in the first field
- - the descriptor, length as specified in the second field
-
- The variable sized fields are padded to 32- or 64-bits
- depending on whether the file is a 32- or 64-bit ELF file.
- */
- size_t align = class == ELFCLASS32 ? 4 : 8;
-#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
-
- size_t idx = 0;
- while (idx < phdr->p_filesz)
- {
- /* XXX Handle 64-bit note section entries correctly. */
- struct
- {
- uint32_t namesz;
- uint32_t descsz;
- uint32_t type;
- char name[0];
- } *noteentry = (__typeof (noteentry)) (notemem + idx);
-
- if (idx + 12 > phdr->p_filesz
- || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
- + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
- /* This entry isn't completely contained in the note
- section. Ignore it. */
- break;
-
- char buf[100];
- char buf2[100];
- printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
- (int) noteentry->namesz, noteentry->name,
- noteentry->descsz,
- ehdr->e_type == ET_CORE
- ? ebl_core_note_type_name (ebl, noteentry->type,
- buf, sizeof (buf))
- : ebl_object_note_type_name (ebl, noteentry->type,
- buf2, sizeof (buf2)));
-
- /* Filter out invalid entries. */
- if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
- /* XXX For now help broken Linux kernels. */
- || 1)
- {
- if (ehdr->e_type == ET_CORE)
- ebl_core_note (ebl, noteentry->name, noteentry->type,
- noteentry->descsz,
- &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
- else
- ebl_object_note (ebl, noteentry->name, noteentry->type,
- noteentry->descsz,
- &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
- }
-
- /* Move to the next entry. */
- idx += (12 + ALIGNED_LEN (noteentry->namesz)
- + ALIGNED_LEN (noteentry->descsz));
- }
-
- gelf_freechunk (ebl->elf, notemem);
- }
-}
diff --git a/src/sectionhash.c b/src/sectionhash.c
deleted file mode 100644
index dc559409..00000000
--- a/src/sectionhash.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Section hash table implementation.
- Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <elf-knowledge.h>
-#include <ld.h>
-
-
-/* Comparison function for sections. */
-static int
-scnhead_compare (struct scnhead *one, struct scnhead *two)
-{
- int result = strcmp (one->name, two->name);
-
- if (result == 0)
- {
- result = one->type - two->type;
-
- if (result == 0)
- {
- GElf_Xword diff = (SH_FLAGS_IMPORTANT (one->flags)
- - SH_FLAGS_IMPORTANT (two->flags));
- result = diff < 0 ? -1 : diff == 0 ? 0 : 1;
-
- if (result == 0)
- {
- result = one->entsize - two->entsize;
-
- if (result == 0)
- {
- result = (one->grp_signature == NULL
- ? (two->grp_signature == NULL ? 0 : -1)
- : (two->grp_signature == NULL
- ? 1 : strcmp (one->grp_signature,
- two->grp_signature)));
-
- if (result == 0)
- result = one->kind - two->kind;
- }
- }
- }
- }
-
- return result;
-}
-
-/* Definitions for the section hash table. */
-#define TYPE struct scnhead *
-#define NAME ld_section_tab
-#define ITERATE 1
-#define COMPARE(a, b) scnhead_compare (a, b)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/sectionhash.h b/src/sectionhash.h
deleted file mode 100644
index 50bcb9c8..00000000
--- a/src/sectionhash.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifndef SECTIONHASH_H
-#define SECTIONHASH_H 1
-
-/* Definitions for the section hash table. */
-#define TYPE struct scnhead *
-#define NAME ld_section_tab
-#define ITERATE 1
-#include <dynamicsizehash.h>
-
-#endif /* sectionhash.h */
diff --git a/src/size.c b/src/size.c
deleted file mode 100644
index e9edb677..00000000
--- a/src/size.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/* Print size information from ELF file.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2000.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <error.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <libelf.h>
-#include <libintl.h>
-#include <locale.h>
-#include <mcheck.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include <system.h>
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-
-/* Values for the parameters which have no short form. */
-#define OPT_FORMAT 0x100
-#define OPT_RADIX 0x101
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { NULL, 0, NULL, 0, N_("Output format:") },
- { "format", OPT_FORMAT, "FORMAT", 0, N_("Use the output format FORMAT. FORMAT can be `bsd' or `sysv'. The default is `bsd'") },
- { NULL, 'A', NULL, 0, N_("Same as `--format=sysv'") },
- { NULL, 'B', NULL, 0, N_("Same as `--format=bsd'") },
- { "radix", OPT_RADIX, "RADIX", 0, N_("Use RADIX for printing symbol values") },
- { NULL, 'd', NULL, 0, N_("Same as `--radix=10'") },
- { NULL, 'o', NULL, 0, N_("Same as `--radix=8'") },
- { NULL, 'x', NULL, 0, N_("Same as `--radix=16'") },
- { NULL, 'f', NULL, 0, N_("Similar to `--format=sysv' output but in one line") },
-
- { NULL, 0, NULL, 0, N_("Output options:") },
- { NULL, 'F', NULL, 0, N_("Print size and permission flags for loadable segments") },
- { "totals", 't', NULL, 0, N_("Display the total sizes (bsd only)") },
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("\
-List section sizes of FILEs (a.out by default).");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("[FILE...]");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help
-};
-
-
-/* Print symbols in file named FNAME. */
-static int process_file (const char *fname);
-
-/* Handle content of archive. */
-static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname);
-
-/* Handle ELF file. */
-static void handle_elf (Elf *elf, const char *fullname, const char *fname);
-
-/* Show total size. */
-static void show_bsd_totals (void);
-
-#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
-
-
-/* User-selectable options. */
-
-/* The selected output format. */
-static enum
-{
- format_bsd = 0,
- format_sysv,
- format_sysv_one_line,
- format_segments
-} format;
-
-/* Radix for printed numbers. */
-static enum
-{
- radix_decimal = 0,
- radix_hex,
- radix_octal
-} radix;
-
-
-/* Mapping of radix and binary class to length. */
-static const int length_map[2][3] =
-{
- [ELFCLASS32 - 1] =
- {
- [radix_hex] = 8,
- [radix_decimal] = 10,
- [radix_octal] = 11
- },
- [ELFCLASS64 - 1] =
- {
- [radix_hex] = 16,
- [radix_decimal] = 20,
- [radix_octal] = 22
- }
-};
-
-/* True if total sizes should be printed. */
-static bool totals;
-/* To print the total sizes in a reasonable format remember the higest
- "class" of ELF binaries processed. */
-static int totals_class;
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- int result = 0;
-
- /* Make memory leak detection possible. */
- mtrace ();
-
- /* We use no threads here which can interfere with handling a stream. */
- __fsetlocking (stdin, FSETLOCKING_BYCALLER);
- __fsetlocking (stdout, FSETLOCKING_BYCALLER);
- __fsetlocking (stderr, FSETLOCKING_BYCALLER);
-
- /* Set locale. */
- setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- bindtextdomain (PACKAGE, LOCALEDIR);
-
- /* Initialize the message catalog. */
- textdomain (PACKAGE);
-
- /* Parse and process arguments. */
- argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
-
- /* Tell the library which version we are expecting. */
- elf_version (EV_CURRENT);
-
- if (remaining == argc)
- /* The user didn't specify a name so we use a.out. */
- result = process_file ("a.out");
- else
- /* Process all the remaining files. */
- do
- result |= process_file (argv[remaining]);
- while (++remaining < argc);
-
- /* Print the total sizes but only if the output format is BSD and at
- least one file has been correctly read (i.e., we recognized the
- class). */
- if (totals && format == format_bsd && totals_class != 0)
- show_bsd_totals ();
-
- return result;
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "size (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'd':
- radix = radix_decimal;
- break;
-
- case 'f':
- format = format_sysv_one_line;
- break;
-
- case 'o':
- radix = radix_octal;
- break;
-
- case 'x':
- radix = radix_hex;
- break;
-
- case 'A':
- format = format_sysv;
- break;
-
- case 'B':
- format = format_bsd;
- break;
-
- case 'F':
- format = format_segments;
- break;
-
- case OPT_FORMAT:
- if (strcmp (arg, "bsd") == 0 || strcmp (arg, "berkeley") == 0)
- format = format_bsd;
- else if (strcmp (arg, "sysv") == 0)
- format = format_sysv;
- else
- error (EXIT_FAILURE, 0, gettext ("Invalid format: %s"), arg);
- break;
-
- case OPT_RADIX:
- if (strcmp (arg, "x") == 0 || strcmp (arg, "16") == 0)
- radix = radix_hex;
- else if (strcmp (arg, "d") == 0 || strcmp (arg, "10") == 0)
- radix = radix_decimal;
- else if (strcmp (arg, "o") == 0 || strcmp (arg, "8") == 0)
- radix = radix_octal;
- else
- error (EXIT_FAILURE, 0, gettext ("Invalid radix: %s"), arg);
- break;
-
- case 't':
- totals = true;
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-static int
-process_file (const char *fname)
-{
- /* Open the file and determine the type. */
- int fd;
- Elf *elf;
-
- /* Open the file. */
- fd = open (fname, O_RDONLY);
- if (fd == -1)
- {
- error (0, errno, fname);
- return 1;
- }
-
- /* Now get the ELF descriptor. */
- elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf != NULL)
- {
- if (elf_kind (elf) == ELF_K_ELF)
- {
- handle_elf (elf, NULL, fname);
-
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
-
- if (close (fd) != 0)
- error (EXIT_FAILURE, errno, gettext ("while close `%s'"), fname);
-
- return 0;
- }
- else
- return handle_ar (fd, elf, NULL, fname);
-
- /* We cannot handle this type. Close the descriptor anyway. */
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
- }
-
- error (0, 0, gettext ("%s: file format not recognized"), fname);
-
- return 1;
-}
-
-
-/* Print the BSD-style header. This is done exactly once. */
-static void
-print_header (Elf *elf)
-{
- static int done;
-
- if (! done)
- {
- int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
- int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
-
- printf ("%*s %*s %*s %*s %*s %s\n",
- ddigits - 2, sgettext ("bsd|text"),
- ddigits - 2, sgettext ("bsd|data"),
- ddigits - 2, sgettext ("bsd|bss"),
- ddigits - 2, sgettext ("bsd|dec"),
- xdigits - 2, sgettext ("bsd|hex"),
- sgettext ("bsd|filename"));
-
- done = 1;
- }
-}
-
-
-static int
-handle_ar (int fd, Elf *elf, const char *prefix, const char *fname)
-{
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char new_prefix[prefix_len + 1 + fname_len];
- int result = 0;
- char *cp = new_prefix;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
-
- /* Process all the files contained in the archive. */
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- /* The the header for this element. */
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
-
- if (elf_kind (subelf) == ELF_K_ELF)
- handle_elf (subelf, new_prefix, arhdr->ar_name);
- else if (elf_kind (subelf) == ELF_K_AR)
- result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name);
- /* else signal error??? */
-
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (elf_end (subelf) != 0)
- INTERNAL_ERROR (fname);
- }
-
- if (elf_end (elf) != 0)
- INTERNAL_ERROR (fname);
-
- if (close (fd) != 0)
- error (EXIT_FAILURE, errno, gettext ("while closing `%s'"), fname);
-
- return result;
-}
-
-
-/* Show sizes in SysV format. */
-static void
-show_sysv (Elf *elf, const char *prefix, const char *fname,
- const char *fullname)
-{
- size_t shstrndx;
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr_mem;
- int maxlen = 10;
- int digits = length_map[gelf_getclass (elf) - 1][radix];
- const char *fmtstr;
- GElf_Off total = 0;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* First round over the sections: determine the longest section name. */
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr == NULL)
- INTERNAL_ERROR (fullname);
-
- /* Ignore all sections which are not used at runtime. */
- if ((shdr->sh_flags & SHF_ALLOC) != 0)
- maxlen = MAX (maxlen,
- strlen (elf_strptr (elf, shstrndx, shdr->sh_name)));
- }
-
- fputs_unlocked (fname, stdout);
- if (prefix != NULL)
- printf (gettext (" (ex %s)"), prefix);
- printf (":\n%-*s %*s %*s\n",
- maxlen, sgettext ("sysv|section"),
- digits - 2, sgettext ("sysv|size"),
- digits, sgettext ("sysv|addr"));
-
- if (radix == radix_hex)
- fmtstr = "%-*s %*" PRIx64 " %*" PRIx64 "\n";
- else if (radix == radix_decimal)
- fmtstr = "%-*s %*" PRId64 " %*" PRId64 "\n";
- else
- fmtstr = "%-*s %*" PRIo64 " %*" PRIo64 "\n";
-
- /* Iterate over all sections. */
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- /* Ignore all sections which are not used at runtime. */
- if ((shdr->sh_flags & SHF_ALLOC) != 0)
- {
- printf (fmtstr,
- maxlen, elf_strptr (elf, shstrndx, shdr->sh_name),
- digits - 2, shdr->sh_size,
- digits, shdr->sh_addr);
-
- total += shdr->sh_size;
- }
- }
-
- if (radix == radix_hex)
- printf ("%-*s %*" PRIx64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
- digits - 2, total);
- else if (radix == radix_decimal)
- printf ("%-*s %*" PRId64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
- digits - 2, total);
- else
- printf ("%-*s %*" PRIo64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
- digits - 2, total);
-}
-
-
-/* Show sizes in SysV format in one line. */
-static void
-show_sysv_one_line (Elf *elf, const char *prefix, const char *fname,
- const char *fullname)
-{
- size_t shstrndx;
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr_mem;
- const char *fmtstr;
- GElf_Off total = 0;
- int first = 1;
-
- /* Get the section header string table index. */
- if (elf_getshstrndx (elf, &shstrndx) < 0)
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- if (radix == radix_hex)
- fmtstr = "%" PRIx64 "(%s)";
- else if (radix == radix_decimal)
- fmtstr = "%" PRId64 "(%s)";
- else
- fmtstr = "%" PRIo64 "(%s)";
-
- /* Iterate over all sections. */
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- /* Ignore all sections which are not used at runtime. */
- if ((shdr->sh_flags & SHF_ALLOC) == 0)
- continue;
-
- if (! first)
- fputs_unlocked (" + ", stdout);
- first = 0;
-
- printf (fmtstr, shdr->sh_size,
- elf_strptr (elf, shstrndx, shdr->sh_name));
-
- total += shdr->sh_size;
- }
-
- if (radix == radix_hex)
- printf (" = %#" PRIx64 "\n", total);
- else if (radix == radix_decimal)
- printf (" = %" PRId64 "\n", total);
- else
- printf (" = %" PRIo64 "\n", total);
-}
-
-
-/* Variables to add up the sizes of all files. */
-static uintmax_t total_textsize;
-static uintmax_t total_datasize;
-static uintmax_t total_bsssize;
-
-
-/* Show sizes in BSD format. */
-static void
-show_bsd (Elf *elf, const char *prefix, const char *fname,
- const char *fullname)
-{
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr_mem;
- GElf_Off textsize = 0;
- GElf_Off datasize = 0;
- GElf_Off bsssize = 0;
- int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
- int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
-
- /* Iterate over all sections. */
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
- if (shdr == NULL)
- INTERNAL_ERROR (fullname);
-
- /* Ignore all sections which are not marked as loaded. */
- if ((shdr->sh_flags & SHF_ALLOC) == 0)
- continue;
-
- if ((shdr->sh_flags & SHF_WRITE) == 0)
- textsize += shdr->sh_size;
- else if (shdr->sh_type == SHT_NOBITS)
- bsssize += shdr->sh_size;
- else
- datasize += shdr->sh_size;
- }
-
- printf ("%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*"
- PRIx64 " %s",
- ddigits - 2, textsize,
- ddigits - 2, datasize,
- ddigits - 2, bsssize,
- ddigits - 2, textsize + datasize + bsssize,
- xdigits - 2, textsize + datasize + bsssize,
- fname);
- if (prefix != NULL)
- printf (gettext (" (ex %s)"), prefix);
- fputs_unlocked ("\n", stdout);
-
- total_textsize += textsize;
- total_datasize += datasize;
- total_bsssize += bsssize;
-
- totals_class = MAX (totals_class, gelf_getclass (elf));
-}
-
-
-/* Show total size. */
-static void
-show_bsd_totals (void)
-{
- int ddigits = length_map[totals_class - 1][radix_decimal];
- int xdigits = length_map[totals_class - 1][radix_hex];
-
- printf ("%*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*"
- PRIxMAX " %s",
- ddigits - 2, total_textsize,
- ddigits - 2, total_datasize,
- ddigits - 2, total_bsssize,
- ddigits - 2, total_textsize + total_datasize + total_bsssize,
- xdigits - 2, total_textsize + total_datasize + total_bsssize,
- gettext ("(TOTALS)\n"));
-}
-
-
-/* Show size and permission of loadable segments. */
-static void
-show_segments (Elf *elf, const char *prefix, const char *fname,
- const char *fullname)
-{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr;
- size_t cnt;
- GElf_Off total = 0;
- int first = 1;
-
- ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr == NULL)
- INTERNAL_ERROR (fullname);
-
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (elf, cnt, &phdr_mem);
- if (phdr == NULL)
- INTERNAL_ERROR (fullname);
-
- if (phdr->p_type != PT_LOAD)
- /* Only load segments. */
- continue;
-
- if (! first)
- fputs_unlocked (" + ", stdout);
- first = 0;
-
- printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)"
- : (radix == radix_decimal ? "%" PRId64 "(%c%c%c)"
- : "%" PRIo64 "(%c%c%c)"),
- phdr->p_memsz,
- (phdr->p_flags & PF_R) == 0 ? '-' : 'r',
- (phdr->p_flags & PF_W) == 0 ? '-' : 'w',
- (phdr->p_flags & PF_X) == 0 ? '-' : 'x');
-
- total += phdr->p_memsz;
- }
-
- if (radix == radix_hex)
- printf (" = %#" PRIx64 "\n", total);
- else if (radix == radix_decimal)
- printf (" = %" PRId64 "\n", total);
- else
- printf (" = %" PRIo64 "\n", total);
-}
-
-
-static void
-handle_elf (Elf *elf, const char *prefix, const char *fname)
-{
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char fullname[prefix_len + 1 + fname_len];
- char *cp = fullname;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
-
- if (format == format_sysv)
- show_sysv (elf, prefix, fname, fullname);
- else if (format == format_sysv_one_line)
- show_sysv_one_line (elf, prefix, fname, fullname);
- else if (format == format_segments)
- show_segments (elf, prefix, fname, fullname);
- else
- {
- print_header (elf);
-
- show_bsd (elf, prefix, fname, fullname);
- }
-}
diff --git a/src/strip.c b/src/strip.c
deleted file mode 100644
index e5c4289c..00000000
--- a/src/strip.c
+++ /dev/null
@@ -1,1769 +0,0 @@
-/* Discard section not used at runtime from object files.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2000.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <assert.h>
-#include <byteswap.h>
-#include <endian.h>
-#include <error.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <libelf.h>
-#include <libintl.h>
-#include <locale.h>
-#include <mcheck.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/time.h>
-
-#include <elf-knowledge.h>
-#include <libebl.h>
-#include <system.h>
-
-
-/* Name and version of program. */
-static void print_version (FILE *stream, struct argp_state *state);
-void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
-
-
-/* Values for the parameters which have no short form. */
-#define OPT_REMOVE_COMMENT 0x100
-#define OPT_PERMISSIVE 0x101
-
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { NULL, 0, NULL, 0, N_("Output selection:") },
- { NULL, 'o', "FILE", 0, N_("Place stripped output into FILE") },
- { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE") },
-
- { NULL, 0, NULL, 0, N_("Output options:") },
- { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols") },
- { "preserve-dates", 'p', NULL, 0,
- N_("Copy modified/access timestamps to the output") },
- { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
- N_("Remove .comment section") },
- { "permissive", OPT_PERMISSIVE, NULL, 0,
- N_("Relax a few rules to handle slightly broken ELF files") },
- { NULL, 0, NULL, 0, NULL }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("Discard symbols from object files.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("[FILE...]");
-
-/* Prototype for option handler. */
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Function to print some extra text in the help message. */
-static char *more_help (int key, const char *text, void *input);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, more_help
-};
-
-
-/* Print symbols in file named FNAME. */
-static int process_file (const char *fname);
-
-/* Handle one ELF file. */
-static int handle_elf (int fd, Elf *elf, const char *prefix,
- const char *fname, mode_t mode, struct timeval tvp[2]);
-
-/* Handle all files contained in the archive. */
-static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
- struct timeval tvp[2]);
-
-#define INTERNAL_ERROR(fname) \
- error (EXIT_FAILURE, 0, gettext ("%s: INTERNAL ERROR %d (%s-%s): %s"), \
- fname, __LINE__, VERSION, __DATE__, elf_errmsg (-1))
-
-
-/* Name of the output file. */
-static const char *output_fname;
-
-/* Name of the debug output file. */
-static const char *debug_fname;
-
-/* If true output files shall have same date as the input file. */
-static bool preserve_dates;
-
-/* If true .comment sections will be removed. */
-static bool remove_comment;
-
-/* If true remove all debug sections. */
-static bool remove_debug;
-
-/* If true relax some ELF rules for input files. */
-static bool permissive;
-
-
-int
-main (int argc, char *argv[])
-{
- int remaining;
- int result = 0;
-
- /* Make memory leak detection possible. */
- mtrace ();
-
- /* We use no threads here which can interfere with handling a stream. */
- __fsetlocking (stdin, FSETLOCKING_BYCALLER);
- __fsetlocking (stdout, FSETLOCKING_BYCALLER);
- __fsetlocking (stderr, FSETLOCKING_BYCALLER);
-
- /* Set locale. */
- setlocale (LC_ALL, "");
-
- /* Make sure the message catalog can be found. */
- bindtextdomain (PACKAGE, LOCALEDIR);
-
- /* Initialize the message catalog. */
- textdomain (PACKAGE);
-
- /* Parse and process arguments. */
- argp_parse (&argp, argc, argv, 0, &remaining, NULL);
-
- /* Tell the library which version we are expecting. */
- elf_version (EV_CURRENT);
-
- if (remaining == argc)
- /* The user didn't specify a name so we use a.out. */
- result = process_file ("a.out");
- else
- {
- /* If we have seen the `-o' or '-f' option there must be exactly one
- input file. */
- if ((output_fname != NULL || debug_fname != NULL)
- && remaining + 1 < argc)
- error (EXIT_FAILURE, 0, gettext ("\
-Only one input file allowed together with '-o' and '-f'"));
-
- /* Process all the remaining files. */
- do
- result |= process_file (argv[remaining]);
- while (++remaining < argc);
- }
-
- return result;
-}
-
-
-/* Print the version information. */
-static void
-print_version (FILE *stream, struct argp_state *state)
-{
- fprintf (stream, "strip (%s) %s\n", PACKAGE_NAME, VERSION);
- fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions. There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2004");
- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg, struct argp_state *state)
-{
- switch (key)
- {
- case 'f':
- debug_fname = arg;
- break;
-
- case 'o':
- output_fname = arg;
- break;
-
- case 'p':
- preserve_dates = true;
- break;
-
- case OPT_REMOVE_COMMENT:
- remove_comment = true;
- break;
-
- case 'g':
- remove_debug = true;
- break;
-
- case OPT_PERMISSIVE:
- permissive = true;
- break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
-
-
-static char *
-more_help (int key, const char *text, void *input)
-{
- char *buf;
-
- switch (key)
- {
- case ARGP_KEY_HELP_EXTRA:
- /* We print some extra information. */
- if (asprintf (&buf, gettext ("Please report bugs to %s.\n"),
- PACKAGE_BUGREPORT) < 0)
- buf = NULL;
- return buf;
-
- default:
- break;
- }
- return (char *) text;
-}
-
-
-static int
-process_file (const char *fname)
-{
- /* If we have to preserve the modify and access timestamps get them
- now. We cannot use fstat() after opening the file since the open
- would change the access time. */
- struct stat64 pre_st;
- struct timeval tv[2];
- again:
- if (preserve_dates)
- {
- if (stat64 (fname, &pre_st) != 0)
- {
- error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
- return 1;
- }
-
- /* If we have to preserve the timestamp, we need it in the
- format utimes() understands. */
- TIMESPEC_TO_TIMEVAL (&tv[0], &pre_st.st_atim);
- TIMESPEC_TO_TIMEVAL (&tv[1], &pre_st.st_mtim);
- }
-
- /* Open the file. */
- int fd = open (fname, O_RDWR);
- if (fd == -1)
- {
- error (0, errno, gettext ("while opening \"%s\""), fname);
- return 1;
- }
-
- /* We always use fstat() even if we called stat() before. This is
- done to make sure the information returned by stat() is for the
- same file. */
- struct stat64 st;
- if (fstat64 (fd, &st) != 0)
- {
- error (0, errno, gettext ("cannot stat input file \"%s\""), fname);
- return 1;
- }
- /* Paranoid mode on. */
- if (preserve_dates
- && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
- {
- /* We detected a race. Try again. */
- close (fd);
- goto again;
- }
-
- /* Now get the ELF descriptor. */
- Elf *elf = elf_begin (fd, ELF_C_RDWR, NULL);
- int result;
- switch (elf_kind (elf))
- {
- case ELF_K_ELF:
- result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
- preserve_dates ? tv : NULL);
- break;
-
- case ELF_K_AR:
- /* It is not possible to strip the content of an archive direct
- the output to a specific file. */
- if (unlikely (output_fname != NULL))
- {
- error (0, 0, gettext ("%s: cannot use -o when stripping archive"),
- fname);
- result = 1;
- }
- else
- result = handle_ar (fd, elf, NULL, fname, preserve_dates ? tv : NULL);
- break;
-
- default:
- error (0, 0, gettext ("%s: File format not recognized"), fname);
- result = 1;
- break;
- }
-
- if (unlikely (elf_end (elf) != 0))
- INTERNAL_ERROR (fname);
-
- close (fd);
-
- return result;
-}
-
-
-/* Maximum size of array allocated on stack. */
-#define MAX_STACK_ALLOC (400 * 1024)
-
-
-static uint32_t
-crc32_file (int fd, uint32_t *resp)
-{
- unsigned char buffer[1024 * 8];
- uint32_t crc = 0;
- ssize_t count;
-
- /* We have to rewind. */
- if (lseek (fd, 0, SEEK_SET) < 0)
- return 1;
-
- while ((count = TEMP_FAILURE_RETRY (read (fd, buffer, sizeof (buffer)))) > 0)
- crc = crc32 (crc, buffer, count);
-
- *resp = crc;
-
- return count != 0;
-}
-
-
-static int
-handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
- mode_t mode, struct timeval tvp[2])
-{
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char *fullname = alloca (prefix_len + 1 + fname_len);
- char *cp = fullname;
- Elf *newelf;
- Elf *debugelf = NULL;
- char *tmp_debug_fname = NULL;
- int result = 0;
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr;
- size_t shstrndx;
- size_t shnum;
- struct shdr_info
- {
- Elf_Scn *scn;
- GElf_Shdr shdr;
- Elf_Data *data;
- const char *name;
- Elf32_Word idx; /* Index in new file. */
- Elf32_Word old_sh_link; /* Original value of shdr.sh_link. */
- Elf32_Word symtab_idx;
- Elf32_Word version_idx;
- Elf32_Word group_idx;
- Elf32_Word group_cnt;
- Elf_Scn *newscn;
- struct Ebl_Strent *se;
- Elf32_Word *newsymidx;
- } *shdr_info = NULL;
- Elf_Scn *scn;
- size_t cnt;
- size_t idx;
- bool changes;
- GElf_Ehdr newehdr_mem;
- GElf_Ehdr *newehdr;
- GElf_Ehdr debugehdr_mem;
- GElf_Ehdr *debugehdr;
- struct Ebl_Strtab *shst = NULL;
- uint32_t debug_crc;
- bool any_symtab_changes = false;
- Elf_Data *shstrtab_data = NULL;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
-
- /* If we are not replacing the input file open a new file here. */
- if (output_fname != NULL)
- {
- fd = open (output_fname, O_RDWR | O_CREAT, mode);
- if (unlikely (fd == -1))
- {
- error (0, errno, gettext ("cannot open `%s'"), output_fname);
- return 1;
- }
- }
-
- int debug_fd = -1;
-
- /* Get the EBL handling. The -g option is currently the only reason
- we need EBL so dont open the backend unless necessary. */
- Ebl *ebl = NULL;
- if (remove_debug)
- {
- ebl = ebl_openbackend (elf);
- if (ebl == NULL)
- {
- error (0, errno, gettext ("cannot open EBL backend"));
- result = 1;
- goto fail;
- }
- }
-
- /* Open the additional file the debug information will be stored in. */
- if (debug_fname != NULL)
- {
- /* Create a temporary file name. We do not want to overwrite
- the debug file if the file would not contain any
- information. */
- size_t debug_fname_len = strlen (debug_fname);
- tmp_debug_fname = (char *) alloca (debug_fname_len + sizeof (".XXXXXX"));
- strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
- ".XXXXXX");
-
- debug_fd = mkstemp (tmp_debug_fname);
- if (unlikely (debug_fd == -1))
- {
- error (0, errno, gettext ("cannot open `%s'"), debug_fname);
- result = 1;
- goto fail;
- }
- }
-
- /* Get the information from the old file. */
- ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr == NULL)
- INTERNAL_ERROR (fname);
-
- /* Get the section header string table index. */
- if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
- error (EXIT_FAILURE, 0,
- gettext ("cannot get section header string table index"));
-
- /* We now create a new ELF descriptor for the same file. We
- construct it almost exactly in the same way with some information
- dropped. */
- if (output_fname != NULL)
- newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
- else
- newelf = elf_clone (elf, ELF_C_EMPTY);
-
- if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
- || (ehdr->e_type != ET_REL
- && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
- {
- error (0, 0, gettext ("cannot create new file `%s': %s"),
- output_fname, elf_errmsg (-1));
- goto fail;
- }
-
- /* Copy over the old program header if needed. */
- if (ehdr->e_type != ET_REL)
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (elf, cnt, &phdr_mem);
- if (phdr == NULL
- || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
- INTERNAL_ERROR (fname);
- }
-
- if (debug_fname != NULL)
- {
- /* Also create an ELF descriptor for the debug file */
- debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
- if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
- || (ehdr->e_type != ET_REL
- && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
- {
- error (0, 0, gettext ("cannot create new file `%s': %s"),
- debug_fname, elf_errmsg (-1));
- goto fail_close;
- }
-
- /* Copy over the old program header if needed. */
- if (ehdr->e_type != ET_REL)
- for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
- {
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr;
-
- phdr = gelf_getphdr (elf, cnt, &phdr_mem);
- if (phdr == NULL
- || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
- INTERNAL_ERROR (fname);
- }
- }
-
- /* Number of sections. */
- if (unlikely (elf_getshnum (elf, &shnum) < 0))
- {
- error (0, 0, gettext ("cannot determine number of sections: %s"),
- elf_errmsg (-1));
- goto fail_close;
- }
-
- /* Storage for section information. We leave room for two more
- entries since we unconditionally create a section header string
- table. Maybe some weird tool created an ELF file without one.
- The other one is used for the debug link section. */
- if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
- shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
- sizeof (struct shdr_info));
- else
- {
- shdr_info = (struct shdr_info *) alloca ((shnum + 2)
- * sizeof (struct shdr_info));
- memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
- }
-
- /* Prepare section information data structure. */
- scn = NULL;
- cnt = 1;
- while ((scn = elf_nextscn (elf, scn)) != NULL)
- {
- /* This should always be true (i.e., there should not be any
- holes in the numbering). */
- assert (elf_ndxscn (scn) == cnt);
-
- shdr_info[cnt].scn = scn;
-
- /* Get the header. */
- if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
- INTERNAL_ERROR (fname);
-
- /* Get the name of the section. */
- shdr_info[cnt].name = elf_strptr (elf, shstrndx,
- shdr_info[cnt].shdr.sh_name);
- if (shdr_info[cnt].name == NULL)
- {
- error (0, 0, gettext ("illformed file `%s'"), fname);
- goto fail_close;
- }
-
- /* Mark them as present but not yet investigated. */
- shdr_info[cnt].idx = 1;
-
- /* Remember the shdr.sh_link value. */
- shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
-
- /* Sections in files other than relocatable object files which
- are not loaded can be freely moved by us. In relocatable
- object files everything can be moved. */
- if (ehdr->e_type == ET_REL
- || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
- shdr_info[cnt].shdr.sh_offset = 0;
-
- /* If this is an extended section index table store an
- appropriate reference. */
- if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
- {
- assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
- shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
- }
- else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
- {
- Elf32_Word *grpref;
- size_t inner;
-
- /* Cross-reference the sections contained in the section
- group. */
- shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
- if (shdr_info[cnt].data == NULL)
- INTERNAL_ERROR (fname);
-
- /* XXX Fix for unaligned access. */
- grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
- for (inner = 1;
- inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
- ++inner)
- shdr_info[grpref[inner]].group_idx = cnt;
-
- if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
- /* If the section group contains only one element and this
- is n COMDAT section we can drop it right away. */
- shdr_info[cnt].idx = 0;
- else
- shdr_info[cnt].group_cnt = inner - 1;
- }
- else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
- {
- assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
- shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
- }
-
- /* If this section is part of a group make sure it is not
- discarded right away. */
- if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
- {
- assert (shdr_info[cnt].group_idx != 0);
-
- if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
- {
- /* The section group section will be removed. */
- shdr_info[cnt].group_idx = 0;
- shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
- }
- }
-
- /* Increment the counter. */
- ++cnt;
- }
-
- /* Now determine which sections can go away. The general rule is that
- all sections which are not used at runtime are stripped out. But
- there are a few exceptions:
-
- - special sections named ".comment" and ".note" are kept
- - OS or architecture specific sections are kept since we might not
- know how to handle them
- - if a section is referred to from a section which is not removed
- in the sh_link or sh_info element it cannot be removed either
- */
- for (cnt = 1; cnt < shnum; ++cnt)
- /* Check whether the section can be removed. */
- if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
- shdr_info[cnt].name, remove_comment, remove_debug))
- {
- /* For now assume this section will be removed. */
- shdr_info[cnt].idx = 0;
-
- idx = shdr_info[cnt].group_idx;
- while (idx != 0)
- {
- /* If the references section group is a normal section
- group and has one element remaining, or if it is an
- empty COMDAT section group it is removed. */
- bool is_comdat;
-
- /* The section group data is already loaded. */
- assert (shdr_info[idx].data != NULL);
-
- is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
- & GRP_COMDAT) != 0;
-
- --shdr_info[idx].group_cnt;
- if ((!is_comdat && shdr_info[idx].group_cnt == 1)
- || (is_comdat && shdr_info[idx].group_cnt == 0))
- {
- shdr_info[idx].idx = 0;
- /* Continue recursively. */
- idx = shdr_info[idx].group_idx;
- }
- else
- break;
- }
- }
-
- /* Mark the SHT_NULL section as handled. */
- shdr_info[0].idx = 2;
-
-
- /* Handle exceptions: section groups and cross-references. We might
- have to repeat this a few times since the resetting of the flag
- might propagate. */
- do
- {
- changes = false;
-
- for (cnt = 1; cnt < shnum; ++cnt)
- {
- if (shdr_info[cnt].idx == 0)
- {
- /* If a relocation section is marked as being removed make
- sure the section it is relocating is removed, too. */
- if ((shdr_info[cnt].shdr.sh_type == SHT_REL
- || shdr_info[cnt].shdr.sh_type == SHT_RELA)
- && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
- shdr_info[cnt].idx = 1;
- }
-
- if (shdr_info[cnt].idx == 1)
- {
- /* The content of symbol tables we don't remove must not
- reference any section which we do remove. Otherwise
- we cannot remove the section. */
- if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
- || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
- {
- Elf_Data *symdata;
- Elf_Data *xndxdata;
- size_t elsize;
-
- /* Make sure the data is loaded. */
- if (shdr_info[cnt].data == NULL)
- {
- shdr_info[cnt].data
- = elf_getdata (shdr_info[cnt].scn, NULL);
- if (shdr_info[cnt].data == NULL)
- INTERNAL_ERROR (fname);
- }
- symdata = shdr_info[cnt].data;
-
- /* If there is an extended section index table load it
- as well. */
- if (shdr_info[cnt].symtab_idx != 0
- && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
- {
- assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
-
- shdr_info[shdr_info[cnt].symtab_idx].data
- = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
- NULL);
- if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
- INTERNAL_ERROR (fname);
- }
- xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
-
- /* Go through all symbols and make sure the section they
- reference is not removed. */
- elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
-
- for (size_t inner = 0;
- inner < shdr_info[cnt].data->d_size / elsize;
- ++inner)
- {
- GElf_Sym sym_mem;
- Elf32_Word xndx;
- GElf_Sym *sym;
- size_t scnidx;
-
- sym = gelf_getsymshndx (symdata, xndxdata, inner,
- &sym_mem, &xndx);
- if (sym == NULL)
- INTERNAL_ERROR (fname);
-
- scnidx = sym->st_shndx;
- if (scnidx == SHN_UNDEF || scnidx >= shnum
- || (scnidx >= SHN_LORESERVE
- && scnidx <= SHN_HIRESERVE
- && scnidx != SHN_XINDEX)
- /* Don't count in the section symbols. */
- || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
- /* This is no section index, leave it alone. */
- continue;
- else if (scnidx == SHN_XINDEX)
- scnidx = xndx;
-
- if (shdr_info[scnidx].idx == 0)
- {
- /* Mark this section as used. */
- shdr_info[scnidx].idx = 1;
- changes |= scnidx < cnt;
- }
- }
- }
-
- /* Cross referencing happens:
- - for the cases the ELF specification says. That are
- + SHT_DYNAMIC in sh_link to string table
- + SHT_HASH in sh_link to symbol table
- + SHT_REL and SHT_RELA in sh_link to symbol table
- + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
- + SHT_GROUP in sh_link to symbol table
- + SHT_SYMTAB_SHNDX in sh_link to symbol table
- Other (OS or architecture-specific) sections might as
- well use this field so we process it unconditionally.
- - references inside section groups
- - specially marked references in sh_info if the SHF_INFO_LINK
- flag is set
- */
-
- if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
- {
- shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
- changes |= shdr_info[cnt].shdr.sh_link < cnt;
- }
-
- /* Handle references through sh_info. */
- if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
- && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
- {
- shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
- changes |= shdr_info[cnt].shdr.sh_info < cnt;
- }
-
- /* Mark the section as investigated. */
- shdr_info[cnt].idx = 2;
- }
- }
- }
- while (changes);
-
- /* Write out a copy of all the sections to the debug output file.
- The ones that are not removed in the stripped file are SHT_NOBITS */
- if (debug_fname != NULL)
- {
- for (cnt = 1; cnt < shnum; ++cnt)
- {
- Elf_Data *debugdata;
- GElf_Shdr debugshdr;
- int discard_section;
-
- scn = elf_newscn (debugelf);
- if (scn == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("while generating output file: %s"),
- elf_errmsg (-1));
-
- discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
-
- /* Set the section header in the new file. */
- debugshdr = shdr_info[cnt].shdr;
- if (discard_section)
- debugshdr.sh_type = SHT_NOBITS;
-
- if (unlikely (gelf_update_shdr (scn, &debugshdr)) == 0)
- /* There cannot be any overflows. */
- INTERNAL_ERROR (fname);
-
- /* Get the data from the old file if necessary. */
- if (shdr_info[cnt].data == NULL)
- {
- shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
- if (shdr_info[cnt].data == NULL)
- INTERNAL_ERROR (fname);
- }
-
- /* Set the data. This is done by copying from the old file. */
- debugdata = elf_newdata (scn);
- if (debugdata == NULL)
- INTERNAL_ERROR (fname);
-
- /* Copy the structure. */
- *debugdata = *shdr_info[cnt].data;
- if (discard_section)
- debugdata->d_buf = NULL;
- }
-
- /* Finish the ELF header. Fill in the fields not handled by
- libelf from the old file. */
- debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
- if (debugehdr == NULL)
- INTERNAL_ERROR (fname);
-
- memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
- debugehdr->e_type = ehdr->e_type;
- debugehdr->e_machine = ehdr->e_machine;
- debugehdr->e_version = ehdr->e_version;
- debugehdr->e_entry = ehdr->e_entry;
- debugehdr->e_flags = ehdr->e_flags;
- debugehdr->e_shstrndx = ehdr->e_shstrndx;
-
- if (unlikely (gelf_update_ehdr (debugelf, debugehdr)) == 0)
- {
- error (0, 0, gettext ("%s: error while creating ELF header: %s"),
- debug_fname, elf_errmsg (-1));
- result = 1;
- goto fail_close;
- }
-
- /* Finally write the file. */
- if (unlikely (elf_update (debugelf, ELF_C_WRITE)) == -1)
- {
- error (0, 0, gettext ("while writing `%s': %s"),
- debug_fname, elf_errmsg (-1));
- result = 1;
- goto fail_close;
- }
-
- /* Create the real output file. First rename, then change the
- mode. */
- if (rename (tmp_debug_fname, debug_fname) != 0
- || fchmod (debug_fd, mode) != 0)
- {
- error (0, errno, gettext ("while creating '%s'"), debug_fname);
- result = 1;
- goto fail_close;
- }
-
- /* The temporary file does not exist anymore. */
- tmp_debug_fname = NULL;
-
- /* Compute the checksum which we will add to the executable. */
- if (crc32_file (debug_fd, &debug_crc) != 0)
- {
- error (0, errno,
- gettext ("while computing checksum for debug information"));
- unlink (debug_fname);
- result = 1;
- goto fail_close;
- }
-
- }
-
- /* Mark the section header string table as unused, we will create
- a new one. */
- shdr_info[shstrndx].idx = 0;
-
- /* We need a string table for the section headers. */
- shst = ebl_strtabinit (true);
- if (shst == NULL)
- error (EXIT_FAILURE, errno, gettext ("while preparing output for `%s'"),
- output_fname ?: fname);
-
- /* Assign new section numbers. */
- shdr_info[0].idx = 0;
- for (cnt = idx = 1; cnt < shnum; ++cnt)
- if (shdr_info[cnt].idx > 0)
- {
- shdr_info[cnt].idx = idx++;
-
- /* Create a new section. */
- shdr_info[cnt].newscn = elf_newscn (newelf);
- if (shdr_info[cnt].newscn == NULL)
- error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
- elf_errmsg (-1));
-
- assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
-
- /* Add this name to the section header string table. */
- shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
- }
-
- /* Test whether we are doing anything at all. */
- if (cnt == idx)
- /* Nope, all removable sections are already gone. */
- goto fail_close;
-
- /* Create the reference to the file with the debug info. */
- if (debug_fname != NULL)
- {
- char *debug_basename;
- off_t crc_offset;
-
- /* Add the section header string table section name. */
- shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
- shdr_info[cnt].idx = idx++;
-
- /* Create the section header. */
- shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
- shdr_info[cnt].shdr.sh_flags = 0;
- shdr_info[cnt].shdr.sh_addr = 0;
- shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
- shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
- shdr_info[cnt].shdr.sh_entsize = 0;
- shdr_info[cnt].shdr.sh_addralign = 4;
- /* We set the offset to zero here. Before we write the ELF file the
- field must have the correct value. This is done in the final
- loop over all section. Then we have all the information needed. */
- shdr_info[cnt].shdr.sh_offset = 0;
-
- /* Create the section. */
- shdr_info[cnt].newscn = elf_newscn (newelf);
- if (shdr_info[cnt].newscn == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("while create section header section: %s"),
- elf_errmsg (-1));
- assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
-
- shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
- if (shdr_info[cnt].data == NULL)
- error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
- elf_errmsg (-1));
-
- debug_basename = basename (debug_fname);
- crc_offset = strlen (debug_basename) + 1;
- /* Align to 4 byte boundary */
- crc_offset = ((crc_offset - 1) & ~3) + 4;
-
- shdr_info[cnt].data->d_align = 4;
- shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
- = crc_offset + 4;
- shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
-
- strcpy (shdr_info[cnt].data->d_buf, debug_basename);
- /* Store the crc value in the correct byteorder */
- if ((__BYTE_ORDER == __LITTLE_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
- || (__BYTE_ORDER == __BIG_ENDIAN
- && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
- debug_crc = bswap_32 (debug_crc);
- memcpy ((char *)shdr_info[cnt].data->d_buf + crc_offset,
- (char *) &debug_crc, 4);
-
- /* One more section done. */
- ++cnt;
- }
-
- /* Index of the section header table in the shdr_info array. */
- size_t shdridx = cnt;
-
- /* Add the section header string table section name. */
- shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
- shdr_info[cnt].idx = idx;
-
- /* Create the section header. */
- shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
- shdr_info[cnt].shdr.sh_flags = 0;
- shdr_info[cnt].shdr.sh_addr = 0;
- shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
- shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
- shdr_info[cnt].shdr.sh_entsize = 0;
- /* We set the offset to zero here. Before we write the ELF file the
- field must have the correct value. This is done in the final
- loop over all section. Then we have all the information needed. */
- shdr_info[cnt].shdr.sh_offset = 0;
- shdr_info[cnt].shdr.sh_addralign = 1;
-
- /* Create the section. */
- shdr_info[cnt].newscn = elf_newscn (newelf);
- if (shdr_info[cnt].newscn == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("while create section header section: %s"),
- elf_errmsg (-1));
- assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
-
- /* Finalize the string table and fill in the correct indices in the
- section headers. */
- shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
- if (shstrtab_data == NULL)
- error (EXIT_FAILURE, 0,
- gettext ("while create section header string table: %s"),
- elf_errmsg (-1));
- ebl_strtabfinalize (shst, shstrtab_data);
-
- /* We have to set the section size. */
- shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
-
- /* Update the section information. */
- GElf_Off lastoffset = 0;
- for (cnt = 1; cnt <= shdridx; ++cnt)
- if (shdr_info[cnt].idx > 0)
- {
- Elf_Data *newdata;
-
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
- assert (scn != NULL);
-
- /* Update the name. */
- shdr_info[cnt].shdr.sh_name = ebl_strtaboffset (shdr_info[cnt].se);
-
- /* Update the section header from the input file. Some fields
- might be section indeces which now have to be adjusted. */
- if (shdr_info[cnt].shdr.sh_link != 0)
- shdr_info[cnt].shdr.sh_link =
- shdr_info[shdr_info[cnt].shdr.sh_link].idx;
-
- if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
- {
- assert (shdr_info[cnt].data != NULL);
-
- Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
- for (size_t inner = 0;
- inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
- ++inner)
- grpref[inner] = shdr_info[grpref[inner]].idx;
- }
-
- /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
- if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
- shdr_info[cnt].shdr.sh_info =
- shdr_info[shdr_info[cnt].shdr.sh_info].idx;
-
- /* Get the data from the old file if necessary. We already
- created the data for the section header string table. */
- if (cnt < shnum)
- {
- if (shdr_info[cnt].data == NULL)
- {
- shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
- if (shdr_info[cnt].data == NULL)
- INTERNAL_ERROR (fname);
- }
-
- /* Set the data. This is done by copying from the old file. */
- newdata = elf_newdata (scn);
- if (newdata == NULL)
- INTERNAL_ERROR (fname);
-
- /* Copy the structure. */
- *newdata = *shdr_info[cnt].data;
-
- /* We know the size. */
- shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
-
- /* We have to adjust symtol tables. The st_shndx member might
- have to be updated. */
- if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
- || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
- {
- Elf_Data *versiondata = NULL;
- Elf_Data *shndxdata = NULL;
-
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
-
- if (shdr_info[cnt].symtab_idx != 0)
- {
- assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
- /* This section has extended section information.
- We have to modify that information, too. */
- shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
- NULL);
-
- assert ((versiondata->d_size / sizeof (Elf32_Word))
- >= shdr_info[cnt].data->d_size / elsize);
- }
-
- if (shdr_info[cnt].version_idx != 0)
- {
- assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
- /* This section has associated version
- information. We have to modify that
- information, too. */
- versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
- NULL);
-
- assert ((versiondata->d_size / sizeof (GElf_Versym))
- >= shdr_info[cnt].data->d_size / elsize);
- }
-
- shdr_info[cnt].newsymidx
- = (Elf32_Word *) xcalloc (shdr_info[cnt].data->d_size
- / elsize, sizeof (Elf32_Word));
-
- bool last_was_local = true;
- size_t destidx;
- size_t inner;
- for (destidx = inner = 1;
- inner < shdr_info[cnt].data->d_size / elsize;
- ++inner)
- {
- Elf32_Word sec;
- GElf_Sym sym_mem;
- Elf32_Word xshndx;
- GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
- shndxdata, inner,
- &sym_mem, &xshndx);
- if (sym == NULL)
- INTERNAL_ERROR (fname);
-
- if (sym->st_shndx == SHN_UNDEF
- || (sym->st_shndx >= shnum
- && sym->st_shndx != SHN_XINDEX))
- {
- /* This is no section index, leave it alone
- unless it is moved. */
- if (destidx != inner
- && gelf_update_symshndx (shdr_info[cnt].data,
- shndxdata,
- destidx, sym,
- xshndx) == 0)
- INTERNAL_ERROR (fname);
-
- shdr_info[cnt].newsymidx[inner] = destidx++;
-
- if (last_was_local
- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
- {
- last_was_local = false;
- shdr_info[cnt].shdr.sh_info = destidx - 1;
- }
-
- continue;
- }
-
- /* Get the full section index, if necessary from the
- XINDEX table. */
- if (sym->st_shndx != SHN_XINDEX)
- sec = shdr_info[sym->st_shndx].idx;
- else
- {
- assert (shndxdata != NULL);
-
- sec = shdr_info[xshndx].idx;
- }
-
- if (sec != 0)
- {
- GElf_Section nshndx;
- Elf32_Word nxshndx;
-
- if (sec < SHN_LORESERVE)
- {
- nshndx = sec;
- nxshndx = 0;
- }
- else
- {
- nshndx = SHN_XINDEX;
- nxshndx = sec;
- }
-
- assert (sec < SHN_LORESERVE || shndxdata != NULL);
-
- if ((inner != destidx || nshndx != sym->st_shndx
- || (shndxdata != NULL && nxshndx != xshndx))
- && (sym->st_shndx = nshndx,
- gelf_update_symshndx (shdr_info[cnt].data,
- shndxdata,
- destidx, sym,
- nxshndx) == 0))
- INTERNAL_ERROR (fname);
-
- shdr_info[cnt].newsymidx[inner] = destidx++;
-
- if (last_was_local
- && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
- {
- last_was_local = false;
- shdr_info[cnt].shdr.sh_info = destidx - 1;
- }
- }
- else
- /* This is a section symbol for a section which has
- been removed. */
- assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
- }
-
- if (destidx != inner)
- {
- /* The size of the symbol table changed. */
- shdr_info[cnt].shdr.sh_size = newdata->d_size
- = destidx * elsize;
- any_symtab_changes = true;
- }
- else
- {
- /* The symbol table didn't really change. */
- free (shdr_info[cnt].newsymidx);
- shdr_info[cnt].newsymidx = NULL;
- }
- }
- }
-
- /* If we have to, compute the offset of the section. */
- if (shdr_info[cnt].shdr.sh_offset == 0)
- shdr_info[cnt].shdr.sh_offset
- = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
- & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
-
- /* Set the section header in the new file. */
- if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
- /* There cannot be any overflows. */
- INTERNAL_ERROR (fname);
-
- /* Remember the last section written so far. */
- GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
- ? shdr_info[cnt].shdr.sh_size : 0);
- if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
- lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
- }
-
- /* Adjust symbol references if symbol tables changed. */
- if (any_symtab_changes)
- {
- /* Find all relocation sections which use this
- symbol table. */
- for (cnt = 1; cnt <= shdridx; ++cnt)
- {
- if (shdr_info[cnt].idx == 0)
- /* Ignore sections which are discarded. */
- continue;
-
- if (shdr_info[cnt].shdr.sh_type == SHT_REL
- || shdr_info[cnt].shdr.sh_type == SHT_RELA)
- {
- /* If the symbol table hasn't changed, do not do anything. */
- if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx == NULL)
- continue;
-
- Elf32_Word *newsymidx
- = shdr_info[shdr_info[cnt].old_sh_link].newsymidx;
- Elf_Data *d = elf_getdata (elf_getscn (newelf,
- shdr_info[cnt].idx),
- NULL);
- assert (d != NULL);
- size_t nrels = (shdr_info[cnt].shdr.sh_size
- / shdr_info[cnt].shdr.sh_entsize);
-
- if (shdr_info[cnt].shdr.sh_type == SHT_REL)
- for (size_t relidx = 0; relidx < nrels; ++relidx)
- {
- GElf_Rel rel_mem;
- if (gelf_getrel (d, relidx, &rel_mem) == NULL)
- INTERNAL_ERROR (fname);
-
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != symidx)
- {
- rel_mem.r_info
- = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
-
- if (gelf_update_rel (d, relidx, &rel_mem) == 0)
- INTERNAL_ERROR (fname);
- }
- }
- else
- for (size_t relidx = 0; relidx < nrels; ++relidx)
- {
- GElf_Rela rel_mem;
- if (gelf_getrela (d, relidx, &rel_mem) == NULL)
- INTERNAL_ERROR (fname);
-
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != symidx)
- {
- rel_mem.r_info
- = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
-
- if (gelf_update_rela (d, relidx, &rel_mem) == 0)
- INTERNAL_ERROR (fname);
- }
- }
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_HASH)
- {
- /* We have to recompute the hash table. */
- Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
-
- /* We do not have to do anything if the symbol table was
- not changed. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- continue;
-
- /* The symbol version section in the new file. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
-
- /* The symbol table data. */
- Elf_Data *symd = elf_getdata (elf_getscn (newelf,
- shdr_info[symtabidx].idx),
- NULL);
- assert (symd != NULL);
-
- /* The hash table data. */
- Elf_Data *hashd = elf_getdata (scn, NULL);
- assert (hashd != NULL);
-
- if (shdr_info[cnt].shdr.sh_entsize == sizeof (Elf32_Word))
- {
- /* Sane arches first. */
- Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
-
- size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
-
- /* Convert to the correct byte order. */
- if (gelf_xlatetom (newelf, hashd, hashd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
- INTERNAL_ERROR (fname);
-
- /* Adjust the nchain value. The symbol table size
- changed. We keep the same size for the bucket array. */
- bucket[1] = symd->d_size / elsize;
- Elf32_Word nbucket = bucket[0];
- bucket += 2;
- Elf32_Word *chain = bucket + nbucket;
-
- /* New size of the section. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_size = hashd->d_size
- = (2 + symd->d_size / elsize + nbucket)
- * sizeof (Elf32_Word);
- (void) gelf_update_shdr (scn, shdr);
-
- /* Clear the arrays. */
- memset (bucket, '\0',
- (symd->d_size / elsize + nbucket)
- * sizeof (Elf32_Word));
-
- for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
- inner < symd->d_size / elsize; ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
- assert (sym != NULL);
-
- const char *name = elf_strptr (elf, strshndx,
- sym->st_name);
- assert (name != NULL);
- size_t hidx = elf_hash (name) % nbucket;
-
- if (bucket[hidx] == 0)
- bucket[hidx] = inner;
- else
- {
- hidx = bucket[hidx];
-
- while (chain[hidx] != 0)
- hidx = chain[hidx];
-
- chain[hidx] = inner;
- }
- }
- }
- else
- {
- /* Alpha and S390 64-bit use 64-bit SHT_HASH entries. */
- assert (shdr_info[cnt].shdr.sh_entsize
- == sizeof (Elf64_Xword));
-
- Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
-
- size_t strshndx = shdr_info[symtabidx].old_sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
-
- /* Convert to the correct byte order. */
- if (gelf_xlatetom (newelf, hashd, hashd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
- INTERNAL_ERROR (fname);
-
- /* Adjust the nchain value. The symbol table size
- changed. We keep the same size for the bucket array. */
- bucket[1] = symd->d_size / elsize;
- Elf64_Xword nbucket = bucket[0];
- bucket += 2;
- Elf64_Xword *chain = bucket + nbucket;
-
- /* New size of the section. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_size = hashd->d_size
- = (2 + symd->d_size / elsize + nbucket)
- * sizeof (Elf64_Xword);
- (void) gelf_update_shdr (scn, shdr);
-
- /* Clear the arrays. */
- memset (bucket, '\0',
- (symd->d_size / elsize + nbucket)
- * sizeof (Elf64_Xword));
-
- for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
- inner < symd->d_size / elsize; ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
- assert (sym != NULL);
-
- const char *name = elf_strptr (elf, strshndx,
- sym->st_name);
- assert (name != NULL);
- size_t hidx = elf_hash (name) % nbucket;
-
- if (bucket[hidx] == 0)
- bucket[hidx] = inner;
- else
- {
- hidx = bucket[hidx];
-
- while (chain[hidx] != 0)
- hidx = chain[hidx];
-
- chain[hidx] = inner;
- }
- }
- }
-
- /* Convert back to the file byte order. */
- if (gelf_xlatetof (newelf, hashd, hashd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
- INTERNAL_ERROR (fname);
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym)
- {
- /* If the symbol table changed we have to adjust the
- entries. */
- Elf32_Word symtabidx = shdr_info[cnt].old_sh_link;
-
- /* We do not have to do anything if the symbol table was
- not changed. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- continue;
-
- /* The symbol version section in the new file. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
-
- /* The symbol table data. */
- Elf_Data *symd = elf_getdata (elf_getscn (newelf,
- shdr_info[symtabidx].idx),
- NULL);
- assert (symd != NULL);
-
- /* The version symbol data. */
- Elf_Data *verd = elf_getdata (scn, NULL);
- assert (verd != NULL);
-
- /* Convert to the correct byte order. */
- if (gelf_xlatetom (newelf, verd, verd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
- INTERNAL_ERROR (fname);
-
- /* The symbol version array. */
- GElf_Half *verstab = (GElf_Half *) verd->d_buf;
-
- /* New indices of the symbols. */
- Elf32_Word *newsymidx = shdr_info[symtabidx].newsymidx;
-
- /* Walk through the list and */
- size_t elsize = gelf_fsize (elf, verd->d_type, 1,
- ehdr->e_version);
- for (size_t inner = 1; inner < verd->d_size / elsize; ++inner)
- if (newsymidx[inner] != 0)
- /* Overwriting the same array works since the
- reordering can only move entries to lower indices
- in the array. */
- verstab[newsymidx[inner]] = verstab[inner];
-
- /* New size of the section. */
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_size = verd->d_size
- = gelf_fsize (newelf, verd->d_type,
- symd->d_size / gelf_fsize (elf, symd->d_type, 1,
- ehdr->e_version),
- ehdr->e_version);
- (void) gelf_update_shdr (scn, shdr);
-
- /* Convert back to the file byte order. */
- if (gelf_xlatetof (newelf, verd, verd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL)
- INTERNAL_ERROR (fname);
- }
- else if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
- {
- /* Check whether the associated symbol table changed. */
- if (shdr_info[shdr_info[cnt].old_sh_link].newsymidx != NULL)
- {
- /* Yes the symbol table changed. Update the section
- header of the section group. */
- scn = elf_getscn (newelf, shdr_info[cnt].idx);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- assert (shdr != NULL);
-
- size_t stabidx = shdr_info[cnt].old_sh_link;
- shdr->sh_info = shdr_info[stabidx].newsymidx[shdr->sh_info];
-
- (void) gelf_update_shdr (scn, shdr);
- }
- }
- }
- }
-
- /* Finally finish the ELF header. Fill in the fields not handled by
- libelf from the old file. */
- newehdr = gelf_getehdr (newelf, &newehdr_mem);
- if (newehdr == NULL)
- INTERNAL_ERROR (fname);
-
- memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
- newehdr->e_type = ehdr->e_type;
- newehdr->e_machine = ehdr->e_machine;
- newehdr->e_version = ehdr->e_version;
- newehdr->e_entry = ehdr->e_entry;
- newehdr->e_flags = ehdr->e_flags;
- newehdr->e_phoff = ehdr->e_phoff;
- /* We need to position the section header table. */
- const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
- newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
- + shdr_info[shdridx].shdr.sh_size + offsize - 1)
- & ~((GElf_Off) (offsize - 1)));
- newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
-
- /* The new section header string table index. */
- if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
- newehdr->e_shstrndx = idx;
- else
- {
- /* The index does not fit in the ELF header field. */
- shdr_info[0].scn = elf_getscn (elf, 0);
-
- if (gelf_getshdr (shdr_info[0].scn, &shdr_info[0].shdr) == NULL)
- INTERNAL_ERROR (fname);
-
- shdr_info[0].shdr.sh_link = idx;
- (void) gelf_update_shdr (shdr_info[0].scn, &shdr_info[0].shdr);
-
- newehdr->e_shstrndx = SHN_XINDEX;
- }
-
- if (gelf_update_ehdr (newelf, newehdr) == 0)
- {
- error (0, 0, gettext ("%s: error while creating ELF header: %s"),
- fname, elf_errmsg (-1));
- return 1;
- }
-
- /* We have everything from the old file. */
- if (elf_cntl (elf, ELF_C_FDDONE) != 0)
- {
- error (0, 0, gettext ("%s: error while reading the file: %s"),
- fname, elf_errmsg (-1));
- return 1;
- }
-
- /* The ELF library better follows our layout when this is not a
- relocatable object file. */
- elf_flagelf (newelf, ELF_C_SET,
- (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
- | (permissive ? ELF_F_PERMISSIVE : 0));
-
- /* Finally write the file. */
- if (elf_update (newelf, ELF_C_WRITE) == -1)
- {
- error (0, 0, gettext ("while writing `%s': %s"),
- fname, elf_errmsg (-1));
- result = 1;
- }
-
- fail_close:
- if (shdr_info != NULL)
- {
- /* For some sections we might have created an table to map symbol
- table indices. */
- if (any_symtab_changes)
- for (cnt = 1; cnt <= shdridx; ++cnt)
- free (shdr_info[cnt].newsymidx);
-
- /* Free the memory. */
- if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
- free (shdr_info);
- }
-
- /* Free other resources. */
- if (shstrtab_data != NULL)
- free (shstrtab_data->d_buf);
- if (shst != NULL)
- ebl_strtabfree (shst);
-
- /* That was it. Close the descriptors. */
- if (elf_end (newelf) != 0)
- {
- error (0, 0, gettext ("error while finishing `%s': %s"), fname,
- elf_errmsg (-1));
- result = 1;
- }
-
- if (debugelf != NULL && elf_end (debugelf) != 0)
- {
- error (0, 0, gettext ("error while finishing `%s': %s"), debug_fname,
- elf_errmsg (-1));
- result = 1;
- }
-
- fail:
- /* Close the EBL backend. */
- if (ebl != NULL)
- ebl_closebackend (ebl);
-
- /* Close debug file descriptor, if opened */
- if (debug_fd >= 0)
- {
- if (tmp_debug_fname != NULL)
- unlink (tmp_debug_fname);
- close (debug_fd);
- }
-
- /* If requested, preserve the timestamp. */
- if (tvp != NULL)
- {
- if (futimes (fd, tvp) != 0)
- {
- error (0, errno, gettext ("\
-cannot set access and modification date of \"%s\""),
- output_fname ?: fname);
- result = 1;
- }
- }
-
- /* Close the file descriptor if we created a new file. */
- if (output_fname != NULL)
- close (fd);
-
- return result;
-}
-
-
-static int
-handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
- struct timeval tvp[2])
-{
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char new_prefix[prefix_len + 1 + fname_len];
- char *cp = new_prefix;
-
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
-
-
- /* Process all the files contained in the archive. */
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_RDWR;
- int result = 0;
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- /* The the header for this element. */
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
-
- if (elf_kind (subelf) == ELF_K_ELF)
- result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
- else if (elf_kind (subelf) == ELF_K_AR)
- result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
-
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (unlikely (elf_end (subelf) != 0))
- INTERNAL_ERROR (fname);
- }
-
- if (tvp != NULL)
- {
- if (unlikely (futimes (fd, tvp) != 0))
- {
- error (0, errno, gettext ("\
-cannot set access and modification date of \"%s\""), fname);
- result = 1;
- }
- }
-
- if (unlikely (close (fd) != 0))
- error (EXIT_FAILURE, errno, gettext ("while closing `%s'"), fname);
-
- return result;
-}
diff --git a/src/symbolhash.c b/src/symbolhash.c
deleted file mode 100644
index da2ae6f6..00000000
--- a/src/symbolhash.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Symbol hash table implementation.
- Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <ld.h>
-
-/* Definitions for the symbol hash table. */
-#define TYPE struct symbol *
-#define NAME ld_symbol_tab
-#define ITERATE 1
-#define COMPARE(a, b) strcmp ((a)->name, (b)->name)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/symbolhash.h b/src/symbolhash.h
deleted file mode 100644
index a8798c2a..00000000
--- a/src/symbolhash.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifndef SYMBOLHASH_H
-#define SYMBOLHASH_H 1
-
-/* Definitions for the symbol hash table. */
-#define TYPE struct symbol *
-#define NAME ld_symbol_tab
-#define ITERATE 1
-#define COMPARE(a, b) strcmp ((a)->name, (b)->name)
-#include <dynamicsizehash.h>
-
-#endif /* symbolhash.h */
diff --git a/src/unaligned.h b/src/unaligned.h
deleted file mode 100644
index 524b35c8..00000000
--- a/src/unaligned.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* Unaligned memory access functionality.
- Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifndef _UNALIGNED_H
-#define _UNALIGNED_H 1
-
-#include <byteswap.h>
-#include <endian.h>
-
-
-#ifndef UNALIGNED_ACCESS_CLASS
-# error "UNALIGNED_ACCESS_CLASS must be defined"
-#endif
-
-
-/* Macros to convert from the host byte order to that of the object file. */
-#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER
-# define target_bswap_16(n) (n)
-# define target_bswap_32(n) (n)
-# define target_bswap_64(n) (n)
-#else
-# define target_bswap_16(n) bswap_16 (n)
-# define target_bswap_32(n) bswap_32 (n)
-# define target_bswap_64(n) bswap_64 (n)
-#endif
-
-
-union u_2ubyte_unaligned
-{
- uint16_t u;
- char c[2];
-} __attribute__((packed));
-
-union u_4ubyte_unaligned
-{
- uint32_t u;
- char c[4];
-} __attribute__((packed));
-
-union u_8ubyte_unaligned
-{
- uint64_t u;
- char c[8];
-} __attribute__((packed));
-
-
-/* Macros to store value at unaligned address. */
-#define store_2ubyte_unaligned(ptr, value) \
- (void) (((union u_2ubyte_unaligned *) (ptr))->u = target_bswap_16 (value))
-#define store_4ubyte_unaligned(ptr, value) \
- (void) (((union u_4ubyte_unaligned *) (ptr))->u = target_bswap_32 (value))
-#define store_8ubyte_unaligned(ptr, value) \
- (void) (((union u_8ubyte_unaligned *) (ptr))->u = target_bswap_64 (value))
-
-
-/* Macros to add value to unaligned address. This is a bit more
- complicated since the value must be read from memory and eventually
- converted twice. */
-#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER
-# define add_2ubyte_unaligned(ptr, value) \
- (void) (((union u_2ubyte_unaligned *) (ptr))->u += value)
-# define add_4ubyte_unaligned(ptr, value) \
- (void) (((union u_4ubyte_unaligned *) (ptr))->u += value)
-# define add_8ubyte_unaligned(ptr, value) \
- (void) (((union u_8ubyte_unaligned *) (ptr))->u += value)
-#else
-# define add_2ubyte_unaligned(ptr, value) \
- do { \
- union u_2ubyte_unaligned *_ptr = (ptr); \
- uint16_t _val = bswap_16 (_ptr->u) + (value); \
- _ptr->u = bswap_16 (_val); \
- } while (0)
-# define add_4ubyte_unaligned(ptr, value) \
- do { \
- union u_4ubyte_unaligned *_ptr = (ptr); \
- uint32_t _val = bswap_32 (_ptr->u) + (value); \
- _ptr->u = bswap_32 (_val); \
- } while (0)
-# define add_8ubyte_unaligned(ptr, value) \
- do { \
- union u_8ubyte_unaligned *_ptr = (ptr); \
- uint64_t _val = bswap_64 (_ptr->u) + (value); \
- _ptr->u = bswap_64 (_val); \
- } while (0)
-#endif
-
-#endif /* unaligned.h */
diff --git a/src/versionhash.c b/src/versionhash.c
deleted file mode 100644
index 79b2e105..00000000
--- a/src/versionhash.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Version symbol hash table implementation.
- Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <ld.h>
-
-/* Definitions for the symbol hash table. */
-#define TYPE struct id_list *
-#define NAME ld_version_str_tab
-#define COMPARE(a, b) strcmp ((a)->id, (b)->id)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/versionhash.h b/src/versionhash.h
deleted file mode 100644
index 243aeeb5..00000000
--- a/src/versionhash.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifndef VERSIONHASH_H
-#define VERSIONHASH_H 1
-
-/* Definitions for the symbol hash table. */
-#define TYPE struct id_list *
-#define NAME ld_version_str_tab
-#include <dynamicsizehash.h>
-
-#endif /* versionhash.h */
diff --git a/src/xelf.h b/src/xelf.h
deleted file mode 100644
index ab36e002..00000000
--- a/src/xelf.h
+++ /dev/null
@@ -1,387 +0,0 @@
-/* Macros to enable writing native and generic ELF access code.
- Copyright (C) 2003 Red Hat, Inc.
- Written by Ulrich Drepper <drepper@redhat.com>, 2003.
-
- This program is Open Source software; you can redistribute it and/or
- modify it under the terms of the Open Software License version 1.0 as
- published by the Open Source Initiative.
-
- You should have received a copy of the Open Software License along
- with this program; if not, you may obtain a copy of the Open Software
- License version 1.0 from http://www.opensource.org/licenses/osl.php or
- by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
- 3001 King Ranch Road, Ukiah, CA 95482. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <libebl.h>
-
-
-/* By default the linker is handling all architectures. But it can
- be configured to be a native-only linker. */
-#if NATIVE_ELF == 32
-/* 32-bit only. */
-# define XElf_Ehdr Elf32_Ehdr
-# define XElf_Shdr Elf32_Shdr
-# define XElf_Off Elf32_Off
-# define XElf_Addr Elf32_Addr
-# define XElf_Half Elf32_Half
-# define XElf_Word Elf32_Word
-# define XElf_Xword Elf32_Word
-# define XElf_Sxword Elf32_Sword
-# define XElf_Versym Elf32_Versym
-# define XElf_Sym Elf32_Sym
-# define XElf_Rel Elf32_Rel
-# define XElf_Rela Elf32_Rela
-
-# define XElf_Ehdr_vardef(name) Elf32_Ehdr *name
-# define xelf_getehdr(elf, name) name = elf32_getehdr (elf)
-# define xelf_getehdr_copy(elf, name, copy) \
- (copy) = *(name = elf32_getehdr (elf))
-# define xelf_newehdr(elf, klass) elf32_newehdr (elf)
-# define xelf_update_ehdr(elf, ehdr) \
- /* nothing */ ((void) (elf), (void) (ehdr), 1)
-
-# define xelf_getclass(elf) ELFCLASS32
-
-# define XElf_Phdr_vardef(name) Elf32_Phdr *name
-# define xelf_newphdr(elf, n) elf32_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) name = elf32_getphdr (elf) + idx
-# define xelf_getphdr_ptr(elf, idx, name) name = elf32_getphdr (elf) + idx
-# define xelf_update_phdr(elf, idx, phdr) \
- /* nothing */ ((void) (elf), (void) (idx), (void) (phdr), 1)
-
-# define XElf_Shdr_vardef(name) Elf32_Shdr *name
-# define xelf_getshdr(scn, name) name = elf32_getshdr (scn)
-# define xelf_getshdr_copy(scn, name, copy) \
- (copy) = *(name = elf32_getshdr (scn))
-# define xelf_update_shdr(scn, shdr) \
- /* nothing */ ((void) (scn), (void) (shdr), 1)
-
-# define XElf_Sym_vardef(name) Elf32_Sym *name
-# define xelf_getsym(data, idx, name) \
- name = &((Elf32_Sym *) (data)->d_buf)[idx]
-# define xelf_getsym_ptr(data, idx, name) \
- name = &((Elf32_Sym *) (data)->d_buf)[idx]
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
- (name1 = &((Elf32_Sym *) ((data)->d_buf))[idx]); \
- name2 = (unlikely ((ndxdata) != NULL) \
- ? ((Elf32_Word *) ((ndxdata)->d_buf))[idx] : 0)
-# define xelf_update_sym(data, idx, sym) \
- /* nothing */ ((void) (data), (void) (idx), (void) (sym), 1)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
- if (datachanged) \
- ((Elf32_Sym *) ((data)->d_buf))[idx] = *name1; \
- if (unlikely (ndxdata != NULL)) \
- ((Elf32_Word *) ((ndxdata)->d_buf))[idx] = name2
-
-# define XElf_Versym_vardef(name) Elf32_Versym name
-# define xelf_getversym_copy(data, idx, name) \
- (name = ((Elf32_Versym *) ((data)->d_buf))[idx], &name)
-
-# define XElf_Dyn_vardef(name) Elf32_Dyn *name
-# define xelf_getdyn(data, idx, name) \
- name = &((Elf32_Dyn *) ((data)->d_buf))[idx]
-# define xelf_getdyn_ptr(data, idx, name) \
- name = &((Elf32_Dyn *) ((data)->d_buf))[idx]
-# define xelf_update_dyn(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rel_vardef(name) Elf32_Rel *name
-# define xelf_getrel(data, idx, name) \
- name = &((Elf32_Rel *) ((data)->d_buf))[idx]
-# define xelf_getrel_ptr(data, idx, name) \
- name = &((Elf32_Rel *) ((data)->d_buf))[idx]
-# define xelf_update_rel(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rela_vardef(name) Elf32_Rela *name
-# define xelf_getrela(data, idx, name) \
- name = &((Elf32_Rela *) ((data)->d_buf))[idx]
-# define xelf_getrela_ptr(data, idx, name) \
- name = &((Elf32_Rela *) ((data)->d_buf))[idx]
-# define xelf_update_rela(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Verdef_vardef(name) Elf32_Verdef *name
-# define xelf_getverdef(data, offset, name) \
- name = ((Elf32_Verdef *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XElf_Verdaux_vardef(name) Elf32_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
- name = ((Elf32_Verdaux *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XELF_ST_TYPE(info) ELF32_ST_TYPE (info)
-# define XELF_ST_BIND(info) ELF32_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) ELF32_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) ELF32_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) ELF32_R_SYM (info)
-# define XELF_R_TYPE(info) ELF32_R_TYPE (info)
-# define XELF_R_INFO(sym, type) ELF32_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
- (__builtin_constant_p (type) \
- ? ({ size_t fsize; \
- switch (type) \
- { \
- case ELF_T_BYTE: fsize = 1; break; \
- case ELF_T_ADDR: fsize = sizeof (Elf32_Addr); break; \
- case ELF_T_DYN: fsize = sizeof (Elf32_Dyn); break; \
- case ELF_T_EHDR: fsize = sizeof (Elf32_Ehdr); break; \
- case ELF_T_HALF: fsize = sizeof (Elf32_Half); break; \
- case ELF_T_OFF: fsize = sizeof (Elf32_Off); break; \
- case ELF_T_PHDR: fsize = sizeof (Elf32_Phdr); break; \
- case ELF_T_RELA: fsize = sizeof (Elf32_Rela); break; \
- case ELF_T_REL: fsize = sizeof (Elf32_Rel); break; \
- case ELF_T_SHDR: fsize = sizeof (Elf32_Shdr); break; \
- case ELF_T_SWORD: fsize = sizeof (Elf32_Sword); break; \
- case ELF_T_SYM: fsize = sizeof (Elf32_Sym); break; \
- case ELF_T_WORD: fsize = sizeof (Elf32_Word); break; \
- case ELF_T_XWORD: fsize = sizeof (Elf32_Xword); break; \
- case ELF_T_SXWORD: fsize = sizeof (Elf32_Sxword); break; \
- case ELF_T_VDEF: fsize = sizeof (Elf32_Verdef); break; \
- case ELF_T_VDAUX: fsize = sizeof (Elf32_Verdaux); break; \
- case ELF_T_VNEED: fsize = sizeof (Elf32_Verneed); break; \
- case ELF_T_VNAUX: fsize = sizeof (Elf32_Vernaux); break; \
- case ELF_T_NHDR: fsize = sizeof (Elf32_Nhdr); break; \
- case ELF_T_SYMINFO: fsize = sizeof (Elf32_Syminfo); break; \
- case ELF_T_MOVE: fsize = sizeof (Elf32_Move); break; \
- default: fsize = 0; break; \
- } \
- fsize * (cnt); }) \
- : gelf_fsize (elf, type, cnt, EV_CURRENT))
-#elif NATIVE_ELF == 64
-/* 64-bit only. */
-# define XElf_Ehdr Elf64_Ehdr
-# define XElf_Shdr Elf64_Shdr
-# define XElf_Addr Elf64_Addr
-# define XElf_Half Elf64_Half
-# define XElf_Off Elf64_Off
-# define XElf_Word Elf64_Word
-# define XElf_Xword Elf64_Xword
-# define XElf_Sxword Elf64_Sxword
-# define XElf_Versym Elf64_Versym
-# define XElf_Sym Elf64_Sym
-# define XElf_Rel Elf64_Rel
-# define XElf_Rela Elf64_Rela
-
-# define XElf_Ehdr_vardef(name) Elf64_Ehdr *name
-# define xelf_getehdr(elf, name) name = elf64_getehdr (elf)
-# define xelf_getehdr_copy(elf, name, copy) \
- (copy) = *(name = elf64_getehdr (elf))
-# define xelf_newehdr(elf, klass) elf64_newehdr (elf)
-# define xelf_update_ehdr(elf, ehdr) \
- /* nothing */ ((void) (elf), (void) (ehdr), 1)
-
-# define xelf_getclass(elf) ELFCLASS32
-
-# define XElf_Phdr_vardef(name) Elf64_Phdr *name
-# define xelf_newphdr(elf, n) elf64_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) name = elf64_getphdr (elf) + idx
-# define xelf_getphdr_ptr(elf, idx, name) name = elf64_getphdr (elf) + idx
-# define xelf_update_phdr(elf, idx, phdr) \
- /* nothing */ ((void) (elf), (void) (idx), (void) (phdr), 1)
-
-# define XElf_Shdr_vardef(name) Elf64_Shdr *name
-# define xelf_getshdr(scn, name) name = elf64_getshdr (scn)
-# define xelf_getshdr_copy(scn, name, copy) \
- (copy) = *(name = elf64_getshdr (scn))
-# define xelf_update_shdr(scn, shdr) \
- /* nothing */ ((void) (scn), (void) (shdr), 1)
-
-# define XElf_Sym_vardef(name) Elf64_Sym *name
-# define xelf_getsym(data, idx, name) \
- name = &((Elf64_Sym *) (data)->d_buf)[idx]
-# define xelf_getsym_ptr(data, idx, name) \
- name = &((Elf64_Sym *) (data)->d_buf)[idx]
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
- (name1 = &((Elf64_Sym *) ((data)->d_buf))[idx]); \
- name2 = (unlikely ((ndxdata) != NULL) \
- ? ((Elf32_Word *) ((ndxdata)->d_buf))[idx] : 0)
-# define xelf_update_sym(data, idx, sym) \
- /* nothing */ ((void) (data), (void) (idx), (void) (sym), 1)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
- if (datachanged) \
- ((Elf64_Sym *) ((data)->d_buf))[idx] = *name1; \
- if (ndxdata != NULL) \
- (((Elf32_Word *) ((ndxdata)->d_buf))[idx] = name2)
-
-# define XElf_Versym_vardef(name) Elf64_Versym name
-# define xelf_getversym_copy(data, idx, name) \
- (name = ((Elf64_Versym *) ((data)->d_buf))[idx], (&name))
-
-# define XElf_Dyn_vardef(name) Elf64_Dyn *name
-# define xelf_getdyn(data, idx, name) \
- name = &((Elf64_Dyn *) ((data)->d_buf))[idx]
-# define xelf_getdyn_ptr(data, idx, name) \
- name = &((Elf64_Dyn *) ((data)->d_buf))[idx]
-# define xelf_update_dyn(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rel_vardef(name) Elf64_Rel *name
-# define xelf_getrel(data, idx, name) \
- name = &((Elf64_Rel *) ((data)->d_buf))[idx]
-# define xelf_getrel_ptr(data, idx, name) \
- name = &((Elf64_Rel *) ((data)->d_buf))[idx]
-# define xelf_update_rel(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rela_vardef(name) Elf64_Rela *name
-# define xelf_getrela(data, idx, name) \
- name = &((Elf64_Rela *) ((data)->d_buf))[idx]
-# define xelf_getrela_ptr(data, idx, name) \
- name = &((Elf64_Rela *) ((data)->d_buf))[idx]
-# define xelf_update_rela(data, idx, name) \
- /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Verdef_vardef(name) Elf64_Verdef *name
-# define xelf_getverdef(data, offset, name) \
- name = ((Elf64_Verdef *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XElf_Verdaux_vardef(name) Elf64_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
- name = ((Elf64_Verdaux *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XELF_ST_TYPE(info) ELF64_ST_TYPE (info)
-# define XELF_ST_BIND(info) ELF64_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) ELF64_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) ELF64_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) ELF64_R_SYM (info)
-# define XELF_R_TYPE(info) ELF64_R_TYPE (info)
-# define XELF_R_INFO(sym, type) ELF64_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
- (__builtin_constant_p (type) \
- ? ({ size_t fsize; \
- switch (type) \
- { \
- case ELF_T_BYTE: fsize = 1; break; \
- case ELF_T_ADDR: fsize = sizeof (Elf64_Addr); break; \
- case ELF_T_DYN: fsize = sizeof (Elf64_Dyn); break; \
- case ELF_T_EHDR: fsize = sizeof (Elf64_Ehdr); break; \
- case ELF_T_HALF: fsize = sizeof (Elf64_Half); break; \
- case ELF_T_OFF: fsize = sizeof (Elf64_Off); break; \
- case ELF_T_PHDR: fsize = sizeof (Elf64_Phdr); break; \
- case ELF_T_RELA: fsize = sizeof (Elf64_Rela); break; \
- case ELF_T_REL: fsize = sizeof (Elf64_Rel); break; \
- case ELF_T_SHDR: fsize = sizeof (Elf64_Shdr); break; \
- case ELF_T_SWORD: fsize = sizeof (Elf64_Sword); break; \
- case ELF_T_SYM: fsize = sizeof (Elf64_Sym); break; \
- case ELF_T_WORD: fsize = sizeof (Elf64_Word); break; \
- case ELF_T_XWORD: fsize = sizeof (Elf64_Xword); break; \
- case ELF_T_SXWORD: fsize = sizeof (Elf64_Sxword); break; \
- case ELF_T_VDEF: fsize = sizeof (Elf64_Verdef); break; \
- case ELF_T_VDAUX: fsize = sizeof (Elf64_Verdaux); break; \
- case ELF_T_VNEED: fsize = sizeof (Elf64_Verneed); break; \
- case ELF_T_VNAUX: fsize = sizeof (Elf64_Vernaux); break; \
- case ELF_T_NHDR: fsize = sizeof (Elf64_Nhdr); break; \
- case ELF_T_SYMINFO: fsize = sizeof (Elf64_Syminfo); break; \
- case ELF_T_MOVE: fsize = sizeof (Elf64_Move); break; \
- default: fsize = 0; break; \
- } \
- fsize * (cnt); }) \
- : gelf_fsize (elf, type, cnt, EV_CURRENT))
-#else
-# include <gelf.h>
-
-/* Generic linker. */
-# define XElf_Ehdr GElf_Ehdr
-# define XElf_Shdr GElf_Shdr
-# define XElf_Addr GElf_Addr
-# define XElf_Half GElf_Half
-# define XElf_Off GElf_Off
-# define XElf_Word GElf_Word
-# define XElf_Xword GElf_Xword
-# define XElf_Sxword GElf_Sxword
-# define XElf_Versym GElf_Versym
-# define XElf_Sym GElf_Sym
-# define XElf_Rel GElf_Rel
-# define XElf_Rela GElf_Rela
-
-# define XElf_Ehdr_vardef(name) GElf_Ehdr name##_mem; GElf_Ehdr *name
-# define xelf_getehdr(elf, name) name = gelf_getehdr (elf, &name##_mem)
-# define xelf_getehdr_copy(elf, name, copy) \
- name = gelf_getehdr (elf, &(copy))
-# define xelf_newehdr(elf, klass) gelf_newehdr (elf, klass)
-# define xelf_update_ehdr(elf, ehdr) gelf_update_ehdr (elf, ehdr)
-
-# define xelf_getclass(elf) gelf_getclass (elf)
-
-# define XElf_Phdr_vardef(name) GElf_Phdr name##_mem; GElf_Phdr *name
-# define xelf_newphdr(elf, n) gelf_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) \
- name = gelf_getphdr (elf, idx, &name##_mem)
-# define xelf_getphdr_ptr(elf, idx, name) \
- name = &name##_mem
-# define xelf_update_phdr(elf, idx, phdr) \
- gelf_update_phdr (elf, idx, phdr)
-
-# define XElf_Shdr_vardef(name) GElf_Shdr name##_mem; GElf_Shdr *name
-# define xelf_getshdr(scn, name) name = gelf_getshdr (scn, &name##_mem)
-# define xelf_getshdr_copy(scn, name, copy) \
- name = gelf_getshdr (scn, &(copy))
-# define xelf_update_shdr(scn, shdr) gelf_update_shdr (scn, shdr)
-
-# define XElf_Sym_vardef(name) GElf_Sym name##_mem; GElf_Sym *name
-# define xelf_getsym(data, idx, name) \
- name = gelf_getsym (data, idx, &name##_mem)
-# define xelf_getsym_ptr(data, idx, name) \
- name = &name##_mem
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
- name1 = gelf_getsymshndx (data, ndxdata, idx, &name1##_mem, &(name2))
-# define xelf_update_sym(data, idx, sym) gelf_update_sym (data, idx, sym)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
- gelf_update_symshndx (data, ndxdata, idx, name1, name2)
-
-# define XElf_Versym_vardef(name) GElf_Versym name
-# define xelf_getversym_copy(data, idx, name) \
- gelf_getversym (data, idx, &name)
-
-# define XElf_Dyn_vardef(name) GElf_Dyn name##_mem; GElf_Dyn *name
-# define xelf_getdyn(data, idx, name) \
- name = gelf_getdyn (data, idx, &name##_mem)
-# define xelf_getdyn_ptr(data, idx, name) \
- name = &name##_mem
-# define xelf_update_dyn(data, idx, name) \
- gelf_update_dyn (data, idx, name)
-
-# define XElf_Rel_vardef(name) GElf_Rel name##_mem; GElf_Rel *name
-# define xelf_getrel(data, idx, name) \
- name = gelf_getrel (data, idx, &name##_mem)
-# define xelf_getrel_ptr(data, idx, name) \
- name = &name##_mem
-# define xelf_update_rel(data, idx, name) \
- gelf_update_rel (data, idx, name)
-
-# define XElf_Rela_vardef(name) GElf_Rela name##_mem; GElf_Rela *name
-# define xelf_getrela(data, idx, name) \
- name = gelf_getrela (data, idx, &name##_mem)
-# define xelf_getrela_ptr(data, idx, name) \
- name = &name##_mem
-# define xelf_update_rela(data, idx, name) \
- gelf_update_rela (data, idx, name)
-
-# define XElf_Verdef_vardef(name) GElf_Verdef name##_mem; GElf_Verdef *name
-# define xelf_getverdef(data, offset, name) \
- name = gelf_getverdef (data, offset, &name##_mem)
-
-# define XElf_Verdaux_vardef(name) GElf_Verdaux name##_mem; GElf_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
- name = gelf_getverdaux (data, offset, &name##_mem)
-
-# define XELF_ST_TYPE(info) GELF_ST_TYPE (info)
-# define XELF_ST_BIND(info) GELF_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) GELF_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) GELF_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) GELF_R_SYM (info)
-# define XELF_R_TYPE(info) GELF_R_TYPE (info)
-# define XELF_R_INFO(sym, type) GELF_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
- gelf_fsize (elf, type, cnt, EV_CURRENT)
-#endif
diff --git a/src/ylwrap b/src/ylwrap
deleted file mode 100644
index e8abf827..00000000
--- a/src/ylwrap
+++ /dev/null
@@ -1,154 +0,0 @@
-#! /bin/sh
-# ylwrap - wrapper for lex/yacc invocations.
-# Copyright 1996, 1997, 1998, 1999, 2001 Free Software Foundation, Inc.
-# Written by Tom Tromey <tromey@cygnus.com>.
-#
-# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Usage:
-# ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
-# * INPUT is the input file
-# * OUTPUT is file PROG generates
-# * DESIRED is file we actually want
-# * PROGRAM is program to run
-# * ARGS are passed to PROG
-# Any number of OUTPUT,DESIRED pairs may be used.
-
-# The input.
-input="$1"
-shift
-case "$input" in
- [\\/]* | ?:[\\/]*)
- # Absolute path; do nothing.
- ;;
- *)
- # Relative path. Make it absolute.
- input="`pwd`/$input"
- ;;
-esac
-
-pairlist=
-while test "$#" -ne 0; do
- if test "$1" = "--"; then
- shift
- break
- fi
- pairlist="$pairlist $1"
- shift
-done
-
-# The program to run.
-prog="$1"
-shift
-# Make any relative path in $prog absolute.
-case "$prog" in
- [\\/]* | ?:[\\/]*) ;;
- *[\\/]*) prog="`pwd`/$prog" ;;
-esac
-
-# FIXME: add hostname here for parallel makes that run commands on
-# other machines. But that might take us over the 14-char limit.
-dirname=ylwrap$$
-trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
-mkdir $dirname || exit 1
-
-cd $dirname
-
-$prog ${1+"$@"} "$input"
-status=$?
-
-if test $status -eq 0; then
- set X $pairlist
- shift
- first=yes
- # Since DOS filename conventions don't allow two dots,
- # the DOS version of Bison writes out y_tab.c instead of y.tab.c
- # and y_tab.h instead of y.tab.h. Test to see if this is the case.
- y_tab_nodot="no"
- if test -f y_tab.c || test -f y_tab.h; then
- y_tab_nodot="yes"
- fi
-
- # The directory holding the input.
- input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
- # Quote $INPUT_DIR so we can use it in a regexp.
- # FIXME: really we should care about more than `.' and `\'.
- input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
-
- while test "$#" -ne 0; do
- from="$1"
- # Handle y_tab.c and y_tab.h output by DOS
- if test $y_tab_nodot = "yes"; then
- if test $from = "y.tab.c"; then
- from="y_tab.c"
- else
- if test $from = "y.tab.h"; then
- from="y_tab.h"
- fi
- fi
- fi
- if test -f "$from"; then
- # If $2 is an absolute path name, then just use that,
- # otherwise prepend `../'.
- case "$2" in
- [\\/]* | ?:[\\/]*) target="$2";;
- *) target="../$2";;
- esac
-
- # Edit out `#line' or `#' directives.
- #
- # We don't want the resulting debug information to point at
- # an absolute srcdir; it is better for it to just mention the
- # .y file with no path.
- #
- # We want to use the real output file name, not yy.lex.c for
- # instance.
- #
- # We want the include guards to be adjusted too.
- FROM=`echo "$from" | sed \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
- -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
- TARGET=`echo "$2" | sed \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
- -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
- sed "/^#/{s,$input_rx,,;s,$from,$2,;s,$FORM,$TO,;}" "$from" >"$target" ||
- status=$?
- else
- # A missing file is only an error for the first file. This
- # is a blatant hack to let us support using "yacc -d". If -d
- # is not specified, we don't want an error when the header
- # file is "missing".
- if test $first = yes; then
- status=1
- fi
- fi
- shift
- shift
- first=no
- done
-else
- status=$?
-fi
-
-# Remove the directory.
-cd ..
-rm -rf $dirname
-
-exit $status