diff options
author | Jing Yu <jingyu@google.com> | 2010-04-24 20:38:09 -0700 |
---|---|---|
committer | Jing Yu <jingyu@google.com> | 2010-04-24 20:38:09 -0700 |
commit | 53b6ed3bceea971857c996b6dcb96de96b99335f (patch) | |
tree | cc49c51c95eeccac5c60aba71f562774bc53e621 | |
parent | d0587d99827bdedd87489d947263e1a40722d35e (diff) | |
download | toolchain_binutils-53b6ed3bceea971857c996b6dcb96de96b99335f.zip toolchain_binutils-53b6ed3bceea971857c996b6dcb96de96b99335f.tar.gz toolchain_binutils-53b6ed3bceea971857c996b6dcb96de96b99335f.tar.bz2 |
Update binutils for Android.
Change-Id: Idb3f13acf9ab3f02a761b6e631901fdcf555ee26
256 files changed, 52229 insertions, 10238 deletions
diff --git a/binutils-2.19/README.android b/binutils-2.19/README.android index cd36a76..6447357 100644 --- a/binutils-2.19/README.android +++ b/binutils-2.19/README.android @@ -1,3 +1,336 @@ +2010-04-09 Doug Kwan <dougkwan@google.com> + + Backport upstream patch to add support for NOLOAD section type in + script. + + http://sourceware.org/ml/binutils-cvs/2010-04/msg00050.html + + Changed files: + gold/layout.cc + gold/layout.h + gold/output.cc + gold/output.h + gold/script-c.h + gold/script-sections.cc + gold/script-sections.h + gold/script.cc + gold/yyscript.y + +2010-04-08 Doug Kwan <dougkwan@google.com> + + Backport upstream patch to fix a problem in handling merge sections + of uneven sizes. + + http://sourceware.org/ml/binutils-cvs/2010-04/msg00047.html + + Changed files: + gold/merge.cc + gold/output.cc + +2010-04-08 Doug Kwan <dougkwan@google.com> + + Backport patch from trunk to fix handling of objects with more than + 64K sections. + + http://sourceware.org/ml/binutils-cvs/2010-04/msg00044.html + + Changed files: + + gold/arm.cc + +2010-04-08 Doug Kwan <dougkwan@google.com> + + Backport patch from trunk to fix some of the kernel build problems. + + http://sourceware.org/ml/binutils-cvs/2010-04/msg00039.html + + Changed files: + + gold/ChangeLog + gold/arm.cc + gold/gold.cc + gold/options.cc + gold/options.h + gold/parameters.cc + gold/parameters.h + gold/target.h + +2010-03-30 Jing Yu <jingyu@google.com> + + Backport patch from 2.20 to fix the misalignment problem. + The patch increases the maximum allowed code alignment from 32 + to 64 bytes, affecting .p2align and .align directives. + + http://sourceware.org/ml/binutils/2009-06/msg00289.html + + Changed files: + + gas/config/tc-arm.c + gas/config/tc-arm.h + +2010-03-25 Doug Kwan <dougkwan@google.com> + + Backport patch from trunk to fix build breakage due to a + conversion warning on a 32-bit host. + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00145.html + + Changed files: + + gold/arm.cc + +2010-03-22 Doug Kwan <dougkwan@google.com> + + Backport patch from trunk to fix handling of BLX branch offsets. + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00116.html + + Changed files: + + gold/arm.cc + gold/testsuite/Makefile.am + gold/testsuite/Makefile.in + gold/testsuite/arm_branch_in_range.sh + + Added files: + + gold/testsuite/thumb_blx_in_range.s + gold/testsuite/thumb_blx_out_of_range.s + +2010-03-19 Doug Kwan <dougkwan@google.com> + + Backport patch from trunk to make stub offsets independent of + unordered map implementation. + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00104.html + + Changed files: + + gold/arm.cc + gold/stringpool.cc + gold/stringpool.h + +2010-03-19 Carrot Wei <carrot@google.com> + + Back port patch from trunk: + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00091.html + + Changed files: + + bfd/elf32-arm.c + bfd/reloc.c + bfd/bfd-in2.h + bfd/libbfd.h + gas/config/tc-arm.c + gas/doc/c-arm.texi + + Added files: + + gas/testsuite/gas/arm/got_prel.d + gas/testsuite/gas/arm/got_prel.s + +2010-03-16 Doug Kwan <dougkwan@google.com> + + Back port patch from trunk: + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00074.html + + Changed files: + + gold/stringpool.cc + gold/stringpool.h + +2010-03-11 Doug Kwan <dougkwan@google.com> + + Add missing files in top-of-trunk sync on 2010-03-01. + + Added files: + + gold/ffsll.c + gold/ftruncate.c + gold/mremap.c + +2010-03-08 Doug Kwan <dougkwan@google.com> + + Back port patches from trunk: + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00036.html + http://sourceware.org/ml/binutils-cvs/2010-03/msg00018.html + + Changed files: + + gold/arm.cc + gold/object.cc + gold/object.h + gold/target-reloc.h + gold/testsuite/Makefile.am + gold/testsuite/Makefile.in + gold/testsuite/discard_locals_test.sh + gold/testsuite/discard_locals_relocatable_test.c + +2010-03-01 Doug Kwan <dougkwan@google.com> + + Sync gold the top of trunk version: + + http://sourceware.org/ml/binutils-cvs/2010-03/msg00002.html + + All the files in src/elfcpp and src/gold are now at the same revision + as the commit above. + + Changed files: + + configure + configure.ac + elfcpp/ChangeLog + elfcpp/elfcpp.h + elfcpp/elfcpp_file.h + elfcpp/elfcpp_swap.h + gold/ChangeLog + gold/Makefile.am + gold/Makefile.in + gold/README + gold/aclocal.m4 + gold/archive.cc + gold/archive.h + gold/binary.cc + gold/common.cc + gold/common.h + gold/config.in + gold/configure + gold/configure.ac + gold/configure.tgt + gold/copy-relocs.cc + gold/cref.cc + gold/cref.h + gold/debug.h + gold/defstd.cc + gold/descriptors.cc + gold/descriptors.h + gold/dirsearch.cc + gold/dirsearch.h + gold/dwarf_reader.cc + gold/dwarf_reader.h + gold/dynobj.cc + gold/dynobj.h + gold/errors.cc + gold/errors.h + gold/expression.cc + gold/fileread.cc + gold/fileread.h + gold/gold-threads.cc + gold/gold-threads.h + gold/gold.cc + gold/gold.h + gold/i386.cc + gold/layout.cc + gold/layout.h + gold/main.cc + gold/mapfile.cc + gold/mapfile.h + gold/merge.cc + gold/merge.h + gold/object.cc + gold/object.h + gold/options.cc + gold/options.h + gold/output.cc + gold/output.h + gold/parameters.cc + gold/parameters.h + gold/po/Make-in + gold/powerpc.cc + gold/pread.c + gold/readsyms.cc + gold/readsyms.h + gold/reduced_debug_output.cc + gold/reduced_debug_output.h + gold/reloc.cc + gold/reloc.h + gold/resolve.cc + gold/script-c.h + gold/script-sections.cc + gold/script-sections.h + gold/script.cc + gold/script.h + gold/sparc.cc + gold/stringpool.cc + gold/stringpool.h + gold/symtab.cc + gold/symtab.h + gold/target-reloc.h + gold/target-select.cc + gold/target-select.h + gold/target.h + gold/testsuite/Makefile.am + gold/testsuite/Makefile.in + gold/testsuite/binary_unittest.cc + gold/testsuite/debug_msg.sh + gold/testsuite/initpri1.c + gold/testsuite/object_unittest.cc + gold/testsuite/relro_script_test.t + gold/testsuite/script_test_3.sh + gold/testsuite/script_test_4.sh + gold/testsuite/testfile.cc + gold/testsuite/tls_test_c.c + gold/testsuite/undef_symbol.sh + gold/testsuite/ver_matching_test.sh + gold/testsuite/ver_test_10.sh + gold/testsuite/ver_test_2.sh + gold/testsuite/ver_test_4.script + gold/testsuite/ver_test_4.sh + gold/testsuite/ver_test_5.sh + gold/testsuite/ver_test_6.c + gold/testsuite/ver_test_7.sh + gold/testsuite/version_script.map + gold/testsuite/weak_plt.sh + gold/token.h + gold/version.cc + gold/workqueue.cc + gold/workqueue.h + gold/x86_64.cc + gold/yyscript.y + include/libiberty.h + libiberty/Makefile.in + libiberty/configure + libiberty/configure.ac + libiberty/functions.texi + + Added files: + + elfcpp/arm.h + gold/testsuite/arm_abs_global.sh + gold/testsuite/arm_branch_in_range.sh + gold/testsuite/arm_fix_v4bx.sh + gold/testsuite/discard_locals_test.sh + gold/testsuite/dynamic_list.sh + gold/testsuite/exclude_libs_test.sh + gold/testsuite/gc_comdat_test.sh + gold/testsuite/gc_orphan_section_test.sh + gold/testsuite/gc_tls_test.sh + gold/testsuite/hidden_test.sh + gold/testsuite/icf_keep_unique_test.sh + gold/testsuite/icf_safe_so_test.sh + gold/testsuite/icf_safe_test.sh + gold/testsuite/icf_test.sh + gold/testsuite/incremental_test.sh + gold/testsuite/no_version_test.sh + gold/testsuite/plugin_test_1.sh + gold/testsuite/plugin_test_2.sh + gold/testsuite/plugin_test_3.sh + gold/testsuite/plugin_test_4.sh + gold/testsuite/retain_symbols_file_test.sh + gold/testsuite/script_test_5.sh + gold/testsuite/script_test_6.sh + gold/testsuite/script_test_7.sh + gold/testsuite/script_test_8.sh + gold/testsuite/split_i386.sh + gold/testsuite/split_x86_64.sh + gold/testsuite/two_file_shared.sh + gold/testsuite/ver_test_1.sh + include/plugin-api.h + libiberty/crc32.c + libiberty/memmem.c 2010-02-04 Doug Kwan <dougkwan@google.com> Apply this patch to fix build breakage. diff --git a/binutils-2.19/bfd/bfd-in2.h b/binutils-2.19/bfd/bfd-in2.h index 9b4d8aa..f9389e3 100644 --- a/binutils-2.19/bfd/bfd-in2.h +++ b/binutils-2.19/bfd/bfd-in2.h @@ -3011,6 +3011,7 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARM_RELATIVE, BFD_RELOC_ARM_GOTOFF, BFD_RELOC_ARM_GOTPC, + BFD_RELOC_ARM_GOT_PREL, /* ARM thread-local storage relocations. */ BFD_RELOC_ARM_TLS_GD32, diff --git a/binutils-2.19/bfd/elf32-arm.c b/binutils-2.19/bfd/elf32-arm.c index b25be54..9ab35a1 100644 --- a/binutils-2.19/bfd/elf32-arm.c +++ b/binutils-2.19/bfd/elf32-arm.c @@ -1721,6 +1721,7 @@ static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = {BFD_RELOC_ARM_RELATIVE, R_ARM_RELATIVE}, {BFD_RELOC_ARM_GOTOFF, R_ARM_GOTOFF32}, {BFD_RELOC_ARM_GOTPC, R_ARM_GOTPC}, + {BFD_RELOC_ARM_GOT_PREL, R_ARM_GOT_PREL}, {BFD_RELOC_ARM_GOT32, R_ARM_GOT32}, {BFD_RELOC_ARM_PLT32, R_ARM_PLT32}, {BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1}, diff --git a/binutils-2.19/bfd/libbfd.h b/binutils-2.19/bfd/libbfd.h index eb84d58..33cc9c1 100644 --- a/binutils-2.19/bfd/libbfd.h +++ b/binutils-2.19/bfd/libbfd.h @@ -1256,6 +1256,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARM_RELATIVE", "BFD_RELOC_ARM_GOTOFF", "BFD_RELOC_ARM_GOTPC", + "BFD_RELOC_ARM_GOT_PREL", "BFD_RELOC_ARM_TLS_GD32", "BFD_RELOC_ARM_TLS_LDO32", "BFD_RELOC_ARM_TLS_LDM32", @@ -2052,4 +2053,3 @@ bfd_boolean bfd_default_scan /* Extracted from elf.c. */ struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name); - diff --git a/binutils-2.19/bfd/reloc.c b/binutils-2.19/bfd/reloc.c index 9d993af..8504e35 100644 --- a/binutils-2.19/bfd/reloc.c +++ b/binutils-2.19/bfd/reloc.c @@ -2860,6 +2860,8 @@ ENUMX BFD_RELOC_ARM_GOTOFF ENUMX BFD_RELOC_ARM_GOTPC +ENUMX + BFD_RELOC_ARM_GOT_PREL ENUMDOC Relocations for setting up GOTs and PLTs for shared libraries. diff --git a/binutils-2.19/configure b/binutils-2.19/configure index a8cf680..2c7815f 100755 --- a/binutils-2.19/configure +++ b/binutils-2.19/configure @@ -2063,7 +2063,7 @@ if test "${ENABLE_GOLD}" = "yes"; then if test "$is_elf" = "yes"; then # Check for target supported by gold. case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-*) + i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*) configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`" ;; esac diff --git a/binutils-2.19/configure.ac b/binutils-2.19/configure.ac index 78c8390..c31e255 100644 --- a/binutils-2.19/configure.ac +++ b/binutils-2.19/configure.ac @@ -318,7 +318,7 @@ if test "${ENABLE_GOLD}" = "yes"; then if test "$is_elf" = "yes"; then # Check for target supported by gold. case "${target}" in - i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-*) + i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-*) configdirs="`echo " ${configdirs} " | sed -e 's/ ld / gold /'`" ;; esac diff --git a/binutils-2.19/depcomp b/binutils-2.19/depcomp index 3510ab0..3510ab0 100755..100644 --- a/binutils-2.19/depcomp +++ b/binutils-2.19/depcomp diff --git a/binutils-2.19/elfcpp/ChangeLog b/binutils-2.19/elfcpp/ChangeLog index 949ffeb..a6c75cd 100644 --- a/binutils-2.19/elfcpp/ChangeLog +++ b/binutils-2.19/elfcpp/ChangeLog @@ -1,3 +1,103 @@ +2010-01-21 Doug Kwan <dougkwan@google.com> + + * arm.h (EXIDX_CANTUNWIND): New enum. + +2010-01-19 Ian Lance Taylor <iant@google.com> + + * elfcpp.h (PN_XNUM): Define. + +2009-12-14 Ian Lance Taylor <iant@google.com> + + * elfcpp_file.h: Revert last patch. + +2009-12-11 Nick Clifton <nickc@redhat.com> + + * elfcpp_file.h: Fix shadowed variable warnings. + +2009-12-10 Doug Kwan <dougkwan@google.com> + + * arm.h: New enums for EABI object attribute tags and values. + +2009-12-05 Doug Kwan <dougkwan@google.com> + + * arm.h: Define enums for Tag_CPU_arch EABI attribute. + +2009-11-24 Rafael Avila de Espindola <espindola@google.com> + + * elfcpp_file.h: Include elfcpp.h. + +2009-11-03 Ian Lance Taylor <iant@google.com> + + * elfcpp.h: Remove trailing commas from enum definitions. + +2009-10-30 Doug Kwan <dougkwan@google.com> + + * arm.h (EF_ARM_BE8, EF_ARM_EABIMASK, EF_ARM_EABI_UNKNOWN, + EF_ARM_EABI_VER1, EF_ARM_EABI_VER2, EF_ARM_EABI_VER3, + EF_ARM_EABI_VER4, EF_ARM_EABI_VER5): New enums for processor-specific + flags. + (arm_eabi_version): New inline function. + * elfcpp.h: Add a comment about DT_ENCODING. + +2009-10-16 Doug Kwan <dougkwan@google.com> + + * elfcpp/elfcpp.h (DT_PREINIT_ARRAY): Correct enum value. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * elfcpp/elfcpp_file.h (Elf_file::section_name): Change shstr_size + to Elf_WXword. + +2009-10-09 Mikolaj Zalewski <mikolajz@google.com> + + * elf_file.h: (class Elf_strtab): New class. + +2009-10-09 Mikolaj Zalewski <mikolajz@google.com> + + * elfcpp_file.h: Fix header guard. Include <cstdio>. + (class Elf_recognizer): New class, code from gold/object.cc. + (Elf_file::find_section_by_type): New method. + +2009-07-23 Ulrich Drepper <drepper@redhat.com> + + * elfcpp.h (enum STB): Add STB_GNU_UNIQUE. + +2009-06-21 Ian Lance Taylor <iant@google.com> + + * elfcpp.h (SHN_X86_64_LCOMMON): Define enum constant. + (enum SHT): Add SHT_X86_64_UNWIND. + (enum SHF): Add SHT_X86_64_LARGE. + +2009-05-27 Doug Kwan <dougkwan@google.com> + + * arm.h: New file. + * elfcpp.h (enum SHT): Add ARM-specific special sections. + (enum PT): Add ARM-specific section types. + (enum SST): Add STT_ARM_TFUNC. + +2009-04-30 Nick Clifton <nickc@redhat.com> + + * elfcpp.h (enum STT): Add STT_GNU_IFUNC. + +2009-03-20 Mikolaj Zalewski <mikolajz@google.com> + + * elfcpp.h (SHT_GNU_INCREMENTAL_INPUTS): Define. + +2009-03-01 Ian Lance Taylor <iant@google.com> + + * elfcpp_swap.h: #include "config.h". Only #include <byteswap.h> + if HAVE_BYTESWAP_H is defined; if not, provide definitions for + bswap_{16,32,64}. For gcc 4.3 and later, use the builtin bswap + functions. Check WORDS_BIGENDIAN rather than __BYTE_ORDER. + +2009-01-06 H.J. Lu <hongjiu.lu@intel.com> + + * elfcpp.h (enum STT): Remove STT_IFUNC. + +2008-12-03 Nick Clifton <nickc@redhat.com> + + * elfcpp.h (enum STT): Add STT_IFUNC. + 2008-06-12 David S. Miller <davem@davemloft.net> * powerpc.h: New file. diff --git a/binutils-2.19/elfcpp/arm.h b/binutils-2.19/elfcpp/arm.h new file mode 100644 index 0000000..397d0d0 --- /dev/null +++ b/binutils-2.19/elfcpp/arm.h @@ -0,0 +1,333 @@ +// arm.h -- ELF definitions specific to EM_ARM -*- C++ -*- + +// Copyright 2009, Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of elfcpp. + +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public License +// as published by the Free Software Foundation; either version 2, or +// (at your option) any later version. + +// In addition to the permissions in the GNU Library General Public +// License, the Free Software Foundation gives you unlimited +// permission to link the compiled version of this file into +// combinations with other programs, and to distribute those +// combinations without any restriction coming from the use of this +// file. (The Library Public License restrictions do apply in other +// respects; for example, they cover modification of the file, and +// distribution when not linked into a combined executable.) + +// 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 +// Library General Public License for more details. + +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +// 02110-1301, USA. + +#ifndef ELFCPP_ARM_H +#define ELFCPP_ARM_H + +// The relocation type information is taken from: +// +// ELF for the ARM Architecture +// Document number: ARM IHI 0044C, current through ABI release 2.07 +// Date of Issue: 10th October, 2008 +// + +namespace elfcpp +{ + +// +// ARM Relocations Codes +// + +// Operation notes: +// S: Address of the symbol. +// A: Addend for relocation. +// P: Address of the place being relocated. +// Pa: Adjusted address of the place being relocated (P & 0xfffffffc) +// T: is 1 if S has type STT_FUNC and the symbol addresses a Thumb +// instruction.Thumb-bit; it is 0 otherwise. +// B(S): Addressing origin of the output segment defining S. +// GOT_ORG: Addressing origin of the Global Offset Table. +// GOT(S): Address of the GOT entry for S. +// + +enum +{ + // Type Class Operation + // ------------------------------ + R_ARM_NONE = 0, // Static Misc + R_ARM_PC24 = 1, // Deprecated ARM ((S + A) | T) - P + R_ARM_ABS32 = 2, // Static Data (S + A) | T + R_ARM_REL32 = 3, // Static Data ((S + A) | T) - P + R_ARM_LDR_PC_G0 = 4, // Static ARM S + A - P + R_ARM_ABS16 = 5, // Static Data S + A + R_ARM_ABS12 = 6, // Static ARM S + A + R_ARM_THM_ABS5 = 7, // Static Thumb16 S + A + R_ARM_ABS8 = 8, // Static Data S + A + R_ARM_SBREL32 = 9, // Static Data ((S + A) | T) - B(S) + R_ARM_THM_CALL = 10, // Static Thumb32 ((S + A) | T) - P + R_ARM_THM_PC8 = 11, // Static Thumb16 + R_ARM_BREL_ADJ = 12, // Dynamic Data DeltaB(S) + A + R_ARM_TLS_DESC = 13, // Dynamic Data + R_ARM_THM_SWI8 = 14, // Obsolete + R_ARM_XPC25 = 15, // Obsolete + R_ARM_THM_XPC22 = 16, // Obsolete + R_ARM_TLS_DTPMOD32 = 17, // Dynamic Data Module(S) + R_ARM_TLS_DTPOFF32 = 18, // Dynamic Data S + A - TLS + R_ARM_TLS_TPOFF32 = 19, // Dynamic Data S + A - tp + R_ARM_COPY = 20, // Dynamic Misc + R_ARM_GLOB_DAT = 21, // Dynamic Data (S + A) | T + R_ARM_JUMP_SLOT = 22, // Dynamic Data (S + A) | T + R_ARM_RELATIVE = 23, // Dynamic Data B(S) + A + R_ARM_GOTOFF32 = 24, // Static Data (((S + A) | T) - GOT_ORG + R_ARM_BASE_PREL = 25, // Static Data B(S) + A - P + R_ARM_GOT_BREL = 26, // Static Data GOT(S) + A - GOT_ORG + R_ARM_PLT32 = 27, // Deprecated ARM ((S + A) | T) - P + R_ARM_CALL = 28, // Static ARM ((S + A) | T) - P + R_ARM_JUMP24 = 29, // Static ARM ((S + A) | T) - P + R_ARM_THM_JUMP24 = 30, // Static Thumb32 ((S + A) | T) - P + R_ARM_BASE_ABS = 31, // Static Data B(S) + A + R_ARM_ALU_PCREL_7_0 = 32, // Obsolete + R_ARM_ALU_PCREL_15_8 = 33, // Obsolete + R_ARM_ALU_PCREL_23_15 = 34, // Obsolete + R_ARM_LDR_SBREL_11_0_NC = 35, // Deprecated ARM S + A - B(S) + R_ARM_ALU_SBREL_19_12_NC = 36,// Deprecated ARM S + A - B(S) + R_ARM_ALU_SBREL_27_20_CK = 37,// Deprecated ARM S + A - B(S) + R_ARM_TARGET1 = 38, // Data Misc (S + A) | T or + // ((S + A) | T) - P + R_ARM_SBREL31 = 39, // Deprecated Data ((S + A) | T) - B(S) + R_ARM_V4BX = 40, // Static Misc + R_ARM_TARGET2 = 41, // Static Misc + R_ARM_PREL31 = 42, // Static Data ((S + A) | T) - P + R_ARM_MOVW_ABS_NC = 43, // Static ARM (S + A) | T + R_ARM_MOVT_ABS = 44, // Static ARM S + A + R_ARM_MOVW_PREL_NC = 45, // Static ARM ((S + A) | T) - P + R_ARM_MOVT_PREL = 46, // Static ARM S + A - P + R_ARM_THM_MOVW_ABS_NC = 47, // Static Thumb32 (S + A) | T + R_ARM_THM_MOVT_ABS = 48, // Static Thumb32 S + A - P + R_ARM_THM_MOVW_PREL_NC = 49, // Static Thumb32 ((S + A) | T) - P + R_ARM_THM_MOVT_PREL = 50, // Static Thumb32 S + A - P + R_ARM_THM_JUMP19 = 51, // Static Thumb32 ((S + A) | T) - P + R_ARM_THM_JUMP6 = 52, // Static Thumb16 S + A - P + R_ARM_THM_ALU_PREL_11_0 = 53, // Static Thumb32 ((S + A) | T) - Pa + R_ARM_THM_PC12 = 54, // Static Thumb32 S + A - Pa + R_ARM_ABS32_NOI = 55, // Static Data S + A + R_ARM_REL32_NOI = 56, // Static Data S + A - P + R_ARM_ALU_PC_G0_NC = 57, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G0 = 58, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G1_NC = 59, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G1 = 60, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G2 = 61, // Static ARM ((S + A) | T) - P + R_ARM_LDR_PC_G1 = 62, // Static ARM S + A - P + R_ARM_LDR_PC_G2 = 63, // Static ARM S + A - P + R_ARM_LDRS_PC_G0 = 64, // Static ARM S + A - P + R_ARM_LDRS_PC_G1 = 65, // Static ARM S + A - P + R_ARM_LDRS_PC_G2 = 66, // Static ARM S + A - P + R_ARM_LDC_PC_G0 = 67, // Static ARM S + A - P + R_ARM_LDC_PC_G1 = 68, // Static ARM S + A - P + R_ARM_LDC_PC_G2 = 69, // Static ARM S + A - P + R_ARM_ALU_SB_G0_NC = 70, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G0 = 71, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G1_NC = 72, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G1 = 73, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G2 = 74, // Static ARM ((S + A) | T) - B(S) + R_ARM_LDR_SB_G0 = 75, // Static ARM S + A - B(S) + R_ARM_LDR_SB_G1 = 76, // Static ARM S + A - B(S) + R_ARM_LDR_SB_G2 = 77, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G0 = 78, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G1 = 79, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G2 = 80, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G0 = 81, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G1 = 82, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G2 = 83, // Static ARM S + A - B(S) + R_ARM_MOVW_BREL_NC = 84, // Static ARM ((S + A) | T) - B(S) + R_ARM_MOVT_BREL = 85, // Static ARM S + A - B(S) + R_ARM_MOVW_BREL = 86, // Static ARM ((S + A) | T) - B(S) + R_ARM_THM_MOVW_BREL_NC = 87, // Static Thumb32 ((S + A) | T) - B(S) + R_ARM_THM_MOVT_BREL = 88, // Static Thumb32 S + A - B(S) + R_ARM_THM_MOVW_BREL = 89, // Static Thumb32 ((S + A) | T) - B(S) + R_ARM_TLS_GOTDESC = 90, // Static Data + R_ARM_TLS_CALL = 91, // Static ARM + R_ARM_TLS_DESCSEQ = 92, // Static ARM TLS relaxation + R_ARM_THM_TLS_CALL = 93, // Static Thumb32 + R_ARM_PLT32_ABS = 94, // Static Data PLT(S) + A + R_ARM_GOT_ABS = 95, // Static Data GOT(S) + A + R_ARM_GOT_PREL = 96, // Static Data GOT(S) + A - P + R_ARM_GOT_BREL12 = 97, // Static ARM GOT(S) + A - GOT_ORG + R_ARM_GOTOFF12 = 98, // Static ARM S + A - GOT_ROG + R_ARM_GOTRELAX = 99, // Static Misc + R_ARM_GNU_VTENTRY = 100, // Deprecated Data + R_ARM_GNU_VTINHERIT = 101, // Deprecated Data + R_ARM_THM_JUMP11 = 102, // Static Thumb16 S + A - P + R_ARM_THM_JUMP8 = 103, // Static Thumb16 S + A - P + R_ARM_TLS_GD32 = 104, // Static Data GOT(S) + A - P + R_ARM_TLS_LDM32 = 105, // Static Data GOT(S) + A - P + R_ARM_TLS_LDO32 = 106, // Static Data S + A - TLS + R_ARM_TLS_IE32 = 107, // Static Data GOT(S) + A - P + R_ARM_TLS_LE32 = 108, // Static Data S + A - tp + R_ARM_TLS_LDO12 = 109, // Static ARM S + A - TLS + R_ARM_TLS_LE12 = 110, // Static ARM S + A - tp + R_ARM_TLS_IE12GP = 111, // Static ARM GOT(S) + A - GOT_ORG + R_ARM_PRIVATE_0 = 112, // Private (n = 0, 1, ... 15) + R_ARM_PRIVATE_1 = 113, + R_ARM_PRIVATE_2 = 114, + R_ARM_PRIVATE_3 = 115, + R_ARM_PRIVATE_4 = 116, + R_ARM_PRIVATE_5 = 117, + R_ARM_PRIVATE_6 = 118, + R_ARM_PRIVATE_7 = 119, + R_ARM_PRIVATE_8 = 120, + R_ARM_PRIVATE_9 = 121, + R_ARM_PRIVATE_10 = 122, + R_ARM_PRIVATE_11 = 123, + R_ARM_PRIVATE_12 = 124, + R_ARM_PRIVATE_13 = 125, + R_ARM_PRIVATE_14 = 126, + R_ARM_PRIVATE_15 = 127, + R_ARM_ME_TOO = 128, // Obsolete + R_ARM_THM_TLS_DESCSEQ16 = 129,// Static Thumb16 + R_ARM_THM_TLS_DESCSEQ32 = 130,// Static Thumb32 + // 131 - 139 Unallocated + // 140 - 159 Dynamic Reserved for future allocation + // 160 - 255 Unallocated +}; + +// e_flags values used for ARM. We only support flags defined in AAELF. + +enum +{ + EF_ARM_BE8 = 0x00800000, + + // Mask to extract EABI version, not really a flag value. + EF_ARM_EABIMASK = 0xFF000000, + + EF_ARM_EABI_UNKNOWN = 0x00000000, + EF_ARM_EABI_VER1 = 0x01000000, + EF_ARM_EABI_VER2 = 0x02000000, + EF_ARM_EABI_VER3 = 0x03000000, + EF_ARM_EABI_VER4 = 0x04000000, + EF_ARM_EABI_VER5 = 0x05000000, +}; + +// Extract EABI version from flags. + +inline Elf_Word +arm_eabi_version(Elf_Word flags) +{ return flags & EF_ARM_EABIMASK; } + +// Values for the Tag_CPU_arch EABI attribute. +enum +{ + TAG_CPU_ARCH_PRE_V4, + TAG_CPU_ARCH_V4, + TAG_CPU_ARCH_V4T, + TAG_CPU_ARCH_V5T, + TAG_CPU_ARCH_V5TE, + TAG_CPU_ARCH_V5TEJ, + TAG_CPU_ARCH_V6, + TAG_CPU_ARCH_V6KZ, + TAG_CPU_ARCH_V6T2, + TAG_CPU_ARCH_V6K, + TAG_CPU_ARCH_V7, + TAG_CPU_ARCH_V6_M, + TAG_CPU_ARCH_V6S_M, + TAG_CPU_ARCH_V7E_M, + MAX_TAG_CPU_ARCH = TAG_CPU_ARCH_V7E_M, + // Pseudo-architecture to allow objects to be compatible with the subset of + // armv4t and armv6-m. This value should never be stored in object files. + TAG_CPU_ARCH_V4T_PLUS_V6_M = (MAX_TAG_CPU_ARCH + 1) +}; + +// EABI object attributes. +enum +{ + // 0-3 are generic. + Tag_CPU_raw_name = 4, + Tag_CPU_name = 5, + Tag_CPU_arch = 6, + Tag_CPU_arch_profile = 7, + Tag_ARM_ISA_use = 8, + Tag_THUMB_ISA_use = 9, + Tag_VFP_arch = 10, + Tag_WMMX_arch = 11, + Tag_Advanced_SIMD_arch = 12, + Tag_PCS_config = 13, + Tag_ABI_PCS_R9_use = 14, + Tag_ABI_PCS_RW_data = 15, + Tag_ABI_PCS_RO_data = 16, + Tag_ABI_PCS_GOT_use = 17, + Tag_ABI_PCS_wchar_t = 18, + Tag_ABI_FP_rounding = 19, + Tag_ABI_FP_denormal = 20, + Tag_ABI_FP_exceptions = 21, + Tag_ABI_FP_user_exceptions = 22, + Tag_ABI_FP_number_model = 23, + Tag_ABI_align8_needed = 24, + Tag_ABI_align8_preserved = 25, + Tag_ABI_enum_size = 26, + Tag_ABI_HardFP_use = 27, + Tag_ABI_VFP_args = 28, + Tag_ABI_WMMX_args = 29, + Tag_ABI_optimization_goals = 30, + Tag_ABI_FP_optimization_goals = 31, + // 32 is generic (Tag_compatibility). + Tag_undefined33 = 33, + Tag_CPU_unaligned_access = 34, + Tag_undefined35 = 35, + Tag_VFP_HP_extension = 36, + Tag_undefined37 = 37, + Tag_ABI_FP_16bit_format = 38, + Tag_undefined39 = 39, + Tag_nodefaults = 64, + Tag_also_compatible_with = 65, + Tag_T2EE_use = 66, + Tag_conformance = 67, + Tag_Virtualization_use = 68, + Tag_undefined69 = 69, + Tag_MPextension_use = 70 +}; + +// Values for Tag_ABI_PCS_R9_use. +enum +{ + AEABI_R9_V6 = 0, + AEABI_R9_SB = 1, + AEABI_R9_TLS = 2, + AEABI_R9_unused = 3 +}; + +// Values for Tag_ABI_PCS_RW_data. +enum +{ + AEABI_PCS_RW_data_absolute = 0, + AEABI_PCS_RW_data_PCrel = 1, + AEABI_PCS_RW_data_SBrel = 2, + AEABI_PCS_RW_data_unused = 3 +}; + +// Values for Tag_ABI_enum_size. +enum +{ + AEABI_enum_unused = 0, + AEABI_enum_short = 1, + AEABI_enum_wide = 2, + AEABI_enum_forced_wide = 3 +}; + +// For Exception Index Table. (Exception handling ABI for the ARM +// architectue, Section 5) +enum +{ + EXIDX_CANTUNWIND = 1, +}; + +} // End namespace elfcpp. + +#endif // !defined(ELFCPP_ARM_H) diff --git a/binutils-2.19/elfcpp/elfcpp.h b/binutils-2.19/elfcpp/elfcpp.h index 080eef1..8ecbc0a 100644 --- a/binutils-2.19/elfcpp/elfcpp.h +++ b/binutils-2.19/elfcpp/elfcpp.h @@ -1,10 +1,10 @@ // elfcpp.h -- main header file for elfcpp -*- C++ -*- -// Copyright 2006, 2007, Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of elfcpp. - + // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public License // as published by the Free Software Foundation; either version 2, or @@ -17,7 +17,7 @@ // combinations without any restriction coming from the use of this // file. (The Library Public License restrictions do apply in other // respects; for example, they cover modification of the file, and -/// distribution when not linked into a combined executable.) +// distribution when not linked into a combined executable.) // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of @@ -302,6 +302,15 @@ enum EM // Old MN10200 objects used 0xdead (EM_MN10200 is correct). }; +// A special value found in the Ehdr e_phnum field. + +enum +{ + // Number of program segments stored in sh_info field of first + // section headre. + PN_XNUM = 0xffff +}; + // Special section indices. enum @@ -321,6 +330,9 @@ enum // with the SHF_LINK_ORDER and SHF_ORDERED section flags. SHN_BEFORE = 0xff00, SHN_AFTER = 0xff01, + + // x86_64 specific large common symbol. + SHN_X86_64_LCOMMON = 0xff02 }; // The valid values found in the Shdr sh_type field. @@ -351,6 +363,8 @@ enum SHT SHT_LOUSER = 0x80000000, SHT_HIUSER = 0xffffffff, // The remaining values are not in the standard. + // Incremental build data. + SHT_GNU_INCREMENTAL_INPUTS = 0x6fff4700, // Object attributes. SHT_GNU_ATTRIBUTES = 0x6ffffff5, // GNU style dynamic hash table. @@ -369,9 +383,23 @@ enum SHT SHT_SPARC_GOTDATA = 0x70000000, + // ARM-specific section types. + // Exception Index table. + SHT_ARM_EXIDX = 0x70000001, + // BPABI DLL dynamic linking pre-emption map. + SHT_ARM_PREEMPTMAP = 0x70000002, + // Object file compatibility attributes. + SHT_ARM_ATTRIBUTES = 0x70000003, + // Support for debugging overlaid programs. + SHT_ARM_DEBUGOVERLAY = 0x70000004, + SHT_ARM_OVERLAYSECTION = 0x70000005, + + // x86_64 unwind information. + SHT_X86_64_UNWIND = 0x70000001, + // Link editor is to sort the entries in this section based on the // address specified in the associated symbol table entry. - SHT_ORDERED = 0x7fffffff, + SHT_ORDERED = 0x7fffffff }; // The valid bit flags found in the Shdr sh_flags field. @@ -402,6 +430,9 @@ enum SHF // executable or shared object. This flag is ignored if SHF_ALLOC // is also set, or if relocations exist against the section. SHF_EXCLUDE = 0x80000000, + + // x86_64 specific large section. + SHF_X86_64_LARGE = 0x10000000 }; // Bit flags which appear in the first 32-bit word of the section data @@ -437,7 +468,11 @@ enum PT // Stack flags. PT_GNU_STACK = 0x6474e551, // Read only after relocation. - PT_GNU_RELRO = 0x6474e552 + PT_GNU_RELRO = 0x6474e552, + // Platform architecture compatibility information + PT_ARM_ARCHEXT = 0x70000000, + // Exception unwind tables + PT_ARM_EXIDX = 0x70000001 }; // The valid bit flags found in the Phdr p_flags field. @@ -459,6 +494,7 @@ enum STB STB_GLOBAL = 1, STB_WEAK = 2, STB_LOOS = 10, + STB_GNU_UNIQUE = 10, STB_HIOS = 12, STB_LOPROC = 13, STB_HIPROC = 15 @@ -476,6 +512,7 @@ enum STT STT_COMMON = 5, STT_TLS = 6, STT_LOOS = 10, + STT_GNU_IFUNC = 10, STT_HIOS = 12, STT_LOPROC = 13, STT_HIPROC = 15, @@ -483,6 +520,10 @@ enum STT // The section type that must be used for register symbols on // Sparc. These symbols initialize a global register. STT_SPARC_REGISTER = 13, + + // ARM: a THUMB function. This is not defined in ARM ELF Specification but + // used by the GNU tool-chain. + STT_ARM_TFUNC = 13 }; inline STB @@ -624,8 +665,12 @@ enum DT DT_FINI_ARRAYSZ = 28, DT_RUNPATH = 29, DT_FLAGS = 30, + + // This is used to mark a range of dynamic tags. It is not really + // a tag value. DT_ENCODING = 32, - DT_PREINIT_ARRAY = 33, + + DT_PREINIT_ARRAY = 32, DT_PREINIT_ARRAYSZ = 33, DT_LOOS = 0x6000000d, DT_HIOS = 0x6ffff000, @@ -719,7 +764,7 @@ enum DF_1 DF_1_INTERPOSE = 0x400, DF_1_NODEFLIB = 0x800, DF_1_NODUMP = 0x1000, - DF_1_CONLFAT = 0x2000, + DF_1_CONLFAT = 0x2000 }; // Version numbers which appear in the vd_version field of a Verdef @@ -934,7 +979,7 @@ class Ehdr_write void put_e_type(Elf_Half v) { this->p_->e_type = Convert<16, big_endian>::convert_host(v); } - + void put_e_machine(Elf_Half v) { this->p_->e_machine = Convert<16, big_endian>::convert_host(v); } diff --git a/binutils-2.19/elfcpp/elfcpp_file.h b/binutils-2.19/elfcpp/elfcpp_file.h index f1f4423..8dd7ad5 100644 --- a/binutils-2.19/elfcpp/elfcpp_file.h +++ b/binutils-2.19/elfcpp/elfcpp_file.h @@ -53,15 +53,47 @@ // This permits writing // elfcpp::Shdr shdr(file, ef.section_header(n)); -#ifndef ELFPCP_FILE_H +#ifndef ELFCPP_FILE_H #define ELFCPP_FILE_H #include <string> +#include <cstdio> #include <cstring> +#include "elfcpp.h" + namespace elfcpp { +// A simple helper class to recognize if a file has an ELF header. + +class Elf_recognizer +{ + public: + // Maximum header size. The user should try to read this much of + // the file when using this class. + + static const int max_header_size = Elf_sizes<64>::ehdr_size; + + // Checks if the file contains the ELF magic. Other header fields + // are not checked. + + static bool + is_elf_file(const unsigned char* ehdr_buf, int size); + + // Check if EHDR_BUF/BUFSIZE is a valid header of a 32-bit or + // 64-bit, little-endian or big-endian ELF file. Assumes + // is_elf_file() has been checked to be true. If the header is not + // valid, *ERROR contains a human-readable error message. If is is, + // *SIZE is set to either 32 or 64, *BIG_ENDIAN is set to indicate + // whether the file is big-endian. + + static bool + is_valid_header(const unsigned char* ehdr_buf, off_t bufsize, + int* size, bool* big_endian, + std::string* error); +}; + // This object is used to read an ELF file. // SIZE: The size of file, 32 or 64. // BIG_ENDIAN: Whether the file is in big-endian format. @@ -99,6 +131,11 @@ class Elf_file shoff() const { return this->shoff_; } + // Find the first section with an sh_type field equal to TYPE and + // return its index. Returns SHN_UNDEF if there is no such section. + unsigned int + find_section_by_type(unsigned int type); + // Return the number of sections. unsigned int shnum() @@ -193,6 +230,142 @@ class Elf_file int large_shndx_offset_; }; +// A small wrapper around SHT_STRTAB data mapped to memory. It checks that the +// index is not out of bounds and the string is NULL-terminated. + +class Elf_strtab +{ + public: + // Construct an Elf_strtab for a section with contents *P and size SIZE. + Elf_strtab(const unsigned char* p, size_t size); + + // Return the file offset to the section headers. + bool + get_c_string(size_t offset, const char** cstring) const + { + if (offset >= this->usable_size_) + return false; + *cstring = this->base_ + offset; + return true; + } + + private: + // Contents of the section mapped to memory. + const char* base_; + // One larger that the position of the last NULL character in the section. + // For valid SHT_STRTAB sections, this is the size of the section. + size_t usable_size_; +}; + +// Inline function definitions. + +// Check for presence of the ELF magic number. + +inline bool +Elf_recognizer::is_elf_file(const unsigned char* ehdr_buf, int size) +{ + if (size < 4) + return false; + + static unsigned char elfmagic[4] = + { + elfcpp::ELFMAG0, elfcpp::ELFMAG1, + elfcpp::ELFMAG2, elfcpp::ELFMAG3 + }; + return memcmp(ehdr_buf, elfmagic, 4) == 0; +} + +namespace +{ + +// Print a number to a string. + +inline std::string +internal_printf_int(const char* format, int arg) +{ + char buf[256]; + snprintf(buf, sizeof(buf), format, arg); + return std::string(buf); +} + +} // End anonymous namespace. + +// Check the validity of the ELF header. + +inline bool +Elf_recognizer::is_valid_header( + const unsigned char* ehdr_buf, + off_t bufsize, + int* size, + bool* big_endian, + std::string* error) +{ + if (bufsize < elfcpp::EI_NIDENT) + { + *error = _("ELF file too short"); + return false; + } + + int v = ehdr_buf[elfcpp::EI_VERSION]; + if (v != elfcpp::EV_CURRENT) + { + if (v == elfcpp::EV_NONE) + *error = _("invalid ELF version 0"); + else + *error = internal_printf_int(_("unsupported ELF version %d"), v); + return false; + } + + int c = ehdr_buf[elfcpp::EI_CLASS]; + if (c == elfcpp::ELFCLASSNONE) + { + *error = _("invalid ELF class 0"); + return false; + } + else if (c != elfcpp::ELFCLASS32 + && c != elfcpp::ELFCLASS64) + { + *error = internal_printf_int(_("unsupported ELF class %d"), c); + return false; + } + + int d = ehdr_buf[elfcpp::EI_DATA]; + if (d == elfcpp::ELFDATANONE) + { + *error = _("invalid ELF data encoding"); + return false; + } + else if (d != elfcpp::ELFDATA2LSB + && d != elfcpp::ELFDATA2MSB) + { + *error = internal_printf_int(_("unsupported ELF data encoding %d"), d); + return false; + } + + *big_endian = (d == elfcpp::ELFDATA2MSB); + + if (c == elfcpp::ELFCLASS32) + { + if (bufsize < elfcpp::Elf_sizes<32>::ehdr_size) + { + *error = _("ELF file too short"); + return false; + } + *size = 32; + } + else + { + if (bufsize < elfcpp::Elf_sizes<64>::ehdr_size) + { + *error = _("ELF file too short"); + return false; + } + *size = 64; + } + + return true; +} + // Template function definitions. // Construct an Elf_file given an ELF file header. @@ -269,6 +442,25 @@ Elf_file<size, big_endian, File>::initialize_shnum() } } +// Find section with sh_type equal to TYPE and return its index. +// Returns SHN_UNDEF if not found. + +template<int size, bool big_endian, typename File> +unsigned int +Elf_file<size, big_endian, File>::find_section_by_type(unsigned int type) +{ + unsigned int shnum = this->shnum(); + typename File::View v(this->file_->view(this->shoff_, + This::shdr_size * shnum)); + for (unsigned int i = 0; i < shnum; i++) + { + Ef_shdr shdr(v.data() + This::shdr_size * i); + if (shdr.get_sh_type() == type) + return i; + } + return SHN_UNDEF; +} + // Return the file offset of the section header of section SHNDX. template<int size, bool big_endian, typename File> @@ -300,7 +492,7 @@ Elf_file<size, big_endian, File>::section_name(unsigned int shndx) // Get the file offset for the section name string table data. off_t shstr_off; - off_t shstr_size; + typename Elf_types<size>::Elf_WXword shstr_size; { const unsigned int shstrndx = this->shstrndx_; typename File::View v(file->view(this->section_header_offset(shstrndx), @@ -479,6 +671,18 @@ Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx) return shdr.get_sh_addralign(); } +inline +Elf_strtab::Elf_strtab(const unsigned char* p, size_t size) +{ + // Check if the section is NUL-terminated. If it isn't, we ignore + // the last part to make sure we don't return non-NUL-terminated + // strings. + while (size > 0 && p[size - 1] != 0) + size--; + this->base_ = reinterpret_cast<const char*>(p); + this->usable_size_ = size; +} + } // End namespace elfcpp. #endif // !defined(ELFCPP_FILE_H) diff --git a/binutils-2.19/elfcpp/elfcpp_swap.h b/binutils-2.19/elfcpp/elfcpp_swap.h index 9f445dc..0685276 100644 --- a/binutils-2.19/elfcpp/elfcpp_swap.h +++ b/binutils-2.19/elfcpp/elfcpp_swap.h @@ -1,6 +1,6 @@ // elfcpp_swap.h -- Handle swapping for elfcpp -*- C++ -*- -// Copyright 2006, 2007, Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of elfcpp. @@ -37,8 +37,54 @@ #define ELFCPP_SWAP_H #include <stdint.h> -#include <endian.h> + +// We need an autoconf-generated config.h file for endianness and +// swapping. We check two macros: WORDS_BIGENDIAN and +// HAVE_BYTESWAP_H. + +#include "config.h" + +#ifdef HAVE_BYTESWAP_H #include <byteswap.h> +#else +// Provide our own versions of the byteswap functions. +inline uint16_t +bswap_16(uint16_t v) +{ + return ((v >> 8) & 0xff) | ((v & 0xff) << 8); +} + +inline uint32_t +bswap_32(uint32_t v) +{ + return ( ((v & 0xff000000) >> 24) + | ((v & 0x00ff0000) >> 8) + | ((v & 0x0000ff00) << 8) + | ((v & 0x000000ff) << 24)); +} + +inline uint64_t +bswap_64(uint64_t v) +{ + return ( ((v & 0xff00000000000000ULL) >> 56) + | ((v & 0x00ff000000000000ULL) >> 40) + | ((v & 0x0000ff0000000000ULL) >> 24) + | ((v & 0x000000ff00000000ULL) >> 8) + | ((v & 0x00000000ff000000ULL) << 8) + | ((v & 0x0000000000ff0000ULL) << 24) + | ((v & 0x000000000000ff00ULL) << 40) + | ((v & 0x00000000000000ffULL) << 56)); +} +#endif // !defined(HAVE_BYTESWAP_H) + +// gcc 4.3 and later provides __builtin_bswap32 and __builtin_bswap64. + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +#undef bswap_32 +#define bswap_32 __builtin_bswap32 +#undef bswap_64 +#define bswap_64 __builtin_bswap64 +#endif namespace elfcpp { @@ -49,7 +95,13 @@ struct Endian { public: // Used for template specializations. - static const bool host_big_endian = __BYTE_ORDER == __BIG_ENDIAN; + static const bool host_big_endian = +#ifdef WORDS_BIGENDIAN + true +#else + false +#endif + ; }; // Valtype_base is a template based on size (8, 16, 32, 64) which diff --git a/binutils-2.19/gas/config/bfin-aux.h b/binutils-2.19/gas/config/bfin-aux.h index 617140b..617140b 100755..100644 --- a/binutils-2.19/gas/config/bfin-aux.h +++ b/binutils-2.19/gas/config/bfin-aux.h diff --git a/binutils-2.19/gas/config/tc-arm.c b/binutils-2.19/gas/config/tc-arm.c index 7b94732..d21fac2 100644 --- a/binutils-2.19/gas/config/tc-arm.c +++ b/binutils-2.19/gas/config/tc-arm.c @@ -1,6 +1,6 @@ /* tc-arm.c -- Assemble for the ARM Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008 + 2004, 2005, 2006, 2007, 2008, 2010 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modified by David Taylor (dtaylor@armltd.co.uk) @@ -14689,7 +14689,8 @@ static struct reloc_entry reloc_names[] = { "tlsldm", BFD_RELOC_ARM_TLS_LDM32}, { "TLSLDM", BFD_RELOC_ARM_TLS_LDM32}, { "tlsldo", BFD_RELOC_ARM_TLS_LDO32}, { "TLSLDO", BFD_RELOC_ARM_TLS_LDO32}, { "gottpoff",BFD_RELOC_ARM_TLS_IE32}, { "GOTTPOFF",BFD_RELOC_ARM_TLS_IE32}, - { "tpoff", BFD_RELOC_ARM_TLS_LE32}, { "TPOFF", BFD_RELOC_ARM_TLS_LE32} + { "tpoff", BFD_RELOC_ARM_TLS_LE32}, { "TPOFF", BFD_RELOC_ARM_TLS_LE32}, + { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL} }; #endif @@ -17159,9 +17160,15 @@ arm_frag_align_code (int n, int max) char * p; /* We assume that there will never be a requirement - to support alignments greater than 32 bytes. */ + to support alignments greater than [MAX_MEM_FOR_RS_ALIGN_CODE] bytes. */ if (max > MAX_MEM_FOR_RS_ALIGN_CODE) - as_fatal (_("alignments greater than 32 bytes not supported in .text sections.")); + { + char err_msg[128]; + sprintf (err_msg, + _("alignments greater than %d bytes not supported in .text sections."), + MAX_MEM_FOR_RS_ALIGN_CODE + 1); + as_fatal (err_msg); + } p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, @@ -18629,6 +18636,11 @@ md_apply_fix (fixS * fixP, if (fixP->fx_done || !seg->use_rela_p) md_number_to_chars (buf, 0, 4); break; + + case BFD_RELOC_ARM_GOT_PREL: + if (fixP->fx_done || !seg->use_rela_p) + md_number_to_chars (buf, value, 4); + break; #endif case BFD_RELOC_RVA: @@ -19206,6 +19218,7 @@ tc_gen_reloc (asection *section, fixS *fixp) #ifdef OBJ_ELF case BFD_RELOC_ARM_GOT32: case BFD_RELOC_ARM_GOTOFF: + case BFD_RELOC_ARM_GOT_PREL: case BFD_RELOC_ARM_PLT32: case BFD_RELOC_ARM_TARGET1: case BFD_RELOC_ARM_ROSEGREL32: diff --git a/binutils-2.19/gas/config/tc-arm.h b/binutils-2.19/gas/config/tc-arm.h index 9b58762..aa70c60 100644 --- a/binutils-2.19/gas/config/tc-arm.h +++ b/binutils-2.19/gas/config/tc-arm.h @@ -179,7 +179,8 @@ void arm_copy_symbol_attributes (symbolS *, symbolS *); #define TC_CONS_FIX_NEW cons_fix_new_arm -#define MAX_MEM_FOR_RS_ALIGN_CODE 31 +#define MAX_MEM_ALIGNMENT_BYTES 6 +#define MAX_MEM_FOR_RS_ALIGN_CODE ((1 << MAX_MEM_ALIGNMENT_BYTES) - 1) /* For frags in code sections we need to record whether they contain ARM code or THUMB code. This is that if they have to be aligned, diff --git a/binutils-2.19/gas/doc/c-arm.texi b/binutils-2.19/gas/doc/c-arm.texi index 9e698b0..3962418 100644 --- a/binutils-2.19/gas/doc/c-arm.texi +++ b/binutils-2.19/gas/doc/c-arm.texi @@ -362,7 +362,8 @@ The following relocations are supported: @code{TLSGD}, @code{TLSLDM}, @code{TLSLDO}, -@code{GOTTPOFF} +@code{GOTTPOFF}, +@code{GOT_PREL} and @code{TPOFF}. diff --git a/binutils-2.19/gas/testsuite/gas/arm/fp-save.s b/binutils-2.19/gas/testsuite/gas/arm/fp-save.s index d86d749..9b8ae80 100644 --- a/binutils-2.19/gas/testsuite/gas/arm/fp-save.s +++ b/binutils-2.19/gas/testsuite/gas/arm/fp-save.s @@ -1,2 +1,2 @@ - sfmfd f4, 1, [sp]!
- .save f4, 1
+ sfmfd f4, 1, [sp]! + .save f4, 1 diff --git a/binutils-2.19/gas/testsuite/gas/arm/got_prel.d b/binutils-2.19/gas/testsuite/gas/arm/got_prel.d new file mode 100644 index 0000000..a4a602c --- /dev/null +++ b/binutils-2.19/gas/testsuite/gas/arm/got_prel.d @@ -0,0 +1,19 @@ +# name: R_ARM_GOT_PREL relocation +# source: got_prel.s +# as: -march=armv5te -meabi=5 +# readelf: -x 4 -r +# target: *-*-*eabi *-*-symbianelf *-*-linux-* *-*-elf + +Relocation section '.rel.text.foo' at offset 0x3ec contains 1 entries: + Offset Info Type Sym.Value Sym. Name +00000010 00000c60 R_ARM_GOT_PREL 00000000 i + +Relocation section '.rel.ARM.exidx.text.foo' at offset 0x3f4 contains 2 entries: + Offset Info Type Sym.Value Sym. Name +00000000 0000052a R_ARM_PREL31 00000000 .text.foo +00000000 00000d00 R_ARM_NONE 00000000 __aeabi_unwind_cpp_pr0 + +Hex dump of section '.text.foo': + NOTE: This section has relocations against it, but these have NOT been applied to this dump. + 0x00000000 034b7b44 1b681a68 1860101c 7047c046 .K{D.h.h.`..pG.F + 0x00000010 0a000000 .... diff --git a/binutils-2.19/gas/testsuite/gas/arm/got_prel.s b/binutils-2.19/gas/testsuite/gas/arm/got_prel.s new file mode 100644 index 0000000..9628d47 --- /dev/null +++ b/binutils-2.19/gas/testsuite/gas/arm/got_prel.s @@ -0,0 +1,23 @@ + .code 16 + .text +.Ltext0: + .section .text.foo,"ax",%progbits + .align 2 + .global foo + .code 16 + .thumb_func + .type foo, %function +foo: + .fnstart + ldr r3, .L3 +.LPIC0: + add r3, pc + ldr r3, [r3] + ldr r2, [r3] + str r0, [r3] + mov r0, r2 + bx lr + .align 2 +.L3: + .word i(GOT_PREL) + (. - (.LPIC0+4)) + .fnend diff --git a/binutils-2.19/gas/testsuite/gas/bfin/bit2.s b/binutils-2.19/gas/testsuite/gas/bfin/bit2.s index 2e06229..2e06229 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/bit2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/bit2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/cache2.s b/binutils-2.19/gas/testsuite/gas/bfin/cache2.s index afa7365..afa7365 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/cache2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/cache2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/control_code2.s b/binutils-2.19/gas/testsuite/gas/bfin/control_code2.s index 50648cc..50648cc 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/control_code2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/control_code2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/event2.s b/binutils-2.19/gas/testsuite/gas/bfin/event2.s index a8b0ec1..a8b0ec1 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/event2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/event2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/logical2.s b/binutils-2.19/gas/testsuite/gas/bfin/logical2.s index d9b6274..d9b6274 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/logical2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/logical2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/move2.s b/binutils-2.19/gas/testsuite/gas/bfin/move2.s index ac8ae8d..ac8ae8d 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/move2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/move2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/shift2.s b/binutils-2.19/gas/testsuite/gas/bfin/shift2.s index 99115a6..99115a6 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/shift2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/shift2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/stack2.s b/binutils-2.19/gas/testsuite/gas/bfin/stack2.s index 0824e7b..0824e7b 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/stack2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/stack2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/vector2.s b/binutils-2.19/gas/testsuite/gas/bfin/vector2.s index be1a5b7..be1a5b7 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/vector2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/vector2.s diff --git a/binutils-2.19/gas/testsuite/gas/bfin/video2.s b/binutils-2.19/gas/testsuite/gas/bfin/video2.s index 22fb50f..22fb50f 100755..100644 --- a/binutils-2.19/gas/testsuite/gas/bfin/video2.s +++ b/binutils-2.19/gas/testsuite/gas/bfin/video2.s diff --git a/binutils-2.19/gas/testsuite/gas/cr16/bal_test.s b/binutils-2.19/gas/testsuite/gas/cr16/bal_test.s index b89f1f6..ff329ab 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/bal_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/bal_test.s @@ -1,14 +1,14 @@ - .text
- .global main
-main:
-bal (ra),*+0xff122
-bal (ra),*+0xfff126
-bal (ra),*+0x22
-bal (ra),*+0x122
-bal (ra),*+0xf122
-bal (ra),*+0x812a
-bal (r1,r0),*+0x122
-bal (r11,r10),*+0xcff122
-bal (r7,r6),*+0xaff122
-bal (r4,r3),*+0x8ff122
-bal (r8,r7),*+0xfff122
+ .text + .global main +main: +bal (ra),*+0xff122 +bal (ra),*+0xfff126 +bal (ra),*+0x22 +bal (ra),*+0x122 +bal (ra),*+0xf122 +bal (ra),*+0x812a +bal (r1,r0),*+0x122 +bal (r11,r10),*+0xcff122 +bal (r7,r6),*+0xaff122 +bal (r4,r3),*+0x8ff122 +bal (r8,r7),*+0xfff122 diff --git a/binutils-2.19/gas/testsuite/gas/cr16/bcc_test.s b/binutils-2.19/gas/testsuite/gas/cr16/bcc_test.s index 50f3fbe..e22dbe8 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/bcc_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/bcc_test.s @@ -1,59 +1,59 @@ - .text
- .global main
-main:
- ###################
- # bcc disp9/disp17/disp25
- ###################
- # bcc disp9
- ###################
- beq *+0x022
- bne *+0x032
- bcc *+0x044
- bcc *+0x054
- bhi *+0x066
- blt *+0x076
- bgt *+0x088
- bfs *+0x09a
- bfc *+0x0aa
- blo *+0x1bc
- bhi *+0x1cc
- blt *+0x1d6
- bge *+0x1e6
- br *+0x0f6
- ###################
- # bcc disp17
- ###################
- beq *+0x112
- beq *+0x1f12
- beq *+0x0f22
- bne *+0x0f34
- bcc *+0x0f44
- bcc *+0x0f56
- bhi *+0x0f66
- blt *+0x0f78
- bgt *+0x0f88
- bfs *+0x0f9a
- bfc *+0x0faa
- blo *+0x1fbc
- bhi *+0x1fcc
- blt *+0x1fda
- bge *+0x1fea
- br *+0xfffa
- ###################
- # bcc disp25
- ###################
- beq *+0xff1f12
- beq *+0xaa0f22
- bne *+0xbb0f34
- bcc *+0xcc0f44
- bcc *+0xdd0f56
- bhi *+0x990f66
- blt *+0x880f78
- bgt *+0x770f88
- bfs *+0x660f9a
- bfc *+0x550faa
- blo *+0x441fbc
- bhi *+0x331fcc
- blt *+0x221fde
- bge *+0x111fee
- br *+0x0ffffe
+ .text + .global main +main: + ################### + # bcc disp9/disp17/disp25 + ################### + # bcc disp9 + ################### + beq *+0x022 + bne *+0x032 + bcc *+0x044 + bcc *+0x054 + bhi *+0x066 + blt *+0x076 + bgt *+0x088 + bfs *+0x09a + bfc *+0x0aa + blo *+0x1bc + bhi *+0x1cc + blt *+0x1d6 + bge *+0x1e6 + br *+0x0f6 + ################### + # bcc disp17 + ################### + beq *+0x112 + beq *+0x1f12 + beq *+0x0f22 + bne *+0x0f34 + bcc *+0x0f44 + bcc *+0x0f56 + bhi *+0x0f66 + blt *+0x0f78 + bgt *+0x0f88 + bfs *+0x0f9a + bfc *+0x0faa + blo *+0x1fbc + bhi *+0x1fcc + blt *+0x1fda + bge *+0x1fea + br *+0xfffa + ################### + # bcc disp25 + ################### + beq *+0xff1f12 + beq *+0xaa0f22 + bne *+0xbb0f34 + bcc *+0xcc0f44 + bcc *+0xdd0f56 + bhi *+0x990f66 + blt *+0x880f78 + bgt *+0x770f88 + bfs *+0x660f9a + bfc *+0x550faa + blo *+0x441fbc + bhi *+0x331fcc + blt *+0x221fde + bge *+0x111fee + br *+0x0ffffe diff --git a/binutils-2.19/gas/testsuite/gas/cr16/cinv_test.s b/binutils-2.19/gas/testsuite/gas/cr16/cinv_test.s index eda4b97..9d2490b 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/cinv_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/cinv_test.s @@ -1,12 +1,12 @@ - .text
- .global main
-main:
- ##############################
- # cin [i/i,u/d/d,u/d,i/d,i,u]
- ##############################
- cinv [i]
- cinv [i,u]
- cinv [d]
- cinv [d,u]
- cinv [d,i]
- cinv [d,i,u]
+ .text + .global main +main: + ############################## + # cin [i/i,u/d/d,u/d,i/d,i,u] + ############################## + cinv [i] + cinv [i,u] + cinv [d] + cinv [d,u] + cinv [d,i] + cinv [d,i,u] diff --git a/binutils-2.19/gas/testsuite/gas/cr16/loadb_test.s b/binutils-2.19/gas/testsuite/gas/cr16/loadb_test.s index 258e3b3..05345b9 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/loadb_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/loadb_test.s @@ -1,72 +1,72 @@ - .text
- .global main
-main:
- ######################
- # loadb abs20/24 reg
- ######################
- loadb 0x0,r0
- loadb 0xff,r1
- loadb 0xfff,r3
- loadb 0x1234,r4
- loadb 0x1234,r5
- loadb 0x7A1234,r0
- loadb 0xBA1234,r1
- loadb 0xffffff,r2
- ######################
- # loadb abs20 rel reg
- ######################
- loadb [r12]0x0,r0
- loadb [r13]0x0,r0
- loadb [r12]0xff,r1
- loadb [r13]0xff,r1
- loadb [r12]0xfff,r3
- loadb [r13]0xfff,r3
- loadb [r12]0x1234,r4
- loadb [r13]0x1234,r4
- loadb [r12]0x1234,r5
- loadb [r13]0x1234,r5
- loadb [r12]0x4567,r2
- loadb [r13]0xA1234,r2
- ###################################
- # loadb rbase(disp20/-disp20) reg
- ###################################
- loadb 0x4(r1,r0),r1
- loadb 0x4(r3,r2),r3
- loadb 0x1234(r1,r0),r4
- loadb 0x1234(r3,r2),r5
- loadb 0xA1234(r1,r0),r6
- loadb -0x4(r1,r0),r1
- loadb -0x4(r3,r2),r3
- loadb -0x1234(r1,r0),r4
- loadb -0x1234(r3,r2),r5
- loadb -0xA1234(r1,r0),r6
- #################################################
- # loadb rpbase(disp4/disp16/disp20/-disp20) reg
- #################################################
- loadb 0x0(r1,r0),r0
- loadb 0x0(r1,r0),r1
- loadb 0xf(r1,r0),r0
- loadb 0xf(r1,r0),r1
- loadb 0x1234(r1,r0),r2
- loadb 0xabcd(r3,r2),r3
- loadb 0xAfff(r4,r3),r4
- loadb 0xA1234(r6,r5),r5
- loadb -0xf(r1,r0),r0
- loadb -0xf(r1,r0),r1
- loadb -0x1234(r1,r0),r2
- loadb -0xabcd(r3,r2),r3
- loadb -0xAfff(r4,r3),r4
- loadb -0xA1234(r6,r5),r5
- ####################################
- # loadb rbase(disp0/disp14) rel reg
- ####################################
- loadb [r12]0x0(r1,r0),r0
- loadb [r13]0x0(r1,r0),r1
- loadb [r12]0x1234(r1,r0),r2
- loadb [r13]0x1abcd(r1,r0),r3
- #################################
- # loadb rpbase(disp20) rel reg
- #################################
- loadb [r12]0xA1234(r1,r0),r4
- loadb [r13]0xB1234(r1,r0),r5
- loadb [r13]0xfffff(r1,r0),r6
+ .text + .global main +main: + ###################### + # loadb abs20/24 reg + ###################### + loadb 0x0,r0 + loadb 0xff,r1 + loadb 0xfff,r3 + loadb 0x1234,r4 + loadb 0x1234,r5 + loadb 0x7A1234,r0 + loadb 0xBA1234,r1 + loadb 0xffffff,r2 + ###################### + # loadb abs20 rel reg + ###################### + loadb [r12]0x0,r0 + loadb [r13]0x0,r0 + loadb [r12]0xff,r1 + loadb [r13]0xff,r1 + loadb [r12]0xfff,r3 + loadb [r13]0xfff,r3 + loadb [r12]0x1234,r4 + loadb [r13]0x1234,r4 + loadb [r12]0x1234,r5 + loadb [r13]0x1234,r5 + loadb [r12]0x4567,r2 + loadb [r13]0xA1234,r2 + ################################### + # loadb rbase(disp20/-disp20) reg + ################################### + loadb 0x4(r1,r0),r1 + loadb 0x4(r3,r2),r3 + loadb 0x1234(r1,r0),r4 + loadb 0x1234(r3,r2),r5 + loadb 0xA1234(r1,r0),r6 + loadb -0x4(r1,r0),r1 + loadb -0x4(r3,r2),r3 + loadb -0x1234(r1,r0),r4 + loadb -0x1234(r3,r2),r5 + loadb -0xA1234(r1,r0),r6 + ################################################# + # loadb rpbase(disp4/disp16/disp20/-disp20) reg + ################################################# + loadb 0x0(r1,r0),r0 + loadb 0x0(r1,r0),r1 + loadb 0xf(r1,r0),r0 + loadb 0xf(r1,r0),r1 + loadb 0x1234(r1,r0),r2 + loadb 0xabcd(r3,r2),r3 + loadb 0xAfff(r4,r3),r4 + loadb 0xA1234(r6,r5),r5 + loadb -0xf(r1,r0),r0 + loadb -0xf(r1,r0),r1 + loadb -0x1234(r1,r0),r2 + loadb -0xabcd(r3,r2),r3 + loadb -0xAfff(r4,r3),r4 + loadb -0xA1234(r6,r5),r5 + #################################### + # loadb rbase(disp0/disp14) rel reg + #################################### + loadb [r12]0x0(r1,r0),r0 + loadb [r13]0x0(r1,r0),r1 + loadb [r12]0x1234(r1,r0),r2 + loadb [r13]0x1abcd(r1,r0),r3 + ################################# + # loadb rpbase(disp20) rel reg + ################################# + loadb [r12]0xA1234(r1,r0),r4 + loadb [r13]0xB1234(r1,r0),r5 + loadb [r13]0xfffff(r1,r0),r6 diff --git a/binutils-2.19/gas/testsuite/gas/cr16/loadd_test.s b/binutils-2.19/gas/testsuite/gas/cr16/loadd_test.s index 677752d..22c641f 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/loadd_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/loadd_test.s @@ -1,72 +1,72 @@ - .text
- .global main
-main:
- ######################
- # loadd abs20/24 regp
- ######################
- loadd 0x0,(r1,r0)
- loadd 0xff,(r1,r0)
- loadd 0xfff,(r3,r2)
- loadd 0x1234,(r4,r3)
- loadd 0x1234,(r5,r4)
- loadd 0x7A1234,(r1,r0)
- loadd 0xBA1234,(r1,r0)
- loadd 0xffffff,(r2,r1)
- ######################
- # loadd abs20 rel regp
- ######################
- loadd [r12]0x0,(r1,r0)
- loadd [r13]0x0,(r1,r0)
- loadd [r12]0xff,(r1,r0)
- loadd [r13]0xff,(r1,r0)
- loadd [r12]0xfff,(r3,r2)
- loadd [r13]0xfff,(r3,r2)
- loadd [r12]0x1234,(r4,r3)
- loadd [r13]0x1234,(r4,r3)
- loadd [r12]0x1234,(r5,r4)
- loadd [r13]0x1234,(r5,r4)
- loadd [r12]0x4567,(r2,r1)
- loadd [r13]0xA1234,(r2,r1)
- ###################################
- # loadd rbase(disp20/-disp20) regp
- ###################################
- loadd 0x4(r1,r0),(r2,r1)
- loadd 0x4(r3,r2),(r3,r2)
- loadd 0x1234(r1,r0),(r4,r3)
- loadd 0x1234(r3,r2),(r5,r4)
- loadd 0xA1234(r1,r0),(r6,r5)
- loadd -0x4(r1,r0),(r2,r1)
- loadd -0x4(r3,r2),(r3,r2)
- loadd -0x1234(r1,r0),(r4,r3)
- loadd -0x1234(r3,r2),(r5,r4)
- loadd -0xA1234(r1,r0),(r6,r5)
- #################################################
- # loadd rpbase(disp4/disp16/disp20/-disp20) reg
- #################################################
- loadd 0x0(r1,r0),(r1,r0)
- loadd 0x0(r1,r0),(r1,r0)
- loadd 0xf(r1,r0),(r1,r0)
- loadd 0xf(r1,r0),(r1,r0)
- loadd 0x1234(r1,r0),(r2,r1)
- loadd 0xabcd(r3,r2),(r3,r2)
- loadd 0xAfff(r4,r3),(r4,r3)
- loadd 0xA1234(r6,r5),(r7,r6)
- loadd -0xf(r1,r0),(r1,r0)
- loadd -0xf(r1,r0),(r1,r0)
- loadd -0x1234(r1,r0),(r2,r1)
- loadd -0xabcd(r3,r2),(r3,r2)
- loadd -0xAfff(r4,r3),(r5,r4)
- loadd -0xA1234(r6,r5),(r5,r4)
- ####################################
- # loadd rbase(disp0/disp14) rel reg
- ####################################
- loadd [r12]0x0(r1,r0),(r1,r0)
- loadd [r13]0x0(r1,r0),(r1,r0)
- loadd [r12]0x1234(r1,r0),(r2,r1)
- loadd [r13]0x1abcd(r1,r0),(r3,r2)
- #################################
- # loadd rpbase(disp20) rel reg
- #################################
- loadd [r12]0xA1234(r1,r0),(r3,r2)
- loadd [r13]0xB1234(r1,r0),(r4,r3)
- loadd [r13]0xfffff(r1,r0),(r5,r4)
+ .text + .global main +main: + ###################### + # loadd abs20/24 regp + ###################### + loadd 0x0,(r1,r0) + loadd 0xff,(r1,r0) + loadd 0xfff,(r3,r2) + loadd 0x1234,(r4,r3) + loadd 0x1234,(r5,r4) + loadd 0x7A1234,(r1,r0) + loadd 0xBA1234,(r1,r0) + loadd 0xffffff,(r2,r1) + ###################### + # loadd abs20 rel regp + ###################### + loadd [r12]0x0,(r1,r0) + loadd [r13]0x0,(r1,r0) + loadd [r12]0xff,(r1,r0) + loadd [r13]0xff,(r1,r0) + loadd [r12]0xfff,(r3,r2) + loadd [r13]0xfff,(r3,r2) + loadd [r12]0x1234,(r4,r3) + loadd [r13]0x1234,(r4,r3) + loadd [r12]0x1234,(r5,r4) + loadd [r13]0x1234,(r5,r4) + loadd [r12]0x4567,(r2,r1) + loadd [r13]0xA1234,(r2,r1) + ################################### + # loadd rbase(disp20/-disp20) regp + ################################### + loadd 0x4(r1,r0),(r2,r1) + loadd 0x4(r3,r2),(r3,r2) + loadd 0x1234(r1,r0),(r4,r3) + loadd 0x1234(r3,r2),(r5,r4) + loadd 0xA1234(r1,r0),(r6,r5) + loadd -0x4(r1,r0),(r2,r1) + loadd -0x4(r3,r2),(r3,r2) + loadd -0x1234(r1,r0),(r4,r3) + loadd -0x1234(r3,r2),(r5,r4) + loadd -0xA1234(r1,r0),(r6,r5) + ################################################# + # loadd rpbase(disp4/disp16/disp20/-disp20) reg + ################################################# + loadd 0x0(r1,r0),(r1,r0) + loadd 0x0(r1,r0),(r1,r0) + loadd 0xf(r1,r0),(r1,r0) + loadd 0xf(r1,r0),(r1,r0) + loadd 0x1234(r1,r0),(r2,r1) + loadd 0xabcd(r3,r2),(r3,r2) + loadd 0xAfff(r4,r3),(r4,r3) + loadd 0xA1234(r6,r5),(r7,r6) + loadd -0xf(r1,r0),(r1,r0) + loadd -0xf(r1,r0),(r1,r0) + loadd -0x1234(r1,r0),(r2,r1) + loadd -0xabcd(r3,r2),(r3,r2) + loadd -0xAfff(r4,r3),(r5,r4) + loadd -0xA1234(r6,r5),(r5,r4) + #################################### + # loadd rbase(disp0/disp14) rel reg + #################################### + loadd [r12]0x0(r1,r0),(r1,r0) + loadd [r13]0x0(r1,r0),(r1,r0) + loadd [r12]0x1234(r1,r0),(r2,r1) + loadd [r13]0x1abcd(r1,r0),(r3,r2) + ################################# + # loadd rpbase(disp20) rel reg + ################################# + loadd [r12]0xA1234(r1,r0),(r3,r2) + loadd [r13]0xB1234(r1,r0),(r4,r3) + loadd [r13]0xfffff(r1,r0),(r5,r4) diff --git a/binutils-2.19/gas/testsuite/gas/cr16/loadw_test.s b/binutils-2.19/gas/testsuite/gas/cr16/loadw_test.s index bd9a2bb..853e98f 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/loadw_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/loadw_test.s @@ -1,72 +1,72 @@ - .text
- .global main
-main:
- ######################
- # loadw abs20/24 reg
- ######################
- loadw 0x0,r0
- loadw 0xff,r1
- loadw 0xfff,r3
- loadw 0x1234,r4
- loadw 0x1234,r5
- loadw 0x7A1234,r0
- loadw 0xBA1234,r1
- loadw 0xffffff,r2
- ######################
- # loadw abs20 rel reg
- ######################
- loadw [r12]0x0,r0
- loadw [r13]0x0,r0
- loadw [r12]0xff,r1
- loadw [r13]0xff,r1
- loadw [r12]0xfff,r3
- loadw [r13]0xfff,r3
- loadw [r12]0x1234,r4
- loadw [r13]0x1234,r4
- loadw [r12]0x1234,r5
- loadw [r13]0x1234,r5
- loadw [r12]0x4567,r2
- loadw [r13]0xA1234,r2
- ###################################
- # loadw rbase(disp20/-disp20) reg
- ###################################
- loadw 0x4(r1,r0),r1
- loadw 0x4(r3,r2),r3
- loadw 0x1234(r1,r0),r4
- loadw 0x1234(r3,r2),r5
- loadw 0xA1234(r1,r0),r6
- loadw -0x4(r1,r0),r1
- loadw -0x4(r3,r2),r3
- loadw -0x1234(r1,r0),r4
- loadw -0x1234(r3,r2),r5
- loadw -0xA1234(r1,r0),r6
- #################################################
- # loadw rpbase(disp4/disp16/disp20/-disp20) reg
- #################################################
- loadw 0x0(r1,r0),r0
- loadw 0x0(r1,r0),r1
- loadw 0xf(r1,r0),r0
- loadw 0xf(r1,r0),r1
- loadw 0x1234(r1,r0),r2
- loadw 0xabcd(r3,r2),r3
- loadw 0xAfff(r4,r3),r4
- loadw 0xA1234(r6,r5),r5
- loadw -0xf(r1,r0),r0
- loadw -0xf(r1,r0),r1
- loadw -0x1234(r1,r0),r2
- loadw -0xabcd(r3,r2),r3
- loadw -0xAfff(r4,r3),r4
- loadw -0xA1234(r6,r5),r5
- ####################################
- # loadw rbase(disp0/disp14) rel reg
- ####################################
- loadw [r12]0x0(r1,r0),r0
- loadw [r13]0x0(r1,r0),r1
- loadw [r12]0x1234(r1,r0),r2
- loadw [r13]0x1abcd(r1,r0),r3
- #################################
- # loadw rpbase(disp20) rel reg
- #################################
- loadw [r12]0xA1234(r1,r0),r4
- loadw [r13]0xB1234(r1,r0),r5
- loadw [r13]0xfffff(r1,r0),r6
+ .text + .global main +main: + ###################### + # loadw abs20/24 reg + ###################### + loadw 0x0,r0 + loadw 0xff,r1 + loadw 0xfff,r3 + loadw 0x1234,r4 + loadw 0x1234,r5 + loadw 0x7A1234,r0 + loadw 0xBA1234,r1 + loadw 0xffffff,r2 + ###################### + # loadw abs20 rel reg + ###################### + loadw [r12]0x0,r0 + loadw [r13]0x0,r0 + loadw [r12]0xff,r1 + loadw [r13]0xff,r1 + loadw [r12]0xfff,r3 + loadw [r13]0xfff,r3 + loadw [r12]0x1234,r4 + loadw [r13]0x1234,r4 + loadw [r12]0x1234,r5 + loadw [r13]0x1234,r5 + loadw [r12]0x4567,r2 + loadw [r13]0xA1234,r2 + ################################### + # loadw rbase(disp20/-disp20) reg + ################################### + loadw 0x4(r1,r0),r1 + loadw 0x4(r3,r2),r3 + loadw 0x1234(r1,r0),r4 + loadw 0x1234(r3,r2),r5 + loadw 0xA1234(r1,r0),r6 + loadw -0x4(r1,r0),r1 + loadw -0x4(r3,r2),r3 + loadw -0x1234(r1,r0),r4 + loadw -0x1234(r3,r2),r5 + loadw -0xA1234(r1,r0),r6 + ################################################# + # loadw rpbase(disp4/disp16/disp20/-disp20) reg + ################################################# + loadw 0x0(r1,r0),r0 + loadw 0x0(r1,r0),r1 + loadw 0xf(r1,r0),r0 + loadw 0xf(r1,r0),r1 + loadw 0x1234(r1,r0),r2 + loadw 0xabcd(r3,r2),r3 + loadw 0xAfff(r4,r3),r4 + loadw 0xA1234(r6,r5),r5 + loadw -0xf(r1,r0),r0 + loadw -0xf(r1,r0),r1 + loadw -0x1234(r1,r0),r2 + loadw -0xabcd(r3,r2),r3 + loadw -0xAfff(r4,r3),r4 + loadw -0xA1234(r6,r5),r5 + #################################### + # loadw rbase(disp0/disp14) rel reg + #################################### + loadw [r12]0x0(r1,r0),r0 + loadw [r13]0x0(r1,r0),r1 + loadw [r12]0x1234(r1,r0),r2 + loadw [r13]0x1abcd(r1,r0),r3 + ################################# + # loadw rpbase(disp20) rel reg + ################################# + loadw [r12]0xA1234(r1,r0),r4 + loadw [r13]0xB1234(r1,r0),r5 + loadw [r13]0xfffff(r1,r0),r6 diff --git a/binutils-2.19/gas/testsuite/gas/cr16/lpsp_test.s b/binutils-2.19/gas/testsuite/gas/cr16/lpsp_test.s index 8e9d459..7f487da 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/lpsp_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/lpsp_test.s @@ -1,63 +1,63 @@ - .text
- .global main
-main:
- ################
- # lpr reg, preg
- ################
- lpr r1,psr
- lpr r2,cfg
- lpr r2,intbasel
- lpr r3,intbaseh
- lpr r4,ispl
- lpr r5,isph
- lpr r6,uspl
- lpr r7,usph
- lpr r8,dsr
- lpr r9,dcrl
- lpr r10,dcrh
- lpr r11,car0l
- lpr r0,car0h
- lpr r1,car1l
- lpr r3,car1h
- #################
- # lprd regp, preg
- #################
- lprd (r1,r0),psr
- lprd (r2,r1),cfg
- lprd (r3,r2),intbase
- lprd (r4,r3),isp
- lprd (r5,r4),usp
- lprd (r6,r5),dsr
- lprd (r7,r6),dcr
- lprd (r8,r7),car0
- lprd (r9,r8),car1
- #################
- # spr preg, reg
- #################
- spr psr,r0
- spr cfg,r1
- spr intbasel,r2
- spr intbaseh,r3
- spr ispl,r4
- spr isph,r5
- spr uspl,r6
- spr usph,r7
- spr dsr,r8
- spr dcrl,r9
- spr dcrh,r10
- spr car0l,r11
- spr car0h,r0
- spr car1l,r1
- spr car1h,r2
- #################
- # sprd preg, regp
- #################
- sprd psr,(r1,r0)
- sprd cfg,(r2,r1)
- sprd intbase,(r3,r2)
- sprd isp,(r4,r3)
- sprd usp,(r5,r4)
- sprd dsr,(r6,r5)
- sprd dcr,(r7,r6)
- sprd car0,(r8,r7)
- sprd car1,(r9,r8)
+ .text + .global main +main: + ################ + # lpr reg, preg + ################ + lpr r1,psr + lpr r2,cfg + lpr r2,intbasel + lpr r3,intbaseh + lpr r4,ispl + lpr r5,isph + lpr r6,uspl + lpr r7,usph + lpr r8,dsr + lpr r9,dcrl + lpr r10,dcrh + lpr r11,car0l + lpr r0,car0h + lpr r1,car1l + lpr r3,car1h + ################# + # lprd regp, preg + ################# + lprd (r1,r0),psr + lprd (r2,r1),cfg + lprd (r3,r2),intbase + lprd (r4,r3),isp + lprd (r5,r4),usp + lprd (r6,r5),dsr + lprd (r7,r6),dcr + lprd (r8,r7),car0 + lprd (r9,r8),car1 + ################# + # spr preg, reg + ################# + spr psr,r0 + spr cfg,r1 + spr intbasel,r2 + spr intbaseh,r3 + spr ispl,r4 + spr isph,r5 + spr uspl,r6 + spr usph,r7 + spr dsr,r8 + spr dcrl,r9 + spr dcrh,r10 + spr car0l,r11 + spr car0h,r0 + spr car1l,r1 + spr car1h,r2 + ################# + # sprd preg, regp + ################# + sprd psr,(r1,r0) + sprd cfg,(r2,r1) + sprd intbase,(r3,r2) + sprd isp,(r4,r3) + sprd usp,(r5,r4) + sprd dsr,(r6,r5) + sprd dcr,(r7,r6) + sprd car0,(r8,r7) + sprd car1,(r9,r8) diff --git a/binutils-2.19/gas/testsuite/gas/cr16/storb_test.s b/binutils-2.19/gas/testsuite/gas/cr16/storb_test.s index 2cd2706..63d8047 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/storb_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/storb_test.s @@ -1,143 +1,143 @@ - .text
- .global main
-main:
- ######################
- # storb reg abs20/24
- ######################
- storb r0,0x0
- storb r1,0xff
- storb r3,0xfff
- storb r4,0x1234
- storb r5,0x1234
- storb r0,0x7A1234
- storb r1,0xBA1234
- storb r2,0xffffff
- ######################
- # storb abs20 rel reg
- ######################
- storb r0,[r12]0x0
- storb r0,[r13]0x0
- storb r1,[r12]0xff
- storb r1,[r13]0xff
- storb r3,[r12]0xfff
- storb r3,[r13]0xfff
- storb r4,[r12]0x1234
- storb r4,[r13]0x1234
- storb r5,[r12]0x1234
- storb r5,[r13]0x1234
- storb r2,[r12]0x4567
- storb r2,[r13]0xA1234
- ###################################
- # storb reg rbase(disp20/-disp20)
- ###################################
- storb r1,0x4(r1,r0)
- storb r3,0x4(r3,r2)
- storb r4,0x1234(r1,r0)
- storb r5,0x1234(r3,r2)
- storb r6,0xA1234(r1,r0)
- storb r1,-0x4(r1,r0)
- storb r3,-0x4(r3,r2)
- storb r4,-0x1234(r1,r0)
- storb r5,-0x1234(r3,r2)
- storb r6,-0xA1234(r1,r0)
- #################################################
- # storb reg rpbase(disp4/disp16/disp20/-disp20)
- #################################################
- storb r0,0x0(r1,r0)
- storb r0,0x0(r1,r0)
- storb r0,0xf(r1,r0)
- storb r1,0xf(r1,r0)
- storb r2,0x1234(r1,r0)
- storb r3,0xabcd(r3,r2)
- storb r4,0xAfff(r4,r3)
- storb r5,0xA1234(r6,r5)
- storb r0,-0xf(r1,r0)
- storb r1,-0xf(r1,r0)
- storb r2,-0x1234(r1,r0)
- storb r3,-0xabcd(r3,r2)
- storb r4,-0xAfff(r4,r3)
- storb r5,-0xA1234(r6,r5)
- ####################################
- # storb rbase(disp0/disp14) rel reg
- ####################################
- storb r0,[r12]0x0(r1,r0)
- storb r1,[r13]0x0(r1,r0)
- storb r2,[r12]0x1234(r1,r0)
- storb r3,[r13]0x1abcd(r1,r0)
- #################################
- # storb reg rpbase(disp20) rel
- #################################
- storb r4,[r12]0xA1234(r1,r0)
- storb r5,[r13]0xB1234(r1,r0)
- storb r6,[r13]0xfffff(r1,r0)
- #######################
- # storb reg, uimm16/20
- ######################
- storb $4,0xbcd
- storb $5,0xaabcd
- storb $3,0xfaabcd
-
- #######################
- # storb reg, uimm16/20
- ######################
- storb $5,[r12]0x14
- storb $4,[r13]0xabfc
- storb $3,[r12]0x1234
- storb $3,[r13]0x1234
- storb $3,[r12]0x34
- #######################
- # storb imm, index-rbase
- ######################
- storb $3,[r12]0xa7a(r1,r0)
- storb $3,[r12]0xa7a(r3,r2)
- storb $3,[r12]0xa7a(r4,r3)
- storb $3,[r12]0xa7a(r5,r4)
- storb $3,[r12]0xa7a(r6,r5)
- storb $3,[r12]0xa7a(r7,r6)
- storb $3,[r12]0xa7a(r9,r8)
- storb $3,[r12]0xa7a(r11,r10)
- storb $3,[r13]0xa7a(r1,r0)
- storb $3,[r13]0xa7a(r3,r2)
- storb $3,[r13]0xa7a(r4,r3)
- storb $3,[r13]0xa7a(r5,r4)
- storb $3,[r13]0xa7a(r6,r5)
- storb $3,[r13]0xa7a(r7,r6)
- storb $3,[r13]0xa7a(r9,r8)
- storb $3,[r13]0xa7a(r11,r10)
- storb $5,[r13]0xb7a(r4,r3)
- storb $1,[r12]0x17a(r6,r5)
- storb $1,[r13]0x134(r6,r5)
- storb $3,[r12]0xabcde(r4,r3)
- storb $5,[r13]0xabcd(r4,r3)
- storb $3,[r12]0xabcd(r6,r5)
- storb $3,[r13]0xbcde(r6,r5)
- #######################
- # storb imm4, rbase(disp)
- ######################
- storb $5,0x0(r2)
- storb $3,0x34(r12)
- storb $3,0xab(r13)
- storb $5,0xad(r1)
- storb $5,0xcd(r2)
- storb $5,0xfff(r0)
- storb $3,0xbcd(r4)
- storb $3,0xfff(r12)
- storb $3,0xfff(r13)
- storb $3,0xffff(r13)
- storb $3,0x2343(r12)
- storb $3,0x12345(r2)
- storb $3,0x4abcd(r8)
- storb $3,0xfabcd(r13)
- storb $3,0xfabcd(r8)
- storb $3,0xfabcd(r9)
- storb $3,0x4abcd(r9)
- ##########################
- # storb imm, disp20(rpbase)
- #########################
- storb $3,0x0(r2,r1)
- storb $5,0x1(r2,r1)
- storb $4,0x1234(r2,r1)
- storb $3,0x1234(r2,r1)
- storb $3,0x12345(r2,r1)
- storb $3,0x123(r2,r1)
- storb $3,0x12345(r2,r1)
+ .text + .global main +main: + ###################### + # storb reg abs20/24 + ###################### + storb r0,0x0 + storb r1,0xff + storb r3,0xfff + storb r4,0x1234 + storb r5,0x1234 + storb r0,0x7A1234 + storb r1,0xBA1234 + storb r2,0xffffff + ###################### + # storb abs20 rel reg + ###################### + storb r0,[r12]0x0 + storb r0,[r13]0x0 + storb r1,[r12]0xff + storb r1,[r13]0xff + storb r3,[r12]0xfff + storb r3,[r13]0xfff + storb r4,[r12]0x1234 + storb r4,[r13]0x1234 + storb r5,[r12]0x1234 + storb r5,[r13]0x1234 + storb r2,[r12]0x4567 + storb r2,[r13]0xA1234 + ################################### + # storb reg rbase(disp20/-disp20) + ################################### + storb r1,0x4(r1,r0) + storb r3,0x4(r3,r2) + storb r4,0x1234(r1,r0) + storb r5,0x1234(r3,r2) + storb r6,0xA1234(r1,r0) + storb r1,-0x4(r1,r0) + storb r3,-0x4(r3,r2) + storb r4,-0x1234(r1,r0) + storb r5,-0x1234(r3,r2) + storb r6,-0xA1234(r1,r0) + ################################################# + # storb reg rpbase(disp4/disp16/disp20/-disp20) + ################################################# + storb r0,0x0(r1,r0) + storb r0,0x0(r1,r0) + storb r0,0xf(r1,r0) + storb r1,0xf(r1,r0) + storb r2,0x1234(r1,r0) + storb r3,0xabcd(r3,r2) + storb r4,0xAfff(r4,r3) + storb r5,0xA1234(r6,r5) + storb r0,-0xf(r1,r0) + storb r1,-0xf(r1,r0) + storb r2,-0x1234(r1,r0) + storb r3,-0xabcd(r3,r2) + storb r4,-0xAfff(r4,r3) + storb r5,-0xA1234(r6,r5) + #################################### + # storb rbase(disp0/disp14) rel reg + #################################### + storb r0,[r12]0x0(r1,r0) + storb r1,[r13]0x0(r1,r0) + storb r2,[r12]0x1234(r1,r0) + storb r3,[r13]0x1abcd(r1,r0) + ################################# + # storb reg rpbase(disp20) rel + ################################# + storb r4,[r12]0xA1234(r1,r0) + storb r5,[r13]0xB1234(r1,r0) + storb r6,[r13]0xfffff(r1,r0) + ####################### + # storb reg, uimm16/20 + ###################### + storb $4,0xbcd + storb $5,0xaabcd + storb $3,0xfaabcd + + ####################### + # storb reg, uimm16/20 + ###################### + storb $5,[r12]0x14 + storb $4,[r13]0xabfc + storb $3,[r12]0x1234 + storb $3,[r13]0x1234 + storb $3,[r12]0x34 + ####################### + # storb imm, index-rbase + ###################### + storb $3,[r12]0xa7a(r1,r0) + storb $3,[r12]0xa7a(r3,r2) + storb $3,[r12]0xa7a(r4,r3) + storb $3,[r12]0xa7a(r5,r4) + storb $3,[r12]0xa7a(r6,r5) + storb $3,[r12]0xa7a(r7,r6) + storb $3,[r12]0xa7a(r9,r8) + storb $3,[r12]0xa7a(r11,r10) + storb $3,[r13]0xa7a(r1,r0) + storb $3,[r13]0xa7a(r3,r2) + storb $3,[r13]0xa7a(r4,r3) + storb $3,[r13]0xa7a(r5,r4) + storb $3,[r13]0xa7a(r6,r5) + storb $3,[r13]0xa7a(r7,r6) + storb $3,[r13]0xa7a(r9,r8) + storb $3,[r13]0xa7a(r11,r10) + storb $5,[r13]0xb7a(r4,r3) + storb $1,[r12]0x17a(r6,r5) + storb $1,[r13]0x134(r6,r5) + storb $3,[r12]0xabcde(r4,r3) + storb $5,[r13]0xabcd(r4,r3) + storb $3,[r12]0xabcd(r6,r5) + storb $3,[r13]0xbcde(r6,r5) + ####################### + # storb imm4, rbase(disp) + ###################### + storb $5,0x0(r2) + storb $3,0x34(r12) + storb $3,0xab(r13) + storb $5,0xad(r1) + storb $5,0xcd(r2) + storb $5,0xfff(r0) + storb $3,0xbcd(r4) + storb $3,0xfff(r12) + storb $3,0xfff(r13) + storb $3,0xffff(r13) + storb $3,0x2343(r12) + storb $3,0x12345(r2) + storb $3,0x4abcd(r8) + storb $3,0xfabcd(r13) + storb $3,0xfabcd(r8) + storb $3,0xfabcd(r9) + storb $3,0x4abcd(r9) + ########################## + # storb imm, disp20(rpbase) + ######################### + storb $3,0x0(r2,r1) + storb $5,0x1(r2,r1) + storb $4,0x1234(r2,r1) + storb $3,0x1234(r2,r1) + storb $3,0x12345(r2,r1) + storb $3,0x123(r2,r1) + storb $3,0x12345(r2,r1) diff --git a/binutils-2.19/gas/testsuite/gas/cr16/stord_test.s b/binutils-2.19/gas/testsuite/gas/cr16/stord_test.s index dcac741..68b1f07 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/stord_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/stord_test.s @@ -1,72 +1,72 @@ - .text
- .global main
-main:
- ######################
- # stord abs20/24 regp
- ######################
- stord (r1,r0),0x0
- stord (r1,r0),0xff
- stord (r3,r2),0xfff
- stord (r4,r3),0x1234
- stord (r5,r4),0x1234
- stord (r1,r0),0x7A1234
- stord (r1,r0),0xBA1234
- stord (r2,r1),0xffffff
- ######################
- # stord abs20 rel regp
- ######################
- stord (r1,r0),[r12]0x0
- stord (r1,r0),[r13]0x0
- stord (r1,r0),[r12]0xff
- stord (r1,r0),[r13]0xff
- stord (r3,r2),[r12]0xfff
- stord (r3,r2),[r13]0xfff
- stord (r4,r3),[r12]0x1234
- stord (r4,r3),[r13]0x1234
- stord (r5,r4),[r12]0x1234
- stord (r5,r4),[r13]0x1234
- stord (r2,r1),[r12]0x4567
- stord (r2,r1),[r13]0xA1234
- ###################################
- # stord regp rbase(disp20/-disp20)
- ###################################
- stord (r2,r1),0x4(r1,r0)
- stord (r3,r2),0x4(r3,r2)
- stord (r4,r3),0x1234(r1,r0)
- stord (r5,r4),0x1234(r3,r2)
- stord (r6,r5),0xA1234(r1,r0)
- stord (r2,r1),-0x4(r1,r0)
- stord (r3,r2),-0x4(r3,r2)
- stord (r4,r3),-0x1234(r1,r0)
- stord (r5,r4),-0x1234(r3,r2)
- stord (r6,r5),-0xA1234(r1,r0)
- #################################################
- # stord regp rpbase(disp4/disp16/disp20/-disp20)
- #################################################
- stord (r1,r0),0x0(r1,r0)
- stord (r1,r0),0x0(r1,r0)
- stord (r1,r0),0xf(r1,r0)
- stord (r1,r0),0xf(r1,r0)
- stord (r2,r1),0x1234(r1,r0)
- stord (r3,r2),0xabcd(r3,r2)
- stord (r4,r3),0xAfff(r4,r3)
- stord (r7,r6),0xA1234(r6,r5)
- stord (r1,r0),-0xf(r1,r0)
- stord (r1,r0),-0xf(r1,r0)
- stord (r2,r1),-0x1234(r1,r0)
- stord (r3,r2),-0xabcd(r3,r2)
- stord (r5,r4),-0xAfff(r4,r3)
- stord (r5,r4),-0xA1234(r6,r5)
- ####################################
- # stord rbase(disp0/disp14) rel reg
- ####################################
- stord (r1,r0),[r12]0x0(r1,r0)
- stord (r1,r0),[r13]0x0(r1,r0)
- stord (r2,r1),[r12]0x1234(r1,r0)
- stord (r3,r2),[r13]0x1abcd(r1,r0)
- #################################
- # stord rpbase(disp20) rel reg
- #################################
- stord (r3,r2),[r12]0xA1234(r1,r0)
- stord (r4,r3),[r13]0xB1234(r1,r0)
- stord (r5,r4),[r13]0xfffff(r1,r0)
+ .text + .global main +main: + ###################### + # stord abs20/24 regp + ###################### + stord (r1,r0),0x0 + stord (r1,r0),0xff + stord (r3,r2),0xfff + stord (r4,r3),0x1234 + stord (r5,r4),0x1234 + stord (r1,r0),0x7A1234 + stord (r1,r0),0xBA1234 + stord (r2,r1),0xffffff + ###################### + # stord abs20 rel regp + ###################### + stord (r1,r0),[r12]0x0 + stord (r1,r0),[r13]0x0 + stord (r1,r0),[r12]0xff + stord (r1,r0),[r13]0xff + stord (r3,r2),[r12]0xfff + stord (r3,r2),[r13]0xfff + stord (r4,r3),[r12]0x1234 + stord (r4,r3),[r13]0x1234 + stord (r5,r4),[r12]0x1234 + stord (r5,r4),[r13]0x1234 + stord (r2,r1),[r12]0x4567 + stord (r2,r1),[r13]0xA1234 + ################################### + # stord regp rbase(disp20/-disp20) + ################################### + stord (r2,r1),0x4(r1,r0) + stord (r3,r2),0x4(r3,r2) + stord (r4,r3),0x1234(r1,r0) + stord (r5,r4),0x1234(r3,r2) + stord (r6,r5),0xA1234(r1,r0) + stord (r2,r1),-0x4(r1,r0) + stord (r3,r2),-0x4(r3,r2) + stord (r4,r3),-0x1234(r1,r0) + stord (r5,r4),-0x1234(r3,r2) + stord (r6,r5),-0xA1234(r1,r0) + ################################################# + # stord regp rpbase(disp4/disp16/disp20/-disp20) + ################################################# + stord (r1,r0),0x0(r1,r0) + stord (r1,r0),0x0(r1,r0) + stord (r1,r0),0xf(r1,r0) + stord (r1,r0),0xf(r1,r0) + stord (r2,r1),0x1234(r1,r0) + stord (r3,r2),0xabcd(r3,r2) + stord (r4,r3),0xAfff(r4,r3) + stord (r7,r6),0xA1234(r6,r5) + stord (r1,r0),-0xf(r1,r0) + stord (r1,r0),-0xf(r1,r0) + stord (r2,r1),-0x1234(r1,r0) + stord (r3,r2),-0xabcd(r3,r2) + stord (r5,r4),-0xAfff(r4,r3) + stord (r5,r4),-0xA1234(r6,r5) + #################################### + # stord rbase(disp0/disp14) rel reg + #################################### + stord (r1,r0),[r12]0x0(r1,r0) + stord (r1,r0),[r13]0x0(r1,r0) + stord (r2,r1),[r12]0x1234(r1,r0) + stord (r3,r2),[r13]0x1abcd(r1,r0) + ################################# + # stord rpbase(disp20) rel reg + ################################# + stord (r3,r2),[r12]0xA1234(r1,r0) + stord (r4,r3),[r13]0xB1234(r1,r0) + stord (r5,r4),[r13]0xfffff(r1,r0) diff --git a/binutils-2.19/gas/testsuite/gas/cr16/storw_test.s b/binutils-2.19/gas/testsuite/gas/cr16/storw_test.s index 6adee5c..e27b198 100644 --- a/binutils-2.19/gas/testsuite/gas/cr16/storw_test.s +++ b/binutils-2.19/gas/testsuite/gas/cr16/storw_test.s @@ -1,144 +1,144 @@ - .text
- .global main
-main:
- ######################
- # storw reg abs20/24
- ######################
- storw r0,0x0
- storw r1,0xff
- storw r3,0xfff
- storw r4,0x1234
- storw r5,0x1234
- storw r0,0x7A1234
- storw r1,0xBA1234
- storw r2,0xffffff
- ######################
- # storw abs20 rel reg
- ######################
- storw r0,[r12]0x0
- storw r0,[r13]0x0
- storw r1,[r12]0xff
- storw r1,[r13]0xff
- storw r3,[r12]0xfff
- storw r3,[r13]0xfff
- storw r4,[r12]0x1234
- storw r4,[r13]0x1234
- storw r5,[r12]0x1234
- storw r5,[r13]0x1234
- storw r2,[r12]0x4567
- storw r2,[r13]0xA1234
- ###################################
- # storw reg rbase(disp20/-disp20)
- ###################################
- storw r1,0x4(r1,r0)
- storw r3,0x4(r3,r2)
- storw r4,0x1234(r1,r0)
- storw r5,0x1234(r3,r2)
- storw r6,0xA1234(r1,r0)
- storw r1,-0x4(r1,r0)
- storw r3,-0x4(r3,r2)
- storw r4,-0x1234(r1,r0)
- storw r5,-0x1234(r3,r2)
- storw r6,-0xA1234(r1,r0)
- #################################################
- # storw reg rpbase(disp4/disp16/disp20/-disp20)
- #################################################
- storw r0,0x0(r1,r0)
- storw r0,0x0(r1,r0)
- storw r0,0xf(r1,r0)
- storw r1,0xf(r1,r0)
- storw r2,0x1234(r1,r0)
- storw r3,0xabcd(r3,r2)
- storw r4,0xAfff(r4,r3)
- storw r5,0xA1234(r6,r5)
- storw r0,-0xf(r1,r0)
- storw r1,-0xf(r1,r0)
- storw r2,-0x1234(r1,r0)
- storw r3,-0xabcd(r3,r2)
- storw r4,-0xAfff(r4,r3)
- storw r5,-0xA1234(r6,r5)
- ####################################
- # storw rbase(disp0/disp14) rel reg
- ####################################
- storw r0,[r12]0x0(r1,r0)
- storw r1,[r13]0x0(r1,r0)
- storw r2,[r12]0x1234(r1,r0)
- storw r3,[r13]0x1abcd(r1,r0)
- #################################
- # storw reg rpbase(disp20) rel
- #################################
- storw r4,[r12]0xA1234(r1,r0)
- storw r5,[r13]0xB1234(r1,r0)
- storw r6,[r13]0xfffff(r1,r0)
- #######################
- # storw reg, uimm16/20
- ######################
- storw $4,0xbcd
- storw $5,0xaabcd
- storw $3,0xfaabcd
-
- #######################
- # storw reg, uimm16/20
- ######################
- storw $5,[r12]0x14
- storw $4,[r13]0xabfc
- storw $3,[r12]0x1234
- storw $3,[r13]0x1234
- storw $3,[r12]0x34
- #######################
- # storw imm, index-rbase
- ######################
- storw $3,[r12]0xa7a(r1,r0)
- storw $3,[r12]0xa7a(r3,r2)
- storw $3,[r12]0xa7a(r4,r3)
- storw $3,[r12]0xa7a(r5,r4)
- storw $3,[r12]0xa7a(r6,r5)
- storw $3,[r12]0xa7a(r7,r6)
- storw $3,[r12]0xa7a(r9,r8)
- storw $3,[r12]0xa7a(r11,r10)
- storw $3,[r13]0xa7a(r1,r0)
- storw $3,[r13]0xa7a(r3,r2)
- storw $3,[r13]0xa7a(r4,r3)
- storw $3,[r13]0xa7a(r5,r4)
- storw $3,[r13]0xa7a(r6,r5)
- storw $3,[r13]0xa7a(r7,r6)
- storw $3,[r13]0xa7a(r9,r8)
- storw $3,[r13]0xa7a(r11,r10)
- storw $5,[r13]0xb7a(r4,r3)
- storw $1,[r12]0x17a(r6,r5)
- storw $1,[r13]0x134(r6,r5)
- storw $3,[r12]0xabcde(r4,r3)
- storw $5,[r13]0xabcd(r4,r3)
- storw $3,[r12]0xabcd(r6,r5)
- storw $3,[r13]0xbcde(r6,r5)
- #######################
- # storw imm4, rbase(disp)
- ######################
- storw $5,0x0(r2)
- storw $3,0x34(r12)
- storw $3,0xab(r13)
- storw $5,0xad(r1)
- storw $5,0xcd(r2)
- storw $5,0xfff(r0)
- storw $3,0xbcd(r4)
- storw $3,0xfff(r12)
- storw $3,0xfff(r13)
- storw $3,0xffff(r13)
- storw $3,0x2343(r12)
- storw $3,0x12345(r2)
- storw $3,0x4abcd(r8)
- storw $3,0xfabcd(r13)
- storw $3,0xfabcd(r8)
- storw $3,0xfabcd(r9)
- storw $3,0x4abcd(r9)
- ##########################
- # storw imm, disp20(rpbase)
- #########################
- storw $3,0x0(r2,r1)
- storw $5,0x1(r2,r1)
- storw $4,0x1234(r2,r1)
- storw $3,0x1234(r2,r1)
- storw $3,0x12345(r2,r1)
- storw $3,0x123(r2,r1)
- storw $3,0x12345(r2,r1)
-
+ .text + .global main +main: + ###################### + # storw reg abs20/24 + ###################### + storw r0,0x0 + storw r1,0xff + storw r3,0xfff + storw r4,0x1234 + storw r5,0x1234 + storw r0,0x7A1234 + storw r1,0xBA1234 + storw r2,0xffffff + ###################### + # storw abs20 rel reg + ###################### + storw r0,[r12]0x0 + storw r0,[r13]0x0 + storw r1,[r12]0xff + storw r1,[r13]0xff + storw r3,[r12]0xfff + storw r3,[r13]0xfff + storw r4,[r12]0x1234 + storw r4,[r13]0x1234 + storw r5,[r12]0x1234 + storw r5,[r13]0x1234 + storw r2,[r12]0x4567 + storw r2,[r13]0xA1234 + ################################### + # storw reg rbase(disp20/-disp20) + ################################### + storw r1,0x4(r1,r0) + storw r3,0x4(r3,r2) + storw r4,0x1234(r1,r0) + storw r5,0x1234(r3,r2) + storw r6,0xA1234(r1,r0) + storw r1,-0x4(r1,r0) + storw r3,-0x4(r3,r2) + storw r4,-0x1234(r1,r0) + storw r5,-0x1234(r3,r2) + storw r6,-0xA1234(r1,r0) + ################################################# + # storw reg rpbase(disp4/disp16/disp20/-disp20) + ################################################# + storw r0,0x0(r1,r0) + storw r0,0x0(r1,r0) + storw r0,0xf(r1,r0) + storw r1,0xf(r1,r0) + storw r2,0x1234(r1,r0) + storw r3,0xabcd(r3,r2) + storw r4,0xAfff(r4,r3) + storw r5,0xA1234(r6,r5) + storw r0,-0xf(r1,r0) + storw r1,-0xf(r1,r0) + storw r2,-0x1234(r1,r0) + storw r3,-0xabcd(r3,r2) + storw r4,-0xAfff(r4,r3) + storw r5,-0xA1234(r6,r5) + #################################### + # storw rbase(disp0/disp14) rel reg + #################################### + storw r0,[r12]0x0(r1,r0) + storw r1,[r13]0x0(r1,r0) + storw r2,[r12]0x1234(r1,r0) + storw r3,[r13]0x1abcd(r1,r0) + ################################# + # storw reg rpbase(disp20) rel + ################################# + storw r4,[r12]0xA1234(r1,r0) + storw r5,[r13]0xB1234(r1,r0) + storw r6,[r13]0xfffff(r1,r0) + ####################### + # storw reg, uimm16/20 + ###################### + storw $4,0xbcd + storw $5,0xaabcd + storw $3,0xfaabcd + + ####################### + # storw reg, uimm16/20 + ###################### + storw $5,[r12]0x14 + storw $4,[r13]0xabfc + storw $3,[r12]0x1234 + storw $3,[r13]0x1234 + storw $3,[r12]0x34 + ####################### + # storw imm, index-rbase + ###################### + storw $3,[r12]0xa7a(r1,r0) + storw $3,[r12]0xa7a(r3,r2) + storw $3,[r12]0xa7a(r4,r3) + storw $3,[r12]0xa7a(r5,r4) + storw $3,[r12]0xa7a(r6,r5) + storw $3,[r12]0xa7a(r7,r6) + storw $3,[r12]0xa7a(r9,r8) + storw $3,[r12]0xa7a(r11,r10) + storw $3,[r13]0xa7a(r1,r0) + storw $3,[r13]0xa7a(r3,r2) + storw $3,[r13]0xa7a(r4,r3) + storw $3,[r13]0xa7a(r5,r4) + storw $3,[r13]0xa7a(r6,r5) + storw $3,[r13]0xa7a(r7,r6) + storw $3,[r13]0xa7a(r9,r8) + storw $3,[r13]0xa7a(r11,r10) + storw $5,[r13]0xb7a(r4,r3) + storw $1,[r12]0x17a(r6,r5) + storw $1,[r13]0x134(r6,r5) + storw $3,[r12]0xabcde(r4,r3) + storw $5,[r13]0xabcd(r4,r3) + storw $3,[r12]0xabcd(r6,r5) + storw $3,[r13]0xbcde(r6,r5) + ####################### + # storw imm4, rbase(disp) + ###################### + storw $5,0x0(r2) + storw $3,0x34(r12) + storw $3,0xab(r13) + storw $5,0xad(r1) + storw $5,0xcd(r2) + storw $5,0xfff(r0) + storw $3,0xbcd(r4) + storw $3,0xfff(r12) + storw $3,0xfff(r13) + storw $3,0xffff(r13) + storw $3,0x2343(r12) + storw $3,0x12345(r2) + storw $3,0x4abcd(r8) + storw $3,0xfabcd(r13) + storw $3,0xfabcd(r8) + storw $3,0xfabcd(r9) + storw $3,0x4abcd(r9) + ########################## + # storw imm, disp20(rpbase) + ######################### + storw $3,0x0(r2,r1) + storw $5,0x1(r2,r1) + storw $4,0x1234(r2,r1) + storw $3,0x1234(r2,r1) + storw $3,0x12345(r2,r1) + storw $3,0x123(r2,r1) + storw $3,0x12345(r2,r1) + diff --git a/binutils-2.19/gold/ChangeLog b/binutils-2.19/gold/ChangeLog index 886f9b4..514310d 100644 --- a/binutils-2.19/gold/ChangeLog +++ b/binutils-2.19/gold/ChangeLog @@ -1,6 +1,5128 @@ -2008-09-09 Alan Modra <amodra@bigpond.net.au> +2010-03-01 Doug Kwan <dougkwan@google.com> + + * layout.cc (Layout::Layout): Force section types of .init_array*, + .preinit_array* and .fini_array* sections. + * output.cc (Output_section::Input_section_sort_entry::has_priority): + Fix check of return value of std::string::find.(). + (Output_section::Input_section_sort_compare::operator()): Remove + comment about .init_array. + (Output_section::Input_section_sort_init_fini_compare::operator()): + New method. + (Output_section::sort_attached_input_sections): Handle .init_array + and .fini_array specially. + * output.h (Output_section::Inut_section_sort_compare): Update + comment. + (Output_section::Input_section_sort_init_fini_compare): New struct. + +2010-02-26 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Relocate::reloc_is_non_pic): Treat + R_ARM_PREL31 and R_ARM_SBREL31 as position independent. + * testsuite/debug_msg.sh: Avoid matching source line number for + use of global variable undef_int. + +2010-02-26 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::scan_reloc_for_stub): Move code handling + R_ARM_V4BX to Target_arm::scan_reloc_section_for_stubs. + (Target_arm::scan_reloc_section_for_stubs): Instead of calling + scan_reloc_for_stub, do all processing of R_ARM_V4BX here. + * options.cc (General_options::General_options): Initialize member + fix_v4bx_. + * testsuite/Makefile.am (check_SCRIPTS): Add arm_fix_v4bx.sh + (check_DATA): Add arm_fix_v4bx.stdout, arm_fix_v4bx_interworking.stdout + and rm_no_fix_v4bx.stdout + (arm_fix_v4bx.stdout, arm_fix_v4bx, arm_fix_v4bx.o, + arm_fix_v4bx_interworking.stdout, arm_fix_v4bx_interworking, + arm_no_fix_v4bx.stdout, arm_no_fix_v4bx): New make rules. + (MOSTLYCLEANFILES): Add arm_fix_v4bx, arm_fix_v4bx_interworking + and arm_no_fix_v4bx. + * Makefile.in: Regenerate. + * testsuite/arm_fix_v4bx.s: New file. + * testsuite/arm_fix_v4bx.sh: Ditto. + +2010-02-24 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::got_section): Make the .got section the first + non RELRO section in the data segment. + * testsuite/script_test_5.sh: Fix match patterns to avoid matching + suffixes of section names. + +2010-02-24 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::do_finalize_sections): Skip processor specific + flags and attributes merging if an input file is a binary file. + * fileread.cc (Input_file::open): Record format of original file. + * fileread.h (Input_file::Format): New enum type. + (Input_file::Input_file): Initialize data member format_. + (Input_file::format): New method definition. + (Input_file::format_):: New data member. + +2010-02-24 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_output_data_got): New class. + (ARM_TCB_SIZE): New constant + (Target_arm): Use Arm_output_data_got instead of Output_data_got. + (Arm_output_section::fix_exidx_coverage): Add a parameter for layout. + If user uses a script with a SECTIONS clause, issue only a warning + for a misplaced EXIDX input section. Otherwise, issue an error. + (Arm_relobj::do_gc_process_relocs): Exit early if we are not doing + garbage collection. + (Target_arm::got_mode_index_entry): Handle static linking. + (Target_arm::Scan::local): Ditto. + (Target_arm::Scan::global): Ditto. + (Target_arm::Relocate::relocate_tls): Handle static linking. Fix + all incorrectly implemented relocations. + (Target_arm::fix_exidx_coverage): Pass layout to + Arm_output_section::fix_exidx_coverage. + * layout.cc (Layout::section_name_mapping): Remove trailing dots + from ".ARM.exidx." and ".ARM.extab.". + +2010-02-23 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Target_arm::do_finalize_sections): Create attribute + section if it does not already exist. + * attributes.cc (Attributes_section_data::Attributes_section_data): + Don't crash if size is zero. + +2010-02-23 Viktor Kutuzov <vkutuzov@accesssoftek.com> + Ian Lance Taylor <iant@google.com> + + * gold.cc (queue_middle_tasks): If no input files were opened, + exit. + * workqueue.h (Task_function::Task_function): Assert that there is + a blocker. + +2010-02-22 Doug Kwan <dougkwan@google.com> + + * gold-threads.h (Once::~Once): Explicitly define virtual destructor. + * icf.cc (get_section_contents): Cast snprintf arguments to long long + types to avoid warnings due to different uint64_t implementations + on different hosts. + +2010-02-21 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relocate_functions::arm_branch_common): Fix bug in + handling of the maximum backward branch offset. + (Arm_relocate_functions::thumb_branch_common): Ditto. + * testsuite/Makefile.am (check_SCRIPTS): Add arm_branch_in_range.sh. + (check_DATA): Add arm_bl_in_range.stdout, arm_bl_out_of_range.stdout + thumb_bl_in_range.stdout, thumb_bl_out_of_range.stdout, + thumb2_bl_in_range.stdout and thumb2_bl_out_of_range.stdout. + (arm_bl_in_range.stdout, arm_bl_in_range, arm_bl_in_range.o, + arm_bl_out_of_range.stdout, arm_bl_out_of_range, + arm_bl_out_of_range.o, thumb_bl_in_range.stdout, thumb_bl_in_range, + thumb_bl_in_range.o, thumb_bl_out_of_range.stdout, + thumb_bl_out_of_range thumb_bl_out_of_range.o, + thumb2_bl_in_range.stdout, thumb2_bl_in_range, thumb2_bl_in_range.o + thumb2_bl_out_of_range.stdout, thumb2_bl_out_of_range, + thumb2_bl_out_of_range.o): New rules. + (MOSTLYCLEANFILES): Add arm_bl_in_range, arm_bl_out_of_range, + thumb_bl_in_range, thumb_bl_out_of_range, thumb2_bl_in_range and + thumb2_bl_out_of_range + * testsuite/Makefile.in: Regenerate. + * testsuite/arm_bl_in_range.s: New file. + * testsuite/arm_bl_out_of_range.s: Ditto. + * testsuite/arm_branch_in_range.sh: Ditto. + * testsuite/arm_branch_range.t: Ditto. + * testsuite/thumb2_branch_range.t: Ditto. + * testsuite/thumb_bl_in_range.s: Ditto. + * testsuite/thumb_bl_out_of_range.s: Ditto. + * testsuite/thumb_branch_range.t: Ditto. + +2010-02-20 Sriraman Tallam <tmsriram@google.com> + + * gc.h (gc_process_relocs): Change vectors to point to the new list. + Add reloc offset information. + * icf.cc (get_section_contents): Change iterators to point to the new + vectors. Add reloc offset information to the contents. + * icf.h (Icf::Sections_reachable_info): New typedef. + (Icf::Sections_reachable_list): New typedef. + (Icf::Offset_info): New typedef. + (Icf::Reloc_info): New struct typedef. + (Icf::Reloc_info_list): New typedef. + (Icf::symbol_reloc_list): Delete method. + (Icf::addend_reloc_list): Delete method. + (Icf::section_reloc_list): Delete method. + (Icf::reloc_info_list): New method. + (Icf::reloc_info_list_): New member. + +2010-02-19 Doug Kwan <dougkwan@google.com> + + * arm-reloc.def: Mark R_ARM_TLS_GD32, R_ARM_TLS_LDM32, + R_ARM_TLS_LDO32, R_ARM_TLS_IE32 and R_ARM_TLS_LE32 are implemented. + * arm.cc (Arm_relocation_functions): New forward declaration. + (Target_arm::Target_arm): Initialize new data members + got_mod_index_offset_ and tls_base_symbol_defined_. + (Target_arm::Relocate::relocate_tls): New method. + (Target_arm::optimize_tls_reloc, Target_arm::define_tls_base_symbol, + Target_arm::got_mod_index_entry, Target_arm::rel_tls_desc_section): + New methods. + (Target_arm::Got_type): Add GOT_TYPE_TLS_NOFFSET, GOT_TYPE_OFFSET, + GOT_TYPE_TLS_PAIR and GOT_TYPE_TLS_DESC. + (Target_arm::got_mod_index_offset_, + Target_arm::tls_base_symbol_defined_): New data members. + (Target_arm::Scan::local, Target::Scan::global, + Target_arm::Relocate::relocate): Handle 32-bit initial TLS + relocations. + +2010-02-18 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::find_linked_text_section): New method. + (Arm_relobj::make_exidx_input_section): Pass section index of linked + text section as a parameter becuase some broken tools may not set + the link in section header. + (Target_arm::has_got_section): New method. + (Target_arm::scan_section_for_cortex_a8_stubs): Treat an input section + without any mapping symbol as data only. Remove warning. + (Arm_relobj::do_read_synbols): If an EXIDX input section has no + link in its section header, try to discover the link by inspecting the + REL31 relocation at the beginning of the section. + (Target_arm::Scan::check_non_pic): Report name of offending relocation + in error message. + (Target_arm::Scan::global): Treat any reference to the symbol + _GLOBAL_OFFSET_TABLE_ as a GOT access. + +2010-02-12 Sriraman Tallam <tmsriram@google.com> + + * arm.cc (Scan::local_reloc_may_be_function_pointer): New function. + (Scan::global_reloc_may_be_function_pointer): New function. + * sparc.cc (Scan::local_reloc_may_be_function_pointer): New function. + (Scan::global_reloc_may_be_function_pointer): New function. + * powerpc.cc (Scan::local_reloc_may_be_function_pointer): New function. + (Scan::global_reloc_may_be_function_pointer): New function. + * i386.cc (Scan::local_reloc_may_be_function_pointer): New function. + (Scan::global_reloc_may_be_function_pointer): New function. + * x86_64.cc (Scan::local_reloc_may_be_function_pointer): New function. + (Scan::global_reloc_may_be_function_pointer): New function. + (Scan::possible_function_pointer_reloc): New function. + (Target_x86_64::can_check_for_function_pointers): New function. + * gc.h (gc_process_relocs): Scan relocation types to determine if + function pointers were taken for targets that support it. + * icf.cc (Icf::find_identical_sections): Include functions for + folding in safe ICF whose pointer is not taken. + * icf.h (Secn_fptr_taken_set): New typedef. + (fptr_section_id_): New member. + (section_has_function_pointers): New function. + (set_section_has_function_pointers): New function. + (check_section_for_function_pointers): New function. + * options.h: Fix comment for safe ICF option. + * target.h (can_check_for_function_pointers): New function. + * testsuite/Makefile.am: Add icf_safe_so_test test case. + Modify icf_safe_test for X86-64. + * testsuite/Makefile.in: Regenerate. + * testsuite/icf_safe_so_test.cc: New file. + * testsuite/icf_safe_so_test.sh: New file. + * testsuite/icf_safe_test.cc (kept_func_3): New function. + (main): Change to take pointer to function kept_func_3. + * testsuite/icf_safe_test.sh (arch_specific_safe_fold): Check if safe + folding is done correctly for X86-64. + +2010-02-12 David S. Miller <davem@davemloft.net> + + * output.h (Output_reloc<SHT_REL>::Output_reloc): Add + is_symbolless parameter. + (Output_reloc<SHT_REL>::is_symbolless): New. + (Output_reloc<SHT_REL>::is_symbolless_): New. + (Output_reloc<SHT_REL>::type_): Decrease to 29 bits. + (Output_reloc<SHT_RELA>::Output_reloc): Add is_symbolless parameter. + (Output_reloc<SHT_RELA>::is_symbolless): New. + (Output_data_reloc::add_global): Handle is_symbolless. + (Output_data_reloc::add_global_relative): Likewise. + (Output_data_reloc::add_local): Likewise. + (Output_data_reloc::add_local_relative): Likewise. + (Output_data_reloc::add_symbolless_global_addend): New. + (Output_data_reloc::add_symbolless_local_addend): New. + * output.cc (Output_reloc<SHT_REL>::Output_reloc): Handle + is_symbolless. + (Output_reloc::set_needs_dynsym_index): Test ->is_symbolless_ + instead of ->is_relative_ + (Output_reloc::write): Likewise. + (Output_reloc::get_symbol_index): Return 0 when ->is_symbolless_ + (Output_reloc::write_rel): Simplify. + + * sparc.cc (Target_sparc::Scan::local): Use + ->add_symbolless_local_addend as needed. + (Target_sparc::Scan::global): Use ->add_symbolless_global_addend as + needed. Also, emit appropriate unaligned vs. aligned dynamic reloc + based upon relocation offset. + +2010-02-11 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Scan::local): Fix bugs in relocation handling. + (Target_arm::Scan::global): Ditto. Also remove a comment before the + beginning of function. + (Target_arm::Relocate::relocate): Remove error messages for MOVW_ABS + and MOVT_ABS relocations. Those are non issued in scanning. Fix + parameter is_32bit in calls to should_apply_static_reloc. + * testsuite/Makefile.am (check_SCRIPTS): Add arm_abs_global.sh. + (check_DATA): Add arm_abs_global.stdout. + (arm_abs_lib.o, libarm_abs.so, arm_abs_global.o, arm_abs_global, + arm_abs_global.stdout): New rules. + (MOSTLLYCLEANFILES): Add arm_abs_global + * Makefile.in: Regenerate. + * testsuite/arm_abs_global.s: New file. + * testsuite/arm_abs_global.sh: Ditto. + * testsuite/arm_abs_lib.s: Ditto. + +2010-02-11 Ian Lance Taylor <iant@google.com> + + * gold.cc (queue_middle_gc_tasks): Use a separate blocker for each + Read_relocs task. + (queue_middle_tasks): Likewise, and also for Scan_relocs. Run + Allocate_commons_task first. + * reloc.cc (Read_relocs::run): Pass next_blocker_ down to next + task, rather than symtab_lock_. + (Gc_process_relocs::~Gc_process_relocs): New function. + (Gc_process_relocs::is_runnable): Check this_blocker_. + (Gc_process_relocs::locks): Use next_blocker_ rather than + blocker_. + (Scan_relocs::~Scan_relocs): New function. + (Scan_relocs::is_runnable): Check this_blocker_ rather than + symtab_lock_. + (Scan_relocs::locks): Drop symtab_lock_ and blocker_. Add + next_blocker_. + * reloc.h (class Read_relocs): Drop symtab_lock_ and blocker_ + fields. Add this_blocker_ and next_blocker_ fields. Adjust + constructor accordingly. + (class Gc_process_relocs): Likewise. + (class Scan_relocs): Likewise. + * common.h (class Allocate_commons_task): Remove symtab_lock_ + field, and corresponding constructor parameter. + * common.cc (Allocate_commons_tasK::is_runnable): Remove use of + symtab_lock_. + (Allocate_commons_task::locks): Likewise. + +2010-02-11 Ian Lance Taylor <iant@google.com> + + * gold-threads.h (class Once): Define. + (class Initialize_lock): Rewrite as child of Once. + * gold-threads.cc (class Once_initialize): Define. + (once_pointer_control): New static variable. + (once_pointer, once_arg): New static variables. + (c_run_once): New static function. + (Once::Once, Once::run_once, Once::internal_run): New functions. + (class Initialize_lock_once): Remove. + (initialize_lock_control): Remove. + (initialize_lock_pointer): Remove. + (initialize_lock_once): Remove. + (Initialize_lock::Initialize_lock): Move to gold-threads.h. + (Initialize_lock::initialize): Rewrite. + (Initialize_lock::do_run_once): New function. + * archive.cc (Archive::interpret_header): Only clear name if it is + not already empty. + * fileread.cc: Include "gold-threads.h" + (file_counts_lock): New static variable. + (file_counts_initialize_lock): Likewise. + (File_read::release): Only increment counts when using --stats. + Use a lock around the increment. + * parameters.cc (class Set_parameters_target_once): Define. + (set_parameters_target_once): New static variable. + (Parameters::Parameters): Move here from parameters.h. + (Parameters::set_target): Rewrite. + (Parameters::set_target_once): New function. + (Parameters::clear_target): Move here and rewrite. + * parameters.h (class Parameters): Update declarations. Add + set_parameters_target_once_ field. + (Parameters::Parameters): Move to parameters.cc. + (Parameters::clear_target): Likewise. + * readsyms.cc (Read_symbols::do_group): Create a Start_group + task. + (Start_group::~Start_group): New function. + (Start_group::is_runnable): New function. + (Start_group::locks, Start_group::run): New functions. + (Finish_group::run): Change saw_undefined to size_t. + * readsyms.h (class Start_group): Define. + (class Finish_group): Change saw_undefined_ field to size_t. + (Finish_group::Finish_group): Remove saw_undefined and + this_blocker parameters. Change all callers. + (Finish_group::set_saw_undefined): New function. + (Finish_group::set_blocker): New function. + * symtab.h (class Symbol_table): Change saw_undefined to return + size_t. Change saw_undefined_ field to size_t. + * target-select.cc (Set_target_once::do_run_once): New function. + (Target_selector::Target_selector): Initialize set_target_once_ + field. Don't initialize lock_ and initialize_lock_ fields. + (Target_selector::instantiate_target): Rewrite. + (Target_selector::set_target): New function. + * target-select.h (class Set_target_once): Define. + (class Target_selector): Update declarations. Make + Set_target_once a friend. Remove lock_ and initialize_lock_ + fields. Add set_target_once_ field. + +2010-02-10 Ian Lance Taylor <iant@google.com> + + * dirsearch.cc (Dirsearch::initialize): Add all blockers before + queueing any tasks. + * gold.cc (queue_middle_gc_tasks): Likewise. Fix final blocker. + (queue_middle_tasks): Add all blockers before queueing any tasks. + (queue_final_tasks): Likewise. + * token.h (Task_token::add_blockers): New function. + * object.h (Input_objects::number_of_relobjs): New function. + +2010-02-10 Ian Lance Taylor <iant@google.com> + + * i386.cc (Relocate::relocate_tls): A local symbol is final if not + shared, not if not position independent. + * x86_64.cc (Relocate::relocate_tls): Likewise. + * testsuite/Makefile.am (check_PROGRAMS): Add tls_pie_pic_test. + (tls_pie_pic_test): New target. + * testsuite/Makefile.in: Rebuild. + + * testsuite/Makefile.am (check_PROGRAMS): Add tls_pie_test. + (tls_test_main_pie.o, tls_test_pie.o): New targets. + (tls_test_file2_pie.o, tls_test_c_pie.o, tls_pie_test): Likewise. + * testsuite/Makefile.in: Rebuild. + +2010-02-09 David S. Miller <davem@davemloft.net> + + * sparc.cc (Target_sparc::Scan::local): Do not emit relocs other than + R_SPARC_RELATIVE using ->add_local_relative(). + (Target_sparc::Scan::global): Likewise for ->add_global_relative(). + + * output.h (Output_data_dynamic::add_section_size): New method + that takes two Output_data objects. + (Output_data_dynamic::Dynamic_entry): Create storage for secondary + entry param. Handle it in initializers. + * output.cc (Output_data_dynamic::Dynamic_entry::write): For + DYNAMIC_SECTION_SIZE, add in second object size if non-NULL. + * layout.h (Layout::add_target_dynamic_tags): Add dynrel_includes_plt + arg. + * layout.cc (Layout::add_target_dynamic_tags): If dynrel_includes_plt, + and .rela.plt exists, set DT_REL{,A}SZ to sum of .rela.dyn and .rela.plt + * arm.cc (Target_arm::do_finalize_sections): Update to pass false + for dynrel_includes_plt. + * i386.cc (Target_i386::do_finalize_sections): Likewise. + * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. + * sparc.cc (Target_sparc::make_plt_entry): Force .rela.dyn to be output + before .rela.plt + (Target_sparc::do_finalize_sections): Update to pass true for + dynrel_includes_plt. + * powerpc.cc (Target_powerpc::make_plt_entry): Force .rela.dyn to be + output before .rela.plt + (Target_powerpc::do_finalize_sections): Update to pass true for + dynrel_includes_plt when 32-bit. + +2010-02-08 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::simple_input_section_output_address): New + method. + (Arm_relobj::section_needs_cortex_a8_stub_scanning, + Arm_relobj::scan_section_for_cortex_a8_stubs, + Arm_relobj::do_relocation_section): Instead of calling + Output_section::output_address, use faster + Arm_relobj::simple_input_section_output_address. + +2010-02-08 David S. Miller <davem@davemloft.net> + + * sparc.cc (Target_sparc::Relocate::relocate): If relocation offset is + unaligned for R_SPARC_16, R_SPARC_32, or R_SPARC_64, use the unaligned + relocation helper function. + + * sparc.cc (Target_sparc::Scan::local): Handle R_SPARC_GOTDATA_OP* + just like R_SPARC_GOT{10,13,22}. + (Target_sparc::Scan::local): Likewise. + (Target_sparc::Relocate:relocate): Likewise. + +2010-02-06 Ian Lance Taylor <iant@google.com> + + * configure.ac: Rewrite targetobjs duplicate removal code to use + only shell constructs. + * configure: Rebuild. + +2010-02-05 Doug Kwan <dougkwan@google.com> + + PR 11247 + * arm.cc (Arm_relobj::section_is_scannable): New method. + (Arm_relobj::section_needs_reloc_stub_scanning): Use it. + (Arm_relobj::section_needs_cortex_a8_stub_scanning): Same. + +2010-02-04 Doug Kwan <dougkwan@google.com> + + PR 11247 + * arm-reloc-property.cc (cstdio): Include. + * configure.ac (targetobjs): Remove duplicates. + * configure: Regenerate. + * resolve.cc (Symbol_table::resolve): Explicit instantiate both + big and little endian version for a given address size. + +2010-02-03 Doug Kwan <dougkwan@google.com> + + * arm-reloc-property.cc + (Arm_reloc_property_table::reloc_name_in_error_message): New method + definition. + * arm-reloc-property.h + (Arm_reloc_property_table::get_implemented_static_reloc_property): + New method definition. + (Arm_reloc_property_table::reloc_name_in_error_message): New method + declaration. + * arm-reloc.def (THM_MOVT_ABS, THM_MOVT_PREL, THM_MOVT_BREL): Change + overflow to N. + (GOT_PREL): Change implemented to Y. + * arm.cc (Target_arm::reloc_uses_thumb_bit): Remove method. + (Target_arm::Relocate::reloc_needs_sym_origin): Remove method. + (Arm_relocate_functions::movw_abs_nc): Remove method. + (Arm_relocate_functions::movt_abs): Ditto. + (Arm_relocate_functions::thm_movw_abs_nc): Ditto. + (Arm_relocate_functions::thm_movt_abs): Ditto. + (Arm_relocate_functions::movw_rel_nc): Ditto. + (Arm_relocate_functions::movw_rel): Ditto. + (Arm_relocate_functions::movt_rel): Ditto. + (Arm_relocate_functions:thm_movw_rel_nc): Ditto. + (Arm_relocate_functions:thm_movw_rel): Ditto. + (Arm_relocate_functions:thm_movt_rel): Ditto. + (Arm_relocate_functions::movw, Arm_relocate_functions::movt, + (Arm_relocate_functions::thm_movw, Arm_relocate_functions::thm_movt): + New method definitions. + (Arm_relocation_functions::arm_grp_alu): Add assertion for group index. + (Arm_relocation_functions::arm_grp_ldr): Ditto. + (Arm_relocation_functions::arm_grp_ldrs): Ditto. + (Arm_relocation_functions::arm_grp_ldc): Ditto. + (Target_arm::Relocate::relocate): Check for non-static or + unimplemented relocation code and exit early. Change calls to + Target_arm::reloc_uses_thumb_bit and + Target_arm::Reloc::reloc_needs_sym_origin to use relocation property + instead. Refactor code to handle similar relocations to increase + code sharing. Remove check for unsupported relocation code in switch + statement. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): Use + relocation property table to find out size. Change error message to + print out the name of a relocation code instead of the numeric value. + (Target_arm::scan_reloc_for_stub): Use relocation property table + instead of calling Target_arm::reloc_uses_thumb_bit(). + +2010-02-02 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::relocate_section): Do view adjustment for all + types of relaxed input section. + +2010-02-02 Doug Kwan <dougkwan@google.com> + + * Makefile.am (HFILES): Add arm-reloc-property.h. + (DEFFILES): New. + (TARGETSOURCES): Add arm-reloc-property.cc + (ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT) + (libgold_a_SOURCES): $(DEFFILES) + * Makefile.in: Regenerate. + * arm-reloc-property.cc: New file. + * arm-reloc-property.h: New file. + * arm-reloc.def: New file. + * arm.cc: Update comments. + (arm-reloc-property.h): New included header. + (arm_reloc_property_table): New global variable. + (Target_arm::do_select_as_default_target): New method definition. + * configure.tgt (armeb*-*-*,armbe*-*-*,arm*-*-*): Add + arm-reloc-property to targ_extra_obj. + * parameters.cc (set_parameters_target): Call + Target::select_as_default_target(). + * target.h (Target::select_as_default_target): New method definition. + (Target::do_select_as_default_target): Same. + +2010-02-01 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_exidx_fixup::Arm_exidx_fixup): Initialize + first_output_text_section_. + (Arm_exidx_fixup::first_output_text_section): New method definition. + (Arm_exidx_fixup::first_output_text_section_): New data member. + (Arm_exidx_fixup::process_exidx_section): Record the first text + output section seen. + (Arm_output_section::fix_exidx_coverage): Set correct linked section + and entsize in output section header. + +2010-01-29 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * gold/arm.cc: Added support for the ARM relocations: R_ARM_THM_PC8, + R_ARM_THM_PC12, R_ARM_THM_ALU_PREL_11_0. + (Arm_relocate_functions::thm_alu11): New Method. + (Arm_relocate_functions::thm_pc8): New Method. + (Arm_relocate_functions::thm_pc12): New Method. + (Target_arm::Scan::local): Handle the relocations. + (Target_arm::Scan::global): Likewise. + (Target_arm::Relocate::relocate): Likewise. + (Target_arm:Relocatable_size_for_reloc::get_size_for_reloc): Likewise. + +2010-01-29 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Scan::global): General PLTs for the same set + of relocation types as ld. + +2010-01-29 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relocate_functions::arm_branch_common) Change visibility + to public. + (Arm_relocate_functions::thumb_branch_common): Ditto. + (Arm_relocate_functions::thm_call, Arm_relocate_functions::thm_jump24, + Arm_relocate_functions::thm_xpc22, Arm_relocate_functions::plt32, + Arm_relocate_functions::xpc25, Arm_relocate_functions::call, + Arm_relocate_functions::jump24): Remove. + (Target_arm::Relocate::relocate): Adjust code to call + Arm_relocation_functions::arm_branch_common and + Arm_relocation_functions::thumb_branch_common instead of their removed + wrappers. Merge switch-cases together to reduce source code size. + +2010-01-29 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::Arm_relobj): Initialize new data member + output_local_symbol_count_needs_update_. + (Arm_relobj::output_local_symbol_count_needs_update, + Arm_relobj::set_output_local_symbol_count_needs_update, + Arm_relobj::update_output_local_symbol_count): New methods. + (Arm_relobj::output_local_symbol_count_needs_update_): New data + member. + (Arm_exidx_cantunwind::do_fixed_endian_write): Write address + of pointed function as in a R_ARM_PREL31 relocation. + (Arm_output_section<big_endian>::fix_exidx_coverage): Mark objects + for output local symbol count updating. + (Target_arm::do_relax): Update output local symbol counts in objects + if necessary. + * object.h (Sized_relobj::set_output_local_symbol_count): New method. + +2010-01-29 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc: Added support for the ARM relocations: + R_ARM_MOVW_BREL_NC, R_ARM_MOVT_BREL, R_ARM_MOVW_BREL, + R_ARM_THM_MOVW_BREL_NC, R_ARM_THM_MOVT_BREL, R_ARM_THM_MOVW_BREL. + (Arm_relocate_functions::movw_rel_nc): Renamed (was + movw_prel_nc). + (Arm_relocate_functions::movw_rel): New method. + (Arm_relocate_functions::movt_rel): Renamed (was movt_prel). + (Arm_relocate_functions::thm_movw_rel_nc): Renamed (was + thm_movw_prel_nc). + (Arm_relocate_functions::thm_movw_rel): New method. + (Arm_relocate_functions::thm_movt_rel): Renamed (was + thm_movt_prel). + (Target_arm::Scan::local): Handle MOVW_BREL/MOVT_BREL + relocations. + (Target_arm::Scan::global): Likewise. + (Target_arm::Relocate::relocate): Likewise. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Likewise. + +2010-01-27 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc: Added support for ARM group relocations. + (Target_arm::reloc_needs_sym_origin): New method. + (Arm_relocate_functions::calc_grp_kn): New method. + (Arm_relocate_functions::calc_grp_residual): New method. + (Arm_relocate_functions::calc_grp_gn): New method. + (Arm_relocate_functions::arm_grp_alu): New Method. + (Arm_relocate_functions::arm_grp_ldr): New Method. + (Arm_relocate_functions::arm_grp_ldrs): New Method. + (Arm_relocate_functions::arm_grp_ldc): New Method. + (Target_arm::Scan::local): Handle the ARM group relocations. + (Target_arm::Scan::global): Likewise. + (Target_arm::Relocate::relocate): Likewise. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Likewise. + +2010-01-26 Doug Kwan <dougkwan@google.com> + + * arm.cc (set): Include. + (class Arm_exidx_fixup): Change type of last_input_section_ to const + pointer type. + (Arm_output_section::Text_section_list): New type. + (Arm_output_section::append_text_sections_to_list): New method. + (Arm_output_section::fix_exidx_coverage): Ditto. + (Arm_relobj::Arm_relobj): Initialize exidx_section_map_. + (Arm_relobj::convert_input_section_to_relaxed_section): Use + Relobj::set_section_offset() instead of + Sized_relobj::invalidate_section_offset(). + (Arm_relobj::section_needs_reloc_stub_scanning): Add an extra + parameter for section headers. Ignore relocation sections for + unallocated sections and EXIDX sections. + (Target_arm::fix_exidx_coverage): New method. + (Target_arm::output_section_address_less_than): New type. + (Arm_exidx_fixup::add_exidx_cantunwind_as_needed): Use index of the + linked text section instead of the EXIDX section. + (Arm_output_section::create_stub_group): Add an assertion to check + that this is not an EXIDX output section. + (Arm_output_section::append_text_sections_to_list): New method. + (Arm_output_section::fix_exidx_coverage): Ditto. + (Arm_relobj::scan_sections_for_stubs): Adjust call to + Arm_relobj::section_needs_reloc_stub_scanning. + (Target_arm::do_relax): Fix EXIDX output section coverage in the + first pass. + (Target_arm::fix_exidx_coverage): New method. + * object.h (Relobj::set_output_section): New method. + (Sized_relobj::invalidate_section_offset): Remove method. + (Sized_relobj::do_invalidate_section_offset): Remove method. + (Sized_relobj::do_set_section_offset): Handle offset value -1. + +2010-01-25 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_exidx_merged_section::do_output_offset): + Fix warning due to signed and unsigned comparison on a 32-bit host. + +2010-01-22 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::do_relax): Record an output section for section + offset adjustment it contains any stub table that has changed. + * layout.cc (Layout::clean_up_after_relaxation): Adjust section + offsets in an output section if necessary. + * output.cc (Output_section::Output_section): Initialize + section_offsets_need_adjustments_. + (Output_section::add_input_section_for_script): Renamed to + Output_section::add_simple_input_section. + (Output_section::save_states): Add a comment. + (Output_section::discard_states): New method defintion. + (Output_section::adjust_section_offsets): Same. + * output.h (Output_section::add_input_section_for_script): Renamed to + Output_section::add_simple_input_section. + (Output_section::discard_states): New method declaration. + (Output_section::adjust_section_offsets): Same. + (Output_section::section_offsets_need_adjustment, + Output_section::set_section_offsets_need_adjustment): New method + definitions. + (Output_section::section_offsets_need_adjustment_): New data member. + * script-sections.cc + (Output_section_element_input::set_section_address): Adjust code for + renaming of Output_section::add_input_section_for_script. + (Orphan_output_section::set_section_address): Same. + +2010-01-22 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * gold/arm.cc (Target_arm): Updated fix_v4bx method and usage of + Fix_v4bx enum values . + * gold/options.h (General_options): New option definitions. + (General_options::fix_v4bx): New method. + (General_options::Fix_v4bx): New enum. + * gold/options.cc (General_options::parse_fix_v4bx): New method. + (General_options::parse_fix_v4bx_interworking): New method. + +2010-01-22 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_exidx_fixup): New class. + +2010-01-21 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_exidx_cantunwind, Arm_exidx_merged_section): New + classes. + (Arm_exidx_section_offset_map): New type. + +2010-01-21 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_exidx_input_section): New class. + (Arm_relobj::exidx_input_section_by_link, + Arm_relobj::exidx_input_section_by_shndx, + Arm_relobj::make_exidx_input_section): New methods. + (read_arm_attributes_section): Remove. + (Arm_relobj::do_read_symbols): Look for ARM.exidx sections and record + information about them. + (Arm_dynobj::do_read_symbols): Move code in read_arm_attributes_section + to here. + +2010-01-20 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Arm_input_section_map): Change key type from + Input_section_specifier to Section_id. + (Target_arm::new_arm_input_section: Adjust code for change of key + type. + (Target_arm::find_arm_input_section): Ditto. + * gc.h (object.h): Include for Section_id nand Section_id_hash. + (Section_id): Remove. + (Garbage_collection::Section_id_hash): Remove. + * icf.h (object.h): Include for Section_id nand Section_id_hash. + (Section_id): Remove. + (Icf::Section_id_hash): Remove. + * object.h (Section_id, Const_section_id, Section_id_hash, + Const_section_id_hash): New type definitions. + * output.cc (Output_section::add_relaxed_input_section): Change to + use Const_section_id instead of Input_section_specifier as key type. + (Output_section::add_merge_input_section): Ditto. + (Output_section::build_relaxation_map): Change to use Section_id + instead of Input_section_specifier as key type. + (Output_section::convert_input_sections_in_list_to_relaxed_sections): + Ditto. + (Output_section::convert_input_sections_to_relaxed_sections): Change + to use Const_section_id instead of Input_section_specifier as key type. + (Output_section::find_merge_section): Ditto. + (Output_section::find_relaxed_input_section): Ditto. + * output.h (Input_section_specifier): Remove class. + (Output_section::Output_section_data_by_input_section_map): Change + key type to Const_section_id. + (Output_section::Output_relaxed_input_section_by_input_section_map): + Ditto. + (Output_section::Relaxation_map): Change key type to Section_id. + +2010-01-20 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * gold/arm.cc: Added support for R_ARM_V4BX relocation + (class Arm_v4bx_stub): New class. + (DEF_STUBS): Updated definition to support v4_veneer_bx. + (Stub_factory::make_arm_v4bx_stub): New method. + (Stub_factory::elf32_arm_stub_v4_veneer_bx): New veneer template. + (Stub_table::empty): Handle v4bx stubs. + (Stub_table::add_arm_v4bx_stub): New method. + (Stub_table::find_arm_v4bx_stub): New method. + (Arm_relocate_functions::v4bx): New method. + (Target_arm::fix_v4bx): New method. + (Target_arm::Target_arm): Handle R_ARM_V4BX. + (Stub_table::relocate_stubs): Likewise. + (Stub_table::do_write): Likewise. + (Stub_table::update_data_size_and_addralign): Likewise. + (Stub_table::finalize_stubs): Likewise. + (Target_arm::Scan::local): Likewise. + (Target_arm::Scan::global): Likewise. + (Target_arm::do_finalize_sections): Likewise. + (Target_arm::Relocate::relocate): Likewise. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Likewise. + (Target_arm::scan_reloc_for_stub): Likewise. + (Target_arm::scan_reloc_section_for_stubs): Likewise. + +2010-01-19 Ian Lance Taylor <iant@google.com> + + * output.cc (Output_section_headers::do_sized_write): Write large + segment count to sh_info field. + (Output_file_header::do_sized_write): For large segment count, + write PN_XNUM to e_phnum field. + +2010-01-15 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Arm_relocate_functions::thm_jump6): New function. + (Arm_relocate_functions::thm_jump8): New function. + (Arm_relocate_functions::thm_jump11): New function. + (Target_arm::Scan::local): Handle R_ARM_THM_JUMP6, R_ARM_THM_JUMP8, + R_ARM_THM_JUMP11. + (Target_arm::Scan::global): Likewise. + (Target_arm::Relocate::relocate): Likewise. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Likewise. + +2010-01-14 Doug Kwan <dougkwan@google.com> + + * arm.cc (map, utility): Include headers. + (Target_arm::apply_cortex_a8_workaround): New method. + (Arm_relobj::do_relocate_sections): Apply any Cortex-A8 workaround. + (Target_arm::Scan::local): Handle R_ARM_THM_JUMP24, R_ARM_THM_JUMP19. + (Target_arm::Scan::global): R_ARM_THM_JUMP19. + (Target_arm::do_finalize_sections): Set fix_cortex_a8_ according to + the --[no-]fix-cortex-a8 command line options. + (Target_arm::Relocate::relocate): Handle R_ARM_JUMP19. + (Target_arm::relocate_stub): Use addend in instruction template. + * options.h (DEFINE_bool): Set the user-set flag. + (General_options): Add --[no-]-fix-cortex options. + * output.cc (Output_section::convert_input_sections_to_relaxed_sections) + : Update fast look-up map after conversion. + +2010-01-14 Sriraman Tallam <tmsriram@google.com> + + * object.cc (Sized_relobj::do_layout): Change to call layout_gnu_stack + in the first pass of do_layout. + +2010-01-13 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::section_needs_reloc_stub_scanning, + Arm_relobj::scan_sections_for_stubs): Rearrange code to avoid an + apparent compiler problem of not folding static constant integral + data members of elfcpp::Elf_sizes<32>. + +2010-01-13 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::section_needs_reloc_stub_scanning, + Arm_relobj::section_needs_cortex_a8_stub_scanning, + Arm_relobj::scan_section_for_cortex_a8_erratum, + Arm_relobj::scan_span_for_cortex_a8_erratum): New methods. + (Arm_relobj::scan_sections_for_stubs): Move code deciding what + sections to scan for relocation stubs into a new method + Arm_relobj::section_needs_reloc_stub_scanning. Handle both + relocation and Cortex-A8 stub scanning. + (Target_arm::do_relax): Force stubs to be after stubbed sections + if fixing the Cortex-A8 erratum. Remove all Cortex-A8 stubs at + the beginning of a new relaxation pass. Update a comment. + (Target_arm::scan_span_for_cortex_a8_erratum): New method definition. + +2010-01-12 Ian Lance Taylor <iant@google.com> + + * target-reloc.h (visibility_error): New inline function. + (relocate_section): Call visibility_error. + * testsuite/Makefile.am (check_DATA): Add protected_3.err. + (MOSTLYCLEANFILES): Likewise. + (protected_4_pic.o, protected_3.err): New targets. + * testsuite/protected_4.cc: New file. + +2010-01-12 Doug Kwan <dougkwan@google.com> + + * arm.cc (Cortex_a8_reloc): New class. + (Target_arm::Target_arm): Initialize new data members fix_cortex_a8_ + and cortex_a8_relocs_info_. + (Target_arm::fix_cortex_a8): New method definition. + (Target_arm::Cortex_a8_relocs_info): New type. + (Target_arm::fix_cortex_a8_, Target_arm::cortex_a8_relocs_info_): + New data member declarations. + (Target_arm::scan_reloc_for_stub): Record information about + relocations for THUMB branches that might be exempted from the + Cortex-A8 workaround. + (Target_arm::do_relax): Clear all Cortex-A8 relocation information + at the beginning of a relaxation pass. + +2010-01-12 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::mapping_symbols_info_): New data member. + (Arm_relobj::Mapping_symbol_position, + Arm_reloj::Mapping_symbol_position_less, + Arm_relobj::Mapping_symbols_info): New types. + (Target_arm::is_mapping_symbol_name): New method definition. + (Arm_relobj::do_count_local_symbols): Save information about mapping + symbols. + +2010-01-11 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relocate_functions::thumb32_branch_offset, + Arm_relocate_functions::thumb32_branch_upper, + Arm_relocate_functions::thumb32_branch_lower, + Arm_relocate_functions::thumb32_cond_branch_offset, + Arm_relocate_functions::thumb32_cond_branch_upper, + Arm_relocate_functions::thumb32_cond_branch_lower, + Arm_relocate_functions::thm_jump19): New methods to handle THUMB + branch offset encoding. + (Arm_relocate_functions::thumb_branch_common): Use new branch + offset encoding methods to avoid code duplication. + (Stub_template::Stub_template) Handle THUMB16_SPECIAL_TYPE. + (Stub_addend_reader::operator()): Use new branch encoding method + to avoid code duplication. + +2010-01-11 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::do_gc_process_relocs): New method. + (Target_arm::do_finalize_sections): Define special EXIDX section + symbols only if referenced. + * gc.h (Garbage_collection::add_reference): New method. + (gc_process_relocs): Use Garbage_collection::add_reference to avoid + code duplication. + +2010-01-11 Ian Lance Taylor <iant@google.com> + + * script.cc (Version_script_info::build_expression_list_lookup): + Change complaing about duplicate wildcard match from error to + warning. + + * script.cc (class Lazy_demangler): Recreate--revert part of patch + of 2009-12-30. + (Version_script_info::Version_script_info): Initialize globs_, + default_version_, default_is_global_, and exact_. Don't + initialize globals_ or locals_. + (Version_script_info::build_lookup_tables): Build local symbols + first. + (Version_script_info::unquote): New function. + (Version_script_info::add_exact_match): New function. + (Version_script_info::build_expression_list_lookup): Remove lookup + parameter. Add is_global parameter. Change all callers. Handle + wildcard pattern specially. Unquote pattern. Call + add_exact_match. + (Version_script_info::get_name_to_match): New function. + (Version_script_info::get_symbol_version): New function. + (Version_script_info::get_symbol_version_helper): Remove. + (Version_script_info::check_unmatched_names): Call unquote. + * script.h (class Version_script_info): Change get_symbol_version + to be non-inline and add is_global parameter; change all callers. + Rewrite symbol_is_local. Update declarations. Define struct + Version_tree_match, Exact, Globs. Don't define struct Lookup. + Remove globals_ and locals_ members. Add exact_, globs_, + default_version_, is_global_. + (Version_script_info::Glob): Remove pattern, add expression and + is_global. Update constructor. Change all callers. + * dynobj.cc (Versions::finalize): Mark the version symbol as the + default version. + (Versions::symbol_section_contents): If a symbol is undefined, or + defined in a dynamic object, set the version index to + VER_NDX_LOCAL. + * symtab.cc (Symbol_table::add_from_relobj): Don't call + symbol_is_local. + (Symbol_table::add_from_pluginobj): Likewise. + * testsuite/ver_matching_test.sh: blaza1 and blaza go into V2. + +2010-01-11 Doug Kwan <dougkwan@google.com> + + * Makefile.am (incremental_dump_DEPENDENCIES): Add libintl dependency. + (incremental_dump_LDADD): Add linking option for libintl. + * Makefile.in: Regenerate. + +2010-01-11 H.J. Lu <hongjiu.lu@intel.com> + + PR gold/11144 + * testsuite/Makefile.am (dynamic_list.stdout): Use --dyn-syms + instead of -Ds. + * testsuite/Makefile.in: Regenerated. + +2010-01-10 Doug Kwan <dougkwan@google.com> + + * options.h (DEFINE_var): Use parentheses around argument varname__ + in macro body to avoid any unintended subsequent substitutions. + +2010-01-10 Ian Lance Taylor <iant@google.com> + + * resolve.cc (Symbol_table::resolve): Add symbols to list of ODR + candidates before doing symbol resolution. + + * resolve.cc (Symbol_table::resolve): Add symbols to the list of + ODR candidates if only one is weak. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + * script.cc (Version_script_info::build_expression_list_lookup): + Don't warn about ambiguous version, just record the ambiguity. + (Version_script_info::get_symbol_version_helper): Give error if + version is ambiguous. + +2010-01-08 Doug Kwan <dougkwan@google.com> + + * arm.cc (Stub_table::Stub_table): Initalize cortex_a8_stubs_, + prev_data_size_ and prev_addralign_. Remove initializer for + deleted data member has_been_changed_. + (Stub_table::empty): Look at both reloc_stubs_ and cortex_a8_stubs_ + to determine if the table is empty. + (Stub_table::has_been_changed, Stub_table_set_has_been_changed): + Remove. + (Stub_table::add_reloc_stub): Define method in class definition + instead of just declaring it there. + (Stub_table::add_cortex_a8_stub): New method definition. + (Stub_table::update_data_size_and_addralign): Ditto. + (Stub_table::finalize_stubs): Ditto. + (Stub_table::apply_cortex_a8_workaround_to_address_range): Ditto. + (Stub_table::do_addralign_): Return address alignment in the + (Stub_table::do_reset_address_and_file_offset): Define method in + class definition instead of declaring it there. Set current data + size to be the data size of the previous pass. + (Stub_table::set_final_data_size): Use current data size as the + final data size. + (Stub_table::relocate_stub): Change parameter type of stub from + Reloc_stub pointer to Stub pointer. + (Stub_table::addralign_, Stub_table::has_been_changed_): Remove. + (Stub_table::Cortex_a8_stub_list): New typedef. + (Stub_table::cortex_a8_stubs_, Stub_table::prev_data_size_, + Stub_table::prev_addralign_): New data member. + (Arm_relobj::Arm_relobj): Initialize data member + section_has_cortex_a8_workaround_. + (Arm_relobj::section_has_cortex_a8_workaround, + Arm_relobj::mark_section_for_cortex_a8_workaround): New method + definitions. + (Arm_relobj::section_has_cortex_a8_workaround_): New data member + declarations. + (Target_arm::relocate_stub): Change parameter type of stub from + Reloc_stub pointer to Stub pointer. + (Insn_template::size, Insn_template::alignment): Handle + THUMB16_SPECIAL_TYPE. + (Stub_table::remove_all_cortex_a8_stubs, Stub_table::finalize_stubs, + Stub_table::update_data_size_and_addralign, + Stub_table::apply_cortex_a8_workaround_to_address_range): New method + definitions. + (Stub_table::relocate_stubs): Handle Cortex-A8 stubs. + (Stub_table::do_write): Ditto. + (Target_arm::do_relax): Adjust code for changes in Stub_table. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + PR 11108 + * symtab.h (class Symbol): Remove fields is_target_special_ and + has_plt_offset_. Add field is_defined_in_discarded_section_. + (Symbol::is_defined_in_discarded_section): New function. + (Symbol::set_is_defined_in_discarded_section): New function. + (Symbol::has_plt_offset): Rewrite. + (Symbol::set_plt_offset): Verify that new offset is not -1U. + * symtab.cc (Symbol::init_fields): Initialize plt_offset_ to -1U. + Don't initialize is_target_special_ or has_plt_offset_. + Initialize is_defined_in_discarded_section_. + (Symbol_table::add_from_relobj): If appropriate, set + is_defined_in_discarded_section. + * resolve.cc (Symbol::override_base_with_special): Don't test + is_target_special_. Change has_plt_offset_ to has_plt_offset(). + * target-reloc.h (relocate_section): Do special handling for + symbols defined in discarded sections for global symbols as well + as local symbols. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + * dynobj.cc (big_endian>::find_dynsym_sections): Set pi to NULL in + the SHT_SYMTAB case. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + * object.cc (Sized_relobj::do_layout): Don't get confused if + layout_eh_frame returns NULL. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + PR 11084 + * dynobj.cc (Sized_dynobj::find_dynsym_sections): If there is no + dynamic symbol table, use the normal symbol table. + (Sized_dynobj::do_read_symbols): Remove assertion about type of + symbol table. + +2010-01-08 Ian Lance Taylor <iant@google.com> + + PR 11072 + * layout.cc (Layout::include_section): Remove .gnu_debuglink + sections. + +2010-01-08 H.J. Lu <hongjiu.lu@intel.com> + + * version.cc (print_version): Change to "Copyright 2010". + +2010-01-08 Ian Lance Taylor <iant@google.com> + + PR 10287 + PR 11063 + * i386.cc (class Target_i386): Change return type of plt_section + to be non-const. + (class Output_data_plt_i386): Add tls_desc_rel_ field. + (Output_data_plt_i386::Output_data_plt_i386): Initialize + tls_desc_rel_ field. + (Output_data_plt_i386::rel_tls_desc): New function. + (Target_i386::rel_tls_desc_section): New function. + (Target_i386::Scan::local): Rewrite R_386_TLS_GOTDESC handling. + (Target_i386::Scan::global): For R_386_TLS_GOTDESC put + R_386_TLS_DESC reloc in rel_tls_desc_section. + * x86_64.cc (class Target_x86_64): Add tlsdesc_reloc_info_ field. + Define struct Tlsdesc_info. + (Target_x86_64::Target_x86_64): Initialize tlsdesc_reloc_info_. + (Target_x86_64::do_reloc_symbol_index): New function. + (Target_x86_64::add_tlsdesc_info): New function. + (class Output_data_plt_x86_64): Add tlsdesc_rel_ field. + (Output_data_plt_x86_64::Output_data_plt_x86_64): Initialize + tlsdesc_rel_ field. + (Output_data_plt_x86_64::rela_plt): Rename from rel_plt. Change + all callers. + (Output_data_plt_x86_64::rela_tlsdesc): New function. + (Target_x86_64::rela_tlsdesc_section): New function. + (Target_x86_64::Scan::local): Rewrite R_X86_64_GOTPC32_TLSDESC + handling. + (Target_x86_64::Scan::global): For R_X86_64_GOTPC32_TLSDESC put + (Target_x86_64::do_reloc_addend): New function. + R_X86_64_TLSDESC reloc in rela_tlsdesc_section. + * output.h (class Output_reloc) [SHT_REL]: Add new constructor + declarations. Define TARGET_CODE. Add arg field to u1_ union. + (Output_reloc::type): New function. + (Output_reloc::is_local_section_symbol): Check for TARGET_CODE. + (Output_reloc::is_target_specific): New function. + (Output_reloc::target_arg): New function. + (class Output_reloc) [SHT_RELA]: Add four new constructors for + absolute relocs and target specific relocs. + (class Output_data_reloc) [SHT_REL]: Add add_absolute and + add_target_specific. + (class Output_data_reloc) [SHT_RELA]: Likewise. + * output.cc (Output_reloc::Output_reloc): Add four new versions + for absolute relocs and target specific relocs. + (Output_reloc::set_needs_dynsym_index): Add TARGET_CODE case. + (Output_reloc::get_symbol_index): Likewise. + (Output_reloc::local_section_offset): Check that local_sym_index_ + is not TARGET_CODE or 0. + (Output_reloc::symbol_value): Likewise. + (Output_reloc::write) [SHT_RELA]: Call target for target specific + reloc. + * target.h (class Target): Add reloc_symbol_index and reloc_addend + functions. Add do_reloc_symbol_index and do_reloc_addend virtual + functions. + * layout.cc (add_target_dynamic_tags): Use output section for + DT_PLTRELSZ and DT_JMPREL. + +2010-01-07 Ian Lance Taylor <iant@google.com> + + PR 11061 + * output.h (class Output_reloc) [SHT_RELA]: Add is_relative + function. + (class Output_data_reloc_generic): Define. + (class Output_data_reloc_base): Change base class to + Output_data_reloc_generic. Change add() method to call + bump_relative_reloc_count for a relative reloc. Remove + sort_relocs_ field. + * output.cc (Output_data_reloc_base::do_write): Change sort_reloc_ + to sort_relocs(). + * layout.cc (Layout::add_target_dynamic_tags): Change dyn_rel to + Output_data_reloc_generic*. Add DT_RELCOUNT/DT_RELACOUNT tag if + appropriate. + * layout.h (class Layout): Update declaration. + +2010-01-07 Ian Lance Taylor <iant@google.com> + + * output.h (class Output_data): Add const version of + output_section and do_output_section. + (class Output_section_data): Add const version of + do_output_section. + (class Output_section): Likewise. + * layout.cc (Layout::add_target_dynamic_tags): New function. + * layout.h (class Layout): Update declarations. + * arm.cc (Target_arm::do_finalize_sections): Use + add_target_dynamic_tags. + * i386.cc (Target_i386::do_finalize_sections): Likewise. + * powerpc.cc (Target_powerpc::do_finalize_sections): Likewise. + * sparc.cc (Target_sparc::do_finalize_sections): Likewise. + * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. + +2010-01-07 Ian Lance Taylor <iant@google.com> + + PR 11042 + * copy-relocs.cc (Copy_relocs::emit_copy_reloc): Mark the dynamic + object as needed. + +2010-01-07 Dmitry Gorbachev <d.g.gorbachev@gmail.com> + Ian Lance Taylor <iant@google.com> + + PR 11019 + * object.cc: Instantiate Xindex::initialize_symtab_xindex and + Xindex::read_symtab_xindex. + +2010-01-07 Doug Kwan <dougkwan@google.com> + + * arm.cc (Insn_template::Type): New enum value THUMB16_SPECIAL_TYPE. + (Insn_template::thumb16_bcond_insn): New method declaration. + (Insn_template): Fix spelling. + (Stub::thumb16_special): New method declaration. + (Stub::do_write): Define virtual method which was previously pure + virtual. + (Stub::do_thumb16_special): New method declaration. + (Stub::do_fixed_endian_write): New template member. + (Reloc_stub::do_write): Remove. + (Reloc_stub::do_fixed_endian_write): Remove. + (Cortex_a8_stub): New class definition. + (Stub_factory::make_cortex_a8_stub): New method definition. + (Stub_factory::Stub_factory): Add missing static storage class + qualifier for elf32_arm_stub_a8_veneer_blx. + +2010-01-07 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.h (class General_options): Add --warn-unresolved-symbols + and --error-unresolved-symbols. + * errors.cc (Errors::undefined_symbol): Implement + --warn-unresolved-symbols. + + * options.h (class General_options): Add -z text and -z textoff. + * layout.cc (Layout::finish_dynamic_section): Implement -z text. + +2010-01-06 Sriraman Tallam <tmsriram@google.com> + + * gc.h (Garbage_collection::Cident_section_map): New typedef. + (Garbage_collection::cident_sections): New function. + (Garbage_collection::add_cident_section): New function. + (Garbage_collection::cident_sections_): New member. + (gc_process_relocs): Add references to sections whose names are C + identifiers. + * gold.h (cident_section_start_prefix): New constant. + (cident_section_stop_prefix): New constant. + (is_cident): New function. + * layout.cc (Layout::define_section_symbols): Replace string constants + with the newly defined constants. + * object.cc (Sized_relobj::do_layout): Track sections whose names are + C identifiers. + * testsuite/Makefile.am: Add gc_orphan_section_test. + * testsuite/Makefile.in: Regenerate. + * testsuite/gc_orphan_section_test.cc: New file. + * testsuite/gc_orphan_section_test.sh: New file. + +2010-01-06 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.h (class General_options): Add --warn-shared-textrel. + * layout.cc (Layout::finish_dynamic_section): Implement + --warn-shared-textrel. + + PR 10980 + * options.h (class General_options): Add --warn-multiple-gp. + +2010-01-06 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * Makefile.am (incremental_dump_DEPENDENCIES): Remove + $(THREADSLIB) and $(LIBDL). + * Makefile.in: Rebuild. + +2010-01-06 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.cc (General_options::parse_section_start): New function. + (General_options::section_start): New function. + (General_options::General_options): Initialize all members. + * options.h: Include <map> + (class General_options): Add --section-start. Add section_starts_ + member. + * layout.cc (Layout::attach_allocated_section_to_segment): If + --section-start was used, set the address of the segment. Remove + local sort_sections. + (Layout::relaxation_loop_body): If the address of the load segment + has been set by --section-start, don't use it. + * output.h (Output_segment::update_flags_for_output_section): New + function. + * output.cc (Output_segment::add_output_section): Call + update_flags_for_output_section. + +2010-01-05 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.h (class General_options): Add --undefined-version. + * script.cc (struct Version_expression): Add was_matched_by_symbol + field. + (Version_script_info::matched_symbol): New function. + (Version_script_info::get_symbol_version_helper): Call + matched_symbol. + (Version_script_info::check_unmatched_names): New function. + * script.h (class Version_script_info): Update declarations. + * gold.cc (queue_middle_tasks): Handle --no-undefined-version. + + * options.h (class General_options): Use DEFINE_bool_alias for + allow_multiple_definition. + * resolve.cc (Symbol_table::should_override): Don't test + allow_multiple_definition. + + PR 10980 + * options.h (class General_options): Add --cref. + * main.cc (main): Print cref table if --cref. Don't close mapfile + until after printing cref table. + * cref.cc: Include "symtab.h". + (class Cref_inputs): Define Cref_table_compare and Cref_table. + (Cref_table_compare::operator()): New function. + (Cref_inputs::gather_cref): New function. + (filecol): New static const. + (Cref_inputs::print_cref): New function. + (Cref::print_cref): New function. + * cref.h: Include <cstdio>. + (class Cref): Update declarations. + * mapfile.h (Mapfile::file): New function. + * object.h (class Object): Define Symbols. Declare virtual + do_get_global_symbols. + (Object::get_global_symbols): New function. + * object.cc (Input_objects::add_object): Pass object to cref_ if + --cref. + (Input_objects::archive_start): Likewise. + (Input_objects::archive_stop): Likewise. + (Input_objects::print_cref): New function. + * dynobj.h (Sized_dynobj::do_get_global_symbols): New function. + * dynobj.cc (big_endian>::do_add_symbols): Create symbols_ if + --cref. + * plugin.cc (Sized_pluginobj::do_get_global_symbols): New + function. + * plugin.h (class Sized_pluginobj): Update declarations. + +2010-01-05 Ian Lance Taylor <iant@google.com> + + * symtab.cc (Symbol_table::add_from_object): Rename def parameter + to is_default_version. Rename insdef to insdefault. + (Symbol_table::add_from_relobj): Rename def to is_default_version + and local to is_forced_local. + (Symbol_table::add_from_pluginobj): Likewise. + (Symbol_table::add_from_dynobj): Likewise. + (Symbol_table::define_special_symbol): Rename insdef to + insdefault. + +2010-01-04 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.h (class General_options): Add + --allow-multiple-definition and -z muldefs. + * resolve.cc (Symbol_table::should_override): Don't warn about a + multiple symbol definition if --allow-multiple-definition or -z + muldefs. + + PR 10980 + * options.h (class General_options): Add --add-needed and + --copy-dt-needed-entries. Tweak --as-needed help entry. + * object.cc (Input_objects::check_dynamic_dependencies): Give an + error if --copy-dt-needed-entries aka --add-needed is used and + would cause a change in behaviour. + + PR 10980 + * options.h (class General_options): Add -G as a short version of + --shared. Add no-op options -assert, -g, and -i. + +2010-01-04 Sriraman Tallam <tmsriram@google.com> + + * gc.h (gc_process_relocs): Call is_section_foldable_candidate to + check for .text or .gnu.linkonce.t sections. + * icf.cc (Icf::find_identical_sections): Ditto. + Change the detection for mangled function name within the section + name. + * icf.h (is_section_foldable_candidate): New function. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10980 + * options.h (class General_options): Permit two dashes with + --retain-symbols-file. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10979 + * layout.cc (Layout::relaxation_loop_body): If -Ttext was used, + don't put the file header and segment headers in the text + segment. + + PR 10979 + * common.cc (Sort_commons::operator()): Stabilize sort when both + entries are NULL. + (Symbol_table::do_allocate_commons_list): When allocating common + symbols, skip a symbol which is no longer common. + * symtab.h (Symbol::is_common): Test whether the symbol comes from + an object before checking its type. + * testsuite/common_test_2.c: New file. + * testsuite/common_test_3.c: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add common_test_2. + (common_test_2_SOURCES, common_test_2_DEPENDENCIES): Define. + (common_test_2_LDFLAGS, common_test_2_LDADD): Define. + (common_test_2_pic.o, common_test_2.so): New targets. + (common_test_3_pic.o, common_test_3.so): New targets. + * testsuite/Makefile.in: Rebuild. + + PR 10979 + * script.cc (read_input_script): If we see a new SECTIONS clause, + and we have added an input section, give an error. + * layout.h (class Layout): Add have_added_input_section function. + Add have_added_input_section_ field. + * layout.cc (Layout::Layout): Initialize + have_added_input_section_. + (Layout::layout): Set have_added_input_section_. + (Layout::layout_eh_frame): Likewise. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10931 + * options.h (class General_options): Add --sort-common option. + * symtab.h (class Symbol_table): Define Sort_commons_order enum. + * common.cc (Sort_common): Add sort_order parameter to + constructor. Add sort_order_ field. + (Sort_commons::operator): Check sort_order_. + (Symbol_table::allocate_commons): Determine the sort order. + (Symbol_table::do_allocate_commons): Add sort_order parameter. + Change all callers. + (Symbol_table::do_allocate_commons_list): Likewise. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10916 + * symtab.cc (Symbol_table::add_from_relobj): When not exporting + symbols from this object, don't change the visibility of an + undefined symbol. + * testsuite/exclude_libs_test_1.c (lib1_ref): New function. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10861 + * script.h (class Version_script_info): Define Language enum. + Update declarations. Define Glob, Exact, and Lookup types. Add + new fields globals_, locals_, and is_finalized_. + * script.cc: Various formatting fixes. + (class Parser_closure): Change language_stack_ from a vector of + std::string to one of Version_script_info::Language. Adjust all + uses accordingly. + (class Lazy_demangler): Remove. + (struct Version_expression): Change language from std::string to + Version_script_info::Language. + (Version_script_info::Version_script_info): New function. + (Version_script_info::~Version_script_info): Don't call clear. + (Version_script_info::finalize): New function. + (Version_script_info::build_lookup_tables): New function. + (Version_script_info::build_expression_list_lookup): New + function. + (Version_script_info::get_symbol_version_helper): Rewrite to use + lookup tables. + (Version_script_info::print_expression_list): Adjust to use + Version_script_info::Language. + (script_push_lex_into_version_mode): Check that the version script + has not been finalized. + (version_script_push_lang): Change language string to + Version_script_info::Language. + * options.cc (Command_line::version_script): New function. + * options.h (class General_options): Add finalize_dynamic_list + function. Change version_script from declaration to definition. + * testsuite/ver_test_4.script: Remove duplicate def of t2_2. + * testsuite/version_script.map: Remove duplicate def of foo. + * testsuite/Makefile.am (ver_matching_def.so): Depend upon + version_script.map. + * testsuite/Makefile.in: Rebuild. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10843 + * target-reloc.h (relocate_for_relocatable): When copying a reloc, + if the input symbol index is 0, make the output symbol index 0. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10670 + * options.h (class General_options): Add -x/--discard-all. + * object.cc (Sized_relobj::do_count_local_symbols): Handle + --discard-all. If the local symbol needs a dynamic entry, check + that before handling --discard-locals. + +2009-12-30 Ian Lance Taylor <iant@google.com> + + PR 10450 + * output.cc (Output_segment::Output_segment): If PT_TLS, set the + flags to PF_R. + (Output_segment::add_output_section): Don't change the flags if + the type is PT_TLS. + + PR 10450 + * dynobj.cc (Dynobj::create_gnu_hash_table): Add symbols to the + GNU hash table if they need a dynamic value. Otherwise, don't add + them if they are defined in a dynamic object or are forced local. + +2009-12-29 Ian Lance Taylor <iant@google.com> + + PR 10450 + * layout.cc (Layout::create_dynamic_symtab): Only set entsize of + .gnu.hash table for a 32-bit target. + + PR 10450 + * symtab.h (Symbol::needs_dynsym_entry): A symbol in both a + regular and a dynamic object only needs a dynamic symbol table + entry if it is externally visible. + + PR 10450 + * i386.cc (class Target_i386): Initialize global_offset_table_ in + constructor. Add global_offset_table_ field. + (Target_i386::got_section): Set global_offset_table_. + (Target_i386::do_finalize_sections): Set global_offset_table_ + size. + * x86_64.cc (class Target_x86_64): Initialize global_offset_table_ + in constructor. Add global_offset_table_ field. + (Target_x86_64::got_section): Set global_offset_table_. + (Target_x86_64::do_finalize_sections): Set global_offset_table_ + size. + + * layout.cc (Layout::Layout): Initialize increase_relro_. + (Layout::get_output_section): Add is_relro, is_last_relro, and + is_first_non_relro parameters. Change all callers. + (Layout::choose_output_section): Likewise. + (Layout::add_output_section_data): Likewise. + (Layout::make_output_section): Likewise. + (Layout::set_segment_offsets): Clear increase_relro when using a + linker script. + * layout.h (class Layout): Add increase_relro method. Add + increase_relro_ field. Update declarations. + * output.cc (Output_section::Output_section): Initialize + is_last_relro_ and is_first_non_relro_. + (Output_segment::add_output_section): Group relro sections is + do_sort is true. Handle is_last_relro and is_first_non_relro. + (Output_segment::maximum_alignment): Remove relro handling. + (Output_segment::set_section_addresses): Add increase_relro + parameter. Change all callers. Add initial alignment to align + relro sections on separate page. Remove old relro handling. + (Output_segment::set_section_list_addresses): Remove in_relro + parameter. Change all callers. + (Output_segment::set_offset): Add increase parameter. Change all + callers. Remove old relro handling. + * output.h (class Output_section): Add new methods: is_last_relro, + set_is_last_relro, is_first_non_relro, set_is_first_non_relro. + Add is_last_relro_ and is_first_non_relro_ fields. + * i386.cc (Target_i386::got_section): Don't call set_is_relro. + Create separate .got.plt section. Call increase_relro. + * x86_64.cc (Target_x86_64::got_section): Likewise. + * testsuite/relro_script_test.t: Add .got.plt. + + PR 10450 + * layout.cc (Layout::Layout): Initialize dynamic_symbol_ field. + (Layout::create_initial_dynamic_sections): Set dynamic_symbol_. + (Layout::finalize): Call set_dynamic_symbol_size. + (Layout::set_dynamic_symbol_size): New function. + * layout.h (class Layout): Add dynamic_symbol_ field. Declare + set_dynamic_symbol_size. + + PR 10450 + * output.h (class Output_section): Add is_entsize_zero_ field. + * output.cc (Output_section::Output_section): Initialize + is_entsize_zero_. + (Output_section::set_entsize): If two different entsizes are + requested, force it to zero. + (Output_section::add_input_section): Set flags for .debug_str + before updating section flags. Set entsize. + (Output_section::update_flags_for_input_section): Set SHF_MERGE + and SHF_STRING if all input sections have those flags. + +2009-12-29 Rafael Espindola <espindola@google.com> + + * main.cc (main): Fix the sys time reporting. + * workqueue.cc (Workqueue::find_and_run_task): Fix the sys time + reporting. + +2009-12-29 Sriraman Tallam <tmsriram@google.com> + + * options.cc (General_options::parse_version): Allow -v to exit + without an error if there is nothing to link. + +2009-12-29 Ian Lance Taylor <iant@google.com> + + * configure.ac: Set the MCMODEL_MEDIUM conditional to false if + using a version of gcc before 4.1. + * configure: Rebuild. + +2009-12-28 Chris Demetriou <cgd@google.com> + + * attributes.cc (Output_attributes_section_data::do_write): Use + std::vector::front rather than std::vector::data. + +2009-12-28 Ian Lance Taylor <iant@google.com> + + * symtab.h (class Symbol_table): Add enum Defined. + * resolve.cc (Symbol_table::should_override): Add defined + parameter. Change all callers. Test whether object is NULL + before calling a method on it. + (Symbol_table::report_resolve_problem): Add defined parameter. + Change all callers. + (Symbol_table::should_override_with_special): Likewise. + * symtab.cc (Symbol_table::define_in_output_data): Add defined + parameter. Change all callers. + (Symbol_table::do_define_in_output_data): Likewise. + (Symbol_table::define_in_output_segment): Likewise. + (Symbol_table::do_define_in_output_segment): Likewise. + (Symbol_table::define_as_constant): Likewise. + (Symbol_table::do_define_as_constant): Likewise. + * script.h (class Symbol_assignment): Add is_defsym parameter to + constructor; change all callers. + * script.cc (Script_options::add_symbol_assignment): Add is_defsym + parameter. Change all callers. Add is_defsym_ field. + (class Parser_closure): Add parsing_defsym parameter to + constructor; change all callers. Add parsing_defsym accessor + function. Add parsing_defsym_ field. + +2009-12-28 Ian Lance Taylor <iant@google.com> + + * gold.cc (queue_middle_tasks): Fix formatting. + * object.cc (Relobj::is_section_name_included): Likewise. + +2009-12-23 Ian Lance Taylor <iant@google.com> + + * i386.cc (Target_i386::do_calls_non_split): Recognize + -fsplit-stack prologue for a function with a static chain. + * x86_64.cc (Target_x86_64::do_calls_non_split): Recognize + -fsplit-stack prologue when using %r11. + +2009-12-21 Sriraman Tallam <tmsriram@google.com> + + * options.cc (General_options::parse_version): Make -v continue and do + the link like GNU ld does. + +2009-12-17 Rafael Avila de Espindola <espindola@google.com> + + * Makefile.am (CCFILES): Add timer.cc. + (HFILES): Add timer.h. + * configure.ac: Check for sysconf and times. + * main.cc: include timer.h. + (main): Use Timer instead of get_run_time. + * timer.cc: New. + * timer.h: New. + * workqueue.cc: include timer.h. + (Workqueue::find_and_run_task): + Report user, sys and wall time. + * Makefile.in: Regenerate. + * config.in: Regenerate. + * configure: Regenerate. + +2009-12-16 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::scan_sections_for_stubs): Exclude ICF-eliminated + sections. + * object.cc (Sized_relobj::do_finalize_local_symbols): Handle + relaxed input sections. + * output.cc (Output_section::find_relaxed_input_section): Change + return type to Output_relaxed_input_section pointer. Adjust code + for new type of relaxed_input_section_map_. + * output.h (Output_section::find_relaxed_input_section): Change + return type to Output_relaxed_input_section pointer. + (Output_section::Output_relaxed_input_section_by_input_section_map): + New type. + (Output_section::relaxed_input_section_map_): Change type to + Output_section::Output_relaxed_input_section_by_input_section_map. + * symtab.cc (Symbol_table::compute_final_value): Handle relaxed + input section. + +2009-12-15 Ian Lance Taylor <iant@google.com> + + * layout.cc (Layout::create_shstrtab): Only write out after input + sections if we are compressing debug sections. + +2009-12-15 Ian Lance Taylor <iant@google.com> + + * archive.cc (Archive::add_symbols): Only look up a symbol without + a version if there is, in fact, a version. + +2009-12-14 Ian Lance Taylor <iant@google.com> + + Revert -Wshadow changes, all changes from: + 2009-12-11 Doug Kwan <dougkwan@google.com> + 2009-12-11 Nick Clifton <nickc@redhat.com> + * configure.ac: Remove -Wshadow when setting WARN_CXXFLAGS. + +2009-12-11 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::do_finalize_sections): Fix build breakage + due to -Wshadow. + * attributes.cc (Object_attribute::size): Ditto. + (Attributes_section_data::size): Ditto. + (Attributes_section_data::Attributes_section_data): Ditto. + (Output_attributes_section_data::do_write): Ditto. + * attributes.h (Object_attribute::set_type): Ditto. + * testsuite/tls_test_main.cc (safe_lock, safe_unlock): Ditto. + +2009-12-11 Nick Clifton <nickc@redhat.com> + + * archive.cc: Fix shadowed variable warnings. + * arm.cc: Likewise. + * compressed_output.cc: Likewise. + * compressed_output.h: Likewise. + * configure: Likewise. + * dwarf_reader.cc: Likewise. + * dynobj.cc: Likewise. + * dynobj.h: Likewise. + * ehframe.cc: Likewise. + * ehframe.h: Likewise. + * errors.cc: Likewise. + * expression.cc: Likewise. + * fileread.cc: Likewise. + * fileread.h: Likewise. + * freebsd.h: Likewise. + * i386.cc: Likewise. + * icf.cc: Likewise. + * incremental.h: Likewise. + * layout.cc: Likewise. + * layout.h: Likewise. + * mapfile.cc: Likewise. + * merge.cc: Likewise. + * merge.h: Likewise. + * object.cc: Likewise. + * object.h: Likewise. + * options.h: Likewise. + * output.cc: Likewise. + * output.h: Likewise. + * parameters.cc: Likewise. + * plugin.cc: Likewise. + * powerpc.cc: Likewise. + * reduced_debug_output.cc: Likewise. + * reduced_debug_output.h: Likewise. + * reloc.cc: Likewise. + * reloc.h: Likewise. + * resolve.cc: Likewise. + * script-sections.cc: Likewise. + * script.cc: Likewise. + * script.h: Likewise. + * sparc.cc: Likewise. + * symtab.cc: Likewise. + * symtab.h: Likewise. + * target-select.cc: Likewise. + * target-select.h: Likewise. + * token.h: Likewise. + * workqueue.cc: Likewise. + * workqueue.h: Likewise. + * x86_64.cc: Likewise. + +2009-12-10 Doug Kwan <dougkwan@google.com> + + * arm.cc (attributes.h): New include. + (Arm_relobj::Arm_relobj): Initialize attributes_section_data_. + (Arm_relobj::~Arm_relobj): Delete object pointed by + attributes_section_data_. + (Arm_relobj::attributes_section_data): New method definition. + (Arm_relobj::attributes_section_data_): New data member declaration. + (Arm_dynobj::Arm_dynobj): Initialize attributes_section_data_. + (Arm_dynobj::~Arm_dynobj): Delete object pointed by + attributes_section_data_. + (Arm_dynobj::attributes_section_data): New method definition. + (Arm_dynobj::attributes_section_data_): New data member declaration. + (Target_arm::Target_arm): Initialize attributes_section_data_. Change + initialization value of may_use_blx_ to false. + (Target_arm::using_thumb2, Target_arm::using_thumb_only, + Target_arm::may_use_arm_nop, Target_arm::may_use_thumb2_nop): Use + object attributes to compute results instead of hard-coding. + (Target_arm::do_attribute_arg_type, Target_arm::do_attributes_order, + Target_arm::get_secondary_compatible_arch, + Target_arm::set_secondary_compatible_arch + Target_arm::tag_cpu_arch_combine, Target_arm::aeabi_enum_name, + Target_arm::tag_cpu_name_value, Target_arm::merge_object_attributes): + New method declarations. + (Target_arm::get_aeabi_object_attribute): New method definition. + (Target_arm::attributes_section_data_): New data member declaration. + (read_arm_attributes_section): New template definition. + (Arm_relobj::do_read_symbols): Read attributes section if it exists. + (Arm_dynobj::do_read_symbols): Ditto. + (Target_arm::do_finalize_sections): Merge attributes sections from + input. Check for BLX use after attributes section merging. + Fix __exidx_start and __exidx_end visibility. Create an + .ARM.attributes section if necessary. + (Target_arm::get_secondary_compatible_arch, + Target_arm::set_secondary_compatible_arch, + Target_arm::tag_cpu_arch_combine, Target_arm::aeabi_enum_name, + Target_arm::tag_cpu_name_value, Target_arm::merge_object_attributes, + Target_arm::do_attribute_arg_type, Target_arm::do_attributes_order): + New method definitions. + +2009-12-09 Ian Lance Taylor <iant@google.com> + + * plugin.cc (Plugin::load): Don't cast from void* to a function + pointer. + +2009-12-09 Ian Lance Taylor <iant@google.com> + + * dynobj.cc (Sized_dynobj::do_read_symbols): Clear version + information fields. + +2009-12-09 H.J. Lu <hongjiu.lu@intel.com> + + * testsuite/Makefile.am (two_file_shared_1_pic_2_test_DEPENDENCIES): + Replace two_file_shared_1.so with two_file_shared_2.so. + * testsuite/Makefile.in: Regenerated. + +2009-12-08 Doug Kwan <dougkwan@google.com> + + * Makefile.am (CCFILES): Add attributes.cc and int_encoding.cc. + (HFILES): Add attributes.h and int_encoding.h. + * Makefile.in: Regenerate. + * dwarf_reader.cc (read_unsigned_LEB_128, read_signed_LEB_128): Move + function definitions to int_encoding.cc + * dwarf_reader.h (read_unsigned_LEB_128, read_signed_LEB_128): Move + prototypes to int_encoding.h + * reduced_debug_output.cc (int_encoding.h): New include. + (write_unsigned_LEB_128, get_length_as_unsigned_LEB_128): Move + function definitions to int_encoding.cc + (insert_into_vector, read_from_pointer): Move template definitions to + int_encoding.h + * attributes.cc: New file. + * attributes.h: New file. + * int_encoding.cc: New file. + * int_encoding.h: New file. + +2009-12-07 Rafael Avila de Espindola <espindola@google.com> + + PR gold/11055 + * incremental-dump.cc (dump_incremental_inputs): New. + (main): Use dump_incremental_inputs. + +2009-12-07 H.J. Lu <hongjiu.lu@intel.com> + + PR gold/10893 + * i386.cc (Target_i386::Scan::globa): Use is_func instead of + checking elfcpp::STT_FUNC. + (Target_i386::Relocate::relocate): Likewise. + * x86_64.cc (Target_x86_64::Scan::global): Likewise. + + * symtab.cc (Symbol_table::sized_write_symbol): Turn IFUNC + symbols from shared libraries into normal FUNC symbols. + + * symtab.h (Symbol): Add is_func and use it. + +2009-12-05 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::arm_info): Initialize new fields + attributes_section and attributes_vendor. + * i386.cc (Target_i386::i386_info): Same. + * object.cc (Sized_relobj::do_layout): Skip attribute section. + * gold/powerpc.cc (Target_powerpc::powerpc_info): Initialize new + fields attributes_section and attributes_vendor. + * sparc.cc (Target_sparc::sparc_info): Same. + * target.h (Target::attributes_section, Target::attributes_vendor, + Target::is_attributes_section, Target::attribute_arg_type, + Target::attributes_order): New method definitions. + (Target::Target_info::attributes_section, + Target::Target_info::attributes_vendor): New fields. + (Target::do_attribute_arg_type, Target::do_attributes_order): New + virtual method definitions. + * x86_64.cc (Target_x86_64::x86_64_info): Initialize new fields + attributes_section and attributes_vendor. + * testsuite/testfile.cc (Target_test::test_target_info): Same. + +2009-12-05 Doug Kwan <dougkwan@google.com> + + * arm.cc: Update comments about interworking and stub generation. + (Target_arm::Relocate::reloc_is_non_pic): Update list of relocations + considered as non-PIC. + (Arm_relocate_functions::base_abs): Fix formatting. + (Arm_relocate_functions::got_prel): Fix comment. Change interface + of function to use GOT entry address instead of offset. + (Target_arm::Scan::global): Issue an error if a symbol would need a + PLT does not get one because it is untyped. Remove code to create + dynamic symbols for relative branches. + (Target_arm::Relocate::relocate: Use 0 instead of false since function + takes unsigned integer instead of boolean. + +2009-12-05 H.J. Lu <hongjiu.lu@intel.com> + + * testsuite/Makefile.am (constructor_test_LDADD): New. Empty. + (two_file_test_LDADD): Likewise. + (common_test_1_LDADD): Likewise. + (exception_test_LDADD) Likewise. + (weak_test_LDADD): Likewise. + (many_sections_test_LDADD): Likewise. + (initpri1_LDADD): Likewise. + (script_test_1_LDADD): Likewise. + (script_test_2_LDADD): Likewise. + (justsyms_LDADD): Likewise. + (binary_test_LDADD): Likewise. + (large_LDADD): Likewise. + * testsuite/Makefile.in: Regenerated. + +2009-12-04 H.J. Lu <hongjiu.lu@intel.com> + + * resolve.cc (symbol_to_bits): Treat STB_GNU_UNIQUE as STB_GLOBAL. + (Symbol_table::override_with_special): Likewise. + (Symbol_table::add_from_object): Likewise. + +2009-12-04 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (Incremental_inputs::sized_create_inputs_section_data): + Don't set the data_offset twice. - * po/gold.pot: Regenerate. +2009-12-04 Rafael Avila de Espindola <espindola@google.com> + + * testsuite/Makefile.in: Regenerate. + +2009-12-03 Doug Kwan <dougkwan@google.com> + + * arm.cc: Remove comment about missing .ARM.exidx section symbols. + (Target_arm::do_finalize_sections): Add parameter for symbol table + pointer. Add __exidx_start and __exidx_end symbols as appropriate. + * i386.cc (Target_i386::do_finalize_sections): Add an additional + parameter for symbol table pointer. + * layout.cc (Layout::finalize): Call Target::finalize_sections with + an additional parameter for a pointer to symbol table. + * powerpc.cc (Target_powerpc::do_finalize_sections): Add an additional + parameter for a symbol table pointer. + * sparc.cc (Target_sparc::do_finalize_sections): Ditto. + * target.h (Target::finalize_sections, Target::do_finalize_sections): + Ditto. + * x86_64.cc (Target_x86_64::do_finalize_sections): Add an additional + parameter for a symbol table pointer. + +2009-12-03 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (Incremental_inputs_header) + (Incremental_inputs_header_write, Incremental_inputs_entry) + (Incremental_inputs_entry_write): Move ... + * incremental.h (Incremental_inputs_header) + (Incremental_inputs_header_write, Incremental_inputs_entry) + (Incremental_inputs_entry_write): here. + +2009-12-02 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (make_sized_incremental_binary): Set the target. + Error if it is incompatible. + * output.h (Output_file): Add filename method. + +2009-12-02 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (Incremental_inputs_entry): Remove unused argument + from the get_* methods. + +2009-12-02 Rafael Avila de Espindola <espindola@google.com> + + * incremental-dump.cc (main): Check that the offeset of a script is 0. + * incremental.cc (Incremental_inputs::sized_create_inputs_section_data): + Write 0 for the data_offset of scripts. + +2009-12-02 Rafael Avila de Espindola <espindola@google.com> + + * testsuite/Makefile.am: Add the incremental_test.sh test. + * testsuite/incremental_test.sh: New. + * testsuite/incremental_test_1.c: New. + * testsuite/incremental_test_2.c: New. + +2009-12-01 Rafael Avila de Espindola <espindola@google.com> + + * incremental-dump.cc (main): Fix typos. + +2009-11-27 Rafael Avila de Espindola <espindola@google.com> + + PR gold/11025 + * incremental-dump.cc (main): Use llu to print 64 bit values. + +2009-11-26 Per Øyvind Karlsen <peroyvind@mandriva.org> + H.J. Lu <hongjiu.lu@intel.com> + + * Makefile.am (incremental_dump_DEPENDENCIES): Add $(THREADSLIB) + $(LIBDL). + (incremental_dump_LDADD): Likewise. + * Makefile.in: Regenerated. + +2009-11-25 Doug Kwan <dougkwan@google.com> + + Revert: + + 2009-11-25 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Target_arm): Move method definition + outside of class definition. Add code to handle + --target1-rel, --target1-abs and --target2= options. + (Target_arm::get_reloc_reloc_type): Change method to be + non-static and const. + (Target_arm::target1_is_rel_, Target_arm::target2_reloc_): + New data member declaration. + (Target_arm::Scan::local, Target_arm::Scan::global, + Target_arm::Relocate::relocate, + Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Adjust call to Target_arm::get_real_reloc_type. + (Target_arm::get_real_reloc_type): Use command line options + to determine real types of R_ARM_TARGET1 and R_ARM_TARGET2. + * options.h (--target1-rel, --target1-abs, --target2): New + ARM-only options. + +2009-11-25 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Target_arm): Move method definition outside of + class definition. Add code to handle --target1-rel, --target1-abs + and --target2= options. + (Target_arm::get_reloc_reloc_type): Change method to be non-static + and const. + (Target_arm::target1_is_rel_, Target_arm::target2_reloc_): New data + member declaration. + (Target_arm::Scan::local, Target_arm::Scan::global, + Target_arm::Relocate::relocate, + Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): Adjust + call to Target_arm::get_real_reloc_type. + (Target_arm::get_real_reloc_type): Use command line options to + determine real types of R_ARM_TARGET1 and R_ARM_TARGET2. + * options.h (--target1-rel, --target1-abs, --target2): New ARM-only + options. + +2009-11-25 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::may_use_thumb2_nop): New method definition. + (Arm_relocate_functions::thumb_branch_common): New metod declaration. + (Arm_relocate_functions::abs12, Arm_relocate_functions::abs16): Fix + formatting. + (Arm_relocate_functions::thm_call): Replace body with a call to + Arm_relocate_functions::thumb_branch_common. + (Arm_relocate_functions::thm_jump24, + Arm_relocate_functions::thm_xpc22): New method definitions. + (Arm_relocate_functions::thumb_branch_common): New method definition. + (Reloc_stub::stbu_type_for_reloc): Fix incorrect uses of bit-wise-or + operator. + (Target_arm::Relocate::relocate): Adjust call to thm_call. + Add code to handle R_ARM_THM_XPC22 and R_ARM_THM_JUMP24. + +2009-11-24 Rafael Avila de Espindola <espindola@google.com> + + * Makefile.am: Build incremental-dump + * Makefile.in: Regenerate. + * incremental-dump.cc: New. + * incremental.cc (Incremental_inputs_header_data, + Incremental_inputs_entry_data): Move to incremental.h + * incremental.h: (Incremental_inputs_header_data, + Incremental_inputs_entry_data): Move from incremental.cc + +2009-11-24 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (Incremental_inputs_header, + Incremental_inputs_header_write, Incremental_inputs_entry, + Incremental_inputs_entry_write): Add a typedef with the data type. + +2009-11-24 Rafael Avila de Espindola <espindola@google.com> + + * incremental.cc (Incremental_inputs_header, + Incremental_inputs_header_write, Incremental_inputs_entry, + Incremental_inputs_entry_write): Update comment about which + type has the filed descriptions. + +2009-11-15 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::may_use_arm_nop): New method definition. + (Arm_relocate_functions::arm_branch_common): Change method defintion + in class definition to a method declaration and update list of formal + parameters. + (Arm_relocate_functions::plt32, Arm_relocate_functions::call, + Arm_relocation_functions::jump24): Adjust call to + Arm_relocate_functions::arm_branch_common. Update list of formal + parameters. + (Arm_relocate_functions::xpc25): New method definition. + (Arm_relocate_functions::arm_branch_common): Move method defintion + out from class definition. Use stubs for mode-switching and extending + branch ranges. + (Target_arm::Relocate::relocate): Handle weakly-undefined symbols + specially. Change code to enable use of stubs in ARM branches. + +2009-11-10 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::do_relocate_sections): Remove options parameter + in method declaration. + (Target_arm::relocate_stub): New method declaration. + (Target_arm::default_target): Change to return a pointer instead of + a const reference. + (Reloc_stub::stub_type_for_reloc): Adjust for the change in + Target_arm::default_target. + (Arm_Relobj::do_relocate_sections): Remove options paramater in + method definition. + (Target_arm::relocate_section): Adjust view. + (Target_arm::relocate_stub): New method definition. + +2009-11-10 Doug Kwan <dougkwan@google.com> + + * i386.cc (Target_i386::do_calls_non_split): Add a cast to avoid + a format warning. + * incremental.cc (open_incremental_binary): Initialized local + variables to avoid warnings. + * object.cc (make_elf_object): Ditto. + * x86_64.cc (Target_x86_64::do_calls_non_split): Add a cast to avoid + a format warning. + +009-11-09 H.J. Lu <hongjiu.lu@intel.com> + + PR gold/10930 + * testsuite/plugin_test.c: Include "config.h". + +2009-11-09 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::fake_relnum_for_stubs): New constant. + (arm_symbol_value): Remove. + (Arm_relocate_functions::arm_branch_common, + Arm_relocate_functions::abs8, Arm_relocate_functions::thm_abs5, + Arm_relocate_functions::abs12, Arm_relocate_functions::abs16, + Arm_relocate_functions::abs32, Arm_relocate_functions::rel32, + Arm_relocate_functions::thm_call, Arm_relocate_functions::plt32, + Arm_relocate_functions::call, Arm_relocate_functions::jump24, + Arm_relocate_functions::prel31, Arm_relocate_functions::mov_abs_nc, + Arm_relocate_functions::movt_abs, Arm_relocate_functions::movw_abs_nc, + Arm_relocate_functions::thm_mobw_abs_nc, + Arm_relocate_functions::thm_mov_abs, + Arm_relocate_functions::movw_prel_nc, + Arm_relocate_functions::thm_movt_abs, + Arm_relocate_functions::movt_prel, + Arm_relocate_functions::thm_movw_prel_nc, + Arm_relocate_functions::thm_movt_prel): Adjust callers of the above. + (Target_arm::Relocate::relocate): Only decompose address into two + parts if relocation type uses the thumb-bit and pass the actual + bit instead of a flag indicating that the thumb-bit is used. Adjust + calls to methods in Arm_relocate_functions for this change. + +2009-11-08 Ian Lance Taylor <iant@google.com> + + PR 10925 + * reloc.cc: Instantiate + Sized_relobj::initialize_input_to_output_maps and + Sized_relobj:free_input_to_output_maps. + +2009-11-06 Ian Lance Taylor <iant@google.com> + + PR 10876 + * defstd.cc (in_segment): Set only_if_ref true for "end". + +2009-11-06 Doug Kwan <dougkwan@google.com> + + * arm.cc (class Reloc_stub): Correct a comment. + (Target_arm::Target_arm): Initialize arm_input_section_map_. + (Target_arm::scan_section_for_stubs): New method declaration. + (Target_arm::do_make_elf_object, Target_arm::do_make_output_section): + Change methods from private to protected. + (Target_arm::do_may_relax): New method definition. + (Target_arm::do_relax, Target_arm::group_sections, + Target_arm::scan_reloc_for_stub, + Target_arm::scan_reloc_section_for_stubs): New method declarations. + (Target_arm::arm_input_section_map_): New data member declaration. + (Target_arm::scan_reloc_for_stub, + Target_arm::scan_reloc_section_for_stubs, + Target_arm::scan_section_for_stubs, Target_arm::group_sections, + Target_arm::do_relax): New method definitions. + +2009-11-06 Mikolaj Zalewski <mikolaj@google.com> + + * configure.ac: Check for (struct stat)::st_mtim + * fileread.cc (File_read::get_mtime): Use st_mtim if available. + * config.in: Regenerate. + * configure: Regenerate. + +2009-11-05 Ian Lance Taylor <iant@google.com> + + PR 10910 + * output.cc (Output_segment::add_output_section): Add missing + return statement. + +2009-11-04 Ian Lance Taylor <iant@google.com> + + PR 10880 + * object.h (class Object): Add is_needed and set_is_needed + methods. Add is_needed_ field. Make bool fields into bitfields. + * symtab.cc (Symbol_table::set_dynsym_indexes): If a symbol is + defined in a dynamic object and referenced by a regular object, + set is_needed for the dynamic object. + * layout.cc (Layout::finish_dynamic_section): Don't add DT_NEEDED + if the file is marked with as_needed and it is not needed. + +2009-11-04 Ian Lance Taylor <iant@google.com> + + PR 10887 + * arm.cc (Target_arm::do_finalize_sections): Don't add dynamic + tags if data is discarded by linker script. + * i386.cc (Target_i386::do_finalize_sections): Likewise. + * powerpc.cc (Target_powerpc::do_finalize_sections): Likewise. + * sparc.cc (Target_sparc::do_finalize_sections): Likewise. + * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. + +2009-11-04 Ian Lance Taylor <iant@google.com> + + * layout.cc (Layout::get_output_section): Add is_interp and + is_dynamic_linker_section parameters. Change all callers. + (Layout::choose_output_section): Likewise. + (Layout::make_output_section): Likewise. + (Layout::add_output_section_data): Add is_dynamic_linker_section + parameter. Change all callers. + * layout.h (class Layout): Update declarations. + * output.h (class Output_section): Add is_interp, set_is_interp, + is_dynamic_linker_section, set_is_dynamic_linker_section methods. + Add is_interp_, is_dynamic_linker_section_ fields. Change + generate_code_fills_at_write_ to a bitfield. + * output.cc (Output_section::Output_sections): Initialize new + fields. + (Output_segment::add_output_section): Add do_sort parameter. + Change all callers. + +2009-11-03 Ian Lance Taylor <iant@google.com> + + PR 10860 + * options.h (class General_options): Add --warn-common. + * resolve.cc (Symbol_table::resolve): Handle --warn-common when + merging two common symbols. + (Symbol_table::should_override): Handle --warn-common when merging + a common symbol with a defined symbol. Use report_resolve_problem + for multiple definitions. + (Symbol_table::report_resolve_problem): New function. + * symtab.h (class Symbol_table): Declare report_resolve_problem. + +2009-11-03 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::Target_arm): Initialize stub_tables_ and + stub_factory_. + (Target_arm::stub_factory): New method definition. + (Target_arm::new_arm_input_section, + Target_arm::find_arm_input_section, Target_arm::new_stub_table, + Target_arm::reloc_uses_thumb_bit): New method declarations. + (Target_arm::Stub_table_list, Target_arm::Arm_input_section_map): + New type definitions. + (Target_arm::stub_tables_, Target_arm::stub_factory_): New data + member declarations. + (Target_arm::reloc_uses_thumb_bit, Target_arm::new_arm_input_section, + Target_arm::find_arm_input_section, Target_arm::new_stub_table): + New method definitions. + +2009-11-03 Ian Lance Taylor <iant@google.com> + + * options.h (class General_options): Add --warn_constructors. + +2009-11-03 Ian Lance Taylor <iant@google.com> + + PR 10893 + * defstd.cc (in_section): Add entries for __rel_iplt_start, + __rel_iplt_end, __rela_iplt_start, __rela_iplt_end, and __stack. + +2009-11-03 Ian Lance Taylor <iant@google.com> + + PR 10895 + * po/Make-in ($(srcdir)/$(PACKAGE).pot): Pass -C and + --msgid-bugs-address. + (install-pdf): New target. + (install-data_yes): Look up one directory to find mkinstalldirs. + +2009-11-03 H.J. Lu <hongjiu.lu@intel.com> + + * po/Make-in (.po.gmo): Don't generate .gmo files in source + tree. + +2009-10-30 Doug Kwan <dougkwan@google.com> + + * arm.cc (Stub_addend_reader): Fix bug in previouls check-in. + +2009-10-30 Doug Kwan <dougkwan@google.com> + + * arm.cc (Stub_addend_reader): New struct template definition + and partial specializations. + (Stub_addend_reader::operator()): New method definition for a + partially specialized template. + +2009-10-30 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj::processor_specific_flags): New method + definition. + (Arm_relobj::do_read_symbols): New method declaration. + (Arm_relobj::processor_specific_flags_): New data member declaration. + (Arm_dynobj): New class definition. + (Target_arm::do_finalize_sections): Add input_objects parameter. + (Target_arm::do_adjust_elf_header): New method declaration. + (Target_arm::are_eabi_versions_compatible, + (Target_arm::merge_processor_specific_flags): New method declaration. + (Target_arm::do_make_elf_object): New overloaded method definitions + and declaration. + (Arm_relobj::do_read_symbols): New method definition. + (Arm_dynobj::do_read_symbols): Ditto. + (Target_arm::do_finalize_sections): Add input_objects parameters. + Merge processor-specific flags from all input objects. + (Target_arm::are_eabi_versions_compatible, + Target_arm::merge_processor_specific_flags, + Target_arm::do_adjust_elf_header, Target_arm::do_make_elf_object): + New method definitions. + * i386.cc (Target_i386::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + * layout.cc (Layout::finalize): Pass input objects to target's. + finalize_sections function. + * output.cc (Output_file_header::do_sized_write): Set ELF file + header's processor-specific flags. + * powerpc.cc (Target_powerpc::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + * sparc.cc (Target_sparc::do_finalize_sections): Same. + * target.h (Input_objects): New forward class declaration. + (Target::processor_specific_flags, + Target::are_processor_specific_flags_sect): New method definitions. + (Target::finalize_sections): Add input_objects parameter. + (Target::Target): Initialize processor_specific_flags_ and + are_processor_specific_flags_set_. + (Target::do_finalize_sections): Add unnamed Input_objects pointer type + parameter. + (Target::set_processor_specific_flags): New method definition. + (Target::processor_specific_flags_, + Target::are_processor_specific_flags_set_): New data member + declarations. + * x86_64.cc (Target_x86_64::do_finalize_sections): Add unnamed + Input_objects pointer type parameter. + +2009-10-30 Doug Kwan <dougkwan@google.com> + + * arm.cc: Use Arm_address instead of elfcpp::Elf_types<32>::Elf_Addr. + +2009-10-28 Ian Lance Taylor <iant@google.com> + + * object.h (class Relobj): Drop options parameter from + gc_process_relocs, scan_relocs, relocate, do_gc_process_relocs, + do_scan_relocs, do_relocate. Change all callers. + (class Sized_relobj): Drop options parameters from + do_gc_process_relocs, do_scan_relocs, do_relocate, + do_relocate_sections, relocate_sections, emit_relocs_scan, + emit_relocs_scan_reltype. Change all callers. + (struct Relocate_info): Remove options field and all references to + it. + * reloc.h (class Read_relocs): Remove options constructor + parameter and options_ field. Change all callers. + (class Gc_process_relocs, class Scan_relocs): Likewise. + (class Relocate_task): Likewise. + * target-reloc.h (scan_relocs): Remove options parameter. Change + all callers. + (scan_relocatable_relocs): Likewise. + * target.h (class Sized_target): Remove options parameter from + gc_process_relocs, scan_relocs, scan_relocatable_relocs. Change + all callers. + * gc.h (gc_process_relocs): Remove options parameter. Change all + callers. + * arm.cc: Update functions to remove options parameters. + * i386.cc: Likewise. + * powerpc.cc: Likewise. + * sparc.cc: Likewise. + * x86_64.cc: Likewise. + * testsuite/testfile.cc: Likewise. + +2009-10-28 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_relobj): New class definition. + (Arm_relobj::scan_sections_for_stubs, + Arm_relobj::do_count_local_symbols, Arm_relobj::do_relocate_sections): + New method definitions. + +2009-10-28 Cary Coutant <ccoutant@google.com> + + * plugin.h (Plugin::Plugin): Initialize cleanup_done_. + (Plugin::cleanup_done_): New member. + (Plugin_manager::Plugin_manager): Remove cleanup_done_. + (Plugin_manager::cleanup_done_): Remove. + (Plugin_manager::add_input_file): Edit error message. + * plugin.cc (Plugin::cleanup): Test and set cleanup_done_. + (Plugin_manager::cleanup): Remove use of cleanup_done_. + +2009-10-27 Mikolaj Zalewski <mikolajz@google.com> + + * fileread.cc: (File_read::View::~View): Use the new + data_ownership_ filed. + (File_read::~File_read): Dispose the new whole_file_view_. + (File_read::open): Mmap the whole file if needed. + (File_read::open): Use whole_file_view_ instead of contents_. + (File_read::find_view): Use whole_file_view_ if applicable. + (File_read::do_read): Use whole_file_view_ instead of contents_. + (File_read::make_view): Use whole_file_view_ instead of contents_, + update File_read::View::View call. + (File_read::find_or_make_view): Update File_read::View::View + call. + * fileread.h: (File_read::File_read): Initialize whole_file_view_, + remove contents_ + (File_read::View::Data_ownership): New enum. + (File_read::View::View): Replace bool mapped_ with Data_ownership + argument. + (File_read::View::mapped_): Remove (replaced by data_ownership_). + (File_read::View::data_ownership_): New field. + (File_read::contents_): Remove (replaced by whole_file_view_). + (File_read::whole_file_view_): New field. + * options.h (class General_options): Add --keep-files-mapped. + +2009-10-27 Cary Coutant <ccoutant@google.com> + + * symtab.cc (add_from_pluginobj): Pass correct value for is_ordinary. + * testsuite/Makefile.am (plugin_test_5): New test case. + * testsuite/Makefile.in: Regenerate. + +2009-10-25 Doug Kwan <dougkwan@google.com> + + * object.h (Sized_relobj::View_size, Sized_relobj::Views): Change + from private to protected to allow access by child class. + (Sized_relobj::do_relocate_sections): New method declaration. + (Sized_relobj::relocate_sections): Virtualize. + * reloc.cc (Sized_relobj::do_relocate_sections): Rename from + Sized_relobj::relocate_sections. Instantiate template explicitly + for different target sizes and endianity. + +2009-10-24 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_output_section, Arm_relobj): Forward class declarations. + (Arm_input_section::as_arm_input_section): New method. + (Arm_output_section): New class definition. + (Arm_output_section::create_stub_group, + Arm_output_section::group_sections): New method definitions. + +2009-10-22 Doug Kwan <dougkwan@google.com> + + * arm.cc (Arm_input_section): New class definition. + (Arm_input_section::init, Arm_input_section:do_write, + Arm_input_section::set_final_data_size, + Arm_input_section::do_reset_address_and_file_offset): New method + definitions. + +2009-10-21 Doug Kwan <dougkwan@google.com> + + * arm.cc (Stub_table, Arm_input_section): New forward class + declarations. + (Stub_table): New class defintion. + (Stub_table::add_reloc_stub, Stub_table::relocate_stubs + Stub_table::do_reset_address_and_file_offset, Stub_table::do_write): + New method definition. + +2009-10-21 Doug Kwan <dougkwan@google.com> + + * arm.cc: Update copyright comments. + (Target_arm): New forward class template declaration. + (Arm_address): New type. + (ARM_MAX_FWD_BRANCH_OFFSET, ARM_MAX_BWD_BRANCH_OFFSET, + THM_MAX_FWD_BRANCH_OFFSET, THM_MAX_BWD_BRANCH_OFFSET, + THM2_MAX_FWD_BRANCH_OFFSET, THM2_MAX_BWD_BRANCH_OFFSET): New + constants. + (Insn_template): Same. + (DEF_STUBS): New macro. + (Stub_type): New enum type. + (Stub_template): New class definition. + (Stub): Same. + (Reloc_stub): Same. + (Stub_factory): Same. + (Target_arm::Target_arm): Initialize may_use_blx_ and + should_force_pic_veneer_. + (Target_arm::may_use_blx, Target_arm::set_may_use_blx, + Target_arm::should_force_pic_veneer, + Target_arm::set_should_force_pic_veneer, Target_arm::using_thumb2, + Target_arm::using_thumb_only, Target_arm:;default_target): New + method defintions. + (Target_arm::may_use_blx_, Target_arm::should_force_pic_veneer_): + New data member declarations. + (Insn_template::size, Insn_template::alignment): New method defintions. + (Stub_template::Stub_template): New method definition. + (Reloc_stub::Key::name, Reloc_stub::stub_type_for_reloc, + Reloc_stub::do_fixed_endian_write, Reloc_stub::do_write): Same. + (Stub_factory::Stub_factory): New method definition. + * gold.h (string_hash): New template. + * output.h (Input_section_specifier::hash_value): Use + gold::string_hash. + (Input_section_specifier::string_hash): Remove. + * stringpool.cc (Stringpool_template::string_hash): Use + gold::string_hash. + +2009-10-20 Doug Kwan <dougkwan@google.com> + + * object.cc (Sized_relobj::do_finalize_local_symbols): Handle section + symbols of relaxed input sections. + * output.h (Output_section::find_relaxed_input_section): Make + method public. + +2009-10-16 Doug Kwan <dougkwan@google.com> + + * dynobj.cc (Versions::Versions): Initialize version_script_. + Only insert base version symbol definition for a shared object + if version script defines any version versions. + (Versions::define_base_version): New method definition. + (Versions::add_def): Check that base version is not needed. + (Versions::add_need): Define base version lazily. + * dynobj.h (Versions::define_base_version): New method declaration. + (Versions::needs_base_version_): New data member declaration. + * testsuite/Makefile.am (check_SCRIPTS): Add no_version_test.sh + (check_DATA): Add no_version_test.stdout. + (libno_version_test.so, no_version_test.o no_version_test.stdout): + New make rules. + * testsuite/Makefile.in: Regenerate. + * testsuite/no_version_test.c: New file. + * testsuite/no_version_test.sh: Ditto. + +2009-10-16 Doug Kwan <dougkwan@google.com> + + * expression.cc (class Segment_start_expression): New class definition. + (Segment_start_expression::value): New method definition. + (script_exp_function_segment_start): Return a new + Segment_start_expression. + * gold/script-c.h (script_saw_segment_start_expression): New function + prototype. + * script-sections.cc (Script_sections::Script_sections): Initialize + SAW_SEGMENT_START_EXPRESSION_ to false. + (Script_sections::set_section_addresses): Use -Ttext, -Tdata + and -Tbbs options to specify section addresses if given in + command line and no SEGMENT_START expression is seen in a script. + * script-sections.h (Script_sections::saw_segment_start_expression, + Script_sections::set_saw_segment_start_expression): New method + definition. + (Script_sections::saw_segment_start_expression_): New data member + declaration. + * script.cc (script_saw_segment_start_expression): New function. + * yyscript.y (SEGMENT_START): Call script_saw_segment_start_expression. + * testsuite/Makefile.am (check_SCRIPTS): Add script_test_6.sh, + script_test_7.sh and script_test_8.sh. + (check_DATA): Add script_test_6.stdout, script_test_7.stdout and + script_test_8.stdout. + (MOSTLYCLEANFILES): Add script_test_6, script_test_7 and script_test_8. + (script_test_6, script_test_6.stdout, script_test_7, + script_test_7.stdout, script_test_8, script_test_8.stdout): New rules. + * Makefile.in: Regenerate. + * testsuite/script_test_6.sh: New file. + * testsuite/script_test_6.t: Same. + * testsuite/script_test_7.sh: Same. + * testsuite/script_test_7.t: Same. + * testsuite/script_test_8.sh: Same. + +2009-10-16 Doug Kwan <dougkwan@google.com> + + * output.cc (Output_segment::set_section_list_address): Cast + expressions to unsigned long long type to avoid format warnings. + +2009-10-15 Ian Lance Taylor <iant@google.com> + + * script.cc (Script_options::add_symbol_assignment): Always add a + dot assignment to script_sections_. + * script-sections.cc (Script_sections::add_dot_assignment): + Initialize if necessary. + + * layout.cc (Layout::relaxation_loop_body): Don't crash if we see + program headers with no load segment if there is a linker script. + + * layout.cc (Layout::set_segment_offsets): Align the file offset + to the segment aligment for -N or -n with no load segment. + * output.cc (Output_segment::add_output_section): Don't crash if + the first section is a TLS section. + (Output_segment::set_section_list_addresses): Print an error + message if the address moves backward in a linker script. + * script-sections.cc + (Output_section_element_input::set_section_addresses): Don't + increase *dot_value for a SHF_TLS/SHT_NOBITS section. + (Orphan_output_section::set_section_addresses): Likewise. + +2009-10-15 Doug Kwan <dougkwan@google.com> + + * layout.cc (Layout::finish_dynamic_section): Generate tags + DT_FINI_ARRAY, DT_FINI_ARRAYSZ, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, + DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ as needed. If -Bsymbolic is + used, add DT_SYMBOLIC and set DF_SYMBOLIC in DT_FLAGS. + +2009-10-14 Ian Lance Taylor <iant@google.com> + + * object.h (class Relocate_info): Add reloc_shdr and data_shdr + fields. + * object.cc (Sized_relobj::relocate_sections): Set reloc_shdr and + data_shdr fields of relinfo. + * i386.cc (class Target_i386::Relocate): Remove ldo_addrs_ field. + (Target_i386::Relocate::relocate_tls): Don't call fix_up_ldo. For + R_386_TLS_LDO_32, adjust based on section flags. + (Target_i386::Relocate::fix_up_ldo): Remove. + +2009-10-13 Ian Lance Taylor <iant@google.com> + + Add support for -pie. + * options.h (class General_options): Add -pie and + --pic-executable. + (General_options::output_is_position_independent): Test -pie. + (General_options::output_is_executable): Return true if not shared + and not relocatable. + (General_options::output_is_pie): Remove. + * options.cc (General_options::finalize): Reject incompatible uses + of -pie. + * gold.cc (queue_middle_tasks): A -pie link is not static. + * symtab.h (Symbol::needs_plt_entry): Return false if -pie. + * symtab.cc (Symbol::final_value_is_known): Return false if + output_is_position_independent. + * layout.cc (Layout::set_segment_offsets): Start at address 0 if + output_is_position_independent. + * output.cc (Output_file_header::do_sized_write): Use ET_DYN if + output_is_position_independent. + * i386.cc (Output_data_plt_i386::do_write): Use the PIC PLT if + output_is_position_independent. + * testsuite/Makefile.am (check_PROGRAMS): Add basic_pie_test and + two_file_pie_test. + (basic_pie_test.o, basic_pie_test): New targets. + (two_file_test_1_pie.o, two_file_test_1b_pie.o): New targets. + (two_file_test_2_pie.o, two_file_test_main_pie.o): New targets. + (two_file_pie_test): New target. + * testsuite/Makefile.in: Rebuild. + * README: Remove note saying that -pie is not supported. + +2009-10-13 Bernhard Reutner-Fischer <aldot@gcc.gnu.org> + + * options.h (class General_options): Add -init and -fini. + * layout.cc (Layout::finish_dynamic_section): Emit + given init and fini functions. + +2009-10-13 Sriraman Tallam <tmsriram@google.com> + + * gc.h (gc_process_relocs): Check if icf is enabled using new + function. + * gold.cc (queue_initial_tasks): Likewise. + (queue_middle_tasks): Likewise. + * object.cc (do_layout): Likewise. + * symtab.cc (is_section_folded): Likewise. + * main.cc (main): Likewise. + * reloc.cc (Read_relocs::run): Likewise. + (Sized_relobj::do_scan_relocs): Likewise. + * icf.cc (is_function_ctor_or_dtor): New function. + (Icf::find_identical_sections): Check if function is ctor or dtor when + safe icf is chosen. + * options.h (General_options::icf): Change option to be an enum. + (Icf_status): New enum. + (icf_enabled): New method. + (icf_safe_folding): New method. + (set_icf_status): New method. + (icf_status_): New variable. + * (options.cc) (General_options::finalize): Set icf_status_. + * testsuite/Makefile.am: Add commands to build icf_safe_test. Modify + icf_test and icf_keep_unique_test to use the --icf enum flag. + * testsuite/icf_safe_test.sh: New file. + * testsuite/icf_safe_test.cc: New file. + +2009-10-12 Sriraman Tallam <tmsriram@google.com> + + * symtab.h: Check for GOLD_SYMTAB_H before header includes. Remove + includes to gc.h and icf.h. + * arm.cc: Include gc.h. + * gold.cc: Likewise. + * i386.cc: Likewise. + * powerpc.cc: Likewise. + * sparc.cc: Likewise. + * x86_64.cc: Likewise. + * gc.h: Include icf.h. + +2009-10-11 Ian Lance Taylor <iant@google.com> + + * plugin.cc: Include "gold.h" before other header files. + +2009-10-10 Chris Demetriou <cgd@google.com> + + * options.h (Input_file_argument::Input_file_type): New enum. + (Input_file_argument::is_lib_): Replace with... + (Input_file_argument::type_): New member. + (Input_file_argument::Input_file_argument): Take Input_file_type + 'type' rather than boolean 'is_lib' as second argument. + (Input_file_argument::is_lib): Use type_. + (Input_file_argument::is_searched_file): New function. + (Input_file_argument::may_need_search): Handle is_searched_file. + * options.cc (General_options::parse_library): Support -l:filename. + (General_options::parse_just_symbols): Update for Input_file_argument + changes. + (Command_line::process): Likewise. + * archive.cc (Archive::get_file_and_offset): Likewise. + * plugin.cc (Plugin_manager::release_input_file): Likewise. + * script.cc (read_script_file, script_add_file): Likewise. + * fileread.cc (Input_file::Input_file): Likewise. + (Input_file::will_search_for): Handle is_searched_file. + (Input_file::open): Likewise. + * readsyms.cc (Read_symbols::get_name): Likewise. + * testsuite/Makefile.am (searched_file_test): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/searched_file_test.cc: New file. + * testsuite/searched_file_test_lib.cc: New file. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + Ian Lance Taylor <iant@google.com> + + * descriptor.cc: Include <cstdio> and "binary-io.h". + (Descriptors::open): Open the files in binary mode always. + * script.cc (Lex::get_token): Treat \r as whitespace. + +2009-10-09 Ian Lance Taylor <iant@google.com> + + * testsuite/retain_symbols_file_test.sh: Don't test for __tcf_0. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + Ian Lance Taylor <iant@google.com> + + * configure.ac: Check for readv function also. + * fileread.cc (readv): Define if not HAVE_READV. + * fileread.h (File_read:: max_readv_entries): Set to 1 if readv + does not exist. + * config.in: Regenerate. + * configure: Regenerate. + +2009-10-09 Doug Kwan <dougkwan@google.com> + + * layout.cc (Layout::make_output_section): Call target hook to make + ordinary output section. + (Layout::finalize): Adjust parameter list of call the + Target::may_relax(). + * layout.h (class Layout::section_list): New method. + * merge.h (Output_merge_base::entsize): Change visibility to public. + (Output_merge_base::is_string, Output_merge_base::do_is_string): + New methods. + (Output_merge_string::do_is_string): New method. + * object.cc (Sized_relobj::do_setup): renamed from + Sized_relobj::set_up. + * object.h (Sized_relobj::adjust_shndx, + Sized_relobj::initializ_input_to_output_maps, + Sized_relobj::free_input_to_output_maps): Change visibilities to + protected. + (Sized_relobj::setup): Virtualize. + (Sized_relobj::do_setup): New method declaration. + (Sized_relobj::invalidate_section_offset, + Sized_relobj::do_invalidate_section_offset): New method decfinitions. + (Sized_relobj::elf_file, Sized_relobj::local_values): New methods. + * options.cc (parse_int): New function. + * options.h (parse_int): New declaration. + (DEFINE_int): New macro. + (stub_group_size): New option. + * output.cc (Output_section::Output_section): Initialize memebers + merge_section_map_, merge_section_by_properties_map_, + relaxed_input_section_map_, is_relaxed_input_section_map_valid_. + (Output_section::add_input_section): Handled deferred code-fill + generation and remove an old comment. + (Output_section::add_relaxed_input_section): New method definition. + (Output_section::add_merge_input_section): Use merge section by + properties map to speed to search. Update merge section maps + as appropriate. + (Output_section::build_relaxation_map): New method definition. + (Output_section::convert_input_sections_in_list_to_relaxed_sections): + Same. + (Output_section::relax_input_section): Renamed to + Output_section::convert_input_sections_to_relaxed_sections and change + interface to take a vector of pointers to relaxed sections. + (Output_section::find_merge_section, + Output_section::find_relaxed_input_section): New method definitions. + (Output_section::is_input_address_mapped, + Output_section::output_offset, Output_section::output_address): + Use output section data maps to speed up searching. + (Output_section::find_starting_output_address): Add comments. + (Output_section::do_write, + Output_section::write_to_postprocessing_buffer): Do code-fill + generation as appropriate. + (Output_section::get_input_sections): Invalidate relaxed input section + map. + (Output_section::restore_states): Adjust type of checkpoint . + Invalidate relaxed input section map. + * output.h (Output_merge_base): New class declaration. + (Input_section_specifier): New class defintion. + (class Output_relaxed_input_section) Change base class to + Output_section_data_build. + (Output_relaxed_input_section::Output_relaxed_input_section): Adjust + base class initializer. + (Output_section::add_relaxed_input_section): New method declaration. + (Output_section::Input_section): Change visibility to protected. + (Output_section::Input_section::relobj, + Output_section::Input_section::shndx): Handle relaxed input sections. + Output_section::input_sections) Change visibility to protected. Also + define overload to return a non-const pointer. + (Output_section::Merge_section_properties): New class defintion. + (Output_section::Merge_section_by_properties_map, + Output_section::Output_section_data_by_input_section_map, + Output_section::Relaxation_map): New types. + (Output_section::relax_input_section): Rename method to + Output_section::convert_input_sections_to_relaxed_sections and change + interface to take a vector of relaxed section pointers. + (Output_section::find_merge_section, + Output_section::find_relaxed_input_section, + Output_section::build_relaxation_map, + Output_section::convert_input_sections_in_list_to_relaxed_sections): + New method declarations. + (Output_section::merge_section_map_ + Output_section::merge_section_by_properties_map_, + Output_section::relaxed_input_section_map_, + Output_section::is_relaxed_input_section_map_valid_, + Output_section::generate_code_fills_at_write_): New data members. + * script-sections.cc + (Output_section_element_input::set_section_addresses): Call + current_data_size and addralign methods of relaxed input sections. + (Orphan_output_section::set_section_addresses): Call current_data_size + and addralign methods of relaxed input sections. + * symtab.cc (Symbol_table::compute_final_value): Extract template + from the body of Symbol_table::sized_finalize_symbol. + (Symbol_table::sized_finalized_symbol): Call + Symbol_table::compute_final_value. + * symtab.h (Symbol_table::Compute_final_value_status): New enum type. + (Symbol_table::compute_final_value): New templated method declaration. + * target.cc (Target::do_make_output_section): New method defintion. + * target.h (Target::make_output_section): New method declaration. + (Target::relax): Add more parameters for input objects, symbol table + and layout. Adjust call to do_relax. + (Target::do_make_output_section): New method declaration. + (Target::do_relax): Add parameters for input objects, symbol table + and layout. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * pread.c: Include stdio.h. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * plugin.cc: Don't include dlfcn.h when ENABLE_PLUGINS is not + defined. + +2009-10-09 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * dwarf_reader.cc (Sized_dwarf_line_info::Sized_dwarf_line_info): + Change read_shndx type to unsigned int. + (Sized_dwarf_line_info::read_lines): Change shndx type to unsigned + int. + (Sized_dwarf_line_info::read_line_mappings): Likewise. + * dwarf_reader.h (Sized_dwarf_line_info::Sized_dwarf_line_info): + Change read_shndx type to unsigned int. + (Sized_dwarf_line_info::read_lines): Change shndx type to unsigned + int. + (Sized_dwarf_line_info::read_line_mappings): Likewise. + * layout.cc (Layout::create_symtab_sections): Cast the result of + local_symcount * symsize to off_t in the gold_assert. + +2009-10-09 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Target_arm::relocate::reloc_is_non_pic): Return true for + R_ARM_THM_ABS5, R_ARM_ABS8, R_ARM_ABS12, R_ARM_ABS16, + R_ARM_BASE_ABS. + (Arm_relocate_functions::abs8): Remove has_thumb_bit parameter. + (Arm_relocate_functions::thm_abs5): New function. + (Arm_relocate_functions::abs12): New function. + (Arm_relocate_functions::abs16): New function. + (Arm_relocate_functions::base_abs): New function. + (Scan::check_non_pic): Handle R_ARM_ABS32_NOI. + (Scan::local): Remove special handling of R_ARM_ABS8. Handle + R_ARM_ABS32_NOI, R_ARM_THM_ABS5, R_ARM_ABS12, R_ARM_ABS16, and + R_ARM_BASE_ABS. + (Scan::global): Likewise. + (Relocate::relocate): Handle R_ARM_ABS12, R_ARM_ABS16, + R_ARM_ABS32_NOI, R_ARM_THM_ABS5, and R_ARM_BASE_ABS. + (Relocatable_size_for_reloc::get_size_for_reloc): Handle + R_ARM_ABS16, R_ARM_THM_ABS5, R_ARM_ABS32_NOI, R_ARM_ABS12, and + R_ARM_BASE_ABS. + +2009-10-09 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Arm_relocate_functions::movw_prel_nc): New function. + (Arm_relocate_functions::movt_prel): New function. + (Arm_relocate_functions::thm_movw_prel_nc): New function. + (Arm_relocate_functions::thm_movt_prel): New function. + (Scan::local): Handle R_ARM_MOVW_PREL_NC, R_ARM_MOVT_PREL, + R_ARM_THM_MOVW_PREL_NC, and R_ARM_THM_MOVT_PREL. + (Scan::global, Relocate::relocate): Likewise. + (Relocatable_size_for_reloc::get_size_for_reloc): Likewise. + +2009-10-09 Mikolaj Zalewski <mikolajz@google.com> + + * gold.cc: (queue_initial_tasks): Pass incremental_inputs to + Incremental_checker. + * incremental.cc: (INCREMENTAL_LINK_VERSION): Change type to + unsigned int. + (class Incremental_inputs_header): New class. + (Incremental_inputs_header_writer): Edit comment. + (Incremental_inputs_entry): New class. + (Incremental_inputs_entry_writer): Edit comment. + (Sized_incremental_binary::do_find_incremental_inputs_section): + Add *strtab_shndx parameter, fill it. + (Sized_incremental_binary::do_check_inputs): New method. + (Incremental_checker::can_incrementally_link_output_file): Use + Sized_incremental_binary::check_inputs. + (Incremental_inputs::report_command_line): Save command line in + command_line_. + * incremental.h: + (Incremental_binary::find_incremental_inputs_section): New + method. + (Incremental_binary::do_find_incremental_inputs_section): Add + strtab_shndx parameter. + (Incremental_binary::do_check_inputs): New pure virtual method. + (Sized_incremental_binary::do_check_inputs): Declare. + (Incremental_checker::Incremental_checker): Add incremental_inputs + parameter, use it to initialize incremental_inputs_. + (Incremental_checker::incremental_inputs_): New field. + (Incremental_checker::command_line): New method. + (Incremental_checker::inputs): New method. + (Incremental_checker::command_line_): New field. + +2009-10-09 Mikolaj Zalewski <mikolajz@google.com> + + * incremental.cc: Include <cstdarg> and "target-select.h". + (vexplain_no_incremental): New function. + (explain_no_incremental): New function. + (Incremental_binary::error): New method. + (Sized_incremental_binary::do_find_incremental_inputs_section): New + method. + (make_sized_incremental_binary): New function. + (open_incremental_binary): New function. + (can_incrementally_link_file): Add checks if output is ELF and has + inputs section. + * incremental.h: Include "elfcpp_file.h" and "output.h". + (Incremental_binary): New class. + (Sized_incremental_binary): New class. + (open_incremental_binary): Declare. + * object.cc (is_elf_object): Use + elfcpp::Elf_recognizer::is_elf_file. + (make_elf_object): Use elfcpp::Elf_recognizer::is_valid_header. + * output.h (Output_file::filesize): New method. + +2009-10-07 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Arm_relocate_functions::extract_arm_movw_movt_addend): + New function. + (Arm_relocate_functions::insert_val_arm_movw_movt): New function. + (Arm_relocate_functions::extract_thumb_movw_movt_addend): New + function. + (Arm_relocate_functions::insert_val_thumb_movw_movt): New + function. + (Arm_relocate_functions::movw_abs_nc): New function. + (Arm_relocate_functions::movt_abs): New function. + (Arm_relocate_functions::thm_movw_abs_nc): New function. + (Arm_relocate_functions::thm_movt_abs): New function. + (Scan::local): Handle R_ARM_MOVW_ABS_NC, R_ARM_MOVT_ABS, + R_ARM_THM_MOVW_ABS_NC, R_ARM_THM_MOVT_ABS. + (Scan::global): Likewise. + (Relocate::relocate): Likewise. + (Relocatable_size_for_reloc::get_size_for_reloc): Likewise. + +2009-10-07 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (Arm_relocate_functions::got_prel) New function. + (Scan::local, Scan::global): Handle R_ARM_GOT_PREL. + (Relocate::relocate): Likewise. + (Relocatable_size_for_reloc::get_size_for_reloc): Likewise. + +2009-10-06 Ian Lance Taylor <iant@google.com> + + * options.h (class General_options): Define + split_stack_adjust_size parameter. + * object.h (class Object): Add uses_split_stack_ and + has_no_split_stack_ fields. Add uses_split_stack and + has_no_split_stack accessor functions. Declare + handle_split_stack_section. + (class Reloc_symbol_changes): Define. + (class Sized_relobj): Define Function_offsets. Declare + split_stack_adjust, split_stack_adjust_reltype, and + find_functions. + * object.cc (Object::handle_split_stack_section): New function. + (Sized_relobj::do_layout): Call handle_split_stack_section. + * dynobj.cc (Sized_dynobj::do_layout): Call + handle_split_stack_section. + * reloc.cc (Sized_relobj::relocate_sections): Call + split_stack_adjust for executable sections in split_stack + objects. Pass reloc_map to relocate_section. + (Sized_relobj::split_stack_adjust): New function. + (Sized_relobj::split_stack_adjust_reltype): New function. + (Sized_relobj::find_functions): New function. + * target-reloc.h: Include "object.h". + (relocate_section): Add reloc_symbol_changes parameter. Change + all callers. + * target.h (class Target): Add calls_non_split method. Declare + do_calls_non_split virtual method. Declare match_view and + set_view_to_nop. + * target.cc: Include "elfcpp.h". + (Target::do_calls_non_split): New function. + (Target::match_view): New function. + (Target::set_view_to_nop): New function. + * gold.cc (queue_middle_tasks): Give an error if mixing + split-stack and non-split-stack objects with -r. + * i386.cc (Target_i386::relocate_section): Add + reloc_symbol_changes parameter. + (Target_i386::do_calls_non_split): New function. + * x86_64.cc (Target_x86_64::relocate_section): Add + reloc_symbol_changes parameter. + (Target_x86_64::do_calls_non_split): New function. + * arm.cc (Target_arm::relocate_section): Add reloc_symbol_changes + parameter. + * powerpc.cc (Target_powerpc::relocate_section): Add + reloc_symbol_changes parameter. + * sparc.cc (Target_sparc::relocate_section): Add + reloc_symbol_changes parameter. + * configure.ac: Call AM_CONDITIONAL for the default target. + * configure: Rebuild. + * testsuite/Makefile.am (TEST_AS): New variable. + (check_SCRIPTS): Add split_i386.sh and split_x86_64.sh. + (check_DATA): Add split_i386 and split_x86_64 files. + (SPLIT_DEFSYMS): Define. + (split_i386_[1234n].o): New targets. + (split_i386_[124]): New targets. + (split_i386_[1234r].stdout): New targets. + (split_x86_64_[1234n].o): New targets. + (split_x86_64_[124]): New targets. + (split_x86_64_[1234r].stdout): New targets. + (MOSTLYCLEANFILES): Add new executables. + * testsuite/split_i386.sh: New file. + * testsuite/split_x86_64.sh: New file. + * testsuite/split_i386_1.s: New file. + * testsuite/split_i386_2.s: New file. + * testsuite/split_i386_3.s: New file. + * testsuite/split_i386_4.s: New file. + * testsuite/split_i386_n.s: New file. + * testsuite/split_x86_64_1.s: New file. + * testsuite/split_x86_64_2.s: New file. + * testsuite/split_x86_64_3.s: New file. + * testsuite/split_x86_64_4.s: New file. + * testsuite/split_x86_64_n.s: New file. + * testsuite/testfile.cc (Target_test): Update relocation_section + function. + * testsuite/Makefile.in: Rebuild. + +2009-10-06 Ian Lance Taylor <iant@google.com> + + * i386.cc (class Target_i386::Relocate): Add ldo_addrs_ field. + (Target_i386::Relocate::relocate_tls): Call fix_up_ldo before + changing local_dynamic_type_ from LOCAL_DYNAMIC_NONE. When + handling R_386_TLS_LDO_32, if local_dynamic_type_ is NONE, push + the address on ldo_addrs_. + (Target_i386::Relocate::fix_up_ldo): New function. + +2009-10-06 Rafael Espindola <espindola@google.com> + + * plugin.cc (add_input_library): New. + (Plugin::load): Add add_input_library to tv. + (Plugin_manager::add_input_file): Add the is_lib argument. + (add_input_file): Update call to Plugin_manager::add_input_file. + (add_input_library): New. + * plugin.h (Plugin_manager::add_input_file): Add the is_lib argument. + +2009-09-30 Doug Kwan <dougkwan@google.com> + + * arm.cc (Target_arm::may_need_copy_reloc): Check for THUMB function + symbol and call Symbol::may_need_copy_reloc to determine if + a copy reloc is needed. + * copy-relocs.cc (Copy_relocs::need_copy_reloc): Return false if -z + nocopyreloc is given in command line. + (Copy_relocs::emit_copy_reloc): Assert that -z nocopyreloc is not + given in command line. + * i386.cc (Target_i386::may_need_copy_reloc): Remove. + (Target_i386::Scan::global): Use Symbol::may_need_copy_reloc instead + of the removed Target_i386::may_need_copy_reloc. + * options.h (copyreloc): New option with default value false. + * powerpc.cc (Target_powerpc::may_need_copy_reloc): Remove. + (Target_powerpc::Scan::global): Use Symbol::may_need_copy_reloc + instead of the removed Target_powerpc::may_need_copy_reloc. + * sparc.cc (Target_powerpc::may_need_copy_reloc): Remove. + (Target_sparc::Scan::global): Use Symbol::may_need_copy_reloc + instead of the removed Target_sparc::may_need_copy_reloc. + * symtab.h (Symbol::may_need_copy_reloc): New method definition. + * x86_64.cc (Target_powerpc::may_need_copy_reloc): Remove. + (Target_x86_64::Scan::global): Use Symbol::may_need_copy_reloc + instead of the removed Target_x86_64::may_need_copy_reloc. + +2009-09-30 Ian Lance Taylor <iant@google.com> + + * object.h (class Object): Remove target_ field, and target, + sized_target, and set_target methods. + (Object::sized_target): Remove. + (class Sized_relobj): Update declarations. Remove sized_target. + * object.cc (Sized_relobj::setup): Remove target parameter. + Change all callers. + (Input_objects::add_object): Don't do anything with the target. + (make_elf_sized_object): Add punconfigured parameter. Change all + callers. Set or test parameter target. + * dynobj.cc (Sized_dynobj::target): Remove target parameter. + Change all callers. + * parameters.cc (Parameters::set_target): Change parameter type to + be non-const. + (Parameters::default_target): Remove. + (set_parameters_target): Change parameter type to be non-const. + (parameters_force_valid_target): New function. + (parameters_clear_target): New function. + * parameters.h (class Parameters): Update declarations. Remove + default_target method. Add sized_target and clear_target + methods. Change target_ to be non-const. + (set_parameters_target): Update declaration. + (parameters_force_valid_target): Declare. + (parameters_clear_target): Declare. + * readsyms.cc (Read_symbols::do_read_symbols): Pass punconfigured + as NULL if we aren't searching. + (Add_symbols::run): Don't check for compatible target. + * fileread.cc (Input_file::open_binary): Call + parameters_force_valid_target. + * gold.cc (queue_middle_tasks): Likewise. + * plugin.cc (make_sized_plugin_object): Likewise. Don't call + set_target on object. + * dynobj.h (class Sized_dynobj): Update declarations. + * archive.cc (Archive::get_elf_object_for_member): Return NULL if + make_elf_object returns NULL. + (Archive::include_member): Don't check whether object target is + compatible. + * output.cc (Output_section::add_input_section): Get target from + parameters. + (Output_section::relax_input_section): Likewise. + * reloc.cc (Sized_relobj::do_gc_process_relocs): Get target from + parameters. + (Sized_relobj::do_scan_relocs): Likewise. + (Sized_relobj::relocate_sections): Likewise. + * resolve.cc (Symbol_table::resolve): Likewise. + * symtab.cc (Symbol_table::wrap_symbol): Likewise. Remove object + parameter. Change all callers. + (Symbol_table::add_from_object): Get target from parameters. + (Symbol_table::add_from_relobj): Don't check object target. + (Symbol_table::add_from_dynobj): Likewise. + (Symbol_table::define_special_symbol): Get target from + parameters. + * symtab.h (class Symbol_table): Update declaration. + * testsuite/binary_unittest.cc (gold_testsuite): Remove target + parameter. Change all callers. Clear parameter target. + (Binary_test): Test target here. + * testsuite/object_unittest.cc (gold_testsuite): Remove + target_test_pointer parameter. Change all callers. + (Object_test): Test target here. + +2009-09-26 Ian Lance Taylor <iant@google.com> + + * testsuite/initpri1.c: Don't try to use constructor priorities if + compiling with gcc before 4.3. + +2009-09-22 Mikolaj Zalewski <mikolajz@google.com> + + * testsuite/retain_symbols_file_test.sh (check_present): Change + output file name to retain_symbols_file_test.stdout. + (check_absent): Likewise. + +2009-09-18 Craig Silverstein <csilvers@google.com> + + * object.cc (Sized_relobj::do_count): Test should_retain_symbol map. + * options.cc: Include <cerrno> and <fstream>. + (General_options::finalize): Parse -retain-symbols-file tag. + * options.h: New flag. + (General_options): New method should_retain_symbol, new + variable symbols_to_retain. + * symtab.cc (Symbol_table::sized_finalize_symbol): Test + should_retain_symbol map. + * testsuite/Makefile.am (retain_symbols_file_test): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/retain_symbols_file_test.sh: New file. + +2009-09-18 Nick Clifton <nickc@redhat.com> + + * po/es.po: Updated Spanish translation. + +2009-09-17 Doug Kwan <dougkwan@google.com> + + * debug.h (DEBUG_RELAXATION): New constant. + (DEBUG_ALL): Add DEBUG_RELAXATION. + (debug_string_to_enum): Add relaxation debug option. + * layout.cc + (Layout::Relaxation_debug_check::check_output_data_for_reset_values, + Layout::Relaxation_debug_check::read_sections, + Layout::Relaxation_debug_check::read_sections): New method definitions. + (Layout::Layout): Initialize data members + record_output_section_data_from_scrips_, + script_output_section_data_list_ and relaxation_debug_check_. + (Layout::save_segments, Layout::restore_segments, + Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation, + Layout::relaxation_loop_body): New method definitions. + (Layout::finalize): Support relaxation. Move section layout code to + Layout::relaxation_loop_body. + (Layout::set_asection_address_from_script): Move code for orphan + section placement out. + (Layout::place_orphan_sections_in_script): New method definition. + * layout.h (Output_segment_headers, Output_file_header): + New forward class declarations. + (Layout::~Layout): Define. + (Layout::new_output_section_data_from_script): New method definition. + (Layout::place_orphan_sections_in_script): New method declaration. + (Layout::Segment_states): New type declaration. + (Layout::save_segments, Layout::restore_segments, + Layout::clean_up_after_relaxation, Layout::prepare_for_relaxation, + Layout::relaxation_loop_body): New method declarations. + (Layout::Output_section_data_list): New type declaration. + (Layout::Relaxation_debug_check): New class definition. + (Layout::record_output_section_data_from_script_, + Layout::script_output_section_data_list_, Layout::segment_states_, + Layout::relaxation_debug_check_): New data members. + * output.cc: (Output_section_headers::do_size): New method definition. + (Output_section_headers::Output_section_headers): Move size + computation to Output_section_headers::do_size. + (Output_segment_headers::do_size): New method definition. + (Output_file_header::Output_file_header): Move size computation to + Output_file_header::do_size and call it. + (Output_file_header::do_size): New method definition. + (Output_data_group::Output_data_group): Adjust call to + Output_section_data. + (Output_data_dynamic::set_final_data_size): Add DT_NULL tag only once. + (Output_symtab_xindex::do_write): Add array bound check. + (Output_section::Input_section::print_to_mapfile): Handle + RELAXED_INPUT_SECTION_CODE. + (Output_section::Output_section): Initialize data member checkpoint_. + (Output_section::~Output_section): Delete checkpoint object pointed + by checkpoint_. + (Output_section::add_input_section): Always add an Input_section if + relaxing. + (Output_section::add_merge_input_section): Add assert. + (Output_section::relax_input_section): New method definition. + (Output_section::set_final_data_size): Set load address to zero for + an unallocated section. + (Output_section::do_address_and_file_offset_have_reset_values): + New method definition. + (Output_section::Input_section_sort_enty::Input_section_sort_enty): + Handle relaxed input section. + (Output_section::sort_attached_input_sections): Checkpoint input + section list lazily. + (Output_section::get_input_sections): Change type of input_sections to + list of Simple_input_section pointers. Checkpoint input section list + lazily. Also handle relaxed input sections. + (Output_section::add_input_section_for_script): Take a reference to + a Simple_input_section object instead of Relobj pointer and section + index as parameter. Handle relaxed input sections. + (Output_section::save_states, Output_section::restore_states): New + method definitions. + * output.h (Output_data::Output_data): Initialize is_data_size_fixed_. + (Output_data::is_data_size_fixed): New method definition. + (Output_data::reset_addresss_and_file_offset): Do not reset data size + if it is fixed. + (Output_data::address_and_file_offset_have_reset_values): New method + definition. + (Output_data::do_address_and_file_offset_have_reset_values): New method + definition. + (Output_data::set_data_size): Check that data size is not fixed. + (Output_data::fix_data_size): New method definition. + (Output_data::is_data_size_fixed_): New data member. + (Output_section_headers::set_final_data_size): New method definition. + (Output_section_headers::do_size): New method declaration. + (Output_segment_headers::set_final_data_size): New method definition. + (Output_segment_headers::do_size): New method declaration. + (Output_file_header::set_final_data_size)::New method definition. + (Output_file_header::do_size)::New method declaration. + (Output_section_data::Output_section_data): Add new parameter + is_data_size_fixed and use it to fix data size. + (Output_data_const::Output_data_const): Adjust call to base class + constructor and fix data size. + (Output_data_const_buffer::Output_data_const_buffer): Adjust call to + base class constructor and fix data size. + (Output_data_fixed_space::Output_data_fixed_space): Adjust call to + base class constructor and fix data size. + (Output_data_zero_fill::Output_data_zero_fill): Adjust call to base + class constructor and fix data size. + (Output_data_group::set_final_data_size): New method definition. + (Output_data_dynamic::Dynamic_entry::tag): New method definition. + (Output_symtab_xindex::Output_symtab_xindex): Adjust call to base + class constructor and fix data size. + (Output_relaxed_input_section): New class definition. + (Output_section::Simple_input_section): New class definition. + (Output_section::get_input_sections): Adjust parameter list. + (Output_section::add_input_section_for_script): Same. + (Output_section::save_states, Output_section::restore_states, + Output_section::do_address_and_file_offset_have_reset_values, + (Output_section::Input_section::Input_section): Handle + RELAXED_INPUT_SECTION_CODE. Add new overload for + Output_relaxed_input_section. + (Output_section::Input_section::is_input_section, + Output_section::Input_section::set_output_section): Handle relaxed + input section. + (Output_section::Input_section::is_relaxed_input_section, + Output_section::Input_section::output_section_data, + Output_section::Input_section::relaxed_input_section): New method + definitions. + (Output_section::Input_section::RELAXED_INPUT_SECTION_CODE): New enum + value. + (Output_section::Input_section::u1_): Update comments. + (Output_section::Input_section::u2_): Add new union member poris. + (Output_section::Checkpoint_output_section): New classs definition. + (Output_section::relax_input_section): New method declaration. + (Output_section::checkpoint_): New data member. + (Output_segment): Update comments. + (Output_segment::Output_segment): Un-privatize copy constructor. + (Output_segment::operator=): Un-privatize. + * script-sections.cc (Output_section_element::Input_section_list): + Change element type to Output_section::Simple_input_section. + (Output_section_element_dot_assignment::set_section_addresses): + Register output section data for relaxation clean up. + (Output_data_exression::Output_data_expression): Adjust call to base + constructor to fix data size. + (Output_section_element_data::set_section_addresses): Register + Output_data_expression object for relaxation clean up. + (struct Input_section_info): Replace Relobj pointer and section index + pair with Output_section::Simple_input_section and Convert struct to a + class. + (Input_section_sorter::operator()): Adjust access to + Input_section_info data member to use accessors. + (Output_section_element_input::set_section_addresses): Use layout + parameter. Adjust code to use Output_section::Simple_input_section + and Input_secction_info classes. Register filler for relaxation + clean up. + (Orphan_output_section::set_section_addresses): Replace Relobj pointer + and section index pair with Output_section::Simple_input_section + class. Adjust code accordingly. + (Phdrs_element::release_segment): New method definition. + (Script_sections::attach_sections_using_phdrs_clause): Do not modify + segment list. + (Script_sections::release_segments): New method definition. + * gold/script-sections.h (Script_sections::release_segments): New + method declaration. + * gold/target.h (Target::may_relax, Target::relax, + Target::do_may_relax, Target::do_relax): New method definitions. + +2009-09-17 Viktor Kutuzov <vkutuzov@accesssoftek.com> + + * arm.cc (has_signed_unsigned_overflow): New function. + (Arm_relocate_functions::abs8): New function. + (Target_arm::Scan::local): Handle R_ARM_ABS8. + (Target_arm::Scan::global): Likewise. + (Target_arm::relocate::relocate): Likewise. + (Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): + Likewise. + +2009-09-16 Cary Coutant <ccoutant@google.com> + + * testsuite/Makefile.am (MOSTLYCLEANFILES): Add more generated files. + * testsuite/Makefile.in: Regenerate. + +2009-09-11 Nick Clifton <nickc@redhat.com> + + * po/gold.pot: Updated by the Translation project. + +2009-09-08 Cary Coutant <ccoutant@google.com> + + * output.cc (Output_file::open): Add execute permission to empty file. + * testsuite/Makefile.am (permission_test): New test. + * testsuite/Makefile.in: Regenerate. + +2009-09-02 Ian Lance Taylor <iant@google.com> + + * output.cc (Output_file::resize): Call map_no_anonymous rather + than map. + +2009-09-01 Mikolaj Zalewski <mikolajz@google.com> + + * gold.cc: Include "incremental.h". + (queue_initial_tasks): Call Incremental_checker methods. + * incremental.cc: Include "output.h". + (Incremental_checker::can_incrementally_link_output_file): New + method. + * incremental.h (Incremental_checker): New class. + + * output.cc (Output_file::open_for_modification): New method. + (Output_file::map_anonymous): Changed return type to bool. Record + map in base_ field. + (Output_file::map_no_anonymous): New method, broken out of map. + (Output_file::map): Use map_no_anonymous and map_anonymous. + * output.h (class Output_file): Update declarations. + +2009-08-24 Cary Coutant <ccoutant@google.com> + + * options.h (Command_line::Pre_options): New class. + (Command_line::pre_options): New member. + * options.cc (gold::options::ready_to_register): New variable. + (One_option::register_option): Do nothing if not registering options. + Assert if same short option registered twice. + (General_options::General_options): Turn off option registration when + done constructing. + (Command_line::Pre_options::Pre_options): New constructor. + +2009-08-24 Cary Coutant <ccoutant@google.com> + + * options.h (General_options::no_keep_memory): Remove incorrect + short option. + +2009-08-24 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.am (am__skiplex, am__skipyacc): New. + * Makefile.in: Regenerate. + +2009-08-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.am (AM_CPPFLAGS): Renamed from ... + (INCLUDES): ... this. + * testsuite/Makefile.am (AUTOMAKE_OPTIONS): Add -Wno-portability. + (AM_CPPFLAGS): Renamed from ... + (INCLUDE): ... this. + * Makefile.in, testsuite/Makefile.in: Regenerate. + + * Makefile.in: Regenerate. + * aclocal.m4: Likewise. + * config.in: Likewise. + * configure: Likewise. + * testsuite/Makefile.in: Likewise. + + * Makefile.am (AUTOMAKE_OPTIONS): Add foreign. + * testsuite/Makefile.am (AUTOMAKE_OPTIONS): Add foreign. + * Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2009-08-19 Cary Coutant <ccoutant@google.com> + + * resolve.cc (Symbol_table::resolve): Don't complain about defined + symbols in shared libraries overridden by hidden or internal symbols + in the main program. + +2009-08-19 Chris Demetriou <cgd@google.com> + + * testsuite/debug_msg.sh: Match .* rather than ${srcdir} when + checking source file names in error messages. + +2009-08-18 Doug Kwan <dougkwan@google.com> + + * dynobj.cc (Sized_dynobj::setup): Take a Target object instead of + an elcpp::Ehdr as parameter. Adjust call to set_target. + * dynobj.h (Sized_dynobj::setup): Take a Target object instead of + an elfcpp::Ehdr as parameter. + * object.cc (Object::set_target): Remove the version that looks up + a target and sets it. + (Sized_relobj::setup): Take a Target object instead of + an elfcpp::Ehdr as parameter. Adjust call to set_target. + (make_elf_sized_object): Find target and ask target to + make an ELF object. + * object.h: (Object::set_target): Remove the version that looks up + a target and sets it. + (Sized_relobj::setup): Take a Target object instead of + an elfcpp:Ehdr as parameter. + * target.cc: Include dynobj.h. + (Target::do_make_elf_object_implementation): New. + (Target::do_make_elf_object): New. + * target.h (Target::make_elf_object): New template declaration. + (Target::do_make_elf_object): New method declarations. + (Target::do_make_elf_object_implementation): New template declaration. + +2009-08-14 Ian Lance Taylor <iant@google.com> + + * gold.h (FUNCTION_NAME): Define. + (gold_unreachable): Use FUNCTION_NAME. + +2009-08-12 Sriraman Tallam <tmsriram@google.com> + + * icf.cc (Icf::find_identical_sections): Issue a warning when a + symbol in the --keep-unique list is not found. + +2009-08-12 Sriraman Tallam <tmsriram@google.com> + + * icf.cc (Icf::find_identical_sections): Unfold symbols that have + been maked as --keep-unique. + (Icf::unfold_section): New function. + * icf.h (Icf::unfold_section): New function. + * options.h (General_options::keep_unique): New option. + * testsuite/Makefile.am: Add commands to build icf_keep_unique_test. + * testsuite/Makefile.in: Regenerate. + * testsuite/icf_keep_unique_test.sh: New file. + * testsuite/icf_keep_unique_test.cc: New file. + +2009-08-12 Cary Coutant <ccoutant@google.com> + + PR 10471 + * resolve.cc (Symbol_table::resolve): Check for references from + dynamic objects to hidden and internal symbols. + * testsuite/Makefile.am (hidden_test.sh): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/hidden_test.sh: New script. + * testsuite/hidden_test_1.c: New test source. + * testsuite/hidden_test_main.c: New test source. + +2009-08-11 Doug Kwan <dougkwan@google.com> + + * arm.cc: Update comments. + (Target_arm::do_finalize_sections): Add a special PT_ARM_EXIDX + segment to locate the .ARM.exidx section if present. + +2009-08-09 Doug Kwan <dougkwan@google.com> + + * dynobj.h (Sized_dynobj::do_section_entsize): Revert the previous + patch. + +2009-08-07 Sriraman Tallam <tmsriram@google.com> + * dynobj.h (Sized_dynobj::do_section_entsize): Add return to avoid + compiler warnings. + +2009-08-06 Sriraman Tallam <tmsriram@google.com> + + * x86_64.cc (Target_x86_64::Relocate::relocate_tls): Check for a + valid tls_segment only for non-debug-section relocations. + * testsuite/Makefile.am: Add gc_tls_test. + * testsuite/Makefile.in: Regenerate. + * testsuite/gc_tls_test.cc: New file. + * testsuite/gc_tls_test.sh: New file. + +2009-08-05 Sriraman Tallam <tmsriram@google.com> + + * icf.cc: New file. + * icf.h: New file. + * Makefile.am (CCFILES): Add icf.cc. + (HFILES): Add icf.h + * Makefile.in: Regenerate. + * dynobj.h (Sized_dynobj::do_section_entsize): New function. + * gc.h (gc_process_relocs): Populate lists used by icf to contain + section, symbol and addend information for the relocs. + * gold.cc (queue_middle_tasks): Call identical code folding. + * gold.h: Add defines for multimap. + * layout.cc (Layout::create_symtab_sections): Add symtab as parameter + to the call of finalize_local_symbols. + * main.cc (main): Create object of class Icf. + * object.cc (Sized_relobj::do_layout): Allow this function to be + called twice during icf. + (Sized_relobj::do_finalize_local_symbols): Fold symbols corresponding + to sections marked as identical by icf. + (Sized_relobj::do_section_flags): Get section_flags from Symbols_data + when available. + (Sized_relobj::do_section_entsize): New function. + * object.h (Object::section_entsize): New function. + (Object::do_section_entsize): New pure virtual function. + (Relobj::finalize_local_symbols): Add new parameter. + (Relobj::do_section_entsize): New function. + * options.h (General_options::icf): New option. + (General_options::icf_iterations): New option. + (General_options::print_icf_sections): New option. + * plugin.cc (Sized_pluginobj::do_section_entsize): New function. + * plugin.h (Sized_pluginobj::do_section_entsize): New function. + * reloc.cc (Read_relocs::run): Delay scanning relocs when doing + icf. + * symtab.cc (Symbol_table::is_section_folded): New function. + (Symbol_table::sized_finalize_symbol): Fold symbols corresponding + to sections marked as identical by icf. + * symtab.h (Symbol_table::set_icf): New function. + (Symbol_table::icf): New function. + (Symbol_table::is_section_folded): New function. + (Symbol_table::icf_): New data member. + * target-reloc.h (relocate_section): Ignore sections folded by icf. + * testsuite/Makefile.am: Add commands to build icf_test. + * testsuite/Makefile.in: Regenerate. + * testsuite/icf_test.sh: New file. + * testsuite/icf_test.cc: New file. + +2009-07-24 Chris Demetriou <cgd@google.com> + + * layout.cc (is_compressible_debug_section): Fix incorrect + comment about compressed section names. + +2009-07-20 Ian Lance Taylor <ian@airs.com> + + PR 10419 + * x86_64.cc (Target_x86_64::do_code_fill): Correct nop sequences. + +2009-07-16 Ian Lance Taylor <iant@google.com> + + PR 10400 + * layout.h: #include <map>. + (class Kept_section): Change from struct to class. Add accessors + and setters. Add section size to Comdat_group mapping. Change + Comdat_group to std::map. Add is_comdat_ field. Add + linkonce_size field in union. + (class Layout): Update declaration of find_or_add_kept_section. + Don't declare find_kept_object. + * layout.cc (Layout::find_or_add_kept_section): Remove candidate + parameter. Add object, shndx, is_comdat, and is_group_name + parameters. Change all callers. Adjust for new Kept_section. + (Layout::find_kept_object): Remove. + * object.cc (Sized_relobj::include_section_group): Update use of + Kept_section. Rename secnum to shndx. Only record + Kept_comdat_section if sections are the same size. + (Sized_relobj::include_linkonce_section): Update use of + Kept_section. Only record Kept_comdat_section if sections are the + same size. Set size of linkonce section. + (Sized_relobj::map_to_kept_section): Update call to + get_kept_comdat_section. + * object.h (class Sized_relobj): Rename fields in + Kept_comdat_section to drop trailing underscores; change object + field to Relobj*. Change Kept_comdat_section_table to store + struct rather than pointer. + (Sized_relobj::set_kept_comdat_section): Remove kept parameter. + Add kept_object and kept_shndx parameters. Change all callers. + (Sized_relobj::get_kept_comdat_section): Change return type to + bool. Add kept_object and kept_shndx parameters. Change all + callers. + * plugin.cc (Pluginobj::include_comdat_group): Update call to + Layout::find_or_add_kept_section. + +2009-07-09 Ian Lance Taylor <iant@google.com> + + * merge.cc (Object_merge_map::initialize_input_to_output_map): + Reserve space in the hash table. + +2009-07-06 Mikolaj Zalewski <mikolajz@google.com> + + * fileread.cc (File_read::get_mtime): New method. + * fileread.h (Timespec): New structure. + (File_read::get_mtime): New method. + * incremental.cc (Incremental_inputs_entry_data::timestamp_usec): + Renamed from timestamp_nsec. + (Incremental_inputs_entry_write::timestamp_sec): Fix argument to + Elf_Xword. + (Incremental_inputs_entry_write::timestamp_usec): Renamed from + timestamp_nsec. + (Incremental_inputs::report_archive): Save mtime; style fix. + (Incremental_inputs::report_obejct): Save mtime; style fix. + (Incremental_inputs::report_script): Save mtime; style fix. + (Incremental_inputs::finalize_inputs): Style fix. + (Incremental_inputs::finalize): Style fix. + (Incremental_inputs::create_input_section_data): Store inputs + mtime. + * incremental.h (Incremental_inputs::report_script): Add mtime + argument. + (Incremental_inputs::Input_info::Input_info): Intialize only one + union member. + (Incremental_inputs::Input_info::archive): Move to nameless + union. + (Incremental_inputs::Input_info::obejct): Move to nameless union. + (Incremental_inputs::Input_info::script): Move to nameless union. + (Incremental_inputs::mtime): New field. + * script.cc (read_input_script): Pass file mtime to + Incremental_input. + * script.h (Script_info::inputs): Style fix. + +2009-07-01 Ian Lance Taylor <ian@airs.com> + + * freebsd.h (Target_freebsd::do_adjust_elf_header): Use size + instead of 32. + +2009-06-24 Ian Lance Taylor <iant@google.com> + + PR 10156 + * layout.cc (Layout::choose_output_section): If we find an + existing section, update the flags. + (Layout::create_notes): New function, broken out of + Layout::finalize. + (Layout::finalize): Don't create note sections. + (Layout::create_note): Don't crash if linker script discards + section. + (Layout::create_gold_note): Likewise. + (Layout::create_build_id): Likewise. Don't set + after_input_sections on the section. + (Layout::create_executable_stack_info): Remove target parameter. + Change caller. + * layout.h (class Layout): Declare create_notes. Update + declaration of create_executable_stack_info. + * gold.cc (queue_middle_tasks): Call create_notes. + * output.cc (Output_section::update_flags_for_input_section): Move + here from output.h. If SHF_ALLOC flag is newly set, mark address + invalid. + * output.h (Output_data::mark_address_invalid): New function. + (class Output_section): Only declare, not define, + update_flags_for_input_section. Remove set_flags. + +2009-06-24 Ian Lance Taylor <iant@google.com> + + * script-sections.cc (Output_section_definition:: + set_section_addresses): Rename shadowing local load_address to + laddr. + +2009-06-24 Ian Lance Taylor <iant@google.com> + + PR 10244 + * reloc.cc (relocate_sections): Skip empty relocation sections. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + PR 10156 + * layout.cc (Layout::create_note): Use choose_output_section + rather than make_output_section. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + PR 10237 + * options.cc (General_options::parse_V): Set printed_version_. + (General_options::General_options): Initialize printed_version_. + * options.h (class General_options): Add printed_version_ field. + * gold.cc (queue_initial_tasks): If there are no input files, + don't give a fatal error if we printed the version information. + (queue_middle_tasks): If using -r with a shared object, give a + fatal error rather than an ordinary error. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + PR 10219 + * layout.cc (Layout::Layout): Initialize have_stabstr_section_. + (Layout::make_output_section): Set have_stabstr_section_ if we see + a .stab*str section. + (Layout::finalize): Call link_stabs_sections. + (Layout::link_stabs_sections): New file. + * layout.h (class Layout): Add have_stabstr_section_ field. + Declare link_stabs_sections. + +2009-06-23 Doug Kwan <dougkwan@google.com> + + * Makefile.am (libgold_a_LIBADD): New. + (ld_new_DEPENDENCIES, ld_new_LDADD): Remove LIBOBJS + * Makefile.in: Regenerate. + * config.in (HAVE_DECL_MEMMEM, HAVE_DECL_STRNDUP): New. + * configure: Regenerate. + * configure.ac (AC_CHECK_DECLS): Add strndup and memmem. + * fileread.cc: Include sys/state.h + * gold.h: Declare memmem and strndup if found missing. + * gold_reloc.h: Include byteswap.h if HAVE_BYTESWAP_H is defined. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + * configure.ac: Call AC_CHECK_DECLS using C, not C++. + * configure: Rebuild. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + PR 10147 + * object.cc (Object::section_contents): Don't try to get a view if + the section has length zero. + (Object::handle_gnu_warning_section): If the section is empty, use + the name of the section as the warning. + +2009-06-23 Ian Lance Taylor <iant@google.com> + + PR 10133 + * stringpool.h (class Stringpool_template): Add optimize_ field. + (Stringpool_template::set_optimize): New function. + * stringpool.cc (Stringpool_template::Stringpool_template): + Initialize optimize_ field. + (Stringpool_template::set_string_offsets): Test local optimize + fild rather than parameter. + * layout.cc (Layout::Layout): Call set_optimize on the section + name stringpool. + +2009-06-22 Ian Lance Taylor <iant@google.com> + + PR 10030 + * yyscript.y: Parse TARGET. + * script.cc (script_set_target): New function. + * script-c.h (script_set_target): Declare. + * options.cc (General_options::string_to_object_format): Rename + from string_to_object_format in anonymous namespace. Change + callers. + * options.h (class General_options): Declare + string_to_object_format. + +2009-06-22 Ian Lance Taylor <iant@google.com> + + * script-sections.cc (Script_sections::create_segments): Don't put + program headers in a PT_LOAD segment if -n or -N. + +2009-06-22 Ian Lance Taylor <iant@google.com> + + PR 10141 + * options.h (class General_options): Add -z lazy and -z now. Sort + -z options into alphabetical order. + * layout.cc (Layout::finish_dynamic_section): Handle -z now. + +2009-06-21 Ian Lance Taylor <iant@google.com> + + * layout.cc (Layout::make_output_section): Call + Target::new_output_section. + (Layout::attach_allocated_section_to_segment): Put large section + sections in a separate load segment with the large segment flag + set. + (Layout::segment_precedes): Sort large data segments after other + load segments. + (align_file_offset): New static function. + (Layout::set_segment_offsets): Use align_file_offset. + * output.h (class Output_section): Add is_small_section_ and + is_large_section_ fields. + (Output_section::is_small_section): New function. + (Output_section::set_is_small_section): New function. + (Output_section::is_large_section): New function. + (Output_section::set_is_large_section): New function. + (Output_section::is_large_data_section): New function. + (class Output_segment): Add is_large_data_segment_ field. + (Output_segment::is_large_data_segment): New function. + (Output_segment::set_is_large_data_segment): New function. + * output.cc (Output_section::Output_section): Initialize new + fields. + (Output_segment::Output_segment): Likewise. + (Output_segment::add_output_section): Add assertion that large + data sections always go in large data segments. Force small data + sections to the end of the list of data sections. Force small BSS + sections to the start of the list of BSS sections. For large BSS + sections to the end of the list of BSS sections. + * symtab.h (class Symbol): Declare is_common_shndx. + (Symbol::is_defined): Check Symbol::is_common_shndx. + (Symbol::is_common): Likewise. + (class Symbol_table): Define enum Commons_section_type. Update + declarations. Add small_commons_ and large_commons_ fields. + * symtab.cc (Symbol::is_common_shndx): New function. + (Symbol_table::Symbol_table): Initialize new fields. + (Symbol_table::add_from_object): Put small and large common + symbols in the right list. + (Symbol_table::sized_finalized_symbol): Check + Symbol::is_common_shndx. + (Symbol_table::sized_write_globals): Likewise. + * common.cc (Symbol_table::do_allocate_commons): Allocate new + common symbol lists. Don't call do_allocate_commons_list if the + list is empty. + (Symbol_table::do_allocate_commons_list): Remove is_tls + parameter. Add comons_section_type parameter. Change all + callers. Handle small and large common symbols. + * object.cc (Sized_relobj::do_finalize_local_symbols): Check + Symbol::is_common_shndx. + * resolve.cc (symbol_to_bits): Likewise. + * target.h (Target::small_common_shndx): New function. + (Target::small_common_section_flags): New function. + (Target::large_common_shndx): New function. + (Target::large_common_section_flags): New function. + (Target::new_output_section): New function. + (Target::Target_info): Add small_common_shndx, large_common_shndx, + small_common_section_flags, and large_common_section_flags + fields. + (Target::do_new_output_section): New virtual function. + * arm.cc (Target_arm::arm_info): Initialize new fields. + * i386.cc (Target_i386::i386_info): Likewise. + * powerpc.cc (Target_powerpc::powerpc_info) [all versions]: + Likewise. + * sparc.c (Target_sparc::sparc_info) [all versions]: Likewise. + * x86_64.cc (Target_x86_64::x86_64_info): Likewise. + (Target_x86_64::do_new_output_section): New function. + * configure.ac: Define conditional MCMODEL_MEDIUM. + * testsuite/Makefile.am (check_PROGRAMS): Add large. + (large_SOURCES, large_CFLAGS, large_DEPENDENCIES): Define. + (large_LDFLAGS): Define. + * testsuite/large.c: New file. + * testsuite/testfile.cc (Target_test::test_target_info): + Initialize new fields. + * configure, testsuite/Makefile.in: Rebuild. + +2009-06-05 Doug Kwan <dougkwan@google.com> + + * Makefile.am (CCFILES): Add target.cc. + * Makefile.in: Regenerate. + * i386.cc (class Target_i386): Define new virtual method to + override do_is_local_label_name in parent. + * object.cc (Sized_relobj::do_count_local_symbols): Discard + local symbols if --discard-locals or -X is given. + * options.h (class General_options): Declare new options + '--discard-locals' and '-X' for discarding locals. + * target.h (class Target): Define new methods is_local_label_name. + Declare new virtual method do_is_local_label_name. + * target.cc: New file. + * testsuite/Makefile.am (check_PROGRAMS): Add discard_locals_test. + (check_SCRIPTS): Add discard_locals_test.sh. + (check_DATA): Add discard_local_tests.syms. + (discard_locals_test_SOURCES, discard_locals_test_LDFLAGS): Define. + (discard_local_tests.syms, discard_locals_test.o): New make rules. + * testsuite/Makefile.in: Regenerate. + * testsuite/discard_locals_test.c: New file. + * testsuite/discard_locals_test.sh: Same. + +2009-06-05 Doug Kwan <dougkwan@google.com> + + * object.cc (Sized_relobj::Sized_relobj): Initialize + discarded_eh_frame_shndx_ to -1U. + (Sized_relobj::do_layout): Record index of a discard .eh_frame + section. + (Sized_relobj::do_count_local_symbols): Skip local symbols in + a discarded .eh_frame section. + (Sized_relobj::do_finalize_local_symbols): Ditto. + * object.h (class Sized_relobj): Declare new member + discarded_eh_frame_shndx_. + * testsuite/Makefile.am (check_PROGRAMS): Add local_labels_test. + (local_labels_test.o, local_labels_test): New rules. + * testsuite/Makefile.in: Regenerate. + +2009-06-04 Doug Kwan <dougkwan@google.com> + + * layout.cc (Layout::section_name_mapping): Add mapping for + special ARM sections. + +2009-06-03 Doug Kwan <dougkwan@google.com> + + * arm.cc (utils::sign_extend): Reverse test in gold_assert. + (utils::has_overflow): Same. + +2009-06-03 Ian Lance Taylor <iant@google.com> + + * layout.cc (Layout::section_name_mapping): New array, replacing + Layout::linkonce_mapping. + (Layout::section_name_mapping_count): New variable, replacing + Layout::linkonce_mapping_count. + (Layout::linkonce_output_name): Remove. + (Layout::output_section_name): Rewrite. + * layout.h (class Layout): Rename Linkonce_mapping to + Section_name_mapping, linkonce_mapping to section_name_mapping, + linkonce_mapping_count to section_name_mapping_count. Don't + declare linkonce_output_name. + +2009-06-03 Doug Kwan <dougkwan@google.com> + + * gold/arm.cc (namespace utils): New. + (Target_arm::reloc_is_non_pic): Define new method. + (class Arm_relocate_functions): New. + (Target_arm::Relocate::relocate): Handle relocation types used by + Android. + +2009-06-03 Ian Lance Taylor <iant@google.com> + + * arm.cc (Target_arm::scan::global): Use || instead of |. + +2009-06-02 Doug Kwan <dougkwan@google.com> + + * gold/arm.cc (Target_arm::Scan::Scan): Initialize + issued_non_pic_error_. + (class Target_arm::Scan): Declare new method check_non_pic. + Define new method symbol_needs_plt_entry. + Declare new data member issued_non_pic_error_. + (class Target_arm::Relocate): Declare new method + should_apply_static_reloc. + (Target_arm::may_need_copy_reloc): Handle STT_ARM_TFUNC. + (Target_arm::Scan::check_non_pic): Define new method. + (Target_arm::Scan::local): Handle a small subset of reloc types used + by Android. + (Target_arm::Scan::local): Same. + (Target_arm::Relocate::should_apply_statci_reloc): Define new method. + +2009-05-31 Mikolaj Zalewski <mikolajz@google.com> + + * incremental.cc (Incremental_inputs::report_command_line): Filter + out --incremental-* options. + +2009-05-29 Doug Kwan <dougkwan@google.com> + + * gold/arm.cc (Output_data_plt_arm): Forward declaration for new + template class. + (class Target_arm): Update comment. + (Target_arm::Target_arm): Initialize new data members GOT_, + PLT_, GOT_PLT_, REL_DYN_, COPY_RELOCS_ and DYNBSS_. + Declare new methods Target_arm::got_section, Target_arm::make_plt_entry + and Target_arm::rel_dyn_section. + Declare new_enum Target_arm::Got_type. + Declare new data members GOT_, PLT_, GOT_PLT_, REL_DYN_, COPY_RELOCS_ + and DYNBSS_. + Update commments for member do_dynsym_value. + (Target_arm::got_size, Target_arm::plt_section, + Target_arm::may_need_copy_reloc and Target_arm::copy_reloc): Define + new methods inside class defintion. + (Target_arm::got_section): Define new method. + (Target_arm::rel_dyn_section): Same. + (Output_data_plt_arm): New template class. + (Output_data_plt_arm::Output_data_plt_arm): Define constructor. + (Output_data_plt_arm:do_adjust_output_section): Define new method. + (Output_data_plt_arm::add_entry): Same. + (Output_data_plt_arm::first_plt_entry): Define new + static data member for PLT instruction template. + (Output_data_plt_arm::plt_entry): Same. + (Output_data_plt_arm::do_write): Define new method. + (Target_arm::make_plt_entry): Same. + (Target_arm::do_finalize_sections): Same. + (Target_arm::do_dynsym_value): Same. + +2009-05-28 Doug Kwan <dougkwan@google.com> + + * Makefile.am (TARGETSOURCES): Add arm.cc. + (ALL_TARGETOBJECTS): Add arm.$(OBJEXT) + * Makefile.in: Regenerate. + * arm.cc: New file. + * configure.tgt: Add armbe*-*-*, armeb*-*-* and arm*-*-* targets. + +2009-05-26 Doug Kwan <dougkwan@google.com> + + * options.cc (General_options::parse_exclude_libs). Fix a comment. + (General_options::check_excluded_libs): Strip off directories in + archive name before matching like GNU ld does. + * testsuite/Makefile.am (MOSTLYCLEANFILES, + exclude_libs_test_DEPENDENCIES): Add alt/libexclude_libs_test_3.a + (exclude_libs_test_LDFLAGS): Add linker option + -Wl,--exclude-libs,libexclude_libs_test_3 + (exclude_libs_test_LADD): Add alt/libexclude_libs_test_3.a as + an explicit archive without using -l. + (alt/libexclude_libs_test_3.a): New make rule. + * testsuite/Makefile.in: Regenerate. + * testsuite/exclude_libs_test.c : Declare lib3_default(). + (main): Call it. + * exclude_libs_test.sh: Add tests for alt/exclude_libs_test_3.a. + * exclude_libs_test_3.c: New file. + +2009-05-26 Nick Clifton <nickc@redhat.com> + + * po/id.po: New Indonesian translation. + * po/gold.pot: Updated template file. + +2009-05-22 Sriraman Tallam <tmsriram@google.com> + + * testsuite/Makefile.am: Add -ffunction-sections to compile + gc_comdat_test files. Add -Wl,--gc-sections to build + gc_comdat_test. + * testsuite/Makefile.in: Regenerate. + * testsuite/gc_comdat_test.sh: Fix the condition around grep. + +2009-05-21 Sriraman Tallam <tmsriram@google.com> + + * object.cc (Sized_relobj::map_to_kept_section): Return NULL if the + kept comdat section was garbage collected. + * testsuite/Makefile.am: Add test gc_comdat_test.sh. + * testsuite/Makefile.in: Regenerate. + * testsuite/gc_comdat_test.sh: New file. + * testsuite/gc_comdat_test_1.cc: New file. + * testsuite/gc_comdat_test_2.cc: New file. + +2009-05-19 Doug Kwan <dougkwan@google.com> + + * archive.cc (Archive::Archive): Move constructor from archive.h + to here. Initialize no_export_. + (Archive::get_elf_object_for_member): Set no_export flag of object. + * archive.h (Archive::Archive): Move constructor body to + archive.cc. + (Archive::no_export): New method. + (Archive::no_export_): New field. + * object.h (Object::Object): Initialize no_export_ to false. + (Object::no_export, Object::set_no_export): New methods. + (Object::no_export_): New field. + * options.cc (General_options::parse_exclude_libs): New method. + (General_options::check_excluded_libs) Same. + * options.h (exclude_libs): New option. + (General_options::check_excluded_libs): New method declaration. + (General_options::excluded_libs_): New field. + * symtab.cc (Symbol_table::add_from_relobj): Hide symbols with + default or protected visibility if an object has no-export flag set. + testsuite/Makefile.am (check_PROGRAMS): Add exclude_libs_test. + (check_SCRIPTS): Add exclude_libs_test.sh. + (check_DATA): Add exclude_libs_test.syms. + (MOSTLYCLEANFILES): Add exclude_libs_test.syms, + libexclude_libs_test_1.a and libexclude_libs_test_2.a. + (exclude_libs_test_SOURCES, exclude_libs_test_DEPENDENCIES, + exclude_libs_test_LDFLAGS and exclude_libs_test_LDADD): Define. + (exclude_libs_test.syms, libexclude_libs_test_1.a, + libexclude_libs_test_2.a): New rules. + * testsuite/Makefile.in: Regenerate. + * testsuite/exclude_libs_test.c: New file. + * testsuite/exclude_libs_test.sh: Ditto. + * testsuite/exclude_libs_test_1.c: Ditto. + * testsuite/exclude_libs_test_2.c: Ditto. + +2009-05-15 Ian Lance Taylor <iant@google.com> + + * configure.ac: Check for declarations for cases where libiberty.h + checks HAVE_DECL_xxx. + * configure, config.in: Rebuild. + +2009-05-15 Mikolaj Zalewski <mikolajz@google.com> + + * gold.h (Incremental_argument_list): Remove (invalid) forward + declaration. + * incremental.cc (Incremental_inputs::report_achive): New method. + (Incremental_inputs::report_object): New method. + (Incremental_inputs::report_script): New method. + (Incremental_inputs::finalize_inputs): New method. + (Incremental_inputs::finalize): Call finalize_inputs(). + (Incremental_inputs::sized_create_incremental_inputs_section_data): + Create inputs entries. + * incremental.h (Incremental_input_type): New enum. + (Incremental_inputs::Incremental_input): Initialize new fields. + (Incremental_inputs::report_inputs): New method. + (Incremental_inputs::report_achive): New method. + (Incremental_inputs::report_object): New method. + (Incremental_inputs::report_script): New method. + (Incremental_inputs::finalize_inputs): New method. + (Incremental_inputs::Input_info): New struct. + (Incremental_inputs::Input_info_map): New typedef. + (Incremental_inputs::lock_): New field. + (Incremental_inputs::Inputs_): New field. + (Incremental_inputs::Inputs_map): New field. + * main.cc (main): Call Incremental_input::report_inputs. + * options.h (Input_argument_list): Typedef moved from + Input_arguments. + (Input_file_group::Files): Remove, use ::Input_argument_list. + (Input_file_group::Input_argument_list): Remove, use + ::Input_argument_list. + * plugin.cc (Plugin_manager::add_input_file): Add error in + incremental build. + * read_syms.cc (do_read_syms): Call Incremental_input::report_* + functions. + * script.cc (read_input_script): Call + Incremental_input::report_script. + * script.h (Script_info): New class. + +2009-04-27 Ian Lance Taylor <iant@google.com> + + * x86_64.cc (do_adjust_output_section): Set entsize to + plt_entry_size. + +2009-04-23 Elliott Hughes <enh@google.com> + + * output.cc (Output_file::close): After short writes, continue + writing from the correct offset in the buffer being written. + +2009-04-23 Chris Demetriou <cgd@google.com> + + * configure.ac (HAVE_TR1_UNORDERED_MAP_REHASH): New define. + * configure: Regenerate. + * config.in: Regenerate. + * gold.h: Avoid std::tr1::unordered_map and std::tr1::unordered_set + if HAVE_TR1_UNORDERED_MAP_REHASH is not defined. + +2009-04-21 Mikolaj Zalewski <mikolajz@google.com> + + * incremental.cc (Incremental_inputs_header_data): Renamed from + Incremental_input_header_data. + (Incremental_inputs_header_data::data_size): New field. + (Incremental_inputs_header_data::put_input_file_count): Renamed + from input_file_count. + (Incremental_inputs_header_data::put_command_line_offset): Renamed + from command_line_offset. + (Incremental_inputs_header_data::put_reserved): Renamed from + put_reserved. + (Incremental_inputs_entry_data): Renamed from + Incremental_input_entry_data. + (Incremental_inputs_entry_data::data_size): New field. + (Incremental_inputs::report_command_line): New method. + (Incremental_inputs::finalize): New method. + (Incremental_inputs::create_incremental_inputs_data): New method. + (Incremental_inputs::sized_create_incremental_inputs_data): New method. + * incremental.h: New file. + * layout.cc (Layout::Layout): Handle new incremental_inputs_. + (Layout::finalize): Create incremental inputs section in + incremental builds. + (Layout::create_incremental_info_sections): New method. + * layout.h (Layout::incremental_inputs): New method. + (Layout::create_incremental_info_sections): New method. + (Layout::incremental_inputs_): New field. + * main.cc (main): Notify Incremental_input of the command line. + +2009-04-01 Ian Lance Taylor <iant@google.com> + Mikolaj Zalewski <mikolajz@google.com> + + * gold.h (reserve_unordered_map): Define, three versions, one for + each version of Unordered_map. + * layout.cc (Layout::Layout): Remove options parameter. Add + number_of_input_files parameter. Don't initialize options_. + Initialize number_of_input_files_ and resized_signatures_. Move + sections_are_attached_. + (Layout::layout_group): Reserve space for group_signatures_. + (Layout::find_or_add_kept_section): Change name parameter to be a + reference. Resize signatures_ map when it gets large enough. + (Layout::layout_eh_frame): Use parameters->options() instead of + this->options_. + (Layout::make_output_section): Likewise. + (Layout::attach_allocated_section_to_segment): Likewise. + (Layout::finalize, Layout::create_executable_stack): Likewise. + (Layout::set_segment_offsets, Layout::create_interp): Likewise. + (Layout::finish_dynamic_section, Layout::write_binary): Likewise. + * layout.h (class Layout): Update declarations. Remove options_ + field. Add number_of_input_files_ and resized_signatures_ + fields. Move sections_are_attached_ field. + * main.cc (main): Pass number of input files to Layout + constructor. Don't pass options. + +2009-03-30 Ian Lance Taylor <iant@google.com> + + * ffsll.c (ffsll): Correct implementation. + +2009-03-27 Ian Lance Taylor <iant@google.com> + + * ffsll.c: New file. + * configure.ac: Call AC_REPLACE_FUNCS on ffsll. + * gold.h (ffsll): Declare if HAVE_FFSLL is not defined. + * ftruncate.c (ftruncate): Declare before definition. + * mremap.c (mremap): Likewise. + * pread.c (pread): Likewise. + * configure, Makefile.in, config.in: Rebuild. + + * mremap.c: New file. + * configure.ac: Call AC_REPLACE_FUNCS on mremap. + * gold.h (MREMAP_MAYMOVE): Define if HAVE_MREMAP is not defined. + (mremap): Declare if HAVE_MREMAP is not defined. + * configure, Makefile.in, config.in: Rebuild. + +2009-03-27 Cary Coutant <ccoutant@google.com> + + * powerpc.cc (Target_powerpc::check_non_pic): Assert that output is + position independent. + * sparc.cc (Target_sparc::check_non_pic): Likewise. + * x86_64.cc (Target_x86_64::check_non_pic): Likewise. + +2009-03-24 Cary Coutant <ccoutant@google.com> + + * symtab.h (needs_plt_entry): Check for unsatisfied reference from + an executable. + (needs_dynamic_reloc): Likewise. + +2009-03-24 Ian Lance Taylor <iant@google.com> + + * yyscript.y (file_cmd): Recognize EXTERN. + (extern_name_list, extern_name_list_body): New nonterminals. + * script.cc (script_add_extern): Define. + * script-c.h (script_add_extern): Declare. + +2009-03-24 Rafael Avila de Espindola <espindola@google.com> + + * object.cc (is_elf_object): Define. + * object.h (is_elf_object): Declare. + * archive.cc (Archive::get_elf_object_for_member): Call + is_elf_object. + * readsyms.cc (Read_symbols::do_read_symbols): Likewise. + +2009-03-24 Elliott Hughes <enh@google.com> + + * output.cc (Output_file::map_anonymous): Define. + (Output_file::map): Use map_anonymous. If the regular mmap fails, + try an anonymous one. Report the size if the mmap fails. + * output.h (class Output_file): Declare map_anonymous. + +2009-03-24 Ian Lance Taylor <iant@google.com> + + * target-select.cc (instantiate_target): Don't acquire the lock if + the instantiated_target_ field has already been set. + +2009-03-23 Ian Lance Taylor <iant@google.com> + + * gold-threads.h (class Initialize_lock): Define. + * gold-threads.cc (class Initialize_lock_once): Define. + (initialize_lock_control): New static variable. + (initialize_lock_pointer): New static variable. + (initialize_lock_once): New static function. + (Initialize_lock::Initialize_lock): Define. + (Initialize_lock::initialize): Define. + * target-select.h: Include "gold-threads.h". + (class Target_selector): Add lock_ and initialize_lock_ fields. + Don't define instantiate_target, just declare it. + * target-select.cc (Target_selector::Target_selector): Initialize + new fields. + (Target_selector::instantiate_target): Define. + * descriptors.h: Include "gold-threads.h". + (class Descriptors): Add initialize_lock_ field. + * descriptors.cc (Descriptors::Descriptors): Initialize new + field. + (Descriptors::open): Use initialize_lock_ field + * errors.h (class Errors): Add initialize_lock_ field. + * errors.cc (Errors::Errors): Initialize new field. + (Errors::initialize_lock): Use initialize_lock_ field. + * powerpc.cc (class Target_selector_powerpc): Remove + instantiated_target_ field. In do_recognize call + instantiate_target rather than do_instantiate_target. In + do_instantiate_target just allocate a new target. + * sparc.cc (class Target_selector_sparc): Likewise. + + * freebsd.h: New file. + * i386.cc: Include "freebsd.h". + (Target_i386): Derive from Target_freebsd rather than + Sized_target. + (Target_selector_i386): Derive from Target_selector_freebsd rather + than Target_selector. + * x86_64.cc: Include "freebsd.h". + (Target_x86_64): Derive from Target_freebsd rather than + Sized_target. + (Target_selector_x86_64): Derive from Target_selector_freebsd + rather than Target_selector. + * target.h (class Target): Add adjust_elf_header and + do_adjust_elf_header. + * output.cc (Output_file_header:: do_sized_write): Call target + adjust_elf_header routine. + * configure.tgt: Set targ_osabi. + * configure.ac: Define GOLD_DEFAULT_OSABI. + * parameters.cc (Parameters::default_target): Pass + GOLD_DEFAULT_OSABI to select_target. + * target-select.h (class Target_selector): Make instantiate_target + protected rather than private. + * Makefile.am (HFILES): Add freebsd.h. + * configure, Makefile.in, config.in: Rebuild. + + * merge.cc (do_add_input_section): Correct pend value. Change + message about last entry not being null terminated from error to + warning. + +2009-03-20 Mikolaj Zalewski <mikolajz@google.com> + + * incremental.cc: New file. + * Makefile.am (CCFILES): Add incremental.cc. + * Makefile.in: Rebuild. + +2009-03-19 Paul Pluzhnikov <ppluzhnikov@google.com> + + * layout.cc (Layout::output_section_name): Preserve names + of '.note.' sections. + +2009-03-19 Ian Lance Taylor <iant@google.com> + + * descriptors.cc (Descriptors::open): Check that the options are + valid before using them. + +2009-03-18 Ian Lance Taylor <iant@google.com> + + * script-sections.h: Include <list>. + (class Script_sections): Change Sections_elements from std::vector + to std::list. Typedef public Elements_iterator. Add + orphan_section_placement_, data_segment_align_start_, and + saw_data_segment_align_ fields. Remove data_segment_align_index_ + field. + * script-sections.cc (class Orphan_section_placement): New class. + (class Sections_element): Add virtual functions is_relro and + orphan_section_init. Remove virtual function place_orphan_here. + (class Output_section_definition): Add is_relro and + orphan_section_init. Remove place_orphan_here. + (class Orphan_output_section): Likewise. + (Script_sections::Script_sections): Update for field changes. + (Script_sections::data_segment_align): Set saw_data_segment_align_ + and data_segment_align_start_, not data_segment_align_index. + (Script_sections::data_segment_relro_end): Check + saw_data_segment_align_. Use data_segment_align_start_ rather + than data_segment_align_index_. + (Script_sections::place_orphan): Rewrite to use + Orphan_section_placement. + +2009-03-17 Ian Lance Taylor <iant@google.com> + + * archive.cc (Archive::add_symbols): Check for a version attached + to the symbol name in the archive map. + * testsuite/Makefile.am (check_PROGRAMS): Add ver_test_11. + (ver_test_11_SOURCES, ver_test_11_DEPENDENCIES): Define. + (ver_test_11_LDFLAGS, ver_test_11_LDADD): Define. + (ver_test_11.a): New target. + * testsuite/Makefile.in: Rebuild. + + * configure.ac: Check for chsize and posix_fallocate. Replace + ftruncate. + * ftruncate.c: New file, from gnulib. + * output.cc (posix_fallocate): Define dummy version if not + HAVE_POSIX_FALLOCATE. + (Output_file::map): Call posix_fallocate rather than lseek and + write. + * gold.h (ftruncate): Declare if not HAVE_FTRUNCATE. + * configure, Makefile.in, config.in: Rebuild. + +2009-03-17 Paul Pluzhnikov <ppluzhnikov@google.com> + + * layout.h (Layout::create_note): Add section_name parameter. + * layout.cc (Layout::create_note): Likewise. + (Layout::create_build_id, Layout::create_gold_note): Fix callers. + +2009-03-17 Ian Lance Taylor <iant@google.com> + + * descriptors.cc: Include "options.h". + (FD_CLOEXEC, O_CLOEXEC): Define if not defined. + (Descriptors::open): Always use O_CLOEXEC when opening a new + descriptor. If we have a plugin, and O_CLOEXEC was not defined, + then set FD_CLOEXEC. + + * sparc.cc (class Target_sparc): Add has_got_section. + (Target_sparc::Scan::global): If we see _GLOBAL_OFFSET_TABLE_, + make sure we have a GOT section. + + * sparc.cc (optimize_tls_reloc): Recognize R_SPARC_TLS_IE_ADD. + (Target_sparc::Scan::local): Likewise. + (Target_sparc::Scan::global): Likewise. + (Target_sparc::Relocate::relocate): Likewise. + (Target_sparc::Relocate::relocate_tls): Likewise. + + * symtab.cc (Symbol_table::define_default_version): New function, + broken out of add_from_object. + (Symbol_table::add_from_object): Call define_default_version. + (Symbol_table::define_special_symbol): Add resolve_oldsym + parameter. Change all callers. If the version for a symbol comes + from a version script, resolve it with the symbol with the same + name with no version. Also add the symbol without a version if + appropriate. + (do_define_in_output_data): If resolving with oldsym, don't delete + sym. + (do_define_in_output_segment): Likewise. + (do_define_as_constant): Likewise. + * symtab.h (class Symbol_table): Update declarations. + +2009-03-13 Ian Lance Taylor <iant@google.com> + + * readsyms.cc (Read_symbols::incompatible_warning): New function. + (Read_symbols::requeue): New function. + (Read_symbols::do_read_symbols): If make_elf_object fails because + the target type is not configured, and the file was searched for, + issue a warning and retry with the next directory. + (Add_symbols::run): If the file has an incompatible format, and + it was searched for, requeue the Read_symbols task. On error, + release the object. + * readsyms.h (class Read_symbols): Add dirindex_ field. Add + dirindex parameter to constructor. Change all callers. Declare + incompatible_warning and requeue. + (class Add_symbols): Add dirpath_, dirindex_, mapfile_, + input_argument_ and input_group_ fields. Add them to + constructor. Change all callers. + (class Read_script): Add dirindex_ field. Add it to constructor. + Change all callers. + * archive.cc (Archive::setup): Remove input_objects parameter. + Change all callers. + (Archive::get_file_and_offset): Likewise. + (Archive::read_all_symbols): Likewise. + (Archive::read_symbols): Likewise. + (Archive::get_elf_object_for_member): Remove input_objects + parameter. Add punconfigured parameter. Change all callers. + (Archive::add_symbols): Change return type to bool. Check return + value of include_member. + (Archive::include_all_members): Likewise. + (Archive::include_member): Change return type to bool. Return + false if first included object has incompatible target. Set + included_member_ field. + (Add_archive_symbols::run): If add_symbols returns false, requeue + Read_symbols task. + * archive.h (class Archive): Add included_member_ field. + Initialize it in constructor. Add input_file and searched_for + methods. Update declarations. + (class Add_archive_symbols): Add dirpath_, dirindex_, and + input_argument_ fields. Add them to constructor. Change all + callers. + * script.cc: Include "target-select.h". + (class Parser_closure): Add skip_on_incompatible_target_ and + found_incompatible_target_ fields. Add + skip_on_incompatible_target parameter to constructor. Change all + callers. Add methods skip_on_incompatible_target, + clear_skip_on_incompatible_target, found_incompatible_target, and + set_found_incompatible_target. + (read_input_script): Add dirindex parameter. Change all callers. + If parser finds an incompatible target, requeue Read_symbols + task. + (script_set_symbol): Clear skip_on_incompatible_target in + closure. + (script_add_assertion, script_parse_option): Likewise. + (script_start_sections, script_add_phdr): Likewise. + (script_check_output_format): New function. + * script.h (read_input_script): Update declaration. + * script-c.h (script_check_output_format): Declare. + * yyscript.y (file_cmd): Handle OUTPUT_FORMAT. + (ignore_cmd): Remove OUTPUT_FORMAT. + * fileread.cc (Input_file::Input_file): Add explicit this. + (Input_file::will_search_for): New function. + (Input_file::open): Add pindex parameter. Change all callers. + * fileread.h (class Input_file): Add input_file_argument method. + Declare will_search_for. Update declarations. + * object.cc (make_elf_object): Add punconfigured parameter. + Change all callers. + * object.h (class Object): Make input_file public. Add + searched_for method. + (make_elf_object): Update declaration. + * dirsearch.cc (Dirsearch::find): Add pindex parameter. Use it to + restart search. + * dirsearch.h (class Dirsearch): Update declaration. + * options.h (class General_options): Add --warn-search-mismatch. + * parameters.cc (Parameters::is_compatible_target): New function. + * parameters.h (class Parameters): Declare is_compatible_target. + * workqueue.cc (Workqueue::add_blocker): New function. + * workqueue.h (class Workqueue): Declare add_blocker. + + * fileread.cc (Input_file::open): Remove options parameter. + Change all callers. + (Input_file::open_binary): Likewise. + * script.cc (read_input_script): Likewise. + * readsyms.h (class Read_symbols): Remove options_ field. Remove + options parameter from constructor. Change all callers. + (class Read_script): Likewise. + * fileread.h (class Input_file): Update declarations. + * script.h (read_input_script): Update declaration. + +2009-03-10 Nick Clifton <nickc@redhat.com> + + * po/es.po: New Spanish translation. + +2009-03-06 Cary Coutant <ccoutant@google.com> + + * options.cc (parse_short_option): Keep dash_z from registering itself. + +2009-03-03 Ian Lance Taylor <iant@google.com> + + PR 9918 + * target-reloc.h (relocate_section): Pass output_section to + relocate. + * i386.cc (Target_i386::should_apply_static_reloc): Add + output_section parameter. Change all callers. + (Target_i386::Relocate::relocate): Add output_section parameter. + * x86_64.cc (Target_x86_64::Relocate::relocate): Likewise. + * sparc.cc (Target_sparc::Relocate::relocate): Likewise. + * powerpc.cc (Target_powerpc::Relocate::relocate): Likewise. + * testsuite/two_file_shared.sh: New script. + * testsuite/Makefile.am (check_SCRIPTS): Add two_file_shared.sh. + (check_DATA): Add two_file_shared.dbg. + (two_file_shared.dbg): New target. + * testsuite/Makefile.in: Rebuild. + +2009-03-01 Ian Lance Taylor <iant@google.com> + + * configure.ac: Check for byteswap.h. + * configure: Rebuild. + * config.in: Rebuild. + +2009-03-01 Mikolaj Zalewski <mikolajz@google.com> + + * layout.cc (Layout::find_or_add_kept_section): New function. + (Layout::add_comdat): Removed. + * layout.h (struct Kept_section): Move out of class Layout. + Remove trailing underscores from field names. Add group_sections + field. Rename group_ field to is_group. Change all uses. + (class Layout): Declare find_or_add_kept_section, not add_comdat. + * object.cc (Sized_relobj::Sized_relobj): Don't initialize + comdat_groups_ field. + (Sized_relobj::include_section_group): Use + find_or_add_kept_section and Kept_section::group_sections. + (Sized_relobj::include_linkonce_section): Likewise. + * object.cc (class Sized_relobj): Don't define Comdat_group or + Comdat_group_table. Remove find_comdat_group and + add_comdat_group. Remove comdat_groups_ field. + * plugin.cc (include_comdat_group): Use + Layout::find_or_add_kept_section. + +2009-02-28 Ian Lance Taylor <iant@google.com> + + * README: --gc-sections and map files are now supported. Document + some build requirements. + + PR 6992 + * symtab.cc (Symbol_table::sized_write_section_symbol): In a + relocatable link set the value of the section symbol to zero. + * object.cc (Sized_relobj::do_finalize_local_symbols): In a + relocatable link don't include the section address in the local + symbol value. + +2009-02-27 Ian Lance Taylor <iant@google.com> + + PR 6811 + * options.h (class Search_directory): Add is_system_directory. + (class General_options): Declare is_in_system_directory. + * options.cc (get_relative_sysroot): Make static. + (get_default_sysroot): Make static. + (General_optoins::is_in_system_directory): New function. + * fileread.cc (Input_file::is_in_system_directory): New function. + * fileread.h (class Input_file): Declare is_in_system_directory. + * object.h (class Object): Add is_in_system_directory. + (class Input_objects): Remove system_library_directory_ field. + * object.cc (Input_objects::add_object): Don't set + system_library_directory_. + (input_objects::found_in_system_library_directory): Remove. + * symtab.cc (Symbol_table::write_globals): Remove input_objects + parameter. Change all callers. + (Symbol_table::sized_write_globals): Likewise. + (Symbol_table::warn_about_undefined_dynobj_symbol): Likewise. + Call Object::is_in_system_directory. + * symtab.h (class Symbol_table): Update declarations. + + PR 5990 + * descriptors.h (Open_descriptor): Add is_on_stack field. + * descriptors.cc (Descriptors::open): If the descriptor is on the + top of the stack, remove it. Initialize is_on_stack field. + (Descriptors::release): Only add pod to stack if it is not on the + stack already. + (Descriptors::close_some_descriptor): Clear stack_next and + is_on_stack fields. + + PR 7091 + * output.cc (Output_section::find_starting_output_address): Rename + from starting_output_address; add PADDR parameter; change return + type. + * output.h (class Output_section): Declare + find_starting_output_address instead of starting_output_address. + * object.cc (Sized_relobj::do_finalize_local_symbols): Handle a + section symbol for which we can't find a merge section. + + PR 9836 + * symtab.cc (Symbol_table::add_from_object): If the visibility is + hidden or internal, force the symbol to be local. + * resolve.cc (Symbol::override_visibility): Define. + (Symbol::override_base): Use override_visibility. + (Symbol_table::resolve): Likewise. + (Symbol::override_base_with_special): Likewise. + (Symbol_table::override_with_special): If the visibility is hidden + or internal, force the symbol to be local. + * symtab.h (class Symbol): Add set_visibility and + override_visibility. + * testsuite/ver_test_1.sh: New file. + * testsuite/Makefile.am (check_SCRIPTS): Add ver_test_1.sh. + (check_DATA): Add ver_test_1.syms. + (ver_test_1.syms): New target. + * testsuite/Makefile.in: Rebuild. + +2009-02-25 Cary Coutant <ccoutant@google.com> + + * layout.cc (Layout::choose_output_section): Don't rename sections + when using a linker script that has a SECTIONS clause. + * Makefile.in: Regenerate. + + * testsuite/Makefile.am (script_test_5.sh): New test case. + * testsuite/Makefile.in: Regenerate. + * testsuite/script_test_5.cc: New file. + * testsuite/script_test_5.sh: New file. + * testsuite/script_test_5.t: New file. + +2009-02-13 Rafael Avila de Espindola <espindola@google.com> + + * archive.cc (Archive::include_member): Update calls to add_symbols. + * dynobj.cc (Sized_dynobj<size, big_endian>::make_version_map): Add + the Layout argument. + * dynobj.h (do_add_symbols): Add the Layout argument. + * object.cc (Sized_relobj<size, big_endian>::do_add_symbols): Add the + Layout argument. + * object.h (Object::add_symbols): Add the Layout argument. + (Object::do_add_symbols): Add the Layout argument. + (Sized_relobj::do_add_symbols): Add the Layout argument. + * plugin.cc (Sized_pluginobj<size, big_endian>::do_add_symbols): + Unify the two versions. + (Add_plugin_symbols): Remove. + * plugin.h (Pluginobj::add_symbols, Pluginobj::do_add_symbols): Remove. + (Sized_pluginobj::do_add_symbols): Unify the two versions. + (Add_plugin_symbols): Remove. + * readsyms.cc (Read_symbols::do_read_symbols): Update call to + Add_symbols. Use Add_symbols instead of Add_plugin_symbols. + (Add_symbols::run): Make it work with Pulginobj. + +2009-02-06 Ian Lance Taylor <iant@google.com> + + * object.cc (Sized_relobj::do_layout): Make info message start + with lower case letter. + +2009-02-06 Mikolaj Zalewski <mikolajz@google.com> + + * binary.cc: Fix file comment. + + * options.h (enum Incremental_disposition): Define. + (class General_options): Add new options: --incremental, + --incremental_changed, --incremental_unchanged, + --incremental_unknown. Add incremental_disposition_ and + implicit_incremental_ fields. + (General_options::incremental_disposition): New function. + (class Position_dependent_options): Add incremental_disposition + option. + (Position_dependent_options::copy_from_options): Set incremental + dispositions. + * options.cc (General_options::parse_incremental_changed): New + function. + (General_options::parse_incremental_unchanged): New function. + (General_options::parse_incremental_unknown): New function. + (General_options::General_options): Initialize new fields + incremental_disposition_ and implicit_incremental_. + (General_options::finalize): Check for uasge of --incremental-* + without --incremental. + +2009-02-06 Chris Demetriou <cgd@google.com> + + * gold.h (gold_undefined_symbol): Change to take only a Symbol + pointer and to report location as the file name associated with + the symbol. + (gold_undefined_symbol_at_location): New function to replace the + old gold_undefined_symbol functionality. + * target-reloc.h (relocate_section): Update to use + gold_undefined_symbol_at_location. + * symtab.cc (Symbol_table::warn_about_undefined_dynobj_symbol): + Call gold_undefined_symbol function rather than gold_error. + * errors.h (Errors::undefined_symbol): Take location as a + string, rather than calculating it from a relocation. + * errors.cc (Errors::fatal): Print "fatal error:" before the + formatted message. + (Errors::error, Errors::error_at_location): Print "error: " + before the formatted message. + (Errors::undefined_symbol): Take location as a string, rather + than calculating it from a relocation. + (gold_undefined_symbol_at_location): New function akin to + old gold_undefined_symbol, calculates location from relocation. + (gold_undefined_symbol): Change to take only a Symbol pointer + and to report location as the file name associated with the symbol. + * testsuite/debug_msg.sh: Update for changed error messages. + * testsuite/undef_symbol.sh: Likewise. + +2009-02-04 Duncan Sands <baldrick@free.fr> + + PR 9812 + * reduced_debug_output.h + (Output_reduced_debug_abbrev_section::failed): Use format for + gold_warning. + (Output_reduced_debug_info_section::faild): Likewise. + +2009-01-31 Mikolaj Zalewski <mikolajz@google.com> + + * script.cc (Lazy_demangler): New class. + (Version_script_info::get_symbol_version_helper): Demangle a + symbol only once. + +2009-01-29 Cary Coutant <ccoutant@google.com> + + * i386.cc (Target_i386::Relocate::relocate): Recognize non-PIC calls + to __tls_get_addr. + * x86_64.cc (Target_x86_64::Relocate::relocate): Likewise. + +2009-01-28 Ian Lance Taylor <iant@google.com> + + * version.cc (version_string): Bump to 1.9. + + * gold.h: Include <cstring> and <stdint.h>. + * version.cc: Include <cstdio>. + * object.cc (Sized_relobj::do_layout): Initialize gc_sd to avoid a + warning. + * reduced_debug_output.cc (insert_into_vector): Rename from + Insert_into_vector; change all callers. Use Swap_unaligned to + avoid aliasing issue; remove union since it is unnecessary. + +2009-01-27 Sriraman Tallam <tmsriram@google.com> + + * Makefile.am (CCFILES): Add gc.cc. + (HFILES): Add gc.h. + * Makefile.in: Regenerate. + * gold.cc (Gc_runner): New class. + (queue_initial_tasks): Call garbage collection related tasks + when corresponding options are invoked. + (queue_middle_gc_tasks): New function. + (queue_middle_tasks): Reorder tasks to allow relocs to be read and + processed early before laying out sections during garbage collection. + * gold.h (queue_middle_gc_tasks): New function. + (is_prefix_of): Move from "layout.cc". + * i386.cc (Target_i386::gc_process_relocs): New function. + * layout.cc (is_prefix_of): Remove. Move to "gold.h" + * main.cc (main): Create object of class "Garbage_collection". + * object.cc (Relobj::copy_symbols_data): New function. + (Relobj::is_section_name_included): New function. + (Sized_relobj::do_layout): Allow this function to be called twice + during garbage collection and defer layout of section during the + first call. + * object.h (Relobj::get_symbols_data): New function. + (Relobj::is_section_name_included): New function. + (Relobj::copy_symbols_data): New function. + (Relobj::set_symbols_data): New function. + (Relobj::get_relocs_data): New function. + (Relobj::set_relocs_data): New function. + (Relobj::is_output_section_offset_invalid): New pure virtual function. + (Relobj::gc_process_relocs): New function. + (Relobj::do_gc_process_relocs): New pure virtual function. + (Relobj::sd_): New data member. + (Sized_relobj::is_output_section_offset_invalid): New function. + (Sized_relobj::do_gc_process_relocs): New function. + * options.h (General_options::gc_sections): Modify to not be a no-op. + (General_options::print_gc_sections): New option. + * plugin.cc (Plugin_finish::run): Remove function call to + Plugin_manager::layout_deferred_objects. Move it to "gold.cc". + * powerpc.cc (Target_powerpc::gc_process_relocs): New function. + * reloc.cc (Read_relocs::run): Add task to process relocs and + determine unreferenced sections when doing garbage collection. + (Gc_process_relocs): New class. + (Sized_relobj::do_gc_process_relocs): New function. + (Sized_relobj::do_scan_relocs): Don't try to scan the relocs for + sections that are garbage collected. + * reloc.h (Gc_process_relocs): New class. + * sparc.cc (Target_sparc::gc_process_relocs): New function. + * symtab.cc (Symbol::should_add_dynsym_entry): Do not add entries for + symbols whose corresponding sections are garbage collected. + (Symbol_table::Symbol_table): Add new parameter for the garbage + collection object. + (Symbol_table::gc_mark_undef_symbols): New function. + (Symbol_table::gc_mark_symbol_for_shlib): New function. + (Symbol_table::gc_mark_dyn_syms): New function. + (Symbol_table::resolve): Do not treat symbols seen in dynamic objects + as garbage. + (Symbol_table::add_from_object): Likewise. + (Symbol_table::add_from_relobj): When building shared objects, do not + treat externally visible symbols as garbage. + (Symbol_table::sized_finalize_symbol): Do not check dynamic symbol + table information for static and relocatable links. + * symtab.h (Symbol_table::set_gc): New function. + (Symbol_table::gc): New function. + (Symbol_table::gc_mark_undef_symbols): New function. + (Symbol_table::gc_mark_symbol_for_shlib): New function. + (Symbol_table::gc_mark_dyn_syms): New function. + (Symbol_table::gc_): New data member. + * target.h (Sized_target::gc_process_relocs): New pure virtual + function. + * x86_64.cc (Target_x86_64::gc_process_relocs): New function. + * testsuite/testfile.cc (Target_test::gc_process_relocs): New function. + +2009-01-20 Chris Faylor <me.sourceware@sourceware.org> + + * options.h (General_options::gc_sections): Define as a no-op for now. + (General_options::no_keep_memory): Ditto. + (General_options::Bshareable): Define. + * options.cc (General_options::finalize): Honor -Bshareable. + +2009-01-20 Andreas Schwab <schwab@suse.de> + + * powerpc.cc (Powerpc_relocate_functions::rel16_ha): Don't try to + read the value in the contents, since we don't use it. Use the + template endianness when writing. + (Relocate::relocate): Use it for R_PPC_REL16_HA. + +2009-01-19 Andreas Schwab <schwab@suse.de> + + * configure.tgt (powerpc64-*): Fix targ_obj. + +2009-01-15 Ian Lance Taylor <iant@google.com> + + * object.cc (Sized_relobj::write_local_symbols): Don't write out + local symbols when stripping all symbols. + +2009-01-14 Cary Coutant <ccoutant@google.com> + + * output.cc (Output_reloc): Add explicit instantiations. + +2009-01-14 Cary Coutant <ccoutant@google.com> + + * archive.cc (Archive::get_elf_object_for_member): Remove call + to File_read::claim_for_plugin. + * descriptors.cc (Descriptors::open): Remove reference to + is_claimed. + (Descriptors::claim_for_plugin): Remove. + * descriptors.h (Descriptors::claim_for_plugin): Remove. + (Descriptors::is_claimed): Remove. + (claim_descriptor_for_plugin): Remove. + * fileread.cc (File_read::claim_for_plugin): Remove. + * fileread.h (File_read::claim_for_plugin): Remove. + (File_read::descriptor): Reopen descriptor if necessary. + * plugin.cc (Plugin::load): Add two new APIs to transfer vector. + (Plugin_manager::all_symbols_read): Add task parameter. Change + all callers. + (Plugin_manager::get_input_file): New function. + (Plugin_manager::release_input_file): New function. + (Pluginobj::Pluginobj): Add filesize parameter and initialize + corresponding data member. + (Sized_pluginobj::Sized_pluginobj): Add filesize parameter + and pass to base constructor. Change all callers. + (get_input_file, release_input_file): New functions. + (make_sized_plugin_object): Add filesize parameter. Change all callers. + * plugin.h (Plugin_manager::Plugin_manager): Initialize task_ member. + (Plugin_manager::all_symbols_read): Add task parameter. + (Plugin_manager::get_input_file): New function. + (Plugin_manager::release_input_file): New function. + (Plugin_manager::task_): New data member. + (Pluginobj::Pluginobj): Add filesize parameter. + (Pluginobj::filename): New function. + (Pluginobj::descriptor): New function. + (Pluginobj::filesize): New function. + (Pluginobj::filesize_): New data member. + (Sized_pluginobj::Sized_pluginobj): Add filesize parameter. + * readsyms.cc (Read_symbols::do_read_symbols): Remove call to + File_read::claim_for_plugin; use Object::unlock to unlock the file. + + * testsuite/Makefile.am (plugin_test_4): New test case for plugins + with archive libraries. + * testsuite/Makefile.in: Regenerate. + * testsuite/plugin_test.c (struct sym_info): New type. + (get_input_file, release_input_file): New static variables. + (onload): Capture new transfer vector entries. + (claim_file_hook): Stop reading at end of file according to filesize. + Factor out parsing of readelf output into separate function. + (all_symbols_read_hook): Exercise get_input_file and release_input_file + APIs and get the source file name from the symbol table. Convert + source file name to corresponding object file name. Print info + message when adding new input files. + (parse_readelf_line): New function. + * testsuite/plugin_test_1.sh: Add checks for new info messages. + * testsuite/plugin_test_2.sh: Likewise. + * testsuite/plugin_test_3.sh: Likewise. + * testsuite/plugin_test_4.sh: New test case. + +2009-01-07 Ian Lance Taylor <iant@google.com> + + * version.cc (version_string): Bump to 1.8. + +2008-12-23 Cary Coutant <ccoutant@google.com> + + * gold.cc (gold_exit): Call plugin cleanup handlers on exit. + * plugin.cc (Plugin_manager::finish): Rename as + layout_deferred_objects. Move cleanup to separate function. + (Plugin_manager::cleanup): New function. + (Plugin_finish::run): Call layout_deferred_objects and cleanup + separately. + * plugin.h (Plugin_manager::finish): Rename as + layout_deferred_objects. + (Plugin_manager::cleanup): New function. + (Plugin_manager::cleanup_done): New field. + +2008-12-23 Cary Coutant <ccoutant@google.com> + + * plugin.cc (is_visible_from_outside): New function. + (Pluginobj::get_symbol_resolution_info): Call is_visible_from_outside + so we don't return "IR only" status for exported symbols or -r links. + + * testsuite/Makefile.am (plugin_test_3): New test case. + * testsuite/Makefile.in: Regenerate. + * testsuite/plugin_test_3.sh: New file. + +2008-12-22 Cary Coutant <ccoutant@google.com> + + * object.cc (Sized_relobj::layout_section): New function. + (Sized_relobj::do_layout): Defer layout of input sections until after + plugin has provided replacement files. + (Sized_relobj::do_layout_deferred_sections): New function. + * object.h (Relobj::set_section_offset): Remove virtual keyword. + (Relobj::layout_deferred_sections): New function. + (Relobj::do_layout_deferred_sections): New function. + (Sized_relobj::do_layout_deferred_sections): New function. + (Sized_relobj::layout_section): New function. + (Sized_relobj::Deferred_layout): New structure. + (Sized_relobj::deferred_layout_): New field. + * plugin.cc (Plugin_manager::finish): Renamed, was cleanup. + Change all callers. Layout deferred sections. + (class Plugin_finish): Renamed, was Plugin_cleanup. Change all + references. + (Plugin_hook::run): Move code from do_plugin_hook inline. + (Plugin_hook::do_plugin_hook): Remove. + * plugin.h (Plugin_manager::Plugin_manager): Add missing initializers. + (Plugin_manager::finish): Renamed, was cleanup. + (Plugin_manager::should_defer_layout): New function. + (Plugin_manager::add_deferred_layout_object): New function. + (Plugin_manager::Deferred_layout_list): New type. + (Plugin_manager::deferred_layout_objects_): New field. + (Plugin_hook::do_plugin_hook): Remove. + +2008-12-17 Ian Lance Taylor <iant@google.com> + + * options.h (class General_options): Add --no case for + --export-dynamic. + +2008-12-16 Cary Coutant <ccoutant@google.com> + + * plugin.cc (Plugin::load): Move LDPT_MESSAGE to front of transfer + vector. + (Plugin_manager::claim_file): Create plugin object even if + plugin did not call the add_symbols callback. + (Plugin_obj::get_symbol_resolution_info): Guard against plugin + asking for more symbols than were added. + * testsuite/Makefile.am (plugin_test_1): Add test case with + no global symbols. + (empty.syms): New target. + * testsuite/Makefile.in: Regenerate. + * testsuite/plugin_test.c (claim_file_hook): Add new debug + message. Don't call add_symbols if no globals. + (all_symbols_read_hook): Don't provide replacement for empty + claimed file. + +2008-12-12 Ian Lance Taylor <iant@google.com> + + * target-reloc.h (Default_scan_relocatable_relocs): Only discard + r_type == 0 for a local symbol with r_sym == 0. + (scan_relocatable_relocs): Pass r_sym to + local_non_section_strategy. + * reloc.cc (Emit_relocs_strategy::local_non_section_strategy): Add + r_sym parameter. + + * configure.ac: Update test for TLS descriptors: they are + supported as of glibc 2.9. + * configure: Rebuild. + +2008-12-11 Ian Lance Taylor <iant@google.com> + + PR 7091 + * target-reloc.h (Default_scan_relocatable_relocs): For each + function, map r_type == 0 to RELOC_DISCARD. + +2008-12-10 Cary Coutant <ccoutant@google.com> + + * layout.cc (Layout::add_comdat): Allow COMDAT group from a replacement + object to override a kept COMDAT group from a plugin object. + +2008-12-09 Ian Lance Taylor <iant@google.com> + + PR 7088 + * yyscript.y (file_cmd): Handle INPUT. + + * testsuite/initpri1.c: Change all declarations to be full + prototypes by adding void, to avoid compiler warnings. + +2008-12-05 Rafael Avila de Espindola <espindola@google.com> + + * options.cc (General_options::parse_plugin_opt): New. + (General_options::add_plugin): The argument now is just the filename. + (General_options::add_plugin_option): New. + * options.h (plugin_opt): New. + (add_plugin): Change argument name. + (add_plugin_option): New. + * plugin.cc (Plugin::load): Don't parse the plugin option. + * plugin.h (Plugin::Plugin): Rename argument. Init filename_. + (Plugin::add_option): New. + (Plugin::args_): Change type. + (Plugin::filename_): New. + (Plugin_manager::add_plugin_option): New. + * testsuite/Makefile.am (plugin_test_1): Use new syntax. + * testsuite/Makefile.in: Regenerate. + +2008-12-05 Cary Coutant <ccoutant@google.com> + + * layout.cc (Layout::include_section): Check for SHF_EXCLUDE. + Handle --strip-lto-sections option. + * options.h (strip_lto_sections): New option. + +2008-12-01 Cary Coutant <ccoutant@google.com> + + * plugin.cc (ld_plugin_message): Change format parameter to const. + Fix mismatch between new[] and delete. + +2008-11-14 Cary Coutant <ccoutant@google.com> + + * reloc.cc (Sized_relobj::do_read_relocs): Use constant invalid_address + instead of -1U. + +2008-11-05 Craig Silverstein <csilvers@google.com> + + * options.cc (General_options::parse_dynamic_list): New function. + * options.h (General_options): New flags dynamic_list, + dynamic_list_data, dynamic_list_cpp_new, and + dynamic_list_cpp_typeinfo. New variable dynamic_list_. + (General_options::in_dynamic_list): New function. + * script.cc (Lex::Mode): New enum DYNAMIC_LIST. + (Lex::can_start_name): Add support for DYNAMIC_LIST mode. + (Lex::can_continue_name): Likewise. + (yylex): Likewise. + (read_script_file): New parameter script_options. + (read_dynamic_list): New function. + (Script_options::define_dynamic_list): New function. + (dynamic_list_keyword_parsecodes): New variable. + (dynamic_list_keywords): New variable. + * script.h (Script_options::define_dynamic_list): New function + prototype. + (read_dynamic_list): New function prototype. + * symtab.cc (strprefix): New macro. + (Symbol::should_add_dynsym_entry): Support dynamic_list, + dynamic_list_data, dynamic_list_cpp_new, and + dynamic_list_cpp_typeinfo. + * yyscript.y (PARSING_DYNAMIC_LIST): New token. + (dynamic_list_expr): New rule. + (dynamic_list_nodes): Likewise. + (dynamic_list_node): Likewise. + * testsuite/Makefile.am (dynamic_list): New test. + * testsuite/Makefile.in: Regenerated. + * testsuite/dynamic_list.t: New file. + * testsuite/dynamic_list.sh: New file. + +2008-11-05 Craig Silverstein <csilvers@google.com> + + * testsuite/tls_test_c.c: Add prototype for t11 and t11_last. + * testsuite/tls_test_c.c (t11): Add explicit "void" to prototype. + (t11_last): Likewise. + * testsuite/ver_test_6.c (main): Likewise. + +2008-10-07 Cary Coutant <ccoutant@google.com> + + * options.c (General_options::finalize): Add check for -static and + -shared. + * gold.cc (queue_middle_tasks): Assert that list of dynamic objects + is not empty. + +2008-10-02 Cary Coutant <ccoutant@google.com> + + * plugin.cc (make_sized_plugin_object): Fix conditional + compilation to work when not all targets are enabled. + +2008-09-29 Cary Coutant <ccoutant@google.com> + + * archive.cc (Archive::get_file_and_offset): Use filename instead + of name to get library path. + (Archive::include_member): Unlock external member of a thin archive. + + * testsuite/Makefile.am (TEST_AR): New variable. + (thin_archive_test_1): New test. + (thin_archive_test_2): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/thin_archive_main.cc: New file. + * testsuite/thin_archive_test_1.cc: New file. + * testsuite/thin_archive_test_2.cc: New file. + * testsuite/thin_archive_test_3.cc: New file. + * testsuite/thin_archive_test_4.cc: New file. + +2008-09-29 Cary Coutant <ccoutant@google.com> + + * mapfile.cc (Mapfile::print_input_section): Change -1U to -1ULL. + * object.cc (Sized_relobj::do_layout): Use constant invalid_address + instead of -1U. + (Sized_relobj::do_finalize_local_symbols): Likewise. + (Sized_relobj::map_to_kept_section): Likewise. + * object.h (Sized_relobj::invalid_address): New constant. + (Sized_relobj::do_output_section_offset): Check for invalid_address + and return -1ULL. + * output.cc (Output_reloc::local_section_offset): Use constant + invalid_address instead of -1U. + (Output_reloc::get_address): Likewise. + (Output_section::output_address): Change -1U to -1ULL. + * output.h (Output_reloc::invalid_address): New constant. + * reloc.cc (Sized_relobj::write_sections): Use constant + invalid_address instead of -1U. + (Sized_relobj::relocate_sections): Likewise. + * symtab.cc (Symbol_table::sized_finalize_symbol): Handle symbol + values for merge sections. + * target-reloc.h (relocate_for_relocatable): Use constant + invalid_address instead of -1U. + +2008-09-19 Cary Coutant <ccoutant@google.com> + + Add plugin functionality for link-time optimization (LTO). + * configure.ac (plugins): Add --enable-plugins option. + * configure: Regenerate. + * config.in: Regenerate. + * Makefile.am (LIBDL): New variable. + (CCFILES): Add plugin.cc. + (HFILES): Add plugin.h. + (ldadd_var): Add LIBDL. + * Makefile.in: Regenerate. + + * archive.cc: Include "plugin.h". + (Archive::setup): Don't preread archive symbols when using a plugin. + (Archive::get_file_and_offset): Add memsize parameter. Change callers. + (Archive::get_elf_object_for_member): Call plugin hooks for claiming + files. + (Archive::include_member): Add symbols from plugin objects. + * archive.h (Archive::get_file_and_offset): Add memsize parameter. + * descriptors.cc (Descriptors::open): Check for file descriptors + abandoned by plugins. + (Descriptors::claim_for_plugin): New function. + * descriptors.h (Descriptors::claim_for_plugin): New function. + (Open_descriptor::is_claimed): New field. + (claim_descriptor_for_plugin): New function. + * fileread.cc (File_read::claim_for_plugin): New function. + * fileread.h (File_read::claim_for_plugin): New function. + (File_read::descriptor): New function. + * gold.cc: Include "plugin.h". + (queue_initial_tasks): Add task to call plugin hooks for generating + new object files. + * main.cc: Include "plugin.h". + (main): Load plugin libraries. + * object.h (Pluginobj): Declare. + (Object::pluginobj): New function. + (Object::do_pluginobj): New function. + (Object::set_target): New function. + * options.cc: Include "plugin.h". + (General_options::parse_plugin): New function. + (General_options::General_options): Initialize plugins_ field. + (General_options::add_plugin): New function. + * options.h (Plugin_manager): Declare. + (General_options): Add --plugin option. + (General_options::has_plugins): New function. + (General_options::plugins): New function. + (General_options::add_plugin): New function. + (General_options::plugins_): New field. + * plugin.cc: New file. + * plugin.h: New file. + * readsyms.cc: Include "plugin.h". + (Read_symbols::do_read_symbols): Check for archive before checking + for ELF file. Call plugin hooks to claim files. + * resolve.cc (Symbol_table::resolve): Record when symbol is referenced + from a real object file; force override when processing replacement + files. + * symtab.cc (Symbol::init_fields): Initialize in_real_elf_ field. + (Symbol::init_base_object): Likewise. + (Symbol::init_base_output_data): Likewise. + (Symbol::init_base_output_segment): Likewise. + (Symbol::init_base_constant): Likewise. + (Symbol::init_base_undefined): Likewise. + (Symbol::output_section): Assert that object is not a plugin. + (Symbol_table::add_from_pluginobj): New function. + (Symbol_table::sized_finalize_symbol): Treat symbols from plugins as + undefined. + (Symbol_table::sized_write_globals): Likewise. + (Symbol_table::add_from_pluginobj): Instantiate template. + * symtab.h (Sized_pluginobj): Declare. + (Symbol::in_real_elf): New function. + (Symbol::set_in_real_elf): New function. + (Symbol::in_real_elf_): New field. + (Symbol_table::add_from_pluginobj): New function. + + * testsuite/Makefile.am (AM_CFLAGS): New variable. + (LIBDL): New variable. + (LDADD): Add LIBDL. + (check_PROGRAMS): Add plugin_test_1 and plugin_test_2. + (check_SCRIPTS): Add plugin_test_1.sh and plugin_test_2.sh. + (check_DATA): Add plugin_test_1.err and plugin_test_2.err. + (MOSTLYCLEANFILES): Likewise. + * testsuite/Makefile.in: Regenerate. + * testsuite/plugin_test.c: New file. + * testsuite/plugin_test_1.sh: New file. + * testsuite/plugin_test_2.sh: New file. + +2008-09-16 Ian Lance Taylor <iant@google.com> + + * target-reloc.h (relocate_section): Check whether a symbol is + defined by the ABI before reporting an undefined symbol error. + * target.h (Target::is_defined_by_abi): Make parameter const. + (Target::do_is_defined_by_abi): Likewise. + * i386.cc (Target_i386::do_is_defined_by_abi): Likewise. + * powerpc.cc (Target_powerpc::do_is_defined_by_abi): Likewise. + * sparc.cc (Target_sparc::do_is_defined_by_abi): Likewise. + * x86_64.cc (Target_x86_64::do_is_defined_by_abi): Likewise. + * testsuite/Makefile.am (tls_test_shared.so): Add -Wl,-z,defs. + * testsuite/Makefile.in: Rebuild. + + * fileread.cc (make_view): Add casts to avoid warning. + +2008-09-16 Alexandre Oliva <aoliva@redhat.com> + + * i386.cc (Target_i386::define_tls_base_symbol): Update comments. + * x86_64.cc (Target_x86_64::define_tls_base_symbol): Likewise. + +2008-09-16 Alexandre Oliva <aoliva@redhat.com> + + * options.h (General_options::output_is_executable): New. + (General_options::output_is_pie): New. + * i386.cc (Target_i386::define_tls_base_symbol): Use SEGMENT_START + for shared libraries. + * x86_64.cc (Target_x86_64::define_tls_base_symbol): Likewise. + +2008-09-11 Chris Demetriou <cgd@google.com> + + * options.h (origin): New -z option. + * layout.cc (Layout:finish_dynamic_section): If "-z origin" + is specified, set DF_ORIGIN in DT_FLAGS and set DF_1_ORIGIN + in DT_FLAGS_1. + +2008-09-05 Cary Coutant <ccoutant@google.com> + + * fileread.cc (File_read::make_view): Add check for attempt to map + beyond end of file. 2008-09-05 Cary Coutant <ccoutant@google.com> @@ -166,7 +5288,7 @@ * testsuite/script_test_2.cc (test_addr): Declare. (test_addr_alias): Declare. (main): Check that test_addr and test_addr_alias have the right - values. + values. * testsuite/script_test_2.t: Define test_addr_alias and test_addr. @@ -348,10 +5470,10 @@ * symtab.cc (Symbol_table::warn_about_undefined_dynobj_symbol): Include symbol version in error message. - + 2008-07-20 Chris Demetriou <cgd@google.com> - * configure.ac (gold_cv_c_random_seed): New configured variable. + * configure.ac (gold_cv_c_random_seed): New configured variable. (RANDOM_SEED_CFLAGS): New substituted variable. * Makefile.am (AM_CFLAGS, AM_CXXFLAGS): Add $(RANDOM_SEED_CFLAGS). * configure: Rebuild. @@ -530,7 +5652,7 @@ 2008-06-05 Kris Van Hees <kris.van.hees@oracle.com> PR 6584 - * binary.cc (Binary_to_elf::sized_convert): Fix .data + * binary.cc (Binary_to_elf::sized_convert): Fix .data alignment. 2008-05-30 Cary Coutant <ccoutant@google.com> @@ -1707,7 +6829,7 @@ for thin archives. Pass additional parameters to Archive::Archive. Unlock the archive file after calling Archive::setup. - + 2008-03-29 Ian Lance Taylor <iant@google.com> * symtab.cc (Symbol_table::do_define_as_constant): Don't force a @@ -2014,4 +7136,3 @@ 2008-03-21 Ian Lance Taylor <iant@google.com> * Added source code to GNU binutils. - diff --git a/binutils-2.19/gold/Makefile.am b/binutils-2.19/gold/Makefile.am index e706703..e0665e0 100644 --- a/binutils-2.19/gold/Makefile.am +++ b/binutils-2.19/gold/Makefile.am @@ -1,6 +1,6 @@ # Process this file with automake to generate Makefile.in -AUTOMAKE_OPTIONS = +AUTOMAKE_OPTIONS = foreign SUBDIRS = po testsuite @@ -11,7 +11,7 @@ ACLOCAL_AMFLAGS = -I ../bfd -I ../config AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) -INCLUDES = \ +AM_CPPFLAGS = \ -I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \ -DLOCALEDIR="\"$(datadir)/locale\"" \ -DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \ @@ -19,17 +19,27 @@ INCLUDES = \ LIBIBERTY = ../libiberty/libiberty.a +if PLUGINS +LIBDL = -ldl +endif + if THREADS THREADSLIB = -lpthread endif AM_YFLAGS = -d -noinst_PROGRAMS = ld-new +# Automake 1.10+ disables lex and yacc output file regeneration if +# maintainer mode is disabled. Avoid this. +am__skiplex = +am__skipyacc = + +noinst_PROGRAMS = ld-new incremental-dump noinst_LIBRARIES = libgold.a CCFILES = \ archive.cc \ + attributes.cc \ binary.cc \ common.cc \ compressed_output.cc \ @@ -44,8 +54,12 @@ CCFILES = \ errors.cc \ expression.cc \ fileread.cc \ + gc.cc \ gold.cc \ gold-threads.cc \ + icf.cc \ + incremental.cc \ + int_encoding.cc \ layout.cc \ mapfile.cc \ merge.cc \ @@ -53,6 +67,7 @@ CCFILES = \ options.cc \ output.cc \ parameters.cc \ + plugin.cc \ readsyms.cc \ reduced_debug_output.cc \ reloc.cc \ @@ -61,13 +76,17 @@ CCFILES = \ script.cc \ stringpool.cc \ symtab.cc \ + target.cc \ target-select.cc \ + timer.cc \ version.cc \ workqueue.cc \ workqueue-threads.cc HFILES = \ + arm-reloc-property.h \ archive.h \ + attributes.h \ binary.h \ common.h \ compressed_output.h \ @@ -81,8 +100,12 @@ HFILES = \ ehframe.h \ errors.h \ fileread.h \ + freebsd.h \ + gc.h \ gold.h \ gold-threads.h \ + icf.h \ + int_encoding.h \ layout.h \ mapfile.h \ merge.h \ @@ -90,6 +113,7 @@ HFILES = \ options.h \ output.h \ parameters.h \ + plugin.h \ readsyms.h \ reduced_debug_output.h \ reloc.h \ @@ -102,6 +126,7 @@ HFILES = \ target.h \ target-reloc.h \ target-select.h \ + timer.h \ tls.h \ token.h \ workqueue.h \ @@ -110,26 +135,37 @@ HFILES = \ YFILES = \ yyscript.y +DEFFILES = arm-reloc.def + EXTRA_DIST = yyscript.c yyscript.h TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc + i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) + i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ + arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) -libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) +libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) +libgold_a_LIBADD = $(LIBOBJS) sources_var = main.cc deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP) -ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) $(THREADSLIB) +ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \ + $(THREADSLIB) $(LIBDL) ld_new_SOURCES = $(sources_var) -ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS) -ld_new_LDADD = $(ldadd_var) $(LIBOBJS) +ld_new_DEPENDENCIES = $(deps_var) +ld_new_LDADD = $(ldadd_var) EXTRA_ld_new_SOURCES = $(TARGETSOURCES) +incremental_dump_SOURCES = incremental-dump.cc +incremental_dump_DEPENDENCIES = $(TARGETOBJS) libgold.a $(LIBIBERTY) \ + $(LIBINTL_DEP) +incremental_dump_LDADD = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \ + $(THREADSLIB) $(LIBDL) + # Use an explicit dependency for the bison generated header file. expression.$(OBJEXT): yyscript.h script-sections.$(OBJEXT): yyscript.h diff --git a/binutils-2.19/gold/Makefile.in b/binutils-2.19/gold/Makefile.in index bbc5417..29e1d1a 100644 --- a/binutils-2.19/gold/Makefile.in +++ b/binutils-2.19/gold/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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. @@ -17,15 +18,12 @@ # Process this file with automake to generate Makefile.in -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = . +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ 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 @@ -40,18 +38,19 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -noinst_PROGRAMS = ld-new$(EXEEXT) +noinst_PROGRAMS = ld-new$(EXEEXT) incremental-dump$(EXEEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@check_PROGRAMS = ld1$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ld2$(EXEEXT) ld1-r$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ld2-r$(EXEEXT) +subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \ $(srcdir)/../config.sub $(srcdir)/../depcomp \ $(srcdir)/../install-sh $(srcdir)/../missing \ - $(srcdir)/../mkinstalldirs $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.in \ - $(top_srcdir)/configure $(top_srcdir)/po/Make-in ChangeLog \ - NEWS TODO pread.c yyscript.c yyscript.h -subdir = . + $(srcdir)/../mkinstalldirs $(srcdir)/../ylwrap \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.in $(top_srcdir)/configure \ + $(top_srcdir)/po/Make-in ChangeLog NEWS TODO ffsll.c \ + ftruncate.c mremap.c pread.c yyscript.c yyscript.h ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/gettext-sister.m4 \ @@ -59,65 +58,76 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/nls.m4 \ $(top_srcdir)/../config/override.m4 \ $(top_srcdir)/../config/po.m4 \ - $(top_srcdir)/../config/proginstall.m4 \ $(top_srcdir)/../config/progtest.m4 \ $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno configure.status.lineno + configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = po/Makefile.in +CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libgold_a_AR = $(AR) $(ARFLAGS) -libgold_a_LIBADD = -am__objects_1 = archive.$(OBJEXT) binary.$(OBJEXT) common.$(OBJEXT) \ - compressed_output.$(OBJEXT) copy-relocs.$(OBJEXT) \ - cref.$(OBJEXT) defstd.$(OBJEXT) descriptors.$(OBJEXT) \ - dirsearch.$(OBJEXT) dynobj.$(OBJEXT) dwarf_reader.$(OBJEXT) \ - ehframe.$(OBJEXT) errors.$(OBJEXT) expression.$(OBJEXT) \ - fileread.$(OBJEXT) gold.$(OBJEXT) gold-threads.$(OBJEXT) \ - layout.$(OBJEXT) mapfile.$(OBJEXT) merge.$(OBJEXT) \ - object.$(OBJEXT) options.$(OBJEXT) output.$(OBJEXT) \ - parameters.$(OBJEXT) readsyms.$(OBJEXT) \ +libgold_a_DEPENDENCIES = $(LIBOBJS) +am__objects_1 = archive.$(OBJEXT) attributes.$(OBJEXT) \ + binary.$(OBJEXT) common.$(OBJEXT) compressed_output.$(OBJEXT) \ + copy-relocs.$(OBJEXT) cref.$(OBJEXT) defstd.$(OBJEXT) \ + descriptors.$(OBJEXT) dirsearch.$(OBJEXT) dynobj.$(OBJEXT) \ + dwarf_reader.$(OBJEXT) ehframe.$(OBJEXT) errors.$(OBJEXT) \ + expression.$(OBJEXT) fileread.$(OBJEXT) gc.$(OBJEXT) \ + gold.$(OBJEXT) gold-threads.$(OBJEXT) icf.$(OBJEXT) \ + incremental.$(OBJEXT) int_encoding.$(OBJEXT) layout.$(OBJEXT) \ + mapfile.$(OBJEXT) merge.$(OBJEXT) object.$(OBJEXT) \ + options.$(OBJEXT) output.$(OBJEXT) parameters.$(OBJEXT) \ + plugin.$(OBJEXT) readsyms.$(OBJEXT) \ reduced_debug_output.$(OBJEXT) reloc.$(OBJEXT) \ resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \ - stringpool.$(OBJEXT) symtab.$(OBJEXT) target-select.$(OBJEXT) \ - version.$(OBJEXT) workqueue.$(OBJEXT) \ - workqueue-threads.$(OBJEXT) + stringpool.$(OBJEXT) symtab.$(OBJEXT) target.$(OBJEXT) \ + target-select.$(OBJEXT) timer.$(OBJEXT) version.$(OBJEXT) \ + workqueue.$(OBJEXT) workqueue-threads.$(OBJEXT) am__objects_2 = am__objects_3 = yyscript.$(OBJEXT) am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \ - $(am__objects_3) + $(am__objects_3) $(am__objects_2) libgold_a_OBJECTS = $(am_libgold_a_OBJECTS) PROGRAMS = $(noinst_PROGRAMS) +am_incremental_dump_OBJECTS = incremental-dump.$(OBJEXT) +incremental_dump_OBJECTS = $(am_incremental_dump_OBJECTS) +am__DEPENDENCIES_1 = am__objects_4 = main.$(OBJEXT) am_ld_new_OBJECTS = $(am__objects_4) ld_new_OBJECTS = $(am_ld_new_OBJECTS) -am__DEPENDENCIES_1 = -am__DEPENDENCIES_2 = ../libiberty/libiberty.a -am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) libgold.a \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ +am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libgold.a $(LIBIBERTY) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) -am__DEPENDENCIES_4 = @LIBOBJS@ am__ld1_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_4) ld1_OBJECTS = $(am_ld1_OBJECTS) +ld1_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld1_LDFLAGS) \ + $(LDFLAGS) -o $@ am__ld1_r_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_r_OBJECTS = $(am__objects_4) ld1_r_OBJECTS = $(am_ld1_r_OBJECTS) +ld1_r_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld1_r_LDFLAGS) \ + $(LDFLAGS) -o $@ am__ld2_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld2_OBJECTS = $(am__objects_4) ld2_OBJECTS = $(am_ld2_OBJECTS) +ld2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld2_LDFLAGS) \ + $(LDFLAGS) -o $@ am__ld2_r_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld2_r_OBJECTS = $(am__objects_4) ld2_r_OBJECTS = $(am_ld2_r_OBJECTS) -DEFAULT_INCLUDES = -I. -I$(srcdir) -I. +ld2_r_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld2_r_LDFLAGS) \ + $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles +am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -127,37 +137,70 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ +@MAINTAINER_MODE_FALSE@am__skipyacc = test -f $@ || YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) -SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES) \ - $(EXTRA_ld_new_SOURCES) $(ld1_SOURCES) $(ld1_r_SOURCES) \ - $(ld2_SOURCES) $(ld2_r_SOURCES) -DIST_SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES) \ - $(EXTRA_ld_new_SOURCES) $(am__ld1_SOURCES_DIST) \ - $(am__ld1_r_SOURCES_DIST) $(am__ld2_SOURCES_DIST) \ - $(am__ld2_r_SOURCES_DIST) +YLWRAP = $(top_srcdir)/../ylwrap +SOURCES = $(libgold_a_SOURCES) $(incremental_dump_SOURCES) \ + $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES) $(ld1_SOURCES) \ + $(ld1_r_SOURCES) $(ld2_SOURCES) $(ld2_r_SOURCES) +DIST_SOURCES = $(libgold_a_SOURCES) $(incremental_dump_SOURCES) \ + $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES) \ + $(am__ld1_SOURCES_DIST) $(am__ld1_r_SOURCES_DIST) \ + $(am__ld2_SOURCES_DIST) $(am__ld2_r_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ - install-exec-recursive install-info-recursive \ - install-recursive installcheck-recursive installdirs-recursive \ - pdf-recursive ps-recursive uninstall-info-recursive \ - uninstall-recursive + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ - { test ! -d $(distdir) \ - || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr $(distdir); }; } + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -168,8 +211,6 @@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CONSTRUCTOR_PRIORITY_FALSE = @CONSTRUCTOR_PRIORITY_FALSE@ -CONSTRUCTOR_PRIORITY_TRUE = @CONSTRUCTOR_PRIORITY_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -185,15 +226,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -FN_PTRS_IN_SO_WITHOUT_PIC_FALSE = @FN_PTRS_IN_SO_WITHOUT_PIC_FALSE@ -FN_PTRS_IN_SO_WITHOUT_PIC_TRUE = @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@ -GCC_FALSE = @GCC_FALSE@ -GCC_TRUE = @GCC_TRUE@ GENCAT = @GENCAT@ GMSGFMT = @GMSGFMT@ -HAVE_ZLIB_FALSE = @HAVE_ZLIB_FALSE@ -HAVE_ZLIB_TRUE = @HAVE_ZLIB_TRUE@ +GREP = @GREP@ INCINTL = @INCINTL@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ @@ -208,23 +245,19 @@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ -NATIVE_LINKER_FALSE = @NATIVE_LINKER_FALSE@ -NATIVE_LINKER_TRUE = @NATIVE_LINKER_TRUE@ NO_WERROR = @NO_WERROR@ OBJEXT = @OBJEXT@ -OMP_SUPPORT_FALSE = @OMP_SUPPORT_FALSE@ -OMP_SUPPORT_TRUE = @OMP_SUPPORT_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ @@ -232,32 +265,21 @@ RANDOM_SEED_CFLAGS = @RANDOM_SEED_CFLAGS@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_TLS_FALSE = @STATIC_TLS_FALSE@ -STATIC_TLS_TRUE = @STATIC_TLS_TRUE@ STRIP = @STRIP@ TARGETOBJS = @TARGETOBJS@ -THREADS_FALSE = @THREADS_FALSE@ -THREADS_TRUE = @THREADS_TRUE@ -TLS_DESCRIPTORS_FALSE = @TLS_DESCRIPTORS_FALSE@ -TLS_DESCRIPTORS_TRUE = @TLS_DESCRIPTORS_TRUE@ -TLS_FALSE = @TLS_FALSE@ -TLS_GNU2_DIALECT_FALSE = @TLS_GNU2_DIALECT_FALSE@ -TLS_GNU2_DIALECT_TRUE = @TLS_GNU2_DIALECT_TRUE@ -TLS_TRUE = @TLS_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_CXXFLAGS = @WARN_CXXFLAGS@ XGETTEXT = @XGETTEXT@ YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ -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__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -269,50 +291,69 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ +htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ +psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -AUTOMAKE_OPTIONS = +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign SUBDIRS = po testsuite tooldir = $(exec_prefix)/$(target_alias) ACLOCAL_AMFLAGS = -I ../bfd -I ../config AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) $(RANDOM_SEED_CFLAGS) -INCLUDES = \ +AM_CPPFLAGS = \ -I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \ -DLOCALEDIR="\"$(datadir)/locale\"" \ -DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \ @INCINTL@ LIBIBERTY = ../libiberty/libiberty.a +@PLUGINS_TRUE@LIBDL = -ldl @THREADS_TRUE@THREADSLIB = -lpthread AM_YFLAGS = -d + +# Automake 1.10+ disables lex and yacc output file regeneration if +# maintainer mode is disabled. Avoid this. +am__skiplex = +am__skipyacc = noinst_LIBRARIES = libgold.a CCFILES = \ archive.cc \ + attributes.cc \ binary.cc \ common.cc \ compressed_output.cc \ @@ -327,8 +368,12 @@ CCFILES = \ errors.cc \ expression.cc \ fileread.cc \ + gc.cc \ gold.cc \ gold-threads.cc \ + icf.cc \ + incremental.cc \ + int_encoding.cc \ layout.cc \ mapfile.cc \ merge.cc \ @@ -336,6 +381,7 @@ CCFILES = \ options.cc \ output.cc \ parameters.cc \ + plugin.cc \ readsyms.cc \ reduced_debug_output.cc \ reloc.cc \ @@ -344,13 +390,17 @@ CCFILES = \ script.cc \ stringpool.cc \ symtab.cc \ + target.cc \ target-select.cc \ + timer.cc \ version.cc \ workqueue.cc \ workqueue-threads.cc HFILES = \ + arm-reloc-property.h \ archive.h \ + attributes.h \ binary.h \ common.h \ compressed_output.h \ @@ -364,8 +414,12 @@ HFILES = \ ehframe.h \ errors.h \ fileread.h \ + freebsd.h \ + gc.h \ gold.h \ gold-threads.h \ + icf.h \ + int_encoding.h \ layout.h \ mapfile.h \ merge.h \ @@ -373,6 +427,7 @@ HFILES = \ options.h \ output.h \ parameters.h \ + plugin.h \ readsyms.h \ reduced_debug_output.h \ reloc.h \ @@ -385,6 +440,7 @@ HFILES = \ target.h \ target-reloc.h \ target-select.h \ + timer.h \ tls.h \ token.h \ workqueue.h \ @@ -393,21 +449,33 @@ HFILES = \ YFILES = \ yyscript.y +DEFFILES = arm-reloc.def EXTRA_DIST = yyscript.c yyscript.h TARGETSOURCES = \ - i386.cc x86_64.cc sparc.cc powerpc.cc + i386.cc x86_64.cc sparc.cc powerpc.cc arm.cc arm-reloc-property.cc ALL_TARGETOBJS = \ - i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) + i386.$(OBJEXT) x86_64.$(OBJEXT) sparc.$(OBJEXT) powerpc.$(OBJEXT) \ + arm.$(OBJEXT) arm-reloc-property.$(OBJEXT) -libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) +libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES) +libgold_a_LIBADD = $(LIBOBJS) sources_var = main.cc deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP) -ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) $(THREADSLIB) +ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \ + $(THREADSLIB) $(LIBDL) + ld_new_SOURCES = $(sources_var) -ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS) -ld_new_LDADD = $(ldadd_var) $(LIBOBJS) +ld_new_DEPENDENCIES = $(deps_var) +ld_new_LDADD = $(ldadd_var) EXTRA_ld_new_SOURCES = $(TARGETSOURCES) +incremental_dump_SOURCES = incremental-dump.cc +incremental_dump_DEPENDENCIES = $(TARGETOBJS) libgold.a $(LIBIBERTY) \ + $(LIBINTL_DEP) + +incremental_dump_LDADD = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \ + $(THREADSLIB) $(LIBDL) + POTFILES = $(CCFILES) $(HFILES) $(TARGETSOURCES) @GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_SOURCES = $(sources_var) @GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_DEPENDENCIES = $(deps_var) gcctestdir1/ld @@ -437,15 +505,15 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ - cd $(srcdir) && $(AUTOMAKE) --foreign \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -461,21 +529,22 @@ $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENC $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(srcdir) && $(AUTOCONF) + $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ - $(MAKE) stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_srcdir) && $(AUTOHEADER) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ @@ -489,7 +558,7 @@ clean-noinstLIBRARIES: yyscript.h: yyscript.c @if test ! -f $@; then \ rm -f yyscript.c; \ - $(MAKE) yyscript.c; \ + $(MAKE) $(AM_MAKEFLAGS) yyscript.c; \ else :; fi libgold.a: $(libgold_a_OBJECTS) $(libgold_a_DEPENDENCIES) -rm -f libgold.a @@ -501,21 +570,24 @@ clean-checkPROGRAMS: clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) +incremental-dump$(EXEEXT): $(incremental_dump_OBJECTS) $(incremental_dump_DEPENDENCIES) + @rm -f incremental-dump$(EXEEXT) + $(CXXLINK) $(incremental_dump_OBJECTS) $(incremental_dump_LDADD) $(LIBS) ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES) @rm -f ld-new$(EXEEXT) - $(CXXLINK) $(ld_new_LDFLAGS) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS) + $(CXXLINK) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS) ld1$(EXEEXT): $(ld1_OBJECTS) $(ld1_DEPENDENCIES) @rm -f ld1$(EXEEXT) - $(CXXLINK) $(ld1_LDFLAGS) $(ld1_OBJECTS) $(ld1_LDADD) $(LIBS) + $(ld1_LINK) $(ld1_OBJECTS) $(ld1_LDADD) $(LIBS) ld1-r$(EXEEXT): $(ld1_r_OBJECTS) $(ld1_r_DEPENDENCIES) @rm -f ld1-r$(EXEEXT) - $(CXXLINK) $(ld1_r_LDFLAGS) $(ld1_r_OBJECTS) $(ld1_r_LDADD) $(LIBS) + $(ld1_r_LINK) $(ld1_r_OBJECTS) $(ld1_r_LDADD) $(LIBS) ld2$(EXEEXT): $(ld2_OBJECTS) $(ld2_DEPENDENCIES) @rm -f ld2$(EXEEXT) - $(CXXLINK) $(ld2_LDFLAGS) $(ld2_OBJECTS) $(ld2_LDADD) $(LIBS) + $(ld2_LINK) $(ld2_OBJECTS) $(ld2_LDADD) $(LIBS) ld2-r$(EXEEXT): $(ld2_r_OBJECTS) $(ld2_r_DEPENDENCIES) @rm -f ld2-r$(EXEEXT) - $(CXXLINK) $(ld2_r_LDFLAGS) $(ld2_r_OBJECTS) $(ld2_r_LDADD) $(LIBS) + $(ld2_r_LINK) $(ld2_r_OBJECTS) $(ld2_r_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -523,8 +595,14 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ffsll.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ftruncate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/mremap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/pread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm-reloc-property.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attributes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/binary.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compressed_output.Po@am__quote@ @@ -539,9 +617,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expression.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold-threads.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental-dump.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/incremental.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int_encoding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@ @@ -550,6 +633,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parameters.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/powerpc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readsyms.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reduced_debug_output.Po@am__quote@ @@ -561,6 +645,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringpool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/symtab.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target-select.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/target.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workqueue-threads.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/workqueue.Po@am__quote@ @@ -568,54 +654,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yyscript.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 +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @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 +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @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) '$<'` .cc.o: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .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: + $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -641,15 +708,14 @@ $(RECURSIVE_TARGETS): else \ local_target="$$target"; \ fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" -mostlyclean-recursive clean-recursive distclean-recursive \ -maintainer-clean-recursive: +$(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ @@ -676,16 +742,16 @@ maintainer-clean-recursive: else \ local_target="$$target"; \ fi; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ - test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -693,14 +759,14 @@ ID: $(HEADERS) $(SOURCES) $(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; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ @@ -712,39 +778,43 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ - tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.in $(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 \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.in $(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" \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -752,7 +822,8 @@ distclean-tags: check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ - list='$(TESTS)'; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ @@ -761,49 +832,63 @@ check-TESTS: $(TESTS) if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *" $$tst "*) \ + *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ - echo "XPASS: $$tst"; \ + col=$$red; res=XPASS; \ ;; \ *) \ - echo "PASS: $$tst"; \ + col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *" $$tst "*) \ + *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ - echo "XFAIL: $$tst"; \ + col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ - echo "FAIL: $$tst"; \ + col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ - echo "SKIP: $$tst"; \ + col=$$blu; res=SKIP; \ fi; \ + echo "$${col}$$res$${std}: $$tst"; \ done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ - banner="All $$all tests passed"; \ + banner="$$All$$all $$tests passed"; \ else \ - banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all tests failed"; \ + banner="$$failed of $$all $$tests failed"; \ else \ - banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ - skipped="($$skip tests were not run)"; \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ @@ -814,64 +899,84 @@ check-TESTS: $(TESTS) dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ - echo "$$dashes"; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ - echo "$$dashes"; \ + echo "$$dashes$$std"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) $(am__remove_distdir) - mkdir $(distdir) - $(mkdir_p) $(distdir)/.. $(distdir)/../bfd $(distdir)/../config $(distdir)/po - @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; \ + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ 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 \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done - list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ - || $(mkdir_p) "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ - distdir=`$(am__cd) $(distdir) && pwd`; \ - top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ - (cd $$subdir && \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ - top_distdir="$$top_distdir" \ - distdir="$$distdir/$$subdir" \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done - -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r $(distdir) + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) @@ -880,6 +985,14 @@ dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) @@ -906,6 +1019,10 @@ distcheck: dist GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ @@ -917,9 +1034,11 @@ distcheck: dist mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && cd $(distdir)/_build \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ @@ -941,13 +1060,15 @@ distcheck: dist && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: - @cd $(distuninstallcheck_dir) \ + @$(am__cd) '$(distuninstallcheck_dir)' \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ @@ -991,6 +1112,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -1015,18 +1137,38 @@ dvi-am: html: html-recursive +html-am: + info: info-recursive info-am: install-data-am: install-data-local +install-dvi: install-dvi-recursive + +install-dvi-am: + install-exec-am: install-exec-local +install-html: install-html-recursive + +install-html-am: + install-info: install-info-recursive +install-info-am: + install-man: +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-recursive @@ -1048,26 +1190,28 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-info-am - -uninstall-info: uninstall-info-recursive - -.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ - check-TESTS check-am clean clean-checkPROGRAMS clean-generic \ - clean-noinstLIBRARIES clean-noinstPROGRAMS clean-recursive \ - ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ - dist-shar dist-tarZ dist-zip distcheck distclean \ - distclean-compile distclean-generic distclean-hdr \ - distclean-recursive distclean-tags distcleancheck distdir \ - distuninstallcheck dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am \ - install-data-local install-exec install-exec-am \ - install-exec-local install-info install-info-am install-man \ +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check-am \ + ctags-recursive install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-noinstLIBRARIES \ + clean-noinstPROGRAMS ctags ctags-recursive dist dist-all \ + dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ dist-xz \ + dist-zip distcheck distclean distclean-compile \ + distclean-generic distclean-hdr distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-data install-data-am \ + install-data-local install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-local install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ - maintainer-clean-recursive mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \ - tags tags-recursive uninstall uninstall-am uninstall-info-am + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags tags-recursive uninstall uninstall-am # Use an explicit dependency for the bison generated header file. @@ -1134,6 +1278,7 @@ po/POTFILES.in: @MAINT@ Makefile @GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "#!/bin/sh" > $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "cmp ld1-r ld2-r" > $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@ chmod +x $@ + # 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/binutils-2.19/gold/README b/binutils-2.19/gold/README index 49de60a..80da455 100644 --- a/binutils-2.19/gold/README +++ b/binutils-2.19/gold/README @@ -17,10 +17,7 @@ omissions--features of the GNU linker not currently supported in gold--are: * MEMORY regions in linker scripts * MRI compatible linker scripts - * linker map files (-M, -Map) * cross-reference reports (--cref) - * linker garbage collection (--gc-sections) - * position independent executables (-pie) * various other minor options @@ -51,3 +48,16 @@ of work. Task objects are stored on a single Workqueue object. Tasks communicate via Task_token objects. Task_token objects are only manipulated while holding the master Workqueue lock. Relatively few mutexes are used. + + +Build requirements +================== + +The gold source code uses templates heavily. Building it requires a +recent version of g++. g++ 4.0.3 is known to work. g++ 3.2 and g++ +3.4.3 are known to fail. + +The linker script parser uses features which are only in newer +versions of bison. bison 2.3 is known to work. bison 1.26 is known +to fail. If you are building gold from an official binutils release, +the bison output should already be included. diff --git a/binutils-2.19/gold/aclocal.m4 b/binutils-2.19/gold/aclocal.m4 index d916a49..db48652 100644 --- a/binutils-2.19/gold/aclocal.m4 +++ b/binutils-2.19/gold/aclocal.m4 @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.9.6 -*- Autoconf -*- +# generated automatically by aclocal 1.11 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file 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. @@ -11,7 +11,15 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. -# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],, +[m4_warning([this file was generated for autoconf 2.64. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -21,14 +29,31 @@ # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.9.6])]) +[AM_AUTOMAKE_VERSION([1.11])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- @@ -85,14 +110,14 @@ am_aux_dir=`cd $ac_aux_dir && pwd` # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file 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. -# serial 7 +# serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- @@ -101,8 +126,11 @@ AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE]) -AC_SUBST([$1_FALSE]) +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' @@ -116,15 +144,14 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # # This file 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. -# serial 8 +# serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, @@ -152,6 +179,7 @@ AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) @@ -180,6 +208,16 @@ AC_CACHE_CHECK([dependency style of $depcc], if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -197,7 +235,17 @@ AC_CACHE_CHECK([dependency style of $depcc], done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -207,18 +255,23 @@ AC_CACHE_CHECK([dependency style of $depcc], break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -269,61 +322,74 @@ if test "x$enable_dependency_tracking" != xno; then AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. -#serial 3 +#serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done done -done +} ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -354,14 +420,14 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file 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. -# serial 12 +# serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. @@ -378,16 +444,20 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.58])dnl +[AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi fi # test whether we have cygpath @@ -407,6 +477,9 @@ m4_ifval([$2], AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl @@ -422,8 +495,8 @@ AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) -AM_PROG_INSTALL_SH -AM_PROG_INSTALL_STRIP +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. @@ -431,20 +504,37 @@ AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header @@ -455,18 +545,19 @@ AC_PROVIDE_IFELSE([AC_PROG_CXX], # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. +_am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $1 | $1:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -477,33 +568,51 @@ echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"$am_aux_dir/install-sh"} +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi AC_SUBST(install_sh)]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005 +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. -# serial 4 +# serial 5 +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], -[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) - dnl maintainer-mode is disabled by default - AC_ARG_ENABLE(maintainer-mode, -[ --enable-maintainer-mode enable make rules and dependencies not useful +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful (and sometimes confusing) to the casual installer], - USE_MAINTAINER_MODE=$enableval, - USE_MAINTAINER_MODE=no) + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) - AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE - AC_SUBST(MAINT)dnl + AC_SUBST([MAINT])dnl ] ) @@ -511,13 +620,13 @@ AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file 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. -# serial 3 +# serial 4 # AM_MAKE_INCLUDE() # ----------------- @@ -526,7 +635,7 @@ AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: - @echo done + @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. @@ -536,24 +645,24 @@ am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) @@ -563,14 +672,14 @@ rm -f confinc confmf # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. -# serial 4 +# serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ @@ -586,7 +695,15 @@ AC_SUBST($1)]) # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " @@ -596,7 +713,7 @@ else fi ]) -# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -604,70 +721,33 @@ fi # AM_PROG_MKDIR_P # --------------- -# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. -# -# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories -# created by `make install' are always world readable, even if the -# installer happens to have an overly restrictive umask (e.g. 077). -# This was a mistake. There are at least two reasons why we must not -# use `-m 0755': -# - it causes special bits like SGID to be ignored, -# - it may be too restrictive (some setups expect 775 directories). -# -# Do not use -m 0755 and let people choose whatever they expect by -# setting umask. -# -# We cannot accept any implementation of `mkdir' that recognizes `-p'. -# Some implementations (such as Solaris 8's) are not thread-safe: if a -# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' -# concurrently, both version can detect that a/ is missing, but only -# one can create it and the other will error out. Consequently we -# restrict ourselves to GNU make (using the --version option ensures -# this.) +# Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], -[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi -AC_SUBST([mkdir_p])]) +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file 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. -# serial 3 +# serial 4 # _AM_MANGLE_OPTION(NAME) # ----------------------- @@ -684,7 +764,7 @@ AC_DEFUN([_AM_SET_OPTION], # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], -[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- @@ -694,14 +774,14 @@ AC_DEFUN([_AM_IF_OPTION], # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. -# serial 4 +# serial 5 # AM_SANITY_CHECK # --------------- @@ -710,16 +790,29 @@ AC_DEFUN([AM_SANITY_CHECK], # Just in case sleep 1 echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` + set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ @@ -769,9 +862,28 @@ dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file 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. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. @@ -874,6 +986,5 @@ m4_include([../config/lead-dot.m4]) m4_include([../config/nls.m4]) m4_include([../config/override.m4]) m4_include([../config/po.m4]) -m4_include([../config/proginstall.m4]) m4_include([../config/progtest.m4]) m4_include([../bfd/warning.m4]) diff --git a/binutils-2.19/gold/archive.cc b/binutils-2.19/gold/archive.cc index f5ad574..a8b0fc6 100644 --- a/binutils-2.19/gold/archive.cc +++ b/binutils-2.19/gold/archive.cc @@ -1,6 +1,6 @@ // archive.cc -- archive support for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -37,6 +37,7 @@ #include "symtab.h" #include "object.h" #include "archive.h" +#include "plugin.h" namespace gold { @@ -82,11 +83,22 @@ const char Archive::armagt[sarmag] = const char Archive::arfmag[2] = { '`', '\n' }; +Archive::Archive(const std::string& name, Input_file* input_file, + bool is_thin_archive, Dirsearch* dirpath, Task* task) + : name_(name), input_file_(input_file), armap_(), armap_names_(), + extended_names_(), armap_checked_(), seen_offsets_(), members_(), + is_thin_archive_(is_thin_archive), included_member_(false), + nested_archives_(), dirpath_(dirpath), task_(task), num_members_(0) +{ + this->no_export_ = + parameters->options().check_excluded_libs(input_file->found_name()); +} + // Set up the archive: read the symbol map and the extended name // table. void -Archive::setup(Input_objects* input_objects) +Archive::setup() { // We need to ignore empty archives. if (this->input_file_->file().filesize() == sarmag) @@ -126,9 +138,12 @@ Archive::setup(Input_objects* input_objects) && parameters->options().preread_archive_symbols()); #ifndef ENABLE_THREADS preread_syms = false; +#else + if (parameters->options().has_plugins()) + preread_syms = false; #endif if (preread_syms) - this->read_all_symbols(input_objects); + this->read_all_symbols(); } // Unlock any nested archives. @@ -260,7 +275,8 @@ Archive::interpret_header(const Archive_header* hdr, off_t off, else if (hdr->ar_name[1] == ' ') { // This is the symbol table. - pname->clear(); + if (!pname->empty()) + pname->clear(); } else if (hdr->ar_name[1] == '/') { @@ -437,13 +453,12 @@ Archive::end() // to the name of the archive member. Return TRUE on success. bool -Archive::get_file_and_offset(off_t off, Input_objects* input_objects, - Input_file** input_file, off_t* memoff, - std::string* member_name) +Archive::get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff, + off_t* memsize, std::string* member_name) { off_t nested_off; - this->read_header(off, false, member_name, &nested_off); + *memsize = this->read_header(off, false, member_name, &nested_off); *input_file = this->input_file_; *memoff = off + static_cast<off_t>(sizeof(Archive_header)); @@ -455,11 +470,11 @@ Archive::get_file_and_offset(off_t off, Input_objects* input_objects, // to the directory containing the archive. if (!IS_ABSOLUTE_PATH(member_name->c_str())) { - const char* arch_path = this->name().c_str(); + const char* arch_path = this->filename().c_str(); const char* basename = lbasename(arch_path); if (basename > arch_path) member_name->replace(0, 0, - this->name().substr(0, basename - arch_path)); + this->filename().substr(0, basename - arch_path)); } if (nested_off > 0) @@ -475,101 +490,108 @@ Archive::get_file_and_offset(off_t off, Input_objects* input_objects, else { Input_file_argument* input_file_arg = - new Input_file_argument(member_name->c_str(), false, "", false, - parameters->options()); + new Input_file_argument(member_name->c_str(), + Input_file_argument::INPUT_FILE_TYPE_FILE, + "", false, parameters->options()); *input_file = new Input_file(input_file_arg); - if (!(*input_file)->open(parameters->options(), *this->dirpath_, - this->task_)) + int dummy = 0; + if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy)) return false; arch = new Archive(*member_name, *input_file, false, this->dirpath_, this->task_); - arch->setup(input_objects); + arch->setup(); std::pair<Nested_archive_table::iterator, bool> ins = this->nested_archives_.insert(std::make_pair(*member_name, arch)); gold_assert(ins.second); } - return arch->get_file_and_offset(nested_off, input_objects, - input_file, memoff, member_name); + return arch->get_file_and_offset(nested_off, input_file, memoff, + memsize, member_name); } // This is an external member of a thin archive. Open the // file as a regular relocatable object file. Input_file_argument* input_file_arg = - new Input_file_argument(member_name->c_str(), false, "", false, - this->input_file_->options()); + new Input_file_argument(member_name->c_str(), + Input_file_argument::INPUT_FILE_TYPE_FILE, + "", false, this->input_file_->options()); *input_file = new Input_file(input_file_arg); - if (!(*input_file)->open(parameters->options(), *this->dirpath_, - this->task_)) + int dummy = 0; + if (!(*input_file)->open(*this->dirpath_, this->task_, &dummy)) return false; *memoff = 0; + *memsize = (*input_file)->file().filesize(); return true; } -// Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to -// the name of the member. +// Return an ELF object for the member at offset OFF. If the ELF +// object has an unsupported target type, set *PUNCONFIGURED to true +// and return NULL. Object* -Archive::get_elf_object_for_member(off_t off, Input_objects* input_objects) +Archive::get_elf_object_for_member(off_t off, bool* punconfigured) { - std::string member_name; + *punconfigured = false; + Input_file* input_file; off_t memoff; - - if (!this->get_file_and_offset(off, input_objects, &input_file, &memoff, - &member_name)) + off_t memsize; + std::string member_name; + if (!this->get_file_and_offset(off, &input_file, &memoff, &memsize, + &member_name)) return NULL; - off_t filesize = input_file->file().filesize(); - int read_size = elfcpp::Elf_sizes<64>::ehdr_size; - if (filesize - memoff < read_size) - read_size = filesize - memoff; - - if (read_size < 4) + if (parameters->options().has_plugins()) { - gold_error(_("%s: member at %zu is not an ELF object"), - this->name().c_str(), static_cast<size_t>(off)); - return NULL; + Object* obj = parameters->options().plugins()->claim_file(input_file, + memoff, + memsize); + if (obj != NULL) + { + // The input file was claimed by a plugin, and its symbols + // have been provided by the plugin. + return obj; + } } - const unsigned char* ehdr = input_file->file().get_view(memoff, 0, read_size, - true, false); - - static unsigned char elfmagic[4] = - { - elfcpp::ELFMAG0, elfcpp::ELFMAG1, - elfcpp::ELFMAG2, elfcpp::ELFMAG3 - }; - if (memcmp(ehdr, elfmagic, 4) != 0) + const unsigned char* ehdr; + int read_size; + if (!is_elf_object(input_file, memoff, &ehdr, &read_size)) { gold_error(_("%s: member at %zu is not an ELF object"), this->name().c_str(), static_cast<size_t>(off)); return NULL; } - return make_elf_object((std::string(this->input_file_->filename()) + Object *obj = make_elf_object((std::string(this->input_file_->filename()) + "(" + member_name + ")"), - input_file, memoff, ehdr, read_size); + input_file, memoff, ehdr, read_size, + punconfigured); + if (obj == NULL) + return NULL; + obj->set_no_export(this->no_export()); + return obj; } // Read the symbols from all the archive members in the link. void -Archive::read_all_symbols(Input_objects* input_objects) +Archive::read_all_symbols() { for (Archive::const_iterator p = this->begin(); p != this->end(); ++p) - this->read_symbols(input_objects, p->off); + this->read_symbols(p->off); } // Read the symbols from an archive member in the link. OFF is the file // offset of the member header. void -Archive::read_symbols(Input_objects* input_objects, off_t off) +Archive::read_symbols(off_t off) { - Object* obj = this->get_elf_object_for_member(off, input_objects); + bool dummy; + Object* obj = this->get_elf_object_for_member(off, &dummy); if (obj == NULL) return; @@ -585,9 +607,11 @@ Archive::read_symbols(Input_objects* input_objects, off_t off) // the symbol table. If it exists as a strong undefined symbol, we // pull in the corresponding element. We have to do this in a loop, // since pulling in one element may create new undefined symbols which -// may be satisfied by other objects in the archive. +// may be satisfied by other objects in the archive. Return true in +// the normal case, false if the first member we tried to add from +// this archive had an incompatible target. -void +bool Archive::add_symbols(Symbol_table* symtab, Layout* layout, Input_objects* input_objects, Mapfile* mapfile) { @@ -611,6 +635,8 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, // Track which symbols in the symbol table we've already found to be // defined. + char* tmpbuf = NULL; + size_t tmpbuflen = 0; bool added_new_object; do { @@ -634,7 +660,41 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, const char* sym_name = (this->armap_names_.data() + this->armap_[i].name_offset); - Symbol* sym = symtab->lookup(sym_name); + + // In an object file, and therefore in an archive map, an + // '@' in the name separates the symbol name from the + // version name. If there are two '@' characters, this is + // the default version. + const char* ver = strchr(sym_name, '@'); + bool def = false; + if (ver != NULL) + { + size_t symlen = ver - sym_name; + if (symlen + 1 > tmpbuflen) + { + tmpbuf = static_cast<char*>(realloc(tmpbuf, symlen + 1)); + tmpbuflen = symlen + 1; + } + memcpy(tmpbuf, sym_name, symlen); + tmpbuf[symlen] = '\0'; + sym_name = tmpbuf; + + ++ver; + if (*ver == '@') + { + ++ver; + def = true; + } + } + + Symbol* sym = symtab->lookup(sym_name, ver); + if (def + && ver != NULL + && (sym == NULL + || !sym->is_undefined() + || sym->binding() == elfcpp::STB_WEAK)) + sym = symtab->lookup(sym_name, NULL); + if (sym == NULL) { // Check whether the symbol was named in a -u option. @@ -660,20 +720,31 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout, why = "-u "; why += sym_name; } - this->include_member(symtab, layout, input_objects, - last_seen_offset, mapfile, sym, why.c_str()); + if (!this->include_member(symtab, layout, input_objects, + last_seen_offset, mapfile, sym, + why.c_str())) + { + if (tmpbuf != NULL) + free(tmpbuf); + return false; + } added_new_object = true; } } while (added_new_object); + if (tmpbuf != NULL) + free(tmpbuf); + input_objects->archive_stop(this); + + return true; } // Include all the archive members in the link. This is for --whole-archive. -void +bool Archive::include_all_members(Symbol_table* symtab, Layout* layout, Input_objects* input_objects, Mapfile* mapfile) { @@ -686,8 +757,9 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout, p != this->members_.end(); ++p) { - this->include_member(symtab, layout, input_objects, p->first, - mapfile, NULL, "--whole-archive"); + if (!this->include_member(symtab, layout, input_objects, p->first, + mapfile, NULL, "--whole-archive")) + return false; ++Archive::total_members; } } @@ -697,13 +769,16 @@ Archive::include_all_members(Symbol_table* symtab, Layout* layout, p != this->end(); ++p) { - this->include_member(symtab, layout, input_objects, p->off, - mapfile, NULL, "--whole-archive"); + if (!this->include_member(symtab, layout, input_objects, p->off, + mapfile, NULL, "--whole-archive")) + return false; ++Archive::total_members; } } input_objects->archive_stop(this); + + return true; } // Return the number of members in the archive. This is only used for @@ -722,8 +797,11 @@ Archive::count_members() // Include an archive member in the link. OFF is the file offset of // the member header. WHY is the reason we are including this member. +// Return true if we added the member or if we had an error, return +// false if this was the first member we tried to add from this +// archive and it had an incompatible format. -void +bool Archive::include_member(Symbol_table* symtab, Layout* layout, Input_objects* input_objects, off_t off, Mapfile* mapfile, Symbol* sym, const char* why) @@ -734,37 +812,65 @@ Archive::include_member(Symbol_table* symtab, Layout* layout, if (p != this->members_.end()) { Object *obj = p->second.obj_; + Read_symbols_data *sd = p->second.sd_; if (mapfile != NULL) mapfile->report_include_archive_member(obj->name(), sym, why); if (input_objects->add_object(obj)) { obj->layout(symtab, layout, sd); - obj->add_symbols(symtab, sd); + obj->add_symbols(symtab, sd, layout); + this->included_member_ = true; } delete sd; - return; + return true; + } + + bool unconfigured; + Object* obj = this->get_elf_object_for_member(off, &unconfigured); + + if (!this->included_member_ + && this->searched_for() + && obj == NULL + && unconfigured) + { + if (obj != NULL) + delete obj; + return false; } - Object* obj = this->get_elf_object_for_member(off, input_objects); if (obj == NULL) - return; + return true; if (mapfile != NULL) mapfile->report_include_archive_member(obj->name(), sym, why); - if (input_objects->add_object(obj)) + Pluginobj* pluginobj = obj->pluginobj(); + if (pluginobj != NULL) { - Read_symbols_data sd; - obj->read_symbols(&sd); - obj->layout(symtab, layout, &sd); - obj->add_symbols(symtab, &sd); + pluginobj->add_symbols(symtab, NULL, layout); + this->included_member_ = true; + return true; } + + if (!input_objects->add_object(obj)) + delete obj; else { - // FIXME: We need to close the descriptor here. - delete obj; + Read_symbols_data sd; + obj->read_symbols(&sd); + obj->layout(symtab, layout, &sd); + obj->add_symbols(symtab, &sd, layout); + + // If this is an external member of a thin archive, unlock the file + // for the next task. + if (obj->offset() == 0) + obj->unlock(this->task_); + + this->included_member_ = true; } + + return true; } // Print statistical information to stderr. This is used for --stats. @@ -809,16 +915,30 @@ Add_archive_symbols::locks(Task_locker* tl) } void -Add_archive_symbols::run(Workqueue*) +Add_archive_symbols::run(Workqueue* workqueue) { - this->archive_->add_symbols(this->symtab_, this->layout_, - this->input_objects_, this->mapfile_); - + bool added = this->archive_->add_symbols(this->symtab_, this->layout_, + this->input_objects_, + this->mapfile_); this->archive_->unlock_nested_archives(); this->archive_->release(); this->archive_->clear_uncached_views(); + if (!added) + { + // This archive holds object files which are incompatible with + // our output file. + Read_symbols::incompatible_warning(this->input_argument_, + this->archive_->input_file()); + Read_symbols::requeue(workqueue, this->input_objects_, this->symtab_, + this->layout_, this->dirpath_, this->dirindex_, + this->mapfile_, this->input_argument_, + this->input_group_, this->next_blocker_); + delete this->archive_; + return; + } + if (this->input_group_ != NULL) this->input_group_->add_archive(this->archive_); else diff --git a/binutils-2.19/gold/archive.h b/binutils-2.19/gold/archive.h index 24fdb2b..7f567b7 100644 --- a/binutils-2.19/gold/archive.h +++ b/binutils-2.19/gold/archive.h @@ -33,6 +33,7 @@ namespace gold { class Task; +class Input_argument; class Input_file; class Input_objects; class Input_group; @@ -48,12 +49,7 @@ class Archive { public: Archive(const std::string& name, Input_file* input_file, - bool is_thin_archive, Dirsearch* dirpath, Task* task) - : name_(name), input_file_(input_file), armap_(), armap_names_(), - extended_names_(), armap_checked_(), seen_offsets_(), members_(), - is_thin_archive_(is_thin_archive), nested_archives_(), - dirpath_(dirpath), task_(task), num_members_(0) - { } + bool is_thin_archive, Dirsearch* dirpath, Task* task); // The length of the magic string at the start of an archive. static const int sarmag = 8; @@ -72,6 +68,11 @@ class Archive name() const { return this->name_; } + // The input file. + const Input_file* + input_file() const + { return this->input_file_; } + // The file name. const std::string& filename() const @@ -79,7 +80,7 @@ class Archive // Set up the archive: read the symbol map. void - setup(Input_objects*); + setup(); // Get a reference to the underlying file. File_read& @@ -131,7 +132,7 @@ class Archive // Select members from the archive as needed and add them to the // link. - void + bool add_symbols(Symbol_table*, Layout*, Input_objects*, Mapfile*); // Dump statistical information to stderr. @@ -142,6 +143,11 @@ class Archive size_t count_members(); + // Return the no-export flag. + bool + no_export() + { return this->no_export_; } + private: Archive(const Archive&); Archive& operator=(const Archive&); @@ -182,33 +188,36 @@ class Archive // within that file (0 if not a nested archive), and *MEMBER_NAME // to the name of the archive member. Return TRUE on success. bool - get_file_and_offset(off_t off, Input_objects* input_objects, - Input_file** input_file, off_t* memoff, - std::string* member_name); + get_file_and_offset(off_t off, Input_file** input_file, off_t* memoff, + off_t* memsize, std::string* member_name); - // Return an ELF object for the member at offset OFF. Set *MEMBER_NAME to - // the name of the member. + // Return an ELF object for the member at offset OFF. Object* - get_elf_object_for_member(off_t off, Input_objects* input_objects); + get_elf_object_for_member(off_t off, bool*); // Read the symbols from all the archive members in the link. void - read_all_symbols(Input_objects* input_objects); + read_all_symbols(); // Read the symbols from an archive member in the link. OFF is the file // offset of the member header. void - read_symbols(Input_objects* input_objects, off_t off); + read_symbols(off_t off); // Include all the archive members in the link. - void + bool include_all_members(Symbol_table*, Layout*, Input_objects*, Mapfile*); // Include an archive member in the link. - void + bool include_member(Symbol_table*, Layout*, Input_objects*, off_t off, Mapfile*, Symbol*, const char* why); + // Return whether we found this archive by searching a directory. + bool + searched_for() const + { return this->input_file_->will_search_for(); } + // Iterate over archive members. class const_iterator; @@ -274,6 +283,8 @@ class Archive std::map<off_t, Archive_member> members_; // True if this is a thin archive. const bool is_thin_archive_; + // True if we have included at least one object from this archive. + bool included_member_; // Table of nested archives, indexed by filename. Nested_archive_table nested_archives_; // The directory search path. @@ -282,6 +293,8 @@ class Archive Task *task_; // Number of members in this archive; unsigned int num_members_; + // True if we exclude this library archive from automatic export. + bool no_export_; }; // This class is used to read an archive and pick out the desired @@ -291,13 +304,17 @@ class Add_archive_symbols : public Task { public: Add_archive_symbols(Symbol_table* symtab, Layout* layout, - Input_objects* input_objects, Mapfile* mapfile, + Input_objects* input_objects, Dirsearch* dirpath, + int dirindex, Mapfile* mapfile, + const Input_argument* input_argument, Archive* archive, Input_group* input_group, Task_token* this_blocker, Task_token* next_blocker) : symtab_(symtab), layout_(layout), input_objects_(input_objects), - mapfile_(mapfile), archive_(archive), input_group_(input_group), - this_blocker_(this_blocker), next_blocker_(next_blocker) + dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile), + input_argument_(input_argument), archive_(archive), + input_group_(input_group), this_blocker_(this_blocker), + next_blocker_(next_blocker) { } ~Add_archive_symbols(); @@ -325,7 +342,10 @@ class Add_archive_symbols : public Task Symbol_table* symtab_; Layout* layout_; Input_objects* input_objects_; + Dirsearch* dirpath_; + int dirindex_; Mapfile* mapfile_; + const Input_argument* input_argument_; Archive* archive_; Input_group* input_group_; Task_token* this_blocker_; diff --git a/binutils-2.19/gold/arm-reloc-property.cc b/binutils-2.19/gold/arm-reloc-property.cc new file mode 100644 index 0000000..4f8fa9e --- /dev/null +++ b/binutils-2.19/gold/arm-reloc-property.cc @@ -0,0 +1,331 @@ +// arm-reloc-property.cc -- ARM relocation property. + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstdio> +#include <cstring> +#include <stack> +#include <string> +#include <vector> + +#include "elfcpp.h" +#include "arm.h" +#include "arm-reloc-property.h" + +namespace gold +{ + +// Arm_reloc_property::Tree_node methods. + +// Parse an S-expression S and build a tree and return the root node. +// Caller is responsible for releasing tree after use. + +Arm_reloc_property::Tree_node* +Arm_reloc_property::Tree_node::make_tree(const std::string& s) +{ + std::stack<size_t> size_stack; + Tree_node_vector node_stack; + + // strtok needs a non-const string pointer. + char* buffer = new char[s.size() + 1]; + memcpy(buffer, s.data(), s.size()); + buffer[s.size()] = '\0'; + char* token = strtok(buffer, " "); + + while (token != NULL) + { + if (strcmp(token, "(") == 0) + // Remember the node stack position for start of a new internal node. + size_stack.push(node_stack.size()); + else if (strcmp(token, ")") == 0) + { + // Pop all tree nodes after the previous '(' and use them as + // children to build a new internal node. Push internal node back. + size_t current_size = node_stack.size(); + size_t prev_size = size_stack.top(); + size_stack.pop(); + Tree_node* node = + new Tree_node(node_stack.begin() + prev_size, + node_stack.begin() + current_size); + node_stack.resize(prev_size); + node_stack.push_back(node); + } + else + // Just push a leaf node to node_stack. + node_stack.push_back(new Tree_node(token)); + + token = strtok(NULL, " "); + } + + delete[] buffer; + + // At this point, size_stack should be empty and node_stack should only + // contain the root node. + gold_assert(size_stack.empty() && node_stack.size() == 1); + return node_stack[0]; +} + +// Arm_reloc_property methods. + +// Constructor. + +Arm_reloc_property::Arm_reloc_property( + unsigned int code, + const char* name, + Reloc_type rtype, + bool is_deprecated, + Reloc_class rclass, + const std::string& operation, + bool is_implemented, + int group_index, + bool checks_overflow) + : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass), + group_index_(group_index), size_(0), align_(1), + relative_address_base_(RAB_NONE), is_deprecated_(is_deprecated), + is_implemented_(is_implemented), checks_overflow_(checks_overflow), + uses_got_entry_(false), uses_got_origin_(false), uses_plt_entry_(false), + uses_thumb_bit_(false), uses_symbol_base_(false), uses_addend_(false) +{ + // Set size and alignment of static and dynamic relocations. + if (rtype == RT_STATIC) + { + switch (rclass) + { + case RC_DATA: + // Except for R_ARM_ABS16 and R_ARM_ABS8, all static data relocations + // have size 4. All static data relocations have alignment of 1. + if (code == elfcpp::R_ARM_ABS8) + this->size_ = 1; + else if (code == elfcpp::R_ARM_ABS16) + this->size_ = 2; + else + this->size_ = 4; + this->align_ = 1; + break; + case RC_MISC: + // R_ARM_V4BX should be treated as an ARM relocation. For all + // others, just use defaults. + if (code != elfcpp::R_ARM_V4BX) + break; + // Fall through. + case RC_ARM: + this->size_ = 4; + this->align_ = 4; + break; + case RC_THM16: + this->size_ = 2; + this->align_ = 2; + break; + case RC_THM32: + this->size_ = 4; + this->align_ = 2; + break; + default: + gold_unreachable(); + } + } + else if (rtype == RT_DYNAMIC) + { + // With the exception of R_ARM_COPY, all dynamic relocations requires + // that the place being relocated is a word-aligned 32-bit object. + if (code != elfcpp::R_ARM_COPY) + { + this->size_ = 4; + this->align_ = 4; + } + } + + // If no relocation operation is specified, we are done. + if (operation == "NONE") + return; + + // Extract information from relocation operation. + Tree_node* root_node = Tree_node::make_tree(operation); + Tree_node* node = root_node; + + // Check for an expression of the form XXX - YYY. + if (!node->is_leaf() + && node->child(0)->is_leaf() + && node->child(0)->name() == "-") + { + struct RAB_table_entry + { + Relative_address_base rab; + const char* name; + }; + + static const RAB_table_entry rab_table[] = + { + { RAB_B_S, "( B S )" }, + { RAB_DELTA_B_S, "( DELTA_B ( S ) )" }, + { RAB_GOT_ORG, "GOT_ORG" }, + { RAB_P, "P" }, + { RAB_Pa, "Pa" }, + { RAB_TLS, "TLS" }, + { RAB_tp, "tp" } + }; + + static size_t rab_table_size = sizeof(rab_table) / sizeof(rab_table[0]); + const std::string rhs(node->child(2)->s_expression()); + for (size_t i = 0; i < rab_table_size; ++i) + if (rhs == rab_table[i].name) + { + this->relative_address_base_ = rab_table[i].rab; + break; + } + + gold_assert(this->relative_address_base_ != RAB_NONE); + if (this->relative_address_base_ == RAB_B_S) + this->uses_symbol_base_ = true; + node = node->child(1); + } + + // Check for an expression of the form XXX | T. + if (!node->is_leaf() + && node->child(0)->is_leaf() + && node->child(0)->name() == "|") + { + gold_assert(node->number_of_children() == 3 + && node->child(2)->is_leaf() + && node->child(2)->name() == "T"); + this->uses_thumb_bit_ = true; + node = node->child(1); + } + + // Check for an expression of the form XXX + A. + if (!node->is_leaf() + && node->child(0)->is_leaf() + && node->child(0)->name() == "+") + { + gold_assert(node->number_of_children() == 3 + && node->child(2)->is_leaf() + && node->child(2)->name() == "A"); + this->uses_addend_ = true; + node = node->child(1); + } + + // Check for an expression of the form XXX(S). + if (!node->is_leaf() && node->child(0)->is_leaf()) + { + gold_assert(node->number_of_children() == 2 + && node->child(1)->is_leaf() + && node->child(1)->name() == "S"); + const std::string func(node->child(0)->name()); + if (func == "B") + this->uses_symbol_base_ = true; + else if (func == "GOT") + this->uses_got_entry_ = true; + else if (func == "PLT") + this->uses_plt_entry_ = true; + else if (func == "Module" || func == "DELTA_B") + // These are used in dynamic relocations. + ; + else + gold_unreachable(); + node = node->child(1); + } + + gold_assert(node->is_leaf() && node->name() == "S"); + + delete root_node; +} + +// Arm_reloc_property_table methods. + +// Constructor. This processing informations in arm-reloc.def to +// initialize the table. + +Arm_reloc_property_table::Arm_reloc_property_table() +{ + // These appers in arm-reloc.def. Do not rename them. + Parse_expression A("A"), GOT_ORG("GOT_ORG"), NONE("NONE"), P("P"), + Pa("Pa"), S("S"), T("T"), TLS("TLS"), tp("tp"); + const bool Y(true), N(false); + + for (unsigned int i = 0; i < Property_table_size; ++i) + this->table_[i] = NULL; + +#undef RD +#define RD(name, type, deprecated, class, operation, is_implemented, \ + group_index, checks_oveflow) \ + do \ + { \ + unsigned int code = elfcpp::R_ARM_##name; \ + gold_assert(code < Property_table_size); \ + this->table_[code] = \ + new Arm_reloc_property(elfcpp::R_ARM_##name, "R_ARM_" #name, \ + Arm_reloc_property::RT_##type, deprecated, \ + Arm_reloc_property::RC_##class, \ + (operation).s_expression(), is_implemented, \ + group_index, checks_oveflow); \ + } \ + while(0); + +#include "arm-reloc.def" +#undef RD +} + +// Return a string describing a relocation code that fails to get a +// relocation property in get_implemented_static_reloc_property(). + +std::string +Arm_reloc_property_table::reloc_name_in_error_message(unsigned int code) +{ + gold_assert(code < Property_table_size); + + const Arm_reloc_property* arp = this->table_[code]; + + if (arp == NULL) + { + char buffer[100]; + sprintf(buffer, _("invalid reloc %u"), code); + return std::string(buffer); + } + + // gold only implements static relocation codes. + Arm_reloc_property::Reloc_type reloc_type = arp->reloc_type(); + gold_assert(reloc_type == Arm_reloc_property::RT_STATIC + || !arp->is_implemented()); + + const char* prefix = NULL; + switch (reloc_type) + { + case Arm_reloc_property::RT_STATIC: + prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc "); + break; + case Arm_reloc_property::RT_DYNAMIC: + prefix = _("dynamic reloc "); + break; + case Arm_reloc_property::RT_PRIVATE: + prefix = _("private reloc "); + break; + case Arm_reloc_property::RT_OBSOLETE: + prefix = _("obsolete reloc "); + break; + default: + gold_unreachable(); + } + return std::string(prefix) + arp->name(); +} + +} // End namespace gold. diff --git a/binutils-2.19/gold/arm-reloc-property.h b/binutils-2.19/gold/arm-reloc-property.h new file mode 100644 index 0000000..349d862 --- /dev/null +++ b/binutils-2.19/gold/arm-reloc-property.h @@ -0,0 +1,379 @@ +// arm-reloc-property.h -- ARM relocation properties -*- C++ -*- + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_ARM_RELOC_PROPERTY_H +#define GOLD_ARM_RELOC_PROPERTY_H + +namespace gold +{ +// The Arm_reloc_property class is to store information about a paticular +// relocation code. + +class Arm_reloc_property +{ + public: + // Types of relocation codes. + enum Reloc_type { + RT_NONE, // No relocation type. + RT_STATIC, // Relocations processed by static linkers. + RT_DYNAMIC, // Relocations processed by dynamic linkers. + RT_PRIVATE, // Private relocations, not supported by gold. + RT_OBSOLETE // Obsolete relocations that should not be used. + }; + + // Classes of relocation codes. + enum Reloc_class { + RC_NONE, // No relocation class. + RC_DATA, // Data relocation. + RC_ARM, // ARM instruction relocation. + RC_THM16, // 16-bit THUMB instruction relocation. + RC_THM32, // 32-bit THUMB instruction relocation. + RC_MISC // Miscellaneous class. + }; + + // Types of bases of relative addressing relocation codes. + enum Relative_address_base { + RAB_NONE, // Relocation is not relative addressing + RAB_B_S, // Address origin of output segment of defining symbol. + RAB_DELTA_B_S, // Change of address origin. + RAB_GOT_ORG, // Origin of GOT. + RAB_P, // Address of the place being relocated. + RAB_Pa, // Adjusted address (P & 0xfffffffc). + RAB_TLS, // Thread local storage. + RAB_tp // Thread pointer. + }; + + // Relocation code represented by this. + unsigned int + code() const + { return this->code_; } + + // Name of the relocation code. + const std::string& + name() const + { return this->name_; } + + // Type of relocation code. + Reloc_type + reloc_type() const + { return this->reloc_type_; } + + // Whether this code is deprecated. + bool + is_deprecated() const + { return this->is_deprecated_; } + + // Class of relocation code. + Reloc_class + reloc_class() const + { return this->reloc_class_; } + + // Whether this code is implemented in gold. + bool + is_implemented() const + { return this->is_implemented_; } + + // If code is a group relocation code, return the group number, otherwise -1. + int + group_index() const + { return this->group_index_; } + + // Whether relocation checks for overflow. + bool + checks_overflow() const + { return this->checks_overflow_; } + + // Return size of relocation. + size_t + size() const + { return this->size_; } + + // Return alignment of relocation. + size_t + align() const + { return this->align_; } + + // Whether relocation use a GOT entry. + bool + uses_got_entry() const + { return this->uses_got_entry_; } + + // Whether relocation use a GOT origin. + bool + uses_got_origin() const + { return this->uses_got_origin_; } + + // Whether relocation uses the Thumb-bit in a symbol address. + bool + uses_thumb_bit() const + { return this->uses_thumb_bit_; } + + // Whether relocation uses the symbol base. + bool + uses_symbol_base() const + { return this->uses_symbol_base_; } + + // Return the type of relative address base or RAB_NONE if this + // is not a relative addressing relocation. + Relative_address_base + relative_address_base() const + { return this->relative_address_base_; } + + protected: + // These are protected. We only allow Arm_reloc_property_table to + // manage Arm_reloc_property. + Arm_reloc_property(unsigned int code, const char* name, Reloc_type rtype, + bool is_deprecated, Reloc_class rclass, + const std::string& operation, bool is_implemented, + int group_index, bool checks_overflow); + + friend class Arm_reloc_property_table; + + private: + // Copying is not allowed. + Arm_reloc_property(const Arm_reloc_property&); + Arm_reloc_property& operator=(const Arm_reloc_property&); + + // The Tree_node class is used to represent parsed relocation operations. + // We look at Trees to extract information about relocation operations. + class Tree_node + { + public: + typedef std::vector<Tree_node*> Tree_node_vector; + + // Construct a leaf node. + Tree_node(const char* name) + : is_leaf_(true), name_(name), children_() + { } + + // Construct an internal node. A node owns all its children and is + // responsible for releasing them at its own destruction. + Tree_node(Tree_node_vector::const_iterator begin, + Tree_node_vector::const_iterator end) + : is_leaf_(false), name_(), children_() + { + for (Tree_node_vector::const_iterator p = begin; p != end; ++p) + this->children_.push_back(*p); + } + + ~Tree_node() + { + for(size_t i = 0; i <this->children_.size(); ++i) + delete this->children_[i]; + } + + // Whether this is a leaf node. + bool + is_leaf() const + { return this->is_leaf_; } + + // Return name of this. This is only valid for a leaf node. + const std::string& + name() const + { + gold_assert(this->is_leaf_); + return this->name_; + } + + // Return the number of children. This is only valid for a non-leaf node. + size_t + number_of_children() const + { + gold_assert(!this->is_leaf_); + return this->children_.size(); + } + + // Return the i-th child of this. This is only valid for a non-leaf node. + Tree_node* + child(size_t i) const + { + gold_assert(!this->is_leaf_ && i < this->children_.size()); + return this->children_[i]; + } + + // Parse an S-expression string and build a tree and return the root node. + // Caller is responsible for releasing tree after use. + static Tree_node* + make_tree(const std::string&); + + // Convert a tree back to an S-expression string. + std::string + s_expression() const + { + if (this->is_leaf_) + return this->name_; + + // Concatenate S-expressions of children. Enclose them with + // a pair of parentheses and use space as token delimiters. + std::string s("("); + for(size_t i = 0; i <this->children_.size(); ++i) + s = s + " " + this->children_[i]->s_expression(); + return s + " )"; + } + + private: + // Whether this is a leaf node. + bool is_leaf_; + // Name of this if this is a leaf node. + std::string name_; + // Children of this if this a non-leaf node. + Tree_node_vector children_; + }; + + // Relocation code. + unsigned int code_; + // Relocation name. + std::string name_; + // Type of relocation. + Reloc_type reloc_type_; + // Class of relocation. + Reloc_class reloc_class_; + // Group index (0, 1, or 2) if this is a group relocation or -1 otherwise. + int group_index_; + // Size of relocation. + size_t size_; + // Alignment of relocation. + size_t align_; + // Relative address base. + Relative_address_base relative_address_base_; + // Whether this is deprecated. + bool is_deprecated_ : 1; + // Whether this is implemented in gold. + bool is_implemented_ : 1; + // Whether this checks overflow. + bool checks_overflow_ : 1; + // Whether this uses a GOT entry. + bool uses_got_entry_ : 1; + // Whether this uses a GOT origin. + bool uses_got_origin_ : 1; + // Whether this uses a PLT entry. + bool uses_plt_entry_ : 1; + // Whether this uses the THUMB bit in symbol address. + bool uses_thumb_bit_ : 1; + // Whether this uses the symbol base. + bool uses_symbol_base_ : 1; + // Whether this uses an addend. + bool uses_addend_ : 1; +}; + +// Arm_reloc_property_table. This table is used for looking up propeties +// of relocationt types. The table entries are initialized using information +// from arm-reloc.def. + +class Arm_reloc_property_table +{ + public: + Arm_reloc_property_table(); + + // Return an Arm_reloc_property object for CODE if it is a valid relocation + // code or NULL otherwise. + const Arm_reloc_property* + get_reloc_property(unsigned int code) const + { + gold_assert(code < Property_table_size); + return this->table_[code]; + } + + // Like get_reloc_property but only return non-NULL if relocation code is + // static and implemented. + const Arm_reloc_property* + get_implemented_static_reloc_property(unsigned int code) const + { + gold_assert(code < Property_table_size); + const Arm_reloc_property* arp = this->table_[code]; + return ((arp != NULL + && (arp->reloc_type() == Arm_reloc_property::RT_STATIC) + && arp->is_implemented()) + ? arp + : NULL); + } + + // Return a string describing the a relocation code that is not + // an implemented static reloc code. + std::string + reloc_name_in_error_message(unsigned int code); + + private: + // Copying is not allowed. + Arm_reloc_property_table(const Arm_reloc_property_table&); + Arm_reloc_property_table& operator=(const Arm_reloc_property_table&); + + // The Parse_expression class is used to convert relocation operations in + // arm-reloc.def into S-expression strings, which are parsed again to + // build actual expression trees. We do not build the expression trees + // directly because the parser for operations in arm-reloc.def is simpler + // this way. Coversion from S-expressions to trees is simple. + class Parse_expression + { + public: + // Construction a Parse_expression with an S-expression string. + Parse_expression(const std::string& s_expression) + : s_expression_(s_expression) + { } + + // Value of this expression as an S-expression string. + const std::string& + s_expression() const + { return this->s_expression_; } + + // We want to overload operators used in relocation operations so + // that we can execute operations in arm-reloc.def to generate + // S-expressions directly. +#define DEF_OPERATOR_OVERLOAD(op) \ + Parse_expression \ + operator op (const Parse_expression& e) \ + { \ + return Parse_expression("( " #op " " + this->s_expression_ + " " + \ + e.s_expression_ + " )"); \ + } + + // Operator appearing in relocation operations in arm-reloc.def. + DEF_OPERATOR_OVERLOAD(+) + DEF_OPERATOR_OVERLOAD(-) + DEF_OPERATOR_OVERLOAD(|) + + private: + // This represented as an S-expression string. + std::string s_expression_; + }; + +#define DEF_RELOC_FUNC(name) \ + static Parse_expression \ + (name)(const Parse_expression& arg) \ + { return Parse_expression("( " #name " " + arg.s_expression() + " )"); } + + // Functions appearing in relocation operations in arm-reloc.def. + DEF_RELOC_FUNC(B) + DEF_RELOC_FUNC(DELTA_B) + DEF_RELOC_FUNC(GOT) + DEF_RELOC_FUNC(Module) + DEF_RELOC_FUNC(PLT) + + static const unsigned int Property_table_size = 256; + + // The property table. + Arm_reloc_property* table_[Property_table_size]; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_ARM_RELOC_PROPERTY_H) diff --git a/binutils-2.19/gold/arm-reloc.def b/binutils-2.19/gold/arm-reloc.def new file mode 100644 index 0000000..2caf371 --- /dev/null +++ b/binutils-2.19/gold/arm-reloc.def @@ -0,0 +1,194 @@ +// arm-reloc.def -- ARM relocation definitions. + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The information here is based on the official ARM document "ELF for ARM +// Architecture" (Document number ARM IHI 0044C). The first five columns of +// the table below are derived from Table 4-8 in the ARM ELF document. Each +// relocation from Table 4-8 corresponds to one relocation definition in the +// table below. A relocation defintion has the following information: +// +// Name: This is the name of the relocation without the "R_ARM_" prefix. +// +// Type: Relocation type. There are four. +// - STATIC for static relocations processed by a static linker. +// - DYNAMIC for dynamic relocations processed by a dynamic linker. +// - PRIVATE for R_ARM_PRIVATE_<n> private relocation type. +// - OBSOLETE for old relocation types no longer used. +// We do not use DEPRECATED as a distinct type since we still have to +// handle deprecated relocations so we one of the types above. +// +// Deprecated: Whether this is a deprecated relocation type. The linker +// is expected to handle these though they should not be generated by fully +// conforming tool-chains. +// +// Operation: An expression specifying how the linker should performace a +// relocation. If there is no operation or the operation cannot be +// specified, it is "NONE". +// +// Implemented: Whether this is implemented by the gold. +// +// Group_index: For a group relocation type, it is one of 0, 1 or 2. For +// a non-group relocation type, it is -1. +// +// Overflow: Whether gold should check for overflow. This is "No" by default +// for relocation types DYNAMIC, PRIVATE and OBSOLETE. +// +// Overflow-----------------------------------------------------------------+ +// Group index----------------------------------------------------------+ | +// Implemented-------------------------------------------------------+ | | +// Operation-------------------------------+ | | | +// Class----------------------------+ | | | | +// Deprecated--------------------+ | | | | | +// Type----------------+ | | | | | | +// Name | | | | | | | +// | | | | | | | | +RD(NONE , STATIC , N, MISC , NONE , Y, -1, N) +RD(PC24 , STATIC , Y, ARM , ((S + A) | T) - P , Y, -1, Y) +RD(ABS32 , STATIC , N, DATA , (S + A) | T , Y, -1, N) +RD(REL32 , STATIC , N, DATA , ((S + A) | T) - P , Y, -1, N) +RD(LDR_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y) +RD(ABS16 , STATIC , N, DATA , S + A , Y, -1, Y) +RD(ABS12 , STATIC , N, ARM , S + A , Y, -1, Y) +RD(THM_ABS5 , STATIC , N, THM16, S + A , Y, -1, Y) +RD(ABS8 , STATIC , N, DATA , S + A , Y, -1, Y) +RD(SBREL32 , STATIC , N, DATA , ((S + A) | T) - B(S) , N, -1, N) +RD(THM_CALL , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y) +RD(THM_PC8 , STATIC , N, THM16, S + A - Pa , Y, -1, Y) +RD(BREL_ADJ , DYNAMIC , N, DATA , DELTA_B(S) + A , Y, -1, N) +RD(TLS_DESC , DYNAMIC , N, DATA , NONE , Y, -1, N) +RD(THM_SWI8 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(XPC25 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(THM_XPC22 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(TLS_DTPMOD32 , DYNAMIC , N, DATA , Module(S) , Y, -1, N) +RD(TLS_DTPOFF32 , DYNAMIC , N, DATA , S + A - TLS , Y, -1, N) +RD(TLS_TPOFF32 , DYNAMIC , N, DATA , S + A - tp , Y, -1, N) +RD(COPY , DYNAMIC , N, MISC , NONE , Y, -1, N) +RD(GLOB_DAT , DYNAMIC , N, DATA , (S + A) | T , Y, -1, N) +RD(JUMP_SLOT , DYNAMIC , N, DATA , (S + A) | T , Y, -1, N) +RD(RELATIVE , DYNAMIC , N, DATA , B(S) + A , Y, -1, N) +RD(GOTOFF32 , STATIC , N, DATA , ((S + A) | T) - GOT_ORG, Y, -1, N) +RD(BASE_PREL , STATIC , N, DATA , B(S) + A - P , Y, -1, N) +RD(GOT_BREL , STATIC , N, DATA , GOT(S) + A - GOT_ORG , Y, -1, N) +RD(PLT32 , STATIC , Y, ARM , ((S + A) | T) - P , Y, -1, Y) +RD(CALL , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, Y) +RD(JUMP24 , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, Y) +RD(THM_JUMP24 , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y) +RD(BASE_ABS , STATIC , N, DATA , B(S) + A , Y, -1, N) +RD(ALU_PCREL_7_0 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(ALU_PCREL_15_8 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(ALU_PCREL_23_15 , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(LDR_SBREL_11_0_NC , STATIC , Y, ARM , S + A - B(S) , N, -1, N) +RD(ALU_SBREL_19_12_NC, STATIC , Y, ARM , S + A - B(S) , N, -1, N) +RD(ALU_SBREL_27_20_CK, STATIC , Y, ARM , S + A - B(S) , N, -1, Y) +RD(TARGET1 , STATIC , N, MISC , NONE , Y, -1, N) +RD(SBREL31 , STATIC , Y, DATA , ((S + A) | T) - B(S) , N, -1, N) +RD(V4BX , STATIC , N, MISC , NONE , Y, -1, N) +RD(TARGET2 , STATIC , N, MISC , NONE , Y, -1, N) +RD(PREL31 , STATIC , N, DATA , ((S + A) | T) - P , Y, -1, Y) +RD(MOVW_ABS_NC , STATIC , N, ARM , (S + A) | T , Y, -1, N) +RD(MOVT_ABS , STATIC , N, ARM , S + A , Y, -1, Y) +RD(MOVW_PREL_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, -1, N) +RD(MOVT_PREL , STATIC , N, ARM , (S + A) - P , Y, -1, Y) +RD(THM_MOVW_ABS_NC , STATIC , N, THM32, (S + A) | T , Y, -1, N) +RD(THM_MOVT_ABS , STATIC , N, THM32, S + A , Y, -1, N) +RD(THM_MOVW_PREL_NC , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, N) +RD(THM_MOVT_PREL , STATIC , N, THM32, S + A - P , Y, -1, N) +RD(THM_JUMP19 , STATIC , N, THM32, ((S + A) | T) - P , Y, -1, Y) +RD(THM_JUMP6 , STATIC , N, THM16, S + A - P , Y, -1, Y) +RD(THM_ALU_PREL_11_0 , STATIC , N, THM32, ((S + A) | T) - Pa , Y, -1, Y) +RD(THM_PC12 , STATIC , N, THM32, S + A - Pa , Y, -1, Y) +RD(ABS32_NOI , STATIC , N, DATA , S + A , Y, -1, N) +RD(REL32_NOI , STATIC , N, DATA , S + A - P , N, -1, N) +RD(ALU_PC_G0_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, 0, N) +RD(ALU_PC_G0 , STATIC , N, ARM , ((S + A) | T) - P , Y, 0, Y) +RD(ALU_PC_G1_NC , STATIC , N, ARM , ((S + A) | T) - P , Y, 1, N) +RD(ALU_PC_G1 , STATIC , N, ARM , ((S + A) | T) - P , Y, 1, Y) +RD(ALU_PC_G2 , STATIC , N, ARM , ((S + A) | T) - P , Y, 2, Y) +RD(LDR_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y) +RD(LDR_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y) +RD(LDRS_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y) +RD(LDRS_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y) +RD(LDRS_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y) +RD(LDC_PC_G0 , STATIC , N, ARM , S + A - P , Y, 0, Y) +RD(LDC_PC_G1 , STATIC , N, ARM , S + A - P , Y, 1, Y) +RD(LDC_PC_G2 , STATIC , N, ARM , S + A - P , Y, 2, Y) +RD(ALU_SB_G0_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 0, N) +RD(ALU_SB_G0 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 0, Y) +RD(ALU_SB_G1_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 1, N) +RD(ALU_SB_G1 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 1, Y) +RD(ALU_SB_G2 , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, 2, Y) +RD(LDR_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y) +RD(LDR_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y) +RD(LDR_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y) +RD(LDRS_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y) +RD(LDRS_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y) +RD(LDRS_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y) +RD(LDC_SB_G0 , STATIC , N, ARM , S + A - B(S) , Y, 0, Y) +RD(LDC_SB_G1 , STATIC , N, ARM , S + A - B(S) , Y, 1, Y) +RD(LDC_SB_G2 , STATIC , N, ARM , S + A - B(S) , Y, 2, Y) +RD(MOVW_BREL_NC , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, -1, N) +RD(MOVT_BREL , STATIC , N, ARM , S + A - B(S) , Y, -1, Y) +RD(MOVW_BREL , STATIC , N, ARM , ((S + A) | T) - B(S) , Y, -1, Y) +RD(THM_MOVW_BREL_NC , STATIC , N, THM32, ((S + A) | T) - B(S) , Y, -1, N) +RD(THM_MOVT_BREL , STATIC , N, THM32, S + A - B(S) , Y, -1, N) +RD(THM_MOVW_BREL , STATIC , N, THM32, ((S + A) | T) - B(S) , Y, -1, Y) +RD(TLS_GOTDESC , STATIC , N, DATA , NONE , Y, -1, N) +RD(TLS_CALL , STATIC , N, ARM , NONE , N, -1, Y) +RD(TLS_DESCSEQ , STATIC , N, ARM , NONE , N, -1, Y) +RD(THM_TLS_CALL , STATIC , N, THM32, NONE , N, -1, Y) +RD(PLT32_ABS , STATIC , N, DATA , PLT(S) + A , N, -1, N) +RD(GOT_ABS , STATIC , N, DATA , GOT(S) + A , N, -1, N) +RD(GOT_PREL , STATIC , N, DATA , GOT(S) + A - P , Y, -1, N) +RD(GOT_BREL12 , STATIC , N, ARM , GOT(S) + A - GOT_ORG , N, -1, Y) +RD(GOTOFF12 , STATIC , N, ARM , S + A - GOT_ORG , N, -1, Y) +RD(GOTRELAX , STATIC , N, MISC , NONE , N, -1, N) +RD(GNU_VTENTRY , STATIC , Y, DATA , NONE , Y, -1, N) +RD(GNU_VTINHERIT , STATIC , Y, DATA , NONE , Y, -1, N) +RD(THM_JUMP11 , STATIC , N, THM16, S + A - P , Y, -1, Y) +RD(THM_JUMP8 , STATIC , N, THM16, S + A - P , Y, -1, Y) +RD(TLS_GD32 , STATIC , N, DATA , GOT(S) + A - P , Y, -1, N) +RD(TLS_LDM32 , STATIC , N, DATA , GOT(S) + A - P , Y, -1, N) +RD(TLS_LDO32 , STATIC , N, DATA , S + A - TLS , Y, -1, N) +RD(TLS_IE32 , STATIC , N, DATA , GOT(S) + A - P , Y, -1, N) +RD(TLS_LE32 , STATIC , N, DATA , S + A - tp , Y, -1, N) +RD(TLS_LDO12 , STATIC , N, ARM , S + A - TLS , N, -1, Y) +RD(TLS_LE12 , STATIC , N, ARM , S + A - tp , N, -1, Y) +RD(TLS_IE12GP , STATIC , N, ARM , GOT(S) + A - GOT_ORG , N, -1, Y) +RD(PRIVATE_0 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_1 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_2 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_3 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_4 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_5 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_6 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_7 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_8 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_9 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_10 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_11 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_12 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_13 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_14 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(PRIVATE_15 , PRIVATE , N, NONE , NONE , N, -1, N) +RD(ME_TOO , OBSOLETE, N, NONE , NONE , N, -1, N) +RD(THM_TLS_DESCSEQ16 , STATIC , N, THM16, NONE , N, -1, Y) +RD(THM_TLS_DESCSEQ32 , STATIC , N, THM32, NONE , N, -1, Y) diff --git a/binutils-2.19/gold/arm.cc b/binutils-2.19/gold/arm.cc new file mode 100644 index 0000000..8943fea --- /dev/null +++ b/binutils-2.19/gold/arm.cc @@ -0,0 +1,10891 @@ +// arm.cc -- arm target support for gold. + +// Copyright 2009, 2010 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com> based on the i386 code +// by Ian Lance Taylor <iant@google.com>. +// This file also contains borrowed and adapted code from +// bfd/elf32-arm.c. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstring> +#include <limits> +#include <cstdio> +#include <string> +#include <algorithm> +#include <map> +#include <utility> +#include <set> + +#include "elfcpp.h" +#include "parameters.h" +#include "reloc.h" +#include "arm.h" +#include "object.h" +#include "symtab.h" +#include "layout.h" +#include "output.h" +#include "copy-relocs.h" +#include "target.h" +#include "target-reloc.h" +#include "target-select.h" +#include "tls.h" +#include "defstd.h" +#include "gc.h" +#include "attributes.h" +#include "arm-reloc-property.h" + +namespace +{ + +using namespace gold; + +template<bool big_endian> +class Output_data_plt_arm; + +template<bool big_endian> +class Stub_table; + +template<bool big_endian> +class Arm_input_section; + +class Arm_exidx_cantunwind; + +class Arm_exidx_merged_section; + +class Arm_exidx_fixup; + +template<bool big_endian> +class Arm_output_section; + +class Arm_exidx_input_section; + +template<bool big_endian> +class Arm_relobj; + +template<bool big_endian> +class Arm_relocate_functions; + +template<bool big_endian> +class Arm_output_data_got; + +template<bool big_endian> +class Target_arm; + +// For convenience. +typedef elfcpp::Elf_types<32>::Elf_Addr Arm_address; + +// Maximum branch offsets for ARM, THUMB and THUMB2. +const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8); +const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8); +const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) -2 + 4); +const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4); +const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4); +const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4); + +// Thread Control Block size. +const size_t ARM_TCB_SIZE = 8; + +// The arm target class. +// +// This is a very simple port of gold for ARM-EABI. It is intended for +// supporting Android only for the time being. +// +// TODOs: +// - Implement all static relocation types documented in arm-reloc.def. +// - Make PLTs more flexible for different architecture features like +// Thumb-2 and BE8. +// There are probably a lot more. + +// Ideally we would like to avoid using global variables but this is used +// very in many places and sometimes in loops. If we use a function +// returning a static instance of Arm_reloc_property_table, it will very +// slow in an threaded environment since the static instance needs to be +// locked. The pointer is below initialized in the +// Target::do_select_as_default_target() hook so that we do not spend time +// building the table if we are not linking ARM objects. +// +// An alternative is to to process the information in arm-reloc.def in +// compilation time and generate a representation of it in PODs only. That +// way we can avoid initialization when the linker starts. + +Arm_reloc_property_table *arm_reloc_property_table = NULL; + +// Instruction template class. This class is similar to the insn_sequence +// struct in bfd/elf32-arm.c. + +class Insn_template +{ + public: + // Types of instruction templates. + enum Type + { + THUMB16_TYPE = 1, + // THUMB16_SPECIAL_TYPE is used by sub-classes of Stub for instruction + // templates with class-specific semantics. Currently this is used + // only by the Cortex_a8_stub class for handling condition codes in + // conditional branches. + THUMB16_SPECIAL_TYPE, + THUMB32_TYPE, + ARM_TYPE, + DATA_TYPE + }; + + // Factory methods to create instruction templates in different formats. + + static const Insn_template + thumb16_insn(uint32_t data) + { return Insn_template(data, THUMB16_TYPE, elfcpp::R_ARM_NONE, 0); } + + // A Thumb conditional branch, in which the proper condition is inserted + // when we build the stub. + static const Insn_template + thumb16_bcond_insn(uint32_t data) + { return Insn_template(data, THUMB16_SPECIAL_TYPE, elfcpp::R_ARM_NONE, 1); } + + static const Insn_template + thumb32_insn(uint32_t data) + { return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_NONE, 0); } + + static const Insn_template + thumb32_b_insn(uint32_t data, int reloc_addend) + { + return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_THM_JUMP24, + reloc_addend); + } + + static const Insn_template + arm_insn(uint32_t data) + { return Insn_template(data, ARM_TYPE, elfcpp::R_ARM_NONE, 0); } + + static const Insn_template + arm_rel_insn(unsigned data, int reloc_addend) + { return Insn_template(data, ARM_TYPE, elfcpp::R_ARM_JUMP24, reloc_addend); } + + static const Insn_template + data_word(unsigned data, unsigned int r_type, int reloc_addend) + { return Insn_template(data, DATA_TYPE, r_type, reloc_addend); } + + // Accessors. This class is used for read-only objects so no modifiers + // are provided. + + uint32_t + data() const + { return this->data_; } + + // Return the instruction sequence type of this. + Type + type() const + { return this->type_; } + + // Return the ARM relocation type of this. + unsigned int + r_type() const + { return this->r_type_; } + + int32_t + reloc_addend() const + { return this->reloc_addend_; } + + // Return size of instruction template in bytes. + size_t + size() const; + + // Return byte-alignment of instruction template. + unsigned + alignment() const; + + private: + // We make the constructor private to ensure that only the factory + // methods are used. + inline + Insn_template(unsigned data, Type type, unsigned int r_type, int reloc_addend) + : data_(data), type_(type), r_type_(r_type), reloc_addend_(reloc_addend) + { } + + // Instruction specific data. This is used to store information like + // some of the instruction bits. + uint32_t data_; + // Instruction template type. + Type type_; + // Relocation type if there is a relocation or R_ARM_NONE otherwise. + unsigned int r_type_; + // Relocation addend. + int32_t reloc_addend_; +}; + +// Macro for generating code to stub types. One entry per long/short +// branch stub + +#define DEF_STUBS \ + DEF_STUB(long_branch_any_any) \ + DEF_STUB(long_branch_v4t_arm_thumb) \ + DEF_STUB(long_branch_thumb_only) \ + DEF_STUB(long_branch_v4t_thumb_thumb) \ + DEF_STUB(long_branch_v4t_thumb_arm) \ + DEF_STUB(short_branch_v4t_thumb_arm) \ + DEF_STUB(long_branch_any_arm_pic) \ + DEF_STUB(long_branch_any_thumb_pic) \ + DEF_STUB(long_branch_v4t_thumb_thumb_pic) \ + DEF_STUB(long_branch_v4t_arm_thumb_pic) \ + DEF_STUB(long_branch_v4t_thumb_arm_pic) \ + DEF_STUB(long_branch_thumb_only_pic) \ + DEF_STUB(a8_veneer_b_cond) \ + DEF_STUB(a8_veneer_b) \ + DEF_STUB(a8_veneer_bl) \ + DEF_STUB(a8_veneer_blx) \ + DEF_STUB(v4_veneer_bx) + +// Stub types. + +#define DEF_STUB(x) arm_stub_##x, +typedef enum + { + arm_stub_none, + DEF_STUBS + + // First reloc stub type. + arm_stub_reloc_first = arm_stub_long_branch_any_any, + // Last reloc stub type. + arm_stub_reloc_last = arm_stub_long_branch_thumb_only_pic, + + // First Cortex-A8 stub type. + arm_stub_cortex_a8_first = arm_stub_a8_veneer_b_cond, + // Last Cortex-A8 stub type. + arm_stub_cortex_a8_last = arm_stub_a8_veneer_blx, + + // Last stub type. + arm_stub_type_last = arm_stub_v4_veneer_bx + } Stub_type; +#undef DEF_STUB + +// Stub template class. Templates are meant to be read-only objects. +// A stub template for a stub type contains all read-only attributes +// common to all stubs of the same type. + +class Stub_template +{ + public: + Stub_template(Stub_type, const Insn_template*, size_t); + + ~Stub_template() + { } + + // Return stub type. + Stub_type + type() const + { return this->type_; } + + // Return an array of instruction templates. + const Insn_template* + insns() const + { return this->insns_; } + + // Return size of template in number of instructions. + size_t + insn_count() const + { return this->insn_count_; } + + // Return size of template in bytes. + size_t + size() const + { return this->size_; } + + // Return alignment of the stub template. + unsigned + alignment() const + { return this->alignment_; } + + // Return whether entry point is in thumb mode. + bool + entry_in_thumb_mode() const + { return this->entry_in_thumb_mode_; } + + // Return number of relocations in this template. + size_t + reloc_count() const + { return this->relocs_.size(); } + + // Return index of the I-th instruction with relocation. + size_t + reloc_insn_index(size_t i) const + { + gold_assert(i < this->relocs_.size()); + return this->relocs_[i].first; + } + + // Return the offset of the I-th instruction with relocation from the + // beginning of the stub. + section_size_type + reloc_offset(size_t i) const + { + gold_assert(i < this->relocs_.size()); + return this->relocs_[i].second; + } + + private: + // This contains information about an instruction template with a relocation + // and its offset from start of stub. + typedef std::pair<size_t, section_size_type> Reloc; + + // A Stub_template may not be copied. We want to share templates as much + // as possible. + Stub_template(const Stub_template&); + Stub_template& operator=(const Stub_template&); + + // Stub type. + Stub_type type_; + // Points to an array of Insn_templates. + const Insn_template* insns_; + // Number of Insn_templates in insns_[]. + size_t insn_count_; + // Size of templated instructions in bytes. + size_t size_; + // Alignment of templated instructions. + unsigned alignment_; + // Flag to indicate if entry is in thumb mode. + bool entry_in_thumb_mode_; + // A table of reloc instruction indices and offsets. We can find these by + // looking at the instruction templates but we pre-compute and then stash + // them here for speed. + std::vector<Reloc> relocs_; +}; + +// +// A class for code stubs. This is a base class for different type of +// stubs used in the ARM target. +// + +class Stub +{ + private: + static const section_offset_type invalid_offset = + static_cast<section_offset_type>(-1); + + public: + Stub(const Stub_template* stub_template) + : stub_template_(stub_template), offset_(invalid_offset) + { } + + virtual + ~Stub() + { } + + // Return the stub template. + const Stub_template* + stub_template() const + { return this->stub_template_; } + + // Return offset of code stub from beginning of its containing stub table. + section_offset_type + offset() const + { + gold_assert(this->offset_ != invalid_offset); + return this->offset_; + } + + // Set offset of code stub from beginning of its containing stub table. + void + set_offset(section_offset_type offset) + { this->offset_ = offset; } + + // Return the relocation target address of the i-th relocation in the + // stub. This must be defined in a child class. + Arm_address + reloc_target(size_t i) + { return this->do_reloc_target(i); } + + // Write a stub at output VIEW. BIG_ENDIAN select how a stub is written. + void + write(unsigned char* view, section_size_type view_size, bool big_endian) + { this->do_write(view, view_size, big_endian); } + + // Return the instruction for THUMB16_SPECIAL_TYPE instruction template + // for the i-th instruction. + uint16_t + thumb16_special(size_t i) + { return this->do_thumb16_special(i); } + + protected: + // This must be defined in the child class. + virtual Arm_address + do_reloc_target(size_t) = 0; + + // This may be overridden in the child class. + virtual void + do_write(unsigned char* view, section_size_type view_size, bool big_endian) + { + if (big_endian) + this->do_fixed_endian_write<true>(view, view_size); + else + this->do_fixed_endian_write<false>(view, view_size); + } + + // This must be overridden if a child class uses the THUMB16_SPECIAL_TYPE + // instruction template. + virtual uint16_t + do_thumb16_special(size_t) + { gold_unreachable(); } + + private: + // A template to implement do_write. + template<bool big_endian> + void inline + do_fixed_endian_write(unsigned char*, section_size_type); + + // Its template. + const Stub_template* stub_template_; + // Offset within the section of containing this stub. + section_offset_type offset_; +}; + +// Reloc stub class. These are stubs we use to fix up relocation because +// of limited branch ranges. + +class Reloc_stub : public Stub +{ + public: + static const unsigned int invalid_index = static_cast<unsigned int>(-1); + // We assume we never jump to this address. + static const Arm_address invalid_address = static_cast<Arm_address>(-1); + + // Return destination address. + Arm_address + destination_address() const + { + gold_assert(this->destination_address_ != this->invalid_address); + return this->destination_address_; + } + + // Set destination address. + void + set_destination_address(Arm_address address) + { + gold_assert(address != this->invalid_address); + this->destination_address_ = address; + } + + // Reset destination address. + void + reset_destination_address() + { this->destination_address_ = this->invalid_address; } + + // Determine stub type for a branch of a relocation of R_TYPE going + // from BRANCH_ADDRESS to BRANCH_TARGET. If TARGET_IS_THUMB is set, + // the branch target is a thumb instruction. TARGET is used for look + // up ARM-specific linker settings. + static Stub_type + stub_type_for_reloc(unsigned int r_type, Arm_address branch_address, + Arm_address branch_target, bool target_is_thumb); + + // Reloc_stub key. A key is logically a triplet of a stub type, a symbol + // and an addend. Since we treat global and local symbol differently, we + // use a Symbol object for a global symbol and a object-index pair for + // a local symbol. + class Key + { + public: + // If SYMBOL is not null, this is a global symbol, we ignore RELOBJ and + // R_SYM. Otherwise, this is a local symbol and RELOBJ must non-NULL + // and R_SYM must not be invalid_index. + Key(Stub_type stub_type, const Symbol* symbol, const Relobj* relobj, + unsigned int r_sym, int32_t addend) + : stub_type_(stub_type), addend_(addend) + { + if (symbol != NULL) + { + this->r_sym_ = Reloc_stub::invalid_index; + this->u_.symbol = symbol; + } + else + { + gold_assert(relobj != NULL && r_sym != invalid_index); + this->r_sym_ = r_sym; + this->u_.relobj = relobj; + } + } + + ~Key() + { } + + // Accessors: Keys are meant to be read-only object so no modifiers are + // provided. + + // Return stub type. + Stub_type + stub_type() const + { return this->stub_type_; } + + // Return the local symbol index or invalid_index. + unsigned int + r_sym() const + { return this->r_sym_; } + + // Return the symbol if there is one. + const Symbol* + symbol() const + { return this->r_sym_ == invalid_index ? this->u_.symbol : NULL; } + + // Return the relobj if there is one. + const Relobj* + relobj() const + { return this->r_sym_ != invalid_index ? this->u_.relobj : NULL; } + + // Whether this equals to another key k. + bool + eq(const Key& k) const + { + return ((this->stub_type_ == k.stub_type_) + && (this->r_sym_ == k.r_sym_) + && ((this->r_sym_ != Reloc_stub::invalid_index) + ? (this->u_.relobj == k.u_.relobj) + : (this->u_.symbol == k.u_.symbol)) + && (this->addend_ == k.addend_)); + } + + // Return a hash value. + size_t + hash_value() const + { + return (this->stub_type_ + ^ this->r_sym_ + ^ gold::string_hash<char>( + (this->r_sym_ != Reloc_stub::invalid_index) + ? this->u_.relobj->name().c_str() + : this->u_.symbol->name()) + ^ this->addend_); + } + + // Functors for STL associative containers. + struct hash + { + size_t + operator()(const Key& k) const + { return k.hash_value(); } + }; + + struct equal_to + { + bool + operator()(const Key& k1, const Key& k2) const + { return k1.eq(k2); } + }; + + // Name of key. This is mainly for debugging. + std::string + name() const; + + private: + // Stub type. + Stub_type stub_type_; + // If this is a local symbol, this is the index in the defining object. + // Otherwise, it is invalid_index for a global symbol. + unsigned int r_sym_; + // If r_sym_ is invalid index. This points to a global symbol. + // Otherwise, this points a relobj. We used the unsized and target + // independent Symbol and Relobj classes instead of Sized_symbol<32> and + // Arm_relobj. This is done to avoid making the stub class a template + // as most of the stub machinery is endianness-neutral. However, it + // may require a bit of casting done by users of this class. + union + { + const Symbol* symbol; + const Relobj* relobj; + } u_; + // Addend associated with a reloc. + int32_t addend_; + }; + + protected: + // Reloc_stubs are created via a stub factory. So these are protected. + Reloc_stub(const Stub_template* stub_template) + : Stub(stub_template), destination_address_(invalid_address) + { } + + ~Reloc_stub() + { } + + friend class Stub_factory; + + // Return the relocation target address of the i-th relocation in the + // stub. + Arm_address + do_reloc_target(size_t i) + { + // All reloc stub have only one relocation. + gold_assert(i == 0); + return this->destination_address_; + } + + private: + // Address of destination. + Arm_address destination_address_; +}; + +// Cortex-A8 stub class. We need a Cortex-A8 stub to redirect any 32-bit +// THUMB branch that meets the following conditions: +// +// 1. The branch straddles across a page boundary. i.e. lower 12-bit of +// branch address is 0xffe. +// 2. The branch target address is in the same page as the first word of the +// branch. +// 3. The branch follows a 32-bit instruction which is not a branch. +// +// To do the fix up, we need to store the address of the branch instruction +// and its target at least. We also need to store the original branch +// instruction bits for the condition code in a conditional branch. The +// condition code is used in a special instruction template. We also want +// to identify input sections needing Cortex-A8 workaround quickly. We store +// extra information about object and section index of the code section +// containing a branch being fixed up. The information is used to mark +// the code section when we finalize the Cortex-A8 stubs. +// + +class Cortex_a8_stub : public Stub +{ + public: + ~Cortex_a8_stub() + { } + + // Return the object of the code section containing the branch being fixed + // up. + Relobj* + relobj() const + { return this->relobj_; } + + // Return the section index of the code section containing the branch being + // fixed up. + unsigned int + shndx() const + { return this->shndx_; } + + // Return the source address of stub. This is the address of the original + // branch instruction. LSB is 1 always set to indicate that it is a THUMB + // instruction. + Arm_address + source_address() const + { return this->source_address_; } + + // Return the destination address of the stub. This is the branch taken + // address of the original branch instruction. LSB is 1 if it is a THUMB + // instruction address. + Arm_address + destination_address() const + { return this->destination_address_; } + + // Return the instruction being fixed up. + uint32_t + original_insn() const + { return this->original_insn_; } + + protected: + // Cortex_a8_stubs are created via a stub factory. So these are protected. + Cortex_a8_stub(const Stub_template* stub_template, Relobj* relobj, + unsigned int shndx, Arm_address source_address, + Arm_address destination_address, uint32_t original_insn) + : Stub(stub_template), relobj_(relobj), shndx_(shndx), + source_address_(source_address | 1U), + destination_address_(destination_address), + original_insn_(original_insn) + { } + + friend class Stub_factory; + + // Return the relocation target address of the i-th relocation in the + // stub. + Arm_address + do_reloc_target(size_t i) + { + if (this->stub_template()->type() == arm_stub_a8_veneer_b_cond) + { + // The conditional branch veneer has two relocations. + gold_assert(i < 2); + return i == 0 ? this->source_address_ + 4 : this->destination_address_; + } + else + { + // All other Cortex-A8 stubs have only one relocation. + gold_assert(i == 0); + return this->destination_address_; + } + } + + // Return an instruction for the THUMB16_SPECIAL_TYPE instruction template. + uint16_t + do_thumb16_special(size_t); + + private: + // Object of the code section containing the branch being fixed up. + Relobj* relobj_; + // Section index of the code section containing the branch begin fixed up. + unsigned int shndx_; + // Source address of original branch. + Arm_address source_address_; + // Destination address of the original branch. + Arm_address destination_address_; + // Original branch instruction. This is needed for copying the condition + // code from a condition branch to its stub. + uint32_t original_insn_; +}; + +// ARMv4 BX Rx branch relocation stub class. +class Arm_v4bx_stub : public Stub +{ + public: + ~Arm_v4bx_stub() + { } + + // Return the associated register. + uint32_t + reg() const + { return this->reg_; } + + protected: + // Arm V4BX stubs are created via a stub factory. So these are protected. + Arm_v4bx_stub(const Stub_template* stub_template, const uint32_t reg) + : Stub(stub_template), reg_(reg) + { } + + friend class Stub_factory; + + // Return the relocation target address of the i-th relocation in the + // stub. + Arm_address + do_reloc_target(size_t) + { gold_unreachable(); } + + // This may be overridden in the child class. + virtual void + do_write(unsigned char* view, section_size_type view_size, bool big_endian) + { + if (big_endian) + this->do_fixed_endian_v4bx_write<true>(view, view_size); + else + this->do_fixed_endian_v4bx_write<false>(view, view_size); + } + + private: + // A template to implement do_write. + template<bool big_endian> + void inline + do_fixed_endian_v4bx_write(unsigned char* view, section_size_type) + { + const Insn_template* insns = this->stub_template()->insns(); + elfcpp::Swap<32, big_endian>::writeval(view, + (insns[0].data() + + (this->reg_ << 16))); + view += insns[0].size(); + elfcpp::Swap<32, big_endian>::writeval(view, + (insns[1].data() + this->reg_)); + view += insns[1].size(); + elfcpp::Swap<32, big_endian>::writeval(view, + (insns[2].data() + this->reg_)); + } + + // A register index (r0-r14), which is associated with the stub. + uint32_t reg_; +}; + +// Stub factory class. + +class Stub_factory +{ + public: + // Return the unique instance of this class. + static const Stub_factory& + get_instance() + { + static Stub_factory singleton; + return singleton; + } + + // Make a relocation stub. + Reloc_stub* + make_reloc_stub(Stub_type stub_type) const + { + gold_assert(stub_type >= arm_stub_reloc_first + && stub_type <= arm_stub_reloc_last); + return new Reloc_stub(this->stub_templates_[stub_type]); + } + + // Make a Cortex-A8 stub. + Cortex_a8_stub* + make_cortex_a8_stub(Stub_type stub_type, Relobj* relobj, unsigned int shndx, + Arm_address source, Arm_address destination, + uint32_t original_insn) const + { + gold_assert(stub_type >= arm_stub_cortex_a8_first + && stub_type <= arm_stub_cortex_a8_last); + return new Cortex_a8_stub(this->stub_templates_[stub_type], relobj, shndx, + source, destination, original_insn); + } + + // Make an ARM V4BX relocation stub. + // This method creates a stub from the arm_stub_v4_veneer_bx template only. + Arm_v4bx_stub* + make_arm_v4bx_stub(uint32_t reg) const + { + gold_assert(reg < 0xf); + return new Arm_v4bx_stub(this->stub_templates_[arm_stub_v4_veneer_bx], + reg); + } + + private: + // Constructor and destructor are protected since we only return a single + // instance created in Stub_factory::get_instance(). + + Stub_factory(); + + // A Stub_factory may not be copied since it is a singleton. + Stub_factory(const Stub_factory&); + Stub_factory& operator=(Stub_factory&); + + // Stub templates. These are initialized in the constructor. + const Stub_template* stub_templates_[arm_stub_type_last+1]; +}; + +// A class to hold stubs for the ARM target. + +template<bool big_endian> +class Stub_table : public Output_data +{ + public: + Stub_table(Arm_input_section<big_endian>* owner) + : Output_data(), owner_(owner), reloc_stubs_(), reloc_stubs_size_(0), + reloc_stubs_addralign_(1), cortex_a8_stubs_(), arm_v4bx_stubs_(0xf), + prev_data_size_(0), prev_addralign_(1) + { } + + ~Stub_table() + { } + + // Owner of this stub table. + Arm_input_section<big_endian>* + owner() const + { return this->owner_; } + + // Whether this stub table is empty. + bool + empty() const + { + return (this->reloc_stubs_.empty() + && this->cortex_a8_stubs_.empty() + && this->arm_v4bx_stubs_.empty()); + } + + // Return the current data size. + off_t + current_data_size() const + { return this->current_data_size_for_child(); } + + // Add a STUB with using KEY. Caller is reponsible for avoid adding + // if already a STUB with the same key has been added. + void + add_reloc_stub(Reloc_stub* stub, const Reloc_stub::Key& key) + { + const Stub_template* stub_template = stub->stub_template(); + gold_assert(stub_template->type() == key.stub_type()); + this->reloc_stubs_[key] = stub; + + // Assign stub offset early. We can do this because we never remove + // reloc stubs and they are in the beginning of the stub table. + uint64_t align = stub_template->alignment(); + this->reloc_stubs_size_ = align_address(this->reloc_stubs_size_, align); + stub->set_offset(this->reloc_stubs_size_); + this->reloc_stubs_size_ += stub_template->size(); + this->reloc_stubs_addralign_ = + std::max(this->reloc_stubs_addralign_, align); + } + + // Add a Cortex-A8 STUB that fixes up a THUMB branch at ADDRESS. + // Caller is reponsible for avoid adding if already a STUB with the same + // address has been added. + void + add_cortex_a8_stub(Arm_address address, Cortex_a8_stub* stub) + { + std::pair<Arm_address, Cortex_a8_stub*> value(address, stub); + this->cortex_a8_stubs_.insert(value); + } + + // Add an ARM V4BX relocation stub. A register index will be retrieved + // from the stub. + void + add_arm_v4bx_stub(Arm_v4bx_stub* stub) + { + gold_assert(stub != NULL && this->arm_v4bx_stubs_[stub->reg()] == NULL); + this->arm_v4bx_stubs_[stub->reg()] = stub; + } + + // Remove all Cortex-A8 stubs. + void + remove_all_cortex_a8_stubs(); + + // Look up a relocation stub using KEY. Return NULL if there is none. + Reloc_stub* + find_reloc_stub(const Reloc_stub::Key& key) const + { + typename Reloc_stub_map::const_iterator p = this->reloc_stubs_.find(key); + return (p != this->reloc_stubs_.end()) ? p->second : NULL; + } + + // Look up an arm v4bx relocation stub using the register index. + // Return NULL if there is none. + Arm_v4bx_stub* + find_arm_v4bx_stub(const uint32_t reg) const + { + gold_assert(reg < 0xf); + return this->arm_v4bx_stubs_[reg]; + } + + // Relocate stubs in this stub table. + void + relocate_stubs(const Relocate_info<32, big_endian>*, + Target_arm<big_endian>*, Output_section*, + unsigned char*, Arm_address, section_size_type); + + // Update data size and alignment at the end of a relaxation pass. Return + // true if either data size or alignment is different from that of the + // previous relaxation pass. + bool + update_data_size_and_addralign(); + + // Finalize stubs. Set the offsets of all stubs and mark input sections + // needing the Cortex-A8 workaround. + void + finalize_stubs(); + + // Apply Cortex-A8 workaround to an address range. + void + apply_cortex_a8_workaround_to_address_range(Target_arm<big_endian>*, + unsigned char*, Arm_address, + section_size_type); + + protected: + // Write out section contents. + void + do_write(Output_file*); + + // Return the required alignment. + uint64_t + do_addralign() const + { return this->prev_addralign_; } + + // Reset address and file offset. + void + do_reset_address_and_file_offset() + { this->set_current_data_size_for_child(this->prev_data_size_); } + + // Set final data size. + void + set_final_data_size() + { this->set_data_size(this->current_data_size()); } + + private: + // Relocate one stub. + void + relocate_stub(Stub*, const Relocate_info<32, big_endian>*, + Target_arm<big_endian>*, Output_section*, + unsigned char*, Arm_address, section_size_type); + + // Unordered map of relocation stubs. + typedef + Unordered_map<Reloc_stub::Key, Reloc_stub*, Reloc_stub::Key::hash, + Reloc_stub::Key::equal_to> + Reloc_stub_map; + + // List of Cortex-A8 stubs ordered by addresses of branches being + // fixed up in output. + typedef std::map<Arm_address, Cortex_a8_stub*> Cortex_a8_stub_list; + // List of Arm V4BX relocation stubs ordered by associated registers. + typedef std::vector<Arm_v4bx_stub*> Arm_v4bx_stub_list; + + // Owner of this stub table. + Arm_input_section<big_endian>* owner_; + // The relocation stubs. + Reloc_stub_map reloc_stubs_; + // Size of reloc stubs. + off_t reloc_stubs_size_; + // Maximum address alignment of reloc stubs. + uint64_t reloc_stubs_addralign_; + // The cortex_a8_stubs. + Cortex_a8_stub_list cortex_a8_stubs_; + // The Arm V4BX relocation stubs. + Arm_v4bx_stub_list arm_v4bx_stubs_; + // data size of this in the previous pass. + off_t prev_data_size_; + // address alignment of this in the previous pass. + uint64_t prev_addralign_; +}; + +// Arm_exidx_cantunwind class. This represents an EXIDX_CANTUNWIND entry +// we add to the end of an EXIDX input section that goes into the output. + +class Arm_exidx_cantunwind : public Output_section_data +{ + public: + Arm_exidx_cantunwind(Relobj* relobj, unsigned int shndx) + : Output_section_data(8, 4, true), relobj_(relobj), shndx_(shndx) + { } + + // Return the object containing the section pointed by this. + Relobj* + relobj() const + { return this->relobj_; } + + // Return the section index of the section pointed by this. + unsigned int + shndx() const + { return this->shndx_; } + + protected: + void + do_write(Output_file* of) + { + if (parameters->target().is_big_endian()) + this->do_fixed_endian_write<true>(of); + else + this->do_fixed_endian_write<false>(of); + } + + private: + // Implement do_write for a given endianness. + template<bool big_endian> + void inline + do_fixed_endian_write(Output_file*); + + // The object containing the section pointed by this. + Relobj* relobj_; + // The section index of the section pointed by this. + unsigned int shndx_; +}; + +// During EXIDX coverage fix-up, we compact an EXIDX section. The +// Offset map is used to map input section offset within the EXIDX section +// to the output offset from the start of this EXIDX section. + +typedef std::map<section_offset_type, section_offset_type> + Arm_exidx_section_offset_map; + +// Arm_exidx_merged_section class. This represents an EXIDX input section +// with some of its entries merged. + +class Arm_exidx_merged_section : public Output_relaxed_input_section +{ + public: + // Constructor for Arm_exidx_merged_section. + // EXIDX_INPUT_SECTION points to the unmodified EXIDX input section. + // SECTION_OFFSET_MAP points to a section offset map describing how + // parts of the input section are mapped to output. DELETED_BYTES is + // the number of bytes deleted from the EXIDX input section. + Arm_exidx_merged_section( + const Arm_exidx_input_section& exidx_input_section, + const Arm_exidx_section_offset_map& section_offset_map, + uint32_t deleted_bytes); + + // Return the original EXIDX input section. + const Arm_exidx_input_section& + exidx_input_section() const + { return this->exidx_input_section_; } + + // Return the section offset map. + const Arm_exidx_section_offset_map& + section_offset_map() const + { return this->section_offset_map_; } + + protected: + // Write merged section into file OF. + void + do_write(Output_file* of); + + bool + do_output_offset(const Relobj*, unsigned int, section_offset_type, + section_offset_type*) const; + + private: + // Original EXIDX input section. + const Arm_exidx_input_section& exidx_input_section_; + // Section offset map. + const Arm_exidx_section_offset_map& section_offset_map_; +}; + +// A class to wrap an ordinary input section containing executable code. + +template<bool big_endian> +class Arm_input_section : public Output_relaxed_input_section +{ + public: + Arm_input_section(Relobj* relobj, unsigned int shndx) + : Output_relaxed_input_section(relobj, shndx, 1), + original_addralign_(1), original_size_(0), stub_table_(NULL) + { } + + ~Arm_input_section() + { } + + // Initialize. + void + init(); + + // Whether this is a stub table owner. + bool + is_stub_table_owner() const + { return this->stub_table_ != NULL && this->stub_table_->owner() == this; } + + // Return the stub table. + Stub_table<big_endian>* + stub_table() const + { return this->stub_table_; } + + // Set the stub_table. + void + set_stub_table(Stub_table<big_endian>* stub_table) + { this->stub_table_ = stub_table; } + + // Downcast a base pointer to an Arm_input_section pointer. This is + // not type-safe but we only use Arm_input_section not the base class. + static Arm_input_section<big_endian>* + as_arm_input_section(Output_relaxed_input_section* poris) + { return static_cast<Arm_input_section<big_endian>*>(poris); } + + protected: + // Write data to output file. + void + do_write(Output_file*); + + // Return required alignment of this. + uint64_t + do_addralign() const + { + if (this->is_stub_table_owner()) + return std::max(this->stub_table_->addralign(), + this->original_addralign_); + else + return this->original_addralign_; + } + + // Finalize data size. + void + set_final_data_size(); + + // Reset address and file offset. + void + do_reset_address_and_file_offset(); + + // Output offset. + bool + do_output_offset(const Relobj* object, unsigned int shndx, + section_offset_type offset, + section_offset_type* poutput) const + { + if ((object == this->relobj()) + && (shndx == this->shndx()) + && (offset >= 0) + && (convert_types<uint64_t, section_offset_type>(offset) + <= this->original_size_)) + { + *poutput = offset; + return true; + } + else + return false; + } + + private: + // Copying is not allowed. + Arm_input_section(const Arm_input_section&); + Arm_input_section& operator=(const Arm_input_section&); + + // Address alignment of the original input section. + uint64_t original_addralign_; + // Section size of the original input section. + uint64_t original_size_; + // Stub table. + Stub_table<big_endian>* stub_table_; +}; + +// Arm_exidx_fixup class. This is used to define a number of methods +// and keep states for fixing up EXIDX coverage. + +class Arm_exidx_fixup +{ + public: + Arm_exidx_fixup(Output_section* exidx_output_section) + : exidx_output_section_(exidx_output_section), last_unwind_type_(UT_NONE), + last_inlined_entry_(0), last_input_section_(NULL), + section_offset_map_(NULL), first_output_text_section_(NULL) + { } + + ~Arm_exidx_fixup() + { delete this->section_offset_map_; } + + // Process an EXIDX section for entry merging. Return number of bytes to + // be deleted in output. If parts of the input EXIDX section are merged + // a heap allocated Arm_exidx_section_offset_map is store in the located + // PSECTION_OFFSET_MAP. The caller owns the map and is reponsible for + // releasing it. + template<bool big_endian> + uint32_t + process_exidx_section(const Arm_exidx_input_section* exidx_input_section, + Arm_exidx_section_offset_map** psection_offset_map); + + // Append an EXIDX_CANTUNWIND entry pointing at the end of the last + // input section, if there is not one already. + void + add_exidx_cantunwind_as_needed(); + + // Return the output section for the text section which is linked to the + // first exidx input in output. + Output_section* + first_output_text_section() const + { return this->first_output_text_section_; } + + private: + // Copying is not allowed. + Arm_exidx_fixup(const Arm_exidx_fixup&); + Arm_exidx_fixup& operator=(const Arm_exidx_fixup&); + + // Type of EXIDX unwind entry. + enum Unwind_type + { + // No type. + UT_NONE, + // EXIDX_CANTUNWIND. + UT_EXIDX_CANTUNWIND, + // Inlined entry. + UT_INLINED_ENTRY, + // Normal entry. + UT_NORMAL_ENTRY, + }; + + // Process an EXIDX entry. We only care about the second word of the + // entry. Return true if the entry can be deleted. + bool + process_exidx_entry(uint32_t second_word); + + // Update the current section offset map during EXIDX section fix-up. + // If there is no map, create one. INPUT_OFFSET is the offset of a + // reference point, DELETED_BYTES is the number of deleted by in the + // section so far. If DELETE_ENTRY is true, the reference point and + // all offsets after the previous reference point are discarded. + void + update_offset_map(section_offset_type input_offset, + section_size_type deleted_bytes, bool delete_entry); + + // EXIDX output section. + Output_section* exidx_output_section_; + // Unwind type of the last EXIDX entry processed. + Unwind_type last_unwind_type_; + // Last seen inlined EXIDX entry. + uint32_t last_inlined_entry_; + // Last processed EXIDX input section. + const Arm_exidx_input_section* last_input_section_; + // Section offset map created in process_exidx_section. + Arm_exidx_section_offset_map* section_offset_map_; + // Output section for the text section which is linked to the first exidx + // input in output. + Output_section* first_output_text_section_; +}; + +// Arm output section class. This is defined mainly to add a number of +// stub generation methods. + +template<bool big_endian> +class Arm_output_section : public Output_section +{ + public: + typedef std::vector<std::pair<Relobj*, unsigned int> > Text_section_list; + + Arm_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags) + : Output_section(name, type, flags) + { } + + ~Arm_output_section() + { } + + // Group input sections for stub generation. + void + group_sections(section_size_type, bool, Target_arm<big_endian>*); + + // Downcast a base pointer to an Arm_output_section pointer. This is + // not type-safe but we only use Arm_output_section not the base class. + static Arm_output_section<big_endian>* + as_arm_output_section(Output_section* os) + { return static_cast<Arm_output_section<big_endian>*>(os); } + + // Append all input text sections in this into LIST. + void + append_text_sections_to_list(Text_section_list* list); + + // Fix EXIDX coverage of this EXIDX output section. SORTED_TEXT_SECTION + // is a list of text input sections sorted in ascending order of their + // output addresses. + void + fix_exidx_coverage(Layout* layout, + const Text_section_list& sorted_text_section, + Symbol_table* symtab); + + private: + // For convenience. + typedef Output_section::Input_section Input_section; + typedef Output_section::Input_section_list Input_section_list; + + // Create a stub group. + void create_stub_group(Input_section_list::const_iterator, + Input_section_list::const_iterator, + Input_section_list::const_iterator, + Target_arm<big_endian>*, + std::vector<Output_relaxed_input_section*>*); +}; + +// Arm_exidx_input_section class. This represents an EXIDX input section. + +class Arm_exidx_input_section +{ + public: + static const section_offset_type invalid_offset = + static_cast<section_offset_type>(-1); + + Arm_exidx_input_section(Relobj* relobj, unsigned int shndx, + unsigned int link, uint32_t size, uint32_t addralign) + : relobj_(relobj), shndx_(shndx), link_(link), size_(size), + addralign_(addralign) + { } + + ~Arm_exidx_input_section() + { } + + // Accessors: This is a read-only class. + + // Return the object containing this EXIDX input section. + Relobj* + relobj() const + { return this->relobj_; } + + // Return the section index of this EXIDX input section. + unsigned int + shndx() const + { return this->shndx_; } + + // Return the section index of linked text section in the same object. + unsigned int + link() const + { return this->link_; } + + // Return size of the EXIDX input section. + uint32_t + size() const + { return this->size_; } + + // Reutnr address alignment of EXIDX input section. + uint32_t + addralign() const + { return this->addralign_; } + + private: + // Object containing this. + Relobj* relobj_; + // Section index of this. + unsigned int shndx_; + // text section linked to this in the same object. + unsigned int link_; + // Size of this. For ARM 32-bit is sufficient. + uint32_t size_; + // Address alignment of this. For ARM 32-bit is sufficient. + uint32_t addralign_; +}; + +// Arm_relobj class. + +template<bool big_endian> +class Arm_relobj : public Sized_relobj<32, big_endian> +{ + public: + static const Arm_address invalid_address = static_cast<Arm_address>(-1); + + Arm_relobj(const std::string& name, Input_file* input_file, off_t offset, + const typename elfcpp::Ehdr<32, big_endian>& ehdr) + : Sized_relobj<32, big_endian>(name, input_file, offset, ehdr), + stub_tables_(), local_symbol_is_thumb_function_(), + attributes_section_data_(NULL), mapping_symbols_info_(), + section_has_cortex_a8_workaround_(NULL), exidx_section_map_(), + output_local_symbol_count_needs_update_(false), + merge_flags_and_attributes_(true) + { } + + ~Arm_relobj() + { delete this->attributes_section_data_; } + + // Return the stub table of the SHNDX-th section if there is one. + Stub_table<big_endian>* + stub_table(unsigned int shndx) const + { + gold_assert(shndx < this->stub_tables_.size()); + return this->stub_tables_[shndx]; + } + + // Set STUB_TABLE to be the stub_table of the SHNDX-th section. + void + set_stub_table(unsigned int shndx, Stub_table<big_endian>* stub_table) + { + gold_assert(shndx < this->stub_tables_.size()); + this->stub_tables_[shndx] = stub_table; + } + + // Whether a local symbol is a THUMB function. R_SYM is the symbol table + // index. This is only valid after do_count_local_symbol is called. + bool + local_symbol_is_thumb_function(unsigned int r_sym) const + { + gold_assert(r_sym < this->local_symbol_is_thumb_function_.size()); + return this->local_symbol_is_thumb_function_[r_sym]; + } + + // Scan all relocation sections for stub generation. + void + scan_sections_for_stubs(Target_arm<big_endian>*, const Symbol_table*, + const Layout*); + + // Convert regular input section with index SHNDX to a relaxed section. + void + convert_input_section_to_relaxed_section(unsigned shndx) + { + // The stubs have relocations and we need to process them after writing + // out the stubs. So relocation now must follow section write. + this->set_section_offset(shndx, -1ULL); + this->set_relocs_must_follow_section_writes(); + } + + // Downcast a base pointer to an Arm_relobj pointer. This is + // not type-safe but we only use Arm_relobj not the base class. + static Arm_relobj<big_endian>* + as_arm_relobj(Relobj* relobj) + { return static_cast<Arm_relobj<big_endian>*>(relobj); } + + // Processor-specific flags in ELF file header. This is valid only after + // reading symbols. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + + // Attribute section data This is the contents of the .ARM.attribute section + // if there is one. + const Attributes_section_data* + attributes_section_data() const + { return this->attributes_section_data_; } + + // Mapping symbol location. + typedef std::pair<unsigned int, Arm_address> Mapping_symbol_position; + + // Functor for STL container. + struct Mapping_symbol_position_less + { + bool + operator()(const Mapping_symbol_position& p1, + const Mapping_symbol_position& p2) const + { + return (p1.first < p2.first + || (p1.first == p2.first && p1.second < p2.second)); + } + }; + + // We only care about the first character of a mapping symbol, so + // we only store that instead of the whole symbol name. + typedef std::map<Mapping_symbol_position, char, + Mapping_symbol_position_less> Mapping_symbols_info; + + // Whether a section contains any Cortex-A8 workaround. + bool + section_has_cortex_a8_workaround(unsigned int shndx) const + { + return (this->section_has_cortex_a8_workaround_ != NULL + && (*this->section_has_cortex_a8_workaround_)[shndx]); + } + + // Mark a section that has Cortex-A8 workaround. + void + mark_section_for_cortex_a8_workaround(unsigned int shndx) + { + if (this->section_has_cortex_a8_workaround_ == NULL) + this->section_has_cortex_a8_workaround_ = + new std::vector<bool>(this->shnum(), false); + (*this->section_has_cortex_a8_workaround_)[shndx] = true; + } + + // Return the EXIDX section of an text section with index SHNDX or NULL + // if the text section has no associated EXIDX section. + const Arm_exidx_input_section* + exidx_input_section_by_link(unsigned int shndx) const + { + Exidx_section_map::const_iterator p = this->exidx_section_map_.find(shndx); + return ((p != this->exidx_section_map_.end() + && p->second->link() == shndx) + ? p->second + : NULL); + } + + // Return the EXIDX section with index SHNDX or NULL if there is none. + const Arm_exidx_input_section* + exidx_input_section_by_shndx(unsigned shndx) const + { + Exidx_section_map::const_iterator p = this->exidx_section_map_.find(shndx); + return ((p != this->exidx_section_map_.end() + && p->second->shndx() == shndx) + ? p->second + : NULL); + } + + // Whether output local symbol count needs updating. + bool + output_local_symbol_count_needs_update() const + { return this->output_local_symbol_count_needs_update_; } + + // Set output_local_symbol_count_needs_update flag to be true. + void + set_output_local_symbol_count_needs_update() + { this->output_local_symbol_count_needs_update_ = true; } + + // Update output local symbol count at the end of relaxation. + void + update_output_local_symbol_count(); + + // Whether we want to merge processor-specific flags and attributes. + bool + merge_flags_and_attributes() const + { return this->merge_flags_and_attributes_; } + + protected: + // Post constructor setup. + void + do_setup() + { + // Call parent's setup method. + Sized_relobj<32, big_endian>::do_setup(); + + // Initialize look-up tables. + Stub_table_list empty_stub_table_list(this->shnum(), NULL); + this->stub_tables_.swap(empty_stub_table_list); + } + + // Count the local symbols. + void + do_count_local_symbols(Stringpool_template<char>*, + Stringpool_template<char>*); + + void + do_relocate_sections(const Symbol_table* symtab, const Layout* layout, + const unsigned char* pshdrs, + typename Sized_relobj<32, big_endian>::Views* pivews); + + // Read the symbol information. + void + do_read_symbols(Read_symbols_data* sd); + + // Process relocs for garbage collection. + void + do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*); + + private: + + // Whether a section needs to be scanned for relocation stubs. + bool + section_needs_reloc_stub_scanning(const elfcpp::Shdr<32, big_endian>&, + const Relobj::Output_sections&, + const Symbol_table *, const unsigned char*); + + // Whether a section is a scannable text section. + bool + section_is_scannable(const elfcpp::Shdr<32, big_endian>&, unsigned int, + const Output_section*, const Symbol_table *); + + // Whether a section needs to be scanned for the Cortex-A8 erratum. + bool + section_needs_cortex_a8_stub_scanning(const elfcpp::Shdr<32, big_endian>&, + unsigned int, Output_section*, + const Symbol_table *); + + // Scan a section for the Cortex-A8 erratum. + void + scan_section_for_cortex_a8_erratum(const elfcpp::Shdr<32, big_endian>&, + unsigned int, Output_section*, + Target_arm<big_endian>*); + + // Find the linked text section of an EXIDX section by looking at the + // first reloction of the EXIDX section. PSHDR points to the section + // headers of a relocation section and PSYMS points to the local symbols. + // PSHNDX points to a location storing the text section index if found. + // Return whether we can find the linked section. + bool + find_linked_text_section(const unsigned char* pshdr, + const unsigned char* psyms, unsigned int* pshndx); + + // + // Make a new Arm_exidx_input_section object for EXIDX section with + // index SHNDX and section header SHDR. TEXT_SHNDX is the section + // index of the linked text section. + void + make_exidx_input_section(unsigned int shndx, + const elfcpp::Shdr<32, big_endian>& shdr, + unsigned int text_shndx); + + // Return the output address of either a plain input section or a + // relaxed input section. SHNDX is the section index. + Arm_address + simple_input_section_output_address(unsigned int, Output_section*); + + typedef std::vector<Stub_table<big_endian>*> Stub_table_list; + typedef Unordered_map<unsigned int, const Arm_exidx_input_section*> + Exidx_section_map; + + // List of stub tables. + Stub_table_list stub_tables_; + // Bit vector to tell if a local symbol is a thumb function or not. + // This is only valid after do_count_local_symbol is called. + std::vector<bool> local_symbol_is_thumb_function_; + // processor-specific flags in ELF file header. + elfcpp::Elf_Word processor_specific_flags_; + // Object attributes if there is an .ARM.attributes section or NULL. + Attributes_section_data* attributes_section_data_; + // Mapping symbols information. + Mapping_symbols_info mapping_symbols_info_; + // Bitmap to indicate sections with Cortex-A8 workaround or NULL. + std::vector<bool>* section_has_cortex_a8_workaround_; + // Map a text section to its associated .ARM.exidx section, if there is one. + Exidx_section_map exidx_section_map_; + // Whether output local symbol count needs updating. + bool output_local_symbol_count_needs_update_; + // Whether we merge processor flags and attributes of this object to + // output. + bool merge_flags_and_attributes_; +}; + +// Arm_dynobj class. + +template<bool big_endian> +class Arm_dynobj : public Sized_dynobj<32, big_endian> +{ + public: + Arm_dynobj(const std::string& name, Input_file* input_file, off_t offset, + const elfcpp::Ehdr<32, big_endian>& ehdr) + : Sized_dynobj<32, big_endian>(name, input_file, offset, ehdr), + processor_specific_flags_(0), attributes_section_data_(NULL) + { } + + ~Arm_dynobj() + { delete this->attributes_section_data_; } + + // Downcast a base pointer to an Arm_relobj pointer. This is + // not type-safe but we only use Arm_relobj not the base class. + static Arm_dynobj<big_endian>* + as_arm_dynobj(Dynobj* dynobj) + { return static_cast<Arm_dynobj<big_endian>*>(dynobj); } + + // Processor-specific flags in ELF file header. This is valid only after + // reading symbols. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + + // Attributes section data. + const Attributes_section_data* + attributes_section_data() const + { return this->attributes_section_data_; } + + protected: + // Read the symbol information. + void + do_read_symbols(Read_symbols_data* sd); + + private: + // processor-specific flags in ELF file header. + elfcpp::Elf_Word processor_specific_flags_; + // Object attributes if there is an .ARM.attributes section or NULL. + Attributes_section_data* attributes_section_data_; +}; + +// Functor to read reloc addends during stub generation. + +template<int sh_type, bool big_endian> +struct Stub_addend_reader +{ + // Return the addend for a relocation of a particular type. Depending + // on whether this is a REL or RELA relocation, read the addend from a + // view or from a Reloc object. + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int /* r_type */, + const unsigned char* /* view */, + const typename Reloc_types<sh_type, + 32, big_endian>::Reloc& /* reloc */) const; +}; + +// Specialized Stub_addend_reader for SHT_REL type relocation sections. + +template<bool big_endian> +struct Stub_addend_reader<elfcpp::SHT_REL, big_endian> +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const; +}; + +// Specialized Stub_addend_reader for RELA type relocation sections. +// We currently do not handle RELA type relocation sections but it is trivial +// to implement the addend reader. This is provided for completeness and to +// make it easier to add support for RELA relocation sections in the future. + +template<bool big_endian> +struct Stub_addend_reader<elfcpp::SHT_RELA, big_endian> +{ + elfcpp::Elf_types<32>::Elf_Swxword + operator()( + unsigned int, + const unsigned char*, + const typename Reloc_types<elfcpp::SHT_RELA, 32, + big_endian>::Reloc& reloc) const + { return reloc.get_r_addend(); } +}; + +// Cortex_a8_reloc class. We keep record of relocation that may need +// the Cortex-A8 erratum workaround. + +class Cortex_a8_reloc +{ + public: + Cortex_a8_reloc(Reloc_stub* reloc_stub, unsigned r_type, + Arm_address destination) + : reloc_stub_(reloc_stub), r_type_(r_type), destination_(destination) + { } + + ~Cortex_a8_reloc() + { } + + // Accessors: This is a read-only class. + + // Return the relocation stub associated with this relocation if there is + // one. + const Reloc_stub* + reloc_stub() const + { return this->reloc_stub_; } + + // Return the relocation type. + unsigned int + r_type() const + { return this->r_type_; } + + // Return the destination address of the relocation. LSB stores the THUMB + // bit. + Arm_address + destination() const + { return this->destination_; } + + private: + // Associated relocation stub if there is one, or NULL. + const Reloc_stub* reloc_stub_; + // Relocation type. + unsigned int r_type_; + // Destination address of this relocation. LSB is used to distinguish + // ARM/THUMB mode. + Arm_address destination_; +}; + +// Arm_output_data_got class. We derive this from Output_data_got to add +// extra methods to handle TLS relocations in a static link. + +template<bool big_endian> +class Arm_output_data_got : public Output_data_got<32, big_endian> +{ + public: + Arm_output_data_got(Symbol_table* symtab, Layout* layout) + : Output_data_got<32, big_endian>(), symbol_table_(symtab), layout_(layout) + { } + + // Add a static entry for the GOT entry at OFFSET. GSYM is a global + // symbol and R_TYPE is the code of a dynamic relocation that needs to be + // applied in a static link. + void + add_static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym) + { this->static_relocs_.push_back(Static_reloc(got_offset, r_type, gsym)); } + + // Add a static reloc for the GOT entry at OFFSET. RELOBJ is an object + // defining a local symbol with INDEX. R_TYPE is the code of a dynamic + // relocation that needs to be applied in a static link. + void + add_static_reloc(unsigned int got_offset, unsigned int r_type, + Sized_relobj<32, big_endian>* relobj, unsigned int index) + { + this->static_relocs_.push_back(Static_reloc(got_offset, r_type, relobj, + index)); + } + + // Add a GOT pair for R_ARM_TLS_GD32. The creates a pair of GOT entries. + // The first one is initialized to be 1, which is the module index for + // the main executable and the second one 0. A reloc of the type + // R_ARM_TLS_DTPOFF32 will be created for the second GOT entry and will + // be applied by gold. GSYM is a global symbol. + void + add_tls_gd32_with_static_reloc(unsigned int got_type, Symbol* gsym); + + // Same as the above but for a local symbol in OBJECT with INDEX. + void + add_tls_gd32_with_static_reloc(unsigned int got_type, + Sized_relobj<32, big_endian>* object, + unsigned int index); + + protected: + // Write out the GOT table. + void + do_write(Output_file*); + + private: + // This class represent dynamic relocations that need to be applied by + // gold because we are using TLS relocations in a static link. + class Static_reloc + { + public: + Static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym) + : got_offset_(got_offset), r_type_(r_type), symbol_is_global_(true) + { this->u_.global.symbol = gsym; } + + Static_reloc(unsigned int got_offset, unsigned int r_type, + Sized_relobj<32, big_endian>* relobj, unsigned int index) + : got_offset_(got_offset), r_type_(r_type), symbol_is_global_(false) + { + this->u_.local.relobj = relobj; + this->u_.local.index = index; + } + + // Return the GOT offset. + unsigned int + got_offset() const + { return this->got_offset_; } + + // Relocation type. + unsigned int + r_type() const + { return this->r_type_; } + + // Whether the symbol is global or not. + bool + symbol_is_global() const + { return this->symbol_is_global_; } + + // For a relocation against a global symbol, the global symbol. + Symbol* + symbol() const + { + gold_assert(this->symbol_is_global_); + return this->u_.global.symbol; + } + + // For a relocation against a local symbol, the defining object. + Sized_relobj<32, big_endian>* + relobj() const + { + gold_assert(!this->symbol_is_global_); + return this->u_.local.relobj; + } + + // For a relocation against a local symbol, the local symbol index. + unsigned int + index() const + { + gold_assert(!this->symbol_is_global_); + return this->u_.local.index; + } + + private: + // GOT offset of the entry to which this relocation is applied. + unsigned int got_offset_; + // Type of relocation. + unsigned int r_type_; + // Whether this relocation is against a global symbol. + bool symbol_is_global_; + // A global or local symbol. + union + { + struct + { + // For a global symbol, the symbol itself. + Symbol* symbol; + } global; + struct + { + // For a local symbol, the object defining object. + Sized_relobj<32, big_endian>* relobj; + // For a local symbol, the symbol index. + unsigned int index; + } local; + } u_; + }; + + // Symbol table of the output object. + Symbol_table* symbol_table_; + // Layout of the output object. + Layout* layout_; + // Static relocs to be applied to the GOT. + std::vector<Static_reloc> static_relocs_; +}; + +// Utilities for manipulating integers of up to 32-bits + +namespace utils +{ + // Sign extend an n-bit unsigned integer stored in an uint32_t into + // an int32_t. NO_BITS must be between 1 to 32. + template<int no_bits> + static inline int32_t + sign_extend(uint32_t bits) + { + gold_assert(no_bits >= 0 && no_bits <= 32); + if (no_bits == 32) + return static_cast<int32_t>(bits); + uint32_t mask = (~((uint32_t) 0)) >> (32 - no_bits); + bits &= mask; + uint32_t top_bit = 1U << (no_bits - 1); + int32_t as_signed = static_cast<int32_t>(bits); + return (bits & top_bit) ? as_signed + (-top_bit * 2) : as_signed; + } + + // Detects overflow of an NO_BITS integer stored in a uint32_t. + template<int no_bits> + static inline bool + has_overflow(uint32_t bits) + { + gold_assert(no_bits >= 0 && no_bits <= 32); + if (no_bits == 32) + return false; + int32_t max = (1 << (no_bits - 1)) - 1; + int32_t min = -(1 << (no_bits - 1)); + int32_t as_signed = static_cast<int32_t>(bits); + return as_signed > max || as_signed < min; + } + + // Detects overflow of an NO_BITS integer stored in a uint32_t when it + // fits in the given number of bits as either a signed or unsigned value. + // For example, has_signed_unsigned_overflow<8> would check + // -128 <= bits <= 255 + template<int no_bits> + static inline bool + has_signed_unsigned_overflow(uint32_t bits) + { + gold_assert(no_bits >= 2 && no_bits <= 32); + if (no_bits == 32) + return false; + int32_t max = static_cast<int32_t>((1U << no_bits) - 1); + int32_t min = -(1 << (no_bits - 1)); + int32_t as_signed = static_cast<int32_t>(bits); + return as_signed > max || as_signed < min; + } + + // Select bits from A and B using bits in MASK. For each n in [0..31], + // the n-th bit in the result is chosen from the n-th bits of A and B. + // A zero selects A and a one selects B. + static inline uint32_t + bit_select(uint32_t a, uint32_t b, uint32_t mask) + { return (a & ~mask) | (b & mask); } +}; + +template<bool big_endian> +class Target_arm : public Sized_target<32, big_endian> +{ + public: + typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian> + Reloc_section; + + // When were are relocating a stub, we pass this as the relocation number. + static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1); + + Target_arm() + : Sized_target<32, big_endian>(&arm_info), + got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL), + copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), + got_mod_index_offset_(-1U), tls_base_symbol_defined_(false), + stub_tables_(), stub_factory_(Stub_factory::get_instance()), + may_use_blx_(false), should_force_pic_veneer_(false), + arm_input_section_map_(), attributes_section_data_(NULL), + fix_cortex_a8_(false), cortex_a8_relocs_info_() + { } + + // Whether we can use BLX. + bool + may_use_blx() const + { return this->may_use_blx_; } + + // Set use-BLX flag. + void + set_may_use_blx(bool value) + { this->may_use_blx_ = value; } + + // Whether we force PCI branch veneers. + bool + should_force_pic_veneer() const + { return this->should_force_pic_veneer_; } + + // Set PIC veneer flag. + void + set_should_force_pic_veneer(bool value) + { this->should_force_pic_veneer_ = value; } + + // Whether we use THUMB-2 instructions. + bool + using_thumb2() const + { + Object_attribute* attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch); + int arch = attr->int_value(); + return arch == elfcpp::TAG_CPU_ARCH_V6T2 || arch >= elfcpp::TAG_CPU_ARCH_V7; + } + + // Whether we use THUMB/THUMB-2 instructions only. + bool + using_thumb_only() const + { + Object_attribute* attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch); + if (attr->int_value() != elfcpp::TAG_CPU_ARCH_V7 + && attr->int_value() != elfcpp::TAG_CPU_ARCH_V7E_M) + return false; + attr = this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch_profile); + return attr->int_value() == 'M'; + } + + // Whether we have an NOP instruction. If not, use mov r0, r0 instead. + bool + may_use_arm_nop() const + { + Object_attribute* attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch); + int arch = attr->int_value(); + return (arch == elfcpp::TAG_CPU_ARCH_V6T2 + || arch == elfcpp::TAG_CPU_ARCH_V6K + || arch == elfcpp::TAG_CPU_ARCH_V7 + || arch == elfcpp::TAG_CPU_ARCH_V7E_M); + } + + // Whether we have THUMB-2 NOP.W instruction. + bool + may_use_thumb2_nop() const + { + Object_attribute* attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch); + int arch = attr->int_value(); + return (arch == elfcpp::TAG_CPU_ARCH_V6T2 + || arch == elfcpp::TAG_CPU_ARCH_V7 + || arch == elfcpp::TAG_CPU_ARCH_V7E_M); + } + + // Process the relocations to determine unreferenced sections for + // garbage collection. + void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + + // Scan the relocations to look for symbol adjustments. + void + scan_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + + // Finalize the sections. + void + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); + + // Return the value to use for a dynamic symbol which requires special + // treatment. + uint64_t + do_dynsym_value(const Symbol*) const; + + // Relocate a section. + void + relocate_section(const Relocate_info<32, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + Arm_address view_address, + section_size_type view_size, + const Reloc_symbol_changes*); + + // Scan the relocs during a relocatable link. + void + scan_relocatable_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs*); + + // Relocate a section during a relocatable link. + void + relocate_for_relocatable(const Relocate_info<32, big_endian>*, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs*, + unsigned char* view, + Arm_address view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size); + + // Return whether SYM is defined by the ABI. + bool + do_is_defined_by_abi(Symbol* sym) const + { return strcmp(sym->name(), "__tls_get_addr") == 0; } + + // Return whether there is a GOT section. + bool + has_got_section() const + { return this->got_ != NULL; } + + // Return the size of the GOT section. + section_size_type + got_size() + { + gold_assert(this->got_ != NULL); + return this->got_->data_size(); + } + + // Map platform-specific reloc types + static unsigned int + get_real_reloc_type (unsigned int r_type); + + // + // Methods to support stub-generations. + // + + // Return the stub factory + const Stub_factory& + stub_factory() const + { return this->stub_factory_; } + + // Make a new Arm_input_section object. + Arm_input_section<big_endian>* + new_arm_input_section(Relobj*, unsigned int); + + // Find the Arm_input_section object corresponding to the SHNDX-th input + // section of RELOBJ. + Arm_input_section<big_endian>* + find_arm_input_section(Relobj* relobj, unsigned int shndx) const; + + // Make a new Stub_table + Stub_table<big_endian>* + new_stub_table(Arm_input_section<big_endian>*); + + // Scan a section for stub generation. + void + scan_section_for_stubs(const Relocate_info<32, big_endian>*, unsigned int, + const unsigned char*, size_t, Output_section*, + bool, const unsigned char*, Arm_address, + section_size_type); + + // Relocate a stub. + void + relocate_stub(Stub*, const Relocate_info<32, big_endian>*, + Output_section*, unsigned char*, Arm_address, + section_size_type); + + // Get the default ARM target. + static Target_arm<big_endian>* + default_target() + { + gold_assert(parameters->target().machine_code() == elfcpp::EM_ARM + && parameters->target().is_big_endian() == big_endian); + return static_cast<Target_arm<big_endian>*>( + parameters->sized_target<32, big_endian>()); + } + + // Whether NAME belongs to a mapping symbol. + static bool + is_mapping_symbol_name(const char* name) + { + return (name + && name[0] == '$' + && (name[1] == 'a' || name[1] == 't' || name[1] == 'd') + && (name[2] == '\0' || name[2] == '.')); + } + + // Whether we work around the Cortex-A8 erratum. + bool + fix_cortex_a8() const + { return this->fix_cortex_a8_; } + + // Whether we fix R_ARM_V4BX relocation. + // 0 - do not fix + // 1 - replace with MOV instruction (armv4 target) + // 2 - make interworking veneer (>= armv4t targets only) + General_options::Fix_v4bx + fix_v4bx() const + { return parameters->options().fix_v4bx(); } + + // Scan a span of THUMB code section for Cortex-A8 erratum. + void + scan_span_for_cortex_a8_erratum(Arm_relobj<big_endian>*, unsigned int, + section_size_type, section_size_type, + const unsigned char*, Arm_address); + + // Apply Cortex-A8 workaround to a branch. + void + apply_cortex_a8_workaround(const Cortex_a8_stub*, Arm_address, + unsigned char*, Arm_address); + + protected: + // Make an ELF object. + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, big_endian>& ehdr); + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, !big_endian>&) + { gold_unreachable(); } + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<64, false>&) + { gold_unreachable(); } + + Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<64, true>&) + { gold_unreachable(); } + + // Make an output section. + Output_section* + do_make_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags) + { return new Arm_output_section<big_endian>(name, type, flags); } + + void + do_adjust_elf_header(unsigned char* view, int len) const; + + // We only need to generate stubs, and hence perform relaxation if we are + // not doing relocatable linking. + bool + do_may_relax() const + { return !parameters->options().relocatable(); } + + bool + do_relax(int, const Input_objects*, Symbol_table*, Layout*); + + // Determine whether an object attribute tag takes an integer, a + // string or both. + int + do_attribute_arg_type(int tag) const; + + // Reorder tags during output. + int + do_attributes_order(int num) const; + + // This is called when the target is selected as the default. + void + do_select_as_default_target() + { + // No locking is required since there should only be one default target. + // We cannot have both the big-endian and little-endian ARM targets + // as the default. + gold_assert(arm_reloc_property_table == NULL); + arm_reloc_property_table = new Arm_reloc_property_table(); + } + + private: + // The class which scans relocations. + class Scan + { + public: + Scan() + : issued_non_pic_error_(false) + { } + + inline void + local(Symbol_table* symtab, Layout* layout, Target_arm* target, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type, + const elfcpp::Sym<32, big_endian>& lsym); + + inline void + global(Symbol_table* symtab, Layout* layout, Target_arm* target, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, big_endian>& reloc, unsigned int r_type, + Symbol* gsym); + + inline bool + local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* , + Sized_relobj<32, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rel<32, big_endian>& , + unsigned int , + const elfcpp::Sym<32, big_endian>&) + { return false; } + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* , + Sized_relobj<32, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rel<32, big_endian>& , + unsigned int , Symbol*) + { return false; } + + private: + static void + unsupported_reloc_local(Sized_relobj<32, big_endian>*, + unsigned int r_type); + + static void + unsupported_reloc_global(Sized_relobj<32, big_endian>*, + unsigned int r_type, Symbol*); + + void + check_non_pic(Relobj*, unsigned int r_type); + + // Almost identical to Symbol::needs_plt_entry except that it also + // handles STT_ARM_TFUNC. + static bool + symbol_needs_plt_entry(const Symbol* sym) + { + // An undefined symbol from an executable does not need a PLT entry. + if (sym->is_undefined() && !parameters->options().shared()) + return false; + + return (!parameters->doing_static_link() + && (sym->type() == elfcpp::STT_FUNC + || sym->type() == elfcpp::STT_ARM_TFUNC) + && (sym->is_from_dynobj() + || sym->is_undefined() + || sym->is_preemptible())); + } + + // Whether we have issued an error about a non-PIC compilation. + bool issued_non_pic_error_; + }; + + // The class which implements relocation. + class Relocate + { + public: + Relocate() + { } + + ~Relocate() + { } + + // Return whether the static relocation needs to be applied. + inline bool + should_apply_static_reloc(const Sized_symbol<32>* gsym, + int ref_flags, + bool is_32bit, + Output_section* output_section); + + // Do a relocation. Return false if the caller should not issue + // any warnings about this relocation. + inline bool + relocate(const Relocate_info<32, big_endian>*, Target_arm*, + Output_section*, size_t relnum, + const elfcpp::Rel<32, big_endian>&, + unsigned int r_type, const Sized_symbol<32>*, + const Symbol_value<32>*, + unsigned char*, Arm_address, + section_size_type); + + // Return whether we want to pass flag NON_PIC_REF for this + // reloc. This means the relocation type accesses a symbol not via + // GOT or PLT. + static inline bool + reloc_is_non_pic (unsigned int r_type) + { + switch (r_type) + { + // These relocation types reference GOT or PLT entries explicitly. + case elfcpp::R_ARM_GOT_BREL: + case elfcpp::R_ARM_GOT_ABS: + case elfcpp::R_ARM_GOT_PREL: + case elfcpp::R_ARM_GOT_BREL12: + case elfcpp::R_ARM_PLT32_ABS: + case elfcpp::R_ARM_TLS_GD32: + case elfcpp::R_ARM_TLS_LDM32: + case elfcpp::R_ARM_TLS_IE32: + case elfcpp::R_ARM_TLS_IE12GP: + + // These relocate types may use PLT entries. + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_THM_JUMP19: + case elfcpp::R_ARM_PLT32: + case elfcpp::R_ARM_THM_XPC22: + case elfcpp::R_ARM_PREL31: + case elfcpp::R_ARM_SBREL31: + return false; + + default: + return true; + } + } + + private: + // Do a TLS relocation. + inline typename Arm_relocate_functions<big_endian>::Status + relocate_tls(const Relocate_info<32, big_endian>*, Target_arm<big_endian>*, + size_t, const elfcpp::Rel<32, big_endian>&, unsigned int, + const Sized_symbol<32>*, const Symbol_value<32>*, + unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, + section_size_type); + + }; + + // A class which returns the size required for a relocation type, + // used while scanning relocs during a relocatable link. + class Relocatable_size_for_reloc + { + public: + unsigned int + get_size_for_reloc(unsigned int, Relobj*); + }; + + // Adjust TLS relocation type based on the options and whether this + // is a local symbol. + static tls::Tls_optimization + optimize_tls_reloc(bool is_final, int r_type); + + // Get the GOT section, creating it if necessary. + Arm_output_data_got<big_endian>* + got_section(Symbol_table*, Layout*); + + // Get the GOT PLT section. + Output_data_space* + got_plt_section() const + { + gold_assert(this->got_plt_ != NULL); + return this->got_plt_; + } + + // Create a PLT entry for a global symbol. + void + make_plt_entry(Symbol_table*, Layout*, Symbol*); + + // Define the _TLS_MODULE_BASE_ symbol in the TLS segment. + void + define_tls_base_symbol(Symbol_table*, Layout*); + + // Create a GOT entry for the TLS module index. + unsigned int + got_mod_index_entry(Symbol_table* symtab, Layout* layout, + Sized_relobj<32, big_endian>* object); + + // Get the PLT section. + const Output_data_plt_arm<big_endian>* + plt_section() const + { + gold_assert(this->plt_ != NULL); + return this->plt_; + } + + // Get the dynamic reloc section, creating it if necessary. + Reloc_section* + rel_dyn_section(Layout*); + + // Get the section to use for TLS_DESC relocations. + Reloc_section* + rel_tls_desc_section(Layout*) const; + + // Return true if the symbol may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc(Symbol* gsym) + { + return (gsym->type() != elfcpp::STT_ARM_TFUNC + && gsym->may_need_copy_reloc()); + } + + // Add a potential copy relocation. + void + copy_reloc(Symbol_table* symtab, Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int shndx, Output_section* output_section, + Symbol* sym, const elfcpp::Rel<32, big_endian>& reloc) + { + this->copy_relocs_.copy_reloc(symtab, layout, + symtab->get_sized_symbol<32>(sym), + object, shndx, output_section, reloc, + this->rel_dyn_section(layout)); + } + + // Whether two EABI versions are compatible. + static bool + are_eabi_versions_compatible(elfcpp::Elf_Word v1, elfcpp::Elf_Word v2); + + // Merge processor-specific flags from input object and those in the ELF + // header of the output. + void + merge_processor_specific_flags(const std::string&, elfcpp::Elf_Word); + + // Get the secondary compatible architecture. + static int + get_secondary_compatible_arch(const Attributes_section_data*); + + // Set the secondary compatible architecture. + static void + set_secondary_compatible_arch(Attributes_section_data*, int); + + static int + tag_cpu_arch_combine(const char*, int, int*, int, int); + + // Helper to print AEABI enum tag value. + static std::string + aeabi_enum_name(unsigned int); + + // Return string value for TAG_CPU_name. + static std::string + tag_cpu_name_value(unsigned int); + + // Merge object attributes from input object and those in the output. + void + merge_object_attributes(const char*, const Attributes_section_data*); + + // Helper to get an AEABI object attribute + Object_attribute* + get_aeabi_object_attribute(int tag) const + { + Attributes_section_data* pasd = this->attributes_section_data_; + gold_assert(pasd != NULL); + Object_attribute* attr = + pasd->get_attribute(Object_attribute::OBJ_ATTR_PROC, tag); + gold_assert(attr != NULL); + return attr; + } + + // + // Methods to support stub-generations. + // + + // Group input sections for stub generation. + void + group_sections(Layout*, section_size_type, bool); + + // Scan a relocation for stub generation. + void + scan_reloc_for_stub(const Relocate_info<32, big_endian>*, unsigned int, + const Sized_symbol<32>*, unsigned int, + const Symbol_value<32>*, + elfcpp::Elf_types<32>::Elf_Swxword, Arm_address); + + // Scan a relocation section for stub. + template<int sh_type> + void + scan_reloc_section_for_stubs( + const Relocate_info<32, big_endian>* relinfo, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + const unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type); + + // Fix .ARM.exidx section coverage. + void + fix_exidx_coverage(Layout*, Arm_output_section<big_endian>*, Symbol_table*); + + // Functors for STL set. + struct output_section_address_less_than + { + bool + operator()(const Output_section* s1, const Output_section* s2) const + { return s1->address() < s2->address(); } + }; + + // Information about this specific target which we pass to the + // general Target structure. + static const Target::Target_info arm_info; + + // The types of GOT entries needed for this platform. + enum Got_type + { + GOT_TYPE_STANDARD = 0, // GOT entry for a regular symbol + GOT_TYPE_TLS_NOFFSET = 1, // GOT entry for negative TLS offset + GOT_TYPE_TLS_OFFSET = 2, // GOT entry for positive TLS offset + GOT_TYPE_TLS_PAIR = 3, // GOT entry for TLS module/offset pair + GOT_TYPE_TLS_DESC = 4 // GOT entry for TLS_DESC pair + }; + + typedef typename std::vector<Stub_table<big_endian>*> Stub_table_list; + + // Map input section to Arm_input_section. + typedef Unordered_map<Section_id, + Arm_input_section<big_endian>*, + Section_id_hash> + Arm_input_section_map; + + // Map output addresses to relocs for Cortex-A8 erratum. + typedef Unordered_map<Arm_address, const Cortex_a8_reloc*> + Cortex_a8_relocs_info; + + // The GOT section. + Arm_output_data_got<big_endian>* got_; + // The PLT section. + Output_data_plt_arm<big_endian>* plt_; + // The GOT PLT section. + Output_data_space* got_plt_; + // The dynamic reloc section. + Reloc_section* rel_dyn_; + // Relocs saved to avoid a COPY reloc. + Copy_relocs<elfcpp::SHT_REL, 32, big_endian> copy_relocs_; + // Space for variables copied with a COPY reloc. + Output_data_space* dynbss_; + // Offset of the GOT entry for the TLS module index. + unsigned int got_mod_index_offset_; + // True if the _TLS_MODULE_BASE_ symbol has been defined. + bool tls_base_symbol_defined_; + // Vector of Stub_tables created. + Stub_table_list stub_tables_; + // Stub factory. + const Stub_factory &stub_factory_; + // Whether we can use BLX. + bool may_use_blx_; + // Whether we force PIC branch veneers. + bool should_force_pic_veneer_; + // Map for locating Arm_input_sections. + Arm_input_section_map arm_input_section_map_; + // Attributes section data in output. + Attributes_section_data* attributes_section_data_; + // Whether we want to fix code for Cortex-A8 erratum. + bool fix_cortex_a8_; + // Map addresses to relocs for Cortex-A8 erratum. + Cortex_a8_relocs_info cortex_a8_relocs_info_; +}; + +template<bool big_endian> +const Target::Target_info Target_arm<big_endian>::arm_info = +{ + 32, // size + big_endian, // is_big_endian + elfcpp::EM_ARM, // machine_code + false, // has_make_symbol + false, // has_resolve + false, // has_code_fill + true, // is_default_stack_executable + '\0', // wrap_char + "/usr/lib/libc.so.1", // dynamic_linker + 0x8000, // default_text_segment_address + 0x1000, // abi_pagesize (overridable by -z max-page-size) + 0x1000, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + ".ARM.attributes", // attributes_section + "aeabi" // attributes_vendor +}; + +// Arm relocate functions class +// + +template<bool big_endian> +class Arm_relocate_functions : public Relocate_functions<32, big_endian> +{ + public: + typedef enum + { + STATUS_OKAY, // No error during relocation. + STATUS_OVERFLOW, // Relocation oveflow. + STATUS_BAD_RELOC // Relocation cannot be applied. + } Status; + + private: + typedef Relocate_functions<32, big_endian> Base; + typedef Arm_relocate_functions<big_endian> This; + + // Encoding of imm16 argument for movt and movw ARM instructions + // from ARM ARM: + // + // imm16 := imm4 | imm12 + // + // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0 + // +-------+---------------+-------+-------+-----------------------+ + // | | |imm4 | |imm12 | + // +-------+---------------+-------+-------+-----------------------+ + + // Extract the relocation addend from VAL based on the ARM + // instruction encoding described above. + static inline typename elfcpp::Swap<32, big_endian>::Valtype + extract_arm_movw_movt_addend( + typename elfcpp::Swap<32, big_endian>::Valtype val) + { + // According to the Elf ABI for ARM Architecture the immediate + // field is sign-extended to form the addend. + return utils::sign_extend<16>(((val >> 4) & 0xf000) | (val & 0xfff)); + } + + // Insert X into VAL based on the ARM instruction encoding described + // above. + static inline typename elfcpp::Swap<32, big_endian>::Valtype + insert_val_arm_movw_movt( + typename elfcpp::Swap<32, big_endian>::Valtype val, + typename elfcpp::Swap<32, big_endian>::Valtype x) + { + val &= 0xfff0f000; + val |= x & 0x0fff; + val |= (x & 0xf000) << 4; + return val; + } + + // Encoding of imm16 argument for movt and movw Thumb2 instructions + // from ARM ARM: + // + // imm16 := imm4 | i | imm3 | imm8 + // + // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0 + // +---------+-+-----------+-------++-+-----+-------+---------------+ + // | |i| |imm4 || |imm3 | |imm8 | + // +---------+-+-----------+-------++-+-----+-------+---------------+ + + // Extract the relocation addend from VAL based on the Thumb2 + // instruction encoding described above. + static inline typename elfcpp::Swap<32, big_endian>::Valtype + extract_thumb_movw_movt_addend( + typename elfcpp::Swap<32, big_endian>::Valtype val) + { + // According to the Elf ABI for ARM Architecture the immediate + // field is sign-extended to form the addend. + return utils::sign_extend<16>(((val >> 4) & 0xf000) + | ((val >> 15) & 0x0800) + | ((val >> 4) & 0x0700) + | (val & 0x00ff)); + } + + // Insert X into VAL based on the Thumb2 instruction encoding + // described above. + static inline typename elfcpp::Swap<32, big_endian>::Valtype + insert_val_thumb_movw_movt( + typename elfcpp::Swap<32, big_endian>::Valtype val, + typename elfcpp::Swap<32, big_endian>::Valtype x) + { + val &= 0xfbf08f00; + val |= (x & 0xf000) << 4; + val |= (x & 0x0800) << 15; + val |= (x & 0x0700) << 4; + val |= (x & 0x00ff); + return val; + } + + // Calculate the smallest constant Kn for the specified residual. + // (see (AAELF 4.6.1.4 Static ARM relocations, Group Relocations, p.32) + static uint32_t + calc_grp_kn(typename elfcpp::Swap<32, big_endian>::Valtype residual) + { + int32_t msb; + + if (residual == 0) + return 0; + // Determine the most significant bit in the residual and + // align the resulting value to a 2-bit boundary. + for (msb = 30; (msb >= 0) && !(residual & (3 << msb)); msb -= 2) + ; + // The desired shift is now (msb - 6), or zero, whichever + // is the greater. + return (((msb - 6) < 0) ? 0 : (msb - 6)); + } + + // Calculate the final residual for the specified group index. + // If the passed group index is less than zero, the method will return + // the value of the specified residual without any change. + // (see (AAELF 4.6.1.4 Static ARM relocations, Group Relocations, p.32) + static typename elfcpp::Swap<32, big_endian>::Valtype + calc_grp_residual(typename elfcpp::Swap<32, big_endian>::Valtype residual, + const int group) + { + for (int n = 0; n <= group; n++) + { + // Calculate which part of the value to mask. + uint32_t shift = calc_grp_kn(residual); + // Calculate the residual for the next time around. + residual &= ~(residual & (0xff << shift)); + } + + return residual; + } + + // Calculate the value of Gn for the specified group index. + // We return it in the form of an encoded constant-and-rotation. + // (see (AAELF 4.6.1.4 Static ARM relocations, Group Relocations, p.32) + static typename elfcpp::Swap<32, big_endian>::Valtype + calc_grp_gn(typename elfcpp::Swap<32, big_endian>::Valtype residual, + const int group) + { + typename elfcpp::Swap<32, big_endian>::Valtype gn = 0; + uint32_t shift = 0; + + for (int n = 0; n <= group; n++) + { + // Calculate which part of the value to mask. + shift = calc_grp_kn(residual); + // Calculate Gn in 32-bit as well as encoded constant-and-rotation form. + gn = residual & (0xff << shift); + // Calculate the residual for the next time around. + residual &= ~gn; + } + // Return Gn in the form of an encoded constant-and-rotation. + return ((gn >> shift) | ((gn <= 0xff ? 0 : (32 - shift) / 2) << 8)); + } + + public: + // Handle ARM long branches. + static typename This::Status + arm_branch_common(unsigned int, const Relocate_info<32, big_endian>*, + unsigned char *, const Sized_symbol<32>*, + const Arm_relobj<big_endian>*, unsigned int, + const Symbol_value<32>*, Arm_address, Arm_address, bool); + + // Handle THUMB long branches. + static typename This::Status + thumb_branch_common(unsigned int, const Relocate_info<32, big_endian>*, + unsigned char *, const Sized_symbol<32>*, + const Arm_relobj<big_endian>*, unsigned int, + const Symbol_value<32>*, Arm_address, Arm_address, bool); + + + // Return the branch offset of a 32-bit THUMB branch. + static inline int32_t + thumb32_branch_offset(uint16_t upper_insn, uint16_t lower_insn) + { + // We use the Thumb-2 encoding (backwards compatible with Thumb-1) + // involving the J1 and J2 bits. + uint32_t s = (upper_insn & (1U << 10)) >> 10; + uint32_t upper = upper_insn & 0x3ffU; + uint32_t lower = lower_insn & 0x7ffU; + uint32_t j1 = (lower_insn & (1U << 13)) >> 13; + uint32_t j2 = (lower_insn & (1U << 11)) >> 11; + uint32_t i1 = j1 ^ s ? 0 : 1; + uint32_t i2 = j2 ^ s ? 0 : 1; + + return utils::sign_extend<25>((s << 24) | (i1 << 23) | (i2 << 22) + | (upper << 12) | (lower << 1)); + } + + // Insert OFFSET to a 32-bit THUMB branch and return the upper instruction. + // UPPER_INSN is the original upper instruction of the branch. Caller is + // responsible for overflow checking and BLX offset adjustment. + static inline uint16_t + thumb32_branch_upper(uint16_t upper_insn, int32_t offset) + { + uint32_t s = offset < 0 ? 1 : 0; + uint32_t bits = static_cast<uint32_t>(offset); + return (upper_insn & ~0x7ffU) | ((bits >> 12) & 0x3ffU) | (s << 10); + } + + // Insert OFFSET to a 32-bit THUMB branch and return the lower instruction. + // LOWER_INSN is the original lower instruction of the branch. Caller is + // responsible for overflow checking and BLX offset adjustment. + static inline uint16_t + thumb32_branch_lower(uint16_t lower_insn, int32_t offset) + { + uint32_t s = offset < 0 ? 1 : 0; + uint32_t bits = static_cast<uint32_t>(offset); + return ((lower_insn & ~0x2fffU) + | ((((bits >> 23) & 1) ^ !s) << 13) + | ((((bits >> 22) & 1) ^ !s) << 11) + | ((bits >> 1) & 0x7ffU)); + } + + // Return the branch offset of a 32-bit THUMB conditional branch. + static inline int32_t + thumb32_cond_branch_offset(uint16_t upper_insn, uint16_t lower_insn) + { + uint32_t s = (upper_insn & 0x0400U) >> 10; + uint32_t j1 = (lower_insn & 0x2000U) >> 13; + uint32_t j2 = (lower_insn & 0x0800U) >> 11; + uint32_t lower = (lower_insn & 0x07ffU); + uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (upper_insn & 0x003fU); + + return utils::sign_extend<21>((upper << 12) | (lower << 1)); + } + + // Insert OFFSET to a 32-bit THUMB conditional branch and return the upper + // instruction. UPPER_INSN is the original upper instruction of the branch. + // Caller is responsible for overflow checking. + static inline uint16_t + thumb32_cond_branch_upper(uint16_t upper_insn, int32_t offset) + { + uint32_t s = offset < 0 ? 1 : 0; + uint32_t bits = static_cast<uint32_t>(offset); + return (upper_insn & 0xfbc0U) | (s << 10) | ((bits & 0x0003f000U) >> 12); + } + + // Insert OFFSET to a 32-bit THUMB conditional branch and return the lower + // instruction. LOWER_INSN is the original lower instruction of the branch. + // Caller is reponsible for overflow checking. + static inline uint16_t + thumb32_cond_branch_lower(uint16_t lower_insn, int32_t offset) + { + uint32_t bits = static_cast<uint32_t>(offset); + uint32_t j2 = (bits & 0x00080000U) >> 19; + uint32_t j1 = (bits & 0x00040000U) >> 18; + uint32_t lo = (bits & 0x00000ffeU) >> 1; + + return (lower_insn & 0xd000U) | (j1 << 13) | (j2 << 11) | lo; + } + + // R_ARM_ABS8: S + A + static inline typename This::Status + abs8(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval) + { + typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<8, big_endian>::readval(wv); + Reltype addend = utils::sign_extend<8>(val); + Reltype x = psymval->value(object, addend); + val = utils::bit_select(val, x, 0xffU); + elfcpp::Swap<8, big_endian>::writeval(wv, val); + + // R_ARM_ABS8 permits signed or unsigned results. + int signed_x = static_cast<int32_t>(x); + return ((signed_x < -128 || signed_x > 255) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_THM_ABS5: S + A + static inline typename This::Status + thm_abs5(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, big_endian>::readval(wv); + Reltype addend = (val & 0x7e0U) >> 6; + Reltype x = psymval->value(object, addend); + val = utils::bit_select(val, x << 6, 0x7e0U); + elfcpp::Swap<16, big_endian>::writeval(wv, val); + + // R_ARM_ABS16 permits signed or unsigned results. + int signed_x = static_cast<int32_t>(x); + return ((signed_x < -32768 || signed_x > 65535) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_ABS12: S + A + static inline typename This::Status + abs12(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + Reltype addend = val & 0x0fffU; + Reltype x = psymval->value(object, addend); + val = utils::bit_select(val, x, 0x0fffU); + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return (utils::has_overflow<12>(x) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_ABS16: S + A + static inline typename This::Status + abs16(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, big_endian>::readval(wv); + Reltype addend = utils::sign_extend<16>(val); + Reltype x = psymval->value(object, addend); + val = utils::bit_select(val, x, 0xffffU); + elfcpp::Swap<16, big_endian>::writeval(wv, val); + return (utils::has_signed_unsigned_overflow<16>(x) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_ABS32: (S + A) | T + static inline typename This::Status + abs32(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address thumb_bit) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype x = psymval->value(object, addend) | thumb_bit; + elfcpp::Swap<32, big_endian>::writeval(wv, x); + return This::STATUS_OKAY; + } + + // R_ARM_REL32: (S + A) | T - P + static inline typename This::Status + rel32(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype addend = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype x = (psymval->value(object, addend) | thumb_bit) - address; + elfcpp::Swap<32, big_endian>::writeval(wv, x); + return This::STATUS_OKAY; + } + + // R_ARM_THM_JUMP24: (S + A) | T - P + static typename This::Status + thm_jump19(unsigned char *view, const Arm_relobj<big_endian>* object, + const Symbol_value<32>* psymval, Arm_address address, + Arm_address thumb_bit); + + // R_ARM_THM_JUMP6: S + A – P + static inline typename This::Status + thm_jump6(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, big_endian>::readval(wv); + // bit[9]:bit[7:3]:’0’ (mask: 0x02f8) + Reltype addend = (((val & 0x0200) >> 3) | ((val & 0x00f8) >> 2)); + Reltype x = (psymval->value(object, addend) - address); + val = (val & 0xfd07) | ((x & 0x0040) << 3) | ((val & 0x003e) << 2); + elfcpp::Swap<16, big_endian>::writeval(wv, val); + // CZB does only forward jumps. + return ((x > 0x007e) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_THM_JUMP8: S + A – P + static inline typename This::Status + thm_jump8(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, big_endian>::readval(wv); + Reltype addend = utils::sign_extend<8>((val & 0x00ff) << 1); + Reltype x = (psymval->value(object, addend) - address); + elfcpp::Swap<16, big_endian>::writeval(wv, (val & 0xff00) | ((x & 0x01fe) >> 1)); + return (utils::has_overflow<8>(x) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_THM_JUMP11: S + A – P + static inline typename This::Status + thm_jump11(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<16, big_endian>::readval(wv); + Reltype addend = utils::sign_extend<11>((val & 0x07ff) << 1); + Reltype x = (psymval->value(object, addend) - address); + elfcpp::Swap<16, big_endian>::writeval(wv, (val & 0xf800) | ((x & 0x0ffe) >> 1)); + return (utils::has_overflow<11>(x) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_BASE_PREL: B(S) + A - P + static inline typename This::Status + base_prel(unsigned char* view, + Arm_address origin, + Arm_address address) + { + Base::rel32(view, origin - address); + return STATUS_OKAY; + } + + // R_ARM_BASE_ABS: B(S) + A + static inline typename This::Status + base_abs(unsigned char* view, + Arm_address origin) + { + Base::rel32(view, origin); + return STATUS_OKAY; + } + + // R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG + static inline typename This::Status + got_brel(unsigned char* view, + typename elfcpp::Swap<32, big_endian>::Valtype got_offset) + { + Base::rel32(view, got_offset); + return This::STATUS_OKAY; + } + + // R_ARM_GOT_PREL: GOT(S) + A - P + static inline typename This::Status + got_prel(unsigned char *view, + Arm_address got_entry, + Arm_address address) + { + Base::rel32(view, got_entry - address); + return This::STATUS_OKAY; + } + + // R_ARM_PREL: (S + A) | T - P + static inline typename This::Status + prel31(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = utils::sign_extend<31>(val); + Valtype x = (psymval->value(object, addend) | thumb_bit) - address; + val = utils::bit_select(val, x, 0x7fffffffU); + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return (utils::has_overflow<31>(x) ? + This::STATUS_OVERFLOW : This::STATUS_OKAY); + } + + // R_ARM_MOVW_ABS_NC: (S + A) | T (relative address base is ) + // R_ARM_MOVW_PREL_NC: (S + A) | T - P + // R_ARM_MOVW_BREL_NC: ((S + A) | T) - B(S) + // R_ARM_MOVW_BREL: ((S + A) | T) - B(S) + static inline typename This::Status + movw(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address relative_address_base, + Arm_address thumb_bit, + bool check_overflow) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = This::extract_arm_movw_movt_addend(val); + Valtype x = ((psymval->value(object, addend) | thumb_bit) + - relative_address_base); + val = This::insert_val_arm_movw_movt(val, x); + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return ((check_overflow && utils::has_overflow<16>(x)) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_MOVT_ABS: S + A (relative address base is 0) + // R_ARM_MOVT_PREL: S + A - P + // R_ARM_MOVT_BREL: S + A - B(S) + static inline typename This::Status + movt(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address relative_address_base) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = This::extract_arm_movw_movt_addend(val); + Valtype x = (psymval->value(object, addend) - relative_address_base) >> 16; + val = This::insert_val_arm_movw_movt(val, x); + elfcpp::Swap<32, big_endian>::writeval(wv, val); + // FIXME: IHI0044D says that we should check for overflow. + return This::STATUS_OKAY; + } + + // R_ARM_THM_MOVW_ABS_NC: S + A | T (relative_address_base is 0) + // R_ARM_THM_MOVW_PREL_NC: (S + A) | T - P + // R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S) + // R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S) + static inline typename This::Status + thm_movw(unsigned char *view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address relative_address_base, + Arm_address thumb_bit, + bool check_overflow) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16) + | elfcpp::Swap<16, big_endian>::readval(wv + 1); + Reltype addend = This::extract_thumb_movw_movt_addend(val); + Reltype x = + (psymval->value(object, addend) | thumb_bit) - relative_address_base; + val = This::insert_val_thumb_movw_movt(val, x); + elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff); + return ((check_overflow && utils::has_overflow<16>(x)) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_THM_MOVT_ABS: S + A (relative address base is 0) + // R_ARM_THM_MOVT_PREL: S + A - P + // R_ARM_THM_MOVT_BREL: S + A - B(S) + static inline typename This::Status + thm_movt(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address relative_address_base) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Reltype val = (elfcpp::Swap<16, big_endian>::readval(wv) << 16) + | elfcpp::Swap<16, big_endian>::readval(wv + 1); + Reltype addend = This::extract_thumb_movw_movt_addend(val); + Reltype x = (psymval->value(object, addend) - relative_address_base) >> 16; + val = This::insert_val_thumb_movw_movt(val, x); + elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff); + return This::STATUS_OKAY; + } + + // R_ARM_THM_ALU_PREL_11_0: ((S + A) | T) - Pa (Thumb32) + static inline typename This::Status + thm_alu11(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Reltype insn = (elfcpp::Swap<16, big_endian>::readval(wv) << 16) + | elfcpp::Swap<16, big_endian>::readval(wv + 1); + + // f e d c b|a|9|8 7 6 5|4|3 2 1 0||f|e d c|b a 9 8|7 6 5 4 3 2 1 0 + // ----------------------------------------------------------------------- + // ADD{S} 1 1 1 1 0|i|0|1 0 0 0|S|1 1 0 1||0|imm3 |Rd |imm8 + // ADDW 1 1 1 1 0|i|1|0 0 0 0|0|1 1 0 1||0|imm3 |Rd |imm8 + // ADR[+] 1 1 1 1 0|i|1|0 0 0 0|0|1 1 1 1||0|imm3 |Rd |imm8 + // SUB{S} 1 1 1 1 0|i|0|1 1 0 1|S|1 1 0 1||0|imm3 |Rd |imm8 + // SUBW 1 1 1 1 0|i|1|0 1 0 1|0|1 1 0 1||0|imm3 |Rd |imm8 + // ADR[-] 1 1 1 1 0|i|1|0 1 0 1|0|1 1 1 1||0|imm3 |Rd |imm8 + + // Determine a sign for the addend. + const int sign = ((insn & 0xf8ef0000) == 0xf0ad0000 + || (insn & 0xf8ef0000) == 0xf0af0000) ? -1 : 1; + // Thumb2 addend encoding: + // imm12 := i | imm3 | imm8 + int32_t addend = (insn & 0xff) + | ((insn & 0x00007000) >> 4) + | ((insn & 0x04000000) >> 15); + // Apply a sign to the added. + addend *= sign; + + int32_t x = (psymval->value(object, addend) | thumb_bit) + - (address & 0xfffffffc); + Reltype val = abs(x); + // Mask out the value and a distinct part of the ADD/SUB opcode + // (bits 7:5 of opword). + insn = (insn & 0xfb0f8f00) + | (val & 0xff) + | ((val & 0x700) << 4) + | ((val & 0x800) << 15); + // Set the opcode according to whether the value to go in the + // place is negative. + if (x < 0) + insn |= 0x00a00000; + + elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff); + return ((val > 0xfff) ? + This::STATUS_OVERFLOW : This::STATUS_OKAY); + } + + // R_ARM_THM_PC8: S + A - Pa (Thumb) + static inline typename This::Status + thm_pc8(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<16, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype insn = elfcpp::Swap<16, big_endian>::readval(wv); + Reltype addend = ((insn & 0x00ff) << 2); + int32_t x = (psymval->value(object, addend) - (address & 0xfffffffc)); + Reltype val = abs(x); + insn = (insn & 0xff00) | ((val & 0x03fc) >> 2); + + elfcpp::Swap<16, big_endian>::writeval(wv, insn); + return ((val > 0x03fc) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); + } + + // R_ARM_THM_PC12: S + A - Pa (Thumb32) + static inline typename This::Status + thm_pc12(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Reltype insn = (elfcpp::Swap<16, big_endian>::readval(wv) << 16) + | elfcpp::Swap<16, big_endian>::readval(wv + 1); + // Determine a sign for the addend (positive if the U bit is 1). + const int sign = (insn & 0x00800000) ? 1 : -1; + int32_t addend = (insn & 0xfff); + // Apply a sign to the added. + addend *= sign; + + int32_t x = (psymval->value(object, addend) - (address & 0xfffffffc)); + Reltype val = abs(x); + // Mask out and apply the value and the U bit. + insn = (insn & 0xff7ff000) | (val & 0xfff); + // Set the U bit according to whether the value to go in the + // place is positive. + if (x >= 0) + insn |= 0x00800000; + + elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff); + return ((val > 0xfff) ? + This::STATUS_OVERFLOW : This::STATUS_OKAY); + } + + // R_ARM_V4BX + static inline typename This::Status + v4bx(const Relocate_info<32, big_endian>* relinfo, + unsigned char *view, + const Arm_relobj<big_endian>* object, + const Arm_address address, + const bool is_interworking) + { + + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + + // Ensure that we have a BX instruction. + gold_assert((val & 0x0ffffff0) == 0x012fff10); + const uint32_t reg = (val & 0xf); + if (is_interworking && reg != 0xf) + { + Stub_table<big_endian>* stub_table = + object->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + Arm_v4bx_stub* stub = stub_table->find_arm_v4bx_stub(reg); + gold_assert(stub != NULL); + + int32_t veneer_address = + stub_table->address() + stub->offset() - 8 - address; + gold_assert((veneer_address <= ARM_MAX_FWD_BRANCH_OFFSET) + && (veneer_address >= ARM_MAX_BWD_BRANCH_OFFSET)); + // Replace with a branch to veneer (B <addr>) + val = (val & 0xf0000000) | 0x0a000000 + | ((veneer_address >> 2) & 0x00ffffff); + } + else + { + // Preserve Rm (lowest four bits) and the condition code + // (highest four bits). Other bits encode MOV PC,Rm. + val = (val & 0xf000000f) | 0x01a0f000; + } + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return This::STATUS_OKAY; + } + + // R_ARM_ALU_PC_G0_NC: ((S + A) | T) - P + // R_ARM_ALU_PC_G0: ((S + A) | T) - P + // R_ARM_ALU_PC_G1_NC: ((S + A) | T) - P + // R_ARM_ALU_PC_G1: ((S + A) | T) - P + // R_ARM_ALU_PC_G2: ((S + A) | T) - P + // R_ARM_ALU_SB_G0_NC: ((S + A) | T) - B(S) + // R_ARM_ALU_SB_G0: ((S + A) | T) - B(S) + // R_ARM_ALU_SB_G1_NC: ((S + A) | T) - B(S) + // R_ARM_ALU_SB_G1: ((S + A) | T) - B(S) + // R_ARM_ALU_SB_G2: ((S + A) | T) - B(S) + static inline typename This::Status + arm_grp_alu(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + const int group, + Arm_address address, + Arm_address thumb_bit, + bool check_overflow) + { + gold_assert(group >= 0 && group < 3); + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype insn = elfcpp::Swap<32, big_endian>::readval(wv); + + // ALU group relocations are allowed only for the ADD/SUB instructions. + // (0x00800000 - ADD, 0x00400000 - SUB) + const Valtype opcode = insn & 0x01e00000; + if (opcode != 0x00800000 && opcode != 0x00400000) + return This::STATUS_BAD_RELOC; + + // Determine a sign for the addend. + const int sign = (opcode == 0x00800000) ? 1 : -1; + // shifter = rotate_imm * 2 + const uint32_t shifter = (insn & 0xf00) >> 7; + // Initial addend value. + int32_t addend = insn & 0xff; + // Rotate addend right by shifter. + addend = (addend >> shifter) | (addend << (32 - shifter)); + // Apply a sign to the added. + addend *= sign; + + int32_t x = ((psymval->value(object, addend) | thumb_bit) - address); + Valtype gn = Arm_relocate_functions::calc_grp_gn(abs(x), group); + // Check for overflow if required + if (check_overflow + && (Arm_relocate_functions::calc_grp_residual(abs(x), group) != 0)) + return This::STATUS_OVERFLOW; + + // Mask out the value and the ADD/SUB part of the opcode; take care + // not to destroy the S bit. + insn &= 0xff1ff000; + // Set the opcode according to whether the value to go in the + // place is negative. + insn |= ((x < 0) ? 0x00400000 : 0x00800000); + // Encode the offset (encoded Gn). + insn |= gn; + + elfcpp::Swap<32, big_endian>::writeval(wv, insn); + return This::STATUS_OKAY; + } + + // R_ARM_LDR_PC_G0: S + A - P + // R_ARM_LDR_PC_G1: S + A - P + // R_ARM_LDR_PC_G2: S + A - P + // R_ARM_LDR_SB_G0: S + A - B(S) + // R_ARM_LDR_SB_G1: S + A - B(S) + // R_ARM_LDR_SB_G2: S + A - B(S) + static inline typename This::Status + arm_grp_ldr(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + const int group, + Arm_address address) + { + gold_assert(group >= 0 && group < 3); + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype insn = elfcpp::Swap<32, big_endian>::readval(wv); + + const int sign = (insn & 0x00800000) ? 1 : -1; + int32_t addend = (insn & 0xfff) * sign; + int32_t x = (psymval->value(object, addend) - address); + // Calculate the relevant G(n-1) value to obtain this stage residual. + Valtype residual = + Arm_relocate_functions::calc_grp_residual(abs(x), group - 1); + if (residual >= 0x1000) + return This::STATUS_OVERFLOW; + + // Mask out the value and U bit. + insn &= 0xff7ff000; + // Set the U bit for non-negative values. + if (x >= 0) + insn |= 0x00800000; + insn |= residual; + + elfcpp::Swap<32, big_endian>::writeval(wv, insn); + return This::STATUS_OKAY; + } + + // R_ARM_LDRS_PC_G0: S + A - P + // R_ARM_LDRS_PC_G1: S + A - P + // R_ARM_LDRS_PC_G2: S + A - P + // R_ARM_LDRS_SB_G0: S + A - B(S) + // R_ARM_LDRS_SB_G1: S + A - B(S) + // R_ARM_LDRS_SB_G2: S + A - B(S) + static inline typename This::Status + arm_grp_ldrs(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + const int group, + Arm_address address) + { + gold_assert(group >= 0 && group < 3); + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype insn = elfcpp::Swap<32, big_endian>::readval(wv); + + const int sign = (insn & 0x00800000) ? 1 : -1; + int32_t addend = (((insn & 0xf00) >> 4) + (insn & 0xf)) * sign; + int32_t x = (psymval->value(object, addend) - address); + // Calculate the relevant G(n-1) value to obtain this stage residual. + Valtype residual = + Arm_relocate_functions::calc_grp_residual(abs(x), group - 1); + if (residual >= 0x100) + return This::STATUS_OVERFLOW; + + // Mask out the value and U bit. + insn &= 0xff7ff0f0; + // Set the U bit for non-negative values. + if (x >= 0) + insn |= 0x00800000; + insn |= ((residual & 0xf0) << 4) | (residual & 0xf); + + elfcpp::Swap<32, big_endian>::writeval(wv, insn); + return This::STATUS_OKAY; + } + + // R_ARM_LDC_PC_G0: S + A - P + // R_ARM_LDC_PC_G1: S + A - P + // R_ARM_LDC_PC_G2: S + A - P + // R_ARM_LDC_SB_G0: S + A - B(S) + // R_ARM_LDC_SB_G1: S + A - B(S) + // R_ARM_LDC_SB_G2: S + A - B(S) + static inline typename This::Status + arm_grp_ldc(unsigned char* view, + const Sized_relobj<32, big_endian>* object, + const Symbol_value<32>* psymval, + const int group, + Arm_address address) + { + gold_assert(group >= 0 && group < 3); + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype insn = elfcpp::Swap<32, big_endian>::readval(wv); + + const int sign = (insn & 0x00800000) ? 1 : -1; + int32_t addend = ((insn & 0xff) << 2) * sign; + int32_t x = (psymval->value(object, addend) - address); + // Calculate the relevant G(n-1) value to obtain this stage residual. + Valtype residual = + Arm_relocate_functions::calc_grp_residual(abs(x), group - 1); + if ((residual & 0x3) != 0 || residual >= 0x400) + return This::STATUS_OVERFLOW; + + // Mask out the value and U bit. + insn &= 0xff7fff00; + // Set the U bit for non-negative values. + if (x >= 0) + insn |= 0x00800000; + insn |= (residual >> 2); + + elfcpp::Swap<32, big_endian>::writeval(wv, insn); + return This::STATUS_OKAY; + } +}; + +// Relocate ARM long branches. This handles relocation types +// R_ARM_CALL, R_ARM_JUMP24, R_ARM_PLT32 and R_ARM_XPC25. +// If IS_WEAK_UNDEFINED_WITH_PLT is true. The target symbol is weakly +// undefined and we do not use PLT in this relocation. In such a case, +// the branch is converted into an NOP. + +template<bool big_endian> +typename Arm_relocate_functions<big_endian>::Status +Arm_relocate_functions<big_endian>::arm_branch_common( + unsigned int r_type, + const Relocate_info<32, big_endian>* relinfo, + unsigned char *view, + const Sized_symbol<32>* gsym, + const Arm_relobj<big_endian>* object, + unsigned int r_sym, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit, + bool is_weakly_undefined_without_plt) +{ + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + + bool insn_is_b = (((val >> 28) & 0xf) <= 0xe) + && ((val & 0x0f000000UL) == 0x0a000000UL); + bool insn_is_uncond_bl = (val & 0xff000000UL) == 0xeb000000UL; + bool insn_is_cond_bl = (((val >> 28) & 0xf) < 0xe) + && ((val & 0x0f000000UL) == 0x0b000000UL); + bool insn_is_blx = (val & 0xfe000000UL) == 0xfa000000UL; + bool insn_is_any_branch = (val & 0x0e000000UL) == 0x0a000000UL; + + // Check that the instruction is valid. + if (r_type == elfcpp::R_ARM_CALL) + { + if (!insn_is_uncond_bl && !insn_is_blx) + return This::STATUS_BAD_RELOC; + } + else if (r_type == elfcpp::R_ARM_JUMP24) + { + if (!insn_is_b && !insn_is_cond_bl) + return This::STATUS_BAD_RELOC; + } + else if (r_type == elfcpp::R_ARM_PLT32) + { + if (!insn_is_any_branch) + return This::STATUS_BAD_RELOC; + } + else if (r_type == elfcpp::R_ARM_XPC25) + { + // FIXME: AAELF document IH0044C does not say much about it other + // than it being obsolete. + if (!insn_is_any_branch) + return This::STATUS_BAD_RELOC; + } + else + gold_unreachable(); + + // A branch to an undefined weak symbol is turned into a jump to + // the next instruction unless a PLT entry will be created. + // Do the same for local undefined symbols. + // The jump to the next instruction is optimized as a NOP depending + // on the architecture. + const Target_arm<big_endian>* arm_target = + Target_arm<big_endian>::default_target(); + if (is_weakly_undefined_without_plt) + { + Valtype cond = val & 0xf0000000U; + if (arm_target->may_use_arm_nop()) + val = cond | 0x0320f000; + else + val = cond | 0x01a00000; // Using pre-UAL nop: mov r0, r0. + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return This::STATUS_OKAY; + } + + Valtype addend = utils::sign_extend<26>(val << 2); + Valtype branch_target = psymval->value(object, addend); + int32_t branch_offset = branch_target - address; + + // We need a stub if the branch offset is too large or if we need + // to switch mode. + bool may_use_blx = arm_target->may_use_blx(); + Reloc_stub* stub = NULL; + if (utils::has_overflow<26>(branch_offset) + || ((thumb_bit != 0) && !(may_use_blx && r_type == elfcpp::R_ARM_CALL))) + { + Valtype unadjusted_branch_target = psymval->value(object, 0); + + Stub_type stub_type = + Reloc_stub::stub_type_for_reloc(r_type, address, + unadjusted_branch_target, + (thumb_bit != 0)); + if (stub_type != arm_stub_none) + { + Stub_table<big_endian>* stub_table = + object->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + Reloc_stub::Key stub_key(stub_type, gsym, object, r_sym, addend); + stub = stub_table->find_reloc_stub(stub_key); + gold_assert(stub != NULL); + thumb_bit = stub->stub_template()->entry_in_thumb_mode() ? 1 : 0; + branch_target = stub_table->address() + stub->offset() + addend; + branch_offset = branch_target - address; + gold_assert(!utils::has_overflow<26>(branch_offset)); + } + } + + // At this point, if we still need to switch mode, the instruction + // must either be a BLX or a BL that can be converted to a BLX. + if (thumb_bit != 0) + { + // Turn BL to BLX. + gold_assert(may_use_blx && r_type == elfcpp::R_ARM_CALL); + val = (val & 0xffffff) | 0xfa000000 | ((branch_offset & 2) << 23); + } + + val = utils::bit_select(val, (branch_offset >> 2), 0xffffffUL); + elfcpp::Swap<32, big_endian>::writeval(wv, val); + return (utils::has_overflow<26>(branch_offset) + ? This::STATUS_OVERFLOW : This::STATUS_OKAY); +} + +// Relocate THUMB long branches. This handles relocation types +// R_ARM_THM_CALL, R_ARM_THM_JUMP24 and R_ARM_THM_XPC22. +// If IS_WEAK_UNDEFINED_WITH_PLT is true. The target symbol is weakly +// undefined and we do not use PLT in this relocation. In such a case, +// the branch is converted into an NOP. + +template<bool big_endian> +typename Arm_relocate_functions<big_endian>::Status +Arm_relocate_functions<big_endian>::thumb_branch_common( + unsigned int r_type, + const Relocate_info<32, big_endian>* relinfo, + unsigned char *view, + const Sized_symbol<32>* gsym, + const Arm_relobj<big_endian>* object, + unsigned int r_sym, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit, + bool is_weakly_undefined_without_plt) +{ + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + uint32_t upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + uint32_t lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + + // FIXME: These tests are too loose and do not take THUMB/THUMB-2 difference + // into account. + bool is_bl_insn = (lower_insn & 0x1000U) == 0x1000U; + bool is_blx_insn = (lower_insn & 0x1000U) == 0x0000U; + + // Check that the instruction is valid. + if (r_type == elfcpp::R_ARM_THM_CALL) + { + if (!is_bl_insn && !is_blx_insn) + return This::STATUS_BAD_RELOC; + } + else if (r_type == elfcpp::R_ARM_THM_JUMP24) + { + // This cannot be a BLX. + if (!is_bl_insn) + return This::STATUS_BAD_RELOC; + } + else if (r_type == elfcpp::R_ARM_THM_XPC22) + { + // Check for Thumb to Thumb call. + if (!is_blx_insn) + return This::STATUS_BAD_RELOC; + if (thumb_bit != 0) + { + gold_warning(_("%s: Thumb BLX instruction targets " + "thumb function '%s'."), + object->name().c_str(), + (gsym ? gsym->name() : "(local)")); + // Convert BLX to BL. + lower_insn |= 0x1000U; + } + } + else + gold_unreachable(); + + // A branch to an undefined weak symbol is turned into a jump to + // the next instruction unless a PLT entry will be created. + // The jump to the next instruction is optimized as a NOP.W for + // Thumb-2 enabled architectures. + const Target_arm<big_endian>* arm_target = + Target_arm<big_endian>::default_target(); + if (is_weakly_undefined_without_plt) + { + if (arm_target->may_use_thumb2_nop()) + { + elfcpp::Swap<16, big_endian>::writeval(wv, 0xf3af); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, 0x8000); + } + else + { + elfcpp::Swap<16, big_endian>::writeval(wv, 0xe000); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, 0xbf00); + } + return This::STATUS_OKAY; + } + + int32_t addend = This::thumb32_branch_offset(upper_insn, lower_insn); + Arm_address branch_target = psymval->value(object, addend); + + // For BLX, bit 1 of target address comes from bit 1 of base address. + bool may_use_blx = arm_target->may_use_blx(); + if (thumb_bit == 0 && may_use_blx) + branch_target = utils::bit_select(branch_target, address, 0x2); + + int32_t branch_offset = branch_target - address; + + // We need a stub if the branch offset is too large or if we need + // to switch mode. + bool thumb2 = arm_target->using_thumb2(); + if ((!thumb2 && utils::has_overflow<23>(branch_offset)) + || (thumb2 && utils::has_overflow<25>(branch_offset)) + || ((thumb_bit == 0) + && (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx) + || r_type == elfcpp::R_ARM_THM_JUMP24))) + { + Arm_address unadjusted_branch_target = psymval->value(object, 0); + + Stub_type stub_type = + Reloc_stub::stub_type_for_reloc(r_type, address, + unadjusted_branch_target, + (thumb_bit != 0)); + + if (stub_type != arm_stub_none) + { + Stub_table<big_endian>* stub_table = + object->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + Reloc_stub::Key stub_key(stub_type, gsym, object, r_sym, addend); + Reloc_stub* stub = stub_table->find_reloc_stub(stub_key); + gold_assert(stub != NULL); + thumb_bit = stub->stub_template()->entry_in_thumb_mode() ? 1 : 0; + branch_target = stub_table->address() + stub->offset() + addend; + if (thumb_bit == 0 && may_use_blx) + branch_target = utils::bit_select(branch_target, address, 0x2); + branch_offset = branch_target - address; + } + } + + // At this point, if we still need to switch mode, the instruction + // must either be a BLX or a BL that can be converted to a BLX. + if (thumb_bit == 0) + { + gold_assert(may_use_blx + && (r_type == elfcpp::R_ARM_THM_CALL + || r_type == elfcpp::R_ARM_THM_XPC22)); + // Make sure this is a BLX. + lower_insn &= ~0x1000U; + } + else + { + // Make sure this is a BL. + lower_insn |= 0x1000U; + } + + // For a BLX instruction, make sure that the relocation is rounded up + // to a word boundary. This follows the semantics of the instruction + // which specifies that bit 1 of the target address will come from bit + // 1 of the base address. + if ((lower_insn & 0x5000U) == 0x4000U) + gold_assert((branch_offset & 3) == 0); + + // Put BRANCH_OFFSET back into the insn. Assumes two's complement. + // We use the Thumb-2 encoding, which is safe even if dealing with + // a Thumb-1 instruction by virtue of our overflow check above. */ + upper_insn = This::thumb32_branch_upper(upper_insn, branch_offset); + lower_insn = This::thumb32_branch_lower(lower_insn, branch_offset); + + elfcpp::Swap<16, big_endian>::writeval(wv, upper_insn); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn); + + gold_assert(!utils::has_overflow<25>(branch_offset)); + + return ((thumb2 + ? utils::has_overflow<25>(branch_offset) + : utils::has_overflow<23>(branch_offset)) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); +} + +// Relocate THUMB-2 long conditional branches. +// If IS_WEAK_UNDEFINED_WITH_PLT is true. The target symbol is weakly +// undefined and we do not use PLT in this relocation. In such a case, +// the branch is converted into an NOP. + +template<bool big_endian> +typename Arm_relocate_functions<big_endian>::Status +Arm_relocate_functions<big_endian>::thm_jump19( + unsigned char *view, + const Arm_relobj<big_endian>* object, + const Symbol_value<32>* psymval, + Arm_address address, + Arm_address thumb_bit) +{ + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(view); + uint32_t upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + uint32_t lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + int32_t addend = This::thumb32_cond_branch_offset(upper_insn, lower_insn); + + Arm_address branch_target = psymval->value(object, addend); + int32_t branch_offset = branch_target - address; + + // ??? Should handle interworking? GCC might someday try to + // use this for tail calls. + // FIXME: We do support thumb entry to PLT yet. + if (thumb_bit == 0) + { + gold_error(_("conditional branch to PLT in THUMB-2 not supported yet.")); + return This::STATUS_BAD_RELOC; + } + + // Put RELOCATION back into the insn. + upper_insn = This::thumb32_cond_branch_upper(upper_insn, branch_offset); + lower_insn = This::thumb32_cond_branch_lower(lower_insn, branch_offset); + + // Put the relocated value back in the object file: + elfcpp::Swap<16, big_endian>::writeval(wv, upper_insn); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn); + + return (utils::has_overflow<21>(branch_offset) + ? This::STATUS_OVERFLOW + : This::STATUS_OKAY); +} + +// Get the GOT section, creating it if necessary. + +template<bool big_endian> +Arm_output_data_got<big_endian>* +Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout) +{ + if (this->got_ == NULL) + { + gold_assert(symtab != NULL && layout != NULL); + + this->got_ = new Arm_output_data_got<big_endian>(symtab, layout); + + Output_section* os; + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_, false, false, false, + true); + // The old GNU linker creates a .got.plt section. We just + // create another set of data in the .got section. Note that we + // always create a PLT if we create a GOT, although the PLT + // might be empty. + this->got_plt_ = new Output_data_space(4, "** GOT PLT"); + os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_WRITE), + this->got_plt_, false, false, + false, false); + + // The first three entries are reserved. + this->got_plt_->set_current_data_size(3 * 4); + + // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, + this->got_plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); + } + return this->got_; +} + +// Get the dynamic reloc section, creating it if necessary. + +template<bool big_endian> +typename Target_arm<big_endian>::Reloc_section* +Target_arm<big_endian>::rel_dyn_section(Layout* layout) +{ + if (this->rel_dyn_ == NULL) + { + gold_assert(layout != NULL); + this->rel_dyn_ = new Reloc_section(parameters->options().combreloc()); + layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL, + elfcpp::SHF_ALLOC, this->rel_dyn_, true, + false, false, false); + } + return this->rel_dyn_; +} + +// Insn_template methods. + +// Return byte size of an instruction template. + +size_t +Insn_template::size() const +{ + switch (this->type()) + { + case THUMB16_TYPE: + case THUMB16_SPECIAL_TYPE: + return 2; + case ARM_TYPE: + case THUMB32_TYPE: + case DATA_TYPE: + return 4; + default: + gold_unreachable(); + } +} + +// Return alignment of an instruction template. + +unsigned +Insn_template::alignment() const +{ + switch (this->type()) + { + case THUMB16_TYPE: + case THUMB16_SPECIAL_TYPE: + case THUMB32_TYPE: + return 2; + case ARM_TYPE: + case DATA_TYPE: + return 4; + default: + gold_unreachable(); + } +} + +// Stub_template methods. + +Stub_template::Stub_template( + Stub_type type, const Insn_template* insns, + size_t insn_count) + : type_(type), insns_(insns), insn_count_(insn_count), alignment_(1), + entry_in_thumb_mode_(false), relocs_() +{ + off_t offset = 0; + + // Compute byte size and alignment of stub template. + for (size_t i = 0; i < insn_count; i++) + { + unsigned insn_alignment = insns[i].alignment(); + size_t insn_size = insns[i].size(); + gold_assert((offset & (insn_alignment - 1)) == 0); + this->alignment_ = std::max(this->alignment_, insn_alignment); + switch (insns[i].type()) + { + case Insn_template::THUMB16_TYPE: + case Insn_template::THUMB16_SPECIAL_TYPE: + if (i == 0) + this->entry_in_thumb_mode_ = true; + break; + + case Insn_template::THUMB32_TYPE: + if (insns[i].r_type() != elfcpp::R_ARM_NONE) + this->relocs_.push_back(Reloc(i, offset)); + if (i == 0) + this->entry_in_thumb_mode_ = true; + break; + + case Insn_template::ARM_TYPE: + // Handle cases where the target is encoded within the + // instruction. + if (insns[i].r_type() == elfcpp::R_ARM_JUMP24) + this->relocs_.push_back(Reloc(i, offset)); + break; + + case Insn_template::DATA_TYPE: + // Entry point cannot be data. + gold_assert(i != 0); + this->relocs_.push_back(Reloc(i, offset)); + break; + + default: + gold_unreachable(); + } + offset += insn_size; + } + this->size_ = offset; +} + +// Stub methods. + +// Template to implement do_write for a specific target endianness. + +template<bool big_endian> +void inline +Stub::do_fixed_endian_write(unsigned char* view, section_size_type view_size) +{ + const Stub_template* stub_template = this->stub_template(); + const Insn_template* insns = stub_template->insns(); + + // FIXME: We do not handle BE8 encoding yet. + unsigned char* pov = view; + for (size_t i = 0; i < stub_template->insn_count(); i++) + { + switch (insns[i].type()) + { + case Insn_template::THUMB16_TYPE: + elfcpp::Swap<16, big_endian>::writeval(pov, insns[i].data() & 0xffff); + break; + case Insn_template::THUMB16_SPECIAL_TYPE: + elfcpp::Swap<16, big_endian>::writeval( + pov, + this->thumb16_special(i)); + break; + case Insn_template::THUMB32_TYPE: + { + uint32_t hi = (insns[i].data() >> 16) & 0xffff; + uint32_t lo = insns[i].data() & 0xffff; + elfcpp::Swap<16, big_endian>::writeval(pov, hi); + elfcpp::Swap<16, big_endian>::writeval(pov + 2, lo); + } + break; + case Insn_template::ARM_TYPE: + case Insn_template::DATA_TYPE: + elfcpp::Swap<32, big_endian>::writeval(pov, insns[i].data()); + break; + default: + gold_unreachable(); + } + pov += insns[i].size(); + } + gold_assert(static_cast<section_size_type>(pov - view) == view_size); +} + +// Reloc_stub::Key methods. + +// Dump a Key as a string for debugging. + +std::string +Reloc_stub::Key::name() const +{ + if (this->r_sym_ == invalid_index) + { + // Global symbol key name + // <stub-type>:<symbol name>:<addend>. + const std::string sym_name = this->u_.symbol->name(); + // We need to print two hex number and two colons. So just add 100 bytes + // to the symbol name size. + size_t len = sym_name.size() + 100; + char* buffer = new char[len]; + int c = snprintf(buffer, len, "%d:%s:%x", this->stub_type_, + sym_name.c_str(), this->addend_); + gold_assert(c > 0 && c < static_cast<int>(len)); + delete[] buffer; + return std::string(buffer); + } + else + { + // local symbol key name + // <stub-type>:<object>:<r_sym>:<addend>. + const size_t len = 200; + char buffer[len]; + int c = snprintf(buffer, len, "%d:%p:%u:%x", this->stub_type_, + this->u_.relobj, this->r_sym_, this->addend_); + gold_assert(c > 0 && c < static_cast<int>(len)); + return std::string(buffer); + } +} + +// Reloc_stub methods. + +// Determine the type of stub needed, if any, for a relocation of R_TYPE at +// LOCATION to DESTINATION. +// This code is based on the arm_type_of_stub function in +// bfd/elf32-arm.c. We have changed the interface a liitle to keep the Stub +// class simple. + +Stub_type +Reloc_stub::stub_type_for_reloc( + unsigned int r_type, + Arm_address location, + Arm_address destination, + bool target_is_thumb) +{ + Stub_type stub_type = arm_stub_none; + + // This is a bit ugly but we want to avoid using a templated class for + // big and little endianities. + bool may_use_blx; + bool should_force_pic_veneer; + bool thumb2; + bool thumb_only; + if (parameters->target().is_big_endian()) + { + const Target_arm<true>* big_endian_target = + Target_arm<true>::default_target(); + may_use_blx = big_endian_target->may_use_blx(); + should_force_pic_veneer = big_endian_target->should_force_pic_veneer(); + thumb2 = big_endian_target->using_thumb2(); + thumb_only = big_endian_target->using_thumb_only(); + } + else + { + const Target_arm<false>* little_endian_target = + Target_arm<false>::default_target(); + may_use_blx = little_endian_target->may_use_blx(); + should_force_pic_veneer = little_endian_target->should_force_pic_veneer(); + thumb2 = little_endian_target->using_thumb2(); + thumb_only = little_endian_target->using_thumb_only(); + } + + int64_t branch_offset; + if (r_type == elfcpp::R_ARM_THM_CALL || r_type == elfcpp::R_ARM_THM_JUMP24) + { + // For THUMB BLX instruction, bit 1 of target comes from bit 1 of the + // base address (instruction address + 4). + if ((r_type == elfcpp::R_ARM_THM_CALL) && may_use_blx && !target_is_thumb) + destination = utils::bit_select(destination, location, 0x2); + branch_offset = static_cast<int64_t>(destination) - location; + + // Handle cases where: + // - this call goes too far (different Thumb/Thumb2 max + // distance) + // - it's a Thumb->Arm call and blx is not available, or it's a + // Thumb->Arm branch (not bl). A stub is needed in this case. + if ((!thumb2 + && (branch_offset > THM_MAX_FWD_BRANCH_OFFSET + || (branch_offset < THM_MAX_BWD_BRANCH_OFFSET))) + || (thumb2 + && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET + || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET))) + || ((!target_is_thumb) + && (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx) + || (r_type == elfcpp::R_ARM_THM_JUMP24)))) + { + if (target_is_thumb) + { + // Thumb to thumb. + if (!thumb_only) + { + stub_type = (parameters->options().shared() + || should_force_pic_veneer) + // PIC stubs. + ? ((may_use_blx + && (r_type == elfcpp::R_ARM_THM_CALL)) + // V5T and above. Stub starts with ARM code, so + // we must be able to switch mode before + // reaching it, which is only possible for 'bl' + // (ie R_ARM_THM_CALL relocation). + ? arm_stub_long_branch_any_thumb_pic + // On V4T, use Thumb code only. + : arm_stub_long_branch_v4t_thumb_thumb_pic) + + // non-PIC stubs. + : ((may_use_blx + && (r_type == elfcpp::R_ARM_THM_CALL)) + ? arm_stub_long_branch_any_any // V5T and above. + : arm_stub_long_branch_v4t_thumb_thumb); // V4T. + } + else + { + stub_type = (parameters->options().shared() + || should_force_pic_veneer) + ? arm_stub_long_branch_thumb_only_pic // PIC stub. + : arm_stub_long_branch_thumb_only; // non-PIC stub. + } + } + else + { + // Thumb to arm. + + // FIXME: We should check that the input section is from an + // object that has interwork enabled. + + stub_type = (parameters->options().shared() + || should_force_pic_veneer) + // PIC stubs. + ? ((may_use_blx + && (r_type == elfcpp::R_ARM_THM_CALL)) + ? arm_stub_long_branch_any_arm_pic // V5T and above. + : arm_stub_long_branch_v4t_thumb_arm_pic) // V4T. + + // non-PIC stubs. + : ((may_use_blx + && (r_type == elfcpp::R_ARM_THM_CALL)) + ? arm_stub_long_branch_any_any // V5T and above. + : arm_stub_long_branch_v4t_thumb_arm); // V4T. + + // Handle v4t short branches. + if ((stub_type == arm_stub_long_branch_v4t_thumb_arm) + && (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET) + && (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET)) + stub_type = arm_stub_short_branch_v4t_thumb_arm; + } + } + } + else if (r_type == elfcpp::R_ARM_CALL + || r_type == elfcpp::R_ARM_JUMP24 + || r_type == elfcpp::R_ARM_PLT32) + { + branch_offset = static_cast<int64_t>(destination) - location; + if (target_is_thumb) + { + // Arm to thumb. + + // FIXME: We should check that the input section is from an + // object that has interwork enabled. + + // We have an extra 2-bytes reach because of + // the mode change (bit 24 (H) of BLX encoding). + if (branch_offset > (ARM_MAX_FWD_BRANCH_OFFSET + 2) + || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET) + || ((r_type == elfcpp::R_ARM_CALL) && !may_use_blx) + || (r_type == elfcpp::R_ARM_JUMP24) + || (r_type == elfcpp::R_ARM_PLT32)) + { + stub_type = (parameters->options().shared() + || should_force_pic_veneer) + // PIC stubs. + ? (may_use_blx + ? arm_stub_long_branch_any_thumb_pic// V5T and above. + : arm_stub_long_branch_v4t_arm_thumb_pic) // V4T stub. + + // non-PIC stubs. + : (may_use_blx + ? arm_stub_long_branch_any_any // V5T and above. + : arm_stub_long_branch_v4t_arm_thumb); // V4T. + } + } + else + { + // Arm to arm. + if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET + || (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET)) + { + stub_type = (parameters->options().shared() + || should_force_pic_veneer) + ? arm_stub_long_branch_any_arm_pic // PIC stubs. + : arm_stub_long_branch_any_any; /// non-PIC. + } + } + } + + return stub_type; +} + +// Cortex_a8_stub methods. + +// Return the instruction for a THUMB16_SPECIAL_TYPE instruction template. +// I is the position of the instruction template in the stub template. + +uint16_t +Cortex_a8_stub::do_thumb16_special(size_t i) +{ + // The only use of this is to copy condition code from a conditional + // branch being worked around to the corresponding conditional branch in + // to the stub. + gold_assert(this->stub_template()->type() == arm_stub_a8_veneer_b_cond + && i == 0); + uint16_t data = this->stub_template()->insns()[i].data(); + gold_assert((data & 0xff00U) == 0xd000U); + data |= ((this->original_insn_ >> 22) & 0xf) << 8; + return data; +} + +// Stub_factory methods. + +Stub_factory::Stub_factory() +{ + // The instruction template sequences are declared as static + // objects and initialized first time the constructor runs. + + // Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx + // to reach the stub if necessary. + static const Insn_template elf32_arm_stub_long_branch_any_any[] = + { + Insn_template::arm_insn(0xe51ff004), // ldr pc, [pc, #-4] + Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0), + // dcd R_ARM_ABS32(X) + }; + + // V4T Arm -> Thumb long branch stub. Used on V4T where blx is not + // available. + static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb[] = + { + Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0] + Insn_template::arm_insn(0xe12fff1c), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0), + // dcd R_ARM_ABS32(X) + }; + + // Thumb -> Thumb long branch stub. Used on M-profile architectures. + static const Insn_template elf32_arm_stub_long_branch_thumb_only[] = + { + Insn_template::thumb16_insn(0xb401), // push {r0} + Insn_template::thumb16_insn(0x4802), // ldr r0, [pc, #8] + Insn_template::thumb16_insn(0x4684), // mov ip, r0 + Insn_template::thumb16_insn(0xbc01), // pop {r0} + Insn_template::thumb16_insn(0x4760), // bx ip + Insn_template::thumb16_insn(0xbf00), // nop + Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0), + // dcd R_ARM_ABS32(X) + }; + + // V4T Thumb -> Thumb long branch stub. Using the stack is not + // allowed. + static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb[] = + { + Insn_template::thumb16_insn(0x4778), // bx pc + Insn_template::thumb16_insn(0x46c0), // nop + Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0] + Insn_template::arm_insn(0xe12fff1c), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0), + // dcd R_ARM_ABS32(X) + }; + + // V4T Thumb -> ARM long branch stub. Used on V4T where blx is not + // available. + static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm[] = + { + Insn_template::thumb16_insn(0x4778), // bx pc + Insn_template::thumb16_insn(0x46c0), // nop + Insn_template::arm_insn(0xe51ff004), // ldr pc, [pc, #-4] + Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0), + // dcd R_ARM_ABS32(X) + }; + + // V4T Thumb -> ARM short branch stub. Shorter variant of the above + // one, when the destination is close enough. + static const Insn_template elf32_arm_stub_short_branch_v4t_thumb_arm[] = + { + Insn_template::thumb16_insn(0x4778), // bx pc + Insn_template::thumb16_insn(0x46c0), // nop + Insn_template::arm_rel_insn(0xea000000, -8), // b (X-8) + }; + + // ARM/Thumb -> ARM long branch stub, PIC. On V5T and above, use + // blx to reach the stub if necessary. + static const Insn_template elf32_arm_stub_long_branch_any_arm_pic[] = + { + Insn_template::arm_insn(0xe59fc000), // ldr r12, [pc] + Insn_template::arm_insn(0xe08ff00c), // add pc, pc, ip + Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4), + // dcd R_ARM_REL32(X-4) + }; + + // ARM/Thumb -> Thumb long branch stub, PIC. On V5T and above, use + // blx to reach the stub if necessary. We can not add into pc; + // it is not guaranteed to mode switch (different in ARMv6 and + // ARMv7). + static const Insn_template elf32_arm_stub_long_branch_any_thumb_pic[] = + { + Insn_template::arm_insn(0xe59fc004), // ldr r12, [pc, #4] + Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip + Insn_template::arm_insn(0xe12fff1c), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0), + // dcd R_ARM_REL32(X) + }; + + // V4T ARM -> ARM long branch stub, PIC. + static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] = + { + Insn_template::arm_insn(0xe59fc004), // ldr ip, [pc, #4] + Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip + Insn_template::arm_insn(0xe12fff1c), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0), + // dcd R_ARM_REL32(X) + }; + + // V4T Thumb -> ARM long branch stub, PIC. + static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] = + { + Insn_template::thumb16_insn(0x4778), // bx pc + Insn_template::thumb16_insn(0x46c0), // nop + Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0] + Insn_template::arm_insn(0xe08cf00f), // add pc, ip, pc + Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4), + // dcd R_ARM_REL32(X) + }; + + // Thumb -> Thumb long branch stub, PIC. Used on M-profile + // architectures. + static const Insn_template elf32_arm_stub_long_branch_thumb_only_pic[] = + { + Insn_template::thumb16_insn(0xb401), // push {r0} + Insn_template::thumb16_insn(0x4802), // ldr r0, [pc, #8] + Insn_template::thumb16_insn(0x46fc), // mov ip, pc + Insn_template::thumb16_insn(0x4484), // add ip, r0 + Insn_template::thumb16_insn(0xbc01), // pop {r0} + Insn_template::thumb16_insn(0x4760), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_REL32, 4), + // dcd R_ARM_REL32(X) + }; + + // V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not + // allowed. + static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] = + { + Insn_template::thumb16_insn(0x4778), // bx pc + Insn_template::thumb16_insn(0x46c0), // nop + Insn_template::arm_insn(0xe59fc004), // ldr ip, [pc, #4] + Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip + Insn_template::arm_insn(0xe12fff1c), // bx ip + Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0), + // dcd R_ARM_REL32(X) + }; + + // Cortex-A8 erratum-workaround stubs. + + // Stub used for conditional branches (which may be beyond +/-1MB away, + // so we can't use a conditional branch to reach this stub). + + // original code: + // + // b<cond> X + // after: + // + static const Insn_template elf32_arm_stub_a8_veneer_b_cond[] = + { + Insn_template::thumb16_bcond_insn(0xd001), // b<cond>.n true + Insn_template::thumb32_b_insn(0xf000b800, -4), // b.w after + Insn_template::thumb32_b_insn(0xf000b800, -4) // true: + // b.w X + }; + + // Stub used for b.w and bl.w instructions. + + static const Insn_template elf32_arm_stub_a8_veneer_b[] = + { + Insn_template::thumb32_b_insn(0xf000b800, -4) // b.w dest + }; + + static const Insn_template elf32_arm_stub_a8_veneer_bl[] = + { + Insn_template::thumb32_b_insn(0xf000b800, -4) // b.w dest + }; + + // Stub used for Thumb-2 blx.w instructions. We modified the original blx.w + // instruction (which switches to ARM mode) to point to this stub. Jump to + // the real destination using an ARM-mode branch. + static const Insn_template elf32_arm_stub_a8_veneer_blx[] = + { + Insn_template::arm_rel_insn(0xea000000, -8) // b dest + }; + + // Stub used to provide an interworking for R_ARM_V4BX relocation + // (bx r[n] instruction). + static const Insn_template elf32_arm_stub_v4_veneer_bx[] = + { + Insn_template::arm_insn(0xe3100001), // tst r<n>, #1 + Insn_template::arm_insn(0x01a0f000), // moveq pc, r<n> + Insn_template::arm_insn(0xe12fff10) // bx r<n> + }; + + // Fill in the stub template look-up table. Stub templates are constructed + // per instance of Stub_factory for fast look-up without locking + // in a thread-enabled environment. + + this->stub_templates_[arm_stub_none] = + new Stub_template(arm_stub_none, NULL, 0); + +#define DEF_STUB(x) \ + do \ + { \ + size_t array_size \ + = sizeof(elf32_arm_stub_##x) / sizeof(elf32_arm_stub_##x[0]); \ + Stub_type type = arm_stub_##x; \ + this->stub_templates_[type] = \ + new Stub_template(type, elf32_arm_stub_##x, array_size); \ + } \ + while (0); + + DEF_STUBS +#undef DEF_STUB +} + +// Stub_table methods. + +// Removel all Cortex-A8 stub. + +template<bool big_endian> +void +Stub_table<big_endian>::remove_all_cortex_a8_stubs() +{ + for (Cortex_a8_stub_list::iterator p = this->cortex_a8_stubs_.begin(); + p != this->cortex_a8_stubs_.end(); + ++p) + delete p->second; + this->cortex_a8_stubs_.clear(); +} + +// Relocate one stub. This is a helper for Stub_table::relocate_stubs(). + +template<bool big_endian> +void +Stub_table<big_endian>::relocate_stub( + Stub* stub, + const Relocate_info<32, big_endian>* relinfo, + Target_arm<big_endian>* arm_target, + Output_section* output_section, + unsigned char* view, + Arm_address address, + section_size_type view_size) +{ + const Stub_template* stub_template = stub->stub_template(); + if (stub_template->reloc_count() != 0) + { + // Adjust view to cover the stub only. + section_size_type offset = stub->offset(); + section_size_type stub_size = stub_template->size(); + gold_assert(offset + stub_size <= view_size); + + arm_target->relocate_stub(stub, relinfo, output_section, view + offset, + address + offset, stub_size); + } +} + +// Relocate all stubs in this stub table. + +template<bool big_endian> +void +Stub_table<big_endian>::relocate_stubs( + const Relocate_info<32, big_endian>* relinfo, + Target_arm<big_endian>* arm_target, + Output_section* output_section, + unsigned char* view, + Arm_address address, + section_size_type view_size) +{ + // If we are passed a view bigger than the stub table's. we need to + // adjust the view. + gold_assert(address == this->address() + && (view_size + == static_cast<section_size_type>(this->data_size()))); + + // Relocate all relocation stubs. + for (typename Reloc_stub_map::const_iterator p = this->reloc_stubs_.begin(); + p != this->reloc_stubs_.end(); + ++p) + this->relocate_stub(p->second, relinfo, arm_target, output_section, view, + address, view_size); + + // Relocate all Cortex-A8 stubs. + for (Cortex_a8_stub_list::iterator p = this->cortex_a8_stubs_.begin(); + p != this->cortex_a8_stubs_.end(); + ++p) + this->relocate_stub(p->second, relinfo, arm_target, output_section, view, + address, view_size); + + // Relocate all ARM V4BX stubs. + for (Arm_v4bx_stub_list::iterator p = this->arm_v4bx_stubs_.begin(); + p != this->arm_v4bx_stubs_.end(); + ++p) + { + if (*p != NULL) + this->relocate_stub(*p, relinfo, arm_target, output_section, view, + address, view_size); + } +} + +// Write out the stubs to file. + +template<bool big_endian> +void +Stub_table<big_endian>::do_write(Output_file* of) +{ + off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + // Write relocation stubs. + for (typename Reloc_stub_map::const_iterator p = this->reloc_stubs_.begin(); + p != this->reloc_stubs_.end(); + ++p) + { + Reloc_stub* stub = p->second; + Arm_address address = this->address() + stub->offset(); + gold_assert(address + == align_address(address, + stub->stub_template()->alignment())); + stub->write(oview + stub->offset(), stub->stub_template()->size(), + big_endian); + } + + // Write Cortex-A8 stubs. + for (Cortex_a8_stub_list::const_iterator p = this->cortex_a8_stubs_.begin(); + p != this->cortex_a8_stubs_.end(); + ++p) + { + Cortex_a8_stub* stub = p->second; + Arm_address address = this->address() + stub->offset(); + gold_assert(address + == align_address(address, + stub->stub_template()->alignment())); + stub->write(oview + stub->offset(), stub->stub_template()->size(), + big_endian); + } + + // Write ARM V4BX relocation stubs. + for (Arm_v4bx_stub_list::const_iterator p = this->arm_v4bx_stubs_.begin(); + p != this->arm_v4bx_stubs_.end(); + ++p) + { + if (*p == NULL) + continue; + + Arm_address address = this->address() + (*p)->offset(); + gold_assert(address + == align_address(address, + (*p)->stub_template()->alignment())); + (*p)->write(oview + (*p)->offset(), (*p)->stub_template()->size(), + big_endian); + } + + of->write_output_view(this->offset(), oview_size, oview); +} + +// Update the data size and address alignment of the stub table at the end +// of a relaxation pass. Return true if either the data size or the +// alignment changed in this relaxation pass. + +template<bool big_endian> +bool +Stub_table<big_endian>::update_data_size_and_addralign() +{ + // Go over all stubs in table to compute data size and address alignment. + off_t size = this->reloc_stubs_size_; + unsigned addralign = this->reloc_stubs_addralign_; + + for (Cortex_a8_stub_list::const_iterator p = this->cortex_a8_stubs_.begin(); + p != this->cortex_a8_stubs_.end(); + ++p) + { + const Stub_template* stub_template = p->second->stub_template(); + addralign = std::max(addralign, stub_template->alignment()); + size = (align_address(size, stub_template->alignment()) + + stub_template->size()); + } + + for (Arm_v4bx_stub_list::const_iterator p = this->arm_v4bx_stubs_.begin(); + p != this->arm_v4bx_stubs_.end(); + ++p) + { + if (*p == NULL) + continue; + + const Stub_template* stub_template = (*p)->stub_template(); + addralign = std::max(addralign, stub_template->alignment()); + size = (align_address(size, stub_template->alignment()) + + stub_template->size()); + } + + // Check if either data size or alignment changed in this pass. + // Update prev_data_size_ and prev_addralign_. These will be used + // as the current data size and address alignment for the next pass. + bool changed = size != this->prev_data_size_; + this->prev_data_size_ = size; + + if (addralign != this->prev_addralign_) + changed = true; + this->prev_addralign_ = addralign; + + return changed; +} + +// Finalize the stubs. This sets the offsets of the stubs within the stub +// table. It also marks all input sections needing Cortex-A8 workaround. + +template<bool big_endian> +void +Stub_table<big_endian>::finalize_stubs() +{ + off_t off = this->reloc_stubs_size_; + for (Cortex_a8_stub_list::const_iterator p = this->cortex_a8_stubs_.begin(); + p != this->cortex_a8_stubs_.end(); + ++p) + { + Cortex_a8_stub* stub = p->second; + const Stub_template* stub_template = stub->stub_template(); + uint64_t stub_addralign = stub_template->alignment(); + off = align_address(off, stub_addralign); + stub->set_offset(off); + off += stub_template->size(); + + // Mark input section so that we can determine later if a code section + // needs the Cortex-A8 workaround quickly. + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(stub->relobj()); + arm_relobj->mark_section_for_cortex_a8_workaround(stub->shndx()); + } + + for (Arm_v4bx_stub_list::const_iterator p = this->arm_v4bx_stubs_.begin(); + p != this->arm_v4bx_stubs_.end(); + ++p) + { + if (*p == NULL) + continue; + + const Stub_template* stub_template = (*p)->stub_template(); + uint64_t stub_addralign = stub_template->alignment(); + off = align_address(off, stub_addralign); + (*p)->set_offset(off); + off += stub_template->size(); + } + + gold_assert(off <= this->prev_data_size_); +} + +// Apply Cortex-A8 workaround to an address range between VIEW_ADDRESS +// and VIEW_ADDRESS + VIEW_SIZE - 1. VIEW points to the mapped address +// of the address range seen by the linker. + +template<bool big_endian> +void +Stub_table<big_endian>::apply_cortex_a8_workaround_to_address_range( + Target_arm<big_endian>* arm_target, + unsigned char* view, + Arm_address view_address, + section_size_type view_size) +{ + // Cortex-A8 stubs are sorted by addresses of branches being fixed up. + for (Cortex_a8_stub_list::const_iterator p = + this->cortex_a8_stubs_.lower_bound(view_address); + ((p != this->cortex_a8_stubs_.end()) + && (p->first < (view_address + view_size))); + ++p) + { + // We do not store the THUMB bit in the LSB of either the branch address + // or the stub offset. There is no need to strip the LSB. + Arm_address branch_address = p->first; + const Cortex_a8_stub* stub = p->second; + Arm_address stub_address = this->address() + stub->offset(); + + // Offset of the branch instruction relative to this view. + section_size_type offset = + convert_to_section_size_type(branch_address - view_address); + gold_assert((offset + 4) <= view_size); + + arm_target->apply_cortex_a8_workaround(stub, stub_address, + view + offset, branch_address); + } +} + +// Arm_input_section methods. + +// Initialize an Arm_input_section. + +template<bool big_endian> +void +Arm_input_section<big_endian>::init() +{ + Relobj* relobj = this->relobj(); + unsigned int shndx = this->shndx(); + + // Cache these to speed up size and alignment queries. It is too slow + // to call section_addraglin and section_size every time. + this->original_addralign_ = relobj->section_addralign(shndx); + this->original_size_ = relobj->section_size(shndx); + + // We want to make this look like the original input section after + // output sections are finalized. + Output_section* os = relobj->output_section(shndx); + off_t offset = relobj->output_section_offset(shndx); + gold_assert(os != NULL && !relobj->is_output_section_offset_invalid(shndx)); + this->set_address(os->address() + offset); + this->set_file_offset(os->offset() + offset); + + this->set_current_data_size(this->original_size_); + this->finalize_data_size(); +} + +template<bool big_endian> +void +Arm_input_section<big_endian>::do_write(Output_file* of) +{ + // We have to write out the original section content. + section_size_type section_size; + const unsigned char* section_contents = + this->relobj()->section_contents(this->shndx(), §ion_size, false); + of->write(this->offset(), section_contents, section_size); + + // If this owns a stub table and it is not empty, write it. + if (this->is_stub_table_owner() && !this->stub_table_->empty()) + this->stub_table_->write(of); +} + +// Finalize data size. + +template<bool big_endian> +void +Arm_input_section<big_endian>::set_final_data_size() +{ + // If this owns a stub table, finalize its data size as well. + if (this->is_stub_table_owner()) + { + uint64_t address = this->address(); + + // The stub table comes after the original section contents. + address += this->original_size_; + address = align_address(address, this->stub_table_->addralign()); + off_t offset = this->offset() + (address - this->address()); + this->stub_table_->set_address_and_file_offset(address, offset); + address += this->stub_table_->data_size(); + gold_assert(address == this->address() + this->current_data_size()); + } + + this->set_data_size(this->current_data_size()); +} + +// Reset address and file offset. + +template<bool big_endian> +void +Arm_input_section<big_endian>::do_reset_address_and_file_offset() +{ + // Size of the original input section contents. + off_t off = convert_types<off_t, uint64_t>(this->original_size_); + + // If this is a stub table owner, account for the stub table size. + if (this->is_stub_table_owner()) + { + Stub_table<big_endian>* stub_table = this->stub_table_; + + // Reset the stub table's address and file offset. The + // current data size for child will be updated after that. + stub_table_->reset_address_and_file_offset(); + off = align_address(off, stub_table_->addralign()); + off += stub_table->current_data_size(); + } + + this->set_current_data_size(off); +} + +// Arm_exidx_cantunwind methods. + +// Write this to Output file OF for a fixed endianness. + +template<bool big_endian> +void +Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of) +{ + off_t offset = this->offset(); + const section_size_type oview_size = 8; + unsigned char* const oview = of->get_output_view(offset, oview_size); + + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(oview); + + Output_section* os = this->relobj_->output_section(this->shndx_); + gold_assert(os != NULL); + + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(this->relobj_); + Arm_address output_offset = + arm_relobj->get_output_section_offset(this->shndx_); + Arm_address section_start; + if (output_offset != Arm_relobj<big_endian>::invalid_address) + section_start = os->address() + output_offset; + else + { + // Currently this only happens for a relaxed section. + const Output_relaxed_input_section* poris = + os->find_relaxed_input_section(this->relobj_, this->shndx_); + gold_assert(poris != NULL); + section_start = poris->address(); + } + + // We always append this to the end of an EXIDX section. + Arm_address output_address = + section_start + this->relobj_->section_size(this->shndx_); + + // Write out the entry. The first word either points to the beginning + // or after the end of a text section. The second word is the special + // EXIDX_CANTUNWIND value. + uint32_t prel31_offset = output_address - this->address(); + if (utils::has_overflow<31>(offset)) + gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry")); + elfcpp::Swap<32, big_endian>::writeval(wv, prel31_offset & 0x7fffffffU); + elfcpp::Swap<32, big_endian>::writeval(wv + 1, elfcpp::EXIDX_CANTUNWIND); + + of->write_output_view(this->offset(), oview_size, oview); +} + +// Arm_exidx_merged_section methods. + +// Constructor for Arm_exidx_merged_section. +// EXIDX_INPUT_SECTION points to the unmodified EXIDX input section. +// SECTION_OFFSET_MAP points to a section offset map describing how +// parts of the input section are mapped to output. DELETED_BYTES is +// the number of bytes deleted from the EXIDX input section. + +Arm_exidx_merged_section::Arm_exidx_merged_section( + const Arm_exidx_input_section& exidx_input_section, + const Arm_exidx_section_offset_map& section_offset_map, + uint32_t deleted_bytes) + : Output_relaxed_input_section(exidx_input_section.relobj(), + exidx_input_section.shndx(), + exidx_input_section.addralign()), + exidx_input_section_(exidx_input_section), + section_offset_map_(section_offset_map) +{ + // Fix size here so that we do not need to implement set_final_data_size. + this->set_data_size(exidx_input_section.size() - deleted_bytes); + this->fix_data_size(); +} + +// Given an input OBJECT, an input section index SHNDX within that +// object, and an OFFSET relative to the start of that input +// section, return whether or not the corresponding offset within +// the output section is known. If this function returns true, it +// sets *POUTPUT to the output offset. The value -1 indicates that +// this input offset is being discarded. + +bool +Arm_exidx_merged_section::do_output_offset( + const Relobj* relobj, + unsigned int shndx, + section_offset_type offset, + section_offset_type* poutput) const +{ + // We only handle offsets for the original EXIDX input section. + if (relobj != this->exidx_input_section_.relobj() + || shndx != this->exidx_input_section_.shndx()) + return false; + + section_offset_type section_size = + convert_types<section_offset_type>(this->exidx_input_section_.size()); + if (offset < 0 || offset >= section_size) + // Input offset is out of valid range. + *poutput = -1; + else + { + // We need to look up the section offset map to determine the output + // offset. Find the reference point in map that is first offset + // bigger than or equal to this offset. + Arm_exidx_section_offset_map::const_iterator p = + this->section_offset_map_.lower_bound(offset); + + // The section offset maps are build such that this should not happen if + // input offset is in the valid range. + gold_assert(p != this->section_offset_map_.end()); + + // We need to check if this is dropped. + section_offset_type ref = p->first; + section_offset_type mapped_ref = p->second; + + if (mapped_ref != Arm_exidx_input_section::invalid_offset) + // Offset is present in output. + *poutput = mapped_ref + (offset - ref); + else + // Offset is discarded owing to EXIDX entry merging. + *poutput = -1; + } + + return true; +} + +// Write this to output file OF. + +void +Arm_exidx_merged_section::do_write(Output_file* of) +{ + // If we retain or discard the whole EXIDX input section, we would + // not be here. + gold_assert(this->data_size() != this->exidx_input_section_.size() + && this->data_size() != 0); + + off_t offset = this->offset(); + const section_size_type oview_size = this->data_size(); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + Output_section* os = this->relobj()->output_section(this->shndx()); + gold_assert(os != NULL); + + // Get contents of EXIDX input section. + section_size_type section_size; + const unsigned char* section_contents = + this->relobj()->section_contents(this->shndx(), §ion_size, false); + gold_assert(section_size == this->exidx_input_section_.size()); + + // Go over spans of input offsets and write only those that are not + // discarded. + section_offset_type in_start = 0; + section_offset_type out_start = 0; + for(Arm_exidx_section_offset_map::const_iterator p = + this->section_offset_map_.begin(); + p != this->section_offset_map_.end(); + ++p) + { + section_offset_type in_end = p->first; + gold_assert(in_end >= in_start); + section_offset_type out_end = p->second; + size_t in_chunk_size = convert_types<size_t>(in_end - in_start + 1); + if (out_end != -1) + { + size_t out_chunk_size = + convert_types<size_t>(out_end - out_start + 1); + gold_assert(out_chunk_size == in_chunk_size); + memcpy(oview + out_start, section_contents + in_start, + out_chunk_size); + out_start += out_chunk_size; + } + in_start += in_chunk_size; + } + + gold_assert(convert_to_section_size_type(out_start) == oview_size); + of->write_output_view(this->offset(), oview_size, oview); +} + +// Arm_exidx_fixup methods. + +// Append an EXIDX_CANTUNWIND in the current output section if the last entry +// is not an EXIDX_CANTUNWIND entry already. The new EXIDX_CANTUNWIND entry +// points to the end of the last seen EXIDX section. + +void +Arm_exidx_fixup::add_exidx_cantunwind_as_needed() +{ + if (this->last_unwind_type_ != UT_EXIDX_CANTUNWIND + && this->last_input_section_ != NULL) + { + Relobj* relobj = this->last_input_section_->relobj(); + unsigned int text_shndx = this->last_input_section_->link(); + Arm_exidx_cantunwind* cantunwind = + new Arm_exidx_cantunwind(relobj, text_shndx); + this->exidx_output_section_->add_output_section_data(cantunwind); + this->last_unwind_type_ = UT_EXIDX_CANTUNWIND; + } +} + +// Process an EXIDX section entry in input. Return whether this entry +// can be deleted in the output. SECOND_WORD in the second word of the +// EXIDX entry. + +bool +Arm_exidx_fixup::process_exidx_entry(uint32_t second_word) +{ + bool delete_entry; + if (second_word == elfcpp::EXIDX_CANTUNWIND) + { + // Merge if previous entry is also an EXIDX_CANTUNWIND. + delete_entry = this->last_unwind_type_ == UT_EXIDX_CANTUNWIND; + this->last_unwind_type_ = UT_EXIDX_CANTUNWIND; + } + else if ((second_word & 0x80000000) != 0) + { + // Inlined unwinding data. Merge if equal to previous. + delete_entry = (this->last_unwind_type_ == UT_INLINED_ENTRY + && this->last_inlined_entry_ == second_word); + this->last_unwind_type_ = UT_INLINED_ENTRY; + this->last_inlined_entry_ = second_word; + } + else + { + // Normal table entry. In theory we could merge these too, + // but duplicate entries are likely to be much less common. + delete_entry = false; + this->last_unwind_type_ = UT_NORMAL_ENTRY; + } + return delete_entry; +} + +// Update the current section offset map during EXIDX section fix-up. +// If there is no map, create one. INPUT_OFFSET is the offset of a +// reference point, DELETED_BYTES is the number of deleted by in the +// section so far. If DELETE_ENTRY is true, the reference point and +// all offsets after the previous reference point are discarded. + +void +Arm_exidx_fixup::update_offset_map( + section_offset_type input_offset, + section_size_type deleted_bytes, + bool delete_entry) +{ + if (this->section_offset_map_ == NULL) + this->section_offset_map_ = new Arm_exidx_section_offset_map(); + section_offset_type output_offset; + if (delete_entry) + output_offset = Arm_exidx_input_section::invalid_offset; + else + output_offset = input_offset - deleted_bytes; + (*this->section_offset_map_)[input_offset] = output_offset; +} + +// Process EXIDX_INPUT_SECTION for EXIDX entry merging. Return the number of +// bytes deleted. If some entries are merged, also store a pointer to a newly +// created Arm_exidx_section_offset_map object in *PSECTION_OFFSET_MAP. The +// caller owns the map and is responsible for releasing it after use. + +template<bool big_endian> +uint32_t +Arm_exidx_fixup::process_exidx_section( + const Arm_exidx_input_section* exidx_input_section, + Arm_exidx_section_offset_map** psection_offset_map) +{ + Relobj* relobj = exidx_input_section->relobj(); + unsigned shndx = exidx_input_section->shndx(); + section_size_type section_size; + const unsigned char* section_contents = + relobj->section_contents(shndx, §ion_size, false); + + if ((section_size % 8) != 0) + { + // Something is wrong with this section. Better not touch it. + gold_error(_("uneven .ARM.exidx section size in %s section %u"), + relobj->name().c_str(), shndx); + this->last_input_section_ = exidx_input_section; + this->last_unwind_type_ = UT_NONE; + return 0; + } + + uint32_t deleted_bytes = 0; + bool prev_delete_entry = false; + gold_assert(this->section_offset_map_ == NULL); + + for (section_size_type i = 0; i < section_size; i += 8) + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + const Valtype* wv = + reinterpret_cast<const Valtype*>(section_contents + i + 4); + uint32_t second_word = elfcpp::Swap<32, big_endian>::readval(wv); + + bool delete_entry = this->process_exidx_entry(second_word); + + // Entry deletion causes changes in output offsets. We use a std::map + // to record these. And entry (x, y) means input offset x + // is mapped to output offset y. If y is invalid_offset, then x is + // dropped in the output. Because of the way std::map::lower_bound + // works, we record the last offset in a region w.r.t to keeping or + // dropping. If there is no entry (x0, y0) for an input offset x0, + // the output offset y0 of it is determined by the output offset y1 of + // the smallest input offset x1 > x0 that there is an (x1, y1) entry + // in the map. If y1 is not -1, then y0 = y1 + x0 - x1. Othewise, y1 + // y0 is also -1. + if (delete_entry != prev_delete_entry && i != 0) + this->update_offset_map(i - 1, deleted_bytes, prev_delete_entry); + + // Update total deleted bytes for this entry. + if (delete_entry) + deleted_bytes += 8; + + prev_delete_entry = delete_entry; + } + + // If section offset map is not NULL, make an entry for the end of + // section. + if (this->section_offset_map_ != NULL) + update_offset_map(section_size - 1, deleted_bytes, prev_delete_entry); + + *psection_offset_map = this->section_offset_map_; + this->section_offset_map_ = NULL; + this->last_input_section_ = exidx_input_section; + + // Set the first output text section so that we can link the EXIDX output + // section to it. Ignore any EXIDX input section that is completely merged. + if (this->first_output_text_section_ == NULL + && deleted_bytes != section_size) + { + unsigned int link = exidx_input_section->link(); + Output_section* os = relobj->output_section(link); + gold_assert(os != NULL); + this->first_output_text_section_ = os; + } + + return deleted_bytes; +} + +// Arm_output_section methods. + +// Create a stub group for input sections from BEGIN to END. OWNER +// points to the input section to be the owner a new stub table. + +template<bool big_endian> +void +Arm_output_section<big_endian>::create_stub_group( + Input_section_list::const_iterator begin, + Input_section_list::const_iterator end, + Input_section_list::const_iterator owner, + Target_arm<big_endian>* target, + std::vector<Output_relaxed_input_section*>* new_relaxed_sections) +{ + // We use a different kind of relaxed section in an EXIDX section. + // The static casting from Output_relaxed_input_section to + // Arm_input_section is invalid in an EXIDX section. We are okay + // because we should not be calling this for an EXIDX section. + gold_assert(this->type() != elfcpp::SHT_ARM_EXIDX); + + // Currently we convert ordinary input sections into relaxed sections only + // at this point but we may want to support creating relaxed input section + // very early. So we check here to see if owner is already a relaxed + // section. + + Arm_input_section<big_endian>* arm_input_section; + if (owner->is_relaxed_input_section()) + { + arm_input_section = + Arm_input_section<big_endian>::as_arm_input_section( + owner->relaxed_input_section()); + } + else + { + gold_assert(owner->is_input_section()); + // Create a new relaxed input section. + arm_input_section = + target->new_arm_input_section(owner->relobj(), owner->shndx()); + new_relaxed_sections->push_back(arm_input_section); + } + + // Create a stub table. + Stub_table<big_endian>* stub_table = + target->new_stub_table(arm_input_section); + + arm_input_section->set_stub_table(stub_table); + + Input_section_list::const_iterator p = begin; + Input_section_list::const_iterator prev_p; + + // Look for input sections or relaxed input sections in [begin ... end]. + do + { + if (p->is_input_section() || p->is_relaxed_input_section()) + { + // The stub table information for input sections live + // in their objects. + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(p->relobj()); + arm_relobj->set_stub_table(p->shndx(), stub_table); + } + prev_p = p++; + } + while (prev_p != end); +} + +// Group input sections for stub generation. GROUP_SIZE is roughly the limit +// of stub groups. We grow a stub group by adding input section until the +// size is just below GROUP_SIZE. The last input section will be converted +// into a stub table. If STUB_ALWAYS_AFTER_BRANCH is false, we also add +// input section after the stub table, effectively double the group size. +// +// This is similar to the group_sections() function in elf32-arm.c but is +// implemented differently. + +template<bool big_endian> +void +Arm_output_section<big_endian>::group_sections( + section_size_type group_size, + bool stubs_always_after_branch, + Target_arm<big_endian>* target) +{ + // We only care about sections containing code. + if ((this->flags() & elfcpp::SHF_EXECINSTR) == 0) + return; + + // States for grouping. + typedef enum + { + // No group is being built. + NO_GROUP, + // A group is being built but the stub table is not found yet. + // We keep group a stub group until the size is just under GROUP_SIZE. + // The last input section in the group will be used as the stub table. + FINDING_STUB_SECTION, + // A group is being built and we have already found a stub table. + // We enter this state to grow a stub group by adding input section + // after the stub table. This effectively doubles the group size. + HAS_STUB_SECTION + } State; + + // Any newly created relaxed sections are stored here. + std::vector<Output_relaxed_input_section*> new_relaxed_sections; + + State state = NO_GROUP; + section_size_type off = 0; + section_size_type group_begin_offset = 0; + section_size_type group_end_offset = 0; + section_size_type stub_table_end_offset = 0; + Input_section_list::const_iterator group_begin = + this->input_sections().end(); + Input_section_list::const_iterator stub_table = + this->input_sections().end(); + Input_section_list::const_iterator group_end = this->input_sections().end(); + for (Input_section_list::const_iterator p = this->input_sections().begin(); + p != this->input_sections().end(); + ++p) + { + section_size_type section_begin_offset = + align_address(off, p->addralign()); + section_size_type section_end_offset = + section_begin_offset + p->data_size(); + + // Check to see if we should group the previously seens sections. + switch (state) + { + case NO_GROUP: + break; + + case FINDING_STUB_SECTION: + // Adding this section makes the group larger than GROUP_SIZE. + if (section_end_offset - group_begin_offset >= group_size) + { + if (stubs_always_after_branch) + { + gold_assert(group_end != this->input_sections().end()); + this->create_stub_group(group_begin, group_end, group_end, + target, &new_relaxed_sections); + state = NO_GROUP; + } + else + { + // But wait, there's more! Input sections up to + // stub_group_size bytes after the stub table can be + // handled by it too. + state = HAS_STUB_SECTION; + stub_table = group_end; + stub_table_end_offset = group_end_offset; + } + } + break; + + case HAS_STUB_SECTION: + // Adding this section makes the post stub-section group larger + // than GROUP_SIZE. + if (section_end_offset - stub_table_end_offset >= group_size) + { + gold_assert(group_end != this->input_sections().end()); + this->create_stub_group(group_begin, group_end, stub_table, + target, &new_relaxed_sections); + state = NO_GROUP; + } + break; + + default: + gold_unreachable(); + } + + // If we see an input section and currently there is no group, start + // a new one. Skip any empty sections. + if ((p->is_input_section() || p->is_relaxed_input_section()) + && (p->relobj()->section_size(p->shndx()) != 0)) + { + if (state == NO_GROUP) + { + state = FINDING_STUB_SECTION; + group_begin = p; + group_begin_offset = section_begin_offset; + } + + // Keep track of the last input section seen. + group_end = p; + group_end_offset = section_end_offset; + } + + off = section_end_offset; + } + + // Create a stub group for any ungrouped sections. + if (state == FINDING_STUB_SECTION || state == HAS_STUB_SECTION) + { + gold_assert(group_end != this->input_sections().end()); + this->create_stub_group(group_begin, group_end, + (state == FINDING_STUB_SECTION + ? group_end + : stub_table), + target, &new_relaxed_sections); + } + + // Convert input section into relaxed input section in a batch. + if (!new_relaxed_sections.empty()) + this->convert_input_sections_to_relaxed_sections(new_relaxed_sections); + + // Update the section offsets + for (size_t i = 0; i < new_relaxed_sections.size(); ++i) + { + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj( + new_relaxed_sections[i]->relobj()); + unsigned int shndx = new_relaxed_sections[i]->shndx(); + // Tell Arm_relobj that this input section is converted. + arm_relobj->convert_input_section_to_relaxed_section(shndx); + } +} + +// Append non empty text sections in this to LIST in ascending +// order of their position in this. + +template<bool big_endian> +void +Arm_output_section<big_endian>::append_text_sections_to_list( + Text_section_list* list) +{ + // We only care about text sections. + if ((this->flags() & elfcpp::SHF_EXECINSTR) == 0) + return; + + gold_assert((this->flags() & elfcpp::SHF_ALLOC) != 0); + + for (Input_section_list::const_iterator p = this->input_sections().begin(); + p != this->input_sections().end(); + ++p) + { + // We only care about plain or relaxed input sections. We also + // ignore any merged sections. + if ((p->is_input_section() || p->is_relaxed_input_section()) + && p->data_size() != 0) + list->push_back(Text_section_list::value_type(p->relobj(), + p->shndx())); + } +} + +template<bool big_endian> +void +Arm_output_section<big_endian>::fix_exidx_coverage( + Layout* layout, + const Text_section_list& sorted_text_sections, + Symbol_table* symtab) +{ + // We should only do this for the EXIDX output section. + gold_assert(this->type() == elfcpp::SHT_ARM_EXIDX); + + // We don't want the relaxation loop to undo these changes, so we discard + // the current saved states and take another one after the fix-up. + this->discard_states(); + + // Remove all input sections. + uint64_t address = this->address(); + typedef std::list<Simple_input_section> Simple_input_section_list; + Simple_input_section_list input_sections; + this->reset_address_and_file_offset(); + this->get_input_sections(address, std::string(""), &input_sections); + + if (!this->input_sections().empty()) + gold_error(_("Found non-EXIDX input sections in EXIDX output section")); + + // Go through all the known input sections and record them. + typedef Unordered_set<Section_id, Section_id_hash> Section_id_set; + Section_id_set known_input_sections; + for (Simple_input_section_list::const_iterator p = input_sections.begin(); + p != input_sections.end(); + ++p) + { + // This should never happen. At this point, we should only see + // plain EXIDX input sections. + gold_assert(!p->is_relaxed_input_section()); + known_input_sections.insert(Section_id(p->relobj(), p->shndx())); + } + + Arm_exidx_fixup exidx_fixup(this); + + // Go over the sorted text sections. + Section_id_set processed_input_sections; + for (Text_section_list::const_iterator p = sorted_text_sections.begin(); + p != sorted_text_sections.end(); + ++p) + { + Relobj* relobj = p->first; + unsigned int shndx = p->second; + + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(relobj); + const Arm_exidx_input_section* exidx_input_section = + arm_relobj->exidx_input_section_by_link(shndx); + + // If this text section has no EXIDX section, force an EXIDX_CANTUNWIND + // entry pointing to the end of the last seen EXIDX section. + if (exidx_input_section == NULL) + { + exidx_fixup.add_exidx_cantunwind_as_needed(); + continue; + } + + Relobj* exidx_relobj = exidx_input_section->relobj(); + unsigned int exidx_shndx = exidx_input_section->shndx(); + Section_id sid(exidx_relobj, exidx_shndx); + if (known_input_sections.find(sid) == known_input_sections.end()) + { + // This is odd. We have not seen this EXIDX input section before. + // We cannot do fix-up. If we saw a SECTIONS clause in a script, + // issue a warning instead. We assume the user knows what he + // or she is doing. Otherwise, this is an error. + if (layout->script_options()->saw_sections_clause()) + gold_warning(_("unwinding may not work because EXIDX input section" + " %u of %s is not in EXIDX output section"), + exidx_shndx, exidx_relobj->name().c_str()); + else + gold_error(_("unwinding may not work because EXIDX input section" + " %u of %s is not in EXIDX output section"), + exidx_shndx, exidx_relobj->name().c_str()); + + exidx_fixup.add_exidx_cantunwind_as_needed(); + continue; + } + + // Fix up coverage and append input section to output data list. + Arm_exidx_section_offset_map* section_offset_map = NULL; + uint32_t deleted_bytes = + exidx_fixup.process_exidx_section<big_endian>(exidx_input_section, + §ion_offset_map); + + if (deleted_bytes == exidx_input_section->size()) + { + // The whole EXIDX section got merged. Remove it from output. + gold_assert(section_offset_map == NULL); + exidx_relobj->set_output_section(exidx_shndx, NULL); + + // All local symbols defined in this input section will be dropped. + // We need to adjust output local symbol count. + arm_relobj->set_output_local_symbol_count_needs_update(); + } + else if (deleted_bytes > 0) + { + // Some entries are merged. We need to convert this EXIDX input + // section into a relaxed section. + gold_assert(section_offset_map != NULL); + Arm_exidx_merged_section* merged_section = + new Arm_exidx_merged_section(*exidx_input_section, + *section_offset_map, deleted_bytes); + this->add_relaxed_input_section(merged_section); + arm_relobj->convert_input_section_to_relaxed_section(exidx_shndx); + + // All local symbols defined in discarded portions of this input + // section will be dropped. We need to adjust output local symbol + // count. + arm_relobj->set_output_local_symbol_count_needs_update(); + } + else + { + // Just add back the EXIDX input section. + gold_assert(section_offset_map == NULL); + Output_section::Simple_input_section sis(exidx_relobj, exidx_shndx); + this->add_simple_input_section(sis, exidx_input_section->size(), + exidx_input_section->addralign()); + } + + processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx)); + } + + // Insert an EXIDX_CANTUNWIND entry at the end of output if necessary. + exidx_fixup.add_exidx_cantunwind_as_needed(); + + // Remove any known EXIDX input sections that are not processed. + for (Simple_input_section_list::const_iterator p = input_sections.begin(); + p != input_sections.end(); + ++p) + { + if (processed_input_sections.find(Section_id(p->relobj(), p->shndx())) + == processed_input_sections.end()) + { + // We only discard a known EXIDX section because its linked + // text section has been folded by ICF. + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(p->relobj()); + const Arm_exidx_input_section* exidx_input_section = + arm_relobj->exidx_input_section_by_shndx(p->shndx()); + gold_assert(exidx_input_section != NULL); + unsigned int text_shndx = exidx_input_section->link(); + gold_assert(symtab->is_section_folded(p->relobj(), text_shndx)); + + // Remove this from link. + p->relobj()->set_output_section(p->shndx(), NULL); + } + } + + // Link exidx output section to the first seen output section and + // set correct entry size. + this->set_link_section(exidx_fixup.first_output_text_section()); + this->set_entsize(8); + + // Make changes permanent. + this->save_states(); + this->set_section_offsets_need_adjustment(); +} + +// Arm_relobj methods. + +// Determine if an input section is scannable for stub processing. SHDR is +// the header of the section and SHNDX is the section index. OS is the output +// section for the input section and SYMTAB is the global symbol table used to +// look up ICF information. + +template<bool big_endian> +bool +Arm_relobj<big_endian>::section_is_scannable( + const elfcpp::Shdr<32, big_endian>& shdr, + unsigned int shndx, + const Output_section* os, + const Symbol_table *symtab) +{ + // Skip any empty sections, unallocated sections or sections whose + // type are not SHT_PROGBITS. + if (shdr.get_sh_size() == 0 + || (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0 + || shdr.get_sh_type() != elfcpp::SHT_PROGBITS) + return false; + + // Skip any discarded or ICF'ed sections. + if (os == NULL || symtab->is_section_folded(this, shndx)) + return false; + + // If this requires special offset handling, check to see if it is + // a relaxed section. If this is not, then it is a merged section that + // we cannot handle. + if (this->is_output_section_offset_invalid(shndx)) + { + const Output_relaxed_input_section* poris = + os->find_relaxed_input_section(this, shndx); + if (poris == NULL) + return false; + } + + return true; +} + +// Determine if we want to scan the SHNDX-th section for relocation stubs. +// This is a helper for Arm_relobj::scan_sections_for_stubs() below. + +template<bool big_endian> +bool +Arm_relobj<big_endian>::section_needs_reloc_stub_scanning( + const elfcpp::Shdr<32, big_endian>& shdr, + const Relobj::Output_sections& out_sections, + const Symbol_table *symtab, + const unsigned char* pshdrs) +{ + unsigned int sh_type = shdr.get_sh_type(); + if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA) + return false; + + // Ignore empty section. + off_t sh_size = shdr.get_sh_size(); + if (sh_size == 0) + return false; + + // Ignore reloc section with unexpected symbol table. The + // error will be reported in the final link. + if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx()) + return false; + + unsigned int reloc_size; + if (sh_type == elfcpp::SHT_REL) + reloc_size = elfcpp::Elf_sizes<32>::rel_size; + else + reloc_size = elfcpp::Elf_sizes<32>::rela_size; + + // Ignore reloc section with unexpected entsize or uneven size. + // The error will be reported in the final link. + if (reloc_size != shdr.get_sh_entsize() || sh_size % reloc_size != 0) + return false; + + // Ignore reloc section with bad info. This error will be + // reported in the final link. + unsigned int index = this->adjust_shndx(shdr.get_sh_info()); + if (index >= this->shnum()) + return false; + + const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + const elfcpp::Shdr<32, big_endian> text_shdr(pshdrs + index * shdr_size); + return this->section_is_scannable(text_shdr, index, + out_sections[index], symtab); +} + +// Return the output address of either a plain input section or a relaxed +// input section. SHNDX is the section index. We define and use this +// instead of calling Output_section::output_address because that is slow +// for large output. + +template<bool big_endian> +Arm_address +Arm_relobj<big_endian>::simple_input_section_output_address( + unsigned int shndx, + Output_section* os) +{ + if (this->is_output_section_offset_invalid(shndx)) + { + const Output_relaxed_input_section* poris = + os->find_relaxed_input_section(this, shndx); + // We do not handle merged sections here. + gold_assert(poris != NULL); + return poris->address(); + } + else + return os->address() + this->get_output_section_offset(shndx); +} + +// Determine if we want to scan the SHNDX-th section for non-relocation stubs. +// This is a helper for Arm_relobj::scan_sections_for_stubs() below. + +template<bool big_endian> +bool +Arm_relobj<big_endian>::section_needs_cortex_a8_stub_scanning( + const elfcpp::Shdr<32, big_endian>& shdr, + unsigned int shndx, + Output_section* os, + const Symbol_table* symtab) +{ + if (!this->section_is_scannable(shdr, shndx, os, symtab)) + return false; + + // If the section does not cross any 4K-boundaries, it does not need to + // be scanned. + Arm_address address = this->simple_input_section_output_address(shndx, os); + if ((address & ~0xfffU) == ((address + shdr.get_sh_size() - 1) & ~0xfffU)) + return false; + + return true; +} + +// Scan a section for Cortex-A8 workaround. + +template<bool big_endian> +void +Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum( + const elfcpp::Shdr<32, big_endian>& shdr, + unsigned int shndx, + Output_section* os, + Target_arm<big_endian>* arm_target) +{ + // Look for the first mapping symbol in this section. It should be + // at (shndx, 0). + Mapping_symbol_position section_start(shndx, 0); + typename Mapping_symbols_info::const_iterator p = + this->mapping_symbols_info_.lower_bound(section_start); + + // There are no mapping symbols for this section. Treat it as a data-only + // section. Issue a warning if section is marked as containing + // instructions. + if (p == this->mapping_symbols_info_.end() || p->first.first != shndx) + { + if ((this->section_flags(shndx) & elfcpp::SHF_EXECINSTR) != 0) + gold_warning(_("cannot scan executable section %u of %s for Cortex-A8 " + "erratum because it has no mapping symbols."), + shndx, this->name().c_str()); + return; + } + + Arm_address output_address = + this->simple_input_section_output_address(shndx, os); + + // Get the section contents. + section_size_type input_view_size = 0; + const unsigned char* input_view = + this->section_contents(shndx, &input_view_size, false); + + // We need to go through the mapping symbols to determine what to + // scan. There are two reasons. First, we should look at THUMB code and + // THUMB code only. Second, we only want to look at the 4K-page boundary + // to speed up the scanning. + + while (p != this->mapping_symbols_info_.end() + && p->first.first == shndx) + { + typename Mapping_symbols_info::const_iterator next = + this->mapping_symbols_info_.upper_bound(p->first); + + // Only scan part of a section with THUMB code. + if (p->second == 't') + { + // Determine the end of this range. + section_size_type span_start = + convert_to_section_size_type(p->first.second); + section_size_type span_end; + if (next != this->mapping_symbols_info_.end() + && next->first.first == shndx) + span_end = convert_to_section_size_type(next->first.second); + else + span_end = convert_to_section_size_type(shdr.get_sh_size()); + + if (((span_start + output_address) & ~0xfffUL) + != ((span_end + output_address - 1) & ~0xfffUL)) + { + arm_target->scan_span_for_cortex_a8_erratum(this, shndx, + span_start, span_end, + input_view, + output_address); + } + } + + p = next; + } +} + +// Scan relocations for stub generation. + +template<bool big_endian> +void +Arm_relobj<big_endian>::scan_sections_for_stubs( + Target_arm<big_endian>* arm_target, + const Symbol_table* symtab, + const Layout* layout) +{ + unsigned int shnum = this->shnum(); + const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + + // Read the section headers. + const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(), + shnum * shdr_size, + true, true); + + // To speed up processing, we set up hash tables for fast lookup of + // input offsets to output addresses. + this->initialize_input_to_output_maps(); + + const Relobj::Output_sections& out_sections(this->output_sections()); + + Relocate_info<32, big_endian> relinfo; + relinfo.symtab = symtab; + relinfo.layout = layout; + relinfo.object = this; + + // Do relocation stubs scanning. + const unsigned char* p = pshdrs + shdr_size; + for (unsigned int i = 1; i < shnum; ++i, p += shdr_size) + { + const elfcpp::Shdr<32, big_endian> shdr(p); + if (this->section_needs_reloc_stub_scanning(shdr, out_sections, symtab, + pshdrs)) + { + unsigned int index = this->adjust_shndx(shdr.get_sh_info()); + Arm_address output_offset = this->get_output_section_offset(index); + Arm_address output_address; + if (output_offset != invalid_address) + output_address = out_sections[index]->address() + output_offset; + else + { + // Currently this only happens for a relaxed section. + const Output_relaxed_input_section* poris = + out_sections[index]->find_relaxed_input_section(this, index); + gold_assert(poris != NULL); + output_address = poris->address(); + } + + // Get the relocations. + const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(), + shdr.get_sh_size(), + true, false); + + // Get the section contents. This does work for the case in which + // we modify the contents of an input section. We need to pass the + // output view under such circumstances. + section_size_type input_view_size = 0; + const unsigned char* input_view = + this->section_contents(index, &input_view_size, false); + + relinfo.reloc_shndx = i; + relinfo.data_shndx = index; + unsigned int sh_type = shdr.get_sh_type(); + unsigned int reloc_size; + if (sh_type == elfcpp::SHT_REL) + reloc_size = elfcpp::Elf_sizes<32>::rel_size; + else + reloc_size = elfcpp::Elf_sizes<32>::rela_size; + + Output_section* os = out_sections[index]; + arm_target->scan_section_for_stubs(&relinfo, sh_type, prelocs, + shdr.get_sh_size() / reloc_size, + os, + output_offset == invalid_address, + input_view, output_address, + input_view_size); + } + } + + // Do Cortex-A8 erratum stubs scanning. This has to be done for a section + // after its relocation section, if there is one, is processed for + // relocation stubs. Merging this loop with the one above would have been + // complicated since we would have had to make sure that relocation stub + // scanning is done first. + if (arm_target->fix_cortex_a8()) + { + const unsigned char* p = pshdrs + shdr_size; + for (unsigned int i = 1; i < shnum; ++i, p += shdr_size) + { + const elfcpp::Shdr<32, big_endian> shdr(p); + if (this->section_needs_cortex_a8_stub_scanning(shdr, i, + out_sections[i], + symtab)) + this->scan_section_for_cortex_a8_erratum(shdr, i, out_sections[i], + arm_target); + } + } + + // After we've done the relocations, we release the hash tables, + // since we no longer need them. + this->free_input_to_output_maps(); +} + +// Count the local symbols. The ARM backend needs to know if a symbol +// is a THUMB function or not. For global symbols, it is easy because +// the Symbol object keeps the ELF symbol type. For local symbol it is +// harder because we cannot access this information. So we override the +// do_count_local_symbol in parent and scan local symbols to mark +// THUMB functions. This is not the most efficient way but I do not want to +// slow down other ports by calling a per symbol targer hook inside +// Sized_relobj<size, big_endian>::do_count_local_symbols. + +template<bool big_endian> +void +Arm_relobj<big_endian>::do_count_local_symbols( + Stringpool_template<char>* pool, + Stringpool_template<char>* dynpool) +{ + // We need to fix-up the values of any local symbols whose type are + // STT_ARM_TFUNC. + + // Ask parent to count the local symbols. + Sized_relobj<32, big_endian>::do_count_local_symbols(pool, dynpool); + const unsigned int loccount = this->local_symbol_count(); + if (loccount == 0) + return; + + // Intialize the thumb function bit-vector. + std::vector<bool> empty_vector(loccount, false); + this->local_symbol_is_thumb_function_.swap(empty_vector); + + // Read the symbol table section header. + const unsigned int symtab_shndx = this->symtab_shndx(); + elfcpp::Shdr<32, big_endian> + symtabshdr(this, this->elf_file()->section_header(symtab_shndx)); + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); + + // Read the local symbols. + const int sym_size =elfcpp::Elf_sizes<32>::sym_size; + gold_assert(loccount == symtabshdr.get_sh_info()); + off_t locsize = loccount * sym_size; + const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), + locsize, true, true); + + // For mapping symbol processing, we need to read the symbol names. + unsigned int strtab_shndx = this->adjust_shndx(symtabshdr.get_sh_link()); + if (strtab_shndx >= this->shnum()) + { + this->error(_("invalid symbol table name index: %u"), strtab_shndx); + return; + } + + elfcpp::Shdr<32, big_endian> + strtabshdr(this, this->elf_file()->section_header(strtab_shndx)); + if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB) + { + this->error(_("symbol table name section has wrong type: %u"), + static_cast<unsigned int>(strtabshdr.get_sh_type())); + return; + } + const char* pnames = + reinterpret_cast<const char*>(this->get_view(strtabshdr.get_sh_offset(), + strtabshdr.get_sh_size(), + false, false)); + + // Loop over the local symbols and mark any local symbols pointing + // to THUMB functions. + + // Skip the first dummy symbol. + psyms += sym_size; + typename Sized_relobj<32, big_endian>::Local_values* plocal_values = + this->local_values(); + for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) + { + elfcpp::Sym<32, big_endian> sym(psyms); + elfcpp::STT st_type = sym.get_st_type(); + Symbol_value<32>& lv((*plocal_values)[i]); + Arm_address input_value = lv.input_value(); + + // Check to see if this is a mapping symbol. + const char* sym_name = pnames + sym.get_st_name(); + if (Target_arm<big_endian>::is_mapping_symbol_name(sym_name)) + { + bool is_ordinary; + unsigned int input_shndx = + this->adjust_sym_shndx(i, sym.get_st_shndx(), &is_ordinary); + gold_assert(is_ordinary); + + // Strip of LSB in case this is a THUMB symbol. + Mapping_symbol_position msp(input_shndx, input_value & ~1U); + this->mapping_symbols_info_[msp] = sym_name[1]; + } + + if (st_type == elfcpp::STT_ARM_TFUNC + || (st_type == elfcpp::STT_FUNC && ((input_value & 1) != 0))) + { + // This is a THUMB function. Mark this and canonicalize the + // symbol value by setting LSB. + this->local_symbol_is_thumb_function_[i] = true; + if ((input_value & 1) == 0) + lv.set_input_value(input_value | 1); + } + } +} + +// Relocate sections. +template<bool big_endian> +void +Arm_relobj<big_endian>::do_relocate_sections( + const Symbol_table* symtab, + const Layout* layout, + const unsigned char* pshdrs, + typename Sized_relobj<32, big_endian>::Views* pviews) +{ + // Call parent to relocate sections. + Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs, + pviews); + + // We do not generate stubs if doing a relocatable link. + if (parameters->options().relocatable()) + return; + + // Relocate stub tables. + unsigned int shnum = this->shnum(); + + Target_arm<big_endian>* arm_target = + Target_arm<big_endian>::default_target(); + + Relocate_info<32, big_endian> relinfo; + relinfo.symtab = symtab; + relinfo.layout = layout; + relinfo.object = this; + + for (unsigned int i = 1; i < shnum; ++i) + { + Arm_input_section<big_endian>* arm_input_section = + arm_target->find_arm_input_section(this, i); + + if (arm_input_section != NULL + && arm_input_section->is_stub_table_owner() + && !arm_input_section->stub_table()->empty()) + { + // We cannot discard a section if it owns a stub table. + Output_section* os = this->output_section(i); + gold_assert(os != NULL); + + relinfo.reloc_shndx = elfcpp::SHN_UNDEF; + relinfo.reloc_shdr = NULL; + relinfo.data_shndx = i; + relinfo.data_shdr = pshdrs + i * elfcpp::Elf_sizes<32>::shdr_size; + + gold_assert((*pviews)[i].view != NULL); + + // We are passed the output section view. Adjust it to cover the + // stub table only. + Stub_table<big_endian>* stub_table = arm_input_section->stub_table(); + gold_assert((stub_table->address() >= (*pviews)[i].address) + && ((stub_table->address() + stub_table->data_size()) + <= (*pviews)[i].address + (*pviews)[i].view_size)); + + off_t offset = stub_table->address() - (*pviews)[i].address; + unsigned char* view = (*pviews)[i].view + offset; + Arm_address address = stub_table->address(); + section_size_type view_size = stub_table->data_size(); + + stub_table->relocate_stubs(&relinfo, arm_target, os, view, address, + view_size); + } + + // Apply Cortex A8 workaround if applicable. + if (this->section_has_cortex_a8_workaround(i)) + { + unsigned char* view = (*pviews)[i].view; + Arm_address view_address = (*pviews)[i].address; + section_size_type view_size = (*pviews)[i].view_size; + Stub_table<big_endian>* stub_table = this->stub_tables_[i]; + + // Adjust view to cover section. + Output_section* os = this->output_section(i); + gold_assert(os != NULL); + Arm_address section_address = + this->simple_input_section_output_address(i, os); + uint64_t section_size = this->section_size(i); + + gold_assert(section_address >= view_address + && ((section_address + section_size) + <= (view_address + view_size))); + + unsigned char* section_view = view + (section_address - view_address); + + // Apply the Cortex-A8 workaround to the output address range + // corresponding to this input section. + stub_table->apply_cortex_a8_workaround_to_address_range( + arm_target, + section_view, + section_address, + section_size); + } + } +} + +// Find the linked text section of an EXIDX section by looking the the first +// relocation. 4.4.1 of the EHABI specifications says that an EXIDX section +// must be linked to to its associated code section via the sh_link field of +// its section header. However, some tools are broken and the link is not +// always set. LD just drops such an EXIDX section silently, causing the +// associated code not unwindabled. Here we try a little bit harder to +// discover the linked code section. +// +// PSHDR points to the section header of a relocation section of an EXIDX +// section. If we can find a linked text section, return true and +// store the text section index in the location PSHNDX. Otherwise +// return false. + +template<bool big_endian> +bool +Arm_relobj<big_endian>::find_linked_text_section( + const unsigned char* pshdr, + const unsigned char* psyms, + unsigned int* pshndx) +{ + elfcpp::Shdr<32, big_endian> shdr(pshdr); + + // If there is no relocation, we cannot find the linked text section. + size_t reloc_size; + if (shdr.get_sh_type() == elfcpp::SHT_REL) + reloc_size = elfcpp::Elf_sizes<32>::rel_size; + else + reloc_size = elfcpp::Elf_sizes<32>::rela_size; + size_t reloc_count = shdr.get_sh_size() / reloc_size; + + // Get the relocations. + const unsigned char* prelocs = + this->get_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false); + + // Find the REL31 relocation for the first word of the first EXIDX entry. + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) + { + Arm_address r_offset; + typename elfcpp::Elf_types<32>::Elf_WXword r_info; + if (shdr.get_sh_type() == elfcpp::SHT_REL) + { + typename elfcpp::Rel<32, big_endian> reloc(prelocs); + r_info = reloc.get_r_info(); + r_offset = reloc.get_r_offset(); + } + else + { + typename elfcpp::Rela<32, big_endian> reloc(prelocs); + r_info = reloc.get_r_info(); + r_offset = reloc.get_r_offset(); + } + + unsigned int r_type = elfcpp::elf_r_type<32>(r_info); + if (r_type != elfcpp::R_ARM_PREL31 && r_type != elfcpp::R_ARM_SBREL31) + continue; + + unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info); + if (r_sym == 0 + || r_sym >= this->local_symbol_count() + || r_offset != 0) + continue; + + // This is the relocation for the first word of the first EXIDX entry. + // We expect to see a local section symbol. + const int sym_size = elfcpp::Elf_sizes<32>::sym_size; + elfcpp::Sym<32, big_endian> sym(psyms + r_sym * sym_size); + if (sym.get_st_type() == elfcpp::STT_SECTION) + { + bool is_ordinary; + *pshndx = + this->adjust_sym_shndx(r_sym, sym.get_st_shndx(), &is_ordinary); + gold_assert(is_ordinary); + return true; + } + else + return false; + } + + return false; +} + +// Make an EXIDX input section object for an EXIDX section whose index is +// SHNDX. SHDR is the section header of the EXIDX section and TEXT_SHNDX +// is the section index of the linked text section. + +template<bool big_endian> +void +Arm_relobj<big_endian>::make_exidx_input_section( + unsigned int shndx, + const elfcpp::Shdr<32, big_endian>& shdr, + unsigned int text_shndx) +{ + // Issue an error and ignore this EXIDX section if it points to a text + // section already has an EXIDX section. + if (this->exidx_section_map_[text_shndx] != NULL) + { + gold_error(_("EXIDX sections %u and %u both link to text section %u " + "in %s"), + shndx, this->exidx_section_map_[text_shndx]->shndx(), + text_shndx, this->name().c_str()); + return; + } + + // Create an Arm_exidx_input_section object for this EXIDX section. + Arm_exidx_input_section* exidx_input_section = + new Arm_exidx_input_section(this, shndx, text_shndx, shdr.get_sh_size(), + shdr.get_sh_addralign()); + this->exidx_section_map_[text_shndx] = exidx_input_section; + + // Also map the EXIDX section index to this. + gold_assert(this->exidx_section_map_[shndx] == NULL); + this->exidx_section_map_[shndx] = exidx_input_section; +} + +// Read the symbol information. + +template<bool big_endian> +void +Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd) +{ + // Call parent class to read symbol information. + Sized_relobj<32, big_endian>::do_read_symbols(sd); + + // If this input file is a binary file, it has no processor + // specific flags and attributes section. + Input_file::Format format = this->input_file()->format(); + if (format != Input_file::FORMAT_ELF) + { + gold_assert(format == Input_file::FORMAT_BINARY); + this->merge_flags_and_attributes_ = false; + return; + } + + // Read processor-specific flags in ELF file header. + const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, + elfcpp::Elf_sizes<32>::ehdr_size, + true, false); + elfcpp::Ehdr<32, big_endian> ehdr(pehdr); + this->processor_specific_flags_ = ehdr.get_e_flags(); + + // Go over the section headers and look for .ARM.attributes and .ARM.exidx + // sections. + std::vector<unsigned int> deferred_exidx_sections; + const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + const unsigned char* pshdrs = sd->section_headers->data(); + const unsigned char *ps = pshdrs + shdr_size; + bool must_merge_flags_and_attributes = false; + for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size) + { + elfcpp::Shdr<32, big_endian> shdr(ps); + + // Sometimes an object has no contents except the section name string + // table and an empty symbol table with the undefined symbol. We + // don't want to merge processor-specific flags from such an object. + if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB) + { + // Symbol table is not empty. + const elfcpp::Elf_types<32>::Elf_WXword sym_size = + elfcpp::Elf_sizes<32>::sym_size; + if (shdr.get_sh_size() > sym_size) + must_merge_flags_and_attributes = true; + } + else if (shdr.get_sh_type() != elfcpp::SHT_STRTAB) + // If this is neither an empty symbol table nor a string table, + // be conservative. + must_merge_flags_and_attributes = true; + + if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES) + { + gold_assert(this->attributes_section_data_ == NULL); + section_offset_type section_offset = shdr.get_sh_offset(); + section_size_type section_size = + convert_to_section_size_type(shdr.get_sh_size()); + File_view* view = this->get_lasting_view(section_offset, + section_size, true, false); + this->attributes_section_data_ = + new Attributes_section_data(view->data(), section_size); + } + else if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX) + { + unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link()); + if (text_shndx >= this->shnum()) + gold_error(_("EXIDX section %u linked to invalid section %u"), + i, text_shndx); + else if (text_shndx == elfcpp::SHN_UNDEF) + deferred_exidx_sections.push_back(i); + else + this->make_exidx_input_section(i, shdr, text_shndx); + } + } + + // This is rare. + if (!must_merge_flags_and_attributes) + { + this->merge_flags_and_attributes_ = false; + return; + } + + // Some tools are broken and they do not set the link of EXIDX sections. + // We look at the first relocation to figure out the linked sections. + if (!deferred_exidx_sections.empty()) + { + // We need to go over the section headers again to find the mapping + // from sections being relocated to their relocation sections. This is + // a bit inefficient as we could do that in the loop above. However, + // we do not expect any deferred EXIDX sections normally. So we do not + // want to slow down the most common path. + typedef Unordered_map<unsigned int, unsigned int> Reloc_map; + Reloc_map reloc_map; + ps = pshdrs + shdr_size; + for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size) + { + elfcpp::Shdr<32, big_endian> shdr(ps); + elfcpp::Elf_Word sh_type = shdr.get_sh_type(); + if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA) + { + unsigned int info_shndx = this->adjust_shndx(shdr.get_sh_info()); + if (info_shndx >= this->shnum()) + gold_error(_("relocation section %u has invalid info %u"), + i, info_shndx); + Reloc_map::value_type value(info_shndx, i); + std::pair<Reloc_map::iterator, bool> result = + reloc_map.insert(value); + if (!result.second) + gold_error(_("section %u has multiple relocation sections " + "%u and %u"), + info_shndx, i, reloc_map[info_shndx]); + } + } + + // Read the symbol table section header. + const unsigned int symtab_shndx = this->symtab_shndx(); + elfcpp::Shdr<32, big_endian> + symtabshdr(this, this->elf_file()->section_header(symtab_shndx)); + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); + + // Read the local symbols. + const int sym_size =elfcpp::Elf_sizes<32>::sym_size; + const unsigned int loccount = this->local_symbol_count(); + gold_assert(loccount == symtabshdr.get_sh_info()); + off_t locsize = loccount * sym_size; + const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), + locsize, true, true); + + // Process the deferred EXIDX sections. + for(unsigned int i = 0; i < deferred_exidx_sections.size(); ++i) + { + unsigned int shndx = deferred_exidx_sections[i]; + elfcpp::Shdr<32, big_endian> shdr(pshdrs + shndx * shdr_size); + unsigned int text_shndx; + Reloc_map::const_iterator it = reloc_map.find(shndx); + if (it != reloc_map.end() + && find_linked_text_section(pshdrs + it->second * shdr_size, + psyms, &text_shndx)) + this->make_exidx_input_section(shndx, shdr, text_shndx); + else + gold_error(_("EXIDX section %u has no linked text section."), + shndx); + } + } +} + +// Process relocations for garbage collection. The ARM target uses .ARM.exidx +// sections for unwinding. These sections are referenced implicitly by +// text sections linked in the section headers. If we ignore these implict +// references, the .ARM.exidx sections and any .ARM.extab sections they use +// will be garbage-collected incorrectly. Hence we override the same function +// in the base class to handle these implicit references. + +template<bool big_endian> +void +Arm_relobj<big_endian>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd) +{ + // First, call base class method to process relocations in this object. + Sized_relobj<32, big_endian>::do_gc_process_relocs(symtab, layout, rd); + + // If --gc-sections is not specified, there is nothing more to do. + // This happens when --icf is used but --gc-sections is not. + if (!parameters->options().gc_sections()) + return; + + unsigned int shnum = this->shnum(); + const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(), + shnum * shdr_size, + true, true); + + // Scan section headers for sections of type SHT_ARM_EXIDX. Add references + // to these from the linked text sections. + const unsigned char* ps = pshdrs + shdr_size; + for (unsigned int i = 1; i < shnum; ++i, ps += shdr_size) + { + elfcpp::Shdr<32, big_endian> shdr(ps); + if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX) + { + // Found an .ARM.exidx section, add it to the set of reachable + // sections from its linked text section. + unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link()); + symtab->gc()->add_reference(this, text_shndx, this, i); + } + } +} + +// Update output local symbol count. Owing to EXIDX entry merging, some local +// symbols will be removed in output. Adjust output local symbol count +// accordingly. We can only changed the static output local symbol count. It +// is too late to change the dynamic symbols. + +template<bool big_endian> +void +Arm_relobj<big_endian>::update_output_local_symbol_count() +{ + // Caller should check that this needs updating. We want caller checking + // because output_local_symbol_count_needs_update() is most likely inlined. + gold_assert(this->output_local_symbol_count_needs_update_); + + gold_assert(this->symtab_shndx() != -1U); + if (this->symtab_shndx() == 0) + { + // This object has no symbols. Weird but legal. + return; + } + + // Read the symbol table section header. + const unsigned int symtab_shndx = this->symtab_shndx(); + elfcpp::Shdr<32, big_endian> + symtabshdr(this, this->elf_file()->section_header(symtab_shndx)); + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); + + // Read the local symbols. + const int sym_size = elfcpp::Elf_sizes<32>::sym_size; + const unsigned int loccount = this->local_symbol_count(); + gold_assert(loccount == symtabshdr.get_sh_info()); + off_t locsize = loccount * sym_size; + const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), + locsize, true, true); + + // Loop over the local symbols. + + typedef typename Sized_relobj<32, big_endian>::Output_sections + Output_sections; + const Output_sections& out_sections(this->output_sections()); + unsigned int shnum = this->shnum(); + unsigned int count = 0; + // Skip the first, dummy, symbol. + psyms += sym_size; + for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) + { + elfcpp::Sym<32, big_endian> sym(psyms); + + Symbol_value<32>& lv((*this->local_values())[i]); + + // This local symbol was already discarded by do_count_local_symbols. + if (lv.is_output_symtab_index_set() && !lv.has_output_symtab_entry()) + continue; + + bool is_ordinary; + unsigned int shndx = this->adjust_sym_shndx(i, sym.get_st_shndx(), + &is_ordinary); + + if (shndx < shnum) + { + Output_section* os = out_sections[shndx]; + + // This local symbol no longer has an output section. Discard it. + if (os == NULL) + { + lv.set_no_output_symtab_entry(); + continue; + } + + // Currently we only discard parts of EXIDX input sections. + // We explicitly check for a merged EXIDX input section to avoid + // calling Output_section_data::output_offset unless necessary. + if ((this->get_output_section_offset(shndx) == invalid_address) + && (this->exidx_input_section_by_shndx(shndx) != NULL)) + { + section_offset_type output_offset = + os->output_offset(this, shndx, lv.input_value()); + if (output_offset == -1) + { + // This symbol is defined in a part of an EXIDX input section + // that is discarded due to entry merging. + lv.set_no_output_symtab_entry(); + continue; + } + } + } + + ++count; + } + + this->set_output_local_symbol_count(count); + this->output_local_symbol_count_needs_update_ = false; +} + +// Arm_dynobj methods. + +// Read the symbol information. + +template<bool big_endian> +void +Arm_dynobj<big_endian>::do_read_symbols(Read_symbols_data* sd) +{ + // Call parent class to read symbol information. + Sized_dynobj<32, big_endian>::do_read_symbols(sd); + + // Read processor-specific flags in ELF file header. + const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, + elfcpp::Elf_sizes<32>::ehdr_size, + true, false); + elfcpp::Ehdr<32, big_endian> ehdr(pehdr); + this->processor_specific_flags_ = ehdr.get_e_flags(); + + // Read the attributes section if there is one. + // We read from the end because gas seems to put it near the end of + // the section headers. + const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + const unsigned char *ps = + sd->section_headers->data() + shdr_size * (this->shnum() - 1); + for (unsigned int i = this->shnum(); i > 0; --i, ps -= shdr_size) + { + elfcpp::Shdr<32, big_endian> shdr(ps); + if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES) + { + section_offset_type section_offset = shdr.get_sh_offset(); + section_size_type section_size = + convert_to_section_size_type(shdr.get_sh_size()); + File_view* view = this->get_lasting_view(section_offset, + section_size, true, false); + this->attributes_section_data_ = + new Attributes_section_data(view->data(), section_size); + break; + } + } +} + +// Stub_addend_reader methods. + +// Read the addend of a REL relocation of type R_TYPE at VIEW. + +template<bool big_endian> +elfcpp::Elf_types<32>::Elf_Swxword +Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()( + unsigned int r_type, + const unsigned char* view, + const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const +{ + typedef struct Arm_relocate_functions<big_endian> RelocFuncs; + + switch (r_type) + { + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_PLT32: + { + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype val = elfcpp::Swap<32, big_endian>::readval(wv); + return utils::sign_extend<26>(val << 2); + } + + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_THM_XPC22: + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + return RelocFuncs::thumb32_branch_offset(upper_insn, lower_insn); + } + + case elfcpp::R_ARM_THM_JUMP19: + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view); + Valtype upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + return RelocFuncs::thumb32_cond_branch_offset(upper_insn, lower_insn); + } + + default: + gold_unreachable(); + } +} + +// Arm_output_data_got methods. + +// Add a GOT pair for R_ARM_TLS_GD32. The creates a pair of GOT entries. +// The first one is initialized to be 1, which is the module index for +// the main executable and the second one 0. A reloc of the type +// R_ARM_TLS_DTPOFF32 will be created for the second GOT entry and will +// be applied by gold. GSYM is a global symbol. +// +template<bool big_endian> +void +Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc( + unsigned int got_type, + Symbol* gsym) +{ + if (gsym->has_got_offset(got_type)) + return; + + // We are doing a static link. Just mark it as belong to module 1, + // the executable. + unsigned int got_offset = this->add_constant(1); + gsym->set_got_offset(got_type, got_offset); + got_offset = this->add_constant(0); + this->static_relocs_.push_back(Static_reloc(got_offset, + elfcpp::R_ARM_TLS_DTPOFF32, + gsym)); +} + +// Same as the above but for a local symbol. + +template<bool big_endian> +void +Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc( + unsigned int got_type, + Sized_relobj<32, big_endian>* object, + unsigned int index) +{ + if (object->local_has_got_offset(index, got_type)) + return; + + // We are doing a static link. Just mark it as belong to module 1, + // the executable. + unsigned int got_offset = this->add_constant(1); + object->set_local_got_offset(index, got_type, got_offset); + got_offset = this->add_constant(0); + this->static_relocs_.push_back(Static_reloc(got_offset, + elfcpp::R_ARM_TLS_DTPOFF32, + object, index)); +} + +template<bool big_endian> +void +Arm_output_data_got<big_endian>::do_write(Output_file* of) +{ + // Call parent to write out GOT. + Output_data_got<32, big_endian>::do_write(of); + + // We are done if there is no fix up. + if (this->static_relocs_.empty()) + return; + + gold_assert(parameters->doing_static_link()); + + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + Output_segment* tls_segment = this->layout_->tls_segment(); + gold_assert(tls_segment != NULL); + + // The thread pointer $tp points to the TCB, which is followed by the + // TLS. So we need to adjust $tp relative addressing by this amount. + Arm_address aligned_tcb_size = + align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment()); + + for (size_t i = 0; i < this->static_relocs_.size(); ++i) + { + Static_reloc& reloc(this->static_relocs_[i]); + + Arm_address value; + if (!reloc.symbol_is_global()) + { + Sized_relobj<32, big_endian>* object = reloc.relobj(); + const Symbol_value<32>* psymval = + reloc.relobj()->local_symbol(reloc.index()); + + // We are doing static linking. Issue an error and skip this + // relocation if the symbol is undefined or in a discarded_section. + bool is_ordinary; + unsigned int shndx = psymval->input_shndx(&is_ordinary); + if ((shndx == elfcpp::SHN_UNDEF) + || (is_ordinary + && shndx != elfcpp::SHN_UNDEF + && !object->is_section_included(shndx) + && !this->symbol_table_->is_section_folded(object, shndx))) + { + gold_error(_("undefined or discarded local symbol %u from " + " object %s in GOT"), + reloc.index(), reloc.relobj()->name().c_str()); + continue; + } + + value = psymval->value(object, 0); + } + else + { + const Symbol* gsym = reloc.symbol(); + gold_assert(gsym != NULL); + if (gsym->is_forwarder()) + gsym = this->symbol_table_->resolve_forwards(gsym); + + // We are doing static linking. Issue an error and skip this + // relocation if the symbol is undefined or in a discarded_section + // unless it is a weakly_undefined symbol. + if ((gsym->is_defined_in_discarded_section() + || gsym->is_undefined()) + && !gsym->is_weak_undefined()) + { + gold_error(_("undefined or discarded symbol %s in GOT"), + gsym->name()); + continue; + } + + if (!gsym->is_weak_undefined()) + { + const Sized_symbol<32>* sym = + static_cast<const Sized_symbol<32>*>(gsym); + value = sym->value(); + } + else + value = 0; + } + + unsigned got_offset = reloc.got_offset(); + gold_assert(got_offset < oview_size); + + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(oview + got_offset); + Valtype x; + switch (reloc.r_type()) + { + case elfcpp::R_ARM_TLS_DTPOFF32: + x = value; + break; + case elfcpp::R_ARM_TLS_TPOFF32: + x = value + aligned_tcb_size; + break; + default: + gold_unreachable(); + } + elfcpp::Swap<32, big_endian>::writeval(wv, x); + } + + of->write_output_view(offset, oview_size, oview); +} + +// A class to handle the PLT data. + +template<bool big_endian> +class Output_data_plt_arm : public Output_section_data +{ + public: + typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian> + Reloc_section; + + Output_data_plt_arm(Layout*, Output_data_space*); + + // Add an entry to the PLT. + void + add_entry(Symbol* gsym); + + // Return the .rel.plt section data. + const Reloc_section* + rel_plt() const + { return this->rel_; } + + protected: + void + do_adjust_output_section(Output_section* os); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, _("** PLT")); } + + private: + // Template for the first PLT entry. + static const uint32_t first_plt_entry[5]; + + // Template for subsequent PLT entries. + static const uint32_t plt_entry[3]; + + // Set the final size. + void + set_final_data_size() + { + this->set_data_size(sizeof(first_plt_entry) + + this->count_ * sizeof(plt_entry)); + } + + // Write out the PLT data. + void + do_write(Output_file*); + + // The reloc section. + Reloc_section* rel_; + // The .got.plt section. + Output_data_space* got_plt_; + // The number of PLT entries. + unsigned int count_; +}; + +// Create the PLT section. The ordinary .got section is an argument, +// since we need to refer to the start. We also create our own .got +// section just for PLT entries. + +template<bool big_endian> +Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout, + Output_data_space* got_plt) + : Output_section_data(4), got_plt_(got_plt), count_(0) +{ + this->rel_ = new Reloc_section(false); + layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, + elfcpp::SHF_ALLOC, this->rel_, true, false, + false, false); +} + +template<bool big_endian> +void +Output_data_plt_arm<big_endian>::do_adjust_output_section(Output_section* os) +{ + os->set_entsize(0); +} + +// Add an entry to the PLT. + +template<bool big_endian> +void +Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym) +{ + gold_assert(!gsym->has_plt_offset()); + + // Note that when setting the PLT offset we skip the initial + // reserved PLT entry. + gsym->set_plt_offset((this->count_) * sizeof(plt_entry) + + sizeof(first_plt_entry)); + + ++this->count_; + + section_offset_type got_offset = this->got_plt_->current_data_size(); + + // Every PLT entry needs a GOT entry which points back to the PLT + // entry (this will be changed by the dynamic linker, normally + // lazily when the function is called). + this->got_plt_->set_current_data_size(got_offset + 4); + + // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); + this->rel_->add_global(gsym, elfcpp::R_ARM_JUMP_SLOT, this->got_plt_, + got_offset); + + // Note that we don't need to save the symbol. The contents of the + // PLT are independent of which symbols are used. The symbols only + // appear in the relocations. +} + +// ARM PLTs. +// FIXME: This is not very flexible. Right now this has only been tested +// on armv5te. If we are to support additional architecture features like +// Thumb-2 or BE8, we need to make this more flexible like GNU ld. + +// The first entry in the PLT. +template<bool big_endian> +const uint32_t Output_data_plt_arm<big_endian>::first_plt_entry[5] = +{ + 0xe52de004, // str lr, [sp, #-4]! + 0xe59fe004, // ldr lr, [pc, #4] + 0xe08fe00e, // add lr, pc, lr + 0xe5bef008, // ldr pc, [lr, #8]! + 0x00000000, // &GOT[0] - . +}; + +// Subsequent entries in the PLT. + +template<bool big_endian> +const uint32_t Output_data_plt_arm<big_endian>::plt_entry[3] = +{ + 0xe28fc600, // add ip, pc, #0xNN00000 + 0xe28cca00, // add ip, ip, #0xNN000 + 0xe5bcf000, // ldr pc, [ip, #0xNNN]! +}; + +// Write out the PLT. This uses the hand-coded instructions above, +// and adjusts them as needed. This is all specified by the arm ELF +// Processor Supplement. + +template<bool big_endian> +void +Output_data_plt_arm<big_endian>::do_write(Output_file* of) +{ + const off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + const off_t got_file_offset = this->got_plt_->offset(); + const section_size_type got_size = + convert_to_section_size_type(this->got_plt_->data_size()); + unsigned char* const got_view = of->get_output_view(got_file_offset, + got_size); + unsigned char* pov = oview; + + Arm_address plt_address = this->address(); + Arm_address got_address = this->got_plt_->address(); + + // Write first PLT entry. All but the last word are constants. + const size_t num_first_plt_words = (sizeof(first_plt_entry) + / sizeof(plt_entry[0])); + for (size_t i = 0; i < num_first_plt_words - 1; i++) + elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]); + // Last word in first PLT entry is &GOT[0] - . + elfcpp::Swap<32, big_endian>::writeval(pov + 16, + got_address - (plt_address + 16)); + pov += sizeof(first_plt_entry); + + unsigned char* got_pov = got_view; + + memset(got_pov, 0, 12); + got_pov += 12; + + const int rel_size = elfcpp::Elf_sizes<32>::rel_size; + unsigned int plt_offset = sizeof(first_plt_entry); + unsigned int plt_rel_offset = 0; + unsigned int got_offset = 12; + const unsigned int count = this->count_; + for (unsigned int i = 0; + i < count; + ++i, + pov += sizeof(plt_entry), + got_pov += 4, + plt_offset += sizeof(plt_entry), + plt_rel_offset += rel_size, + got_offset += 4) + { + // Set and adjust the PLT entry itself. + int32_t offset = ((got_address + got_offset) + - (plt_address + plt_offset + 8)); + + gold_assert(offset >= 0 && offset < 0x0fffffff); + uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff); + elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0); + uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff); + elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1); + uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff); + elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2); + + // Set the entry in the GOT. + elfcpp::Swap<32, big_endian>::writeval(got_pov, plt_address); + } + + gold_assert(static_cast<section_size_type>(pov - oview) == oview_size); + gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size); + + of->write_output_view(offset, oview_size, oview); + of->write_output_view(got_file_offset, got_size, got_view); +} + +// Create a PLT entry for a global symbol. + +template<bool big_endian> +void +Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout, + Symbol* gsym) +{ + if (gsym->has_plt_offset()) + return; + + if (this->plt_ == NULL) + { + // Create the GOT sections first. + this->got_section(symtab, layout); + + this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR), + this->plt_, false, false, false, false); + } + this->plt_->add_entry(gsym); +} + +// Get the section to use for TLS_DESC relocations. + +template<bool big_endian> +typename Target_arm<big_endian>::Reloc_section* +Target_arm<big_endian>::rel_tls_desc_section(Layout* layout) const +{ + return this->plt_section()->rel_tls_desc(layout); +} + +// Define the _TLS_MODULE_BASE_ symbol in the TLS segment. + +template<bool big_endian> +void +Target_arm<big_endian>::define_tls_base_symbol( + Symbol_table* symtab, + Layout* layout) +{ + if (this->tls_base_symbol_defined_) + return; + + Output_segment* tls_segment = layout->tls_segment(); + if (tls_segment != NULL) + { + bool is_exec = parameters->options().output_is_executable(); + symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL, + Symbol_table::PREDEFINED, + tls_segment, 0, 0, + elfcpp::STT_TLS, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + (is_exec + ? Symbol::SEGMENT_END + : Symbol::SEGMENT_START), + true); + } + this->tls_base_symbol_defined_ = true; +} + +// Create a GOT entry for the TLS module index. + +template<bool big_endian> +unsigned int +Target_arm<big_endian>::got_mod_index_entry( + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object) +{ + if (this->got_mod_index_offset_ == -1U) + { + gold_assert(symtab != NULL && layout != NULL && object != NULL); + Arm_output_data_got<big_endian>* got = this->got_section(symtab, layout); + unsigned int got_offset; + if (!parameters->doing_static_link()) + { + got_offset = got->add_constant(0); + Reloc_section* rel_dyn = this->rel_dyn_section(layout); + rel_dyn->add_local(object, 0, elfcpp::R_ARM_TLS_DTPMOD32, got, + got_offset); + } + else + { + // We are doing a static link. Just mark it as belong to module 1, + // the executable. + got_offset = got->add_constant(1); + } + + got->add_constant(0); + this->got_mod_index_offset_ = got_offset; + } + return this->got_mod_index_offset_; +} + +// Optimize the TLS relocation type based on what we know about the +// symbol. IS_FINAL is true if the final address of this symbol is +// known at link time. + +template<bool big_endian> +tls::Tls_optimization +Target_arm<big_endian>::optimize_tls_reloc(bool, int) +{ + // FIXME: Currently we do not do any TLS optimization. + return tls::TLSOPT_NONE; +} + +// Report an unsupported relocation against a local symbol. + +template<bool big_endian> +void +Target_arm<big_endian>::Scan::unsupported_reloc_local( + Sized_relobj<32, big_endian>* object, + unsigned int r_type) +{ + gold_error(_("%s: unsupported reloc %u against local symbol"), + object->name().c_str(), r_type); +} + +// We are about to emit a dynamic relocation of type R_TYPE. If the +// dynamic linker does not support it, issue an error. The GNU linker +// only issues a non-PIC error for an allocated read-only section. +// Here we know the section is allocated, but we don't know that it is +// read-only. But we check for all the relocation types which the +// glibc dynamic linker supports, so it seems appropriate to issue an +// error even if the section is not read-only. + +template<bool big_endian> +void +Target_arm<big_endian>::Scan::check_non_pic(Relobj* object, + unsigned int r_type) +{ + switch (r_type) + { + // These are the relocation types supported by glibc for ARM. + case elfcpp::R_ARM_RELATIVE: + case elfcpp::R_ARM_COPY: + case elfcpp::R_ARM_GLOB_DAT: + case elfcpp::R_ARM_JUMP_SLOT: + case elfcpp::R_ARM_ABS32: + case elfcpp::R_ARM_ABS32_NOI: + case elfcpp::R_ARM_PC24: + // FIXME: The following 3 types are not supported by Android's dynamic + // linker. + case elfcpp::R_ARM_TLS_DTPMOD32: + case elfcpp::R_ARM_TLS_DTPOFF32: + case elfcpp::R_ARM_TLS_TPOFF32: + return; + + default: + { + // This prevents us from issuing more than one error per reloc + // section. But we can still wind up issuing more than one + // error per object file. + if (this->issued_non_pic_error_) + return; + const Arm_reloc_property* reloc_property = + arm_reloc_property_table->get_reloc_property(r_type); + gold_assert(reloc_property != NULL); + object->error(_("requires unsupported dynamic reloc %s; " + "recompile with -fPIC"), + reloc_property->name().c_str()); + this->issued_non_pic_error_ = true; + return; + } + + case elfcpp::R_ARM_NONE: + gold_unreachable(); + } +} + +// Scan a relocation for a local symbol. +// FIXME: This only handles a subset of relocation types used by Android +// on ARM v5te devices. + +template<bool big_endian> +inline void +Target_arm<big_endian>::Scan::local(Symbol_table* symtab, + Layout* layout, + Target_arm* target, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, big_endian>& reloc, + unsigned int r_type, + const elfcpp::Sym<32, big_endian>& lsym) +{ + r_type = get_real_reloc_type(r_type); + switch (r_type) + { + case elfcpp::R_ARM_NONE: + case elfcpp::R_ARM_V4BX: + case elfcpp::R_ARM_GNU_VTENTRY: + case elfcpp::R_ARM_GNU_VTINHERIT: + break; + + case elfcpp::R_ARM_ABS32: + case elfcpp::R_ARM_ABS32_NOI: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. The relocation applied at link time will + // apply the link-time value, so we flag the location with + // an R_ARM_RELATIVE relocation so the dynamic loader can + // relocate it easily. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + // If we are to add more other reloc types than R_ARM_ABS32, + // we need to add check_non_pic(object, r_type) here. + rel_dyn->add_local_relative(object, r_sym, elfcpp::R_ARM_RELATIVE, + output_section, data_shndx, + reloc.get_r_offset()); + } + break; + + case elfcpp::R_ARM_ABS16: + case elfcpp::R_ARM_ABS12: + case elfcpp::R_ARM_THM_ABS5: + case elfcpp::R_ARM_ABS8: + case elfcpp::R_ARM_BASE_ABS: + case elfcpp::R_ARM_MOVW_ABS_NC: + case elfcpp::R_ARM_MOVT_ABS: + case elfcpp::R_ARM_THM_MOVW_ABS_NC: + case elfcpp::R_ARM_THM_MOVT_ABS: + // If building a shared library (or a position-independent + // executable), we need to create a dynamic relocation for + // this location. Because the addend needs to remain in the + // data section, we need to be careful not to apply this + // relocation statically. + if (parameters->options().output_is_position_independent()) + { + check_non_pic(object, r_type); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + if (lsym.get_st_type() != elfcpp::STT_SECTION) + rel_dyn->add_local(object, r_sym, r_type, output_section, + data_shndx, reloc.get_r_offset()); + else + { + gold_assert(lsym.get_st_value() == 0); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, + &is_ordinary); + if (!is_ordinary) + object->error(_("section symbol %u has bad shndx %u"), + r_sym, shndx); + else + rel_dyn->add_local_section(object, shndx, + r_type, output_section, + data_shndx, reloc.get_r_offset()); + } + } + break; + + case elfcpp::R_ARM_PC24: + case elfcpp::R_ARM_REL32: + case elfcpp::R_ARM_LDR_PC_G0: + case elfcpp::R_ARM_SBREL32: + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_THM_PC8: + case elfcpp::R_ARM_BASE_PREL: + case elfcpp::R_ARM_PLT32: + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_LDR_SBREL_11_0_NC: + case elfcpp::R_ARM_ALU_SBREL_19_12_NC: + case elfcpp::R_ARM_ALU_SBREL_27_20_CK: + case elfcpp::R_ARM_SBREL31: + case elfcpp::R_ARM_PREL31: + case elfcpp::R_ARM_MOVW_PREL_NC: + case elfcpp::R_ARM_MOVT_PREL: + case elfcpp::R_ARM_THM_MOVW_PREL_NC: + case elfcpp::R_ARM_THM_MOVT_PREL: + case elfcpp::R_ARM_THM_JUMP19: + case elfcpp::R_ARM_THM_JUMP6: + case elfcpp::R_ARM_THM_ALU_PREL_11_0: + case elfcpp::R_ARM_THM_PC12: + case elfcpp::R_ARM_REL32_NOI: + case elfcpp::R_ARM_ALU_PC_G0_NC: + case elfcpp::R_ARM_ALU_PC_G0: + case elfcpp::R_ARM_ALU_PC_G1_NC: + case elfcpp::R_ARM_ALU_PC_G1: + case elfcpp::R_ARM_ALU_PC_G2: + case elfcpp::R_ARM_LDR_PC_G1: + case elfcpp::R_ARM_LDR_PC_G2: + case elfcpp::R_ARM_LDRS_PC_G0: + case elfcpp::R_ARM_LDRS_PC_G1: + case elfcpp::R_ARM_LDRS_PC_G2: + case elfcpp::R_ARM_LDC_PC_G0: + case elfcpp::R_ARM_LDC_PC_G1: + case elfcpp::R_ARM_LDC_PC_G2: + case elfcpp::R_ARM_ALU_SB_G0_NC: + case elfcpp::R_ARM_ALU_SB_G0: + case elfcpp::R_ARM_ALU_SB_G1_NC: + case elfcpp::R_ARM_ALU_SB_G1: + case elfcpp::R_ARM_ALU_SB_G2: + case elfcpp::R_ARM_LDR_SB_G0: + case elfcpp::R_ARM_LDR_SB_G1: + case elfcpp::R_ARM_LDR_SB_G2: + case elfcpp::R_ARM_LDRS_SB_G0: + case elfcpp::R_ARM_LDRS_SB_G1: + case elfcpp::R_ARM_LDRS_SB_G2: + case elfcpp::R_ARM_LDC_SB_G0: + case elfcpp::R_ARM_LDC_SB_G1: + case elfcpp::R_ARM_LDC_SB_G2: + case elfcpp::R_ARM_MOVW_BREL_NC: + case elfcpp::R_ARM_MOVT_BREL: + case elfcpp::R_ARM_MOVW_BREL: + case elfcpp::R_ARM_THM_MOVW_BREL_NC: + case elfcpp::R_ARM_THM_MOVT_BREL: + case elfcpp::R_ARM_THM_MOVW_BREL: + case elfcpp::R_ARM_THM_JUMP11: + case elfcpp::R_ARM_THM_JUMP8: + // We don't need to do anything for a relative addressing relocation + // against a local symbol if it does not reference the GOT. + break; + + case elfcpp::R_ARM_GOTOFF32: + case elfcpp::R_ARM_GOTOFF12: + // We need a GOT section: + target->got_section(symtab, layout); + break; + + case elfcpp::R_ARM_GOT_BREL: + case elfcpp::R_ARM_GOT_PREL: + { + // The symbol requires a GOT entry. + Arm_output_data_got<big_endian>* got = + target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + if (got->add_local(object, r_sym, GOT_TYPE_STANDARD)) + { + // If we are generating a shared object, we need to add a + // dynamic RELATIVE relocation for this symbol's GOT entry. + if (parameters->options().output_is_position_independent()) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + rel_dyn->add_local_relative( + object, r_sym, elfcpp::R_ARM_RELATIVE, got, + object->local_got_offset(r_sym, GOT_TYPE_STANDARD)); + } + } + } + break; + + case elfcpp::R_ARM_TARGET1: + case elfcpp::R_ARM_TARGET2: + // This should have been mapped to another type already. + // Fall through. + case elfcpp::R_ARM_COPY: + case elfcpp::R_ARM_GLOB_DAT: + case elfcpp::R_ARM_JUMP_SLOT: + case elfcpp::R_ARM_RELATIVE: + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + + // These are initial TLS relocs, which are expected when + // linking. + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + case elfcpp::R_ARM_TLS_LE32: // Local-exec + { + bool output_is_shared = parameters->options().shared(); + const tls::Tls_optimization optimized_type + = Target_arm<big_endian>::optimize_tls_reloc(!output_is_shared, + r_type); + switch (r_type) + { + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Arm_output_data_got<big_endian>* got + = target->got_section(symtab, layout); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + { + object->error(_("local symbol %u has bad shndx %u"), + r_sym, shndx); + break; + } + + if (!parameters->doing_static_link()) + got->add_local_pair_with_rel(object, r_sym, shndx, + GOT_TYPE_TLS_PAIR, + target->rel_dyn_section(layout), + elfcpp::R_ARM_TLS_DTPMOD32, 0); + else + got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR, + object, r_sym); + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + break; + + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Arm_output_data_got<big_endian>* got + = target->got_section(symtab, layout); + unsigned int r_sym = + elfcpp::elf_r_sym<32>(reloc.get_r_info()); + if (!parameters->doing_static_link()) + got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET, + target->rel_dyn_section(layout), + elfcpp::R_ARM_TLS_TPOFF32); + else if (!object->local_has_got_offset(r_sym, + GOT_TYPE_TLS_OFFSET)) + { + got->add_local(object, r_sym, GOT_TYPE_TLS_OFFSET); + unsigned int got_offset = + object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET); + got->add_static_reloc(got_offset, + elfcpp::R_ARM_TLS_TPOFF32, object, + r_sym); + } + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LE32: // Local-exec + layout->set_has_static_tls(); + if (output_is_shared) + { + // We need to create a dynamic relocation. + gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); + unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_local(object, r_sym, elfcpp::R_ARM_TLS_TPOFF32, + output_section, data_shndx, + reloc.get_r_offset()); + } + break; + + default: + gold_unreachable(); + } + } + break; + + default: + unsupported_reloc_local(object, r_type); + break; + } +} + +// Report an unsupported relocation against a global symbol. + +template<bool big_endian> +void +Target_arm<big_endian>::Scan::unsupported_reloc_global( + Sized_relobj<32, big_endian>* object, + unsigned int r_type, + Symbol* gsym) +{ + gold_error(_("%s: unsupported reloc %u against global symbol %s"), + object->name().c_str(), r_type, gsym->demangled_name().c_str()); +} + +// Scan a relocation for a global symbol. + +template<bool big_endian> +inline void +Target_arm<big_endian>::Scan::global(Symbol_table* symtab, + Layout* layout, + Target_arm* target, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rel<32, big_endian>& reloc, + unsigned int r_type, + Symbol* gsym) +{ + // A reference to _GLOBAL_OFFSET_TABLE_ implies that we need a got + // section. We check here to avoid creating a dynamic reloc against + // _GLOBAL_OFFSET_TABLE_. + if (!target->has_got_section() + && strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0) + target->got_section(symtab, layout); + + r_type = get_real_reloc_type(r_type); + switch (r_type) + { + case elfcpp::R_ARM_NONE: + case elfcpp::R_ARM_V4BX: + case elfcpp::R_ARM_GNU_VTENTRY: + case elfcpp::R_ARM_GNU_VTINHERIT: + break; + + case elfcpp::R_ARM_ABS32: + case elfcpp::R_ARM_ABS16: + case elfcpp::R_ARM_ABS12: + case elfcpp::R_ARM_THM_ABS5: + case elfcpp::R_ARM_ABS8: + case elfcpp::R_ARM_BASE_ABS: + case elfcpp::R_ARM_MOVW_ABS_NC: + case elfcpp::R_ARM_MOVT_ABS: + case elfcpp::R_ARM_THM_MOVW_ABS_NC: + case elfcpp::R_ARM_THM_MOVT_ABS: + case elfcpp::R_ARM_ABS32_NOI: + // Absolute addressing relocations. + { + // Make a PLT entry if necessary. + if (this->symbol_needs_plt_entry(gsym)) + { + target->make_plt_entry(symtab, layout, gsym); + // Since this is not a PC-relative relocation, we may be + // taking the address of a function. In that case we need to + // set the entry in the dynamic symbol table to the address of + // the PLT entry. + if (gsym->is_from_dynobj() && !parameters->options().shared()) + gsym->set_needs_dynsym_value(); + } + // Make a dynamic relocation if necessary. + if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) + { + if (gsym->may_need_copy_reloc()) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else if ((r_type == elfcpp::R_ARM_ABS32 + || r_type == elfcpp::R_ARM_ABS32_NOI) + && gsym->can_use_relative_reloc(false)) + { + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global_relative(gsym, elfcpp::R_ARM_RELATIVE, + output_section, object, + data_shndx, reloc.get_r_offset()); + } + else + { + check_non_pic(object, r_type); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset()); + } + } + } + break; + + case elfcpp::R_ARM_GOTOFF32: + case elfcpp::R_ARM_GOTOFF12: + // We need a GOT section. + target->got_section(symtab, layout); + break; + + case elfcpp::R_ARM_REL32: + case elfcpp::R_ARM_LDR_PC_G0: + case elfcpp::R_ARM_SBREL32: + case elfcpp::R_ARM_THM_PC8: + case elfcpp::R_ARM_BASE_PREL: + case elfcpp::R_ARM_LDR_SBREL_11_0_NC: + case elfcpp::R_ARM_ALU_SBREL_19_12_NC: + case elfcpp::R_ARM_ALU_SBREL_27_20_CK: + case elfcpp::R_ARM_MOVW_PREL_NC: + case elfcpp::R_ARM_MOVT_PREL: + case elfcpp::R_ARM_THM_MOVW_PREL_NC: + case elfcpp::R_ARM_THM_MOVT_PREL: + case elfcpp::R_ARM_THM_ALU_PREL_11_0: + case elfcpp::R_ARM_THM_PC12: + case elfcpp::R_ARM_REL32_NOI: + case elfcpp::R_ARM_ALU_PC_G0_NC: + case elfcpp::R_ARM_ALU_PC_G0: + case elfcpp::R_ARM_ALU_PC_G1_NC: + case elfcpp::R_ARM_ALU_PC_G1: + case elfcpp::R_ARM_ALU_PC_G2: + case elfcpp::R_ARM_LDR_PC_G1: + case elfcpp::R_ARM_LDR_PC_G2: + case elfcpp::R_ARM_LDRS_PC_G0: + case elfcpp::R_ARM_LDRS_PC_G1: + case elfcpp::R_ARM_LDRS_PC_G2: + case elfcpp::R_ARM_LDC_PC_G0: + case elfcpp::R_ARM_LDC_PC_G1: + case elfcpp::R_ARM_LDC_PC_G2: + case elfcpp::R_ARM_ALU_SB_G0_NC: + case elfcpp::R_ARM_ALU_SB_G0: + case elfcpp::R_ARM_ALU_SB_G1_NC: + case elfcpp::R_ARM_ALU_SB_G1: + case elfcpp::R_ARM_ALU_SB_G2: + case elfcpp::R_ARM_LDR_SB_G0: + case elfcpp::R_ARM_LDR_SB_G1: + case elfcpp::R_ARM_LDR_SB_G2: + case elfcpp::R_ARM_LDRS_SB_G0: + case elfcpp::R_ARM_LDRS_SB_G1: + case elfcpp::R_ARM_LDRS_SB_G2: + case elfcpp::R_ARM_LDC_SB_G0: + case elfcpp::R_ARM_LDC_SB_G1: + case elfcpp::R_ARM_LDC_SB_G2: + case elfcpp::R_ARM_MOVW_BREL_NC: + case elfcpp::R_ARM_MOVT_BREL: + case elfcpp::R_ARM_MOVW_BREL: + case elfcpp::R_ARM_THM_MOVW_BREL_NC: + case elfcpp::R_ARM_THM_MOVT_BREL: + case elfcpp::R_ARM_THM_MOVW_BREL: + // Relative addressing relocations. + { + // Make a dynamic relocation if necessary. + int flags = Symbol::NON_PIC_REF; + if (gsym->needs_dynamic_reloc(flags)) + { + if (target->may_need_copy_reloc(gsym)) + { + target->copy_reloc(symtab, layout, object, + data_shndx, output_section, gsym, reloc); + } + else + { + check_non_pic(object, r_type); + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, r_type, output_section, object, + data_shndx, reloc.get_r_offset()); + } + } + } + break; + + case elfcpp::R_ARM_PC24: + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_PLT32: + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_SBREL31: + case elfcpp::R_ARM_PREL31: + case elfcpp::R_ARM_THM_JUMP19: + case elfcpp::R_ARM_THM_JUMP6: + case elfcpp::R_ARM_THM_JUMP11: + case elfcpp::R_ARM_THM_JUMP8: + // All the relocation above are branches except for the PREL31 ones. + // A PREL31 relocation can point to a personality function in a shared + // library. In that case we want to use a PLT because we want to + // call the personality routine and the dyanmic linkers we care about + // do not support dynamic PREL31 relocations. An REL31 relocation may + // point to a function whose unwinding behaviour is being described but + // we will not mistakenly generate a PLT for that because we should use + // a local section symbol. + + // If the symbol is fully resolved, this is just a relative + // local reloc. Otherwise we need a PLT entry. + if (gsym->final_value_is_known()) + break; + // If building a shared library, we can also skip the PLT entry + // if the symbol is defined in the output file and is protected + // or hidden. + if (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible()) + break; + target->make_plt_entry(symtab, layout, gsym); + break; + + case elfcpp::R_ARM_GOT_BREL: + case elfcpp::R_ARM_GOT_ABS: + case elfcpp::R_ARM_GOT_PREL: + { + // The symbol requires a GOT entry. + Arm_output_data_got<big_endian>* got = + target->got_section(symtab, layout); + if (gsym->final_value_is_known()) + got->add_global(gsym, GOT_TYPE_STANDARD); + else + { + // If this symbol is not fully resolved, we need to add a + // GOT entry with a dynamic relocation. + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + if (gsym->is_from_dynobj() + || gsym->is_undefined() + || gsym->is_preemptible()) + got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, + rel_dyn, elfcpp::R_ARM_GLOB_DAT); + else + { + if (got->add_global(gsym, GOT_TYPE_STANDARD)) + rel_dyn->add_global_relative( + gsym, elfcpp::R_ARM_RELATIVE, got, + gsym->got_offset(GOT_TYPE_STANDARD)); + } + } + } + break; + + case elfcpp::R_ARM_TARGET1: + case elfcpp::R_ARM_TARGET2: + // These should have been mapped to other types already. + // Fall through. + case elfcpp::R_ARM_COPY: + case elfcpp::R_ARM_GLOB_DAT: + case elfcpp::R_ARM_JUMP_SLOT: + case elfcpp::R_ARM_RELATIVE: + // These are relocations which should only be seen by the + // dynamic linker, and should never be seen here. + gold_error(_("%s: unexpected reloc %u in object file"), + object->name().c_str(), r_type); + break; + + // These are initial tls relocs, which are expected when + // linking. + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + case elfcpp::R_ARM_TLS_LE32: // Local-exec + { + const bool is_final = gsym->final_value_is_known(); + const tls::Tls_optimization optimized_type + = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a pair of GOT entries for the module index and + // dtv-relative offset. + Arm_output_data_got<big_endian>* got + = target->got_section(symtab, layout); + if (!parameters->doing_static_link()) + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR, + target->rel_dyn_section(layout), + elfcpp::R_ARM_TLS_DTPMOD32, + elfcpp::R_ARM_TLS_DTPOFF32); + else + got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR, gsym); + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the module index. + target->got_mod_index_entry(symtab, layout, object); + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + break; + + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + layout->set_has_static_tls(); + if (optimized_type == tls::TLSOPT_NONE) + { + // Create a GOT entry for the tp-relative offset. + Arm_output_data_got<big_endian>* got + = target->got_section(symtab, layout); + if (!parameters->doing_static_link()) + got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET, + target->rel_dyn_section(layout), + elfcpp::R_ARM_TLS_TPOFF32); + else if (!gsym->has_got_offset(GOT_TYPE_TLS_OFFSET)) + { + got->add_global(gsym, GOT_TYPE_TLS_OFFSET); + unsigned int got_offset = + gsym->got_offset(GOT_TYPE_TLS_OFFSET); + got->add_static_reloc(got_offset, + elfcpp::R_ARM_TLS_TPOFF32, gsym); + } + } + else + // FIXME: TLS optimization not supported yet. + gold_unreachable(); + break; + + case elfcpp::R_ARM_TLS_LE32: // Local-exec + layout->set_has_static_tls(); + if (parameters->options().shared()) + { + // We need to create a dynamic relocation. + Reloc_section* rel_dyn = target->rel_dyn_section(layout); + rel_dyn->add_global(gsym, elfcpp::R_ARM_TLS_TPOFF32, + output_section, object, + data_shndx, reloc.get_r_offset()); + } + break; + + default: + gold_unreachable(); + } + } + break; + + default: + unsupported_reloc_global(object, r_type, gsym); + break; + } +} + +// Process relocations for gc. + +template<bool big_endian> +void +Target_arm<big_endian>::gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef Target_arm<big_endian> Arm; + typedef typename Target_arm<big_endian>::Scan Scan; + + gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Scan relocations for a section. + +template<bool big_endian> +void +Target_arm<big_endian>::scan_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef typename Target_arm<big_endian>::Scan Scan; + if (sh_type == elfcpp::SHT_RELA) + { + gold_error(_("%s: unsupported RELA reloc section"), + object->name().c_str()); + return; + } + + gold::scan_relocs<32, big_endian, Target_arm, elfcpp::SHT_REL, Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + +// Finalize the sections. + +template<bool big_endian> +void +Target_arm<big_endian>::do_finalize_sections( + Layout* layout, + const Input_objects* input_objects, + Symbol_table* symtab) +{ + // Create an empty uninitialized attribute section if we still don't have it + // at this moment. + if (this->attributes_section_data_ == NULL) + this->attributes_section_data_ = new Attributes_section_data(NULL, 0); + + // Merge processor-specific flags. + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(*p); + if (arm_relobj->merge_flags_and_attributes()) + { + this->merge_processor_specific_flags( + arm_relobj->name(), + arm_relobj->processor_specific_flags()); + this->merge_object_attributes(arm_relobj->name().c_str(), + arm_relobj->attributes_section_data()); + } + } + + for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); + p != input_objects->dynobj_end(); + ++p) + { + Arm_dynobj<big_endian>* arm_dynobj = + Arm_dynobj<big_endian>::as_arm_dynobj(*p); + this->merge_processor_specific_flags( + arm_dynobj->name(), + arm_dynobj->processor_specific_flags()); + this->merge_object_attributes(arm_dynobj->name().c_str(), + arm_dynobj->attributes_section_data()); + } + + // Check BLX use. + const Object_attribute* cpu_arch_attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch); + if (cpu_arch_attr->int_value() > elfcpp::TAG_CPU_ARCH_V4) + this->set_may_use_blx(true); + + // Check if we need to use Cortex-A8 workaround. + if (parameters->options().user_set_fix_cortex_a8()) + this->fix_cortex_a8_ = parameters->options().fix_cortex_a8(); + else + { + // If neither --fix-cortex-a8 nor --no-fix-cortex-a8 is used, turn on + // Cortex-A8 erratum workaround for ARMv7-A or ARMv7 with unknown + // profile. + const Object_attribute* cpu_arch_profile_attr = + this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch_profile); + this->fix_cortex_a8_ = + (cpu_arch_attr->int_value() == elfcpp::TAG_CPU_ARCH_V7 + && (cpu_arch_profile_attr->int_value() == 'A' + || cpu_arch_profile_attr->int_value() == 0)); + } + + // Check if we can use V4BX interworking. + // The V4BX interworking stub contains BX instruction, + // which is not specified for some profiles. + if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING + && !this->may_use_blx()) + gold_error(_("unable to provide V4BX reloc interworking fix up; " + "the target profile does not support BX instruction")); + + // Fill in some more dynamic tags. + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, + this->rel_dyn_, true, false); + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. + if (this->copy_relocs_.any_saved_relocs()) + this->copy_relocs_.emit(this->rel_dyn_section(layout)); + + // Handle the .ARM.exidx section. + Output_section* exidx_section = layout->find_output_section(".ARM.exidx"); + if (exidx_section != NULL + && exidx_section->type() == elfcpp::SHT_ARM_EXIDX + && !parameters->options().relocatable()) + { + // Create __exidx_start and __exdix_end symbols. + symtab->define_in_output_data("__exidx_start", NULL, + Symbol_table::PREDEFINED, + exidx_section, 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0, + false, true); + symtab->define_in_output_data("__exidx_end", NULL, + Symbol_table::PREDEFINED, + exidx_section, 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0, + true, true); + + // For the ARM target, we need to add a PT_ARM_EXIDX segment for + // the .ARM.exidx section. + if (!layout->script_options()->saw_phdrs_clause()) + { + gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0, 0) + == NULL); + Output_segment* exidx_segment = + layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R); + exidx_segment->add_output_section(exidx_section, elfcpp::PF_R, + false); + } + } + + // Create an .ARM.attributes section unless we have no regular input + // object. In that case the output will be empty. + if (input_objects->number_of_relobjs() != 0) + { + Output_attributes_section_data* attributes_section = + new Output_attributes_section_data(*this->attributes_section_data_); + layout->add_output_section_data(".ARM.attributes", + elfcpp::SHT_ARM_ATTRIBUTES, 0, + attributes_section, false, false, false, + false); + } +} + +// Return whether a direct absolute static relocation needs to be applied. +// In cases where Scan::local() or Scan::global() has created +// a dynamic relocation other than R_ARM_RELATIVE, the addend +// of the relocation is carried in the data, and we must not +// apply the static relocation. + +template<bool big_endian> +inline bool +Target_arm<big_endian>::Relocate::should_apply_static_reloc( + const Sized_symbol<32>* gsym, + int ref_flags, + bool is_32bit, + Output_section* output_section) +{ + // If the output section is not allocated, then we didn't call + // scan_relocs, we didn't create a dynamic reloc, and we must apply + // the reloc here. + if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0) + return true; + + // For local symbols, we will have created a non-RELATIVE dynamic + // relocation only if (a) the output is position independent, + // (b) the relocation is absolute (not pc- or segment-relative), and + // (c) the relocation is not 32 bits wide. + if (gsym == NULL) + return !(parameters->options().output_is_position_independent() + && (ref_flags & Symbol::ABSOLUTE_REF) + && !is_32bit); + + // For global symbols, we use the same helper routines used in the + // scan pass. If we did not create a dynamic relocation, or if we + // created a RELATIVE dynamic relocation, we should apply the static + // relocation. + bool has_dyn = gsym->needs_dynamic_reloc(ref_flags); + bool is_rel = (ref_flags & Symbol::ABSOLUTE_REF) + && gsym->can_use_relative_reloc(ref_flags + & Symbol::FUNCTION_CALL); + return !has_dyn || is_rel; +} + +// Perform a relocation. + +template<bool big_endian> +inline bool +Target_arm<big_endian>::Relocate::relocate( + const Relocate_info<32, big_endian>* relinfo, + Target_arm* target, + Output_section *output_section, + size_t relnum, + const elfcpp::Rel<32, big_endian>& rel, + unsigned int r_type, + const Sized_symbol<32>* gsym, + const Symbol_value<32>* psymval, + unsigned char* view, + Arm_address address, + section_size_type view_size) +{ + typedef Arm_relocate_functions<big_endian> Arm_relocate_functions; + + r_type = get_real_reloc_type(r_type); + const Arm_reloc_property* reloc_property = + arm_reloc_property_table->get_implemented_static_reloc_property(r_type); + if (reloc_property == NULL) + { + std::string reloc_name = + arm_reloc_property_table->reloc_name_in_error_message(r_type); + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("cannot relocate %s in object file"), + reloc_name.c_str()); + return true; + } + + const Arm_relobj<big_endian>* object = + Arm_relobj<big_endian>::as_arm_relobj(relinfo->object); + + // If the final branch target of a relocation is THUMB instruction, this + // is 1. Otherwise it is 0. + Arm_address thumb_bit = 0; + Symbol_value<32> symval; + bool is_weakly_undefined_without_plt = false; + if (relnum != Target_arm<big_endian>::fake_relnum_for_stubs) + { + if (gsym != NULL) + { + // This is a global symbol. Determine if we use PLT and if the + // final target is THUMB. + if (gsym->use_plt_offset(reloc_is_non_pic(r_type))) + { + // This uses a PLT, change the symbol value. + symval.set_output_value(target->plt_section()->address() + + gsym->plt_offset()); + psymval = &symval; + } + else if (gsym->is_weak_undefined()) + { + // This is a weakly undefined symbol and we do not use PLT + // for this relocation. A branch targeting this symbol will + // be converted into an NOP. + is_weakly_undefined_without_plt = true; + } + else + { + // Set thumb bit if symbol: + // -Has type STT_ARM_TFUNC or + // -Has type STT_FUNC, is defined and with LSB in value set. + thumb_bit = + (((gsym->type() == elfcpp::STT_ARM_TFUNC) + || (gsym->type() == elfcpp::STT_FUNC + && !gsym->is_undefined() + && ((psymval->value(object, 0) & 1) != 0))) + ? 1 + : 0); + } + } + else + { + // This is a local symbol. Determine if the final target is THUMB. + // We saved this information when all the local symbols were read. + elfcpp::Elf_types<32>::Elf_WXword r_info = rel.get_r_info(); + unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info); + thumb_bit = object->local_symbol_is_thumb_function(r_sym) ? 1 : 0; + } + } + else + { + // This is a fake relocation synthesized for a stub. It does not have + // a real symbol. We just look at the LSB of the symbol value to + // determine if the target is THUMB or not. + thumb_bit = ((psymval->value(object, 0) & 1) != 0); + } + + // Strip LSB if this points to a THUMB target. + if (thumb_bit != 0 + && reloc_property->uses_thumb_bit() + && ((psymval->value(object, 0) & 1) != 0)) + { + Arm_address stripped_value = + psymval->value(object, 0) & ~static_cast<Arm_address>(1); + symval.set_output_value(stripped_value); + psymval = &symval; + } + + // Get the GOT offset if needed. + // The GOT pointer points to the end of the GOT section. + // We need to subtract the size of the GOT section to get + // the actual offset to use in the relocation. + bool have_got_offset = false; + unsigned int got_offset = 0; + switch (r_type) + { + case elfcpp::R_ARM_GOT_BREL: + case elfcpp::R_ARM_GOT_PREL: + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); + got_offset = (gsym->got_offset(GOT_TYPE_STANDARD) + - target->got_size()); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); + got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD) + - target->got_size()); + } + have_got_offset = true; + break; + + default: + break; + } + + // To look up relocation stubs, we need to pass the symbol table index of + // a local symbol. + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + + // Get the addressing origin of the output segment defining the + // symbol gsym if needed (AAELF 4.6.1.2 Relocation types). + Arm_address sym_origin = 0; + if (reloc_property->uses_symbol_base()) + { + if (r_type == elfcpp::R_ARM_BASE_ABS && gsym == NULL) + // R_ARM_BASE_ABS with the NULL symbol will give the + // absolute address of the GOT origin (GOT_ORG) (see ARM IHI + // 0044C (AAELF): 4.6.1.8 Proxy generating relocations). + sym_origin = target->got_plt_section()->address(); + else if (gsym == NULL) + sym_origin = 0; + else if (gsym->source() == Symbol::IN_OUTPUT_SEGMENT) + sym_origin = gsym->output_segment()->vaddr(); + else if (gsym->source() == Symbol::IN_OUTPUT_DATA) + sym_origin = gsym->output_data()->address(); + + // TODO: Assumes the segment base to be zero for the global symbols + // till the proper support for the segment-base-relative addressing + // will be implemented. This is consistent with GNU ld. + } + + // For relative addressing relocation, find out the relative address base. + Arm_address relative_address_base = 0; + switch(reloc_property->relative_address_base()) + { + case Arm_reloc_property::RAB_NONE: + // Relocations with relative address bases RAB_TLS and RAB_tp are + // handled by relocate_tls. So we do not need to do anything here. + case Arm_reloc_property::RAB_TLS: + case Arm_reloc_property::RAB_tp: + break; + case Arm_reloc_property::RAB_B_S: + relative_address_base = sym_origin; + break; + case Arm_reloc_property::RAB_GOT_ORG: + relative_address_base = target->got_plt_section()->address(); + break; + case Arm_reloc_property::RAB_P: + relative_address_base = address; + break; + case Arm_reloc_property::RAB_Pa: + relative_address_base = address & 0xfffffffcU; + break; + default: + gold_unreachable(); + } + + typename Arm_relocate_functions::Status reloc_status = + Arm_relocate_functions::STATUS_OKAY; + bool check_overflow = reloc_property->checks_overflow(); + switch (r_type) + { + case elfcpp::R_ARM_NONE: + break; + + case elfcpp::R_ARM_ABS8: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::abs8(view, object, psymval); + break; + + case elfcpp::R_ARM_ABS12: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::abs12(view, object, psymval); + break; + + case elfcpp::R_ARM_ABS16: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::abs16(view, object, psymval); + break; + + case elfcpp::R_ARM_ABS32: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true, + output_section)) + reloc_status = Arm_relocate_functions::abs32(view, object, psymval, + thumb_bit); + break; + + case elfcpp::R_ARM_ABS32_NOI: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true, + output_section)) + // No thumb bit for this relocation: (S + A) + reloc_status = Arm_relocate_functions::abs32(view, object, psymval, + 0); + break; + + case elfcpp::R_ARM_MOVW_ABS_NC: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::movw(view, object, psymval, + 0, thumb_bit, + check_overflow); + break; + + case elfcpp::R_ARM_MOVT_ABS: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::movt(view, object, psymval, 0); + break; + + case elfcpp::R_ARM_THM_MOVW_ABS_NC: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::thm_movw(view, object, psymval, + 0, thumb_bit, false); + break; + + case elfcpp::R_ARM_THM_MOVT_ABS: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::thm_movt(view, object, + psymval, 0); + break; + + case elfcpp::R_ARM_MOVW_PREL_NC: + case elfcpp::R_ARM_MOVW_BREL_NC: + case elfcpp::R_ARM_MOVW_BREL: + reloc_status = + Arm_relocate_functions::movw(view, object, psymval, + relative_address_base, thumb_bit, + check_overflow); + break; + + case elfcpp::R_ARM_MOVT_PREL: + case elfcpp::R_ARM_MOVT_BREL: + reloc_status = + Arm_relocate_functions::movt(view, object, psymval, + relative_address_base); + break; + + case elfcpp::R_ARM_THM_MOVW_PREL_NC: + case elfcpp::R_ARM_THM_MOVW_BREL_NC: + case elfcpp::R_ARM_THM_MOVW_BREL: + reloc_status = + Arm_relocate_functions::thm_movw(view, object, psymval, + relative_address_base, + thumb_bit, check_overflow); + break; + + case elfcpp::R_ARM_THM_MOVT_PREL: + case elfcpp::R_ARM_THM_MOVT_BREL: + reloc_status = + Arm_relocate_functions::thm_movt(view, object, psymval, + relative_address_base); + break; + + case elfcpp::R_ARM_REL32: + reloc_status = Arm_relocate_functions::rel32(view, object, psymval, + address, thumb_bit); + break; + + case elfcpp::R_ARM_THM_ABS5: + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + reloc_status = Arm_relocate_functions::thm_abs5(view, object, psymval); + break; + + // Thumb long branches. + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_THM_XPC22: + case elfcpp::R_ARM_THM_JUMP24: + reloc_status = + Arm_relocate_functions::thumb_branch_common( + r_type, relinfo, view, gsym, object, r_sym, psymval, address, + thumb_bit, is_weakly_undefined_without_plt); + break; + + case elfcpp::R_ARM_GOTOFF32: + { + Arm_address got_origin; + got_origin = target->got_plt_section()->address(); + reloc_status = Arm_relocate_functions::rel32(view, object, psymval, + got_origin, thumb_bit); + } + break; + + case elfcpp::R_ARM_BASE_PREL: + gold_assert(gsym != NULL); + reloc_status = + Arm_relocate_functions::base_prel(view, sym_origin, address); + break; + + case elfcpp::R_ARM_BASE_ABS: + { + if (!should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) + break; + + reloc_status = Arm_relocate_functions::base_abs(view, sym_origin); + } + break; + + case elfcpp::R_ARM_GOT_BREL: + gold_assert(have_got_offset); + reloc_status = Arm_relocate_functions::got_brel(view, got_offset); + break; + + case elfcpp::R_ARM_GOT_PREL: + gold_assert(have_got_offset); + // Get the address origin for GOT PLT, which is allocated right + // after the GOT section, to calculate an absolute address of + // the symbol GOT entry (got_origin + got_offset). + Arm_address got_origin; + got_origin = target->got_plt_section()->address(); + reloc_status = Arm_relocate_functions::got_prel(view, + got_origin + got_offset, + address); + break; + + case elfcpp::R_ARM_PLT32: + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_XPC25: + gold_assert(gsym == NULL + || gsym->has_plt_offset() + || gsym->final_value_is_known() + || (gsym->is_defined() + && !gsym->is_from_dynobj() + && !gsym->is_preemptible())); + reloc_status = + Arm_relocate_functions::arm_branch_common( + r_type, relinfo, view, gsym, object, r_sym, psymval, address, + thumb_bit, is_weakly_undefined_without_plt); + break; + + case elfcpp::R_ARM_THM_JUMP19: + reloc_status = + Arm_relocate_functions::thm_jump19(view, object, psymval, address, + thumb_bit); + break; + + case elfcpp::R_ARM_THM_JUMP6: + reloc_status = + Arm_relocate_functions::thm_jump6(view, object, psymval, address); + break; + + case elfcpp::R_ARM_THM_JUMP8: + reloc_status = + Arm_relocate_functions::thm_jump8(view, object, psymval, address); + break; + + case elfcpp::R_ARM_THM_JUMP11: + reloc_status = + Arm_relocate_functions::thm_jump11(view, object, psymval, address); + break; + + case elfcpp::R_ARM_PREL31: + reloc_status = Arm_relocate_functions::prel31(view, object, psymval, + address, thumb_bit); + break; + + case elfcpp::R_ARM_V4BX: + if (target->fix_v4bx() > General_options::FIX_V4BX_NONE) + { + const bool is_v4bx_interworking = + (target->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING); + reloc_status = + Arm_relocate_functions::v4bx(relinfo, view, object, address, + is_v4bx_interworking); + } + break; + + case elfcpp::R_ARM_THM_PC8: + reloc_status = + Arm_relocate_functions::thm_pc8(view, object, psymval, address); + break; + + case elfcpp::R_ARM_THM_PC12: + reloc_status = + Arm_relocate_functions::thm_pc12(view, object, psymval, address); + break; + + case elfcpp::R_ARM_THM_ALU_PREL_11_0: + reloc_status = + Arm_relocate_functions::thm_alu11(view, object, psymval, address, + thumb_bit); + break; + + case elfcpp::R_ARM_ALU_PC_G0_NC: + case elfcpp::R_ARM_ALU_PC_G0: + case elfcpp::R_ARM_ALU_PC_G1_NC: + case elfcpp::R_ARM_ALU_PC_G1: + case elfcpp::R_ARM_ALU_PC_G2: + case elfcpp::R_ARM_ALU_SB_G0_NC: + case elfcpp::R_ARM_ALU_SB_G0: + case elfcpp::R_ARM_ALU_SB_G1_NC: + case elfcpp::R_ARM_ALU_SB_G1: + case elfcpp::R_ARM_ALU_SB_G2: + reloc_status = + Arm_relocate_functions::arm_grp_alu(view, object, psymval, + reloc_property->group_index(), + relative_address_base, + thumb_bit, check_overflow); + break; + + case elfcpp::R_ARM_LDR_PC_G0: + case elfcpp::R_ARM_LDR_PC_G1: + case elfcpp::R_ARM_LDR_PC_G2: + case elfcpp::R_ARM_LDR_SB_G0: + case elfcpp::R_ARM_LDR_SB_G1: + case elfcpp::R_ARM_LDR_SB_G2: + reloc_status = + Arm_relocate_functions::arm_grp_ldr(view, object, psymval, + reloc_property->group_index(), + relative_address_base); + break; + + case elfcpp::R_ARM_LDRS_PC_G0: + case elfcpp::R_ARM_LDRS_PC_G1: + case elfcpp::R_ARM_LDRS_PC_G2: + case elfcpp::R_ARM_LDRS_SB_G0: + case elfcpp::R_ARM_LDRS_SB_G1: + case elfcpp::R_ARM_LDRS_SB_G2: + reloc_status = + Arm_relocate_functions::arm_grp_ldrs(view, object, psymval, + reloc_property->group_index(), + relative_address_base); + break; + + case elfcpp::R_ARM_LDC_PC_G0: + case elfcpp::R_ARM_LDC_PC_G1: + case elfcpp::R_ARM_LDC_PC_G2: + case elfcpp::R_ARM_LDC_SB_G0: + case elfcpp::R_ARM_LDC_SB_G1: + case elfcpp::R_ARM_LDC_SB_G2: + reloc_status = + Arm_relocate_functions::arm_grp_ldc(view, object, psymval, + reloc_property->group_index(), + relative_address_base); + break; + + // These are initial tls relocs, which are expected when + // linking. + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + case elfcpp::R_ARM_TLS_LE32: // Local-exec + reloc_status = + this->relocate_tls(relinfo, target, relnum, rel, r_type, gsym, psymval, + view, address, view_size); + break; + + default: + gold_unreachable(); + } + + // Report any errors. + switch (reloc_status) + { + case Arm_relocate_functions::STATUS_OKAY: + break; + case Arm_relocate_functions::STATUS_OVERFLOW: + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("relocation overflow in %s"), + reloc_property->name().c_str()); + break; + case Arm_relocate_functions::STATUS_BAD_RELOC: + gold_error_at_location( + relinfo, + relnum, + rel.get_r_offset(), + _("unexpected opcode while processing relocation %s"), + reloc_property->name().c_str()); + break; + default: + gold_unreachable(); + } + + return true; +} + +// Perform a TLS relocation. + +template<bool big_endian> +inline typename Arm_relocate_functions<big_endian>::Status +Target_arm<big_endian>::Relocate::relocate_tls( + const Relocate_info<32, big_endian>* relinfo, + Target_arm<big_endian>* target, + size_t relnum, + const elfcpp::Rel<32, big_endian>& rel, + unsigned int r_type, + const Sized_symbol<32>* gsym, + const Symbol_value<32>* psymval, + unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr address, + section_size_type /*view_size*/ ) +{ + typedef Arm_relocate_functions<big_endian> ArmRelocFuncs; + typedef Relocate_functions<32, big_endian> RelocFuncs; + Output_segment* tls_segment = relinfo->layout->tls_segment(); + + const Sized_relobj<32, big_endian>* object = relinfo->object; + + elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0); + + const bool is_final = (gsym == NULL + ? !parameters->options().shared() + : gsym->final_value_is_known()); + const tls::Tls_optimization optimized_type + = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type); + switch (r_type) + { + case elfcpp::R_ARM_TLS_GD32: // Global-dynamic + { + unsigned int got_type = GOT_TYPE_TLS_PAIR; + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type) - target->got_size(); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = (object->local_got_offset(r_sym, got_type) + - target->got_size()); + } + if (optimized_type == tls::TLSOPT_NONE) + { + Arm_address got_entry = + target->got_plt_section()->address() + got_offset; + + // Relocate the field with the PC relative offset of the pair of + // GOT entries. + RelocFuncs::pcrel32(view, got_entry, address); + return ArmRelocFuncs::STATUS_OKAY; + } + } + break; + + case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic + if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the module index. + unsigned int got_offset; + got_offset = (target->got_mod_index_entry(NULL, NULL, NULL) + - target->got_size()); + Arm_address got_entry = + target->got_plt_section()->address() + got_offset; + + // Relocate the field with the PC relative offset of the pair of + // GOT entries. + RelocFuncs::pcrel32(view, got_entry, address); + return ArmRelocFuncs::STATUS_OKAY; + } + break; + + case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic + RelocFuncs::rel32(view, value); + return ArmRelocFuncs::STATUS_OKAY; + + case elfcpp::R_ARM_TLS_IE32: // Initial-exec + if (optimized_type == tls::TLSOPT_NONE) + { + // Relocate the field with the offset of the GOT entry for + // the tp-relative offset of the symbol. + unsigned int got_type = GOT_TYPE_TLS_OFFSET; + unsigned int got_offset; + if (gsym != NULL) + { + gold_assert(gsym->has_got_offset(got_type)); + got_offset = gsym->got_offset(got_type); + } + else + { + unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info()); + gold_assert(object->local_has_got_offset(r_sym, got_type)); + got_offset = object->local_got_offset(r_sym, got_type); + } + + // All GOT offsets are relative to the end of the GOT. + got_offset -= target->got_size(); + + Arm_address got_entry = + target->got_plt_section()->address() + got_offset; + + // Relocate the field with the PC relative offset of the GOT entry. + RelocFuncs::pcrel32(view, got_entry, address); + return ArmRelocFuncs::STATUS_OKAY; + } + break; + + case elfcpp::R_ARM_TLS_LE32: // Local-exec + // If we're creating a shared library, a dynamic relocation will + // have been created for this location, so do not apply it now. + if (!parameters->options().shared()) + { + gold_assert(tls_segment != NULL); + + // $tp points to the TCB, which is followed by the TLS, so we + // need to add TCB size to the offset. + Arm_address aligned_tcb_size = + align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment()); + RelocFuncs::rel32(view, value + aligned_tcb_size); + + } + return ArmRelocFuncs::STATUS_OKAY; + + default: + gold_unreachable(); + } + + gold_error_at_location(relinfo, relnum, rel.get_r_offset(), + _("unsupported reloc %u"), + r_type); + return ArmRelocFuncs::STATUS_BAD_RELOC; +} + +// Relocate section data. + +template<bool big_endian> +void +Target_arm<big_endian>::relocate_section( + const Relocate_info<32, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + Arm_address address, + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) +{ + typedef typename Target_arm<big_endian>::Relocate Arm_relocate; + gold_assert(sh_type == elfcpp::SHT_REL); + + // See if we are relocating a relaxed input section. If so, the view + // covers the whole output section and we need to adjust accordingly. + if (needs_special_offset_handling) + { + const Output_relaxed_input_section* poris = + output_section->find_relaxed_input_section(relinfo->object, + relinfo->data_shndx); + if (poris != NULL) + { + Arm_address section_address = poris->address(); + section_size_type section_size = poris->data_size(); + + gold_assert((section_address >= address) + && ((section_address + section_size) + <= (address + view_size))); + + off_t offset = section_address - address; + view += offset; + address += offset; + view_size = section_size; + } + } + + gold::relocate_section<32, big_endian, Target_arm, elfcpp::SHT_REL, + Arm_relocate>( + relinfo, + this, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + address, + view_size, + reloc_symbol_changes); +} + +// Return the size of a relocation while scanning during a relocatable +// link. + +template<bool big_endian> +unsigned int +Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc( + unsigned int r_type, + Relobj* object) +{ + r_type = get_real_reloc_type(r_type); + const Arm_reloc_property* arp = + arm_reloc_property_table->get_implemented_static_reloc_property(r_type); + if (arp != NULL) + return arp->size(); + else + { + std::string reloc_name = + arm_reloc_property_table->reloc_name_in_error_message(r_type); + gold_error(_("%s: unexpected %s in object file"), + object->name().c_str(), reloc_name.c_str()); + return 0; + } +} + +// Scan the relocs during a relocatable link. + +template<bool big_endian> +void +Target_arm<big_endian>::scan_relocatable_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols, + Relocatable_relocs* rr) +{ + gold_assert(sh_type == elfcpp::SHT_REL); + + typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_REL, + Relocatable_size_for_reloc> Scan_relocatable_relocs; + + gold::scan_relocatable_relocs<32, big_endian, elfcpp::SHT_REL, + Scan_relocatable_relocs>( + symtab, + layout, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols, + rr); +} + +// Relocate a section during a relocatable link. + +template<bool big_endian> +void +Target_arm<big_endian>::relocate_for_relocatable( + const Relocate_info<32, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + off_t offset_in_output_section, + const Relocatable_relocs* rr, + unsigned char* view, + Arm_address view_address, + section_size_type view_size, + unsigned char* reloc_view, + section_size_type reloc_view_size) +{ + gold_assert(sh_type == elfcpp::SHT_REL); + + gold::relocate_for_relocatable<32, big_endian, elfcpp::SHT_REL>( + relinfo, + prelocs, + reloc_count, + output_section, + offset_in_output_section, + rr, + view, + view_address, + view_size, + reloc_view, + reloc_view_size); +} + +// Return the value to use for a dynamic symbol which requires special +// treatment. This is how we support equality comparisons of function +// pointers across shared library boundaries, as described in the +// processor specific ABI supplement. + +template<bool big_endian> +uint64_t +Target_arm<big_endian>::do_dynsym_value(const Symbol* gsym) const +{ + gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset()); + return this->plt_section()->address() + gsym->plt_offset(); +} + +// Map platform-specific relocs to real relocs +// +template<bool big_endian> +unsigned int +Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type) +{ + switch (r_type) + { + case elfcpp::R_ARM_TARGET1: + // This is either R_ARM_ABS32 or R_ARM_REL32; + return elfcpp::R_ARM_ABS32; + + case elfcpp::R_ARM_TARGET2: + // This can be any reloc type but ususally is R_ARM_GOT_PREL + return elfcpp::R_ARM_GOT_PREL; + + default: + return r_type; + } +} + +// Whether if two EABI versions V1 and V2 are compatible. + +template<bool big_endian> +bool +Target_arm<big_endian>::are_eabi_versions_compatible( + elfcpp::Elf_Word v1, + elfcpp::Elf_Word v2) +{ + // v4 and v5 are the same spec before and after it was released, + // so allow mixing them. + if ((v1 == elfcpp::EF_ARM_EABI_VER4 && v2 == elfcpp::EF_ARM_EABI_VER5) + || (v1 == elfcpp::EF_ARM_EABI_VER5 && v2 == elfcpp::EF_ARM_EABI_VER4)) + return true; + + return v1 == v2; +} + +// Combine FLAGS from an input object called NAME and the processor-specific +// flags in the ELF header of the output. Much of this is adapted from the +// processor-specific flags merging code in elf32_arm_merge_private_bfd_data +// in bfd/elf32-arm.c. + +template<bool big_endian> +void +Target_arm<big_endian>::merge_processor_specific_flags( + const std::string& name, + elfcpp::Elf_Word flags) +{ + if (this->are_processor_specific_flags_set()) + { + elfcpp::Elf_Word out_flags = this->processor_specific_flags(); + + // Nothing to merge if flags equal to those in output. + if (flags == out_flags) + return; + + // Complain about various flag mismatches. + elfcpp::Elf_Word version1 = elfcpp::arm_eabi_version(flags); + elfcpp::Elf_Word version2 = elfcpp::arm_eabi_version(out_flags); + if (!this->are_eabi_versions_compatible(version1, version2) + && parameters->options().warn_mismatch()) + gold_error(_("Source object %s has EABI version %d but output has " + "EABI version %d."), + name.c_str(), + (flags & elfcpp::EF_ARM_EABIMASK) >> 24, + (out_flags & elfcpp::EF_ARM_EABIMASK) >> 24); + } + else + { + // If the input is the default architecture and had the default + // flags then do not bother setting the flags for the output + // architecture, instead allow future merges to do this. If no + // future merges ever set these flags then they will retain their + // uninitialised values, which surprise surprise, correspond + // to the default values. + if (flags == 0) + return; + + // This is the first time, just copy the flags. + // We only copy the EABI version for now. + this->set_processor_specific_flags(flags & elfcpp::EF_ARM_EABIMASK); + } +} + +// Adjust ELF file header. +template<bool big_endian> +void +Target_arm<big_endian>::do_adjust_elf_header( + unsigned char* view, + int len) const +{ + gold_assert(len == elfcpp::Elf_sizes<32>::ehdr_size); + + elfcpp::Ehdr<32, big_endian> ehdr(view); + unsigned char e_ident[elfcpp::EI_NIDENT]; + memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT); + + if (elfcpp::arm_eabi_version(this->processor_specific_flags()) + == elfcpp::EF_ARM_EABI_UNKNOWN) + e_ident[elfcpp::EI_OSABI] = elfcpp::ELFOSABI_ARM; + else + e_ident[elfcpp::EI_OSABI] = 0; + e_ident[elfcpp::EI_ABIVERSION] = 0; + + // FIXME: Do EF_ARM_BE8 adjustment. + + elfcpp::Ehdr_write<32, big_endian> oehdr(view); + oehdr.put_e_ident(e_ident); +} + +// do_make_elf_object to override the same function in the base class. +// We need to use a target-specific sub-class of Sized_relobj<32, big_endian> +// to store ARM specific information. Hence we need to have our own +// ELF object creation. + +template<bool big_endian> +Object* +Target_arm<big_endian>::do_make_elf_object( + const std::string& name, + Input_file* input_file, + off_t offset, const elfcpp::Ehdr<32, big_endian>& ehdr) +{ + int et = ehdr.get_e_type(); + if (et == elfcpp::ET_REL) + { + Arm_relobj<big_endian>* obj = + new Arm_relobj<big_endian>(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else if (et == elfcpp::ET_DYN) + { + Sized_dynobj<32, big_endian>* obj = + new Arm_dynobj<big_endian>(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else + { + gold_error(_("%s: unsupported ELF file type %d"), + name.c_str(), et); + return NULL; + } +} + +// Read the architecture from the Tag_also_compatible_with attribute, if any. +// Returns -1 if no architecture could be read. +// This is adapted from get_secondary_compatible_arch() in bfd/elf32-arm.c. + +template<bool big_endian> +int +Target_arm<big_endian>::get_secondary_compatible_arch( + const Attributes_section_data* pasd) +{ + const Object_attribute *known_attributes = + pasd->known_attributes(Object_attribute::OBJ_ATTR_PROC); + + // Note: the tag and its argument below are uleb128 values, though + // currently-defined values fit in one byte for each. + const std::string& sv = + known_attributes[elfcpp::Tag_also_compatible_with].string_value(); + if (sv.size() == 2 + && sv.data()[0] == elfcpp::Tag_CPU_arch + && (sv.data()[1] & 128) != 128) + return sv.data()[1]; + + // This tag is "safely ignorable", so don't complain if it looks funny. + return -1; +} + +// Set, or unset, the architecture of the Tag_also_compatible_with attribute. +// The tag is removed if ARCH is -1. +// This is adapted from set_secondary_compatible_arch() in bfd/elf32-arm.c. + +template<bool big_endian> +void +Target_arm<big_endian>::set_secondary_compatible_arch( + Attributes_section_data* pasd, + int arch) +{ + Object_attribute *known_attributes = + pasd->known_attributes(Object_attribute::OBJ_ATTR_PROC); + + if (arch == -1) + { + known_attributes[elfcpp::Tag_also_compatible_with].set_string_value(""); + return; + } + + // Note: the tag and its argument below are uleb128 values, though + // currently-defined values fit in one byte for each. + char sv[3]; + sv[0] = elfcpp::Tag_CPU_arch; + gold_assert(arch != 0); + sv[1] = arch; + sv[2] = '\0'; + + known_attributes[elfcpp::Tag_also_compatible_with].set_string_value(sv); +} + +// Combine two values for Tag_CPU_arch, taking secondary compatibility tags +// into account. +// This is adapted from tag_cpu_arch_combine() in bfd/elf32-arm.c. + +template<bool big_endian> +int +Target_arm<big_endian>::tag_cpu_arch_combine( + const char* name, + int oldtag, + int* secondary_compat_out, + int newtag, + int secondary_compat) +{ +#define T(X) elfcpp::TAG_CPU_ARCH_##X + static const int v6t2[] = + { + T(V6T2), // PRE_V4. + T(V6T2), // V4. + T(V6T2), // V4T. + T(V6T2), // V5T. + T(V6T2), // V5TE. + T(V6T2), // V5TEJ. + T(V6T2), // V6. + T(V7), // V6KZ. + T(V6T2) // V6T2. + }; + static const int v6k[] = + { + T(V6K), // PRE_V4. + T(V6K), // V4. + T(V6K), // V4T. + T(V6K), // V5T. + T(V6K), // V5TE. + T(V6K), // V5TEJ. + T(V6K), // V6. + T(V6KZ), // V6KZ. + T(V7), // V6T2. + T(V6K) // V6K. + }; + static const int v7[] = + { + T(V7), // PRE_V4. + T(V7), // V4. + T(V7), // V4T. + T(V7), // V5T. + T(V7), // V5TE. + T(V7), // V5TEJ. + T(V7), // V6. + T(V7), // V6KZ. + T(V7), // V6T2. + T(V7), // V6K. + T(V7) // V7. + }; + static const int v6_m[] = + { + -1, // PRE_V4. + -1, // V4. + T(V6K), // V4T. + T(V6K), // V5T. + T(V6K), // V5TE. + T(V6K), // V5TEJ. + T(V6K), // V6. + T(V6KZ), // V6KZ. + T(V7), // V6T2. + T(V6K), // V6K. + T(V7), // V7. + T(V6_M) // V6_M. + }; + static const int v6s_m[] = + { + -1, // PRE_V4. + -1, // V4. + T(V6K), // V4T. + T(V6K), // V5T. + T(V6K), // V5TE. + T(V6K), // V5TEJ. + T(V6K), // V6. + T(V6KZ), // V6KZ. + T(V7), // V6T2. + T(V6K), // V6K. + T(V7), // V7. + T(V6S_M), // V6_M. + T(V6S_M) // V6S_M. + }; + static const int v7e_m[] = + { + -1, // PRE_V4. + -1, // V4. + T(V7E_M), // V4T. + T(V7E_M), // V5T. + T(V7E_M), // V5TE. + T(V7E_M), // V5TEJ. + T(V7E_M), // V6. + T(V7E_M), // V6KZ. + T(V7E_M), // V6T2. + T(V7E_M), // V6K. + T(V7E_M), // V7. + T(V7E_M), // V6_M. + T(V7E_M), // V6S_M. + T(V7E_M) // V7E_M. + }; + static const int v4t_plus_v6_m[] = + { + -1, // PRE_V4. + -1, // V4. + T(V4T), // V4T. + T(V5T), // V5T. + T(V5TE), // V5TE. + T(V5TEJ), // V5TEJ. + T(V6), // V6. + T(V6KZ), // V6KZ. + T(V6T2), // V6T2. + T(V6K), // V6K. + T(V7), // V7. + T(V6_M), // V6_M. + T(V6S_M), // V6S_M. + T(V7E_M), // V7E_M. + T(V4T_PLUS_V6_M) // V4T plus V6_M. + }; + static const int *comb[] = + { + v6t2, + v6k, + v7, + v6_m, + v6s_m, + v7e_m, + // Pseudo-architecture. + v4t_plus_v6_m + }; + + // Check we've not got a higher architecture than we know about. + + if (oldtag >= elfcpp::MAX_TAG_CPU_ARCH || newtag >= elfcpp::MAX_TAG_CPU_ARCH) + { + gold_error(_("%s: unknown CPU architecture"), name); + return -1; + } + + // Override old tag if we have a Tag_also_compatible_with on the output. + + if ((oldtag == T(V6_M) && *secondary_compat_out == T(V4T)) + || (oldtag == T(V4T) && *secondary_compat_out == T(V6_M))) + oldtag = T(V4T_PLUS_V6_M); + + // And override the new tag if we have a Tag_also_compatible_with on the + // input. + + if ((newtag == T(V6_M) && secondary_compat == T(V4T)) + || (newtag == T(V4T) && secondary_compat == T(V6_M))) + newtag = T(V4T_PLUS_V6_M); + + // Architectures before V6KZ add features monotonically. + int tagh = std::max(oldtag, newtag); + if (tagh <= elfcpp::TAG_CPU_ARCH_V6KZ) + return tagh; + + int tagl = std::min(oldtag, newtag); + int result = comb[tagh - T(V6T2)][tagl]; + + // Use Tag_CPU_arch == V4T and Tag_also_compatible_with (Tag_CPU_arch V6_M) + // as the canonical version. + if (result == T(V4T_PLUS_V6_M)) + { + result = T(V4T); + *secondary_compat_out = T(V6_M); + } + else + *secondary_compat_out = -1; + + if (result == -1) + { + gold_error(_("%s: conflicting CPU architectures %d/%d"), + name, oldtag, newtag); + return -1; + } + + return result; +#undef T +} + +// Helper to print AEABI enum tag value. + +template<bool big_endian> +std::string +Target_arm<big_endian>::aeabi_enum_name(unsigned int value) +{ + static const char *aeabi_enum_names[] = + { "", "variable-size", "32-bit", "" }; + const size_t aeabi_enum_names_size = + sizeof(aeabi_enum_names) / sizeof(aeabi_enum_names[0]); + + if (value < aeabi_enum_names_size) + return std::string(aeabi_enum_names[value]); + else + { + char buffer[100]; + sprintf(buffer, "<unknown value %u>", value); + return std::string(buffer); + } +} + +// Return the string value to store in TAG_CPU_name. + +template<bool big_endian> +std::string +Target_arm<big_endian>::tag_cpu_name_value(unsigned int value) +{ + static const char *name_table[] = { + // These aren't real CPU names, but we can't guess + // that from the architecture version alone. + "Pre v4", + "ARM v4", + "ARM v4T", + "ARM v5T", + "ARM v5TE", + "ARM v5TEJ", + "ARM v6", + "ARM v6KZ", + "ARM v6T2", + "ARM v6K", + "ARM v7", + "ARM v6-M", + "ARM v6S-M", + "ARM v7E-M" + }; + const size_t name_table_size = sizeof(name_table) / sizeof(name_table[0]); + + if (value < name_table_size) + return std::string(name_table[value]); + else + { + char buffer[100]; + sprintf(buffer, "<unknown CPU value %u>", value); + return std::string(buffer); + } +} + +// Merge object attributes from input file called NAME with those of the +// output. The input object attributes are in the object pointed by PASD. + +template<bool big_endian> +void +Target_arm<big_endian>::merge_object_attributes( + const char* name, + const Attributes_section_data* pasd) +{ + // Return if there is no attributes section data. + if (pasd == NULL) + return; + + // If output has no object attributes, just copy. + if (this->attributes_section_data_ == NULL) + { + this->attributes_section_data_ = new Attributes_section_data(*pasd); + return; + } + + const int vendor = Object_attribute::OBJ_ATTR_PROC; + const Object_attribute* in_attr = pasd->known_attributes(vendor); + Object_attribute* out_attr = + this->attributes_section_data_->known_attributes(vendor); + + // This needs to happen before Tag_ABI_FP_number_model is merged. */ + if (in_attr[elfcpp::Tag_ABI_VFP_args].int_value() + != out_attr[elfcpp::Tag_ABI_VFP_args].int_value()) + { + // Ignore mismatches if the object doesn't use floating point. */ + if (out_attr[elfcpp::Tag_ABI_FP_number_model].int_value() == 0) + out_attr[elfcpp::Tag_ABI_VFP_args].set_int_value( + in_attr[elfcpp::Tag_ABI_VFP_args].int_value()); + else if (in_attr[elfcpp::Tag_ABI_FP_number_model].int_value() != 0 + && parameters->options().warn_mismatch()) + gold_error(_("%s uses VFP register arguments, output does not"), + name); + } + + for (int i = 4; i < Vendor_object_attributes::NUM_KNOWN_ATTRIBUTES; ++i) + { + // Merge this attribute with existing attributes. + switch (i) + { + case elfcpp::Tag_CPU_raw_name: + case elfcpp::Tag_CPU_name: + // These are merged after Tag_CPU_arch. + break; + + case elfcpp::Tag_ABI_optimization_goals: + case elfcpp::Tag_ABI_FP_optimization_goals: + // Use the first value seen. + break; + + case elfcpp::Tag_CPU_arch: + { + unsigned int saved_out_attr = out_attr->int_value(); + // Merge Tag_CPU_arch and Tag_also_compatible_with. + int secondary_compat = + this->get_secondary_compatible_arch(pasd); + int secondary_compat_out = + this->get_secondary_compatible_arch( + this->attributes_section_data_); + out_attr[i].set_int_value( + tag_cpu_arch_combine(name, out_attr[i].int_value(), + &secondary_compat_out, + in_attr[i].int_value(), + secondary_compat)); + this->set_secondary_compatible_arch(this->attributes_section_data_, + secondary_compat_out); + + // Merge Tag_CPU_name and Tag_CPU_raw_name. + if (out_attr[i].int_value() == saved_out_attr) + ; // Leave the names alone. + else if (out_attr[i].int_value() == in_attr[i].int_value()) + { + // The output architecture has been changed to match the + // input architecture. Use the input names. + out_attr[elfcpp::Tag_CPU_name].set_string_value( + in_attr[elfcpp::Tag_CPU_name].string_value()); + out_attr[elfcpp::Tag_CPU_raw_name].set_string_value( + in_attr[elfcpp::Tag_CPU_raw_name].string_value()); + } + else + { + out_attr[elfcpp::Tag_CPU_name].set_string_value(""); + out_attr[elfcpp::Tag_CPU_raw_name].set_string_value(""); + } + + // If we still don't have a value for Tag_CPU_name, + // make one up now. Tag_CPU_raw_name remains blank. + if (out_attr[elfcpp::Tag_CPU_name].string_value() == "") + { + const std::string cpu_name = + this->tag_cpu_name_value(out_attr[i].int_value()); + // FIXME: If we see an unknown CPU, this will be set + // to "<unknown CPU n>", where n is the attribute value. + // This is different from BFD, which leaves the name alone. + out_attr[elfcpp::Tag_CPU_name].set_string_value(cpu_name); + } + } + break; + + case elfcpp::Tag_ARM_ISA_use: + case elfcpp::Tag_THUMB_ISA_use: + case elfcpp::Tag_WMMX_arch: + case elfcpp::Tag_Advanced_SIMD_arch: + // ??? Do Advanced_SIMD (NEON) and WMMX conflict? + case elfcpp::Tag_ABI_FP_rounding: + case elfcpp::Tag_ABI_FP_exceptions: + case elfcpp::Tag_ABI_FP_user_exceptions: + case elfcpp::Tag_ABI_FP_number_model: + case elfcpp::Tag_VFP_HP_extension: + case elfcpp::Tag_CPU_unaligned_access: + case elfcpp::Tag_T2EE_use: + case elfcpp::Tag_Virtualization_use: + case elfcpp::Tag_MPextension_use: + // Use the largest value specified. + if (in_attr[i].int_value() > out_attr[i].int_value()) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + + case elfcpp::Tag_ABI_align8_preserved: + case elfcpp::Tag_ABI_PCS_RO_data: + // Use the smallest value specified. + if (in_attr[i].int_value() < out_attr[i].int_value()) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + + case elfcpp::Tag_ABI_align8_needed: + if ((in_attr[i].int_value() > 0 || out_attr[i].int_value() > 0) + && (in_attr[elfcpp::Tag_ABI_align8_preserved].int_value() == 0 + || (out_attr[elfcpp::Tag_ABI_align8_preserved].int_value() + == 0))) + { + // This error message should be enabled once all non-conformant + // binaries in the toolchain have had the attributes set + // properly. + // gold_error(_("output 8-byte data alignment conflicts with %s"), + // name); + } + // Fall through. + case elfcpp::Tag_ABI_FP_denormal: + case elfcpp::Tag_ABI_PCS_GOT_use: + { + // These tags have 0 = don't care, 1 = strong requirement, + // 2 = weak requirement. + static const int order_021[3] = {0, 2, 1}; + + // Use the "greatest" from the sequence 0, 2, 1, or the largest + // value if greater than 2 (for future-proofing). + if ((in_attr[i].int_value() > 2 + && in_attr[i].int_value() > out_attr[i].int_value()) + || (in_attr[i].int_value() <= 2 + && out_attr[i].int_value() <= 2 + && (order_021[in_attr[i].int_value()] + > order_021[out_attr[i].int_value()]))) + out_attr[i].set_int_value(in_attr[i].int_value()); + } + break; + + case elfcpp::Tag_CPU_arch_profile: + if (out_attr[i].int_value() != in_attr[i].int_value()) + { + // 0 will merge with anything. + // 'A' and 'S' merge to 'A'. + // 'R' and 'S' merge to 'R'. + // 'M' and 'A|R|S' is an error. + if (out_attr[i].int_value() == 0 + || (out_attr[i].int_value() == 'S' + && (in_attr[i].int_value() == 'A' + || in_attr[i].int_value() == 'R'))) + out_attr[i].set_int_value(in_attr[i].int_value()); + else if (in_attr[i].int_value() == 0 + || (in_attr[i].int_value() == 'S' + && (out_attr[i].int_value() == 'A' + || out_attr[i].int_value() == 'R'))) + ; // Do nothing. + else if (parameters->options().warn_mismatch()) + { + gold_error + (_("conflicting architecture profiles %c/%c"), + in_attr[i].int_value() ? in_attr[i].int_value() : '0', + out_attr[i].int_value() ? out_attr[i].int_value() : '0'); + } + } + break; + case elfcpp::Tag_VFP_arch: + { + static const struct + { + int ver; + int regs; + } vfp_versions[7] = + { + {0, 0}, + {1, 16}, + {2, 16}, + {3, 32}, + {3, 16}, + {4, 32}, + {4, 16} + }; + + // Values greater than 6 aren't defined, so just pick the + // biggest. + if (in_attr[i].int_value() > 6 + && in_attr[i].int_value() > out_attr[i].int_value()) + { + *out_attr = *in_attr; + break; + } + // The output uses the superset of input features + // (ISA version) and registers. + int ver = std::max(vfp_versions[in_attr[i].int_value()].ver, + vfp_versions[out_attr[i].int_value()].ver); + int regs = std::max(vfp_versions[in_attr[i].int_value()].regs, + vfp_versions[out_attr[i].int_value()].regs); + // This assumes all possible supersets are also a valid + // options. + int newval; + for (newval = 6; newval > 0; newval--) + { + if (regs == vfp_versions[newval].regs + && ver == vfp_versions[newval].ver) + break; + } + out_attr[i].set_int_value(newval); + } + break; + case elfcpp::Tag_PCS_config: + if (out_attr[i].int_value() == 0) + out_attr[i].set_int_value(in_attr[i].int_value()); + else if (in_attr[i].int_value() != 0 + && out_attr[i].int_value() != 0 + && parameters->options().warn_mismatch()) + { + // It's sometimes ok to mix different configs, so this is only + // a warning. + gold_warning(_("%s: conflicting platform configuration"), name); + } + break; + case elfcpp::Tag_ABI_PCS_R9_use: + if (in_attr[i].int_value() != out_attr[i].int_value() + && out_attr[i].int_value() != elfcpp::AEABI_R9_unused + && in_attr[i].int_value() != elfcpp::AEABI_R9_unused + && parameters->options().warn_mismatch()) + { + gold_error(_("%s: conflicting use of R9"), name); + } + if (out_attr[i].int_value() == elfcpp::AEABI_R9_unused) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + case elfcpp::Tag_ABI_PCS_RW_data: + if (in_attr[i].int_value() == elfcpp::AEABI_PCS_RW_data_SBrel + && (in_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value() + != elfcpp::AEABI_R9_SB) + && (out_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value() + != elfcpp::AEABI_R9_unused) + && parameters->options().warn_mismatch()) + { + gold_error(_("%s: SB relative addressing conflicts with use " + "of R9"), + name); + } + // Use the smallest value specified. + if (in_attr[i].int_value() < out_attr[i].int_value()) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + case elfcpp::Tag_ABI_PCS_wchar_t: + // FIXME: Make it possible to turn off this warning. + if (out_attr[i].int_value() + && in_attr[i].int_value() + && out_attr[i].int_value() != in_attr[i].int_value() + && parameters->options().warn_mismatch()) + { + gold_warning(_("%s uses %u-byte wchar_t yet the output is to " + "use %u-byte wchar_t; use of wchar_t values " + "across objects may fail"), + name, in_attr[i].int_value(), + out_attr[i].int_value()); + } + else if (in_attr[i].int_value() && !out_attr[i].int_value()) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + case elfcpp::Tag_ABI_enum_size: + if (in_attr[i].int_value() != elfcpp::AEABI_enum_unused) + { + if (out_attr[i].int_value() == elfcpp::AEABI_enum_unused + || out_attr[i].int_value() == elfcpp::AEABI_enum_forced_wide) + { + // The existing object is compatible with anything. + // Use whatever requirements the new object has. + out_attr[i].set_int_value(in_attr[i].int_value()); + } + // FIXME: Make it possible to turn off this warning. + else if (in_attr[i].int_value() != elfcpp::AEABI_enum_forced_wide + && out_attr[i].int_value() != in_attr[i].int_value() + && parameters->options().warn_mismatch()) + { + unsigned int in_value = in_attr[i].int_value(); + unsigned int out_value = out_attr[i].int_value(); + gold_warning(_("%s uses %s enums yet the output is to use " + "%s enums; use of enum values across objects " + "may fail"), + name, + this->aeabi_enum_name(in_value).c_str(), + this->aeabi_enum_name(out_value).c_str()); + } + } + break; + case elfcpp::Tag_ABI_VFP_args: + // Aready done. + break; + case elfcpp::Tag_ABI_WMMX_args: + if (in_attr[i].int_value() != out_attr[i].int_value() + && parameters->options().warn_mismatch()) + { + gold_error(_("%s uses iWMMXt register arguments, output does " + "not"), + name); + } + break; + case Object_attribute::Tag_compatibility: + // Merged in target-independent code. + break; + case elfcpp::Tag_ABI_HardFP_use: + // 1 (SP) and 2 (DP) conflict, so combine to 3 (SP & DP). + if ((in_attr[i].int_value() == 1 && out_attr[i].int_value() == 2) + || (in_attr[i].int_value() == 2 && out_attr[i].int_value() == 1)) + out_attr[i].set_int_value(3); + else if (in_attr[i].int_value() > out_attr[i].int_value()) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + case elfcpp::Tag_ABI_FP_16bit_format: + if (in_attr[i].int_value() != 0 && out_attr[i].int_value() != 0) + { + if (in_attr[i].int_value() != out_attr[i].int_value() + && parameters->options().warn_mismatch()) + gold_error(_("fp16 format mismatch between %s and output"), + name); + } + if (in_attr[i].int_value() != 0) + out_attr[i].set_int_value(in_attr[i].int_value()); + break; + + case elfcpp::Tag_nodefaults: + // This tag is set if it exists, but the value is unused (and is + // typically zero). We don't actually need to do anything here - + // the merge happens automatically when the type flags are merged + // below. + break; + case elfcpp::Tag_also_compatible_with: + // Already done in Tag_CPU_arch. + break; + case elfcpp::Tag_conformance: + // Keep the attribute if it matches. Throw it away otherwise. + // No attribute means no claim to conform. + if (in_attr[i].string_value() != out_attr[i].string_value()) + out_attr[i].set_string_value(""); + break; + + default: + { + const char* err_object = NULL; + + // The "known_obj_attributes" table does contain some undefined + // attributes. Ensure that there are unused. + if (out_attr[i].int_value() != 0 + || out_attr[i].string_value() != "") + err_object = "output"; + else if (in_attr[i].int_value() != 0 + || in_attr[i].string_value() != "") + err_object = name; + + if (err_object != NULL + && parameters->options().warn_mismatch()) + { + // Attribute numbers >=64 (mod 128) can be safely ignored. + if ((i & 127) < 64) + gold_error(_("%s: unknown mandatory EABI object attribute " + "%d"), + err_object, i); + else + gold_warning(_("%s: unknown EABI object attribute %d"), + err_object, i); + } + + // Only pass on attributes that match in both inputs. + if (!in_attr[i].matches(out_attr[i])) + { + out_attr[i].set_int_value(0); + out_attr[i].set_string_value(""); + } + } + } + + // If out_attr was copied from in_attr then it won't have a type yet. + if (in_attr[i].type() && !out_attr[i].type()) + out_attr[i].set_type(in_attr[i].type()); + } + + // Merge Tag_compatibility attributes and any common GNU ones. + this->attributes_section_data_->merge(name, pasd); + + // Check for any attributes not known on ARM. + typedef Vendor_object_attributes::Other_attributes Other_attributes; + const Other_attributes* in_other_attributes = pasd->other_attributes(vendor); + Other_attributes::const_iterator in_iter = in_other_attributes->begin(); + Other_attributes* out_other_attributes = + this->attributes_section_data_->other_attributes(vendor); + Other_attributes::iterator out_iter = out_other_attributes->begin(); + + while (in_iter != in_other_attributes->end() + || out_iter != out_other_attributes->end()) + { + const char* err_object = NULL; + int err_tag = 0; + + // The tags for each list are in numerical order. + // If the tags are equal, then merge. + if (out_iter != out_other_attributes->end() + && (in_iter == in_other_attributes->end() + || in_iter->first > out_iter->first)) + { + // This attribute only exists in output. We can't merge, and we + // don't know what the tag means, so delete it. + err_object = "output"; + err_tag = out_iter->first; + int saved_tag = out_iter->first; + delete out_iter->second; + out_other_attributes->erase(out_iter); + out_iter = out_other_attributes->upper_bound(saved_tag); + } + else if (in_iter != in_other_attributes->end() + && (out_iter != out_other_attributes->end() + || in_iter->first < out_iter->first)) + { + // This attribute only exists in input. We can't merge, and we + // don't know what the tag means, so ignore it. + err_object = name; + err_tag = in_iter->first; + ++in_iter; + } + else // The tags are equal. + { + // As present, all attributes in the list are unknown, and + // therefore can't be merged meaningfully. + err_object = "output"; + err_tag = out_iter->first; + + // Only pass on attributes that match in both inputs. + if (!in_iter->second->matches(*(out_iter->second))) + { + // No match. Delete the attribute. + int saved_tag = out_iter->first; + delete out_iter->second; + out_other_attributes->erase(out_iter); + out_iter = out_other_attributes->upper_bound(saved_tag); + } + else + { + // Matched. Keep the attribute and move to the next. + ++out_iter; + ++in_iter; + } + } + + if (err_object && parameters->options().warn_mismatch()) + { + // Attribute numbers >=64 (mod 128) can be safely ignored. */ + if ((err_tag & 127) < 64) + { + gold_error(_("%s: unknown mandatory EABI object attribute %d"), + err_object, err_tag); + } + else + { + gold_warning(_("%s: unknown EABI object attribute %d"), + err_object, err_tag); + } + } + } +} + +// Stub-generation methods for Target_arm. + +// Make a new Arm_input_section object. + +template<bool big_endian> +Arm_input_section<big_endian>* +Target_arm<big_endian>::new_arm_input_section( + Relobj* relobj, + unsigned int shndx) +{ + Section_id sid(relobj, shndx); + + Arm_input_section<big_endian>* arm_input_section = + new Arm_input_section<big_endian>(relobj, shndx); + arm_input_section->init(); + + // Register new Arm_input_section in map for look-up. + std::pair<typename Arm_input_section_map::iterator, bool> ins = + this->arm_input_section_map_.insert(std::make_pair(sid, arm_input_section)); + + // Make sure that it we have not created another Arm_input_section + // for this input section already. + gold_assert(ins.second); + + return arm_input_section; +} + +// Find the Arm_input_section object corresponding to the SHNDX-th input +// section of RELOBJ. + +template<bool big_endian> +Arm_input_section<big_endian>* +Target_arm<big_endian>::find_arm_input_section( + Relobj* relobj, + unsigned int shndx) const +{ + Section_id sid(relobj, shndx); + typename Arm_input_section_map::const_iterator p = + this->arm_input_section_map_.find(sid); + return (p != this->arm_input_section_map_.end()) ? p->second : NULL; +} + +// Make a new stub table. + +template<bool big_endian> +Stub_table<big_endian>* +Target_arm<big_endian>::new_stub_table(Arm_input_section<big_endian>* owner) +{ + Stub_table<big_endian>* stub_table = + new Stub_table<big_endian>(owner); + this->stub_tables_.push_back(stub_table); + + stub_table->set_address(owner->address() + owner->data_size()); + stub_table->set_file_offset(owner->offset() + owner->data_size()); + stub_table->finalize_data_size(); + + return stub_table; +} + +// Scan a relocation for stub generation. + +template<bool big_endian> +void +Target_arm<big_endian>::scan_reloc_for_stub( + const Relocate_info<32, big_endian>* relinfo, + unsigned int r_type, + const Sized_symbol<32>* gsym, + unsigned int r_sym, + const Symbol_value<32>* psymval, + elfcpp::Elf_types<32>::Elf_Swxword addend, + Arm_address address) +{ + typedef typename Target_arm<big_endian>::Relocate Relocate; + + const Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(relinfo->object); + + bool target_is_thumb; + Symbol_value<32> symval; + if (gsym != NULL) + { + // This is a global symbol. Determine if we use PLT and if the + // final target is THUMB. + if (gsym->use_plt_offset(Relocate::reloc_is_non_pic(r_type))) + { + // This uses a PLT, change the symbol value. + symval.set_output_value(this->plt_section()->address() + + gsym->plt_offset()); + psymval = &symval; + target_is_thumb = false; + } + else if (gsym->is_undefined()) + // There is no need to generate a stub symbol is undefined. + return; + else + { + target_is_thumb = + ((gsym->type() == elfcpp::STT_ARM_TFUNC) + || (gsym->type() == elfcpp::STT_FUNC + && !gsym->is_undefined() + && ((psymval->value(arm_relobj, 0) & 1) != 0))); + } + } + else + { + // This is a local symbol. Determine if the final target is THUMB. + target_is_thumb = arm_relobj->local_symbol_is_thumb_function(r_sym); + } + + // Strip LSB if this points to a THUMB target. + const Arm_reloc_property* reloc_property = + arm_reloc_property_table->get_implemented_static_reloc_property(r_type); + gold_assert(reloc_property != NULL); + if (target_is_thumb + && reloc_property->uses_thumb_bit() + && ((psymval->value(arm_relobj, 0) & 1) != 0)) + { + Arm_address stripped_value = + psymval->value(arm_relobj, 0) & ~static_cast<Arm_address>(1); + symval.set_output_value(stripped_value); + psymval = &symval; + } + + // Get the symbol value. + Symbol_value<32>::Value value = psymval->value(arm_relobj, 0); + + // Owing to pipelining, the PC relative branches below actually skip + // two instructions when the branch offset is 0. + Arm_address destination; + switch (r_type) + { + case elfcpp::R_ARM_CALL: + case elfcpp::R_ARM_JUMP24: + case elfcpp::R_ARM_PLT32: + // ARM branches. + destination = value + addend + 8; + break; + case elfcpp::R_ARM_THM_CALL: + case elfcpp::R_ARM_THM_XPC22: + case elfcpp::R_ARM_THM_JUMP24: + case elfcpp::R_ARM_THM_JUMP19: + // THUMB branches. + destination = value + addend + 4; + break; + default: + gold_unreachable(); + } + + Reloc_stub* stub = NULL; + Stub_type stub_type = + Reloc_stub::stub_type_for_reloc(r_type, address, destination, + target_is_thumb); + if (stub_type != arm_stub_none) + { + // Try looking up an existing stub from a stub table. + Stub_table<big_endian>* stub_table = + arm_relobj->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + // Locate stub by destination. + Reloc_stub::Key stub_key(stub_type, gsym, arm_relobj, r_sym, addend); + + // Create a stub if there is not one already + stub = stub_table->find_reloc_stub(stub_key); + if (stub == NULL) + { + // create a new stub and add it to stub table. + stub = this->stub_factory().make_reloc_stub(stub_type); + stub_table->add_reloc_stub(stub, stub_key); + } + + // Record the destination address. + stub->set_destination_address(destination + | (target_is_thumb ? 1 : 0)); + } + + // For Cortex-A8, we need to record a relocation at 4K page boundary. + if (this->fix_cortex_a8_ + && (r_type == elfcpp::R_ARM_THM_JUMP24 + || r_type == elfcpp::R_ARM_THM_JUMP19 + || r_type == elfcpp::R_ARM_THM_CALL + || r_type == elfcpp::R_ARM_THM_XPC22) + && (address & 0xfffU) == 0xffeU) + { + // Found a candidate. Note we haven't checked the destination is + // within 4K here: if we do so (and don't create a record) we can't + // tell that a branch should have been relocated when scanning later. + this->cortex_a8_relocs_info_[address] = + new Cortex_a8_reloc(stub, r_type, + destination | (target_is_thumb ? 1 : 0)); + } +} + +// This function scans a relocation sections for stub generation. +// The template parameter Relocate must be a class type which provides +// a single function, relocate(), which implements the machine +// specific part of a relocation. + +// BIG_ENDIAN is the endianness of the data. SH_TYPE is the section type: +// SHT_REL or SHT_RELA. + +// PRELOCS points to the relocation data. RELOC_COUNT is the number +// of relocs. OUTPUT_SECTION is the output section. +// NEEDS_SPECIAL_OFFSET_HANDLING is true if input offsets need to be +// mapped to output offsets. + +// VIEW is the section data, VIEW_ADDRESS is its memory address, and +// VIEW_SIZE is the size. These refer to the input section, unless +// NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to +// the output section. + +template<bool big_endian> +template<int sh_type> +void inline +Target_arm<big_endian>::scan_reloc_section_for_stubs( + const Relocate_info<32, big_endian>* relinfo, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + const unsigned char* view, + elfcpp::Elf_types<32>::Elf_Addr view_address, + section_size_type) +{ + typedef typename Reloc_types<sh_type, 32, big_endian>::Reloc Reltype; + const int reloc_size = + Reloc_types<sh_type, 32, big_endian>::reloc_size; + + Arm_relobj<big_endian>* arm_object = + Arm_relobj<big_endian>::as_arm_relobj(relinfo->object); + unsigned int local_count = arm_object->local_symbol_count(); + + Comdat_behavior comdat_behavior = CB_UNDETERMINED; + + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) + { + Reltype reloc(prelocs); + + typename elfcpp::Elf_types<32>::Elf_WXword r_info = reloc.get_r_info(); + unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info); + unsigned int r_type = elfcpp::elf_r_type<32>(r_info); + + r_type = this->get_real_reloc_type(r_type); + + // Only a few relocation types need stubs. + if ((r_type != elfcpp::R_ARM_CALL) + && (r_type != elfcpp::R_ARM_JUMP24) + && (r_type != elfcpp::R_ARM_PLT32) + && (r_type != elfcpp::R_ARM_THM_CALL) + && (r_type != elfcpp::R_ARM_THM_XPC22) + && (r_type != elfcpp::R_ARM_THM_JUMP24) + && (r_type != elfcpp::R_ARM_THM_JUMP19) + && (r_type != elfcpp::R_ARM_V4BX)) + continue; + + section_offset_type offset = + convert_to_section_size_type(reloc.get_r_offset()); + + if (needs_special_offset_handling) + { + offset = output_section->output_offset(relinfo->object, + relinfo->data_shndx, + offset); + if (offset == -1) + continue; + } + + // Create a v4bx stub if --fix-v4bx-interworking is used. + if (r_type == elfcpp::R_ARM_V4BX) + { + if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING) + { + // Get the BX instruction. + typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype; + const Valtype* wv = + reinterpret_cast<const Valtype*>(view + offset); + elfcpp::Elf_types<32>::Elf_Swxword insn = + elfcpp::Swap<32, big_endian>::readval(wv); + const uint32_t reg = (insn & 0xf); + + if (reg < 0xf) + { + // Try looking up an existing stub from a stub table. + Stub_table<big_endian>* stub_table = + arm_object->stub_table(relinfo->data_shndx); + gold_assert(stub_table != NULL); + + if (stub_table->find_arm_v4bx_stub(reg) == NULL) + { + // create a new stub and add it to stub table. + Arm_v4bx_stub* stub = + this->stub_factory().make_arm_v4bx_stub(reg); + gold_assert(stub != NULL); + stub_table->add_arm_v4bx_stub(stub); + } + } + } + continue; + } + + // Get the addend. + Stub_addend_reader<sh_type, big_endian> stub_addend_reader; + elfcpp::Elf_types<32>::Elf_Swxword addend = + stub_addend_reader(r_type, view + offset, reloc); + + const Sized_symbol<32>* sym; + + Symbol_value<32> symval; + const Symbol_value<32> *psymval; + if (r_sym < local_count) + { + sym = NULL; + psymval = arm_object->local_symbol(r_sym); + + // If the local symbol belongs to a section we are discarding, + // and that section is a debug section, try to find the + // corresponding kept section and map this symbol to its + // counterpart in the kept section. The symbol must not + // correspond to a section we are folding. + bool is_ordinary; + unsigned int shndx = psymval->input_shndx(&is_ordinary); + if (is_ordinary + && shndx != elfcpp::SHN_UNDEF + && !arm_object->is_section_included(shndx) + && !(relinfo->symtab->is_section_folded(arm_object, shndx))) + { + if (comdat_behavior == CB_UNDETERMINED) + { + std::string name = + arm_object->section_name(relinfo->data_shndx); + comdat_behavior = get_comdat_behavior(name.c_str()); + } + if (comdat_behavior == CB_PRETEND) + { + bool found; + typename elfcpp::Elf_types<32>::Elf_Addr value = + arm_object->map_to_kept_section(shndx, &found); + if (found) + symval.set_output_value(value + psymval->input_value()); + else + symval.set_output_value(0); + } + else + { + symval.set_output_value(0); + } + symval.set_no_output_symtab_entry(); + psymval = &symval; + } + } + else + { + const Symbol* gsym = arm_object->global_symbol(r_sym); + gold_assert(gsym != NULL); + if (gsym->is_forwarder()) + gsym = relinfo->symtab->resolve_forwards(gsym); + + sym = static_cast<const Sized_symbol<32>*>(gsym); + if (sym->has_symtab_index()) + symval.set_output_symtab_index(sym->symtab_index()); + else + symval.set_no_output_symtab_entry(); + + // We need to compute the would-be final value of this global + // symbol. + const Symbol_table* symtab = relinfo->symtab; + const Sized_symbol<32>* sized_symbol = + symtab->get_sized_symbol<32>(gsym); + Symbol_table::Compute_final_value_status status; + Arm_address value = + symtab->compute_final_value<32>(sized_symbol, &status); + + // Skip this if the symbol has not output section. + if (status == Symbol_table::CFVS_NO_OUTPUT_SECTION) + continue; + + symval.set_output_value(value); + psymval = &symval; + } + + // If symbol is a section symbol, we don't know the actual type of + // destination. Give up. + if (psymval->is_section_symbol()) + continue; + + this->scan_reloc_for_stub(relinfo, r_type, sym, r_sym, psymval, + addend, view_address + offset); + } +} + +// Scan an input section for stub generation. + +template<bool big_endian> +void +Target_arm<big_endian>::scan_section_for_stubs( + const Relocate_info<32, big_endian>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + const unsigned char* view, + Arm_address view_address, + section_size_type view_size) +{ + if (sh_type == elfcpp::SHT_REL) + this->scan_reloc_section_for_stubs<elfcpp::SHT_REL>( + relinfo, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + view_address, + view_size); + else if (sh_type == elfcpp::SHT_RELA) + // We do not support RELA type relocations yet. This is provided for + // completeness. + this->scan_reloc_section_for_stubs<elfcpp::SHT_RELA>( + relinfo, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + view, + view_address, + view_size); + else + gold_unreachable(); +} + +// Group input sections for stub generation. +// +// We goup input sections in an output sections so that the total size, +// including any padding space due to alignment is smaller than GROUP_SIZE +// unless the only input section in group is bigger than GROUP_SIZE already. +// Then an ARM stub table is created to follow the last input section +// in group. For each group an ARM stub table is created an is placed +// after the last group. If STUB_ALWATS_AFTER_BRANCH is false, we further +// extend the group after the stub table. + +template<bool big_endian> +void +Target_arm<big_endian>::group_sections( + Layout* layout, + section_size_type group_size, + bool stubs_always_after_branch) +{ + // Group input sections and insert stub table + Layout::Section_list section_list; + layout->get_allocated_sections(§ion_list); + for (Layout::Section_list::const_iterator p = section_list.begin(); + p != section_list.end(); + ++p) + { + Arm_output_section<big_endian>* output_section = + Arm_output_section<big_endian>::as_arm_output_section(*p); + output_section->group_sections(group_size, stubs_always_after_branch, + this); + } +} + +// Relaxation hook. This is where we do stub generation. + +template<bool big_endian> +bool +Target_arm<big_endian>::do_relax( + int pass, + const Input_objects* input_objects, + Symbol_table* symtab, + Layout* layout) +{ + // No need to generate stubs if this is a relocatable link. + gold_assert(!parameters->options().relocatable()); + + // If this is the first pass, we need to group input sections into + // stub groups. + bool done_exidx_fixup = false; + if (pass == 1) + { + // Determine the stub group size. The group size is the absolute + // value of the parameter --stub-group-size. If --stub-group-size + // is passed a negative value, we restict stubs to be always after + // the stubbed branches. + int32_t stub_group_size_param = + parameters->options().stub_group_size(); + bool stubs_always_after_branch = stub_group_size_param < 0; + section_size_type stub_group_size = abs(stub_group_size_param); + + // The Cortex-A8 erratum fix depends on stubs not being in the same 4K + // page as the first half of a 32-bit branch straddling two 4K pages. + // This is a crude way of enforcing that. + if (this->fix_cortex_a8_) + stubs_always_after_branch = true; + + if (stub_group_size == 1) + { + // Default value. + // Thumb branch range is +-4MB has to be used as the default + // maximum size (a given section can contain both ARM and Thumb + // code, so the worst case has to be taken into account). If we are + // fixing cortex-a8 errata, the branch range has to be even smaller, + // since wide conditional branch has a range of +-1MB only. + // + // This value is 24K less than that, which allows for 2025 + // 12-byte stubs. If we exceed that, then we will fail to link. + // The user will have to relink with an explicit group size + // option. + if (this->fix_cortex_a8_) + stub_group_size = 1024276; + else + stub_group_size = 4170000; + } + + group_sections(layout, stub_group_size, stubs_always_after_branch); + + // Also fix .ARM.exidx section coverage. + Output_section* os = layout->find_output_section(".ARM.exidx"); + if (os != NULL && os->type() == elfcpp::SHT_ARM_EXIDX) + { + Arm_output_section<big_endian>* exidx_output_section = + Arm_output_section<big_endian>::as_arm_output_section(os); + this->fix_exidx_coverage(layout, exidx_output_section, symtab); + done_exidx_fixup = true; + } + } + + // The Cortex-A8 stubs are sensitive to layout of code sections. At the + // beginning of each relaxation pass, just blow away all the stubs. + // Alternatively, we could selectively remove only the stubs and reloc + // information for code sections that have moved since the last pass. + // That would require more book-keeping. + typedef typename Stub_table_list::iterator Stub_table_iterator; + if (this->fix_cortex_a8_) + { + // Clear all Cortex-A8 reloc information. + for (typename Cortex_a8_relocs_info::const_iterator p = + this->cortex_a8_relocs_info_.begin(); + p != this->cortex_a8_relocs_info_.end(); + ++p) + delete p->second; + this->cortex_a8_relocs_info_.clear(); + + // Remove all Cortex-A8 stubs. + for (Stub_table_iterator sp = this->stub_tables_.begin(); + sp != this->stub_tables_.end(); + ++sp) + (*sp)->remove_all_cortex_a8_stubs(); + } + + // Scan relocs for relocation stubs + for (Input_objects::Relobj_iterator op = input_objects->relobj_begin(); + op != input_objects->relobj_end(); + ++op) + { + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(*op); + arm_relobj->scan_sections_for_stubs(this, symtab, layout); + } + + // Check all stub tables to see if any of them have their data sizes + // or addresses alignments changed. These are the only things that + // matter. + bool any_stub_table_changed = false; + Unordered_set<const Output_section*> sections_needing_adjustment; + for (Stub_table_iterator sp = this->stub_tables_.begin(); + (sp != this->stub_tables_.end()) && !any_stub_table_changed; + ++sp) + { + if ((*sp)->update_data_size_and_addralign()) + { + // Update data size of stub table owner. + Arm_input_section<big_endian>* owner = (*sp)->owner(); + uint64_t address = owner->address(); + off_t offset = owner->offset(); + owner->reset_address_and_file_offset(); + owner->set_address_and_file_offset(address, offset); + + sections_needing_adjustment.insert(owner->output_section()); + any_stub_table_changed = true; + } + } + + // Output_section_data::output_section() returns a const pointer but we + // need to update output sections, so we record all output sections needing + // update above and scan the sections here to find out what sections need + // to be updated. + for(Layout::Section_list::const_iterator p = layout->section_list().begin(); + p != layout->section_list().end(); + ++p) + { + if (sections_needing_adjustment.find(*p) + != sections_needing_adjustment.end()) + (*p)->set_section_offsets_need_adjustment(); + } + + // Stop relaxation if no EXIDX fix-up and no stub table change. + bool continue_relaxation = done_exidx_fixup || any_stub_table_changed; + + // Finalize the stubs in the last relaxation pass. + if (!continue_relaxation) + { + for (Stub_table_iterator sp = this->stub_tables_.begin(); + (sp != this->stub_tables_.end()) && !any_stub_table_changed; + ++sp) + (*sp)->finalize_stubs(); + + // Update output local symbol counts of objects if necessary. + for (Input_objects::Relobj_iterator op = input_objects->relobj_begin(); + op != input_objects->relobj_end(); + ++op) + { + Arm_relobj<big_endian>* arm_relobj = + Arm_relobj<big_endian>::as_arm_relobj(*op); + + // Update output local symbol counts. We need to discard local + // symbols defined in parts of input sections that are discarded by + // relaxation. + if (arm_relobj->output_local_symbol_count_needs_update()) + arm_relobj->update_output_local_symbol_count(); + } + } + + return continue_relaxation; +} + +// Relocate a stub. + +template<bool big_endian> +void +Target_arm<big_endian>::relocate_stub( + Stub* stub, + const Relocate_info<32, big_endian>* relinfo, + Output_section* output_section, + unsigned char* view, + Arm_address address, + section_size_type view_size) +{ + Relocate relocate; + const Stub_template* stub_template = stub->stub_template(); + for (size_t i = 0; i < stub_template->reloc_count(); i++) + { + size_t reloc_insn_index = stub_template->reloc_insn_index(i); + const Insn_template* insn = &stub_template->insns()[reloc_insn_index]; + + unsigned int r_type = insn->r_type(); + section_size_type reloc_offset = stub_template->reloc_offset(i); + section_size_type reloc_size = insn->size(); + gold_assert(reloc_offset + reloc_size <= view_size); + + // This is the address of the stub destination. + Arm_address target = stub->reloc_target(i) + insn->reloc_addend(); + Symbol_value<32> symval; + symval.set_output_value(target); + + // Synthesize a fake reloc just in case. We don't have a symbol so + // we use 0. + unsigned char reloc_buffer[elfcpp::Elf_sizes<32>::rel_size]; + memset(reloc_buffer, 0, sizeof(reloc_buffer)); + elfcpp::Rel_write<32, big_endian> reloc_write(reloc_buffer); + reloc_write.put_r_offset(reloc_offset); + reloc_write.put_r_info(elfcpp::elf_r_info<32>(0, r_type)); + elfcpp::Rel<32, big_endian> rel(reloc_buffer); + + relocate.relocate(relinfo, this, output_section, + this->fake_relnum_for_stubs, rel, r_type, + NULL, &symval, view + reloc_offset, + address + reloc_offset, reloc_size); + } +} + +// Determine whether an object attribute tag takes an integer, a +// string or both. + +template<bool big_endian> +int +Target_arm<big_endian>::do_attribute_arg_type(int tag) const +{ + if (tag == Object_attribute::Tag_compatibility) + return (Object_attribute::ATTR_TYPE_FLAG_INT_VAL + | Object_attribute::ATTR_TYPE_FLAG_STR_VAL); + else if (tag == elfcpp::Tag_nodefaults) + return (Object_attribute::ATTR_TYPE_FLAG_INT_VAL + | Object_attribute::ATTR_TYPE_FLAG_NO_DEFAULT); + else if (tag == elfcpp::Tag_CPU_raw_name || tag == elfcpp::Tag_CPU_name) + return Object_attribute::ATTR_TYPE_FLAG_STR_VAL; + else if (tag < 32) + return Object_attribute::ATTR_TYPE_FLAG_INT_VAL; + else + return ((tag & 1) != 0 + ? Object_attribute::ATTR_TYPE_FLAG_STR_VAL + : Object_attribute::ATTR_TYPE_FLAG_INT_VAL); +} + +// Reorder attributes. +// +// The ABI defines that Tag_conformance should be emitted first, and that +// Tag_nodefaults should be second (if either is defined). This sets those +// two positions, and bumps up the position of all the remaining tags to +// compensate. + +template<bool big_endian> +int +Target_arm<big_endian>::do_attributes_order(int num) const +{ + // Reorder the known object attributes in output. We want to move + // Tag_conformance to position 4 and Tag_conformance to position 5 + // and shift eveything between 4 .. Tag_conformance - 1 to make room. + if (num == 4) + return elfcpp::Tag_conformance; + if (num == 5) + return elfcpp::Tag_nodefaults; + if ((num - 2) < elfcpp::Tag_nodefaults) + return num - 2; + if ((num - 1) < elfcpp::Tag_conformance) + return num - 1; + return num; +} + +// Scan a span of THUMB code for Cortex-A8 erratum. + +template<bool big_endian> +void +Target_arm<big_endian>::scan_span_for_cortex_a8_erratum( + Arm_relobj<big_endian>* arm_relobj, + unsigned int shndx, + section_size_type span_start, + section_size_type span_end, + const unsigned char* view, + Arm_address address) +{ + // Scan for 32-bit Thumb-2 branches which span two 4K regions, where: + // + // The opcode is BLX.W, BL.W, B.W, Bcc.W + // The branch target is in the same 4KB region as the + // first half of the branch. + // The instruction before the branch is a 32-bit + // length non-branch instruction. + section_size_type i = span_start; + bool last_was_32bit = false; + bool last_was_branch = false; + while (i < span_end) + { + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + const Valtype* wv = reinterpret_cast<const Valtype*>(view + i); + uint32_t insn = elfcpp::Swap<16, big_endian>::readval(wv); + bool is_blx = false, is_b = false; + bool is_bl = false, is_bcc = false; + + bool insn_32bit = (insn & 0xe000) == 0xe000 && (insn & 0x1800) != 0x0000; + if (insn_32bit) + { + // Load the rest of the insn (in manual-friendly order). + insn = (insn << 16) | elfcpp::Swap<16, big_endian>::readval(wv + 1); + + // Encoding T4: B<c>.W. + is_b = (insn & 0xf800d000U) == 0xf0009000U; + // Encoding T1: BL<c>.W. + is_bl = (insn & 0xf800d000U) == 0xf000d000U; + // Encoding T2: BLX<c>.W. + is_blx = (insn & 0xf800d000U) == 0xf000c000U; + // Encoding T3: B<c>.W (not permitted in IT block). + is_bcc = ((insn & 0xf800d000U) == 0xf0008000U + && (insn & 0x07f00000U) != 0x03800000U); + } + + bool is_32bit_branch = is_b || is_bl || is_blx || is_bcc; + + // If this instruction is a 32-bit THUMB branch that crosses a 4K + // page boundary and it follows 32-bit non-branch instruction, + // we need to work around. + if (is_32bit_branch + && ((address + i) & 0xfffU) == 0xffeU + && last_was_32bit + && !last_was_branch) + { + // Check to see if there is a relocation stub for this branch. + bool force_target_arm = false; + bool force_target_thumb = false; + const Cortex_a8_reloc* cortex_a8_reloc = NULL; + Cortex_a8_relocs_info::const_iterator p = + this->cortex_a8_relocs_info_.find(address + i); + + if (p != this->cortex_a8_relocs_info_.end()) + { + cortex_a8_reloc = p->second; + bool target_is_thumb = (cortex_a8_reloc->destination() & 1) != 0; + + if (cortex_a8_reloc->r_type() == elfcpp::R_ARM_THM_CALL + && !target_is_thumb) + force_target_arm = true; + else if (cortex_a8_reloc->r_type() == elfcpp::R_ARM_THM_CALL + && target_is_thumb) + force_target_thumb = true; + } + + off_t offset; + Stub_type stub_type = arm_stub_none; + + // Check if we have an offending branch instruction. + uint16_t upper_insn = (insn >> 16) & 0xffffU; + uint16_t lower_insn = insn & 0xffffU; + typedef struct Arm_relocate_functions<big_endian> RelocFuncs; + + if (cortex_a8_reloc != NULL + && cortex_a8_reloc->reloc_stub() != NULL) + // We've already made a stub for this instruction, e.g. + // it's a long branch or a Thumb->ARM stub. Assume that + // stub will suffice to work around the A8 erratum (see + // setting of always_after_branch above). + ; + else if (is_bcc) + { + offset = RelocFuncs::thumb32_cond_branch_offset(upper_insn, + lower_insn); + stub_type = arm_stub_a8_veneer_b_cond; + } + else if (is_b || is_bl || is_blx) + { + offset = RelocFuncs::thumb32_branch_offset(upper_insn, + lower_insn); + if (is_blx) + offset &= ~3; + + stub_type = (is_blx + ? arm_stub_a8_veneer_blx + : (is_bl + ? arm_stub_a8_veneer_bl + : arm_stub_a8_veneer_b)); + } + + if (stub_type != arm_stub_none) + { + Arm_address pc_for_insn = address + i + 4; + + // The original instruction is a BL, but the target is + // an ARM instruction. If we were not making a stub, + // the BL would have been converted to a BLX. Use the + // BLX stub instead in that case. + if (this->may_use_blx() && force_target_arm + && stub_type == arm_stub_a8_veneer_bl) + { + stub_type = arm_stub_a8_veneer_blx; + is_blx = true; + is_bl = false; + } + // Conversely, if the original instruction was + // BLX but the target is Thumb mode, use the BL stub. + else if (force_target_thumb + && stub_type == arm_stub_a8_veneer_blx) + { + stub_type = arm_stub_a8_veneer_bl; + is_blx = false; + is_bl = true; + } + + if (is_blx) + pc_for_insn &= ~3; + + // If we found a relocation, use the proper destination, + // not the offset in the (unrelocated) instruction. + // Note this is always done if we switched the stub type above. + if (cortex_a8_reloc != NULL) + offset = (off_t) (cortex_a8_reloc->destination() - pc_for_insn); + + Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1); + + // Add a new stub if destination address in in the same page. + if (((address + i) & ~0xfffU) == (target & ~0xfffU)) + { + Cortex_a8_stub* stub = + this->stub_factory_.make_cortex_a8_stub(stub_type, + arm_relobj, shndx, + address + i, + target, insn); + Stub_table<big_endian>* stub_table = + arm_relobj->stub_table(shndx); + gold_assert(stub_table != NULL); + stub_table->add_cortex_a8_stub(address + i, stub); + } + } + } + + i += insn_32bit ? 4 : 2; + last_was_32bit = insn_32bit; + last_was_branch = is_32bit_branch; + } +} + +// Apply the Cortex-A8 workaround. + +template<bool big_endian> +void +Target_arm<big_endian>::apply_cortex_a8_workaround( + const Cortex_a8_stub* stub, + Arm_address stub_address, + unsigned char* insn_view, + Arm_address insn_address) +{ + typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype; + Valtype* wv = reinterpret_cast<Valtype*>(insn_view); + Valtype upper_insn = elfcpp::Swap<16, big_endian>::readval(wv); + Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1); + off_t branch_offset = stub_address - (insn_address + 4); + + typedef struct Arm_relocate_functions<big_endian> RelocFuncs; + switch (stub->stub_template()->type()) + { + case arm_stub_a8_veneer_b_cond: + gold_assert(!utils::has_overflow<21>(branch_offset)); + upper_insn = RelocFuncs::thumb32_cond_branch_upper(upper_insn, + branch_offset); + lower_insn = RelocFuncs::thumb32_cond_branch_lower(lower_insn, + branch_offset); + break; + + case arm_stub_a8_veneer_b: + case arm_stub_a8_veneer_bl: + case arm_stub_a8_veneer_blx: + if ((lower_insn & 0x5000U) == 0x4000U) + // For a BLX instruction, make sure that the relocation is + // rounded up to a word boundary. This follows the semantics of + // the instruction which specifies that bit 1 of the target + // address will come from bit 1 of the base address. + branch_offset = (branch_offset + 2) & ~3; + + // Put BRANCH_OFFSET back into the insn. + gold_assert(!utils::has_overflow<25>(branch_offset)); + upper_insn = RelocFuncs::thumb32_branch_upper(upper_insn, branch_offset); + lower_insn = RelocFuncs::thumb32_branch_lower(lower_insn, branch_offset); + break; + + default: + gold_unreachable(); + } + + // Put the relocated value back in the object file: + elfcpp::Swap<16, big_endian>::writeval(wv, upper_insn); + elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn); +} + +template<bool big_endian> +class Target_selector_arm : public Target_selector +{ + public: + Target_selector_arm() + : Target_selector(elfcpp::EM_ARM, 32, big_endian, + (big_endian ? "elf32-bigarm" : "elf32-littlearm")) + { } + + Target* + do_instantiate_target() + { return new Target_arm<big_endian>(); } +}; + +// Fix .ARM.exidx section coverage. + +template<bool big_endian> +void +Target_arm<big_endian>::fix_exidx_coverage( + Layout* layout, + Arm_output_section<big_endian>* exidx_section, + Symbol_table* symtab) +{ + // We need to look at all the input sections in output in ascending + // order of of output address. We do that by building a sorted list + // of output sections by addresses. Then we looks at the output sections + // in order. The input sections in an output section are already sorted + // by addresses within the output section. + + typedef std::set<Output_section*, output_section_address_less_than> + Sorted_output_section_list; + Sorted_output_section_list sorted_output_sections; + Layout::Section_list section_list; + layout->get_allocated_sections(§ion_list); + for (Layout::Section_list::const_iterator p = section_list.begin(); + p != section_list.end(); + ++p) + { + // We only care about output sections that contain executable code. + if (((*p)->flags() & elfcpp::SHF_EXECINSTR) != 0) + sorted_output_sections.insert(*p); + } + + // Go over the output sections in ascending order of output addresses. + typedef typename Arm_output_section<big_endian>::Text_section_list + Text_section_list; + Text_section_list sorted_text_sections; + for(typename Sorted_output_section_list::iterator p = + sorted_output_sections.begin(); + p != sorted_output_sections.end(); + ++p) + { + Arm_output_section<big_endian>* arm_output_section = + Arm_output_section<big_endian>::as_arm_output_section(*p); + arm_output_section->append_text_sections_to_list(&sorted_text_sections); + } + + exidx_section->fix_exidx_coverage(layout, sorted_text_sections, symtab); +} + +Target_selector_arm<false> target_selector_arm; +Target_selector_arm<true> target_selector_armbe; + +} // End anonymous namespace. diff --git a/binutils-2.19/gold/attributes.cc b/binutils-2.19/gold/attributes.cc new file mode 100644 index 0000000..b9b3608 --- /dev/null +++ b/binutils-2.19/gold/attributes.cc @@ -0,0 +1,458 @@ +// attributes.cc -- object attributes for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. +// This file contains code adapted from BFD. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <limits> + +#include "attributes.h" +#include "elfcpp.h" +#include "target.h" +#include "parameters.h" +#include "int_encoding.h" + +namespace gold +{ + +// Object_attribute methods. + +// Return size of attribute encode in ULEB128. + +size_t +Object_attribute::size(int tag) const +{ + // Attributes with default values are not written out. + if (this->is_default_attribute()) + return 0; + + size_t size = get_length_as_unsigned_LEB_128(tag); + if (Object_attribute::attribute_type_has_int_value(this->type_)) + size += get_length_as_unsigned_LEB_128(this->int_value_); + if (Object_attribute::attribute_type_has_string_value(this->type_)) + size += this->string_value_.size() + 1; + return size; +} + +// Whether this has the default value (0/""). + +bool +Object_attribute::is_default_attribute() const +{ + if (Object_attribute::attribute_type_has_int_value(this->type_) + && this->int_value_ != 0) + return false; + if (Object_attribute::attribute_type_has_string_value(this->type_) + && !this->string_value_.empty()) + return false; + if (Object_attribute::attribute_type_has_no_default(this->type_)) + return false; + + return true; +} + +// Whether this matches another Object_attribute OA in merging. +// Two Object_attributes match if they have the same values. + +bool +Object_attribute::matches(const Object_attribute& oa) const +{ + return ((this->int_value_ != oa.int_value_) + && (this->string_value_ == oa.string_value_)); +} + +// Write this with TAG to a BUFFER. + +void +Object_attribute::write( + int tag, + std::vector<unsigned char>* buffer) const +{ + // No need to write default attributes. + if (this->is_default_attribute()) + return; + + // Write tag. + write_unsigned_LEB_128(buffer, convert_types<uint64_t, int>(tag)); + + // Write integer value. + if (Object_attribute::attribute_type_has_int_value(this->type_)) + write_unsigned_LEB_128(buffer, + convert_types<uint64_t, int>(this->int_value_)); + + // Write string value. + if (Object_attribute::attribute_type_has_string_value(this->type_)) + { + const unsigned char* start = + reinterpret_cast<const unsigned char*>(this->string_value_.c_str()); + const unsigned char* end = start + this->string_value_.size() + 1; + buffer->insert(buffer->end(), start, end); + } +} + +// Vendor_object_attributes methods. + +// Copying constructor. + +Vendor_object_attributes::Vendor_object_attributes( + const Vendor_object_attributes& voa) +{ + this->vendor_ = voa.vendor_; + + for (int i = 0; i < NUM_KNOWN_ATTRIBUTES; ++i) + this->known_attributes_[i] = voa.known_attributes_[i]; + + // We do not handle attribute deletion. So this must be empty. + gold_assert(this->other_attributes_.empty()); + + for (Other_attributes::const_iterator p = voa.other_attributes_.begin(); + p != voa.other_attributes_.end(); + ++p) + this->other_attributes_[p->first] = new Object_attribute(*(p->second)); +} + +// Size of this in number of bytes. + +size_t +Vendor_object_attributes::size() const +{ + if (this->name() == NULL) + return 0; + + size_t data_size = 0; + for (int i = 4; i < NUM_KNOWN_ATTRIBUTES; ++i) + data_size += this->known_attributes_[i].size(i); + + for (Other_attributes::const_iterator p = this->other_attributes_.begin(); + p != this->other_attributes_.end(); + ++p) + data_size += p->second->size(p->first); + + // <size> <vendor_name> NUL 0x1 <size> + return ((data_size != 0 + || this->vendor_ == Object_attribute::OBJ_ATTR_PROC) + ? data_size + strlen(this->name()) + 2 + 2 * 4 + : 0); +} + +// Return a new attribute associated with TAG. + +Object_attribute* +Vendor_object_attributes::new_attribute(int tag) +{ + int type = Object_attribute::arg_type(this->vendor_, tag); + + if (tag < NUM_KNOWN_ATTRIBUTES) + { + this->known_attributes_[tag].set_type(type); + return &this->known_attributes_[tag]; + } + else + { + Object_attribute* attr = new Object_attribute(); + + // This should be the first time we insert this. + std::pair<Other_attributes::iterator, bool> ins = + this->other_attributes_.insert(std::make_pair(tag, attr)); + gold_assert(ins.second); + + attr->set_type(type); + return attr; + } +} + +// Return an attribute associated with TAG. + +Object_attribute* +Vendor_object_attributes::get_attribute(int tag) +{ + if (tag < NUM_KNOWN_ATTRIBUTES) + return &this->known_attributes_[tag]; + else + { + Other_attributes::iterator p = + this->other_attributes_.find(tag); + return p != this->other_attributes_.end() ? p->second : NULL; + } +} + +const Object_attribute* +Vendor_object_attributes::get_attribute(int tag) const +{ + if (tag < NUM_KNOWN_ATTRIBUTES) + return &this->known_attributes_[tag]; + else + { + Other_attributes::const_iterator p = + this->other_attributes_.find(tag); + return p != this->other_attributes_.end() ? p->second : NULL; + } +} + +// Write attributes to BUFFER. + +void +Vendor_object_attributes::write(std::vector<unsigned char>* buffer) const +{ + // Write subsection size. + size_t voa_size = this->size(); + uint32_t voa_size_as_u32 = convert_types<uint32_t, size_t>(voa_size); + insert_into_vector<32>(buffer, voa_size_as_u32); + + // Write vendor name. + const unsigned char* vendor_start = + reinterpret_cast<const unsigned char*>(this->name()); + size_t vendor_length = strlen(this->name()) + 1; + const unsigned char* vendor_end = vendor_start + vendor_length; + buffer->insert(buffer->end(), vendor_start, vendor_end); + + // Write file tag. + buffer->push_back(Object_attribute::Tag_File); + + // Write attributes size. + uint32_t attributes_size_as_u32 = + convert_types<uint32_t, size_t>(voa_size - 4 - vendor_length); + insert_into_vector<32>(buffer, attributes_size_as_u32); + + // Write known attributes, skipping any defaults. + for (int i = 4; i < NUM_KNOWN_ATTRIBUTES; ++i) + { + // A target may write known attributes in a special order. + // Call target hook to remap tags. Attributes_order is the identity + // function if no re-ordering is required. + int tag = parameters->target().attributes_order(i); + this->known_attributes_[tag].write(tag, buffer); + } + + // Write other attributes. + for (Other_attributes::const_iterator q = this->other_attributes_.begin(); + q != this->other_attributes_.end(); + ++q) + q->second->write(q->first, buffer); +} + +// Attributes_section_data methods. + +// Compute encoded size of this. + +size_t +Attributes_section_data::size() const +{ + size_t data_size = 0; + for(int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) + data_size += this->vendor_object_attributes_[vendor]->size(); + + // 'A' <sections for each vendor> + return data_size != 0 ? data_size + 1 : 0; +} + +// Construct an Attributes_section_data object by parsing section contents +// specified by VIEW and SIZE. + +Attributes_section_data::Attributes_section_data( + const unsigned char* view, + section_size_type size) +{ + for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) + this->vendor_object_attributes_[vendor] = + new Vendor_object_attributes(vendor); + + const unsigned char *p = view; + p = view; + if (size > 0 && p != NULL && *(p++) == 'A') + { + size--; + while (size > 0) + { + // Size of vendor attributes section. + section_size_type section_size = + convert_to_section_size_type(read_from_pointer<32>(&p)); + + if (section_size > size) + section_size = size; + size -= section_size; + + const char* section_name = reinterpret_cast<const char*>(p); + section_size_type section_name_size = strlen(section_name) + 1; + section_size -= section_name_size + 4; + + int vendor; + const char *std_section = parameters->target().attributes_vendor(); + if (std_section != NULL && strcmp(section_name, std_section) == 0) + vendor = Object_attribute::OBJ_ATTR_PROC; + else if (strcmp(section_name, "gnu") == 0) + vendor = Object_attribute::OBJ_ATTR_GNU; + else + { + // Other vendor section. Ignore it. + p += section_name_size + section_size; + continue; + } + p += section_name_size; + + while (section_size > 0) + { + const unsigned char* subsection_start = p; + + // Read vendor subsection index and size. + size_t uleb128_len; + uint64_t val = read_unsigned_LEB_128(p, &uleb128_len); + p += uleb128_len; + + int tag = convert_types<int, uint64_t>(val); + section_size_type subsection_size = + convert_to_section_size_type(read_from_pointer<32>(&p)); + section_size -= subsection_size; + subsection_size -= (p - subsection_start); + + const unsigned char* end = p + subsection_size; + switch (tag) + { + case Object_attribute::Tag_File: + while (p < end) + { + val = read_unsigned_LEB_128(p, &uleb128_len); + p += uleb128_len; + tag = convert_types<int, uint64_t>(val); + Vendor_object_attributes* pvoa = + this->vendor_object_attributes_[vendor]; + Object_attribute* attr = pvoa->new_attribute(tag); + const char* string_arg; + unsigned int int_arg; + + int type = Object_attribute::arg_type(vendor, tag); + switch (type + & (Object_attribute::ATTR_TYPE_FLAG_INT_VAL + | Object_attribute::ATTR_TYPE_FLAG_STR_VAL)) + { + case (Object_attribute::ATTR_TYPE_FLAG_INT_VAL + | Object_attribute::ATTR_TYPE_FLAG_STR_VAL): + val = read_unsigned_LEB_128(p, &uleb128_len); + p += uleb128_len; + int_arg = convert_types<unsigned int, uint64_t>(val); + string_arg = reinterpret_cast<const char *>(p); + attr->set_int_value(int_arg); + p += strlen(string_arg) + 1; + break; + case Object_attribute::ATTR_TYPE_FLAG_STR_VAL: + string_arg = reinterpret_cast<const char *>(p); + attr->set_string_value(string_arg); + p += strlen(string_arg) + 1; + break; + case Object_attribute::ATTR_TYPE_FLAG_INT_VAL: + val = read_unsigned_LEB_128(p, &uleb128_len); + p += uleb128_len; + int_arg = convert_types<unsigned int, uint64_t>(val); + attr->set_int_value(int_arg); + break; + default: + gold_unreachable(); + } + } + break; + case Object_attribute::Tag_Section: + case Object_attribute::Tag_Symbol: + // Don't have anywhere convenient to attach these. + // Fall through for now. + default: + // Ignore things we don't know about. + p += subsection_size; + subsection_size = 0; + break; + } + } + } + } +} + +// Merge target-independent attributes from another Attribute_section_data +// ASD from an object called NAME into this. + +void +Attributes_section_data::merge( + const char* name, + const Attributes_section_data* pasd) +{ + // The only common attribute is currently Tag_compatibility, + // accepted in both processor and "gnu" sections. + for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) + { + // Handle Tag_compatibility. The tags are only compatible if the flags + // are identical and, if the flags are '1', the strings are identical. + // If the flags are non-zero, then we can only use the string "gnu". + const Object_attribute* in_attr = + &pasd->known_attributes(vendor)[Object_attribute::Tag_compatibility]; + Object_attribute* out_attr = + &this->known_attributes(vendor)[Object_attribute::Tag_compatibility]; + + if (in_attr->int_value() > 0 + && in_attr->string_value() != "gnu") + { + gold_error(_("%s: must be processed by '%s' toolchain"), + name, in_attr->string_value().c_str()); + return; + } + + if (in_attr->int_value() != out_attr->int_value() + || in_attr->string_value() != out_attr->string_value()) + { + gold_error(_("%s: object tag '%d, %s' is " + "incompatible with tag '%d, %s'"), + name, in_attr->int_value(), + in_attr->string_value().c_str(), + out_attr->int_value(), + out_attr->string_value().c_str()); + } + } +} + +// Write to a buffer. + +void +Attributes_section_data::write(std::vector<unsigned char>* buffer) const +{ + buffer->push_back('A'); + for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) + if (this->vendor_object_attributes_[vendor]->size() != 0) + this->vendor_object_attributes_[vendor]->write(buffer); +} + +// Methods for Output_attributes_section_data. + +// Write attributes section data to file OF. + +void +Output_attributes_section_data::do_write(Output_file* of) +{ + off_t offset = this->offset(); + const section_size_type oview_size = + convert_to_section_size_type(this->data_size()); + unsigned char* const oview = of->get_output_view(offset, oview_size); + + std::vector<unsigned char> buffer; + this->attributes_section_data_.write(&buffer); + gold_assert(convert_to_section_size_type(buffer.size()) == oview_size); + memcpy(oview, &buffer.front(), buffer.size()); + of->write_output_view(this->offset(), oview_size, oview); +} + +} // End namespace gold. diff --git a/binutils-2.19/gold/attributes.h b/binutils-2.19/gold/attributes.h new file mode 100644 index 0000000..7c4baf4 --- /dev/null +++ b/binutils-2.19/gold/attributes.h @@ -0,0 +1,406 @@ +// attributes.h -- object attributes for gold -*- C++ -*- + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. +// This file contains code adapted from BFD. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// Handle object attributes. + +#ifndef GOLD_ATTRIBUTES_H +#define GOLD_ATTRIBUTES_H + +#include <map> + +#include "parameters.h" +#include "target.h" +#include "output.h" +#include "reduced_debug_output.h" + +namespace gold +{ + +// Object attribute values. The attribute tag is not stored in this object. + +class Object_attribute +{ + public: + // The value of an object attribute. The type indicates whether the + // attribute holds and integer, a string, or both. It can also indicate that + // there can be no default (i.e. all values must be written to file, even + // zero). + enum + { + ATTR_TYPE_FLAG_INT_VAL = (1 << 0), + ATTR_TYPE_FLAG_STR_VAL = (1 << 1), + ATTR_TYPE_FLAG_NO_DEFAULT = (1 << 2) + }; + + // Object attributes may either be defined by the processor ABI, index + // OBJ_ATTR_PROC in the *_obj_attributes arrays, or be GNU-specific + // (and possibly also processor-specific), index OBJ_ATTR_GNU. + enum + { + OBJ_ATTR_PROC, + OBJ_ATTR_GNU, + OBJ_ATTR_FIRST = OBJ_ATTR_PROC, + OBJ_ATTR_LAST = OBJ_ATTR_GNU + }; + + // The following object attribute tags are taken as generic, for all + // targets and for "gnu" where there is no target standard. + enum + { + Tag_NULL = 0, + Tag_File = 1, + Tag_Section = 2, + Tag_Symbol = 3, + Tag_compatibility = 32 + }; + + Object_attribute() + : type_(0), int_value_(0), string_value_() + { } + + // Copying constructor. We need to implement this to copy the string value. + Object_attribute(const Object_attribute& oa) + : type_(oa.type_), int_value_(oa.int_value_), string_value_(oa.string_value_) + { } + + ~Object_attribute() + { } + + // Assignment operator. We need to implement this to copy the string value. + Object_attribute& + operator=(const Object_attribute& source) + { + this->type_ = source.type_; + this->int_value_ = source.int_value_; + this->string_value_ = source.string_value_; + return *this; + } + + // Return attribute type. + int + type() const + { return this->type_; } + + // Set attribute type. + void + set_type(int type) + { this->type_ = type; } + + // Return integer value. + unsigned int + int_value() const + { return this->int_value_; } + + // Set integer value. + void + set_int_value(unsigned int i) + { this->int_value_ = i; } + + // Return string value. + const std::string& + string_value() const + { return this->string_value_; } + + // Set string value. + void + set_string_value(const std::string& s) + { this->string_value_ = s; } + + void + set_string_value(const char* s) + { this->string_value_ = s; } + + // Whether attribute type has integer value. + static bool + attribute_type_has_int_value(int type) + { return (type & ATTR_TYPE_FLAG_INT_VAL) != 0; } + + // Whether attribute type has string value. + static bool + attribute_type_has_string_value(int type) + { return (type & ATTR_TYPE_FLAG_STR_VAL) != 0; } + + // Whether attribute type has no default value. + static bool + attribute_type_has_no_default(int type) + { return (type & ATTR_TYPE_FLAG_NO_DEFAULT) != 0; } + + // Whether this has default value (0/""). + bool + is_default_attribute() const; + + // Return ULEB128 encoded size of tag and attribute. + size_t + size(int tag) const; + + // Whether this matches another object attribute in merging. + bool + matches(const Object_attribute& oa) const; + + // Write to attribute with tag to BUFFER. + void + write(int tag, std::vector<unsigned char>* buffer) const; + + // Determine what arguments an attribute tag takes. + static int + arg_type (int vendor, int tag) + { + switch (vendor) + { + case OBJ_ATTR_PROC: + return parameters->target().attribute_arg_type(tag); + case OBJ_ATTR_GNU: + return Object_attribute::gnu_arg_type(tag); + default: + gold_unreachable(); + } + } + + private: + // Determine whether a GNU object attribute tag takes an integer, a + // string or both. */ + static int + gnu_arg_type (int tag) + { + // Except for Tag_compatibility, for GNU attributes we follow the + // same rule ARM ones > 32 follow: odd-numbered tags take strings + // and even-numbered tags take integers. In addition, tag & 2 is + // nonzero for architecture-independent tags and zero for + // architecture-dependent ones. + if (tag == Object_attribute::Tag_compatibility) + return ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL; + else + return (tag & 1) != 0 ? ATTR_TYPE_FLAG_STR_VAL : ATTR_TYPE_FLAG_INT_VAL; + } + + // Attribute type. + int type_; + // Integer value. + int int_value_; + // String value. + std::string string_value_; +}; + +// This class contains attributes of a particular vendor. + +class Vendor_object_attributes +{ + public: + // The maximum number of known object attributes for any target. + static const int NUM_KNOWN_ATTRIBUTES = 71; + + Vendor_object_attributes(int vendor) + : vendor_(vendor), other_attributes_() + { } + + // Copying constructor. + Vendor_object_attributes(const Vendor_object_attributes&); + + ~Vendor_object_attributes() + { + for (Other_attributes::iterator p = this->other_attributes_.begin(); + p != this->other_attributes_.end(); + ++p) + delete p->second; + } + + // Size of this in number of bytes. + size_t + size() const; + + // Name of this written vendor subsection. + const char* + name() const + { + return (this->vendor_ == Object_attribute::OBJ_ATTR_PROC + ? parameters->target().attributes_vendor() + : "gnu"); + } + + // Return an array of known attributes. + Object_attribute* + known_attributes() + { return &this->known_attributes_[0]; } + + const Object_attribute* + known_attributes() const + { return &this->known_attributes_[0]; } + + typedef std::map<int, Object_attribute*> Other_attributes; + + // Return attributes other than the known ones. + Other_attributes* + other_attributes() + { return &this->other_attributes_; } + + const Other_attributes* + other_attributes() const + { return &this->other_attributes_; } + + // Return a new attribute asssociated with TAG. + Object_attribute* + new_attribute(int tag); + + // Get an attribute + Object_attribute* + get_attribute(int tag); + + const Object_attribute* + get_attribute(int tag) const; + + // Write to BUFFER. + void + write(std::vector<unsigned char>* buffer) const; + + private: + // Vendor of the object attributes. + int vendor_; + // Attributes with known tags. There are store in an array for fast + // access. + Object_attribute known_attributes_[NUM_KNOWN_ATTRIBUTES]; + // Attributes with known tags. There are stored in a sorted container. + Other_attributes other_attributes_; +}; + +// This class contains contents of an attributes section. + +class Attributes_section_data +{ + public: + // Construct an Attributes_section_data object by parsing section contents + // in VIEW of SIZE. + Attributes_section_data(const unsigned char* view, section_size_type size); + + // Copying constructor. + Attributes_section_data(const Attributes_section_data& asd) + { + for (int vendor = Object_attribute::OBJ_ATTR_FIRST; + vendor <= Object_attribute::OBJ_ATTR_LAST; + ++vendor) + this->vendor_object_attributes_[vendor] = + new Vendor_object_attributes(*asd.vendor_object_attributes_[vendor]); + } + + ~Attributes_section_data() + { + for (int vendor = Object_attribute::OBJ_ATTR_FIRST; + vendor <= Object_attribute::OBJ_ATTR_LAST; + ++vendor) + delete this->vendor_object_attributes_[vendor]; + } + + // Return the size of this as number of bytes. + size_t + size() const; + + // Return an array of known attributes. + Object_attribute* + known_attributes(int vendor) + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->known_attributes(); + } + + const Object_attribute* + known_attributes(int vendor) const + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->known_attributes(); + } + + // Return the other attributes. + Vendor_object_attributes::Other_attributes* + other_attributes(int vendor) + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->other_attributes(); + } + + // Return the other attributes. + const Vendor_object_attributes::Other_attributes* + other_attributes(int vendor) const + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->other_attributes(); + } + + // Return an attribute. + Object_attribute* + get_attribute(int vendor, int tag) + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->get_attribute(tag); + } + + const Object_attribute* + get_attribute(int vendor, int tag) const + { + gold_assert(vendor >= OBJ_ATTR_FIRST && vendor <= OBJ_ATTR_LAST); + return this->vendor_object_attributes_[vendor]->get_attribute(tag); + } + + // Merge target-independent attributes from another Attributes_section_data + // of an object called NAME. + void + merge(const char* name, const Attributes_section_data* pasd); + + // Write to byte stream in an unsigned char vector. + void + write(std::vector<unsigned char>*) const; + + private: + // For convenience. + static const int OBJ_ATTR_FIRST = Object_attribute::OBJ_ATTR_FIRST; + static const int OBJ_ATTR_LAST = Object_attribute::OBJ_ATTR_LAST; + + // Vendor object attributes. + Vendor_object_attributes* vendor_object_attributes_[OBJ_ATTR_LAST+1]; +}; + +// This class is used for writing out an Attribute_section_data. + +class Output_attributes_section_data : public Output_section_data +{ + public: + Output_attributes_section_data(const Attributes_section_data& asd) + : Output_section_data(1), attributes_section_data_(asd) + { } + + protected: + // Write the data to the output file. + void + do_write(Output_file*); + + // Set final data size. + void + set_final_data_size() + { this->set_data_size(attributes_section_data_.size()); } + + private: + // Attributes_section_data corresponding to this. + const Attributes_section_data& attributes_section_data_; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_ATTRIBUTES_H) diff --git a/binutils-2.19/gold/binary.cc b/binutils-2.19/gold/binary.cc index 7eb7223..f14df0d 100644 --- a/binutils-2.19/gold/binary.cc +++ b/binutils-2.19/gold/binary.cc @@ -35,7 +35,7 @@ // Support for reading binary files as input. These become blobs in // the final output. These files are treated as though they have a // single .data section and define three symbols: -// _binary_FILENAME_start, _binary_FILENAME_end, _binary_FILENAME_end. +// _binary_FILENAME_start, _binary_FILENAME_end, _binary_FILENAME_size. // The FILENAME is the name of the input file, with any // non-alphanumeric character changed to an underscore. diff --git a/binutils-2.19/gold/common.cc b/binutils-2.19/gold/common.cc index 632a20b..8346c0b 100644 --- a/binutils-2.19/gold/common.cc +++ b/binutils-2.19/gold/common.cc @@ -1,6 +1,6 @@ // common.cc -- handle common symbols for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -36,24 +36,21 @@ namespace gold // Allocate_commons_task methods. -// This task allocates the common symbols. We need a lock on the -// symbol table. +// This task allocates the common symbols. We arrange to run it +// before anything else which needs to access the symbol table. Task_token* Allocate_commons_task::is_runnable() { - if (!this->symtab_lock_->is_writable()) - return this->symtab_lock_; return NULL; } -// Return the locks we hold: one on the symbol table, and one blocker. +// Release a blocker. void Allocate_commons_task::locks(Task_locker* tl) { tl->add(this, this->blocker_); - tl->add(this, this->symtab_lock_); } // Allocate the common symbols. @@ -64,21 +61,26 @@ Allocate_commons_task::run(Workqueue*) this->symtab_->allocate_commons(this->layout_, this->mapfile_); } -// This class is used to sort the common symbol by size. We put the -// larger common symbols first. +// This class is used to sort the common symbol. We normally put the +// larger common symbols first. This can be changed by using +// --sort-commons, which tells the linker to sort by alignment. template<int size> class Sort_commons { public: - Sort_commons(const Symbol_table* symtab) - : symtab_(symtab) + Sort_commons(const Symbol_table* symtab, + Symbol_table::Sort_commons_order sort_order) + : symtab_(symtab), sort_order_(sort_order) { } bool operator()(const Symbol* a, const Symbol* b) const; private: + // The symbol table. const Symbol_table* symtab_; + // How to sort. + Symbol_table::Sort_commons_order sort_order_; }; template<int size> @@ -86,7 +88,16 @@ bool Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const { if (pa == NULL) - return false; + { + if (pb == NULL) + { + // Stabilize sort. The order really doesn't matter, because + // these entries will be discarded, but we want to return + // the same result every time we compare pa and pb. + return pa < pb; + } + return false; + } if (pb == NULL) return true; @@ -94,22 +105,48 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const const Sized_symbol<size>* psa = symtab->get_sized_symbol<size>(pa); const Sized_symbol<size>* psb = symtab->get_sized_symbol<size>(pb); - // Sort by largest size first. + // The size. typename Sized_symbol<size>::Size_type sa = psa->symsize(); typename Sized_symbol<size>::Size_type sb = psb->symsize(); + + // The alignment. + typename Sized_symbol<size>::Value_type aa = psa->value(); + typename Sized_symbol<size>::Value_type ab = psb->value(); + + if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_DESCENDING) + { + if (aa < ab) + return false; + else if (ab < aa) + return true; + } + else if (this->sort_order_ + == Symbol_table::SORT_COMMONS_BY_ALIGNMENT_ASCENDING) + { + if (aa < ab) + return true; + else if (ab < aa) + return false; + } + else + gold_assert(this->sort_order_ + == Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING); + + // Sort by descending size. if (sa < sb) return false; else if (sb < sa) return true; - // When the symbols are the same size, we sort them by alignment, - // largest alignment first. - typename Sized_symbol<size>::Value_type va = psa->value(); - typename Sized_symbol<size>::Value_type vb = psb->value(); - if (va < vb) - return false; - else if (vb < va) - return true; + if (this->sort_order_ == Symbol_table::SORT_COMMONS_BY_SIZE_DESCENDING) + { + // When the symbols are the same size, we sort them by + // alignment, largest alignment first. + if (aa < ab) + return false; + else if (ab < aa) + return true; + } // Otherwise we stabilize the sort by sorting by name. return strcmp(psa->name(), psb->name()) < 0; @@ -120,10 +157,27 @@ Sort_commons<size>::operator()(const Symbol* pa, const Symbol* pb) const void Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile) { + Sort_commons_order sort_order; + if (!parameters->options().user_set_sort_common()) + sort_order = SORT_COMMONS_BY_SIZE_DESCENDING; + else + { + const char* order = parameters->options().sort_common(); + if (*order == '\0' || strcmp(order, "descending") == 0) + sort_order = SORT_COMMONS_BY_ALIGNMENT_DESCENDING; + else if (strcmp(order, "ascending") == 0) + sort_order = SORT_COMMONS_BY_ALIGNMENT_ASCENDING; + else + { + gold_error("invalid --sort-common argument: %s", order); + sort_order = SORT_COMMONS_BY_SIZE_DESCENDING; + } + } + if (parameters->target().get_size() == 32) { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) - this->do_allocate_commons<32>(layout, mapfile); + this->do_allocate_commons<32>(layout, mapfile, sort_order); #else gold_unreachable(); #endif @@ -131,7 +185,7 @@ Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile) else if (parameters->target().get_size() == 64) { #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) - this->do_allocate_commons<64>(layout, mapfile); + this->do_allocate_commons<64>(layout, mapfile, sort_order); #else gold_unreachable(); #endif @@ -144,12 +198,25 @@ Symbol_table::allocate_commons(Layout* layout, Mapfile* mapfile) template<int size> void -Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile) +Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile, + Sort_commons_order sort_order) { - this->do_allocate_commons_list<size>(layout, false, &this->commons_, - mapfile); - this->do_allocate_commons_list<size>(layout, true, &this->tls_commons_, - mapfile); + if (!this->commons_.empty()) + this->do_allocate_commons_list<size>(layout, COMMONS_NORMAL, + &this->commons_, mapfile, + sort_order); + if (!this->tls_commons_.empty()) + this->do_allocate_commons_list<size>(layout, COMMONS_TLS, + &this->tls_commons_, mapfile, + sort_order); + if (!this->small_commons_.empty()) + this->do_allocate_commons_list<size>(layout, COMMONS_SMALL, + &this->small_commons_, mapfile, + sort_order); + if (!this->large_commons_.empty()) + this->do_allocate_commons_list<size>(layout, COMMONS_LARGE, + &this->large_commons_, mapfile, + sort_order); } // Allocate the common symbols in a list. IS_TLS indicates whether @@ -157,9 +224,12 @@ Symbol_table::do_allocate_commons(Layout* layout, Mapfile* mapfile) template<int size> void -Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls, - Commons_type* commons, - Mapfile* mapfile) +Symbol_table::do_allocate_commons_list( + Layout* layout, + Commons_section_type commons_section_type, + Commons_type* commons, + Mapfile* mapfile, + Sort_commons_order sort_order) { typedef typename Sized_symbol<size>::Value_type Value_type; typedef typename Sized_symbol<size>::Size_type Size_type; @@ -192,26 +262,51 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls, if (!any) return; - // Sort the common symbols by size, so that they pack better into - // memory. + // Sort the common symbols. std::sort(commons->begin(), commons->end(), - Sort_commons<size>(this)); + Sort_commons<size>(this, sort_order)); // Place them in a newly allocated BSS section. - - Output_data_space *poc = new Output_data_space(addralign, - (is_tls - ? "** tls common" - : "** common")); - - const char* name = ".bss"; elfcpp::Elf_Xword flags = elfcpp::SHF_WRITE | elfcpp::SHF_ALLOC; - if (is_tls) + const char* name; + const char* ds_name; + switch (commons_section_type) { - name = ".tbss"; + case COMMONS_NORMAL: + name = ".bss"; + ds_name = "** common"; + break; + case COMMONS_TLS: flags |= elfcpp::SHF_TLS; + name = ".tbss"; + ds_name = "** tls common"; + break; + case COMMONS_SMALL: + flags |= parameters->target().small_common_section_flags(); + name = ".sbss"; + ds_name = "** small common"; + break; + case COMMONS_LARGE: + flags |= parameters->target().large_common_section_flags(); + name = ".lbss"; + ds_name = "** large common"; + break; + default: + gold_unreachable(); + } + + Output_data_space *poc = new Output_data_space(addralign, ds_name); + Output_section *os = layout->add_output_section_data(name, + elfcpp::SHT_NOBITS, + flags, poc, false, + false, false, false); + if (os != NULL) + { + if (commons_section_type == COMMONS_SMALL) + os->set_is_small_section(); + else if (commons_section_type == COMMONS_LARGE) + os->set_is_large_section(); } - layout->add_output_section_data(name, elfcpp::SHT_NOBITS, flags, poc); // Allocate them all. @@ -223,6 +318,17 @@ Symbol_table::do_allocate_commons_list(Layout* layout, bool is_tls, Symbol* sym = *p; if (sym == NULL) break; + + // Because we followed forwarding symbols above, but we didn't + // do it reliably before adding symbols to the list, it is + // possible for us to have the same symbol on the list twice. + // This can happen in the horrible case where a program defines + // a common symbol with the same name as a versioned libc + // symbol. That will show up here as a symbol which has already + // been allocated and is therefore no longer a common symbol. + if (!sym->is_common()) + continue; + Sized_symbol<size>* ssym = this->get_sized_symbol<size>(sym); // Record the symbol in the map file now, before we change its diff --git a/binutils-2.19/gold/common.h b/binutils-2.19/gold/common.h index 9653604..4de585c 100644 --- a/binutils-2.19/gold/common.h +++ b/binutils-2.19/gold/common.h @@ -1,6 +1,6 @@ // common.h -- handle common symbols for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -36,9 +36,8 @@ class Allocate_commons_task : public Task { public: Allocate_commons_task(Symbol_table* symtab, Layout* layout, Mapfile* mapfile, - Task_token* symtab_lock, Task_token* blocker) - : symtab_(symtab), layout_(layout), mapfile_(mapfile), - symtab_lock_(symtab_lock), blocker_(blocker) + Task_token* blocker) + : symtab_(symtab), layout_(layout), mapfile_(mapfile), blocker_(blocker) { } // The standard Task methods. @@ -60,7 +59,6 @@ class Allocate_commons_task : public Task Symbol_table* symtab_; Layout* layout_; Mapfile* mapfile_; - Task_token* symtab_lock_; Task_token* blocker_; }; diff --git a/binutils-2.19/gold/config.in b/binutils-2.19/gold/config.in index 73cc6e9..7a824b0 100644 --- a/binutils-2.19/gold/config.in +++ b/binutils-2.19/gold/config.in @@ -1,9 +1,15 @@ /* config.in. Generated from configure.ac by autoheader. */ +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS +/* Define to enable linker plugins */ +#undef ENABLE_PLUGINS + /* Define to do multi-threaded linking */ #undef ENABLE_THREADS @@ -13,15 +19,65 @@ /* Default machine code */ #undef GOLD_DEFAULT_MACHINE +/* Default OSABI code */ +#undef GOLD_DEFAULT_OSABI + /* Default size (32 or 64) */ #undef GOLD_DEFAULT_SIZE +/* Define to 1 if you have the <byteswap.h> header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the `chsize' function. */ +#undef HAVE_CHSIZE + +/* Define to 1 if you have the declaration of `asprintf', and to 0 if you + don't. */ +#undef HAVE_DECL_ASPRINTF + +/* Define to 1 if you have the declaration of `basename', and to 0 if you + don't. */ +#undef HAVE_DECL_BASENAME + +/* Define to 1 if you have the declaration of `ffs', and to 0 if you don't. */ +#undef HAVE_DECL_FFS + +/* Define to 1 if you have the declaration of `memmem', and to 0 if you don't. + */ +#undef HAVE_DECL_MEMMEM + +/* Define to 1 if you have the declaration of `snprintf', and to 0 if you + don't. */ +#undef HAVE_DECL_SNPRINTF + +/* Define to 1 if you have the declaration of `strndup', and to 0 if you + don't. */ +#undef HAVE_DECL_STRNDUP + +/* Define to 1 if you have the declaration of `strverscmp', and to 0 if you + don't. */ +#undef HAVE_DECL_STRVERSCMP + +/* Define to 1 if you have the declaration of `vasprintf', and to 0 if you + don't. */ +#undef HAVE_DECL_VASPRINTF + +/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you + don't. */ +#undef HAVE_DECL_VSNPRINTF + /* Define to 1 if you have the <ext/hash_map> header file. */ #undef HAVE_EXT_HASH_MAP /* Define to 1 if you have the <ext/hash_set> header file. */ #undef HAVE_EXT_HASH_SET +/* Define to 1 if you have the `ffsll' function. */ +#undef HAVE_FFSLL + +/* Define to 1 if you have the `ftruncate' function. */ +#undef HAVE_FTRUNCATE + /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H @@ -31,12 +87,24 @@ /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the `mremap' function. */ +#undef HAVE_MREMAP + /* Define if compiler supports #pragma omp threadprivate */ #undef HAVE_OMP_SUPPORT +/* Define to 1 if you have the `posix_fallocate' function. */ +#undef HAVE_POSIX_FALLOCATE + /* Define to 1 if you have the `pread' function. */ #undef HAVE_PREAD +/* Define to 1 if you have the `readv' function. */ +#undef HAVE_READV + +/* Define if struct stat has a field st_mtim with timespec for mtime */ +#undef HAVE_STAT_ST_MTIM + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H @@ -49,6 +117,9 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H @@ -70,9 +141,15 @@ /* Define if attributes work on C++ templates */ #undef HAVE_TEMPLATE_ATTRIBUTES +/* Define to 1 if you have the `times' function. */ +#undef HAVE_TIMES + /* Define to 1 if you have the <tr1/unordered_map> header file. */ #undef HAVE_TR1_UNORDERED_MAP +/* Define if ::std::tr1::unordered_map::rehash is usable */ +#undef HAVE_TR1_UNORDERED_MAP_REHASH + /* Define to 1 if you have the <tr1/unordered_set> header file. */ #undef HAVE_TR1_UNORDERED_SET @@ -97,6 +174,9 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME +/* Define to the home page for this package. */ +#undef PACKAGE_URL + /* Define to the version of this package. */ #undef PACKAGE_VERSION @@ -109,14 +189,49 @@ /* Whether the system root can be relocated */ #undef TARGET_SYSTEM_ROOT_RELOCATABLE -/* Version number of package */ -#undef VERSION - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -#undef WORDS_BIGENDIAN - +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE diff --git a/binutils-2.19/gold/configure b/binutils-2.19/gold/configure index f2ec1ef..9fd198f 100755..100644 --- a/binutils-2.19/gold/configure +++ b/binutils-2.19/gold/configure @@ -1,81 +1,413 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59 for gold 0.1. +# Generated by GNU Autoconf 2.64 for gold 0.1. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software +# Foundation, Inc. # -# Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac fi -DUALCASE=1; export DUALCASE # for MKS sh -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } fi -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." else - $as_unset $as_var + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." fi -done + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. -as_me=`$as_basename "$0" || +as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` -# PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -83,146 +415,107 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop - s,-$,, - s,^['$as_cr_digits']*\n,, + s/-\n.*// ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" # Exit status is that of the last command. exit } - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file else - as_expr=false + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln else as_ln_s='cp -p' fi -rm -f conf$$ conf$$.exe conf$$.file +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -as_executable_p="test -f" +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -231,38 +524,24 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - +exec 7<&0 </dev/null 6>&1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` -exec 6>&1 - # # Initializations. # ac_default_prefix=/usr/local +ac_clean_files= ac_config_libobj_dir=. +LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME='gold' @@ -270,52 +549,247 @@ PACKAGE_TARNAME='gold' PACKAGE_VERSION='0.1' PACKAGE_STRING='gold 0.1' PACKAGE_BUGREPORT='' +PACKAGE_URL='' ac_unique_file="gold.cc" # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> -#if HAVE_SYS_TYPES_H +#ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif -#if HAVE_SYS_STAT_H +#ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif -#if STDC_HEADERS +#ifdef STDC_HEADERS # include <stdlib.h> # include <stddef.h> #else -# if HAVE_STDLIB_H +# ifdef HAVE_STDLIB_H # include <stdlib.h> # endif #endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include <memory.h> # endif # include <string.h> #endif -#if HAVE_STRINGS_H +#ifdef HAVE_STRINGS_H # include <strings.h> #endif -#if HAVE_INTTYPES_H +#ifdef HAVE_INTTYPES_H # include <inttypes.h> -#else -# if HAVE_STDINT_H -# include <stdint.h> -# endif #endif -#if HAVE_UNISTD_H +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H # include <unistd.h> #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar THREADS_TRUE THREADS_FALSE TARGETOBJS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE OMP_SUPPORT_TRUE OMP_SUPPORT_FALSE TLS_GNU2_DIALECT_TRUE TLS_GNU2_DIALECT_FALSE TLS_DESCRIPTORS_TRUE TLS_DESCRIPTORS_FALSE CONSTRUCTOR_PRIORITY_TRUE CONSTRUCTOR_PRIORITY_FALSE RANDOM_SEED_CFLAGS WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CFLAGS LIBOBJS CPP EGREP HAVE_ZLIB_TRUE HAVE_ZLIB_FALSE CXXCPP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS' +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +CXXCPP +HAVE_ZLIB_FALSE +HAVE_ZLIB_TRUE +LIBOBJS +LFS_CFLAGS +WARN_CXXFLAGS +NO_WERROR +WARN_CFLAGS +RANDOM_SEED_CFLAGS +CONSTRUCTOR_PRIORITY_FALSE +CONSTRUCTOR_PRIORITY_TRUE +TLS_DESCRIPTORS_FALSE +TLS_DESCRIPTORS_TRUE +TLS_GNU2_DIALECT_FALSE +TLS_GNU2_DIALECT_TRUE +OMP_SUPPORT_FALSE +OMP_SUPPORT_TRUE +STATIC_TLS_FALSE +STATIC_TLS_TRUE +TLS_FALSE +TLS_TRUE +MCMODEL_MEDIUM_FALSE +MCMODEL_MEDIUM_TRUE +FN_PTRS_IN_SO_WITHOUT_PIC_FALSE +FN_PTRS_IN_SO_WITHOUT_PIC_TRUE +GCC_FALSE +GCC_TRUE +NATIVE_LINKER_FALSE +NATIVE_LINKER_TRUE +MSGMERGE +MSGFMT +MKINSTALLDIRS +CATOBJEXT +GENCAT +INSTOBJEXT +DATADIRNAME +CATALOGS +POSUB +GMSGFMT +XGETTEXT +INCINTL +LIBINTL_DEP +LIBINTL +USE_NLS +EGREP +GREP +CPP +LN_S +RANLIB +YFLAGS +YACC +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +TARGETOBJS +DEFAULT_TARGET_X86_64_FALSE +DEFAULT_TARGET_X86_64_TRUE +DEFAULT_TARGET_SPARC_FALSE +DEFAULT_TARGET_SPARC_TRUE +DEFAULT_TARGET_POWERPC_FALSE +DEFAULT_TARGET_POWERPC_TRUE +DEFAULT_TARGET_I386_FALSE +DEFAULT_TARGET_I386_TRUE +DEFAULT_TARGET_ARM_FALSE +DEFAULT_TARGET_ARM_TRUE +PLUGINS_FALSE +PLUGINS_TRUE +THREADS_FALSE +THREADS_TRUE +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' ac_subst_files='' -ac_pwd=`pwd` +ac_user_opts=' +enable_option_checking +with_sysroot +enable_threads +enable_plugins +enable_targets +enable_dependency_tracking +enable_nls +enable_werror +enable_build_warnings +enable_maintainer_mode +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +YACC +YFLAGS +CPP +CXXCPP' + # Initialize some variables set by options. ac_init_help= ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null @@ -338,34 +812,48 @@ x_libraries=NONE # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' +datarootdir='${prefix}/share' +datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' ac_prev= +ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" + eval $ac_prev=\$ac_option ac_prev= continue fi - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac # Accept the important Cygnus configure options, so we can diagnose typos. - case $ac_option in + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; @@ -387,33 +875,59 @@ do --config-cache | -C) cache_file=config.cache ;; - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) + -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "enable_$ac_feature='$ac_optarg'" ;; + eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ @@ -440,6 +954,12 @@ do -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; @@ -464,13 +984,16 @@ do | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) + | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) @@ -535,6 +1058,16 @@ do | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; @@ -585,26 +1118,36 @@ do ac_init_version=: ;; -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "with_$ac_package='$ac_optarg'" ;; + eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. @@ -624,26 +1167,25 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; @@ -652,31 +1194,36 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } + as_fn_error "missing argument to $ac_option" fi -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac -done +fi -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir do - eval ac_val=$`echo $ac_var` + eval ac_val=\$$ac_var + # Remove trailing slashes. case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -690,7 +1237,7 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes @@ -703,86 +1250,72 @@ test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi -fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CXX_set=${CXX+set} -ac_env_CXX_value=$CXX -ac_cv_env_CXX_set=${CXX+set} -ac_cv_env_CXX_value=$CXX -ac_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_env_CXXFLAGS_value=$CXXFLAGS -ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} -ac_cv_env_CXXFLAGS_value=$CXXFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP -ac_env_CXXCPP_set=${CXXCPP+set} -ac_env_CXXCPP_value=$CXXCPP -ac_cv_env_CXXCPP_set=${CXXCPP+set} -ac_cv_env_CXXCPP_value=$CXXCPP +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done # # Report the --help message. @@ -811,14 +1344,11 @@ Configuration: -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] -_ACEOF - - cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] + [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] + [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify @@ -828,18 +1358,25 @@ for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/gold] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF @@ -863,9 +1400,11 @@ if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads multi-threaded linking + --enable-plugins linker plugins --enable-targets alternative target configurations --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors @@ -885,131 +1424,810 @@ Some influential environment variables: CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir> - CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have - headers in a nonstandard directory <include dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> CXX C++ compiler command CXXFLAGS C++ compiler flags + YACC The `Yet Another C Compiler' implementation to use. Defaults to + the first program found out of: `bison -y', `byacc', `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. CPP C preprocessor CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. +Report bugs to the package provider. _ACEOF +ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. - ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue ac_builddir=. -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix case $srcdir in - .) # No --srcdir option. We are building in place. + .) # We are building in place. ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd "$ac_popdir" + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } done fi -test -n "$ac_init_help" && exit 0 +test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF gold configure 0.1 -generated by GNU Autoconf 2.59 +generated by GNU Autoconf 2.64 -Copyright (C) 2003 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF - exit 0 + exit fi -exec 5>config.log -cat >&5 <<_ACEOF + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR +# ------------------------------------ +# Tests whether SYMBOL is declared, setting cache variable VAR accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5 +$as_echo_n "checking whether $2 is declared... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $2 + (void) $2; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_decl + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_func + +# ac_fn_cxx_check_decl LINENO SYMBOL VAR +# -------------------------------------- +# Tests whether SYMBOL is declared, setting cache variable VAR accordingly. +ac_fn_cxx_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $2 is declared" >&5 +$as_echo_n "checking whether $2 is declared... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $2 + (void) $2; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_decl +cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by gold $as_me 0.1, which was -generated by GNU Autoconf 2.59. Invocation command line was +generated by GNU Autoconf 2.64. Invocation command line was $ $0 $@ _ACEOF +exec 5>>config.log { cat <<_ASUNAME ## --------- ## @@ -1028,7 +2246,7 @@ uname -v = `(uname -v) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` @@ -1040,8 +2258,9 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS } >&5 @@ -1063,7 +2282,6 @@ _ACEOF ac_configure_args= ac_configure_args0= ac_configure_args1= -ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do @@ -1074,13 +2292,13 @@ do -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" + as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else @@ -1096,21 +2314,19 @@ do -* ) ac_must_keep_next=true ;; esac fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " + as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { @@ -1123,20 +2339,35 @@ trap 'exit_status=$? _ASBOX echo # The following way of writing the cache mishandles newlines in values, -{ +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; - esac; -} + esac | + sort +) echo cat <<\_ASBOX @@ -1147,22 +2378,28 @@ _ASBOX echo for ac_var in $ac_subst_vars do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## +## ------------------- ## +## File substitutions. ## +## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi @@ -1174,26 +2411,26 @@ _ASBOX ## ----------- ## _ASBOX echo - sed "/^$/d" confdefs.h | sort + cat confdefs.h echo fi test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status - ' 0 +' 0 for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. @@ -1201,40 +2438,46 @@ cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + # Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi @@ -1244,80 +2487,79 @@ if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in - [\\/]* | ?:[\\/]* ) . $cache_file;; - *) . ./$cache_file;; + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; esac fi else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do +for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then - # differences in whitespace do not lead to failure. - ac_old_val_w=`echo x $ac_old_val` - ac_new_val_w=`echo x $ac_new_val` - if test "$ac_old_val_w" != "$ac_new_val_w"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5 -echo "$as_me: former value: \`$ac_old_val'" >&2;} - { echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5 -echo "$as_me: current value: \`$ac_new_val'" >&2;} + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -1331,130 +2573,131 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - - - - - - - - ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f $ac_dir/shtool; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + for ac_t in install-sh install.sh shtool; do + if test -f "$ac_dir/$ac_t"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/$ac_t -c" + break 2 + fi + done done if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + # Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } - -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } - -fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if test "${ac_cv_build+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; +esac build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if test "${ac_cv_host+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; +esac host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac -echo "$as_me:$LINENO: checking target system type" >&5 -echo $ECHO_N "checking target system type... $ECHO_C" >&6 -if test "${ac_cv_target+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if test "${ac_cv_target+set}" = set; then : + $as_echo_n "(cached) " >&6 else - ac_cv_target_alias=$target_alias -test "x$ac_cv_target_alias" = "x" && - ac_cv_target_alias=$ac_cv_host_alias -ac_cv_target=`$ac_config_sub $ac_cv_target_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_target_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_target_alias failed" >&2;} - { (exit 1); exit 1; }; } + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi fi -echo "$as_me:$LINENO: result: $ac_cv_target" >&5 -echo "${ECHO_T}$ac_cv_target" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error "invalid value of canonical target" "$LINENO" 5;; +esac target=$ac_cv_target -target_cpu=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -target_vendor=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -target_os=`echo $ac_cv_target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. @@ -1464,7 +2707,8 @@ test -n "$target_alias" && NONENONEs,x,x, && program_prefix=${target_alias}- -am__api_version="1.9" +am__api_version='1.11' + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -1479,22 +2723,22 @@ am__api_version="1.9" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -1502,7 +2746,7 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -1530,7 +2774,9 @@ case $as_dir/ in done ;; esac -done + + done +IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir @@ -1545,8 +2791,8 @@ fi INSTALL=$ac_install_sh fi fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. @@ -1556,21 +2802,34 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -echo "$as_me:$LINENO: checking whether build environment is sane" >&5 -echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` + set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ @@ -1580,11 +2839,8 @@ if ( # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". - { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&5 -echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&2;} - { (exit 1); exit 1; }; } + as_fn_error "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file @@ -1593,81 +2849,206 @@ then # Ok. : else - { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! -Check your system clock" >&5 -echo "$as_me: error: newly created file is older than distributed files! -Check your system clock" >&2;} - { (exit 1); exit 1; }; } + as_fn_error "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } test "$program_prefix" != NONE && - program_transform_name="s,^,$program_prefix,;$program_transform_name" + program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && - program_transform_name="s,\$,$program_suffix,;$program_transform_name" -# Double any \ or $. echo might interpret backslashes. + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. # By default was `s,x,x', remove it if useless. -cat <<\_ACEOF >conftest.sed -s/[\\$]/&&/g;s/;s,x,x,$// -_ACEOF -program_transform_name=`echo $program_transform_name | sed -f conftest.sed` -rm conftest.sed +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= - { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 -echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -fi - -if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" else - mkdir_p='$(install_sh) -d' + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + test -d ./--version && rmdir ./--version + MKDIR_P="$ac_install_sh -d" fi fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_AWK+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. @@ -1677,55 +3058,59 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then - echo "$as_me:$LINENO: result: $AWK" >&5 -echo "${ECHO_T}$AWK" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$AWK" && break done -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF +SHELL = /bin/sh all: - @echo 'ac_maketemp="$(MAKE)"' + @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac rm -f conftest.make fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } SET_MAKE= else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi @@ -1738,12 +3123,14 @@ else fi rmdir .tst 2>/dev/null -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 -echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} - { (exit 1); exit 1; }; } +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi fi # test whether we have cygpath @@ -1786,96 +3173,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -install_sh=${install_sh-"$am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - - test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - STRIP=$ac_ct_STRIP -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" - # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. @@ -1889,17 +3186,17 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' - ac_config_headers="$ac_config_headers config.h:config.in" +ac_config_headers="$ac_config_headers config.h:config.in" -# Check whether --with-sysroot or --without-sysroot was given. -if test "${with_sysroot+set}" = set; then - withval="$with_sysroot" - sysroot=$withval +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; sysroot=$withval else sysroot=no -fi; +fi + if test "$sysroot" = "yes"; then sysroot='${exec_prefix}/${target_alias}/sys-root' @@ -1930,27 +3227,23 @@ cat >>confdefs.h <<_ACEOF _ACEOF -# Check whether --enable-threads or --disable-threads was given. -if test "${enable_threads+set}" = set; then - enableval="$enable_threads" - case "${enableval}" in +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; case "${enableval}" in yes | "") threads=yes ;; no) threads=no ;; *) threads=yes ;; esac else threads=no -fi; +fi + if test "$threads" = "yes"; then -cat >>confdefs.h <<\_ACEOF -#define ENABLE_THREADS 1 -_ACEOF +$as_echo "#define ENABLE_THREADS 1" >>confdefs.h fi - - -if test "$threads" = "yes"; then + if test "$threads" = "yes"; then THREADS_TRUE= THREADS_FALSE='#' else @@ -1959,14 +3252,36 @@ else fi -# Check whether --enable-targets or --disable-targets was given. -if test "${enable_targets+set}" = set; then - enableval="$enable_targets" - case "${enableval}" in +# Check whether --enable-plugins was given. +if test "${enable_plugins+set}" = set; then : + enableval=$enable_plugins; case "${enableval}" in + yes | "") plugins=yes ;; + no) plugins=no ;; + *) plugins=yes ;; + esac +else + plugins=no +fi + +if test "$plugins" = "yes"; then + +$as_echo "#define ENABLE_PLUGINS 1" >>confdefs.h + +fi + if test "$plugins" = "yes"; then + PLUGINS_TRUE= + PLUGINS_FALSE='#' +else + PLUGINS_TRUE='#' + PLUGINS_FALSE= +fi + + +# Check whether --enable-targets was given. +if test "${enable_targets+set}" = set; then : + enableval=$enable_targets; case "${enableval}" in yes | "") - { { echo "$as_me:$LINENO: error: --enable-targets option must specify target names or 'all'" >&5 -echo "$as_me: error: --enable-targets option must specify target names or 'all'" >&2;} - { (exit 1); exit 1; }; } + as_fn_error "--enable-targets option must specify target names or 'all'" "$LINENO" 5 ;; no) enable_targets= @@ -1979,7 +3294,8 @@ else # For now, enable all targets by default enable_targets=all -fi; +fi + # Canonicalize the enabled targets. if test -n "$enable_targets"; then @@ -2000,6 +3316,7 @@ all_targets= default_machine= default_size= default_big_endian= +default_osabi=ELFOSABI_NONE targ_32_little= targ_32_big= targ_64_little= @@ -2015,9 +3332,7 @@ for targ in $target $canon_targets; do . ${srcdir}/configure.tgt if test "$targ_obj" = "UNKNOWN"; then - { { echo "$as_me:$LINENO: error: \"unsupported target $targ\"" >&5 -echo "$as_me: error: \"unsupported target $targ\"" >&2;} - { (exit 1); exit 1; }; } + as_fn_error "\"unsupported target $targ\"" "$LINENO" 5 else targetobjs="$targetobjs ${targ_obj}.\$(OBJEXT)" if test "$targ_extra_obj" != ""; then @@ -2048,37 +3363,81 @@ echo "$as_me: error: \"unsupported target $targ\"" >&2;} default_machine=$targ_machine default_size=$targ_size default_big_endian=$targ_big_endian + default_osabi=$targ_osabi + + if test "$targ_obj" = "arm"; then + DEFAULT_TARGET_ARM_TRUE= + DEFAULT_TARGET_ARM_FALSE='#' +else + DEFAULT_TARGET_ARM_TRUE='#' + DEFAULT_TARGET_ARM_FALSE= +fi + + if test "$targ_obj" = "i386"; then + DEFAULT_TARGET_I386_TRUE= + DEFAULT_TARGET_I386_FALSE='#' +else + DEFAULT_TARGET_I386_TRUE='#' + DEFAULT_TARGET_I386_FALSE= +fi + + if test "$targ_obj" = "powerpc"; then + DEFAULT_TARGET_POWERPC_TRUE= + DEFAULT_TARGET_POWERPC_FALSE='#' +else + DEFAULT_TARGET_POWERPC_TRUE='#' + DEFAULT_TARGET_POWERPC_FALSE= +fi + + if test "$targ_obj" = "sparc"; then + DEFAULT_TARGET_SPARC_TRUE= + DEFAULT_TARGET_SPARC_FALSE='#' +else + DEFAULT_TARGET_SPARC_TRUE='#' + DEFAULT_TARGET_SPARC_FALSE= +fi + + if test "$targ_obj" = "x86_64"; then + DEFAULT_TARGET_X86_64_TRUE= + DEFAULT_TARGET_X86_64_FALSE='#' +else + DEFAULT_TARGET_X86_64_TRUE='#' + DEFAULT_TARGET_X86_64_FALSE= +fi + fi fi fi done +# Remove any duplicates. +to="" +for t in $targetobjs; do + case " $to " in + *" $t "*) ;; + *) to="$to $t" ;; + esac +done +targetobjs=$to + if test -n "$targ_32_little"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TARGET_32_LITTLE 1 -_ACEOF +$as_echo "#define HAVE_TARGET_32_LITTLE 1" >>confdefs.h fi if test -n "$targ_32_big"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TARGET_32_BIG 1 -_ACEOF +$as_echo "#define HAVE_TARGET_32_BIG 1" >>confdefs.h fi if test -n "$targ_64_little"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TARGET_64_LITTLE 1 -_ACEOF +$as_echo "#define HAVE_TARGET_64_LITTLE 1" >>confdefs.h fi if test -n "$targ_64_big"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TARGET_64_BIG 1 -_ACEOF +$as_echo "#define HAVE_TARGET_64_BIG 1" >>confdefs.h fi @@ -2105,6 +3464,11 @@ cat >>confdefs.h <<_ACEOF _ACEOF +cat >>confdefs.h <<_ACEOF +#define GOLD_DEFAULT_OSABI $default_osabi +_ACEOF + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2113,10 +3477,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2126,35 +3490,37 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. @@ -2164,39 +3530,50 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - CC=$ac_ct_CC + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2206,77 +3583,37 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi + fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2287,18 +3624,19 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. @@ -2316,24 +3654,25 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then - for ac_prog in cl + for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -2343,39 +3682,41 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC - for ac_prog in cl + for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. @@ -2385,68 +3726,78 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$ac_ct_CC" && break done - CC=$ac_ct_CC + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi fi fi -test -z "$CC" && { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 - (eval $ac_compiler --version </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 - (eval $ac_compiler -v </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 - (eval $ac_compiler -V </dev/null >&5) 2>&5 +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + rm -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2458,116 +3809,142 @@ main () } _ACEOF ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. - -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. break;; * ) break;; esac done +test "$ac_cv_exeext" = no && ac_cv_exeext= + else - echo "$as_me: failed program was:" >&5 + ac_file='' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +if test -z "$ac_file"; then : + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; }; } +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "C compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } fi - ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 -# Check the compiler produces executables we can run. If not, either +# Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else - { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } +See \`config.log' for more details." "$LINENO" 5; } fi fi fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -rm -f a.out a.exe conftest$ac_cv_exeext b.out +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either +# Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -2575,40 +3952,31 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext break;; * ) break;; esac done else - { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } fi - rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2620,47 +3988,46 @@ main () } _ACEOF rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else - echo "$as_me: failed program was:" >&5 + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } fi - rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2674,54 +4041,34 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no + ac_compiler_gnu=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2732,38 +4079,49 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -ac_cv_prog_cc_g=no +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then @@ -2779,18 +4137,14 @@ else CFLAGS= fi fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 else - ac_cv_prog_cc_stdc=no + ac_cv_prog_cc_c89=no ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdarg.h> #include <stdio.h> @@ -2818,12 +4172,17 @@ static char *f (char * (*g) (char **, int), char **p, ...) /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get + as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ + that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; @@ -2838,201 +4197,37 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; return 0; } _ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg fi -rm -f conftest.err conftest.$ac_objext +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break done -rm -f conftest.$ac_ext conftest.$ac_objext +rm -f conftest.$ac_ext CC=$ac_save_CC fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac +if test "x$ac_cv_prog_cc_c89" != xno; then : -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include <stdlib.h> -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3040,60 +4235,58 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" - ac_config_commands="$ac_config_commands depfiles" +ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: - @echo done + @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. -echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 -echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac fi -echo "$as_me:$LINENO: result: $_am_result" >&5 -echo "${ECHO_T}$_am_result" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } rm -f confinc confmf -# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then - enableval="$enable_dependency_tracking" +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi -fi; if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi - - -if test "x$enable_dependency_tracking" != xno; then + if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else @@ -3103,13 +4296,12 @@ fi - depcc="$CC" am_compiler_list= -echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up @@ -3134,6 +4326,11 @@ else if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -3151,7 +4348,17 @@ else done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -3161,18 +4368,23 @@ else break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -3196,13 +4408,11 @@ else fi fi -echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - -if + if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= @@ -3213,20 +4423,24 @@ else fi -ac_ext=cc +ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -n "$ac_tool_prefix"; then - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. @@ -3236,39 +4450,41 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then - echo "$as_me:$LINENO: result: $CXX" >&5 -echo "${ECHO_T}$CXX" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX - for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. @@ -3278,64 +4494,77 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then - echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 -echo "${ECHO_T}$ac_ct_CXX" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$ac_ct_CXX" && break done -test -n "$ac_ct_CXX" || ac_ct_CXX="g++" - CXX=$ac_ct_CXX + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi fi - + fi +fi # Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C++ compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 - (eval $ac_compiler --version </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 - (eval $ac_compiler -v </dev/null >&5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 - (eval $ac_compiler -V </dev/null >&5) 2>&5 +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + rm -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done -echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -3349,54 +4578,34 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no + ac_compiler_gnu=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi -echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 -GXX=`test $ac_compiler_gnu = yes && echo yes` +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS -CXXFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 -echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cxx_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -3407,157 +4616,64 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_prog_cxx_g=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_declaration -#include <stdlib.h> + int main () { -exit (42); + ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_cxx_try_compile "$LINENO"; then : -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$ac_declaration + int main () { -exit (42); + ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi fi - ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3566,10 +4682,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CXX" am_compiler_list= -echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 -if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up @@ -3594,6 +4710,11 @@ else if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and @@ -3611,7 +4732,17 @@ else done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested @@ -3621,18 +4752,23 @@ else break fi ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; none) break ;; esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message @@ -3656,13 +4792,11 @@ else fi fi -echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - -if + if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= @@ -3677,10 +4811,10 @@ for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_YACC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_YACC+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. @@ -3690,26 +4824,28 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_YACC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then - echo "$as_me:$LINENO: result: $YACC" >&5 -echo "${ECHO_T}$YACC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +$as_echo "$YACC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" @@ -3717,10 +4853,10 @@ test -n "$YACC" || YACC="yacc" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. @@ -3730,35 +4866,37 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then - echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. @@ -3768,139 +4906,514 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS - test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then - echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - RANLIB=$ac_ct_RANLIB + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi else RANLIB="$ac_cv_prog_RANLIB" fi -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -# Reject install programs that cannot install multiple files. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - rm -rf conftest.one conftest.two conftest.dir - echo one > conftest.one - echo two > conftest.two - mkdir conftest.dir - if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && - test -s conftest.one && test -s conftest.two && - test -s conftest.dir/conftest.one && - test -s conftest.dir/conftest.two - then - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - fi - done - done - ;; + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac -done -rm -rf conftest.one conftest.two conftest.dir + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi +else + ac_cv_path_EGREP=$EGREP fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> -echo "$as_me:$LINENO: checking whether ln -s works" >&5 -echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 -LN_S=$as_ln_s -if test "$LN_S" = "ln -s"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes else - echo "$as_me:$LINENO: result: no, using $LN_S" >&5 -echo "${ECHO_T}no, using $LN_S" >&6 + ac_cv_header_stdc=no fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : +else + ac_cv_header_stdc=no +fi +rm -f conftest* +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> -cat >>confdefs.h <<\_ACEOF -#define _GNU_SOURCE 1 _ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = x""yes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if test "${ac_cv_safe_to_define___extensions__+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + @@ -3917,22 +5430,20 @@ POSUB= if test -f ../intl/config.intl; then . ../intl/config.intl fi -echo "$as_me:$LINENO: checking whether NLS is requested" >&5 -echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } if test x"$USE_NLS" != xyes; then - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } else - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } -cat >>confdefs.h <<\_ACEOF -#define ENABLE_NLS 1 -_ACEOF +$as_echo "#define ENABLE_NLS 1" >>confdefs.h - echo "$as_me:$LINENO: checking for catalogs to be installed" >&5 -echo $ECHO_N "checking for catalogs to be installed... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 +$as_echo_n "checking for catalogs to be installed... " >&6; } # Look for .po and .gmo files in the source directory. CATALOGS= XLINGUAS= @@ -3963,8 +5474,8 @@ echo $ECHO_N "checking for catalogs to be installed... $ECHO_C" >&6 fi done LINGUAS="$XLINGUAS" - echo "$as_me:$LINENO: result: $LINGUAS" >&5 -echo "${ECHO_T}$LINGUAS" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 +$as_echo "$LINGUAS" >&6; } DATADIRNAME=share @@ -3990,17 +5501,17 @@ fi - echo "$as_me:$LINENO: checking whether NLS is requested" >&5 -echo $ECHO_N "checking whether NLS is requested... $ECHO_C" >&6 - # Check whether --enable-nls or --disable-nls was given. -if test "${enable_nls+set}" = set; then - enableval="$enable_nls" - USE_NLS=$enableval + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval else USE_NLS=yes -fi; - echo "$as_me:$LINENO: result: $USE_NLS" >&5 -echo "${ECHO_T}$USE_NLS" >&6 +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } @@ -4037,10 +5548,10 @@ rm -f conf$$.file # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_MSGFMT+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 else case "$MSGFMT" in [\\/]* | ?:[\\/]*) @@ -4068,19 +5579,19 @@ esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then - echo "$as_me:$LINENO: result: $MSGFMT" >&5 -echo "${ECHO_T}$MSGFMT" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_GMSGFMT+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_GMSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) @@ -4092,31 +5603,32 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT - if test -n "$GMSGFMT"; then - echo "$as_me:$LINENO: result: $GMSGFMT" >&5 -echo "${ECHO_T}$GMSGFMT" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + # Prepare PATH_SEPARATOR. # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then @@ -4147,10 +5659,10 @@ rm -f conf$$.file # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_XGETTEXT+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_XGETTEXT+set}" = set; then : + $as_echo_n "(cached) " >&6 else case "$XGETTEXT" in [\\/]* | ?:[\\/]*) @@ -4178,11 +5690,11 @@ esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then - echo "$as_me:$LINENO: result: $XGETTEXT" >&5 -echo "${ECHO_T}$XGETTEXT" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi rm -f messages.po @@ -4218,10 +5730,10 @@ rm -f conf$$.file # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_MSGMERGE+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGMERGE+set}" = set; then : + $as_echo_n "(cached) " >&6 else case "$MSGMERGE" in [\\/]* | ?:[\\/]*) @@ -4248,11 +5760,11 @@ esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then - echo "$as_me:$LINENO: result: $MSGMERGE" >&5 -echo "${ECHO_T}$MSGMERGE" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi @@ -4262,8 +5774,8 @@ fi : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` - echo "$as_me:$LINENO: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 -echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 +$as_echo "found $GMSGFMT program is not GNU msgfmt; ignore it" >&6; } GMSGFMT=":" fi fi @@ -4273,251 +5785,245 @@ echo "${ECHO_T}found $GMSGFMT program is not GNU msgfmt; ignore it" >&6 (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else - echo "$as_me:$LINENO: result: found xgettext program is not GNU xgettext; ignore it" >&5 -echo "${ECHO_T}found xgettext program is not GNU xgettext; ignore it" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 +$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } XGETTEXT=":" fi rm -f messages.po fi - ac_config_commands="$ac_config_commands default-1" - + ac_config_commands="$ac_config_commands default-1" -echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 -echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 -if test "${ac_cv_c_bigendian+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then : + $as_echo_n "(cached) " >&6 else - # See if sys/param.h defines the BYTE_ORDER macro. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <sys/types.h> -#include <sys/param.h> + #include <sys/param.h> int main () { -#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN - bogus endian macros -#endif +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <sys/types.h> -#include <sys/param.h> + #include <sys/param.h> int main () { #if BYTE_ORDER != BIG_ENDIAN - not big endian -#endif + not big endian + #endif ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_bigendian=no + ac_cv_c_bigendian=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> -# It does not; compile a test program. -if test "$cross_compiling" = yes; then - # try to guess the endianness by grepping values into an object file - ac_cv_c_bigendian=unknown - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} _ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; -short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; -void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } -short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; -short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; -void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +#include <limits.h> + int main () { - _ascii (); _ebcdic (); +#ifndef _BIG_ENDIAN + not big endian + #endif + ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no fi -if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then - if test "$ac_cv_c_bigendian" = unknown; then - ac_cv_c_bigendian=no - else - # finding both strings is unlikely to happen, but who knows? - ac_cv_c_bigendian=unknown - fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +$ac_includes_default int main () { - /* Are we little or big endian? From Harbison&Steele. */ - union - { - long l; - char c[sizeof (long)]; - } u; - u.l = 1; - exit (u.c[sizeof (long) - 1] == 1); + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_c_bigendian=yes -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi + ac_cv_c_bigendian=yes fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 -echo "${ECHO_T}$ac_cv_c_bigendian" >&6 -case $ac_cv_c_bigendian in - yes) - -cat >>confdefs.h <<\_ACEOF -#define WORDS_BIGENDIAN 1 -_ACEOF - ;; - no) - ;; - *) - { { echo "$as_me:$LINENO: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&5 -echo "$as_me: error: unknown endianness -presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} - { (exit 1); exit 1; }; } ;; -esac - + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac -if test "x$target_alias" = "x" -o "x$host_alias" = "x$target_alias"; then + if test "x$target_alias" = "x" -o "x$host_alias" = "x$target_alias"; then NATIVE_LINKER_TRUE= NATIVE_LINKER_FALSE='#' else @@ -4525,9 +6031,7 @@ else NATIVE_LINKER_FALSE= fi - - -if test "$GCC" = yes; then + if test "$GCC" = yes; then GCC_TRUE= GCC_FALSE='#' else @@ -4536,9 +6040,7 @@ else fi - - -if + if case $target_cpu in i?86) true;; x86_64) false;; @@ -4553,50 +6055,60 @@ else fi -echo "$as_me:$LINENO: checking for thread support" >&5 -echo $ECHO_N "checking for thread support... $ECHO_C" >&6 -if test "${gold_cv_c_thread+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc >= 4.1" >&5 +$as_echo_n "checking for gcc >= 4.1... " >&6; } +if test "${gold_cv_prog_gcc41+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -__thread int i = 1; + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if !defined __GNUC__ +error +#elif __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) +error +#endif + _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - gold_cv_c_thread=yes +if ac_fn_c_try_compile "$LINENO"; then : + gold_cv_prog_gcc41=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_c_thread=no + gold_cv_prog_gcc41=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $gold_cv_c_thread" >&5 -echo "${ECHO_T}$gold_cv_c_thread" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_prog_gcc41" >&5 +$as_echo "$gold_cv_prog_gcc41" >&6; } + if test "$target_cpu" = "x86_64" -a "$gold_cv_prog_gcc41" = "yes"; then + MCMODEL_MEDIUM_TRUE= + MCMODEL_MEDIUM_FALSE='#' +else + MCMODEL_MEDIUM_TRUE='#' + MCMODEL_MEDIUM_FALSE= +fi -if test "$gold_cv_c_thread" = "yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread support" >&5 +$as_echo_n "checking for thread support... " >&6; } +if test "${gold_cv_c_thread+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__thread int i = 1; +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gold_cv_c_thread=yes +else + gold_cv_c_thread=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_c_thread" >&5 +$as_echo "$gold_cv_c_thread" >&6; } + + if test "$gold_cv_c_thread" = "yes"; then TLS_TRUE= TLS_FALSE='#' else @@ -4605,12 +6117,13 @@ else fi -echo "$as_me:$LINENO: checking for glibc >= 2.4" >&5 -echo $ECHO_N "checking for glibc >= 2.4... $ECHO_C" >&6 -if test "${gold_cv_lib_glibc24+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc >= 2.4" >&5 +$as_echo_n "checking for glibc >= 2.4... " >&6; } +if test "${gold_cv_lib_glibc24+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ #include <features.h> #if !defined __GLIBC__ @@ -4620,42 +6133,17 @@ error #endif _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : gold_cv_lib_glibc24=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_lib_glibc24=no + gold_cv_lib_glibc24=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $gold_cv_lib_glibc24" >&5 -echo "${ECHO_T}$gold_cv_lib_glibc24" >&6 - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_lib_glibc24" >&5 +$as_echo "$gold_cv_lib_glibc24" >&6; } - -if test "$gold_cv_lib_glibc24" = "yes"; then + if test "$gold_cv_lib_glibc24" = "yes"; then STATIC_TLS_TRUE= STATIC_TLS_FALSE='#' else @@ -4664,63 +6152,37 @@ else fi -echo "$as_me:$LINENO: checking for omp support" >&5 -echo $ECHO_N "checking for omp support... $ECHO_C" >&6 -if test "${gold_cv_c_threadprivate+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for omp support" >&5 +$as_echo_n "checking for omp support... " >&6; } +if test "${gold_cv_c_threadprivate+set}" = set; then : + $as_echo_n "(cached) " >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fopenmp" -cat >conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ #include <omp.h> int i; #pragma omp threadprivate (i) _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : gold_cv_c_threadprivate=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_c_threadprivate=no + gold_cv_c_threadprivate=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" fi -echo "$as_me:$LINENO: result: $gold_cv_c_threadprivate" >&5 -echo "${ECHO_T}$gold_cv_c_threadprivate" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_c_threadprivate" >&5 +$as_echo "$gold_cv_c_threadprivate" >&6; } if test "$gold_cv_c_threadprivate" = "yes"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_OMP_SUPPORT 1 -_ACEOF +$as_echo "#define HAVE_OMP_SUPPORT 1" >>confdefs.h fi - - -if test "$gold_cv_c_threadprivate" = "yes"; then + if test "$gold_cv_c_threadprivate" = "yes"; then OMP_SUPPORT_TRUE= OMP_SUPPORT_FALSE='#' else @@ -4731,42 +6193,18 @@ fi save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -mtls-dialect=gnu2" -cat >conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ int i; _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : have_tls_gnu2=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -have_tls_gnu2=no + have_tls_gnu2=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" - - -if test "$have_tls_gnu2" = "yes"; then + if test "$have_tls_gnu2" = "yes"; then TLS_GNU2_DIALECT_TRUE= TLS_GNU2_DIALECT_FALSE='#' else @@ -4775,57 +6213,33 @@ else fi -echo "$as_me:$LINENO: checking for glibc >= 2.5" >&5 -echo $ECHO_N "checking for glibc >= 2.5... $ECHO_C" >&6 -if test "${gold_cv_lib_glibc25+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc >= 2.9" >&5 +$as_echo_n "checking for glibc >= 2.9... " >&6; } +if test "${gold_cv_lib_glibc29+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ #include <features.h> #if !defined __GLIBC__ error -#elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 5) +#elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 9) error #endif _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - gold_cv_lib_glibc25=yes +if ac_fn_c_try_compile "$LINENO"; then : + gold_cv_lib_glibc29=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_lib_glibc25=no + gold_cv_lib_glibc29=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $gold_cv_lib_glibc25" >&5 -echo "${ECHO_T}$gold_cv_lib_glibc25" >&6 - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_lib_glibc29" >&5 +$as_echo "$gold_cv_lib_glibc29" >&6; } -if test "$gold_cv_lib_glibc25" = "yes"; then + if test "$gold_cv_lib_glibc29" = "yes"; then TLS_DESCRIPTORS_TRUE= TLS_DESCRIPTORS_FALSE='#' else @@ -4834,50 +6248,26 @@ else fi -echo "$as_me:$LINENO: checking for constructor priorities" >&5 -echo $ECHO_N "checking for constructor priorities... $ECHO_C" >&6 -if test "${gold_cv_c_conprio+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for constructor priorities" >&5 +$as_echo_n "checking for constructor priorities... " >&6; } +if test "${gold_cv_c_conprio+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ void f() __attribute__ ((constructor (1))); _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : gold_cv_c_conprio=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_c_conprio=no + gold_cv_c_conprio=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $gold_cv_c_conprio" >&5 -echo "${ECHO_T}$gold_cv_c_conprio" >&6 - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_c_conprio" >&5 +$as_echo "$gold_cv_c_conprio" >&6; } -if test "$gold_cv_c_conprio" = "yes"; then + if test "$gold_cv_c_conprio" = "yes"; then CONSTRUCTOR_PRIORITY_TRUE= CONSTRUCTOR_PRIORITY_FALSE='#' else @@ -4886,49 +6276,27 @@ else fi -echo "$as_me:$LINENO: checking for -frandom-seed support" >&5 -echo $ECHO_N "checking for -frandom-seed support... $ECHO_C" >&6 -if test "${gold_cv_c_random_seed+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -frandom-seed support" >&5 +$as_echo_n "checking for -frandom-seed support... " >&6; } +if test "${gold_cv_c_random_seed+set}" = set; then : + $as_echo_n "(cached) " >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -frandom-seed=foo" -cat >conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ int i; _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : gold_cv_c_random_seed=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_c_random_seed=no + gold_cv_c_random_seed=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" fi -echo "$as_me:$LINENO: result: $gold_cv_c_random_seed" >&5 -echo "${ECHO_T}$gold_cv_c_random_seed" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_c_random_seed" >&5 +$as_echo "$gold_cv_c_random_seed" >&6; } if test "$gold_cv_c_random_seed" = "yes"; then # In Makefile, '$@' will be expanded to be the name of the file # being built, providing a unique seed for each file. @@ -4937,19 +6305,17 @@ fi -GCC_WARN_CFLAGS="-W -Wall -Wstrict-prototypes -Wmissing-prototypes" +GCC_WARN_CFLAGS="-W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow" -# Check whether --enable-werror or --disable-werror was given. -if test "${enable_werror+set}" = set; then - enableval="$enable_werror" - case "${enableval}" in +# Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then : + enableval=$enable_werror; case "${enableval}" in yes | y) ERROR_ON_WARNING="yes" ;; no | n) ERROR_ON_WARNING="no" ;; - *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-werror" >&5 -echo "$as_me: error: bad value ${enableval} for --enable-werror" >&2;} - { (exit 1); exit 1; }; } ;; + *) as_fn_error "bad value ${enableval} for --enable-werror" "$LINENO" 5 ;; esac -fi; +fi + # Enable -Wno-format by default when using gcc on mingw case "${host}" in @@ -4976,10 +6342,9 @@ if test "${GCC}" = yes ; then WARN_CFLAGS="${GCC_WARN_CFLAGS}" fi -# Check whether --enable-build-warnings or --disable-build-warnings was given. -if test "${enable_build_warnings+set}" = set; then - enableval="$enable_build_warnings" - case "${enableval}" in +# Check whether --enable-build-warnings was given. +if test "${enable_build_warnings+set}" = set; then : + enableval=$enable_build_warnings; case "${enableval}" in yes) WARN_CFLAGS="${GCC_WARN_CFLAGS}";; no) if test "${GCC}" = yes ; then WARN_CFLAGS="-w" @@ -4990,7 +6355,8 @@ if test "${enable_build_warnings+set}" = set; then WARN_CFLAGS="${t} ${GCC_WARN_CFLAGS}";; *) WARN_CFLAGS=`echo "${enableval}" | sed -e "s/,/ /g"`;; esac -fi; +fi + if test x"$silent" != x"yes" && test x"$WARN_CFLAGS" != x""; then echo "Setting warning flags = $WARN_CFLAGS" 6>&1 @@ -5000,117 +6366,38 @@ fi -WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//'` +WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//' -e 's/-Wshadow//'` LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" - -for ac_func in pread -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. - For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - <limits.h> exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} +for ac_func in chsize +do : + ac_fn_c_check_func "$LINENO" "chsize" "ac_cv_func_chsize" +if test "x$ac_cv_func_chsize" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CHSIZE 1 _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 -eval "$as_ac_var=no" fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then +done + +for ac_func in pread ftruncate mremap ffsll +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else - case $LIBOBJS in - "$ac_func.$ac_objext" | \ - *" $ac_func.$ac_objext" | \ - "$ac_func.$ac_objext "* | \ + case " $LIBOBJS " in *" $ac_func.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" ;; + *) LIBOBJS="$LIBOBJS $ac_func.$ac_objext" + ;; esac fi @@ -5119,778 +6406,155 @@ done # Link in zlib if we can. This allows us to write compressed sections. -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing zlibVersion" >&5 +$as_echo_n "checking for library containing zlibVersion... " >&6; } +if test "${ac_cv_search_zlibVersion+set}" = set; then : + $as_echo_n "(cached) " >&6 else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" - do - ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" #endif - Syntax error +char zlibVersion (); +int +main () +{ +return zlibVersion (); + ; + return 0; +} _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag +for ac_lib in '' z; do + if test -z "$ac_lib"; then + ac_res="none required" else - ac_cpp_err= + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi -else - ac_cpp_err=yes + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_zlibVersion=$ac_res fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ac_nonexistent.h> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_zlibVersion+set}" = set; then : break fi +done +if test "${ac_cv_search_zlibVersion+set}" = set; then : - done - ac_cv_prog_CPP=$CPP - -fi - CPP=$ac_cv_prog_CPP else - ac_cv_prog_CPP=$CPP + ac_cv_search_zlibVersion=no fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 -ac_preproc_ok=false -for ac_c_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - # <limits.h> exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - Syntax error -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS fi -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether non-existent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ac_nonexistent.h> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_zlibVersion" >&5 +$as_echo "$ac_cv_search_zlibVersion" >&6; } +ac_res=$ac_cv_search_zlibVersion +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. -ac_preproc_ok=: -break fi -rm -f conftest.err conftest.$ac_ext done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' - fi fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <float.h> - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <string.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : + if test "$ac_cv_search_zlibVersion" != "no"; then + HAVE_ZLIB_TRUE= + HAVE_ZLIB_FALSE='#' else - ac_cv_header_stdc=no + HAVE_ZLIB_TRUE='#' + HAVE_ZLIB_FALSE= fi -rm -f conftest* -fi -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <stdlib.h> - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : +ac_fn_c_check_decl "$LINENO" "basename" "ac_cv_have_decl_basename" "$ac_includes_default" +if test "x$ac_cv_have_decl_basename" = x""yes; then : + ac_have_decl=1 else - ac_cv_header_stdc=no + ac_have_decl=0 fi -rm -f conftest* -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <ctype.h> -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); -} +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BASENAME $ac_have_decl _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : +ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "$ac_includes_default" +if test "x$ac_cv_have_decl_ffs" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - + ac_have_decl=0 fi -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FFS $ac_have_decl _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" +ac_fn_c_check_decl "$LINENO" "asprintf" "ac_cv_have_decl_asprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_asprintf" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + ac_have_decl=0 fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF -fi - -done - - -echo "$as_me:$LINENO: checking for library containing zlibVersion" >&5 -echo $ECHO_N "checking for library containing zlibVersion... $ECHO_C" >&6 -if test "${ac_cv_search_zlibVersion+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_func_search_save_LIBS=$LIBS -ac_cv_search_zlibVersion=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char zlibVersion (); -int -main () -{ -zlibVersion (); - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ASPRINTF $ac_have_decl _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_zlibVersion="none required" +ac_fn_c_check_decl "$LINENO" "vasprintf" "ac_cv_have_decl_vasprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_vasprintf" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - + ac_have_decl=0 fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_zlibVersion" = no; then - for ac_lib in z; do - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char zlibVersion (); -int -main () -{ -zlibVersion (); - ; - return 0; -} +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_VASPRINTF $ac_have_decl _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_zlibVersion="-l$ac_lib" -break +ac_fn_c_check_decl "$LINENO" "snprintf" "ac_cv_have_decl_snprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_snprintf" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done -fi -LIBS=$ac_func_search_save_LIBS + ac_have_decl=0 fi -echo "$as_me:$LINENO: result: $ac_cv_search_zlibVersion" >&5 -echo "${ECHO_T}$ac_cv_search_zlibVersion" >&6 -if test "$ac_cv_search_zlibVersion" != no; then - test "$ac_cv_search_zlibVersion" = "none required" || LIBS="$ac_cv_search_zlibVersion $LIBS" -for ac_header in zlib.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SNPRINTF $ac_have_decl _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes +ac_fn_c_check_decl "$LINENO" "vsnprintf" "ac_cv_have_decl_vsnprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_vsnprintf" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no + ac_have_decl=0 fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_VSNPRINTF $ac_have_decl _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes +ac_fn_c_check_decl "$LINENO" "strverscmp" "ac_cv_have_decl_strverscmp" "$ac_includes_default" +if test "x$ac_cv_have_decl_strverscmp" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no + ac_have_decl=0 fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------- ## -## Report this to the gold lists. ## -## ------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRVERSCMP $ac_have_decl _ACEOF -fi - -done - -fi - - - -if test "$ac_cv_search_zlibVersion" != "no"; then - HAVE_ZLIB_TRUE= - HAVE_ZLIB_FALSE='#' -else - HAVE_ZLIB_TRUE='#' - HAVE_ZLIB_FALSE= -fi - -ac_ext=cc +ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' @@ -5898,16 +6562,16 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -ac_ext=cc +ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if test "${ac_cv_prog_CXXCPP+set}" = set; then : + $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" @@ -5921,11 +6585,7 @@ do # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> @@ -5934,68 +6594,24 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_cxx_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext - # OK, works on sane cases. Now check whether non-existent headers + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then +if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break @@ -6005,7 +6621,7 @@ rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then +if $ac_preproc_ok; then : break fi @@ -6017,8 +6633,8 @@ fi else ac_cv_prog_CXXCPP=$CXXCPP fi -echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do @@ -6028,11 +6644,7 @@ do # <limits.h> exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include <limits.h> @@ -6041,68 +6653,24 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_cxx_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext - # OK, works on sane cases. Now check whether non-existent headers + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <ac_nonexistent.h> _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then +if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break @@ -6112,436 +6680,214 @@ rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : +if $ac_preproc_ok; then : + else - { { echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 -echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } fi -ac_ext=cc +ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - for ac_header in tr1/unordered_set tr1/unordered_map -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 -ac_header_compiler=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> +done + +for ac_header in ext/hash_map ext/hash_set +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - ac_header_preproc=no fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------- ## -## Report this to the gold lists. ## -## ------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +done -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then +for ac_header in byteswap.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default" +if test "x$ac_cv_header_byteswap_h" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define HAVE_BYTESWAP_H 1 _ACEOF fi done +for ac_func in mallinfo posix_fallocate readv sysconf times +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF - -for ac_header in ext/hash_map ext/hash_set -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +done + +ac_fn_cxx_check_decl "$LINENO" "basename" "ac_cv_have_decl_basename" "$ac_includes_default" +if test "x$ac_cv_have_decl_basename" = x""yes; then : + ac_have_decl=1 else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BASENAME $ac_have_decl _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes +ac_fn_cxx_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "$ac_includes_default" +if test "x$ac_cv_have_decl_ffs" = x""yes; then : + ac_have_decl=1 else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no + ac_have_decl=0 fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FFS $ac_have_decl _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi +ac_fn_cxx_check_decl "$LINENO" "asprintf" "ac_cv_have_decl_asprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_asprintf" = x""yes; then : + ac_have_decl=1 else - ac_cpp_err=yes + ac_have_decl=0 fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - ac_header_preproc=no +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ASPRINTF $ac_have_decl +_ACEOF +ac_fn_cxx_check_decl "$LINENO" "vasprintf" "ac_cv_have_decl_vasprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_vasprintf" = x""yes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------- ## -## Report this to the gold lists. ## -## ------------------------------- ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_VASPRINTF $ac_have_decl +_ACEOF +ac_fn_cxx_check_decl "$LINENO" "snprintf" "ac_cv_have_decl_snprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_snprintf" = x""yes; then : + ac_have_decl=1 else - eval "$as_ac_Header=\$ac_header_preproc" + ac_have_decl=0 fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_SNPRINTF $ac_have_decl _ACEOF +ac_fn_cxx_check_decl "$LINENO" "vsnprintf" "ac_cv_have_decl_vsnprintf" "$ac_includes_default" +if test "x$ac_cv_have_decl_vsnprintf" = x""yes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_VSNPRINTF $ac_have_decl +_ACEOF +ac_fn_cxx_check_decl "$LINENO" "strverscmp" "ac_cv_have_decl_strverscmp" "$ac_includes_default" +if test "x$ac_cv_have_decl_strverscmp" = x""yes; then : + ac_have_decl=1 +else + ac_have_decl=0 fi -done +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRVERSCMP $ac_have_decl +_ACEOF +ac_fn_cxx_check_decl "$LINENO" "strndup" "ac_cv_have_decl_strndup" "$ac_includes_default" +if test "x$ac_cv_have_decl_strndup" = x""yes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_STRNDUP $ac_have_decl +_ACEOF +ac_fn_cxx_check_decl "$LINENO" "memmem" "ac_cv_have_decl_memmem" "$ac_includes_default" +if test "x$ac_cv_have_decl_memmem" = x""yes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi -for ac_func in mallinfo -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MEMMEM $ac_have_decl _ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. - For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define $ac_func innocuous_$ac_func -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - <limits.h> exists even on freestanding compilers. */ -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif +# Use of ::std::tr1::unordered_map::rehash causes undefined symbols +# at link time with some versions of GCC. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ::std::tr1::unordered_map::rehash is usable." >&5 +$as_echo_n "checking whether ::std::tr1::unordered_map::rehash is usable.... " >&6; } +if test "${gold_cv_unordered_map_rehash+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif +#include <tr1/unordered_map> +void bar() { ::std::tr1::unordered_map<int, int> x; x.rehash(10); } int main () { -return f != $ac_func; + ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" +if ac_fn_cxx_try_link "$LINENO"; then : + gold_cv_unordered_map_rehash=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" + gold_cv_unordered_map_rehash=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_unordered_map_rehash" >&5 +$as_echo "$gold_cv_unordered_map_rehash" >&6; } +if test "$gold_cv_unordered_map_rehash" = "yes"; then -fi -done +$as_echo "#define HAVE_TR1_UNORDERED_MAP_REHASH 1" >>confdefs.h +fi # gcc 4.3.0 doesn't recognize the printf attribute on a template # function. Check for that. This is gcc bug 35546. This test can # probably be removed after the bug has been fixed for a while. -echo "$as_me:$LINENO: checking whether we can use attributes with template functions" >&5 -echo $ECHO_N "checking whether we can use attributes with template functions... $ECHO_C" >&6 -if test "${gold_cv_template_attribute+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can use attributes with template functions" >&5 +$as_echo_n "checking whether we can use attributes with template functions... " >&6; } +if test "${gold_cv_template_attribute+set}" = set; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ template<typename T> extern void foo(const char*, ...) __attribute__ ((__format__ (__printf__, 1, 2))); @@ -6549,43 +6895,52 @@ template<typename T> void foo(const char* format, ...) {} void bar() { foo<int>("%s\n", "foo"); } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_cxx_try_compile "$LINENO"; then : gold_cv_template_attribute=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -gold_cv_template_attribute=no + gold_cv_template_attribute=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $gold_cv_template_attribute" >&5 -echo "${ECHO_T}$gold_cv_template_attribute" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_template_attribute" >&5 +$as_echo "$gold_cv_template_attribute" >&6; } if test "$gold_cv_template_attribute" = "yes"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TEMPLATE_ATTRIBUTES 1 +$as_echo "#define HAVE_TEMPLATE_ATTRIBUTES 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat::st_mtim." >&5 +$as_echo_n "checking for struct stat::st_mtim.... " >&6; } +if test "${gold_cv_stat_st_mtim+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/stat.h> +long bar() { struct stat s; return (long)(s.st_mtim.tv_sec + s.st_mtim.tv_sec);} + +int +main () +{ + + ; + return 0; +} _ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + gold_cv_stat_st_mtim=yes +else + gold_cv_stat_st_mtim=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_stat_st_mtim" >&5 +$as_echo "$gold_cv_stat_st_mtim" >&6; } +if test "$gold_cv_stat_st_mtim" = "yes"; then + +$as_echo "#define HAVE_STAT_ST_MTIM 1" >>confdefs.h fi @@ -6596,20 +6951,19 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5 -echo $ECHO_N "checking whether to enable maintainer-specific portions of Makefiles... $ECHO_C" >&6 - # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. -if test "${enable_maintainer_mode+set}" = set; then - enableval="$enable_maintainer_mode" - USE_MAINTAINER_MODE=$enableval + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no -fi; - echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5 -echo "${ECHO_T}$USE_MAINTAINER_MODE" >&6 - +fi -if test $USE_MAINTAINER_MODE = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else @@ -6621,7 +6975,8 @@ fi - ac_config_files="$ac_config_files Makefile testsuite/Makefile po/Makefile.in:po/Make-in" +ac_config_files="$ac_config_files Makefile testsuite/Makefile po/Makefile.in:po/Make-in" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -6640,39 +6995,59 @@ _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. +# So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. -{ +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; + ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; - esac; -} | + esac | + sort +) | sed ' + /^ac_cv_env_/b end t clear - : clear + :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end - /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - : end' >>confcache -if diff $cache_file confcache >/dev/null 2>&1; then :; else - if test -w $cache_file; then - test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else - echo "not updating unwritable cache $cache_file" + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache @@ -6681,150 +7056,130 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + if test -z "${THREADS_TRUE}" && test -z "${THREADS_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"THREADS\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"THREADS\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"THREADS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PLUGINS_TRUE}" && test -z "${PLUGINS_FALSE}"; then + as_fn_error "conditional \"PLUGINS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_TARGET_ARM_TRUE}" && test -z "${DEFAULT_TARGET_ARM_FALSE}"; then + as_fn_error "conditional \"DEFAULT_TARGET_ARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_TARGET_I386_TRUE}" && test -z "${DEFAULT_TARGET_I386_FALSE}"; then + as_fn_error "conditional \"DEFAULT_TARGET_I386\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_TARGET_POWERPC_TRUE}" && test -z "${DEFAULT_TARGET_POWERPC_FALSE}"; then + as_fn_error "conditional \"DEFAULT_TARGET_POWERPC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_TARGET_SPARC_TRUE}" && test -z "${DEFAULT_TARGET_SPARC_FALSE}"; then + as_fn_error "conditional \"DEFAULT_TARGET_SPARC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEFAULT_TARGET_X86_64_TRUE}" && test -z "${DEFAULT_TARGET_X86_64_FALSE}"; then + as_fn_error "conditional \"DEFAULT_TARGET_X86_64\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi + if test -z "${NATIVE_LINKER_TRUE}" && test -z "${NATIVE_LINKER_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"NATIVE_LINKER\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"NATIVE_LINKER\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"NATIVE_LINKER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GCC_TRUE}" && test -z "${GCC_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"GCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"GCC\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"GCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FN_PTRS_IN_SO_WITHOUT_PIC_TRUE}" && test -z "${FN_PTRS_IN_SO_WITHOUT_PIC_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"FN_PTRS_IN_SO_WITHOUT_PIC\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"FN_PTRS_IN_SO_WITHOUT_PIC\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"FN_PTRS_IN_SO_WITHOUT_PIC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MCMODEL_MEDIUM_TRUE}" && test -z "${MCMODEL_MEDIUM_FALSE}"; then + as_fn_error "conditional \"MCMODEL_MEDIUM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${TLS_TRUE}" && test -z "${TLS_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"TLS\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"TLS\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"TLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${STATIC_TLS_TRUE}" && test -z "${STATIC_TLS_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"STATIC_TLS\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"STATIC_TLS\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"STATIC_TLS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OMP_SUPPORT_TRUE}" && test -z "${OMP_SUPPORT_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"OMP_SUPPORT\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"OMP_SUPPORT\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"OMP_SUPPORT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${TLS_GNU2_DIALECT_TRUE}" && test -z "${TLS_GNU2_DIALECT_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"TLS_GNU2_DIALECT\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"TLS_GNU2_DIALECT\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"TLS_GNU2_DIALECT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${TLS_DESCRIPTORS_TRUE}" && test -z "${TLS_DESCRIPTORS_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"TLS_DESCRIPTORS\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"TLS_DESCRIPTORS\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"TLS_DESCRIPTORS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CONSTRUCTOR_PRIORITY_TRUE}" && test -z "${CONSTRUCTOR_PRIORITY_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"CONSTRUCTOR_PRIORITY\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"CONSTRUCTOR_PRIORITY\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"CONSTRUCTOR_PRIORITY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_ZLIB_TRUE}" && test -z "${HAVE_ZLIB_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"HAVE_ZLIB\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"HAVE_ZLIB\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"HAVE_ZLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } + as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : ${CONFIG_STATUS=./config.status} +ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. @@ -6834,81 +7189,252 @@ cat >$CONFIG_STATUS <<_ACEOF debug=false ac_cs_recheck=false ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac fi -DUALCASE=1; export DUALCASE # for MKS sh -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' fi +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi -done + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. -as_me=`$as_basename "$0" || +as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` -# PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -6916,148 +7442,123 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file else - as_expr=false + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null fi - -rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln else as_ln_s='cp -p' fi -rm -f conf$$ conf$$.exe conf$$.file +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -as_executable_p="test -f" +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -7066,31 +7567,20 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 -# Open the log real soon, to keep \$[0] and so on meaningful, and to +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - +# values after options handling. +ac_log=" This file was extended by gold $as_me 0.1, which was -generated by GNU Autoconf 2.59. Invocation command line was +generated by GNU Autoconf 2.64. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -7098,45 +7588,46 @@ generated by GNU Autoconf 2.59. Invocation command line was CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + _ACEOF -# Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" -cat >>$CONFIG_STATUS <<\_ACEOF +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. -Usage: $0 [OPTIONS] [FILE]... +Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages + -V, --version print version number and configuration settings, then exit + -q, --quiet, --silent + do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE Configuration files: $config_files @@ -7147,84 +7638,83 @@ $config_headers Configuration commands: $config_commands -Report bugs to <bug-autoconf@gnu.org>." -_ACEOF +Report bugs to the package provider." -cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ gold config.status 0.1 -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" +configured by $0, generated by GNU Autoconf 2.64, + with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" -Copyright (C) 2003 Free Software Foundation, Inc. +Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -INSTALL="$INSTALL" + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - -*) + *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; esac case $ac_option in # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; - *) ac_config_targets="$ac_config_targets $1" ;; + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; esac shift @@ -7238,19 +7728,32 @@ if $ac_cs_silent; then fi _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" fi _ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 -cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # -# INIT-COMMANDS section. +# INIT-COMMANDS # - AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # Capture the value of obsolete ALL_LINGUAS because we need it to compute # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it @@ -7262,25 +7765,24 @@ AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - -cat >>$CONFIG_STATUS <<\_ACEOF +# Handling of arguments. for ac_config_target in $ac_config_targets do - case "$ac_config_target" in - # Handling of arguments. - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; - "po/Makefile.in" ) CONFIG_FILES="$CONFIG_FILES po/Makefile.in:po/Make-in" ;; - "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; - "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h:config.in" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in:po/Make-in" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done + # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely @@ -7292,869 +7794,669 @@ if $ac_need_defaults; then fi # Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, +# simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. $debug || { - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 } - # Create a (secure) tmp directory for tmp files. { - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + { - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\).*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\).*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// } +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" -_ACEOF +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} -cat >>$CONFIG_STATUS <<_ACEOF +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF -# -# CONFIG_FILES section. -# +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@target@,$target,;t t -s,@target_cpu@,$target_cpu,;t t -s,@target_vendor@,$target_vendor,;t t -s,@target_os@,$target_os,;t t -s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t -s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t -s,@INSTALL_DATA@,$INSTALL_DATA,;t t -s,@CYGPATH_W@,$CYGPATH_W,;t t -s,@PACKAGE@,$PACKAGE,;t t -s,@VERSION@,$VERSION,;t t -s,@ACLOCAL@,$ACLOCAL,;t t -s,@AUTOCONF@,$AUTOCONF,;t t -s,@AUTOMAKE@,$AUTOMAKE,;t t -s,@AUTOHEADER@,$AUTOHEADER,;t t -s,@MAKEINFO@,$MAKEINFO,;t t -s,@install_sh@,$install_sh,;t t -s,@STRIP@,$STRIP,;t t -s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t -s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t -s,@mkdir_p@,$mkdir_p,;t t -s,@AWK@,$AWK,;t t -s,@SET_MAKE@,$SET_MAKE,;t t -s,@am__leading_dot@,$am__leading_dot,;t t -s,@AMTAR@,$AMTAR,;t t -s,@am__tar@,$am__tar,;t t -s,@am__untar@,$am__untar,;t t -s,@THREADS_TRUE@,$THREADS_TRUE,;t t -s,@THREADS_FALSE@,$THREADS_FALSE,;t t -s,@TARGETOBJS@,$TARGETOBJS,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@DEPDIR@,$DEPDIR,;t t -s,@am__include@,$am__include,;t t -s,@am__quote@,$am__quote,;t t -s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t -s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t -s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t -s,@CCDEPMODE@,$CCDEPMODE,;t t -s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t -s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t -s,@CXX@,$CXX,;t t -s,@CXXFLAGS@,$CXXFLAGS,;t t -s,@ac_ct_CXX@,$ac_ct_CXX,;t t -s,@CXXDEPMODE@,$CXXDEPMODE,;t t -s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t -s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t -s,@YACC@,$YACC,;t t -s,@RANLIB@,$RANLIB,;t t -s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t -s,@LN_S@,$LN_S,;t t -s,@USE_NLS@,$USE_NLS,;t t -s,@LIBINTL@,$LIBINTL,;t t -s,@LIBINTL_DEP@,$LIBINTL_DEP,;t t -s,@INCINTL@,$INCINTL,;t t -s,@XGETTEXT@,$XGETTEXT,;t t -s,@GMSGFMT@,$GMSGFMT,;t t -s,@POSUB@,$POSUB,;t t -s,@CATALOGS@,$CATALOGS,;t t -s,@DATADIRNAME@,$DATADIRNAME,;t t -s,@INSTOBJEXT@,$INSTOBJEXT,;t t -s,@GENCAT@,$GENCAT,;t t -s,@CATOBJEXT@,$CATOBJEXT,;t t -s,@MKINSTALLDIRS@,$MKINSTALLDIRS,;t t -s,@MSGFMT@,$MSGFMT,;t t -s,@MSGMERGE@,$MSGMERGE,;t t -s,@NATIVE_LINKER_TRUE@,$NATIVE_LINKER_TRUE,;t t -s,@NATIVE_LINKER_FALSE@,$NATIVE_LINKER_FALSE,;t t -s,@GCC_TRUE@,$GCC_TRUE,;t t -s,@GCC_FALSE@,$GCC_FALSE,;t t -s,@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@,$FN_PTRS_IN_SO_WITHOUT_PIC_TRUE,;t t -s,@FN_PTRS_IN_SO_WITHOUT_PIC_FALSE@,$FN_PTRS_IN_SO_WITHOUT_PIC_FALSE,;t t -s,@TLS_TRUE@,$TLS_TRUE,;t t -s,@TLS_FALSE@,$TLS_FALSE,;t t -s,@STATIC_TLS_TRUE@,$STATIC_TLS_TRUE,;t t -s,@STATIC_TLS_FALSE@,$STATIC_TLS_FALSE,;t t -s,@OMP_SUPPORT_TRUE@,$OMP_SUPPORT_TRUE,;t t -s,@OMP_SUPPORT_FALSE@,$OMP_SUPPORT_FALSE,;t t -s,@TLS_GNU2_DIALECT_TRUE@,$TLS_GNU2_DIALECT_TRUE,;t t -s,@TLS_GNU2_DIALECT_FALSE@,$TLS_GNU2_DIALECT_FALSE,;t t -s,@TLS_DESCRIPTORS_TRUE@,$TLS_DESCRIPTORS_TRUE,;t t -s,@TLS_DESCRIPTORS_FALSE@,$TLS_DESCRIPTORS_FALSE,;t t -s,@CONSTRUCTOR_PRIORITY_TRUE@,$CONSTRUCTOR_PRIORITY_TRUE,;t t -s,@CONSTRUCTOR_PRIORITY_FALSE@,$CONSTRUCTOR_PRIORITY_FALSE,;t t -s,@RANDOM_SEED_CFLAGS@,$RANDOM_SEED_CFLAGS,;t t -s,@WARN_CFLAGS@,$WARN_CFLAGS,;t t -s,@NO_WERROR@,$NO_WERROR,;t t -s,@WARN_CXXFLAGS@,$WARN_CXXFLAGS,;t t -s,@LFS_CFLAGS@,$LFS_CFLAGS,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@CPP@,$CPP,;t t -s,@EGREP@,$EGREP,;t t -s,@HAVE_ZLIB_TRUE@,$HAVE_ZLIB_TRUE,;t t -s,@HAVE_ZLIB_FALSE@,$HAVE_ZLIB_FALSE,;t t -s,@CXXCPP@,$CXXCPP,;t t -s,@MAINTAINER_MODE_TRUE@,$MAINTAINER_MODE_TRUE,;t t -s,@MAINTAINER_MODE_FALSE@,$MAINTAINER_MODE_FALSE,;t t -s,@MAINT@,$MAINT,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { _ACEOF - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi -fi # test -n "$CONFIG_FILES" +done +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix case $srcdir in - .) # No --srcdir option. We are building in place. + .) # We are building in place. ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac + case $ac_mode in + :F) + # + # CONFIG_FILE + # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub $extrasub _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -s,@INSTALL@,$ac_INSTALL,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi - -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_HEADER section. -# - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' -ac_dC=' ' -ac_dD=',;t' -# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='$,\1#\2define\3' -ac_uC=' ' -ac_uD=',;t' - -for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - # Do quote $f, to prevent DOS paths from being IFS'd. - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in - -_ACEOF - -# Transform confdefs.h into two sed scripts, `conftest.defines' and -# `conftest.undefs', that substitutes the proper values into -# config.h.in to produce config.h. The first handles `#define' -# templates, and the second `#undef' templates. -# And first: Protect against being on the right side of a sed subst in -# config.status. Protect against being in an unquoted here document -# in config.status. -rm -f conftest.defines conftest.undefs -# Using a here document instead of a string reduces the quoting nightmare. -# Putting comments in sed scripts is not portable. -# -# `end' is used to avoid that the second main sed command (meant for -# 0-ary CPP macros) applies to n-ary macro definitions. -# See the Autoconf documentation for `clear'. -cat >confdef2sed.sed <<\_ACEOF -s/[\\&,]/\\&/g -s,[\\$`],\\&,g -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp -t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp -: end -_ACEOF -# If some macros were called several times there might be several times -# the same #defines, which is useless. Nevertheless, we may not want to -# sort them, since we want the *last* AC-DEFINE to be honored. -uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines -sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs -rm -f confdef2sed.sed - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -_ACEOF - -# Break up conftest.defines because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS -echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS -echo ' :' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.defines >/dev/null -do - # Write a limited-size here document to $tmp/defines.sed. - echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS - # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/defines.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines -echo ' fi # grep' >>$CONFIG_STATUS -echo >>$CONFIG_STATUS - -# Break up conftest.undefs because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #undef templates' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.undefs >/dev/null -do - # Write a limited-size here document to $tmp/undefs.sed. - echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS - # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/undefs.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail - rm -f conftest.undefs - mv conftest.tail conftest.undefs -done -rm -f conftest.undefs - -cat >>$CONFIG_STATUS <<\_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - echo "/* Generated by configure. */" >$tmp/config.h - else - echo "/* $ac_file. Generated by configure. */" >$tmp/config.h - fi - cat $tmp/in >>$tmp/config.h - rm -f $tmp/in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # if test x"$ac_file" != x-; then - if diff $ac_file $tmp/config.h >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} else - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - rm -f $ac_file - mv $tmp/config.h $ac_file + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else - cat $tmp/config.h - rm -f $tmp/config.h + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error "could not create -" "$LINENO" 5 fi -# Compute $ac_file's index in $config_headers. +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in - $ac_file | $ac_file:* ) + $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done -echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || -$as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X$ac_file | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'`/stamp-h$_am_stamp_count -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF - -# -# CONFIG_COMMANDS section. -# -for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue - ac_dest=`echo "$ac_file" | sed 's,:.*,,'` - ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_dir=`(dirname "$ac_dest") 2>/dev/null || -$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_dest" : 'X\(//\)[^/]' \| \ - X"$ac_dest" : 'X\(//\)$' \| \ - X"$ac_dest" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_dest" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - ac_builddir=. - -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi - -case $srcdir in - .) # No --srcdir option. We are building in place. - ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac - { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 -echo "$as_me: executing $ac_dest commands" >&6;} - case $ac_dest in - depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`(dirname "$mf") 2>/dev/null || + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`(dirname "$file") 2>/dev/null || + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p $dirpart/$fdir - else - as_dir=$dirpart/$fdir - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 -echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} - { (exit 1); exit 1; }; }; } - - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" done -done +} ;; - default-1 ) + "default-1":C) for ac_file in $CONFIG_FILES; do # Support "outfile[:infile[:infile...]]" case "$ac_file" in @@ -8255,17 +8557,18 @@ done ;; esac done ;; + esac -done -_ACEOF +done # for ac_tag -cat >>$CONFIG_STATUS <<\_ACEOF -{ (exit 0); exit 0; } +as_fn_exit 0 _ACEOF -chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. @@ -8285,6 +8588,10 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } + $ac_cs_success || as_fn_exit $? +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi diff --git a/binutils-2.19/gold/configure.ac b/binutils-2.19/gold/configure.ac index 3fbcd0e..f184d4b 100644 --- a/binutils-2.19/gold/configure.ac +++ b/binutils-2.19/gold/configure.ac @@ -53,6 +53,20 @@ if test "$threads" = "yes"; then fi AM_CONDITIONAL(THREADS, test "$threads" = "yes") +AC_ARG_ENABLE([plugins], +[ --enable-plugins linker plugins], +[case "${enableval}" in + yes | "") plugins=yes ;; + no) plugins=no ;; + *) plugins=yes ;; + esac], +[plugins=no]) +if test "$plugins" = "yes"; then + AC_DEFINE(ENABLE_PLUGINS, 1, + [Define to enable linker plugins]) +fi +AM_CONDITIONAL(PLUGINS, test "$plugins" = "yes") + AC_ARG_ENABLE([targets], [ --enable-targets alternative target configurations], [case "${enableval}" in @@ -89,6 +103,7 @@ all_targets= default_machine= default_size= default_big_endian= +default_osabi=ELFOSABI_NONE targ_32_little= targ_32_big= targ_64_little= @@ -135,11 +150,28 @@ for targ in $target $canon_targets; do default_machine=$targ_machine default_size=$targ_size default_big_endian=$targ_big_endian + default_osabi=$targ_osabi + + AM_CONDITIONAL(DEFAULT_TARGET_ARM, test "$targ_obj" = "arm") + AM_CONDITIONAL(DEFAULT_TARGET_I386, test "$targ_obj" = "i386") + AM_CONDITIONAL(DEFAULT_TARGET_POWERPC, test "$targ_obj" = "powerpc") + AM_CONDITIONAL(DEFAULT_TARGET_SPARC, test "$targ_obj" = "sparc") + AM_CONDITIONAL(DEFAULT_TARGET_X86_64, test "$targ_obj" = "x86_64") fi fi fi done +# Remove any duplicates. +to="" +for t in $targetobjs; do + case " $to " in + *" $t "*) ;; + *) to="$to $t" ;; + esac +done +targetobjs=$to + if test -n "$targ_32_little"; then AC_DEFINE(HAVE_TARGET_32_LITTLE, 1, [Define to support 32-bit little-endian targets]) @@ -170,6 +202,8 @@ AC_DEFINE_UNQUOTED(GOLD_DEFAULT_SIZE, $default_size, [Default size (32 or 64)]) AC_DEFINE_UNQUOTED(GOLD_DEFAULT_BIG_ENDIAN, $default_big_endian, [Default big endian (true or false)]) +AC_DEFINE_UNQUOTED(GOLD_DEFAULT_OSABI, $default_osabi, + [Default OSABI code]) AC_PROG_CC AC_PROG_CXX @@ -203,6 +237,21 @@ AM_CONDITIONAL(FN_PTRS_IN_SO_WITHOUT_PIC, [ *) true;; esac]) +dnl Test for gcc 4.1 or later. Full support for -mcmodel=medium is +dnl only available in gcc 4.1. +AC_CACHE_CHECK([for gcc >= 4.1], [gold_cv_prog_gcc41], +[AC_COMPILE_IFELSE([ +#if !defined __GNUC__ +error +#elif __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1) +error +#endif +], [gold_cv_prog_gcc41=yes], [gold_cv_prog_gcc41=no])]) + +dnl Whether we can test -mcmodel=medium. +AM_CONDITIONAL(MCMODEL_MEDIUM, +[test "$target_cpu" = "x86_64" -a "$gold_cv_prog_gcc41" = "yes"]) + dnl Test for __thread support. AC_CACHE_CHECK([for thread support], [gold_cv_c_thread], [AC_COMPILE_IFELSE([__thread int i = 1;], @@ -248,18 +297,18 @@ CFLAGS="$save_CFLAGS" AM_CONDITIONAL(TLS_GNU2_DIALECT, test "$have_tls_gnu2" = "yes") dnl On GNU/Linux TLS descriptors are supported by the dynamic loader -dnl only with glibc 2.5 or later. -AC_CACHE_CHECK([for glibc >= 2.5], [gold_cv_lib_glibc25], +dnl only with glibc 2.9 or later. +AC_CACHE_CHECK([for glibc >= 2.9], [gold_cv_lib_glibc29], [AC_COMPILE_IFELSE([ #include <features.h> #if !defined __GLIBC__ error -#elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 5) +#elif __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 9) error #endif -], [gold_cv_lib_glibc25=yes], [gold_cv_lib_glibc25=no])]) +], [gold_cv_lib_glibc29=yes], [gold_cv_lib_glibc29=no])]) -AM_CONDITIONAL(TLS_DESCRIPTORS, test "$gold_cv_lib_glibc25" = "yes") +AM_CONDITIONAL(TLS_DESCRIPTORS, test "$gold_cv_lib_glibc29" = "yes") dnl Check whether the compiler supports constructor priorities in dnl attributes, which were added in gcc 4.3. @@ -285,7 +334,7 @@ AC_SUBST(RANDOM_SEED_CFLAGS) AM_BINUTILS_WARNINGS -WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//'` +WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//' -e 's/-Wshadow//'` AC_SUBST(WARN_CXXFLAGS) dnl Force support for large files by default. This may need to be @@ -293,17 +342,39 @@ dnl host dependent. If build == host, we can check getconf LFS_CFLAGS. LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" AC_SUBST(LFS_CFLAGS) -AC_REPLACE_FUNCS(pread) +AC_CHECK_FUNCS(chsize) +AC_REPLACE_FUNCS(pread ftruncate mremap ffsll) # Link in zlib if we can. This allows us to write compressed sections. AC_SEARCH_LIBS(zlibVersion, z, [AC_CHECK_HEADERS(zlib.h)]) AM_CONDITIONAL(HAVE_ZLIB, test "$ac_cv_search_zlibVersion" != "no") +dnl We have to check these in C, not C++, because autoconf generates +dnl tests which have no type information, and current glibc provides +dnl multiple declarations of functions like basename when compiling +dnl with C++. +AC_CHECK_DECLS([basename, ffs, asprintf, vasprintf, snprintf, vsnprintf, strverscmp]) + AC_LANG_PUSH(C++) AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map) AC_CHECK_HEADERS(ext/hash_map ext/hash_set) -AC_CHECK_FUNCS(mallinfo) +AC_CHECK_HEADERS(byteswap.h) +AC_CHECK_FUNCS(mallinfo posix_fallocate readv sysconf times) +AC_CHECK_DECLS([basename, ffs, asprintf, vasprintf, snprintf, vsnprintf, strverscmp, strndup, memmem]) + +# Use of ::std::tr1::unordered_map::rehash causes undefined symbols +# at link time with some versions of GCC. +AC_CACHE_CHECK([whether ::std::tr1::unordered_map::rehash is usable.], +[gold_cv_unordered_map_rehash], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#include <tr1/unordered_map> +void bar() { ::std::tr1::unordered_map<int, int> x; x.rehash(10); } +]])], [gold_cv_unordered_map_rehash=yes], [gold_cv_unordered_map_rehash=no])]) +if test "$gold_cv_unordered_map_rehash" = "yes"; then + AC_DEFINE(HAVE_TR1_UNORDERED_MAP_REHASH, 1, + [Define if ::std::tr1::unordered_map::rehash is usable]) +fi # gcc 4.3.0 doesn't recognize the printf attribute on a template # function. Check for that. This is gcc bug 35546. This test can @@ -321,6 +392,18 @@ if test "$gold_cv_template_attribute" = "yes"; then [Define if attributes work on C++ templates]) fi +dnl Check if the system has struct stat::st_mtim. +AC_CACHE_CHECK([for struct stat::st_mtim.], +[gold_cv_stat_st_mtim], +[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <sys/stat.h> +long bar() { struct stat s; return (long)(s.st_mtim.tv_sec + s.st_mtim.tv_sec);} +]])], [gold_cv_stat_st_mtim=yes], [gold_cv_stat_st_mtim=no])]) +if test "$gold_cv_stat_st_mtim" = "yes"; then + AC_DEFINE(HAVE_STAT_ST_MTIM, 1, + [Define if struct stat has a field st_mtim with timespec for mtime]) +fi + AC_LANG_POP(C++) AM_MAINTAINER_MODE diff --git a/binutils-2.19/gold/configure.tgt b/binutils-2.19/gold/configure.tgt index 6bf49bc..0f3b1c3 100644 --- a/binutils-2.19/gold/configure.tgt +++ b/binutils-2.19/gold/configure.tgt @@ -1,6 +1,6 @@ # configure.tgt -- target configuration for gold -*- sh -*- -# Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # Written by Ian Lance Taylor <iant@google.com>. # This file is part of gold. @@ -36,6 +36,7 @@ # targ_extra_size extra targ_size setting for the target # targ_big_endian whether the target is big-endian--true or false # targ_extra_big_endian extra targ_big_endian setting for the target +# targ_osabi EI_OSABI value # If the target is not recognized targ_obj is set to "UNKNOWN". @@ -45,12 +46,18 @@ targ_size= targ_extra_size= targ_big_endian= targ_extra_big_endian= +targ_osabi=ELFOSABI_NONE case "$targ" in i?86-*) targ_obj=i386 targ_machine=EM_386 targ_size=32 targ_big_endian=false + case "$targ" in + i?86-*-freebsd*) + targ_osabi=ELFOSABI_FREEBSD + ;; + esac ;; x86_64*) targ_obj=x86_64 @@ -59,6 +66,11 @@ x86_64*) targ_size=64 targ_extra_size=32 targ_big_endian=false + case "$targ" in + x86_64-*-freebsd*) + targ_osabi=ELFOSABI_FREEBSD + ;; + esac ;; sparc-*) targ_obj=sparc @@ -85,13 +97,29 @@ powerpc-*) targ_extra_big_endian=false ;; powerpc64-*) - targ_obj=ppc64 + targ_obj=powerpc targ_machine=EM_PPC64 targ_size=64 targ_extra_size=32 targ_big_endian=true targ_extra_big_endian=false ;; +armeb*-*-*|armbe*-*-*) + targ_obj=arm + targ_extra_obj=arm-reloc-property + targ_machine=EM_ARM + targ_size=32 + targ_big_endian=true + targ_extra_big_endian=false + ;; +arm*-*-*) + targ_obj=arm + targ_extra_obj=arm-reloc-property + targ_machine=EM_ARM + targ_size=32 + targ_big_endian=false + targ_extra_big_endian=true + ;; *) targ_obj=UNKNOWN ;; diff --git a/binutils-2.19/gold/copy-relocs.cc b/binutils-2.19/gold/copy-relocs.cc index 80b50df..1ff7ffe 100644 --- a/binutils-2.19/gold/copy-relocs.cc +++ b/binutils-2.19/gold/copy-relocs.cc @@ -1,6 +1,6 @@ // copy-relocs.cc -- handle COPY relocations for gold. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -84,7 +84,8 @@ Copy_relocs<sh_type, size, big_endian>::need_copy_reloc( Sized_relobj<size, big_endian>* object, unsigned int shndx) const { - // FIXME: Handle -z nocopyrelocs. + if (!parameters->options().copyreloc()) + return false; if (sym->symsize() == 0) return false; @@ -109,6 +110,9 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc( Sized_symbol<size>* sym, Output_data_reloc<sh_type, true, size, big_endian>* reloc_section) { + // We should not be here if -z nocopyreloc is given. + gold_assert(parameters->options().copyreloc()); + typename elfcpp::Elf_types<size>::Elf_WXword symsize = sym->symsize(); // There is no defined way to determine the required alignment of @@ -128,13 +132,17 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc( while ((value & (addralign - 1)) != 0) addralign >>= 1; + // Mark the dynamic object as needed for the --as-needed option. + sym->object()->set_is_needed(); + if (this->dynbss_ == NULL) { this->dynbss_ = new Output_data_space(addralign, "** dynbss"); layout->add_output_section_data(".bss", elfcpp::SHT_NOBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->dynbss_); + this->dynbss_, false, false, false, + false); } Output_data_space* dynbss = this->dynbss_; diff --git a/binutils-2.19/gold/cref.cc b/binutils-2.19/gold/cref.cc index ec95f36..c36f989 100644 --- a/binutils-2.19/gold/cref.cc +++ b/binutils-2.19/gold/cref.cc @@ -1,6 +1,6 @@ // cref.cc -- cross reference for gold -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -31,6 +31,7 @@ #include "object.h" #include "archive.h" +#include "symtab.h" #include "cref.h" namespace gold @@ -63,6 +64,10 @@ class Cref_inputs void print_symbol_counts(const Symbol_table*, FILE*) const; + // Print a cross reference tabl.e + void + print_cref(const Symbol_table*, FILE*) const; + private: // A list of input objects. typedef std::vector<Object*> Objects; @@ -82,6 +87,19 @@ class Cref_inputs // that archive. typedef std::map<std::string, Archive_info> Archives; + // For --cref, we build a cross reference table which maps from + // symbols to lists of objects. The symbols are sorted + // alphabetically. + + class Cref_table_compare + { + public: + bool + operator()(const Symbol*, const Symbol*) const; + }; + + typedef std::map<const Symbol*, Objects*, Cref_table_compare> Cref_table; + // Report symbol counts for a list of Objects. void print_objects_symbol_counts(const Symbol_table*, FILE*, const Objects*) const; @@ -90,6 +108,10 @@ class Cref_inputs void print_object_symbol_counts(const Symbol_table*, FILE*, const Object*) const; + // Gather cross reference information. + void + gather_cref(const Objects*, Cref_table*) const; + // List of input objects. Objects objects_; // List of input archives. This is a mapping from the archive file @@ -144,7 +166,7 @@ Cref_inputs::print_object_symbol_counts(const Symbol_table* symtab, fprintf(f, "symbols %s %zu %zu\n", object->name().c_str(), defined, used); } -// Report symbol counts for a list of Inputs. +// Report symbol counts for a list of inputs. void Cref_inputs::print_objects_symbol_counts(const Symbol_table* symtab, @@ -189,6 +211,124 @@ Cref_inputs::print_symbol_counts(const Symbol_table* symtab, FILE* f) const } } +// Sort symbols for the cross reference table. + +bool +Cref_inputs::Cref_table_compare::operator()(const Symbol* s1, + const Symbol* s2) const +{ + int i = strcmp(s1->name(), s2->name()); + if (i != 0) + return i < 0; + + if (s1->version() == NULL) + { + if (s2->version() != NULL) + return true; + } + else if (s2->version() == NULL) + return false; + else + { + i = strcmp(s1->version(), s2->version()); + if (i != 0) + return i < 0; + } + + // We should never have two different symbols with the same name and + // version. + if (s1 == s2) + return false; + gold_unreachable(); +} + +// Gather cross reference information from a list of inputs. + +void +Cref_inputs::gather_cref(const Objects* objects, Cref_table* table) const +{ + for (Objects::const_iterator po = objects->begin(); + po != objects->end(); + ++po) + { + const Object::Symbols* symbols = (*po)->get_global_symbols(); + if (symbols == NULL) + continue; + for (Object::Symbols::const_iterator ps = symbols->begin(); + ps != symbols->end(); + ++ps) + { + const Symbol* sym = *ps; + if (sym == NULL) + continue; + Objects* const onull = NULL; + std::pair<Cref_table::iterator, bool> ins = + table->insert(std::make_pair(sym, onull)); + Cref_table::iterator pc = ins.first; + if (ins.second) + pc->second = new Objects(); + if (sym->source() == Symbol::FROM_OBJECT + && sym->object() == *po + && sym->is_defined()) + pc->second->insert(pc->second->begin(), *po); + else + pc->second->push_back(*po); + } + } +} + +// The column where the file name starts in a cross reference table. + +static const size_t filecol = 50; + +// Print a cross reference table. + +void +Cref_inputs::print_cref(const Symbol_table*, FILE* f) const +{ + Cref_table table; + this->gather_cref(&this->objects_, &table); + for (Archives::const_iterator p = this->archives_.begin(); + p != this->archives_.end(); + ++p) + this->gather_cref(p->second.objects, &table); + + for (Cref_table::const_iterator pc = table.begin(); + pc != table.end(); + ++pc) + { + // If all the objects are dynamic, skip this symbol. + const Symbol* sym = pc->first; + const Objects* objects = pc->second; + Objects::const_iterator po; + for (po = objects->begin(); po != objects->end(); ++po) + if (!(*po)->is_dynamic()) + break; + if (po == objects->end()) + continue; + + std::string s = sym->demangled_name(); + if (sym->version() != NULL) + { + s += '@'; + if (sym->is_default()) + s += '@'; + s += sym->version(); + } + + fputs(s.c_str(), f); + + size_t len = s.length(); + + for (po = objects->begin(); po != objects->end(); ++po) + { + int n = len < filecol ? filecol - len : 1; + fprintf(f, "%*c%s\n", n, ' ', (*po)->name().c_str()); + len = 0; + } + } +} + // Class Cref. // Make sure the Cref_inputs object has been created. @@ -250,4 +390,18 @@ Cref::print_symbol_counts(const Symbol_table* symtab) const } } +// Print a cross reference table. + +void +Cref::print_cref(const Symbol_table* symtab, FILE* f) const +{ + fprintf(f, _("\nCross Reference Table\n\n")); + const char* msg = _("Symbol"); + int len = filecol - strlen(msg); + fprintf(f, "%s%*c%s\n", msg, len, ' ', _("File")); + + if (parameters->options().cref() && this->inputs_ != NULL) + this->inputs_->print_cref(symtab, f); +} + } // End namespace gold. diff --git a/binutils-2.19/gold/cref.h b/binutils-2.19/gold/cref.h index 3da5d3a..a40a34a 100644 --- a/binutils-2.19/gold/cref.h +++ b/binutils-2.19/gold/cref.h @@ -1,6 +1,6 @@ // cref.h -- cross reference reports for gold -*- C++ -*- -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -23,6 +23,8 @@ #ifndef GOLD_CREF_H #define GOLD_CREF_H +#include <cstdio> + namespace gold { @@ -61,6 +63,10 @@ class Cref void print_symbol_counts(const Symbol_table*) const; + // Print a cross reference table. + void + print_cref(const Symbol_table*, FILE*) const; + private: void need_inputs(); diff --git a/binutils-2.19/gold/debug.h b/binutils-2.19/gold/debug.h index 8428dc8..4b9ef19 100644 --- a/binutils-2.19/gold/debug.h +++ b/binutils-2.19/gold/debug.h @@ -36,8 +36,10 @@ namespace gold const int DEBUG_TASK = 0x1; const int DEBUG_SCRIPT = 0x2; const int DEBUG_FILES = 0x4; +const int DEBUG_RELAXATION = 0x8; -const int DEBUG_ALL = DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES; +const int DEBUG_ALL = (DEBUG_TASK | DEBUG_SCRIPT | DEBUG_FILES + | DEBUG_RELAXATION); // Convert a debug string to the appropriate enum. inline int @@ -49,6 +51,7 @@ debug_string_to_enum(const char* arg) { "task", DEBUG_TASK }, { "script", DEBUG_SCRIPT }, { "files", DEBUG_FILES }, + { "relaxation", DEBUG_RELAXATION }, { "all", DEBUG_ALL } }; diff --git a/binutils-2.19/gold/defstd.cc b/binutils-2.19/gold/defstd.cc index 984f3e1..e09d814 100644 --- a/binutils-2.19/gold/defstd.cc +++ b/binutils-2.19/gold/defstd.cc @@ -107,7 +107,67 @@ const Define_symbol_in_section in_section[] = 0, // nonvis true, // offset_is_from_end true // only_if_ref - } + }, + { + "__rel_iplt_start", // name + ".rel.iplt", // output_section + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_HIDDEN, // visibility + 0, // nonvis + false, // offset_is_from_end + true // only_if_ref + }, + { + "__rel_iplt_end", // name + ".rel.iplt", // output_section + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_HIDDEN, // visibility + 0, // nonvis + true, // offset_is_from_end + true // only_if_ref + }, + { + "__rela_iplt_start", // name + ".rela.iplt", // output_section + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_HIDDEN, // visibility + 0, // nonvis + false, // offset_is_from_end + true // only_if_ref + }, + { + "__rela_iplt_end", // name + ".rela.iplt", // output_section + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_HIDDEN, // visibility + 0, // nonvis + true, // offset_is_from_end + true // only_if_ref + }, + { + "__stack", // name + ".stack", // output_section + 0, // value + 0, // size + elfcpp::STT_NOTYPE, // type + elfcpp::STB_GLOBAL, // binding + elfcpp::STV_DEFAULT, // visibility + 0, // nonvis + false, // offset_is_from_end + true // only_if_ref + }, }; const int in_section_count = sizeof in_section / sizeof in_section[0]; @@ -238,7 +298,7 @@ const Define_symbol_in_segment in_segment[] = elfcpp::STV_DEFAULT, // visibility 0, // nonvis Symbol::SEGMENT_END, // offset_from_base - false // only_if_ref + true // only_if_ref } }; diff --git a/binutils-2.19/gold/descriptors.cc b/binutils-2.19/gold/descriptors.cc index 75a7a86..f4a02d0 100644 --- a/binutils-2.19/gold/descriptors.cc +++ b/binutils-2.19/gold/descriptors.cc @@ -1,6 +1,6 @@ // descriptors.cc -- manage file descriptors for gold -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -23,13 +23,26 @@ #include "gold.h" #include <cerrno> +#include <cstdio> #include <cstring> #include <fcntl.h> #include <unistd.h> #include "parameters.h" +#include "options.h" #include "gold-threads.h" #include "descriptors.h" +#include "binary-io.h" + +// Very old systems may not define FD_CLOEXEC. +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +// O_CLOEXEC is only available on newer systems. +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif namespace gold { @@ -40,8 +53,8 @@ namespace gold // adjusted downward if we run out of file descriptors. Descriptors::Descriptors() - : lock_(NULL), open_descriptors_(), stack_top_(-1), current_(0), - limit_(8192 - 16) + : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(), + stack_top_(-1), current_(0), limit_(8192 - 16) { this->open_descriptors_.reserve(128); } @@ -55,13 +68,9 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) // initialize a Lock until we have parsed the options to find out // whether we are running with threads. We can be called before // options are valid when reading a linker script. - if (this->lock_ == NULL) - { - if (parameters->options_valid()) - this->lock_ = new Lock(); - else - gold_assert(descriptor < 0); - } + bool lock_initialized = this->initialize_lock_.initialize(); + + gold_assert(lock_initialized || descriptor < 0); if (descriptor >= 0) { @@ -75,12 +84,25 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) { gold_assert(!pod->inuse); pod->inuse = true; + if (descriptor == this->stack_top_) + { + this->stack_top_ = pod->stack_next; + pod->stack_next = -1; + pod->is_on_stack = false; + } return descriptor; } } while (true) { + // We always want to set the close-on-exec flag; we don't + // require callers to pass it. + flags |= O_CLOEXEC; + + // Always open the file as a binary file. + flags |= O_BINARY; + int new_descriptor = ::open(name, flags, mode); if (new_descriptor < 0 && errno != ENFILE @@ -103,23 +125,37 @@ Descriptors::open(int descriptor, const char* name, int flags, int mode) if (new_descriptor >= 0) { - Hold_optional_lock hl(this->lock_); - - if (static_cast<size_t>(new_descriptor) - >= this->open_descriptors_.size()) - this->open_descriptors_.resize(new_descriptor + 64); - - Open_descriptor* pod = &this->open_descriptors_[new_descriptor]; - pod->name = name; - pod->stack_next = -1; - pod->inuse = true; - pod->is_write = (flags & O_ACCMODE) != O_RDONLY; - - ++this->current_; - if (this->current_ >= this->limit_) - this->close_some_descriptor(); - - return new_descriptor; + // If we have any plugins, we really do need to set the + // close-on-exec flag, even if O_CLOEXEC is not defined. + // FIXME: In some cases O_CLOEXEC may be defined in the + // header file but not supported by the kernel. + // Unfortunately there doesn't seem to be any obvious way to + // detect that, as unknown flags passed to open are ignored. + if (O_CLOEXEC == 0 + && parameters->options_valid() + && parameters->options().has_plugins()) + fcntl(new_descriptor, F_SETFD, FD_CLOEXEC); + + { + Hold_optional_lock hl(this->lock_); + + if (static_cast<size_t>(new_descriptor) + >= this->open_descriptors_.size()) + this->open_descriptors_.resize(new_descriptor + 64); + + Open_descriptor* pod = &this->open_descriptors_[new_descriptor]; + pod->name = name; + pod->stack_next = -1; + pod->inuse = true; + pod->is_write = (flags & O_ACCMODE) != O_RDONLY; + pod->is_on_stack = false; + + ++this->current_; + if (this->current_ >= this->limit_) + this->close_some_descriptor(); + + return new_descriptor; + } } // We ran out of file descriptors. @@ -158,10 +194,11 @@ Descriptors::release(int descriptor, bool permanent) else { pod->inuse = false; - if (!pod->is_write) + if (!pod->is_write && !pod->is_on_stack) { pod->stack_next = this->stack_top_; this->stack_top_ = descriptor; + pod->is_on_stack = true; } } } @@ -193,6 +230,8 @@ Descriptors::close_some_descriptor() this->stack_top_ = pod->stack_next; else this->open_descriptors_[last].stack_next = pod->stack_next; + pod->stack_next = -1; + pod->is_on_stack = false; return true; } last = i; diff --git a/binutils-2.19/gold/descriptors.h b/binutils-2.19/gold/descriptors.h index 6a6ab61..8e154a6 100644 --- a/binutils-2.19/gold/descriptors.h +++ b/binutils-2.19/gold/descriptors.h @@ -1,6 +1,6 @@ // descriptors.h -- manage file descriptors for gold -*- C++ -*- -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -25,11 +25,11 @@ #include <vector> +#include "gold-threads.h" + namespace gold { -class Lock; - // This class manages file descriptors for gold. class Descriptors @@ -69,6 +69,8 @@ class Descriptors bool inuse; // Whether this is a write descriptor. bool is_write; + // Whether the descriptor is on the stack. + bool is_on_stack; }; bool @@ -76,6 +78,8 @@ class Descriptors // We need to lock before accessing any fields. Lock* lock_; + // Used to initialize the lock_ field exactly once. + Initialize_lock initialize_lock_; // Information for descriptors. std::vector<Open_descriptor> open_descriptors_; // Top of stack. diff --git a/binutils-2.19/gold/dirsearch.cc b/binutils-2.19/gold/dirsearch.cc index eb57f99..fac3b2c 100644 --- a/binutils-2.19/gold/dirsearch.cc +++ b/binutils-2.19/gold/dirsearch.cc @@ -1,6 +1,6 @@ // dirsearch.cc -- directory searching for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -220,6 +220,8 @@ Dir_cache_task::run(gold::Workqueue*) namespace gold { +// Initialize. + void Dirsearch::initialize(Workqueue* workqueue, const General_options::Dir_list* directories) @@ -227,34 +229,35 @@ Dirsearch::initialize(Workqueue* workqueue, gold_assert(caches == NULL); caches = new Dir_caches; this->directories_ = directories; + this->token_.add_blockers(directories->size()); for (General_options::Dir_list::const_iterator p = directories->begin(); p != directories->end(); ++p) - { - this->token_.add_blocker(); - workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_)); - } + workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_)); } -// NOTE: we only log failed file-lookup attempts here. Successfully -// lookups will eventually get logged in File_read::open. +// Search for a file. NOTE: we only log failed file-lookup attempts +// here. Successfully lookups will eventually get logged in +// File_read::open. std::string Dirsearch::find(const std::string& n1, const std::string& n2, - bool *is_in_sysroot) const + bool* is_in_sysroot, int* pindex) const { gold_assert(!this->token_.is_blocked()); + gold_assert(*pindex >= 0); - for (General_options::Dir_list::const_iterator p = - this->directories_->begin(); - p != this->directories_->end(); - ++p) + for (unsigned int i = static_cast<unsigned int>(*pindex); + i < this->directories_->size(); + ++i) { + const Search_directory* p = &this->directories_->at(i); Dir_cache* pdc = caches->lookup(p->name().c_str()); gold_assert(pdc != NULL); if (pdc->find(n1)) { *is_in_sysroot = p->is_in_sysroot(); + *pindex = i; return p->name() + '/' + n1; } else @@ -266,6 +269,7 @@ Dirsearch::find(const std::string& n1, const std::string& n2, if (pdc->find(n2)) { *is_in_sysroot = p->is_in_sysroot(); + *pindex = i; return p->name() + '/' + n2; } else @@ -274,6 +278,7 @@ Dirsearch::find(const std::string& n1, const std::string& n2, } } + *pindex = -2; return std::string(); } diff --git a/binutils-2.19/gold/dirsearch.h b/binutils-2.19/gold/dirsearch.h index 639d49e..f14b5ed 100644 --- a/binutils-2.19/gold/dirsearch.h +++ b/binutils-2.19/gold/dirsearch.h @@ -53,9 +53,14 @@ class Dirsearch // second one may be empty). Return a full path name for the file, // or the empty string if it could not be found. This may only be // called if the token is not blocked. Set *IS_IN_SYSROOT if the - // file was found in a directory which is in the sysroot. + // file was found in a directory which is in the sysroot. *PINDEX + // should be set to zero the first time this is called; it will be + // updated with the index of the directory where the file is found, + // and that value plus one may be used to find the next file with + // the same name(s). std::string - find(const std::string&, const std::string& n2, bool *is_in_sysroot) const; + find(const std::string&, const std::string& n2, bool *is_in_sysroot, + int* pindex) const; // Return the blocker token which controls access. Task_token* diff --git a/binutils-2.19/gold/dwarf_reader.cc b/binutils-2.19/gold/dwarf_reader.cc index 3d0f65a..4062fe6 100644 --- a/binutils-2.19/gold/dwarf_reader.cc +++ b/binutils-2.19/gold/dwarf_reader.cc @@ -1,6 +1,6 @@ // dwarf_reader.cc -- parse dwarf2/3 debug information -// Copyright 2007, 2008 Free Software Foundation, Inc. +// Copyright 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -31,77 +31,10 @@ #include "parameters.h" #include "reloc.h" #include "dwarf_reader.h" +#include "int_encoding.h" namespace gold { -// Read an unsigned LEB128 number. Each byte contains 7 bits of -// information, plus one bit saying whether the number continues or -// not. - -uint64_t -read_unsigned_LEB_128(const unsigned char* buffer, size_t* len) -{ - uint64_t result = 0; - size_t num_read = 0; - unsigned int shift = 0; - unsigned char byte; - - do - { - if (num_read >= 64 / 7) - { - gold_warning(_("Unusually large LEB128 decoded, " - "debug information may be corrupted")); - break; - } - byte = *buffer++; - num_read++; - result |= (static_cast<uint64_t>(byte & 0x7f)) << shift; - shift += 7; - } - while (byte & 0x80); - - *len = num_read; - - return result; -} - -// Read a signed LEB128 number. These are like regular LEB128 -// numbers, except the last byte may have a sign bit set. - -int64_t -read_signed_LEB_128(const unsigned char* buffer, size_t* len) -{ - int64_t result = 0; - int shift = 0; - size_t num_read = 0; - unsigned char byte; - - do - { - if (num_read >= 64 / 7) - { - gold_warning(_("Unusually large LEB128 decoded, " - "debug information may be corrupted")); - break; - } - byte = *buffer++; - num_read++; - result |= (static_cast<uint64_t>(byte & 0x7f) << shift); - shift += 7; - } - while (byte & 0x80); - - if ((shift < 8 * static_cast<int>(sizeof(result))) && (byte & 0x40)) - result |= -((static_cast<int64_t>(1)) << shift); - *len = num_read; - return result; -} - -// This is the format of a DWARF2/3 line state machine that we process -// opcodes using. There is no need for anything outside the lineinfo -// processor to know how this works. - struct LineStateMachine { int file_num; @@ -129,7 +62,7 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt) template<int size, bool big_endian> Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object, - off_t read_shndx) + unsigned int read_shndx) : data_valid_(false), buffer_(NULL), symtab_buffer_(NULL), directories_(), files_(), current_header_index_(-1) { @@ -508,7 +441,7 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode( template<int size, bool big_endian> unsigned const char* Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr, - off_t shndx) + unsigned int shndx) { struct LineStateMachine lsm; @@ -595,7 +528,7 @@ Sized_dwarf_line_info<size, big_endian>::read_relocs(Object* object) template<int size, bool big_endian> void Sized_dwarf_line_info<size, big_endian>::read_line_mappings(Object* object, - off_t shndx) + unsigned int shndx) { gold_assert(this->data_valid_ == true); diff --git a/binutils-2.19/gold/dwarf_reader.h b/binutils-2.19/gold/dwarf_reader.h index c9d760c..e2b8aa0 100644 --- a/binutils-2.19/gold/dwarf_reader.h +++ b/binutils-2.19/gold/dwarf_reader.h @@ -1,6 +1,6 @@ // dwarf_reader.h -- parse dwarf2/3 debug information for gold -*- C++ -*- -// Copyright 2007, 2008 Free Software Foundation, Inc. +// Copyright 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -38,12 +38,6 @@ template<int size, bool big_endian> class Track_relocs; struct LineStateMachine; -uint64_t -read_unsigned_LEB_128(const unsigned char* buffer, size_t* len); - -int64_t -read_signed_LEB_128(const unsigned char* buffer, size_t* len); - // We can't do better than to keep the offsets in a sorted vector. // Here, offset is the key, and file_num/line_num is the value. struct Offset_to_lineno_entry @@ -105,7 +99,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info // Initializes a .debug_line reader for a given object file. // If SHNDX is specified and non-negative, only read the debug // information that pertains to the specified section. - Sized_dwarf_line_info(Object* object, off_t read_shndx = -1U); + Sized_dwarf_line_info(Object* object, unsigned int read_shndx = -1U); private: std::string @@ -115,7 +109,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info // If SHNDX is non-negative, only store debug information that // pertains to the specified section. void - read_line_mappings(Object*, off_t shndx); + read_line_mappings(Object*, unsigned int shndx); // Reads the relocation section associated with .debug_line and // stores relocation information in reloc_map_. @@ -140,7 +134,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info // discard all line information that doesn't pertain to the given // section. const unsigned char* - read_lines(const unsigned char* lineptr, off_t shndx); + read_lines(const unsigned char* lineptr, unsigned int shndx); // Process a single line info opcode at START using the state // machine at LSM. Return true if we should define a line using the diff --git a/binutils-2.19/gold/dynobj.cc b/binutils-2.19/gold/dynobj.cc index 5420613..dc6b009 100644 --- a/binutils-2.19/gold/dynobj.cc +++ b/binutils-2.19/gold/dynobj.cc @@ -1,6 +1,6 @@ // dynobj.cc -- dynamic object support for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -83,13 +83,8 @@ Sized_dynobj<size, big_endian>::Sized_dynobj( template<int size, bool big_endian> void -Sized_dynobj<size, big_endian>::setup( - const elfcpp::Ehdr<size, big_endian>& ehdr) +Sized_dynobj<size, big_endian>::setup() { - this->set_target(ehdr.get_e_machine(), size, big_endian, - ehdr.get_e_ident()[elfcpp::EI_OSABI], - ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]); - const unsigned int shnum = this->elf_file_.shnum(); this->set_shnum(shnum); } @@ -111,6 +106,7 @@ Sized_dynobj<size, big_endian>::find_dynsym_sections( *pverneed_shndx = -1U; *pdynamic_shndx = -1U; + unsigned int symtab_shndx = 0; unsigned int xindex_shndx = 0; unsigned int xindex_link = 0; const unsigned int shnum = this->shnum(); @@ -133,6 +129,10 @@ Sized_dynobj<size, big_endian>::find_dynsym_sections( } pi = NULL; break; + case elfcpp::SHT_SYMTAB: + symtab_shndx = i; + pi = NULL; + break; case elfcpp::SHT_GNU_versym: pi = pversym_shndx; break; @@ -171,6 +171,25 @@ Sized_dynobj<size, big_endian>::find_dynsym_sections( *pi = i; } + + // If there is no dynamic symbol table, use the normal symbol table. + // On some SVR4 systems, a shared library is stored in an archive. + // The version stored in the archive only has a normal symbol table. + // It has an SONAME entry which points to another copy in the file + // system which has a dynamic symbol table as usual. This is way of + // addressing the issues which glibc addresses using GROUP with + // libc_nonshared.a. + if (this->dynsym_shndx_ == -1U && symtab_shndx != 0) + { + this->dynsym_shndx_ = symtab_shndx; + if (xindex_shndx > 0 && xindex_link == symtab_shndx) + { + Xindex* xindex = new Xindex(this->elf_file_.large_shndx_offset()); + xindex->read_symtab_xindex<size, big_endian>(this, xindex_shndx, + pshdrs); + this->set_xindex(xindex); + } + } } // Read the contents of section SHNDX. PSHDRS points to the section @@ -328,13 +347,20 @@ Sized_dynobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd) sd->external_symbols_offset = 0; sd->symbol_names = NULL; sd->symbol_names_size = 0; + sd->versym = NULL; + sd->versym_size = 0; + sd->verdef = NULL; + sd->verdef_size = 0; + sd->verdef_info = 0; + sd->verneed = NULL; + sd->verneed_size = 0; + sd->verneed_info = 0; if (this->dynsym_shndx_ != -1U) { // Get the dynamic symbols. typename This::Shdr dynsymshdr(pshdrs + this->dynsym_shndx_ * This::shdr_size); - gold_assert(dynsymshdr.get_sh_type() == elfcpp::SHT_DYNSYM); sd->symbols = this->get_lasting_view(dynsymshdr.get_sh_offset(), dynsymshdr.get_sh_size(), true, @@ -413,7 +439,7 @@ Sized_dynobj<size, big_endian>::do_initialize_xindex() // Lay out the input sections for a dynamic object. We don't want to // include sections from a dynamic object, so all that we actually do -// here is check for .gnu.warning sections. +// here is check for .gnu.warning and .note.GNU-split-stack sections. template<int size, bool big_endian> void @@ -448,6 +474,7 @@ Sized_dynobj<size, big_endian>::do_layout(Symbol_table* symtab, const char* name = pnames + shdr.get_sh_name(); this->handle_gnu_warning_section(name, i, symtab); + this->handle_split_stack_section(name); } delete sd->section_headers; @@ -655,7 +682,8 @@ Sized_dynobj<size, big_endian>::make_version_map( template<int size, bool big_endian> void Sized_dynobj<size, big_endian>::do_add_symbols(Symbol_table* symtab, - Read_symbols_data* sd) + Read_symbols_data* sd, + Layout*) { if (sd->symbols == NULL) { @@ -677,9 +705,10 @@ Sized_dynobj<size, big_endian>::do_add_symbols(Symbol_table* symtab, Version_map version_map; this->make_version_map(sd, &version_map); - // If printing symbol counts, we want to track symbols. - - if (parameters->options().user_set_print_symbol_counts()) + // If printing symbol counts or a cross reference table, we want to + // track symbols. + if (parameters->options().user_set_print_symbol_counts() + || parameters->options().cref()) { this->symbols_ = new Symbols(); this->symbols_->resize(symcount); @@ -954,9 +983,10 @@ Dynobj::create_gnu_hash_table(const std::vector<Symbol*>& dynsyms, { Symbol* sym = dynsyms[i]; - // FIXME: Should put on unhashed_dynsyms if the symbol is - // hidden. - if (sym->is_undefined()) + if (!sym->needs_dynsym_value() + && (sym->is_undefined() + || sym->is_from_dynobj() + || sym->is_forced_local())) unhashed_dynsyms.push_back(sym); else { @@ -1303,27 +1333,18 @@ Verneed::write(const Stringpool* dynpool, bool is_last, Versions::Versions(const Version_script_info& version_script, Stringpool* dynpool) : defs_(), needs_(), version_table_(), - is_finalized_(false), version_script_(version_script) + is_finalized_(false), version_script_(version_script), + needs_base_version_(parameters->options().shared()) { - // We always need a base version, so define that first. Nothing - // explicitly declares itself as part of base, so it doesn't need to - // be in version_table_. - if (parameters->options().shared()) - { - const char* name = parameters->options().soname(); - if (name == NULL) - name = parameters->options().output_file_name(); - name = dynpool->add(name, false, NULL); - Verdef* vdbase = new Verdef(name, std::vector<std::string>(), - true, false, true); - this->defs_.push_back(vdbase); - } - if (!this->version_script_.empty()) { // Parse the version script, and insert each declared version into // defs_ and version_table_. std::vector<std::string> versions = this->version_script_.get_versions(); + + if (this->needs_base_version_ && !versions.empty()) + this->define_base_version(dynpool); + for (size_t k = 0; k < versions.size(); ++k) { Stringpool::Key version_key; @@ -1353,6 +1374,28 @@ Versions::~Versions() delete *p; } +// Define the base version of a shared library. The base version definition +// must be the first entry in defs_. We insert it lazily so that defs_ is +// empty if no symbol versioning is used. Then layout can just drop the +// version sections. + +void +Versions::define_base_version(Stringpool* dynpool) +{ + // If we do any versioning at all, we always need a base version, so + // define that first. Nothing explicitly declares itself as part of base, + // so it doesn't need to be in version_table_. + gold_assert(this->defs_.empty()); + const char* name = parameters->options().soname(); + if (name == NULL) + name = parameters->options().output_file_name(); + name = dynpool->add(name, false, NULL); + Verdef* vdbase = new Verdef(name, std::vector<std::string>(), + true, false, true); + this->defs_.push_back(vdbase); + this->needs_base_version_ = false; +} + // Return the dynamic object which a symbol refers to. Dynobj* @@ -1424,7 +1467,10 @@ Versions::add_def(const Symbol* sym, const char* version, if (parameters->options().shared()) gold_error(_("symbol %s has undefined version %s"), sym->demangled_name().c_str(), version); - + else + // We only insert a base version for shared library. + gold_assert(!this->needs_base_version_); + // When creating a regular executable, automatically define // a new version. Verdef* vd = new Verdef(version, std::vector<std::string>(), @@ -1471,6 +1517,10 @@ Versions::add_need(Stringpool* dynpool, const char* filename, const char* name, if (vn == NULL) { + // Create base version definition lazily for shared library. + if (this->needs_base_version_) + this->define_base_version(dynpool); + // We have a new filename. vn = new Verneed(filename); this->needs_.push_back(vn); @@ -1501,13 +1551,16 @@ Versions::finalize(Symbol_table* symtab, unsigned int dynsym_index, if (!(*p)->is_symbol_created()) { Symbol* vsym = symtab->define_as_constant((*p)->name(), - (*p)->name(), 0, 0, + (*p)->name(), + Symbol_table::PREDEFINED, + 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_GLOBAL, elfcpp::STV_DEFAULT, 0, false, false); vsym->set_needs_dynsym_entry(); vsym->set_dynsym_index(dynsym_index); + vsym->set_is_default(); ++dynsym_index; syms->push_back(vsym); // The name is already in the dynamic pool. @@ -1597,10 +1650,15 @@ Versions::symbol_section_contents(const Symbol_table* symtab, { unsigned int version_index; const char* version = (*p)->version(); - if (version == NULL) - version_index = elfcpp::VER_NDX_GLOBAL; - else + if (version != NULL) version_index = this->version_index(symtab, dynpool, *p); + else + { + if ((*p)->is_defined() && !(*p)->is_from_dynobj()) + version_index = elfcpp::VER_NDX_GLOBAL; + else + version_index = elfcpp::VER_NDX_LOCAL; + } // If the symbol was defined as foo@V1 instead of foo@@V1, add // the hidden bit. if ((*p)->version() != NULL && !(*p)->is_default()) diff --git a/binutils-2.19/gold/dynobj.h b/binutils-2.19/gold/dynobj.h index b5b9bd9..71d1b68 100644 --- a/binutils-2.19/gold/dynobj.h +++ b/binutils-2.19/gold/dynobj.h @@ -1,6 +1,6 @@ // dynobj.h -- dynamic object support for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -161,9 +161,9 @@ class Sized_dynobj : public Dynobj Sized_dynobj(const std::string& name, Input_file* input_file, off_t offset, const typename elfcpp::Ehdr<size, big_endian>&); - // Set up the object file based on the ELF header. + // Set up the object file based on TARGET. void - setup(const typename elfcpp::Ehdr<size, big_endian>&); + setup(); // Read the symbols. void @@ -175,7 +175,7 @@ class Sized_dynobj : public Dynobj // Add the symbols to the symbol table. void - do_add_symbols(Symbol_table*, Read_symbols_data*); + do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*); // Get the size of a section. uint64_t @@ -198,6 +198,11 @@ class Sized_dynobj : public Dynobj do_section_flags(unsigned int shndx) { return this->elf_file_.section_flags(shndx); } + // Not used for dynobj. + uint64_t + do_section_entsize(unsigned int ) + { gold_unreachable(); } + // Return section address. uint64_t do_section_address(unsigned int shndx) @@ -231,6 +236,11 @@ class Sized_dynobj : public Dynobj void do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const; + // Get the global symbols. + const Symbols* + do_get_global_symbols() const + { return this->symbols_; } + private: // For convenience. typedef Sized_dynobj<size, big_endian> This; @@ -579,6 +589,10 @@ class Versions version_index(const Symbol_table*, const Stringpool*, const Symbol* sym) const; + // Define the base version of a shared library. + void + define_base_version(Stringpool* dynpool); + // We keep a hash table mapping canonicalized name/version pairs to // a version base. typedef std::pair<Stringpool::Key, Stringpool::Key> Key; @@ -611,6 +625,9 @@ class Versions bool is_finalized_; // Contents of --version-script, if passed, or NULL. const Version_script_info& version_script_; + // Whether we need to insert a base version. This is only used for + // shared libaries and is cleared when the base version is defined. + bool needs_base_version_; }; } // End namespace gold. diff --git a/binutils-2.19/gold/errors.cc b/binutils-2.19/gold/errors.cc index 01ce97f..b8031b1 100644 --- a/binutils-2.19/gold/errors.cc +++ b/binutils-2.19/gold/errors.cc @@ -1,6 +1,6 @@ // errors.cc -- handle errors for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -39,8 +39,8 @@ namespace gold const int Errors::max_undefined_error_report; Errors::Errors(const char* program_name) - : program_name_(program_name), lock_(NULL), error_count_(0), - warning_count_(0), undefined_symbols_() + : program_name_(program_name), lock_(NULL), initialize_lock_(&this->lock_), + error_count_(0), warning_count_(0), undefined_symbols_() { } @@ -53,9 +53,7 @@ Errors::Errors(const char* program_name) bool Errors::initialize_lock() { - if (this->lock_ == NULL && parameters->options_valid()) - this->lock_ = new Lock; - return this->lock_ != NULL; + return this->initialize_lock_.initialize(); } // Increment a counter, holding the lock if available. @@ -80,7 +78,7 @@ Errors::increment_counter(int *counter) void Errors::fatal(const char* format, va_list args) { - fprintf(stderr, "%s: ", this->program_name_); + fprintf(stderr, _("%s: fatal error: "), this->program_name_); vfprintf(stderr, format, args); fputc('\n', stderr); gold_exit(false); @@ -91,7 +89,7 @@ Errors::fatal(const char* format, va_list args) void Errors::error(const char* format, va_list args) { - fprintf(stderr, "%s: ", this->program_name_); + fprintf(stderr, _("%s: error: "), this->program_name_); vfprintf(stderr, format, args); fputc('\n', stderr); @@ -127,7 +125,7 @@ Errors::error_at_location(const Relocate_info<size, big_endian>* relinfo, size_t relnum, off_t reloffset, const char* format, va_list args) { - fprintf(stderr, "%s: %s: ", this->program_name_, + fprintf(stderr, _("%s: %s: error: "), this->program_name_, relinfo->location(relnum, reloffset).c_str()); vfprintf(stderr, format, args); fputc('\n', stderr); @@ -151,30 +149,40 @@ Errors::warning_at_location(const Relocate_info<size, big_endian>* relinfo, this->increment_counter(&this->warning_count_); } -// Issue an undefined symbol error. +// Issue an undefined symbol error with a caller-supplied location string. -template<int size, bool big_endian> void -Errors::undefined_symbol(const Symbol* sym, - const Relocate_info<size, big_endian>* relinfo, - size_t relnum, off_t reloffset) +Errors::undefined_symbol(const Symbol* sym, const std::string& location) { bool initialized = this->initialize_lock(); gold_assert(initialized); + + const char* zmsg; { Hold_lock h(*this->lock_); if (++this->undefined_symbols_[sym] >= max_undefined_error_report) return; - ++this->error_count_; + if (parameters->options().warn_unresolved_symbols()) + { + ++this->warning_count_; + zmsg = _("warning"); + } + else + { + ++this->error_count_; + zmsg = _("error"); + } } + const char* const version = sym->version(); if (version == NULL) - fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"), - this->program_name_, relinfo->location(relnum, reloffset).c_str(), + fprintf(stderr, _("%s: %s: %s: undefined reference to '%s'\n"), + this->program_name_, location.c_str(), zmsg, sym->demangled_name().c_str()); else - fprintf(stderr, _("%s: %s: undefined reference to '%s', version '%s'\n"), - this->program_name_, relinfo->location(relnum, reloffset).c_str(), + fprintf(stderr, + _("%s: %s: %s: undefined reference to '%s', version '%s'\n"), + this->program_name_, location.c_str(), zmsg, sym->demangled_name().c_str(), version); } @@ -271,13 +279,22 @@ gold_warning_at_location(const Relocate_info<size, big_endian>* relinfo, // Report an undefined symbol. +void +gold_undefined_symbol(const Symbol* sym) +{ + parameters->errors()->undefined_symbol(sym, sym->object()->name().c_str()); +} + +// Report an undefined symbol at a reloc location + template<int size, bool big_endian> void -gold_undefined_symbol(const Symbol* sym, +gold_undefined_symbol_at_location(const Symbol* sym, const Relocate_info<size, big_endian>* relinfo, size_t relnum, off_t reloffset) { - parameters->errors()->undefined_symbol(sym, relinfo, relnum, reloffset); + parameters->errors()->undefined_symbol(sym, + relinfo->location(relnum, reloffset)); } #ifdef HAVE_TARGET_32_LITTLE @@ -347,33 +364,37 @@ gold_warning_at_location<64, true>(const Relocate_info<64, true>* relinfo, #ifdef HAVE_TARGET_32_LITTLE template void -gold_undefined_symbol<32, false>(const Symbol* sym, - const Relocate_info<32, false>* relinfo, - size_t relnum, off_t reloffset); +gold_undefined_symbol_at_location<32, false>( + const Symbol* sym, + const Relocate_info<32, false>* relinfo, + size_t relnum, off_t reloffset); #endif #ifdef HAVE_TARGET_32_BIG template void -gold_undefined_symbol<32, true>(const Symbol* sym, - const Relocate_info<32, true>* relinfo, - size_t relnum, off_t reloffset); +gold_undefined_symbol_at_location<32, true>( + const Symbol* sym, + const Relocate_info<32, true>* relinfo, + size_t relnum, off_t reloffset); #endif #ifdef HAVE_TARGET_64_LITTLE template void -gold_undefined_symbol<64, false>(const Symbol* sym, - const Relocate_info<64, false>* relinfo, - size_t relnum, off_t reloffset); +gold_undefined_symbol_at_location<64, false>( + const Symbol* sym, + const Relocate_info<64, false>* relinfo, + size_t relnum, off_t reloffset); #endif #ifdef HAVE_TARGET_64_BIG template void -gold_undefined_symbol<64, true>(const Symbol* sym, - const Relocate_info<64, true>* relinfo, - size_t relnum, off_t reloffset); +gold_undefined_symbol_at_location<64, true>( + const Symbol* sym, + const Relocate_info<64, true>* relinfo, + size_t relnum, off_t reloffset); #endif } // End namespace gold. diff --git a/binutils-2.19/gold/errors.h b/binutils-2.19/gold/errors.h index b373a06..a8f823d 100644 --- a/binutils-2.19/gold/errors.h +++ b/binutils-2.19/gold/errors.h @@ -75,14 +75,10 @@ class Errors size_t relnum, off_t reloffset, const char* format, va_list); - // Issue an undefined symbol error. SYM is the undefined symbol. - // RELINFO is the general relocation info. RELNUM is the number of - // the reloc, and RELOFFSET is the reloc's offset. - template<int size, bool big_endian> + // Issue an undefined symbol error. LOCATION is the location of + // the error (typically an object file name or relocation info). void - undefined_symbol(const Symbol* sym, - const Relocate_info<size, big_endian>* relinfo, - size_t relnum, off_t reloffset); + undefined_symbol(const Symbol* sym, const std::string& location); // Report a debugging message. void @@ -120,6 +116,8 @@ class Errors // This class can be accessed from multiple threads. This lock is // used to control access to the data structures. Lock* lock_; + // Used to initialize the lock_ field exactly once. + Initialize_lock initialize_lock_; // Numbers of errors reported. int error_count_; // Number of warnings reported. diff --git a/binutils-2.19/gold/expression.cc b/binutils-2.19/gold/expression.cc index 25f3ac3..853a698 100644 --- a/binutils-2.19/gold/expression.cc +++ b/binutils-2.19/gold/expression.cc @@ -1113,17 +1113,62 @@ script_exp_function_sizeof_headers() return new Sizeof_headers_expression(); } -// In the GNU linker SEGMENT_START basically returns the value for -// -Ttext, -Tdata, or -Tbss. We could implement this by copying the -// values from General_options to Parameters. But I doubt that -// anybody actually uses it. The point of it for the GNU linker was -// because -Ttext set the address of the .text section rather than the -// text segment. In gold -Ttext sets the text segment address anyhow. +// SEGMENT_START. + +class Segment_start_expression : public Unary_expression +{ + public: + Segment_start_expression(const char* segment_name, size_t segment_name_len, + Expression* default_value) + : Unary_expression(default_value), + segment_name_(segment_name, segment_name_len) + { } + + uint64_t + value(const Expression_eval_info*); + + void + print(FILE* f) const + { + fprintf(f, "SEGMENT_START(\"%s\", ", this->segment_name_.c_str()); + this->arg_print(f); + fprintf(f, ")"); + } + + private: + std::string segment_name_; +}; + +uint64_t +Segment_start_expression::value(const Expression_eval_info* eei) +{ + // Check for command line overrides. + if (parameters->options().user_set_Ttext() + && this->segment_name_ == ".text") + return parameters->options().Ttext(); + else if (parameters->options().user_set_Tdata() + && this->segment_name_ == ".data") + return parameters->options().Tdata(); + else if (parameters->options().user_set_Tbss() + && this->segment_name_ == ".bss") + return parameters->options().Tbss(); + else + { + Output_section* dummy; + uint64_t ret = this->arg_value(eei, &dummy); + // Force the value to be absolute. + *eei->result_section_pointer = NULL; + return ret; + } +} extern "C" Expression* -script_exp_function_segment_start(const char*, size_t, Expression*) +script_exp_function_segment_start(const char* segment_name, + size_t segment_name_len, + Expression* default_value) { - gold_fatal(_("SEGMENT_START not implemented")); + return new Segment_start_expression(segment_name, segment_name_len, + default_value); } // Functions for memory regions. These can not be implemented unless diff --git a/binutils-2.19/gold/ffsll.c b/binutils-2.19/gold/ffsll.c new file mode 100644 index 0000000..b247bc3 --- /dev/null +++ b/binutils-2.19/gold/ffsll.c @@ -0,0 +1,48 @@ +/* ffsll.c -- version of ffsll for gold. */ + +/* Copyright 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor <iant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" + +#include <string.h> + +extern int ffsll (long long); + +/* This file implements ffsll for systems which don't have it. We use + ffsll if possible because gcc supports it as a builtin which will + use a machine instruction if there is one. */ + +int +ffsll (long long arg) +{ + unsigned long long i; + int ret; + + if (arg == 0) + ret = 0; + else + { + ret = 1; + for (i = (unsigned long long) arg; (i & 1) == 0; i >>= 1) + ++ret; + } + return ret; +} diff --git a/binutils-2.19/gold/fileread.cc b/binutils-2.19/gold/fileread.cc index 8c2f8f3..9f19099 100644 --- a/binutils-2.19/gold/fileread.cc +++ b/binutils-2.19/gold/fileread.cc @@ -1,6 +1,6 @@ // fileread.cc -- read files for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -28,6 +28,7 @@ #include <unistd.h> #include <sys/mman.h> #include <sys/uio.h> +#include <sys/stat.h> #include "filenames.h" #include "debug.h" @@ -37,8 +38,18 @@ #include "target.h" #include "binary.h" #include "descriptors.h" +#include "gold-threads.h" #include "fileread.h" +#ifndef HAVE_READV +struct iovec { void* iov_base; size_t iov_len }; +ssize_t +readv(int, const iovec*, int) +{ + gold_unreachable(); +} +#endif + namespace gold { @@ -47,14 +58,20 @@ namespace gold File_read::View::~View() { gold_assert(!this->is_locked()); - if (!this->mapped_) - delete[] this->data_; - else + switch (this->data_ownership_) { + case DATA_ALLOCATED_ARRAY: + delete[] this->data_; + break; + case DATA_MMAPPED: if (::munmap(const_cast<unsigned char*>(this->data_), this->size_) != 0) gold_warning(_("munmap failed: %s"), strerror(errno)); - File_read::current_mapped_bytes -= this->size_; + break; + case DATA_NOT_OWNED: + break; + default: + gold_unreachable(); } } @@ -79,6 +96,10 @@ File_read::View::is_locked() // Class File_read. +// A lock for the File_read static variables. +static Lock* file_counts_lock = NULL; +static Initialize_lock file_counts_initialize_lock(&file_counts_lock); + // The File_read static variables. unsigned long long File_read::total_mapped_bytes; unsigned long long File_read::current_mapped_bytes; @@ -95,6 +116,8 @@ File_read::~File_read() } this->name_.clear(); this->clear_views(true); + if (this->whole_file_view_) + delete this->whole_file_view_; } // Open the file. @@ -122,6 +145,22 @@ File_read::open(const Task* task, const std::string& name) gold_debug(DEBUG_FILES, "Attempt to open %s succeeded", this->name_.c_str()); + // Options may not yet be ready e.g. when reading a version + // script. We then default to --no-keep-files-mapped. + if (parameters->options_valid() + && parameters->options().keep_files_mapped()) + { + const unsigned char* contents = static_cast<const unsigned char*>( + ::mmap(NULL, this->size_, PROT_READ, MAP_PRIVATE, + this->descriptor_, 0)); + if (contents == MAP_FAILED) + gold_fatal(_("%s: mmap failed: %s"), this->filename().c_str(), + strerror(errno)); + this->whole_file_view_ = new View(0, this->size_, contents, 0, false, + View::DATA_MMAPPED); + this->mapped_bytes_ += this->size_; + } + this->token_.add_writer(task); } @@ -139,7 +178,8 @@ File_read::open(const Task* task, const std::string& name, && !this->is_descriptor_opened_ && this->name_.empty()); this->name_ = name; - this->contents_ = contents; + this->whole_file_view_ = new View(0, size, contents, 0, false, + View::DATA_NOT_OWNED); this->size_ = size; this->token_.add_writer(task); return true; @@ -169,11 +209,17 @@ File_read::release() { gold_assert(this->is_locked()); - File_read::total_mapped_bytes += this->mapped_bytes_; - File_read::current_mapped_bytes += this->mapped_bytes_; + if (!parameters->options_valid() || parameters->options().stats()) + { + file_counts_initialize_lock.initialize(); + Hold_optional_lock hl(file_counts_lock); + File_read::total_mapped_bytes += this->mapped_bytes_; + File_read::current_mapped_bytes += this->mapped_bytes_; + if (File_read::current_mapped_bytes > File_read::maximum_mapped_bytes) + File_read::maximum_mapped_bytes = File_read::current_mapped_bytes; + } + this->mapped_bytes_ = 0; - if (File_read::current_mapped_bytes > File_read::maximum_mapped_bytes) - File_read::maximum_mapped_bytes = File_read::current_mapped_bytes; // Only clear views if there is only one attached object. Otherwise // we waste time trying to clear cached archive views. Similarly @@ -236,6 +282,12 @@ File_read::find_view(off_t start, section_size_type size, if (vshifted != NULL) *vshifted = NULL; + // If we have the whole file mmapped, and the alignment is right, + // we can return it. + if (this->whole_file_view_) + if (byteshift == -1U || byteshift == 0) + return this->whole_file_view_; + off_t page = File_read::page_offset(start); unsigned int bszero = 0; @@ -271,12 +323,12 @@ void File_read::do_read(off_t start, section_size_type size, void* p) { ssize_t bytes; - if (this->contents_ != NULL) + if (this->whole_file_view_ != NULL) { bytes = this->size_ - start; if (static_cast<section_size_type>(bytes) >= size) { - memcpy(p, this->contents_ + start, size); + memcpy(p, this->whole_file_view_->data() + start, size); return; } } @@ -355,6 +407,16 @@ File_read::make_view(off_t start, section_size_type size, { gold_assert(size > 0); + // Check that start and end of the view are within the file. + if (start > this->size_ + || (static_cast<unsigned long long>(size) + > static_cast<unsigned long long>(this->size_ - start))) + gold_fatal(_("%s: attempt to map %lld bytes at offset %lld exceeds " + "size of file; the file may be corrupt"), + this->filename().c_str(), + static_cast<long long>(size), + static_cast<long long>(start)); + off_t poff = File_read::page_offset(start); section_size_type psize = File_read::pages(size + (start - poff)); @@ -366,12 +428,13 @@ File_read::make_view(off_t start, section_size_type size, } File_read::View* v; - if (this->contents_ != NULL || byteshift != 0) + if (this->whole_file_view_ != NULL || byteshift != 0) { unsigned char* p = new unsigned char[psize + byteshift]; memset(p, 0, byteshift); this->do_read(poff, psize, p + byteshift); - v = new File_read::View(poff, psize, p, byteshift, cache, false); + v = new File_read::View(poff, psize, p, byteshift, cache, + View::DATA_ALLOCATED_ARRAY); } else { @@ -388,7 +451,8 @@ File_read::make_view(off_t start, section_size_type size, this->mapped_bytes_ += psize; const unsigned char* pbytes = static_cast<const unsigned char*>(p); - v = new File_read::View(poff, psize, pbytes, 0, cache, true); + v = new File_read::View(poff, psize, pbytes, 0, cache, + View::DATA_MMAPPED); } this->add_view(v); @@ -443,9 +507,9 @@ File_read::find_or_make_view(off_t offset, off_t start, memset(pbytes, 0, byteshift); memcpy(pbytes + byteshift, v->data() + v->byteshift(), v->size()); - File_read::View* shifted_view = new File_read::View(v->start(), v->size(), - pbytes, byteshift, - cache, false); + File_read::View* shifted_view = + new File_read::View(v->start(), v->size(), pbytes, byteshift, + cache, View::DATA_ALLOCATED_ARRAY); this->add_view(shifted_view); return shifted_view; @@ -706,9 +770,9 @@ Input_file::Input_file(const Task* task, const char* name, : file_() { this->input_argument_ = - new Input_file_argument(name, false, "", false, - Position_dependent_options()); - bool ok = file_.open(task, name, contents, size); + new Input_file_argument(name, Input_file_argument::INPUT_FILE_TYPE_FILE, + "", false, Position_dependent_options()); + bool ok = this->file_.open(task, name, contents, size); gold_assert(ok); } @@ -728,6 +792,16 @@ Input_file::name() const return this->input_argument_->name(); } +// Return whether this file is in a system directory. + +bool +Input_file::is_in_system_directory() const +{ + if (this->is_in_sysroot()) + return true; + return parameters->options().is_in_system_directory(this->filename()); +} + // Return whether we are only reading symbols. bool @@ -736,51 +810,90 @@ Input_file::just_symbols() const return this->input_argument_->just_symbols(); } +// Return whether this is a file that we will search for in the list +// of directories. + +bool +Input_file::will_search_for() const +{ + return (!IS_ABSOLUTE_PATH(this->input_argument_->name()) + && (this->input_argument_->is_lib() + || this->input_argument_->is_searched_file() + || this->input_argument_->extra_search_path() != NULL)); +} + +// Return the file last modification time. Calls gold_fatal if the stat +// system call failed. + +Timespec +File_read::get_mtime() +{ + struct stat file_stat; + this->reopen_descriptor(); + + if (fstat(this->descriptor_, &file_stat) < 0) + gold_fatal(_("%s: stat failed: %s"), this->name_.c_str(), + strerror(errno)); +#ifdef HAVE_STAT_ST_MTIM + return Timespec(file_stat.st_mtim.tv_sec, file_stat.st_mtim.tv_nsec); +#else + return Timespec(file_stat.st_mtime, 0); +#endif +} + // Open the file. // If the filename is not absolute, we assume it is in the current // directory *except* when: -// A) input_argument_->is_lib() is true; or -// B) input_argument_->extra_search_path() is not empty. -// In both cases, we look in extra_search_path + library_path to find +// A) input_argument_->is_lib() is true; +// B) input_argument_->is_searched_file() is true; or +// C) input_argument_->extra_search_path() is not empty. +// In each, we look in extra_search_path + library_path to find // the file location, rather than the current directory. bool -Input_file::open(const General_options& options, const Dirsearch& dirpath, - const Task* task) +Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex) { std::string name; // Case 1: name is an absolute file, just try to open it - // Case 2: name is relative but is_lib is false and extra_search_path - // is empty - if (IS_ABSOLUTE_PATH (this->input_argument_->name()) + // Case 2: name is relative but is_lib is false, is_searched_file is false, + // and extra_search_path is empty + if (IS_ABSOLUTE_PATH(this->input_argument_->name()) || (!this->input_argument_->is_lib() + && !this->input_argument_->is_searched_file() && this->input_argument_->extra_search_path() == NULL)) { name = this->input_argument_->name(); this->found_name_ = name; } - // Case 3: is_lib is true - else if (this->input_argument_->is_lib()) + // Case 3: is_lib is true or is_searched_file is true + else if (this->input_argument_->is_lib() + || this->input_argument_->is_searched_file()) { // We don't yet support extra_search_path with -l. gold_assert(this->input_argument_->extra_search_path() == NULL); - std::string n1("lib"); - n1 += this->input_argument_->name(); - std::string n2; - if (options.is_static() - || !this->input_argument_->options().Bdynamic()) - n1 += ".a"; - else + std::string n1, n2; + if (this->input_argument_->is_lib()) { - n2 = n1 + ".a"; - n1 += ".so"; + n1 = "lib"; + n1 += this->input_argument_->name(); + if (parameters->options().is_static() + || !this->input_argument_->options().Bdynamic()) + n1 += ".a"; + else + { + n2 = n1 + ".a"; + n1 += ".so"; + } } - name = dirpath.find(n1, n2, &this->is_in_sysroot_); + else + n1 = this->input_argument_->name(); + name = dirpath.find(n1, n2, &this->is_in_sysroot_, pindex); if (name.empty()) { - gold_error(_("cannot find -l%s"), + gold_error(_("cannot find %s%s"), + this->input_argument_->is_lib() ? "-l" : "", this->input_argument_->name()); return false; } @@ -800,17 +913,21 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath, name += '/'; name += this->input_argument_->name(); struct stat dummy_stat; - if (::stat(name.c_str(), &dummy_stat) < 0) + if (*pindex > 0 || ::stat(name.c_str(), &dummy_stat) < 0) { // extra_search_path failed, so check the normal search-path. + int index = *pindex; + if (index > 0) + --index; name = dirpath.find(this->input_argument_->name(), "", - &this->is_in_sysroot_); + &this->is_in_sysroot_, &index); if (name.empty()) { gold_error(_("cannot find %s"), this->input_argument_->name()); return false; } + *pindex = index + 1; } this->found_name_ = this->input_argument_->name(); } @@ -821,17 +938,22 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath, this->input_argument_->options().format_enum(); bool ok; if (format == General_options::OBJECT_FORMAT_ELF) - ok = this->file_.open(task, name); + { + ok = this->file_.open(task, name); + this->format_ = FORMAT_ELF; + } else { gold_assert(format == General_options::OBJECT_FORMAT_BINARY); - ok = this->open_binary(options, task, name); + ok = this->open_binary(task, name); + this->format_ = FORMAT_BINARY; } if (!ok) { gold_error(_("cannot open %s: %s"), name.c_str(), strerror(errno)); + this->format_ = FORMAT_NONE; return false; } @@ -841,21 +963,17 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath, // Open a file for --format binary. bool -Input_file::open_binary(const General_options&, - const Task* task, const std::string& name) +Input_file::open_binary(const Task* task, const std::string& name) { // In order to open a binary file, we need machine code, size, and // endianness. We may not have a valid target at this point, in // which case we use the default target. - const Target* target; - if (parameters->target_valid()) - target = ¶meters->target(); - else - target = ¶meters->default_target(); + parameters_force_valid_target(); + const Target& target(parameters->target()); - Binary_to_elf binary_to_elf(target->machine_code(), - target->get_size(), - target->is_big_endian(), + Binary_to_elf binary_to_elf(target.machine_code(), + target.get_size(), + target.is_big_endian(), name); if (!binary_to_elf.convert(task)) return false; diff --git a/binutils-2.19/gold/fileread.h b/binutils-2.19/gold/fileread.h index 4236ce0..9933460 100644 --- a/binutils-2.19/gold/fileread.h +++ b/binutils-2.19/gold/fileread.h @@ -1,6 +1,6 @@ // fileread.h -- read files for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -35,6 +35,23 @@ namespace gold { +// Since not all system supports stat.st_mtim and struct timespec, +// we define our own structure and fill the nanoseconds if we can. + +struct Timespec +{ + Timespec() + : seconds(0), nanoseconds(0) + { } + + Timespec(time_t a_seconds, int a_nanoseconds) + : seconds(a_seconds), nanoseconds(a_nanoseconds) + { } + + time_t seconds; + int nanoseconds; +}; + class Position_dependent_options; class Input_file_argument; class Dirsearch; @@ -48,8 +65,8 @@ class File_read public: File_read() : name_(), descriptor_(-1), is_descriptor_opened_(false), object_count_(0), - size_(0), token_(false), views_(), saved_views_(), contents_(NULL), - mapped_bytes_(0), released_(true) + size_(0), token_(false), views_(), saved_views_(), mapped_bytes_(0), + released_(true), whole_file_view_(NULL) { } ~File_read(); @@ -183,31 +200,56 @@ class File_read static void print_stats(); + // Return the open file descriptor (for plugins). + int + descriptor() + { + this->reopen_descriptor(); + return this->descriptor_; + } + + // Return the file last modification time. Calls gold_fatal if the stat + // system call failed. + Timespec + get_mtime(); + private: // This class may not be copied. File_read(const File_read&); File_read& operator=(const File_read&); - // Total bytes mapped into memory during the link. This variable - // may not be accurate when running multi-threaded. + // Total bytes mapped into memory during the link if --stats. static unsigned long long total_mapped_bytes; - // Current number of bytes mapped into memory during the link. This - // variable may not be accurate when running multi-threaded. + // Current number of bytes mapped into memory during the link if + // --stats. static unsigned long long current_mapped_bytes; - // High water mark of bytes mapped into memory during the link. - // This variable may not be accurate when running multi-threaded. + // High water mark of bytes mapped into memory during the link if + // --stats. static unsigned long long maximum_mapped_bytes; // A view into the file. class View { public: + // Specifies how to dispose the data on destruction of the view. + enum Data_ownership + { + // Data owned by File object - nothing done in destructor. + DATA_NOT_OWNED, + // Data alocated with new[] and owned by this object - should + // use delete[]. + DATA_ALLOCATED_ARRAY, + // Data mmapped and owned by this object - should munmap. + DATA_MMAPPED + }; + View(off_t start, section_size_type size, const unsigned char* data, - unsigned int byteshift, bool cache, bool mapped) + unsigned int byteshift, bool cache, Data_ownership data_ownership) : start_(start), size_(size), data_(data), lock_count_(0), - byteshift_(byteshift), cache_(cache), mapped_(mapped), accessed_(true) + byteshift_(byteshift), cache_(cache), data_ownership_(data_ownership), + accessed_(true) { } ~View(); @@ -281,7 +323,7 @@ class File_read bool cache_; // Whether the view is mapped into memory. If not, data_ points // to memory allocated using new[]. - bool mapped_; + Data_ownership data_ownership_; // Whether the view has been accessed recently. bool accessed_; }; @@ -340,7 +382,13 @@ class File_read { return (file_size + (page_size - 1)) & ~ (page_size - 1); } // The maximum number of entries we will pass to ::readv. +#ifdef HAVE_READV static const size_t max_readv_entries = 128; +#else + // On targets that don't have readv set the max to 1 so readv is not + // used. + static const size_t max_readv_entries = 1; +#endif // Use readv to read data. void @@ -364,14 +412,18 @@ class File_read // List of views which were locked but had to be removed from views_ // because they were not large enough. Saved_views saved_views_; - // Specified file contents. Used only for testing purposes. - const unsigned char* contents_; // Total amount of space mapped into memory. This is only changed // while the file is locked. When we unlock the file, we transfer // the total to total_mapped_bytes, and reset this to zero. size_t mapped_bytes_; // Whether the file was released. bool released_; + // A view containing the whole file. May be NULL if we mmap only + // the relevant parts of the file. Not NULL if: + // - Flag --mmap_whole_files is set (default on 64-bit hosts). + // - The contents was specified in the constructor. Used only for + // testing purposes). + View* whole_file_view_; }; // A view of file data that persists even when the file is unlocked. @@ -412,9 +464,16 @@ class File_view class Input_file { public: + enum Format + { + FORMAT_NONE, + FORMAT_ELF, + FORMAT_BINARY + }; + Input_file(const Input_file_argument* input_argument) : input_argument_(input_argument), found_name_(), file_(), - is_in_sysroot_(false) + is_in_sysroot_(false), format_(FORMAT_NONE) { } // Create an input file with the contents already provided. This is @@ -423,10 +482,23 @@ class Input_file Input_file(const Task*, const char* name, const unsigned char* contents, off_t size); + // Return the command line argument. + const Input_file_argument* + input_file_argument() const + { return this->input_argument_; } + + // Return whether this is a file that we will search for in the list + // of directories. + bool + will_search_for() const; + // Open the file. If the open fails, this will report an error and - // return false. + // return false. If there is a search, it starts at directory + // *PINDEX. *PINDEX should be initialized to zero. It may be + // restarted to find the next file with a matching name by + // incrementing the result and calling this again. bool - open(const General_options&, const Dirsearch&, const Task*); + open(const Dirsearch&, const Task*, int *pindex); // Return the name given by the user. For -lc this will return "c". const char* @@ -463,18 +535,26 @@ class Input_file is_in_sysroot() const { return this->is_in_sysroot_; } + // Whether this file is in a system directory. + bool + is_in_system_directory() const; + // Return whether this file is to be read only for its symbols. bool just_symbols() const; + // Return the format of the unconverted input file. + Format + format() const + { return this->format_; } + private: Input_file(const Input_file&); Input_file& operator=(const Input_file&); // Open a binary file. bool - open_binary(const General_options&, const Task* task, - const std::string& name); + open_binary(const Task* task, const std::string& name); // The argument from the command line. const Input_file_argument* input_argument_; @@ -487,6 +567,8 @@ class Input_file File_read file_; // Whether we found the file in a directory in the system root. bool is_in_sysroot_; + // Format of unconverted input file. + Format format_; }; } // end namespace gold diff --git a/binutils-2.19/gold/freebsd.h b/binutils-2.19/gold/freebsd.h new file mode 100644 index 0000000..de69735 --- /dev/null +++ b/binutils-2.19/gold/freebsd.h @@ -0,0 +1,168 @@ +// freebsd.h -- FreeBSD support for gold -*- C++ -*- + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "target.h" +#include "target-select.h" + +#ifndef GOLD_FREEBSD_H +#define GOLD_FREEBSD_H + +namespace gold +{ + +// FreeBSD 4.1 and later wants the EI_OSABI field in the ELF header to +// be set to ELFOSABI_FREEBSD. This is a subclass of Sized_target +// which supports that. The real target would be a subclass of this +// one. We permit combining FreeBSD and non-FreeBSD object files. +// The effect of this target is to set the code in the output file. + +template<int size, bool big_endian> +class Target_freebsd : public Sized_target<size, big_endian> +{ + public: + // Set the value to use for the EI_OSABI field in the ELF header. + void + set_osabi(elfcpp::ELFOSABI osabi) + { this->osabi_ = osabi; } + + protected: + Target_freebsd(const Target::Target_info* pti) + : Sized_target<size, big_endian>(pti), + osabi_(elfcpp::ELFOSABI_NONE) + { } + + virtual void + do_adjust_elf_header(unsigned char* view, int len) const; + + private: + // Value to store in the EI_OSABI field of the ELF file header. + elfcpp::ELFOSABI osabi_; +}; + +// Adjust the ELF file header by storing the requested value in the +// OSABI field. This is for FreeBSD support. + +template<int size, bool big_endian> +inline void +Target_freebsd<size, big_endian>::do_adjust_elf_header(unsigned char* view, + int len) const +{ + if (this->osabi_ != elfcpp::ELFOSABI_NONE) + { + gold_assert(len == elfcpp::Elf_sizes<size>::ehdr_size); + + elfcpp::Ehdr<size, false> ehdr(view); + unsigned char e_ident[elfcpp::EI_NIDENT]; + memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT); + + e_ident[elfcpp::EI_OSABI] = this->osabi_; + + elfcpp::Ehdr_write<size, false> oehdr(view); + oehdr.put_e_ident(e_ident); + } +} + +// A target selector for targets which permit combining both FreeBSD +// and non-FreeBSD object files. + +class Target_selector_freebsd : public Target_selector +{ + public: + Target_selector_freebsd(int machine, int size, bool is_big_endian, + const char* bfd_name, + const char* freebsd_bfd_name) + : Target_selector(machine, size, is_big_endian, NULL), + bfd_name_(bfd_name), freebsd_bfd_name_(freebsd_bfd_name) + { } + + protected: + // If we see a FreeBSD input file, mark the output file as using + // FreeBSD. + virtual Target* + do_recognize(int, int osabi, int) + { + Target* ret = this->instantiate_target(); + if (osabi == elfcpp::ELFOSABI_FREEBSD) + this->set_osabi(ret); + return ret; + } + + // Recognize two names. + virtual Target* + do_recognize_by_name(const char* name) + { + if (strcmp(name, this->bfd_name_) == 0) + return this->instantiate_target(); + else if (strcmp(name, this->freebsd_bfd_name_) == 0) + { + Target* ret = this->instantiate_target(); + this->set_osabi(ret); + return ret; + } + else + return NULL; + } + + // Print both names in --help output. + virtual void + do_supported_names(std::vector<const char*>* names) + { + names->push_back(this->bfd_name_); + names->push_back(this->freebsd_bfd_name_); + } + + private: + // Set the OSABI field. This is quite ugly. + void + set_osabi(Target* target) + { + if (this->get_size() == 32) + { + if (this->is_big_endian()) + static_cast<Target_freebsd<32, true>*>(target)-> + set_osabi(elfcpp::ELFOSABI_FREEBSD); + else + static_cast<Target_freebsd<32, false>*>(target)-> + set_osabi(elfcpp::ELFOSABI_FREEBSD); + } + else if (this->get_size() == 64) + { + if (this->is_big_endian()) + static_cast<Target_freebsd<64, true>*>(target)-> + set_osabi(elfcpp::ELFOSABI_FREEBSD); + else + static_cast<Target_freebsd<64, false>*>(target)-> + set_osabi(elfcpp::ELFOSABI_FREEBSD); + } + else + gold_unreachable(); + } + + // The BFD name for the non-Freebsd target. + const char* bfd_name_; + // The BFD name for the Freebsd target. + const char* freebsd_bfd_name_; +}; + +} // end namespace gold + +#endif // !defined(GOLD_FREEBSD_H) diff --git a/binutils-2.19/gold/ftruncate.c b/binutils-2.19/gold/ftruncate.c new file mode 100644 index 0000000..fc0bbc8 --- /dev/null +++ b/binutils-2.19/gold/ftruncate.c @@ -0,0 +1,92 @@ +/* ftruncate emulations that work on some System V's. + This file is in the public domain. */ + +#include <config.h> + +/* Specification. */ +#include <unistd.h> + +#include <sys/types.h> +#include <fcntl.h> + +extern int ftruncate (int, off_t); + +#ifdef F_CHSIZE + +int +ftruncate (int fd, off_t length) +{ + return fcntl (fd, F_CHSIZE, length); +} + +#else /* not F_CHSIZE */ +# ifdef F_FREESP + +/* By William Kucharski <kucharsk@netcom.com>. */ + +# include <sys/stat.h> +# include <errno.h> + +int +ftruncate (int fd, off_t length) +{ + struct flock fl; + struct stat filebuf; + + if (fstat (fd, &filebuf) < 0) + return -1; + + if (filebuf.st_size < length) + { + /* Extend file length. */ + if (lseek (fd, (length - 1), SEEK_SET) < 0) + return -1; + + /* Write a "0" byte. */ + if (write (fd, "", 1) != 1) + return -1; + } + else + { + + /* Truncate length. */ + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = length; + fl.l_type = F_WRLCK; /* write lock on file space */ + + /* This relies on the *undocumented* F_FREESP argument to fcntl, + which truncates the file so that it ends at the position + indicated by fl.l_start. Will minor miracles never cease? */ + + if (fcntl (fd, F_FREESP, &fl) < 0) + return -1; + } + + return 0; +} + +# else /* not F_CHSIZE nor F_FREESP */ +# if HAVE_CHSIZE /* native Windows, e.g. mingw */ + +int +ftruncate (int fd, off_t length) +{ + return chsize (fd, length); +} + +# else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */ + +# include <errno.h> + +int +ftruncate (int fd, off_t length) +{ + errno = EIO; + return -1; +} + +# endif /* not HAVE_CHSIZE */ +# endif /* not F_FREESP */ +#endif /* not F_CHSIZE */ diff --git a/binutils-2.19/gold/gc.cc b/binutils-2.19/gold/gc.cc new file mode 100644 index 0000000..7a594a5 --- /dev/null +++ b/binutils-2.19/gold/gc.cc @@ -0,0 +1,74 @@ +// gc.cc -- garbage collection of unused sections + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + + +#include "gold.h" +#include "object.h" +#include "gc.h" +#include "symtab.h" + +namespace gold +{ + +// Garbage collection uses a worklist style algorithm to determine the +// transitive closure of all referenced sections. +void +Garbage_collection::do_transitive_closure() +{ + while (!this->worklist().empty()) + { + // Add elements from the work list to the referenced list + // one by one. + Section_id entry = this->worklist().front(); + this->worklist().pop(); + if (this->referenced_list().find(entry) + == this->referenced_list().end()) + { + this->referenced_list().insert(entry); + } + else + { + continue; + } + Garbage_collection::Section_ref::iterator find_it = + this->section_reloc_map().find(entry); + if (find_it == this->section_reloc_map().end()) + continue; + Garbage_collection::Sections_reachable v = find_it->second; + // Scan the vector of references for each work_list entry. + for (Garbage_collection::Sections_reachable::iterator it_v = v.begin(); + it_v != v.end(); + ++it_v) + { + // Do not add already processed sections to the work_list. + if (this->referenced_list().find(*it_v) + == this->referenced_list().end()) + { + this->worklist().push(*it_v); + } + } + } + this->worklist_ready(); +} + +} // End namespace gold. + diff --git a/binutils-2.19/gold/gc.h b/binutils-2.19/gold/gc.h new file mode 100644 index 0000000..b79bd77 --- /dev/null +++ b/binutils-2.19/gold/gc.h @@ -0,0 +1,344 @@ +// gc.h -- garbage collection of unused sections + +// Copyright 2009, 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_GC_H +#define GOLD_GC_H + +#include <queue> +#include <vector> + +#include "elfcpp.h" +#include "symtab.h" +#include "object.h" +#include "icf.h" + +namespace gold +{ + +class Object; + +template<int size, bool big_endian> +class Sized_relobj; + +template<int sh_type, int size, bool big_endian> +class Reloc_types; + +class Output_section; +class General_options; +class Layout; + +class Garbage_collection +{ + public: + + typedef Unordered_set<Section_id, Section_id_hash> Sections_reachable; + typedef std::map<Section_id, Sections_reachable> Section_ref; + typedef std::queue<Section_id> Worklist_type; + // This maps the name of the section which can be represented as a C + // identifier (cident) to the list of sections that have that name. + // Different object files can have cident sections with the same name. + typedef std::map<std::string, Sections_reachable> Cident_section_map; + + Garbage_collection() + : is_worklist_ready_(false) + { } + + // Accessor methods for the private members. + + Sections_reachable& + referenced_list() + { return referenced_list_; } + + Section_ref& + section_reloc_map() + { return this->section_reloc_map_; } + + Worklist_type& + worklist() + { return this->work_list_; } + + bool + is_worklist_ready() + { return this->is_worklist_ready_; } + + void + worklist_ready() + { this->is_worklist_ready_ = true; } + + void + do_transitive_closure(); + + bool + is_section_garbage(Object* obj, unsigned int shndx) + { return (this->referenced_list().find(Section_id(obj, shndx)) + == this->referenced_list().end()); } + + Cident_section_map* + cident_sections() + { return &cident_sections_; } + + void + add_cident_section(std::string section_name, + Section_id secn) + { this->cident_sections_[section_name].insert(secn); } + + // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to + // DST_SHNDX-th section of DST_OBJECT. + void + add_reference(Object* src_object, unsigned int src_shndx, + Object* dst_object, unsigned int dst_shndx) + { + Section_id src_id(src_object, src_shndx); + Section_id dst_id(dst_object, dst_shndx); + Section_ref::iterator p = this->section_reloc_map_.find(src_id); + if (p == this->section_reloc_map_.end()) + this->section_reloc_map_[src_id].insert(dst_id); + else + p->second.insert(dst_id); + } + + private: + + Worklist_type work_list_; + bool is_worklist_ready_; + Section_ref section_reloc_map_; + Sections_reachable referenced_list_; + Cident_section_map cident_sections_; +}; + +// Data to pass between successive invocations of do_layout +// in object.cc while garbage collecting. This data structure +// is filled by using the data from Read_symbols_data. + +struct Symbols_data +{ + // Section headers. + unsigned char* section_headers_data; + // Section names. + unsigned char* section_names_data; + // Size of section name data in bytes. + section_size_type section_names_size; + // Symbol data. + unsigned char* symbols_data; + // Size of symbol data in bytes. + section_size_type symbols_size; + // Offset of external symbols within symbol data. This structure + // sometimes contains only external symbols, in which case this will + // be zero. Sometimes it contains all symbols. + section_offset_type external_symbols_offset; + // Symbol names. + unsigned char* symbol_names_data; + // Size of symbol name data in bytes. + section_size_type symbol_names_size; +}; + +// This function implements the generic part of reloc +// processing to map a section to all the sections it +// references through relocs. It is called only during +// garbage collection (--gc-sections) and identical code +// folding (--icf). + +template<int size, bool big_endian, typename Target_type, int sh_type, + typename Scan> +inline void +gc_process_relocs( + Symbol_table* symtab, + Layout*, + Target_type* target, + Sized_relobj<size, big_endian>* src_obj, + unsigned int src_indx, + const unsigned char* prelocs, + size_t reloc_count, + Output_section*, + bool, + size_t local_count, + const unsigned char* plocal_syms) +{ + Object *dst_obj; + unsigned int dst_indx; + Scan scan; + + typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; + const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + const int sym_size = elfcpp::Elf_sizes<size>::sym_size; + + Icf::Sections_reachable_info* secvec = NULL; + Icf::Symbol_info* symvec = NULL; + Icf::Addend_info* addendvec = NULL; + Icf::Offset_info* offsetvec = NULL; + bool is_icf_tracked = false; + const char* cident_section_name = NULL; + + std::string src_section_name = (parameters->options().icf_enabled() + ? src_obj->section_name(src_indx) + : ""); + + bool check_section_for_function_pointers = false; + + if (parameters->options().icf_enabled() + && is_section_foldable_candidate(src_section_name.c_str())) + { + is_icf_tracked = true; + Section_id src_id(src_obj, src_indx); + Icf::Reloc_info* reloc_info = + &symtab->icf()->reloc_info_list()[src_id]; + secvec = &reloc_info->section_info; + symvec = &reloc_info->symbol_info; + addendvec = &reloc_info->addend_info; + offsetvec = &reloc_info->offset_info; + } + + check_section_for_function_pointers = + symtab->icf()->check_section_for_function_pointers(src_section_name, + target); + + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) + { + Reltype reloc(prelocs); + typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); + unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + unsigned int r_type = elfcpp::elf_r_type<size>(r_info); + typename elfcpp::Elf_types<size>::Elf_Swxword addend = + Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc); + + if (r_sym < local_count) + { + gold_assert(plocal_syms != NULL); + typename elfcpp::Sym<size, big_endian> lsym(plocal_syms + + r_sym * sym_size); + unsigned int shndx = lsym.get_st_shndx(); + bool is_ordinary; + shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary); + if (!is_ordinary) + continue; + dst_obj = src_obj; + dst_indx = shndx; + Section_id dst_id(dst_obj, dst_indx); + if (is_icf_tracked) + { + (*secvec).push_back(dst_id); + (*symvec).push_back(NULL); + long long symvalue = static_cast<long long>(lsym.get_st_value()); + (*addendvec).push_back(std::make_pair(symvalue, + static_cast<long long>(addend))); + uint64_t reloc_offset = + convert_to_section_size_type(reloc.get_r_offset()); + (*offsetvec).push_back(reloc_offset); + } + + // When doing safe folding, check to see if this relocation is that + // of a function pointer being taken. + if (check_section_for_function_pointers + && lsym.get_st_type() != elfcpp::STT_OBJECT + && scan.local_reloc_may_be_function_pointer(symtab, NULL, NULL, + src_obj, src_indx, + NULL, reloc, r_type, + lsym)) + symtab->icf()->set_section_has_function_pointers( + src_obj, lsym.get_st_shndx()); + + if (shndx == src_indx) + continue; + } + else + { + Symbol* gsym = src_obj->global_symbol(r_sym); + gold_assert(gsym != NULL); + if (gsym->is_forwarder()) + gsym = symtab->resolve_forwards(gsym); + if (gsym->source() != Symbol::FROM_OBJECT) + continue; + bool is_ordinary; + dst_obj = gsym->object(); + dst_indx = gsym->shndx(&is_ordinary); + Section_id dst_id(dst_obj, dst_indx); + + // When doing safe folding, check to see if this relocation is that + // of a function pointer being taken. + if (check_section_for_function_pointers + && gsym->type() != elfcpp::STT_OBJECT + && (!is_ordinary + || scan.global_reloc_may_be_function_pointer( + symtab, NULL, NULL, src_obj, src_indx, NULL, reloc, + r_type, gsym))) + symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx); + + if (!is_ordinary) + continue; + + // If the symbol name matches '__start_XXX' then the section with + // the C identifier like name 'XXX' should not be garbage collected. + // A similar treatment to symbols with the name '__stop_XXX'. + if (is_prefix_of(cident_section_start_prefix, gsym->name())) + { + cident_section_name = (gsym->name() + + strlen(cident_section_start_prefix)); + } + else if (is_prefix_of(cident_section_stop_prefix, gsym->name())) + { + cident_section_name = (gsym->name() + + strlen(cident_section_stop_prefix)); + } + if (is_icf_tracked) + { + (*secvec).push_back(dst_id); + (*symvec).push_back(gsym); + Sized_symbol<size>* sized_gsym = + static_cast<Sized_symbol<size>* >(gsym); + long long symvalue = + static_cast<long long>(sized_gsym->value()); + (*addendvec).push_back(std::make_pair(symvalue, + static_cast<long long>(addend))); + uint64_t reloc_offset = + convert_to_section_size_type(reloc.get_r_offset()); + (*offsetvec).push_back(reloc_offset); + } + } + if (parameters->options().gc_sections()) + { + symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx); + if (cident_section_name != NULL) + { + Garbage_collection::Cident_section_map::iterator ele = + symtab->gc()->cident_sections()->find(std::string(cident_section_name)); + if (ele == symtab->gc()->cident_sections()->end()) + continue; + Section_id src_id(src_obj, src_indx); + Garbage_collection::Sections_reachable& + v(symtab->gc()->section_reloc_map()[src_id]); + Garbage_collection::Sections_reachable& cident_secn(ele->second); + for (Garbage_collection::Sections_reachable::iterator it_v + = cident_secn.begin(); + it_v != cident_secn.end(); + ++it_v) + { + v.insert(*it_v); + } + } + } + } + return; +} + +} // End of namespace gold. + +#endif diff --git a/binutils-2.19/gold/gold-threads.cc b/binutils-2.19/gold/gold-threads.cc index 9aa883d..f5347bf 100644 --- a/binutils-2.19/gold/gold-threads.cc +++ b/binutils-2.19/gold/gold-threads.cc @@ -1,6 +1,6 @@ // gold-threads.cc -- thread support for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -276,4 +276,172 @@ Condvar::~Condvar() delete this->condvar_; } +#ifdef ENABLE_THREADS + +// Class Once_initialize. This exists to hold a pthread_once_t +// structure for Once. + +class Once_initialize +{ + public: + Once_initialize() + : once_(PTHREAD_ONCE_INIT) + { } + + // Return a pointer to the pthread_once_t variable. + pthread_once_t* + once_control() + { return &this->once_; } + + private: + pthread_once_t once_; +}; + +#endif // defined(ENABLE_THREADS) + +#ifdef ENABLE_THREADS + +// A single lock which controls access to once_pointer. This is used +// because we can't pass parameters to functions passed to +// pthread_once. + +static pthread_mutex_t once_pointer_control = PTHREAD_MUTEX_INITIALIZER; + +// A pointer to Once structure we want to run. Access to this is +// controlled by once_pointer_control. + +static Once* once_pointer; + +// The argument to pass to the Once structure. Access to this is +// controlled by once_pointer_control. + +static void* once_arg; + +// A routine passed to pthread_once which runs the Once pointer. + +extern "C" +{ + +static void +c_run_once(void) +{ + once_pointer->internal_run(once_arg); +} + +} + +#endif // defined(ENABLE_THREADS) + +// Class Once. + +Once::Once() + : was_run_(false), was_run_lock_(0) +{ +#ifndef ENABLE_THREADS + this->once_ = NULL; +#else + this->once_ = new Once_initialize(); +#endif +} + +// Run the function once. + +void +Once::run_once(void* arg) +{ +#ifndef ENABLE_THREADS + + // If there is no threads support, we don't need to use pthread_once. + if (!this->was_run_) + this->internal_run(arg); + +#else // defined(ENABLE_THREADS) + + if (parameters->options_valid() && !parameters->options().threads()) + { + // If we are not using threads, we don't need to lock. + if (!this->was_run_) + this->internal_run(arg); + return; + } + + // If we have the sync builtins, use them to skip the lock if the + // value has already been initialized. +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + while (true) + { + if (__sync_bool_compare_and_swap(&this->was_run_lock_, 0, 1)) + break; + } + bool was_run = this->was_run_; + while (true) + { + if (__sync_bool_compare_and_swap(&this->was_run_lock_, 1, 0)) + break; + } + if (was_run) + return; +#endif + + // Since we can't pass parameters to routines called by + // pthread_once, we use a static variable: once_pointer. This in + // turns means that we need to use a mutex to control access to + // once_pointer. + + int err = pthread_mutex_lock(&once_pointer_control); + if (err != 0) + gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err)); + + once_pointer = this; + once_arg = arg; + + err = pthread_once(this->once_->once_control(), c_run_once); + if (err != 0) + gold_fatal(_("pthread_once failed: %s"), strerror(err)); + + once_pointer = NULL; + once_arg = NULL; + + err = pthread_mutex_unlock(&once_pointer_control); + if (err != 0) + gold_fatal(_("pthread_mutex_unlock falied: %s"), strerror(err)); + +#endif // defined(ENABLE_THREADS) +} + +// Actually run the function in the child class. This function will +// be run only once. + +void +Once::internal_run(void* arg) +{ + this->do_run_once(arg); + this->was_run_ = true; +} + +// Class Initialize_lock. + +// Initialize the lock. + +bool +Initialize_lock::initialize() +{ + // We can't initialize the lock until we have read the options. + if (!parameters->options_valid()) + return false; + else + { + this->run_once(NULL); + return true; + } +} + +// Initialize the lock exactly once. + +void +Initialize_lock::do_run_once(void*) +{ + *this->pplock_ = new Lock(); +} + } // End namespace gold. diff --git a/binutils-2.19/gold/gold-threads.h b/binutils-2.19/gold/gold-threads.h index c901e42..622bf32 100644 --- a/binutils-2.19/gold/gold-threads.h +++ b/binutils-2.19/gold/gold-threads.h @@ -1,6 +1,6 @@ // gold-threads.h -- thread support for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -35,6 +35,8 @@ namespace gold { class Condvar; +class Once_initialize; +class Initialize_lock_once; // The interface for the implementation of a Lock. @@ -190,6 +192,74 @@ class Condvar Condvar_impl* condvar_; }; +// A class used to do something once. This is an abstract parent +// class; any actual use will involve a child of this. + +class Once +{ + public: + Once(); + + virtual + ~Once() + { } + + // Call this function to do whatever it is. We pass an argument + // even though you have to use a child class because in some uses + // setting the argument would itself require a Once class. + void + run_once(void* arg); + + // This is an internal function, which must be public because it is + // run by an extern "C" function called via pthread_once. + void + internal_run(void* arg); + + protected: + // This must be implemented by the child class. + virtual void + do_run_once(void* arg) = 0; + + private: + // True if we have already run the function. + bool was_run_; + // Internal compare-and-swap lock on was_run_; + uint32_t was_run_lock_; + // The lock to run the function only once. + Once_initialize* once_; +}; + +// A class used to initialize a lock exactly once, after the options +// have been read. This is needed because the implementation of locks +// depends on whether we've seen the --threads option. Before the +// options have been read, we know we are single-threaded, so we can +// get by without using a lock. This class should be an instance +// variable of the class which has a lock which needs to be +// initialized. + +class Initialize_lock : public Once +{ + public: + // The class which uses this will have a pointer to a lock. This + // must be constructed with a pointer to that pointer. + Initialize_lock(Lock** pplock) + : pplock_(pplock) + { } + + // Initialize the lock. Return true if the lock is now initialized, + // false if it is not (because the options have not yet been read). + bool + initialize(); + + protected: + void + do_run_once(void*); + + private: + // A pointer to the lock pointer which must be initialized. + Lock** const pplock_; +}; + } // End namespace gold. #endif // !defined(GOLD_THREADS_H) diff --git a/binutils-2.19/gold/gold.cc b/binutils-2.19/gold/gold.cc index 42c6248..39c2ce7 100644 --- a/binutils-2.19/gold/gold.cc +++ b/binutils-2.19/gold/gold.cc @@ -1,6 +1,6 @@ // gold.cc -- main linker functions -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -40,6 +40,10 @@ #include "layout.h" #include "reloc.h" #include "defstd.h" +#include "plugin.h" +#include "gc.h" +#include "icf.h" +#include "incremental.h" namespace gold { @@ -49,6 +53,10 @@ const char* program_name; void gold_exit(bool status) { + if (parameters != NULL + && parameters->options_valid() + && parameters->options().has_plugins()) + parameters->options().plugins()->cleanup(); if (!status && parameters != NULL && parameters->options_valid()) unlink_if_ordinary(parameters->options().output_file_name()); exit(status ? EXIT_SUCCESS : EXIT_FAILURE); @@ -117,6 +125,38 @@ Middle_runner::run(Workqueue* workqueue, const Task* task) this->layout_, workqueue, this->mapfile_); } +// This class arranges the tasks to process the relocs for garbage collection. + +class Gc_runner : public Task_function_runner +{ + public: + Gc_runner(const General_options& options, + const Input_objects* input_objects, + Symbol_table* symtab, + Layout* layout, Mapfile* mapfile) + : options_(options), input_objects_(input_objects), symtab_(symtab), + layout_(layout), mapfile_(mapfile) + { } + + void + run(Workqueue*, const Task*); + + private: + const General_options& options_; + const Input_objects* input_objects_; + Symbol_table* symtab_; + Layout* layout_; + Mapfile* mapfile_; +}; + +void +Gc_runner::run(Workqueue* workqueue, const Task* task) +{ + queue_middle_gc_tasks(this->options_, task, this->input_objects_, + this->symtab_, this->layout_, workqueue, + this->mapfile_); +} + // Queue up the initial set of tasks for this link job. void @@ -127,13 +167,32 @@ queue_initial_tasks(const General_options& options, Symbol_table* symtab, Layout* layout, Mapfile* mapfile) { if (cmdline.begin() == cmdline.end()) - gold_fatal(_("no input files")); + { + if (options.printed_version()) + gold_exit(true); + gold_fatal(_("no input files")); + } int thread_count = options.thread_count_initial(); if (thread_count == 0) thread_count = cmdline.number_of_input_files(); workqueue->set_thread_count(thread_count); + if (cmdline.options().incremental()) + { + Incremental_checker incremental_checker( + parameters->options().output_file_name(), + layout->incremental_inputs()); + if (incremental_checker.can_incrementally_link_output_file()) + { + // TODO: remove when incremental linking implemented. + printf("Incremental linking might be possible " + "(not implemented yet)\n"); + } + // TODO: If we decide on an incremental build, fewer tasks + // should be scheduled. + } + // Read the input files. We have to add the symbols to the symbol // table in order. We do this by creating a separate blocker for // each input file. We associate the blocker with the following @@ -145,19 +204,85 @@ queue_initial_tasks(const General_options& options, { Task_token* next_blocker = new Task_token(true); next_blocker->add_blocker(); - workqueue->queue(new Read_symbols(options, input_objects, symtab, layout, - &search_path, mapfile, &*p, NULL, + workqueue->queue(new Read_symbols(input_objects, symtab, layout, + &search_path, 0, mapfile, &*p, NULL, this_blocker, next_blocker)); this_blocker = next_blocker; } - workqueue->queue(new Task_function(new Middle_runner(options, + if (options.has_plugins()) + { + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + workqueue->queue(new Plugin_hook(options, input_objects, symtab, layout, + &search_path, mapfile, this_blocker, + next_blocker)); + this_blocker = next_blocker; + } + + if (parameters->options().relocatable() + && (parameters->options().gc_sections() + || parameters->options().icf_enabled())) + gold_error(_("cannot mix -r with --gc-sections or --icf")); + + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + workqueue->queue(new Task_function(new Gc_runner(options, input_objects, - symtab, - layout, - mapfile), - this_blocker, - "Task_function Middle_runner")); + symtab, + layout, + mapfile), + this_blocker, + "Task_function Gc_runner")); + } + else + { + workqueue->queue(new Task_function(new Middle_runner(options, + input_objects, + symtab, + layout, + mapfile), + this_blocker, + "Task_function Middle_runner")); + } +} + +// Queue up a set of tasks to be done before queueing the middle set +// of tasks. This is only necessary when garbage collection +// (--gc-sections) of unused sections is desired. The relocs are read +// and processed here early to determine the garbage sections before the +// relocs can be scanned in later tasks. + +void +queue_middle_gc_tasks(const General_options& options, + const Task* , + const Input_objects* input_objects, + Symbol_table* symtab, + Layout* layout, + Workqueue* workqueue, + Mapfile* mapfile) +{ + // Read_relocs for all the objects must be done and processed to find + // unused sections before any scanning of the relocs can take place. + Task_token* this_blocker = NULL; + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker, + next_blocker)); + this_blocker = next_blocker; + } + workqueue->queue(new Task_function(new Middle_runner(options, + input_objects, + symtab, + layout, + mapfile), + this_blocker, + "Task_function Middle_runner")); } // Queue up the middle set of tasks. These are the tasks which run @@ -173,12 +298,95 @@ queue_middle_tasks(const General_options& options, Workqueue* workqueue, Mapfile* mapfile) { + // Add any symbols named with -u options to the symbol table. + symtab->add_undefined_symbols_from_command_line(); + + // If garbage collection was chosen, relocs have been read and processed + // at this point by pre_middle_tasks. Layout can then be done for all + // objects. + if (parameters->options().gc_sections()) + { + // Find the start symbol if any. + Symbol* start_sym; + if (parameters->options().entry()) + start_sym = symtab->lookup(parameters->options().entry()); + else + start_sym = symtab->lookup("_start"); + if (start_sym != NULL) + { + bool is_ordinary; + unsigned int shndx = start_sym->shndx(&is_ordinary); + if (is_ordinary) + { + symtab->gc()->worklist().push( + Section_id(start_sym->object(), shndx)); + } + } + // Symbols named with -u should not be considered garbage. + symtab->gc_mark_undef_symbols(); + gold_assert(symtab->gc() != NULL); + // Do a transitive closure on all references to determine the worklist. + symtab->gc()->do_transitive_closure(); + } + + // If identical code folding (--icf) is chosen it makes sense to do it + // only after garbage collection (--gc-sections) as we do not want to + // be folding sections that will be garbage. + if (parameters->options().icf_enabled()) + { + symtab->icf()->find_identical_sections(input_objects, symtab); + } + + // Call Object::layout for the second time to determine the + // output_sections for all referenced input sections. When + // --gc-sections or --icf is turned on, Object::layout is + // called twice. It is called the first time when the + // symbols are added. + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + (*p)->layout(symtab, layout, NULL); + } + } + + // Layout deferred objects due to plugins. + if (parameters->options().has_plugins()) + { + Plugin_manager* plugins = parameters->options().plugins(); + gold_assert(plugins != NULL); + plugins->layout_deferred_objects(); + } + + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + // Update the value of output_section stored in rd. + Read_relocs_data *rd = (*p)->get_relocs_data(); + for (Read_relocs_data::Relocs_list::iterator q = rd->relocs.begin(); + q != rd->relocs.end(); + ++q) + { + q->output_section = (*p)->output_section(q->data_shndx); + q->needs_special_offset_handling = + (*p)->is_output_section_offset_invalid(q->data_shndx); + } + } + } + // We have to support the case of not seeing any input objects, and // generate an empty file. Existing builds depend on being able to // pass an empty archive to the linker and get an empty object file // out. In order to do this we need to use a default target. if (input_objects->number_of_input_objects() == 0) - set_parameters_target(¶meters->default_target()); + parameters_force_valid_target(); int thread_count = options.thread_count_middle(); if (thread_count == 0) @@ -186,23 +394,42 @@ queue_middle_tasks(const General_options& options, workqueue->set_thread_count(thread_count); // Now we have seen all the input files. - const bool doing_static_link = (!input_objects->any_dynamic() - && !parameters->options().shared()); + const bool doing_static_link = + (!input_objects->any_dynamic() + && !parameters->options().output_is_position_independent()); set_parameters_doing_static_link(doing_static_link); if (!doing_static_link && options.is_static()) { // We print out just the first .so we see; there may be others. + gold_assert(input_objects->dynobj_begin() != input_objects->dynobj_end()); gold_error(_("cannot mix -static with dynamic object %s"), (*input_objects->dynobj_begin())->name().c_str()); } if (!doing_static_link && parameters->options().relocatable()) - gold_error(_("cannot mix -r with dynamic object %s"), + gold_fatal(_("cannot mix -r with dynamic object %s"), (*input_objects->dynobj_begin())->name().c_str()); if (!doing_static_link && options.oformat_enum() != General_options::OBJECT_FORMAT_ELF) gold_fatal(_("cannot use non-ELF output format with dynamic object %s"), (*input_objects->dynobj_begin())->name().c_str()); + if (parameters->options().relocatable()) + { + Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + if (p != input_objects->relobj_end()) + { + bool uses_split_stack = (*p)->uses_split_stack(); + for (++p; p != input_objects->relobj_end(); ++p) + { + if ((*p)->uses_split_stack() != uses_split_stack) + gold_fatal(_("cannot mix split-stack '%s' and " + "non-split-stack '%s' when using -r"), + (*input_objects->relobj_begin())->name().c_str(), + (*p)->name().c_str()); + } + } + } + if (is_debugging_enabled(DEBUG_SCRIPT)) layout->script_options()->print(stderr); @@ -214,6 +441,16 @@ queue_middle_tasks(const General_options& options, // TODO: if this is too slow, do this as a task, rather than inline. symtab->detect_odr_violations(task, options.output_file_name()); + // Do the --no-undefined-version check. + if (!parameters->options().undefined_version()) + { + Script_options* so = layout->script_options(); + so->version_script_info()->check_unmatched_names(symtab); + } + + // Create any automatic note sections. + layout->create_notes(); + // Create any output sections required by any linker script. layout->create_script_sections(); @@ -224,9 +461,6 @@ queue_middle_tasks(const General_options& options, // Define symbols from any linker scripts. layout->define_script_symbols(symtab); - // Add any symbols named with -u options to the symbol table. - symtab->add_undefined_symbols_from_command_line(); - // Attach sections to segments. layout->attach_sections_to_segments(); @@ -243,40 +477,78 @@ queue_middle_tasks(const General_options& options, // Make sure we have symbols for any required group signatures. layout->define_group_signatures(symtab); - // Read the relocations of the input files. We do this to find - // which symbols are used by relocations which require a GOT and/or - // a PLT entry, or a COPY reloc. When we implement garbage - // collection we will do it here by reading the relocations in a - // breadth first search by references. - // - // We could also read the relocations during the first pass, and - // mark symbols at that time. That is how the old GNU linker works. - // Doing that is more complex, since we may later decide to discard - // some of the sections, and thus change our minds about the types - // of references made to the symbols. - Task_token* blocker = new Task_token(true); - Task_token* symtab_lock = new Task_token(false); - for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); - p != input_objects->relobj_end(); - ++p) - { - // We can read and process the relocations in any order. But we - // only want one task to write to the symbol table at a time. - // So we queue up a task for each object to read the - // relocations. That task will in turn queue a task to wait - // until it can write to the symbol table. - blocker->add_blocker(); - workqueue->queue(new Read_relocs(options, symtab, layout, *p, - symtab_lock, blocker)); - } + Task_token* this_blocker = NULL; - // Allocate common symbols. This requires write access to the - // symbol table, but is independent of the relocation processing. + // Allocate common symbols. We use a blocker to run this before the + // Scan_relocs tasks, because it writes to the symbol table just as + // they do. if (parameters->options().define_common()) { - blocker->add_blocker(); + this_blocker = new Task_token(true); + this_blocker->add_blocker(); workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile, - symtab_lock, blocker)); + this_blocker)); + } + + // If doing garbage collection, the relocations have already been read. + // Otherwise, read and scan the relocations. + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + workqueue->queue(new Scan_relocs(symtab, layout, *p, + (*p)->get_relocs_data(), + this_blocker, next_blocker)); + this_blocker = next_blocker; + } + } + else + { + // Read the relocations of the input files. We do this to find + // which symbols are used by relocations which require a GOT and/or + // a PLT entry, or a COPY reloc. When we implement garbage + // collection we will do it here by reading the relocations in a + // breadth first search by references. + // + // We could also read the relocations during the first pass, and + // mark symbols at that time. That is how the old GNU linker works. + // Doing that is more complex, since we may later decide to discard + // some of the sections, and thus change our minds about the types + // of references made to the symbols. + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker, + next_blocker)); + this_blocker = next_blocker; + } + } + + if (this_blocker == NULL) + { + if (input_objects->number_of_relobjs() == 0) + { + // If we are given only archives in input, we have no regular + // objects and THIS_BLOCKER is NULL here. Create a dummy + // blocker here so that we can run the layout task immediately. + this_blocker = new Task_token(true); + } + else + { + // If we failed to open any input files, it's possible for + // THIS_BLOCKER to be NULL here. There's no real point in + // continuing if that happens. + gold_assert(parameters->errors()->error_count() > 0); + gold_exit(false); + } } // When all those tasks are complete, we can start laying out the @@ -289,7 +561,7 @@ queue_middle_tasks(const General_options& options, target, layout, mapfile), - blocker, + this_blocker, "Task_function Layout_task_runner")); } @@ -315,17 +587,26 @@ queue_final_tasks(const General_options& options, // written out. Task_token* input_sections_blocker = NULL; if (!any_postprocessing_sections) - input_sections_blocker = new Task_token(true); + { + input_sections_blocker = new Task_token(true); + input_sections_blocker->add_blockers(input_objects->number_of_relobjs()); + } // Use a blocker to block any objects which have to wait for the // output sections to complete before they can apply relocations. Task_token* output_sections_blocker = new Task_token(true); + output_sections_blocker->add_blocker(); // Use a blocker to block the final cleanup task. Task_token* final_blocker = new Task_token(true); + // Write_symbols_task, Write_sections_task, Write_data_task, + // Relocate_tasks. + final_blocker->add_blockers(3); + final_blocker->add_blockers(input_objects->number_of_relobjs()); + if (!any_postprocessing_sections) + final_blocker->add_blocker(); // Queue a task to write out the symbol table. - final_blocker->add_blocker(); workqueue->queue(new Write_symbols_task(layout, symtab, input_objects, @@ -335,13 +616,10 @@ queue_final_tasks(const General_options& options, final_blocker)); // Queue a task to write out the output sections. - output_sections_blocker->add_blocker(); - final_blocker->add_blocker(); workqueue->queue(new Write_sections_task(layout, of, output_sections_blocker, final_blocker)); // Queue a task to write out everything else. - final_blocker->add_blocker(); workqueue->queue(new Write_data_task(layout, symtab, of, final_blocker)); // Queue a task for each input object to relocate the sections and @@ -349,15 +627,10 @@ queue_final_tasks(const General_options& options, for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); p != input_objects->relobj_end(); ++p) - { - if (input_sections_blocker != NULL) - input_sections_blocker->add_blocker(); - final_blocker->add_blocker(); - workqueue->queue(new Relocate_task(options, symtab, layout, *p, of, - input_sections_blocker, - output_sections_blocker, - final_blocker)); - } + workqueue->queue(new Relocate_task(symtab, layout, *p, of, + input_sections_blocker, + output_sections_blocker, + final_blocker)); // Queue a task to write out the output sections which depend on // input sections. If there are any sections which require @@ -365,7 +638,6 @@ queue_final_tasks(const General_options& options, // the output file. if (!any_postprocessing_sections) { - final_blocker->add_blocker(); Task* t = new Write_after_input_sections_task(layout, of, input_sections_blocker, final_blocker); diff --git a/binutils-2.19/gold/gold.h b/binutils-2.19/gold/gold.h index 63df994..5c98de0 100644 --- a/binutils-2.19/gold/gold.h +++ b/binutils-2.19/gold/gold.h @@ -1,6 +1,6 @@ // gold.h -- general definitions for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -27,6 +27,8 @@ #include "ansidecl.h" #include <cstddef> +#include <cstring> +#include <stdint.h> #include <sys/types.h> #ifndef ENABLE_NLS @@ -63,7 +65,8 @@ // Figure out how to get a hash set and a hash map. -#if defined(HAVE_TR1_UNORDERED_SET) && defined(HAVE_TR1_UNORDERED_MAP) +#if defined(HAVE_TR1_UNORDERED_SET) && defined(HAVE_TR1_UNORDERED_MAP) \ + && defined(HAVE_TR1_UNORDERED_MAP_REHASH) #include <tr1/unordered_set> #include <tr1/unordered_map> @@ -72,6 +75,9 @@ #define Unordered_set std::tr1::unordered_set #define Unordered_map std::tr1::unordered_map +#define Unordered_multimap std::tr1::unordered_multimap + +#define reserve_unordered_map(map, n) ((map)->rehash(n)) #elif defined(HAVE_EXT_HASH_MAP) && defined(HAVE_EXT_HASH_SET) @@ -81,6 +87,7 @@ #define Unordered_set __gnu_cxx::hash_set #define Unordered_map __gnu_cxx::hash_map +#define Unordered_multimap __gnu_cxx::hash_multimap namespace __gnu_cxx { @@ -103,6 +110,8 @@ struct hash<T*> } +#define reserve_unordered_map(map, n) ((map)->resize(n)) + #else // The fallback is to just use set and map. @@ -112,6 +121,9 @@ struct hash<T*> #define Unordered_set std::set #define Unordered_map std::map +#define Unordered_map std::multimap + +#define reserve_unordered_map(map, n) #endif @@ -119,6 +131,27 @@ struct hash<T*> extern "C" ssize_t pread(int, void*, size_t, off_t); #endif +#ifndef HAVE_FTRUNCATE +extern "C" int ftruncate(int, off_t); +#endif + +#ifndef HAVE_MREMAP +#define MREMAP_MAYMOVE 1 +extern "C" void *mremap(void *, size_t, size_t, int, ...); +#endif + +#ifndef HAVE_FFSLL +extern "C" int ffsll(long long); +#endif + +#if !HAVE_DECL_MEMMEM +extern "C" void *memmem(const void *, size_t, const void *, size_t); +#endif + +#if !HAVE_DECL_STRNDUP +extern "C" char *strndup(const char *, size_t); +#endif + namespace gold { @@ -126,7 +159,6 @@ namespace gold class General_options; class Command_line; -class Input_argument_list; class Dirsearch; class Input_objects; class Mapfile; @@ -200,22 +232,43 @@ gold_warning_at_location(const Relocate_info<size, big_endian>*, size_t, off_t, const char* format, ...) TEMPLATE_ATTRIBUTE_PRINTF_4; -// This function is called to report an undefined symbol. +// This function is called to report an undefined symbol without +// a relocation (e.g., referenced by a dynamic object). SYM is +// the undefined symbol. The file name associated with the SYM +// is used to print a location for the undefined symbol. +extern void +gold_undefined_symbol(const Symbol*); + +// This function is called to report an undefined symbol resulting +// from a relocation. SYM is the undefined symbol. RELINFO is the +// general relocation info. RELNUM is the number of the reloc, +// and RELOFFSET is the reloc's offset. template<int size, bool big_endian> extern void -gold_undefined_symbol(const Symbol*, - const Relocate_info<size, big_endian>*, - size_t, off_t); +gold_undefined_symbol_at_location(const Symbol*, + const Relocate_info<size, big_endian>*, + size_t, off_t); // This is function is called in some cases if we run out of memory. extern void gold_nomem() ATTRIBUTE_NORETURN; +// In versions of gcc before 4.3, using __FUNCTION__ in a template +// function can cause gcc to get confused about whether or not the +// function can return. See http://gcc.gnu.org/PR30988. Use a macro +// to avoid the problem. This can be removed when we no longer need +// to care about gcc versions before 4.3. +#if defined(__GNUC__) && GCC_VERSION < 4003 +#define FUNCTION_NAME static_cast<const char*>(__FUNCTION__) +#else +#define FUNCTION_NAME __FUNCTION__ +#endif + // This macro and function are used in cases which can not arise if // the code is written correctly. #define gold_unreachable() \ - (gold::do_gold_unreachable(__FILE__, __LINE__, __FUNCTION__)) + (gold::do_gold_unreachable(__FILE__, __LINE__, FUNCTION_NAME)) extern void do_gold_unreachable(const char*, int, const char*) ATTRIBUTE_NORETURN; @@ -259,6 +312,18 @@ queue_initial_tasks(const General_options&, Layout*, Mapfile*); +// Queue up the set of tasks to be done before +// the middle set of tasks. Only used when garbage +// collection is to be done. +extern void +queue_middle_gc_tasks(const General_options&, + const Task*, + const Input_objects*, + Symbol_table*, + Layout*, + Workqueue*, + Mapfile*); + // Queue up the middle set of tasks. extern void queue_middle_tasks(const General_options&, @@ -278,6 +343,64 @@ queue_final_tasks(const General_options&, Workqueue*, Output_file* of); +inline bool +is_prefix_of(const char* prefix, const char* str) +{ + return strncmp(prefix, str, strlen(prefix)) == 0; +} + +const char* const cident_section_start_prefix = "__start_"; +const char* const cident_section_stop_prefix = "__stop_"; + +// Returns true if the name is a valid C identifier +inline bool +is_cident(const char* name) +{ + return (name[strspn(name, + ("0123456789" + "ABCDEFGHIJKLMNOPWRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "_"))] + == '\0'); +} + +// We sometimes need to hash strings. Ideally we should use std::tr1::hash or +// __gnu_cxx::hash on some systems but there is no guarantee that either +// one is available. For portability, we define simple string hash functions. + +template<typename Char_type> +inline size_t +string_hash(const Char_type* s, size_t length) +{ + // This is the hash function used by the dynamic linker for + // DT_GNU_HASH entries. I compared this to a Fowler/Noll/Vo hash + // for a C++ program with 385,775 global symbols. This hash + // function was very slightly worse. However, it is much faster to + // compute. Overall wall clock time was a win. + const unsigned char* p = reinterpret_cast<const unsigned char*>(s); + size_t h = 5381; + for (size_t i = 0; i < length * sizeof(Char_type); ++i) + h = h * 33 + *p++; + return h; +} + +// Same as above except we expect the string to be zero terminated. + +template<typename Char_type> +inline size_t +string_hash(const Char_type* s) +{ + const unsigned char* p = reinterpret_cast<const unsigned char*>(s); + size_t h = 5381; + for (size_t i = 0; s[i] != 0; ++i) + { + for (size_t j = 0; j < sizeof(Char_type); j++) + h = h * 33 + *p++; + } + + return h; +} + } // End namespace gold. #endif // !defined(GOLD_GOLD_H) diff --git a/binutils-2.19/gold/i386.cc b/binutils-2.19/gold/i386.cc index 54f1233..eb4ef0a 100644 --- a/binutils-2.19/gold/i386.cc +++ b/binutils-2.19/gold/i386.cc @@ -1,6 +1,6 @@ // i386.cc -- i386 target support for gold. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -37,6 +37,8 @@ #include "target-reloc.h" #include "target-select.h" #include "tls.h" +#include "freebsd.h" +#include "gc.h" namespace { @@ -50,22 +52,36 @@ class Output_data_plt_i386; // http://people.redhat.com/drepper/tls.pdf // http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt -class Target_i386 : public Sized_target<32, false> +class Target_i386 : public Target_freebsd<32, false> { public: typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section; Target_i386() - : Sized_target<32, false>(&i386_info), - got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL), - copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL), + : Target_freebsd<32, false>(&i386_info), + got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL), + rel_dyn_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL), got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) { } + // Process the relocations to determine unreferenced sections for + // garbage collection. + void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Scan the relocations to look for symbol adjustments. void - scan_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<32, false>* object, unsigned int data_shndx, @@ -79,7 +95,7 @@ class Target_i386 : public Sized_target<32, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); // Return the value to use for a dynamic which requires special // treatment. @@ -96,12 +112,12 @@ class Target_i386 : public Sized_target<32, false> bool needs_special_offset_handling, unsigned char* view, elfcpp::Elf_types<32>::Elf_Addr view_address, - section_size_type view_size); + section_size_type view_size, + const Reloc_symbol_changes*); // Scan the relocs during a relocatable link. void - scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<32, false>* object, unsigned int data_shndx, @@ -135,9 +151,29 @@ class Target_i386 : public Sized_target<32, false> // Return whether SYM is defined by the ABI. bool - do_is_defined_by_abi(Symbol* sym) const + do_is_defined_by_abi(const Symbol* sym) const { return strcmp(sym->name(), "___tls_get_addr") == 0; } + // Return whether a symbol name implies a local label. The UnixWare + // 2.1 cc generates temporary symbols that start with .X, so we + // recognize them here. FIXME: do other SVR4 compilers also use .X?. + // If so, we should move the .X recognition into + // Target::do_is_local_label_name. + bool + do_is_local_label_name(const char* name) const + { + if (name[0] == '.' && name[1] == 'X') + return true; + return Target::do_is_local_label_name(name); + } + + // Adjust -fstack-split code which calls non-stack-split code. + void + do_calls_non_split(Relobj* object, unsigned int shndx, + section_offset_type fnoffset, section_size_type fnsize, + unsigned char* view, section_size_type view_size, + std::string* from, std::string* to) const; + // Return the size of the GOT section. section_size_type got_size() @@ -151,8 +187,7 @@ class Target_i386 : public Sized_target<32, false> struct Scan { inline void - local(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_i386* target, + local(Symbol_table* symtab, Layout* layout, Target_i386* target, Sized_relobj<32, false>* object, unsigned int data_shndx, Output_section* output_section, @@ -160,14 +195,33 @@ class Target_i386 : public Sized_target<32, false> const elfcpp::Sym<32, false>& lsym); inline void - global(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_i386* target, + global(Symbol_table* symtab, Layout* layout, Target_i386* target, Sized_relobj<32, false>* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rel<32, false>& reloc, unsigned int r_type, Symbol* gsym); + inline bool + local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_i386* , + Sized_relobj<32, false>* , + unsigned int , + Output_section* , + const elfcpp::Rel<32, false>& , + unsigned int , + const elfcpp::Sym<32, false>&) + { return false; } + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_i386* , + Sized_relobj<32, false>* , + unsigned int , + Output_section* , + const elfcpp::Rel<32, false>& , + unsigned int , Symbol*) + { return false; } + static void unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type); @@ -198,13 +252,14 @@ class Target_i386 : public Sized_target<32, false> inline bool should_apply_static_reloc(const Sized_symbol<32>* gsym, int ref_flags, - bool is_32bit); + bool is_32bit, + Output_section* output_section); // Do a relocation. Return false if the caller should not issue // any warnings about this relocation. inline bool - relocate(const Relocate_info<32, false>*, Target_i386*, size_t relnum, - const elfcpp::Rel<32, false>&, + relocate(const Relocate_info<32, false>*, Target_i386*, Output_section*, + size_t relnum, const elfcpp::Rel<32, false>&, unsigned int r_type, const Sized_symbol<32>*, const Symbol_value<32>*, unsigned char*, elfcpp::Elf_types<32>::Elf_Addr, @@ -323,7 +378,7 @@ class Target_i386 : public Sized_target<32, false> void make_plt_entry(Symbol_table*, Layout*, Symbol*); - // Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + // Define the _TLS_MODULE_BASE_ symbol in the TLS segment. void define_tls_base_symbol(Symbol_table*, Layout*); @@ -333,7 +388,7 @@ class Target_i386 : public Sized_target<32, false> Sized_relobj<32, false>* object); // Get the PLT section. - const Output_data_plt_i386* + Output_data_plt_i386* plt_section() const { gold_assert(this->plt_ != NULL); @@ -344,16 +399,9 @@ class Target_i386 : public Sized_target<32, false> Reloc_section* rel_dyn_section(Layout*); - // Return true if the symbol may need a COPY relocation. - // References from an executable object to non-function symbols - // defined in a dynamic object may need a COPY relocation. - bool - may_need_copy_reloc(Symbol* gsym) - { - return (!parameters->options().shared() - && gsym->is_from_dynobj() - && gsym->type() != elfcpp::STT_FUNC); - } + // Get the section to use for TLS_DESC relocations. + Reloc_section* + rel_tls_desc_section(Layout*) const; // Add a potential copy relocation. void @@ -388,6 +436,8 @@ class Target_i386 : public Sized_target<32, false> Output_data_plt_i386* plt_; // The GOT PLT section. Output_data_space* got_plt_; + // The _GLOBAL_OFFSET_TABLE_ symbol. + Symbol* global_offset_table_; // The dynamic reloc section. Reloc_section* rel_dyn_; // Relocs saved to avoid a COPY reloc. @@ -413,7 +463,13 @@ const Target::Target_info Target_i386::i386_info = "/usr/lib/libc.so.1", // dynamic_linker 0x08048000, // default_text_segment_address 0x1000, // abi_pagesize (overridable by -z max-page-size) - 0x1000 // common_pagesize (overridable by -z common-page-size) + 0x1000, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; // Get the GOT section, creating it if necessary. @@ -431,30 +487,31 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_); - os->set_is_relro(); + this->got_, false, true, true, + false); - // The old GNU linker creates a .got.plt section. We just - // create another set of data in the .got section. Note that we - // always create a PLT if we create a GOT, although the PLT - // might be empty. this->got_plt_ = new Output_data_space(4, "** GOT PLT"); - os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + os = layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_plt_); - os->set_is_relro(); + this->got_plt_, false, false, false, + true); // The first three entries are reserved. this->got_plt_->set_current_data_size(3 * 4); + // Those bytes can go into the relro segment. + layout->increase_relro(3 * 4); + // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. - symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, - this->got_plt_, - 0, 0, elfcpp::STT_OBJECT, - elfcpp::STB_LOCAL, - elfcpp::STV_HIDDEN, 0, - false, false); + this->global_offset_table_ = + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, + this->got_plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); } return this->got_; @@ -470,7 +527,8 @@ Target_i386::rel_dyn_section(Layout* layout) gold_assert(layout != NULL); this->rel_dyn_ = new Reloc_section(parameters->options().combreloc()); layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL, - elfcpp::SHF_ALLOC, this->rel_dyn_); + elfcpp::SHF_ALLOC, this->rel_dyn_, true, + false, false, false); } return this->rel_dyn_; } @@ -493,6 +551,10 @@ class Output_data_plt_i386 : public Output_section_data rel_plt() const { return this->rel_; } + // Return where the TLS_DESC relocations should go. + Reloc_section* + rel_tls_desc(Layout*); + protected: void do_adjust_output_section(Output_section* os); @@ -529,6 +591,9 @@ class Output_data_plt_i386 : public Output_section_data // The reloc section. Reloc_section* rel_; + // The TLS_DESC relocations, if necessary. These must follow the + // regular PLT relocs. + Reloc_section* tls_desc_rel_; // The .got.plt section. Output_data_space* got_plt_; // The number of PLT entries. @@ -541,11 +606,12 @@ class Output_data_plt_i386 : public Output_section_data Output_data_plt_i386::Output_data_plt_i386(Layout* layout, Output_data_space* got_plt) - : Output_section_data(4), got_plt_(got_plt), count_(0) + : Output_section_data(4), tls_desc_rel_(NULL), got_plt_(got_plt), count_(0) { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, - elfcpp::SHF_ALLOC, this->rel_); + elfcpp::SHF_ALLOC, this->rel_, true, + false, false, false); } void @@ -586,6 +652,24 @@ Output_data_plt_i386::add_entry(Symbol* gsym) // appear in the relocations. } +// Return where the TLS_DESC relocations should go, creating it if +// necessary. These follow the JUMP_SLOT relocations. + +Output_data_plt_i386::Reloc_section* +Output_data_plt_i386::rel_tls_desc(Layout* layout) +{ + if (this->tls_desc_rel_ == NULL) + { + this->tls_desc_rel_ = new Reloc_section(false); + layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, + elfcpp::SHF_ALLOC, this->tls_desc_rel_, + true, false, false, false); + gold_assert(this->tls_desc_rel_->output_section() == + this->rel_->output_section()); + } + return this->tls_desc_rel_; +} + // The first entry in the PLT for an executable. unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] = @@ -653,7 +737,7 @@ Output_data_plt_i386::do_write(Output_file* of) elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address(); elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address(); - if (parameters->options().shared()) + if (parameters->options().output_is_position_independent()) memcpy(pov, dyn_first_plt_entry, plt_entry_size); else { @@ -685,7 +769,7 @@ Output_data_plt_i386::do_write(Output_file* of) { // Set and adjust the PLT entry itself. - if (parameters->options().shared()) + if (parameters->options().output_is_position_independent()) { memcpy(pov, dyn_plt_entry, plt_entry_size); elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset); @@ -730,13 +814,21 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym) layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), - this->plt_); + this->plt_, false, false, false, false); } this->plt_->add_entry(gsym); } -// Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. +// Get the section to use for TLS_DESC relocations. + +Target_i386::Reloc_section* +Target_i386::rel_tls_desc_section(Layout* layout) const +{ + return this->plt_section()->rel_tls_desc(layout); +} + +// Define the _TLS_MODULE_BASE_ symbol in the TLS segment. void Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) @@ -747,12 +839,17 @@ Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) Output_segment* tls_segment = layout->tls_segment(); if (tls_segment != NULL) { + bool is_exec = parameters->options().output_is_executable(); symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL, + Symbol_table::PREDEFINED, tls_segment, 0, 0, elfcpp::STT_TLS, elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN, 0, - Symbol::SEGMENT_END, true); + (is_exec + ? Symbol::SEGMENT_END + : Symbol::SEGMENT_START), + true); } this->tls_base_symbol_defined_ = true; } @@ -847,8 +944,7 @@ Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object, // Scan a relocation for a local symbol. inline void -Target_i386::Scan::local(const General_options&, - Symbol_table* symtab, +Target_i386::Scan::local(Symbol_table* symtab, Layout* layout, Target_i386* target, Sized_relobj<32, false>* object, @@ -1016,17 +1112,20 @@ Target_i386::Scan::local(const General_options&, Output_data_got<32, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info()); - unsigned int shndx = lsym.get_st_shndx(); - bool is_ordinary; - shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); - if (!is_ordinary) - object->error(_("local symbol %u has bad shndx %u"), - r_sym, shndx); - else - got->add_local_pair_with_rel(object, r_sym, shndx, - GOT_TYPE_TLS_DESC, - target->rel_dyn_section(layout), - elfcpp::R_386_TLS_DESC, 0); + if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC)) + { + unsigned int got_offset = got->add_constant(0); + // The local symbol value is stored in the second + // GOT entry. + got->add_local(object, r_sym, GOT_TYPE_TLS_DESC); + // That set the GOT offset of the local symbol to + // point to the second entry, but we want it to + // point to the first. + object->set_local_got_offset(r_sym, GOT_TYPE_TLS_DESC, + got_offset); + Reloc_section* rt = target->rel_tls_desc_section(layout); + rt->add_absolute(elfcpp::R_386_TLS_DESC, got, got_offset); + } } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -1138,8 +1237,7 @@ Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object, // Scan a relocation for a global symbol. inline void -Target_i386::Scan::global(const General_options&, - Symbol_table* symtab, +Target_i386::Scan::global(Symbol_table* symtab, Layout* layout, Target_i386* target, Sized_relobj<32, false>* object, @@ -1174,7 +1272,7 @@ Target_i386::Scan::global(const General_options&, // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -1216,11 +1314,11 @@ Target_i386::Scan::global(const General_options&, } // Make a dynamic relocation if necessary. int flags = Symbol::NON_PIC_REF; - if (gsym->type() == elfcpp::STT_FUNC) + if (gsym->is_func()) flags |= Symbol::FUNCTION_CALL; if (gsym->needs_dynamic_reloc(flags)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -1348,8 +1446,8 @@ Target_i386::Scan::global(const General_options&, // Create a double GOT entry with an R_386_TLS_DESC reloc. Output_data_got<32, false>* got = target->got_section(symtab, layout); - got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, - target->rel_dyn_section(layout), + Reloc_section* rt = target->rel_tls_desc_section(layout); + got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt, elfcpp::R_386_TLS_DESC, 0); } else if (optimized_type == tls::TLSOPT_TO_IE) @@ -1452,11 +1550,40 @@ Target_i386::Scan::global(const General_options&, } } +// Process relocations for gc. + +void +Target_i386::gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<32, false>* object, + unsigned int data_shndx, + unsigned int, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL, + Target_i386::Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + // Scan relocations for a section. void -Target_i386::scan_relocs(const General_options& options, - Symbol_table* symtab, +Target_i386::scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<32, false>* object, unsigned int data_shndx, @@ -1477,7 +1604,6 @@ Target_i386::scan_relocs(const General_options& options, gold::scan_relocs<32, false, Target_i386, elfcpp::SHT_REL, Target_i386::Scan>( - options, symtab, layout, this, @@ -1494,44 +1620,30 @@ Target_i386::scan_relocs(const General_options& options, // Finalize the sections. void -Target_i386::do_finalize_sections(Layout* layout) +Target_i386::do_finalize_sections( + Layout* layout, + const Input_objects*, + Symbol_table* symtab) { - // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->got_plt_ != NULL) - odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); - - if (this->plt_ != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); - } - - if (this->rel_dyn_ != NULL) - { - const Output_data* od = this->rel_dyn_; - odyn->add_section_address(elfcpp::DT_REL, od); - odyn->add_section_size(elfcpp::DT_RELSZ, od); - odyn->add_constant(elfcpp::DT_RELENT, - elfcpp::Elf_sizes<32>::rel_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, + this->rel_dyn_, true, false); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. if (this->copy_relocs_.any_saved_relocs()) this->copy_relocs_.emit(this->rel_dyn_section(layout)); + + // Set the size of the _GLOBAL_OFFSET_TABLE_ symbol to the size of + // the .got.plt section. + Symbol* sym = this->global_offset_table_; + if (sym != NULL) + { + uint32_t data_size = this->got_plt_->current_data_size(); + symtab->get_sized_symbol<32>(sym)->set_symsize(data_size); + } } // Return whether a direct absolute static relocation needs to be applied. @@ -1543,8 +1655,15 @@ Target_i386::do_finalize_sections(Layout* layout) inline bool Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym, int ref_flags, - bool is_32bit) + bool is_32bit, + Output_section* output_section) { + // If the output section is not allocated, then we didn't call + // scan_relocs, we didn't create a dynamic reloc, and we must apply + // the reloc here. + if ((output_section->flags() & elfcpp::SHF_ALLOC) == 0) + return true; + // For local symbols, we will have created a non-RELATIVE dynamic // relocation only if (a) the output is position independent, // (b) the relocation is absolute (not pc- or segment-relative), and @@ -1570,6 +1689,7 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym, inline bool Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, Target_i386* target, + Output_section *output_section, size_t relnum, const elfcpp::Rel<32, false>& rel, unsigned int r_type, @@ -1581,7 +1701,8 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, { if (this->skip_call_tls_get_addr_) { - if (r_type != elfcpp::R_386_PLT32 + if ((r_type != elfcpp::R_386_PLT32 + && r_type != elfcpp::R_386_PC32) || gsym == NULL || strcmp(gsym->name(), "___tls_get_addr") != 0) gold_error_at_location(relinfo, relnum, rel.get_r_offset(), @@ -1644,46 +1765,50 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, break; case elfcpp::R_386_32: - if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true)) + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true, + output_section)) Relocate_functions<32, false>::rel32(view, object, psymval); break; case elfcpp::R_386_PC32: { int ref_flags = Symbol::NON_PIC_REF; - if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + if (gsym != NULL && gsym->is_func()) ref_flags |= Symbol::FUNCTION_CALL; - if (should_apply_static_reloc(gsym, ref_flags, true)) + if (should_apply_static_reloc(gsym, ref_flags, true, output_section)) Relocate_functions<32, false>::pcrel32(view, object, psymval, address); } break; case elfcpp::R_386_16: - if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false)) + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) Relocate_functions<32, false>::rel16(view, object, psymval); break; case elfcpp::R_386_PC16: { int ref_flags = Symbol::NON_PIC_REF; - if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + if (gsym != NULL && gsym->is_func()) ref_flags |= Symbol::FUNCTION_CALL; - if (should_apply_static_reloc(gsym, ref_flags, false)) + if (should_apply_static_reloc(gsym, ref_flags, false, output_section)) Relocate_functions<32, false>::pcrel16(view, object, psymval, address); } break; case elfcpp::R_386_8: - if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false)) + if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false, + output_section)) Relocate_functions<32, false>::rel8(view, object, psymval); break; case elfcpp::R_386_PC8: { int ref_flags = Symbol::NON_PIC_REF; - if (gsym != NULL && gsym->type() == elfcpp::STT_FUNC) + if (gsym != NULL && gsym->is_func()) ref_flags |= Symbol::FUNCTION_CALL; - if (should_apply_static_reloc(gsym, ref_flags, false)) + if (should_apply_static_reloc(gsym, ref_flags, false, + output_section)) Relocate_functions<32, false>::pcrel8(view, object, psymval, address); } break; @@ -1792,10 +1917,9 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0); - const bool is_final = - (gsym == NULL - ? !parameters->options().output_is_position_independent() - : gsym->final_value_is_known()); + const bool is_final = (gsym == NULL + ? !parameters->options().shared() + : gsym->final_value_is_known()); const tls::Tls_optimization optimized_type = Target_i386::optimize_tls_reloc(is_final, r_type); switch (r_type) @@ -1931,14 +2055,19 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo, break; case elfcpp::R_386_TLS_LDO_32: // Alternate local-dynamic - // This reloc can appear in debugging sections, in which case we - // won't see the TLS_LDM reloc. The local_dynamic_type field - // tells us this. - if (optimized_type == tls::TLSOPT_TO_LE - && this->local_dynamic_type_ != LOCAL_DYNAMIC_NONE) + if (optimized_type == tls::TLSOPT_TO_LE) { - gold_assert(tls_segment != NULL); - value -= tls_segment->memsz(); + // This reloc can appear in debugging sections, in which + // case we must not convert to local-exec. We decide what + // to do based on whether the section is marked as + // containing executable code. That is what the GNU linker + // does as well. + elfcpp::Shdr<32, false> shdr(relinfo->data_shdr); + if ((shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0) + { + gold_assert(tls_segment != NULL); + value -= tls_segment->memsz(); + } } Relocate_functions<32, false>::rel32(view, value); break; @@ -2357,7 +2486,8 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo, bool needs_special_offset_handling, unsigned char* view, elfcpp::Elf_types<32>::Elf_Addr address, - section_size_type view_size) + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) { gold_assert(sh_type == elfcpp::SHT_REL); @@ -2371,7 +2501,8 @@ Target_i386::relocate_section(const Relocate_info<32, false>* relinfo, needs_special_offset_handling, view, address, - view_size); + view_size, + reloc_symbol_changes); } // Return the size of a relocation while scanning during a relocatable @@ -2448,8 +2579,7 @@ Target_i386::Relocatable_size_for_reloc::get_size_for_reloc( // Scan the relocs during a relocatable link. void -Target_i386::scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, +Target_i386::scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<32, false>* object, unsigned int data_shndx, @@ -2469,7 +2599,6 @@ Target_i386::scan_relocatable_relocs(const General_options& options, gold::scan_relocatable_relocs<32, false, elfcpp::SHT_REL, Scan_relocatable_relocs>( - options, symtab, layout, object, @@ -2591,13 +2720,73 @@ Target_i386::do_code_fill(section_size_type length) const return std::string(nops[length], length); } +// FNOFFSET in section SHNDX in OBJECT is the start of a function +// compiled with -fstack-split. The function calls non-stack-split +// code. We have to change the function so that it always ensures +// that it has enough stack space to run some random function. + +void +Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx, + section_offset_type fnoffset, + section_size_type fnsize, + unsigned char* view, + section_size_type view_size, + std::string* from, + std::string* to) const +{ + // The function starts with a comparison of the stack pointer and a + // field in the TCB. This is followed by a jump. + + // cmp %gs:NN,%esp + if (this->match_view(view, view_size, fnoffset, "\x65\x3b\x25", 3) + && fnsize > 7) + { + // We will call __morestack if the carry flag is set after this + // comparison. We turn the comparison into an stc instruction + // and some nops. + view[fnoffset] = '\xf9'; + this->set_view_to_nop(view, view_size, fnoffset + 1, 6); + } + // lea NN(%esp),%ecx + // lea NN(%esp),%edx + else if ((this->match_view(view, view_size, fnoffset, "\x8d\x8c\x24", 3) + || this->match_view(view, view_size, fnoffset, "\x8d\x94\x24", 3)) + && fnsize > 7) + { + // This is loading an offset from the stack pointer for a + // comparison. The offset is negative, so we decrease the + // offset by the amount of space we need for the stack. This + // means we will avoid calling __morestack if there happens to + // be plenty of space on the stack already. + unsigned char* pval = view + fnoffset + 3; + uint32_t val = elfcpp::Swap_unaligned<32, false>::readval(pval); + val -= parameters->options().split_stack_adjust_size(); + elfcpp::Swap_unaligned<32, false>::writeval(pval, val); + } + else + { + if (!object->has_no_split_stack()) + object->error(_("failed to match split-stack sequence at " + "section %u offset %0zx"), + shndx, static_cast<size_t>(fnoffset)); + return; + } + + // We have to change the function so that it calls + // __morestack_non_split instead of __morestack. The former will + // allocate additional stack space. + *from = "__morestack"; + *to = "__morestack_non_split"; +} + // The selector for i386 object files. -class Target_selector_i386 : public Target_selector +class Target_selector_i386 : public Target_selector_freebsd { public: Target_selector_i386() - : Target_selector(elfcpp::EM_386, 32, false, "elf32-i386") + : Target_selector_freebsd(elfcpp::EM_386, 32, false, + "elf32-i386", "elf32-i386-freebsd") { } Target* diff --git a/binutils-2.19/gold/icf.cc b/binutils-2.19/gold/icf.cc new file mode 100644 index 0000000..ff2058c --- /dev/null +++ b/binutils-2.19/gold/icf.cc @@ -0,0 +1,739 @@ +// icf.cc -- Identical Code Folding. +// +// Copyright 2009, 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// Identical Code Folding Algorithm +// ---------------------------------- +// Detecting identical functions is done here and the basic algorithm +// is as follows. A checksum is computed on each foldable section using +// its contents and relocations. If the symbol name corresponding to +// a relocation is known it is used to compute the checksum. If the +// symbol name is not known the stringified name of the object and the +// section number pointed to by the relocation is used. The checksums +// are stored as keys in a hash map and a section is identical to some +// other section if its checksum is already present in the hash map. +// Checksum collisions are handled by using a multimap and explicitly +// checking the contents when two sections have the same checksum. +// +// However, two functions A and B with identical text but with +// relocations pointing to different foldable sections can be identical if +// the corresponding foldable sections to which their relocations point to +// turn out to be identical. Hence, this checksumming process must be +// done repeatedly until convergence is obtained. Here is an example for +// the following case : +// +// int funcA () int funcB () +// { { +// return foo(); return goo(); +// } } +// +// The functions funcA and funcB are identical if functions foo() and +// goo() are identical. +// +// Hence, as described above, we repeatedly do the checksumming, +// assigning identical functions to the same group, until convergence is +// obtained. Now, we have two different ways to do this depending on how +// we initialize. +// +// Algorithm I : +// ----------- +// We can start with marking all functions as different and repeatedly do +// the checksumming. This has the advantage that we do not need to wait +// for convergence. We can stop at any point and correctness will be +// guaranteed although not all cases would have been found. However, this +// has a problem that some cases can never be found even if it is run until +// convergence. Here is an example with mutually recursive functions : +// +// int funcA (int a) int funcB (int a) +// { { +// if (a == 1) if (a == 1) +// return 1; return 1; +// return 1 + funcB(a - 1); return 1 + funcA(a - 1); +// } } +// +// In this example funcA and funcB are identical and one of them could be +// folded into the other. However, if we start with assuming that funcA +// and funcB are not identical, the algorithm, even after it is run to +// convergence, cannot detect that they are identical. It should be noted +// that even if the functions were self-recursive, Algorithm I cannot catch +// that they are identical, at least as is. +// +// Algorithm II : +// ------------ +// Here we start with marking all functions as identical and then repeat +// the checksumming until convergence. This can detect the above case +// mentioned above. It can detect all cases that Algorithm I can and more. +// However, the caveat is that it has to be run to convergence. It cannot +// be stopped arbitrarily like Algorithm I as correctness cannot be +// guaranteed. Algorithm II is not implemented. +// +// Algorithm I is used because experiments show that about three +// iterations are more than enough to achieve convergence. Algorithm I can +// handle recursive calls if it is changed to use a special common symbol +// for recursive relocs. This seems to be the most common case that +// Algorithm I could not catch as is. Mutually recursive calls are not +// frequent and Algorithm I wins because of its ability to be stopped +// arbitrarily. +// +// Caveat with using function pointers : +// ------------------------------------ +// +// Programs using function pointer comparisons/checks should use function +// folding with caution as the result of such comparisons could be different +// when folding takes place. This could lead to unexpected run-time +// behaviour. +// +// Safe Folding : +// ------------ +// +// ICF in safe mode folds only ctors and dtors if their function pointers can +// never be taken. Also, for X86-64, safe folding uses the relocation +// type to determine if a function's pointer is taken or not and only folds +// functions whose pointers are definitely not taken. +// +// Caveat with safe folding : +// ------------------------ +// +// This applies only to x86_64. +// +// Position independent executables are created from PIC objects (compiled +// with -fPIC) and/or PIE objects (compiled with -fPIE). For PIE objects, the +// relocation types for function pointer taken and a call are the same. +// Now, it is not always possible to tell if an object used in the link of +// a pie executable is a PIC object or a PIE object. Hence, for pie +// executables, using relocation types to disambiguate function pointers is +// currently disabled. +// +// Further, it is not correct to use safe folding to build non-pie +// executables using PIC/PIE objects. PIC/PIE objects have different +// relocation types for function pointers than non-PIC objects, and the +// current implementation of safe folding does not handle those relocation +// types. Hence, if used, functions whose pointers are taken could still be +// folded causing unpredictable run-time behaviour if the pointers were used +// in comparisons. +// +// +// +// How to run : --icf=[safe|all|none] +// Optional parameters : --icf-iterations <num> --print-icf-sections +// +// Performance : Less than 20 % link-time overhead on industry strength +// applications. Up to 6 % text size reductions. + +#include "gold.h" +#include "object.h" +#include "gc.h" +#include "icf.h" +#include "symtab.h" +#include "libiberty.h" +#include "demangle.h" + +namespace gold +{ + +// This function determines if a section or a group of identical +// sections has unique contents. Such unique sections or groups can be +// declared final and need not be processed any further. +// Parameters : +// ID_SECTION : Vector mapping a section index to a Section_id pair. +// IS_SECN_OR_GROUP_UNIQUE : To check if a section or a group of identical +// sections is already known to be unique. +// SECTION_CONTENTS : Contains the section's text and relocs to sections +// that cannot be folded. SECTION_CONTENTS are NULL +// implies that this function is being called for the +// first time before the first iteration of icf. + +static void +preprocess_for_unique_sections(const std::vector<Section_id>& id_section, + std::vector<bool>* is_secn_or_group_unique, + std::vector<std::string>* section_contents) +{ + Unordered_map<uint32_t, unsigned int> uniq_map; + std::pair<Unordered_map<uint32_t, unsigned int>::iterator, bool> + uniq_map_insert; + + for (unsigned int i = 0; i < id_section.size(); i++) + { + if ((*is_secn_or_group_unique)[i]) + continue; + + uint32_t cksum; + Section_id secn = id_section[i]; + section_size_type plen; + if (section_contents == NULL) + { + const unsigned char* contents; + contents = secn.first->section_contents(secn.second, + &plen, + false); + cksum = xcrc32(contents, plen, 0xffffffff); + } + else + { + const unsigned char* contents_array = reinterpret_cast + <const unsigned char*>((*section_contents)[i].c_str()); + cksum = xcrc32(contents_array, (*section_contents)[i].length(), + 0xffffffff); + } + uniq_map_insert = uniq_map.insert(std::make_pair(cksum, i)); + if (uniq_map_insert.second) + { + (*is_secn_or_group_unique)[i] = true; + } + else + { + (*is_secn_or_group_unique)[i] = false; + (*is_secn_or_group_unique)[uniq_map_insert.first->second] = false; + } + } +} + +// This returns the buffer containing the section's contents, both +// text and relocs. Relocs are differentiated as those pointing to +// sections that could be folded and those that cannot. Only relocs +// pointing to sections that could be folded are recomputed on +// subsequent invocations of this function. +// Parameters : +// FIRST_ITERATION : true if it is the first invocation. +// SECN : Section for which contents are desired. +// SECTION_NUM : Unique section number of this section. +// NUM_TRACKED_RELOCS : Vector reference to store the number of relocs +// to ICF sections. +// KEPT_SECTION_ID : Vector which maps folded sections to kept sections. +// SECTION_CONTENTS : Store the section's text and relocs to non-ICF +// sections. + +static std::string +get_section_contents(bool first_iteration, + const Section_id& secn, + unsigned int section_num, + unsigned int* num_tracked_relocs, + Symbol_table* symtab, + const std::vector<unsigned int>& kept_section_id, + std::vector<std::string>* section_contents) +{ + section_size_type plen; + const unsigned char* contents = NULL; + + if (first_iteration) + { + contents = secn.first->section_contents(secn.second, + &plen, + false); + } + + // The buffer to hold all the contents including relocs. A checksum + // is then computed on this buffer. + std::string buffer; + std::string icf_reloc_buffer; + + if (num_tracked_relocs) + *num_tracked_relocs = 0; + + Icf::Reloc_info_list& reloc_info_list = + symtab->icf()->reloc_info_list(); + + Icf::Reloc_info_list::iterator it_reloc_info_list = + reloc_info_list.find(secn); + + buffer.clear(); + icf_reloc_buffer.clear(); + + // Process relocs and put them into the buffer. + + if (it_reloc_info_list != reloc_info_list.end()) + { + Icf::Sections_reachable_info v = + (it_reloc_info_list->second).section_info; + Icf::Symbol_info s = (it_reloc_info_list->second).symbol_info; + Icf::Addend_info a = (it_reloc_info_list->second).addend_info; + Icf::Offset_info o = (it_reloc_info_list->second).offset_info; + Icf::Sections_reachable_info::iterator it_v = v.begin(); + Icf::Symbol_info::iterator it_s = s.begin(); + Icf::Addend_info::iterator it_a = a.begin(); + Icf::Offset_info::iterator it_o = o.begin(); + + for (; it_v != v.end(); ++it_v, ++it_s, ++it_a, ++it_o) + { + // ADDEND_STR stores the symbol value and addend and offset, + // each atmost 16 hex digits long. it_a points to a pair + // where first is the symbol value and second is the + // addend. + char addend_str[50]; + + // It would be nice if we could use format macros in inttypes.h + // here but there are not in ISO/IEC C++ 1998. + snprintf(addend_str, sizeof(addend_str), "%llx %llx %llux", + static_cast<long long>((*it_a).first), + static_cast<long long>((*it_a).second), + static_cast<unsigned long long>(*it_o)); + Section_id reloc_secn(it_v->first, it_v->second); + + // If this reloc turns back and points to the same section, + // like a recursive call, use a special symbol to mark this. + if (reloc_secn.first == secn.first + && reloc_secn.second == secn.second) + { + if (first_iteration) + { + buffer.append("R"); + buffer.append(addend_str); + buffer.append("@"); + } + continue; + } + Icf::Uniq_secn_id_map& section_id_map = + symtab->icf()->section_to_int_map(); + Icf::Uniq_secn_id_map::iterator section_id_map_it = + section_id_map.find(reloc_secn); + if (section_id_map_it != section_id_map.end()) + { + // This is a reloc to a section that might be folded. + if (num_tracked_relocs) + (*num_tracked_relocs)++; + + char kept_section_str[10]; + unsigned int secn_id = section_id_map_it->second; + snprintf(kept_section_str, sizeof(kept_section_str), "%u", + kept_section_id[secn_id]); + if (first_iteration) + { + buffer.append("ICF_R"); + buffer.append(addend_str); + } + icf_reloc_buffer.append(kept_section_str); + // Append the addend. + icf_reloc_buffer.append(addend_str); + icf_reloc_buffer.append("@"); + } + else + { + // This is a reloc to a section that cannot be folded. + // Process it only in the first iteration. + if (!first_iteration) + continue; + + uint64_t secn_flags = (it_v->first)->section_flags(it_v->second); + // This reloc points to a merge section. Hash the + // contents of this section. + if ((secn_flags & elfcpp::SHF_MERGE) != 0) + { + uint64_t entsize = + (it_v->first)->section_entsize(it_v->second); + long long offset = it_a->first + it_a->second; + section_size_type secn_len; + const unsigned char* str_contents = + (it_v->first)->section_contents(it_v->second, + &secn_len, + false) + offset; + if ((secn_flags & elfcpp::SHF_STRINGS) != 0) + { + // String merge section. + const char* str_char = + reinterpret_cast<const char*>(str_contents); + switch(entsize) + { + case 1: + { + buffer.append(str_char); + break; + } + case 2: + { + const uint16_t* ptr_16 = + reinterpret_cast<const uint16_t*>(str_char); + unsigned int strlen_16 = 0; + // Find the NULL character. + while(*(ptr_16 + strlen_16) != 0) + strlen_16++; + buffer.append(str_char, strlen_16 * 2); + } + break; + case 4: + { + const uint32_t* ptr_32 = + reinterpret_cast<const uint32_t*>(str_char); + unsigned int strlen_32 = 0; + // Find the NULL character. + while(*(ptr_32 + strlen_32) != 0) + strlen_32++; + buffer.append(str_char, strlen_32 * 4); + } + break; + default: + gold_unreachable(); + } + } + else + { + // Use the entsize to determine the length. + buffer.append(reinterpret_cast<const + char*>(str_contents), + entsize); + } + } + else if ((*it_s) != NULL) + { + // If symbol name is available use that. + const char *sym_name = (*it_s)->name(); + buffer.append(sym_name); + // Append the addend. + buffer.append(addend_str); + buffer.append("@"); + } + else + { + // Symbol name is not available, like for a local symbol, + // use object and section id. + buffer.append(it_v->first->name()); + char secn_id[10]; + snprintf(secn_id, sizeof(secn_id), "%u",it_v->second); + buffer.append(secn_id); + // Append the addend. + buffer.append(addend_str); + buffer.append("@"); + } + } + } + } + + if (first_iteration) + { + buffer.append("Contents = "); + buffer.append(reinterpret_cast<const char*>(contents), plen); + // Store the section contents that dont change to avoid recomputing + // during the next call to this function. + (*section_contents)[section_num] = buffer; + } + else + { + gold_assert(buffer.empty()); + // Reuse the contents computed in the previous iteration. + buffer.append((*section_contents)[section_num]); + } + + buffer.append(icf_reloc_buffer); + return buffer; +} + +// This function computes a checksum on each section to detect and form +// groups of identical sections. The first iteration does this for all +// sections. +// Further iterations do this only for the kept sections from each group to +// determine if larger groups of identical sections could be formed. The +// first section in each group is the kept section for that group. +// +// CRC32 is the checksumming algorithm and can have collisions. That is, +// two sections with different contents can have the same checksum. Hence, +// a multimap is used to maintain more than one group of checksum +// identical sections. A section is added to a group only after its +// contents are explicitly compared with the kept section of the group. +// +// Parameters : +// ITERATION_NUM : Invocation instance of this function. +// NUM_TRACKED_RELOCS : Vector reference to store the number of relocs +// to ICF sections. +// KEPT_SECTION_ID : Vector which maps folded sections to kept sections. +// ID_SECTION : Vector mapping a section to an unique integer. +// IS_SECN_OR_GROUP_UNIQUE : To check if a section or a group of identical +// sectionsis already known to be unique. +// SECTION_CONTENTS : Store the section's text and relocs to non-ICF +// sections. + +static bool +match_sections(unsigned int iteration_num, + Symbol_table* symtab, + std::vector<unsigned int>* num_tracked_relocs, + std::vector<unsigned int>* kept_section_id, + const std::vector<Section_id>& id_section, + std::vector<bool>* is_secn_or_group_unique, + std::vector<std::string>* section_contents) +{ + Unordered_multimap<uint32_t, unsigned int> section_cksum; + std::pair<Unordered_multimap<uint32_t, unsigned int>::iterator, + Unordered_multimap<uint32_t, unsigned int>::iterator> key_range; + bool converged = true; + + if (iteration_num == 1) + preprocess_for_unique_sections(id_section, + is_secn_or_group_unique, + NULL); + else + preprocess_for_unique_sections(id_section, + is_secn_or_group_unique, + section_contents); + + std::vector<std::string> full_section_contents; + + for (unsigned int i = 0; i < id_section.size(); i++) + { + full_section_contents.push_back(""); + if ((*is_secn_or_group_unique)[i]) + continue; + + Section_id secn = id_section[i]; + std::string this_secn_contents; + uint32_t cksum; + if (iteration_num == 1) + { + unsigned int num_relocs = 0; + this_secn_contents = get_section_contents(true, secn, i, &num_relocs, + symtab, (*kept_section_id), + section_contents); + (*num_tracked_relocs)[i] = num_relocs; + } + else + { + if ((*kept_section_id)[i] != i) + { + // This section is already folded into something. See + // if it should point to a different kept section. + unsigned int kept_section = (*kept_section_id)[i]; + if (kept_section != (*kept_section_id)[kept_section]) + { + (*kept_section_id)[i] = (*kept_section_id)[kept_section]; + } + continue; + } + this_secn_contents = get_section_contents(false, secn, i, NULL, + symtab, (*kept_section_id), + section_contents); + } + + const unsigned char* this_secn_contents_array = + reinterpret_cast<const unsigned char*>(this_secn_contents.c_str()); + cksum = xcrc32(this_secn_contents_array, this_secn_contents.length(), + 0xffffffff); + size_t count = section_cksum.count(cksum); + + if (count == 0) + { + // Start a group with this cksum. + section_cksum.insert(std::make_pair(cksum, i)); + full_section_contents[i] = this_secn_contents; + } + else + { + key_range = section_cksum.equal_range(cksum); + Unordered_multimap<uint32_t, unsigned int>::iterator it; + // Search all the groups with this cksum for a match. + for (it = key_range.first; it != key_range.second; ++it) + { + unsigned int kept_section = it->second; + if (full_section_contents[kept_section].length() + != this_secn_contents.length()) + continue; + if (memcmp(full_section_contents[kept_section].c_str(), + this_secn_contents.c_str(), + this_secn_contents.length()) != 0) + continue; + (*kept_section_id)[i] = kept_section; + converged = false; + break; + } + if (it == key_range.second) + { + // Create a new group for this cksum. + section_cksum.insert(std::make_pair(cksum, i)); + full_section_contents[i] = this_secn_contents; + } + } + // If there are no relocs to foldable sections do not process + // this section any further. + if (iteration_num == 1 && (*num_tracked_relocs)[i] == 0) + (*is_secn_or_group_unique)[i] = true; + } + + return converged; +} + +// During safe icf (--icf=safe), only fold functions that are ctors or dtors. +// This function returns true if the mangled function name is a ctor or a +// dtor. + +static bool +is_function_ctor_or_dtor(const char* mangled_func_name) +{ + if ((is_prefix_of("_ZN", mangled_func_name) + || is_prefix_of("_ZZ", mangled_func_name)) + && (is_gnu_v3_mangled_ctor(mangled_func_name) + || is_gnu_v3_mangled_dtor(mangled_func_name))) + { + return true; + } + return false; +} + +// This is the main ICF function called in gold.cc. This does the +// initialization and calls match_sections repeatedly (twice by default) +// which computes the crc checksums and detects identical functions. + +void +Icf::find_identical_sections(const Input_objects* input_objects, + Symbol_table* symtab) +{ + unsigned int section_num = 0; + std::vector<unsigned int> num_tracked_relocs; + std::vector<bool> is_secn_or_group_unique; + std::vector<std::string> section_contents; + const Target& target = parameters->target(); + + // Decide which sections are possible candidates first. + + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + for (unsigned int i = 0;i < (*p)->shnum(); ++i) + { + const char* section_name = (*p)->section_name(i).c_str(); + if (!is_section_foldable_candidate(section_name)) + continue; + if (!(*p)->is_section_included(i)) + continue; + if (parameters->options().gc_sections() + && symtab->gc()->is_section_garbage(*p, i)) + continue; + const char* mangled_func_name = strrchr(section_name, '.'); + gold_assert(mangled_func_name != NULL); + // With --icf=safe, check if the mangled function name is a ctor + // or a dtor. The mangled function name can be obtained from the + // section name by stripping the section prefix. + if (parameters->options().icf_safe_folding() + && !is_function_ctor_or_dtor(mangled_func_name + 1) + && (!target.can_check_for_function_pointers() + || section_has_function_pointers(*p, i))) + { + continue; + } + this->id_section_.push_back(Section_id(*p, i)); + this->section_id_[Section_id(*p, i)] = section_num; + this->kept_section_id_.push_back(section_num); + num_tracked_relocs.push_back(0); + is_secn_or_group_unique.push_back(false); + section_contents.push_back(""); + section_num++; + } + } + + unsigned int num_iterations = 0; + + // Default number of iterations to run ICF is 2. + unsigned int max_iterations = (parameters->options().icf_iterations() > 0) + ? parameters->options().icf_iterations() + : 2; + + bool converged = false; + + while (!converged && (num_iterations < max_iterations)) + { + num_iterations++; + converged = match_sections(num_iterations, symtab, + &num_tracked_relocs, &this->kept_section_id_, + this->id_section_, &is_secn_or_group_unique, + §ion_contents); + } + + if (parameters->options().print_icf_sections()) + { + if (converged) + gold_info(_("%s: ICF Converged after %u iteration(s)"), + program_name, num_iterations); + else + gold_info(_("%s: ICF stopped after %u iteration(s)"), + program_name, num_iterations); + } + + // Unfold --keep-unique symbols. + for (options::String_set::const_iterator p = + parameters->options().keep_unique_begin(); + p != parameters->options().keep_unique_end(); + ++p) + { + const char* name = p->c_str(); + Symbol* sym = symtab->lookup(name); + if (sym == NULL) + { + gold_warning(_("Could not find symbol %s to unfold\n"), name); + } + else if (sym->source() == Symbol::FROM_OBJECT + && !sym->object()->is_dynamic()) + { + Object* obj = sym->object(); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary) + { + this->unfold_section(obj, shndx); + } + } + + } + + this->icf_ready(); +} + +// Unfolds the section denoted by OBJ and SHNDX if folded. + +void +Icf::unfold_section(Object* obj, unsigned int shndx) +{ + Section_id secn(obj, shndx); + Uniq_secn_id_map::iterator it = this->section_id_.find(secn); + if (it == this->section_id_.end()) + return; + unsigned int section_num = it->second; + unsigned int kept_section_id = this->kept_section_id_[section_num]; + if (kept_section_id != section_num) + this->kept_section_id_[section_num] = section_num; +} + +// This function determines if the section corresponding to the +// given object and index is folded based on if the kept section +// is different from this section. + +bool +Icf::is_section_folded(Object* obj, unsigned int shndx) +{ + Section_id secn(obj, shndx); + Uniq_secn_id_map::iterator it = this->section_id_.find(secn); + if (it == this->section_id_.end()) + return false; + unsigned int section_num = it->second; + unsigned int kept_section_id = this->kept_section_id_[section_num]; + return kept_section_id != section_num; +} + +// This function returns the folded section for the given section. + +Section_id +Icf::get_folded_section(Object* dup_obj, unsigned int dup_shndx) +{ + Section_id dup_secn(dup_obj, dup_shndx); + Uniq_secn_id_map::iterator it = this->section_id_.find(dup_secn); + gold_assert(it != this->section_id_.end()); + unsigned int section_num = it->second; + unsigned int kept_section_id = this->kept_section_id_[section_num]; + Section_id folded_section = this->id_section_[kept_section_id]; + return folded_section; +} + +} // End of namespace gold. diff --git a/binutils-2.19/gold/icf.h b/binutils-2.19/gold/icf.h new file mode 100644 index 0000000..c1db8e5 --- /dev/null +++ b/binutils-2.19/gold/icf.h @@ -0,0 +1,177 @@ +// icf.h -- Identical Code Folding + +// Copyright 2009, 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_ICF_H +#define GOLD_ICF_H + +#include <vector> + +#include "elfcpp.h" +#include "symtab.h" +#include "object.h" + +namespace gold +{ + +class Object; +class Input_objects; +class Symbol_table; + +class Icf +{ + public: + typedef std::vector<Section_id> Sections_reachable_info; + typedef std::vector<Symbol*> Symbol_info; + typedef std::vector<std::pair<long long, long long> > Addend_info; + typedef std::vector<uint64_t> Offset_info; + typedef Unordered_map<Section_id, + unsigned int, + Section_id_hash> Uniq_secn_id_map; + typedef Unordered_set<Section_id, Section_id_hash> Secn_fptr_taken_set; + + typedef struct + { + // This stores the section corresponding to the reloc. + Sections_reachable_info section_info; + // This stores the symbol corresponding to the reloc. + Symbol_info symbol_info; + // This stores the symbol value and the addend for a reloc. + Addend_info addend_info; + Offset_info offset_info; + } Reloc_info; + + typedef Unordered_map<Section_id, Reloc_info, + Section_id_hash> Reloc_info_list; + + Icf() + : id_section_(), section_id_(), kept_section_id_(), + fptr_section_id_(), + num_tracked_relocs(NULL), icf_ready_(false), + reloc_info_list_() + { } + + // Returns the kept folded identical section corresponding to + // dup_obj and dup_shndx. + Section_id + get_folded_section(Object* dup_obj, unsigned int dup_shndx); + + // Forms groups of identical sections where the first member + // of each group is the kept section during folding. + void + find_identical_sections(const Input_objects* input_objects, + Symbol_table* symtab); + + // This is set when ICF has been run and the groups of + // identical sections have been formed. + void + icf_ready() + { this->icf_ready_ = true; } + + // Returns true if ICF has been run. + bool + is_icf_ready() + { return this->icf_ready_; } + + // Unfolds the section denoted by OBJ and SHNDX if folded. + void + unfold_section(Object* obj, unsigned int shndx); + + // Returns the kept section corresponding to the + // given section. + bool + is_section_folded(Object* obj, unsigned int shndx); + + // Given an object and a section index, this returns true if the + // pointer of the function defined in this section is taken. + bool + section_has_function_pointers(Object *obj, unsigned int shndx) + { + return (this->fptr_section_id_.find(Section_id(obj, shndx)) + != this->fptr_section_id_.end()); + } + + // Records that a pointer of the function defined in this section + // is taken. + void + set_section_has_function_pointers(Object *obj, unsigned int shndx) + { + this->fptr_section_id_.insert(Section_id(obj, shndx)); + } + + // Checks if the section_name should be searched for relocs + // corresponding to taken function pointers. Ignores eh_frame + // and vtable sections. + inline bool + check_section_for_function_pointers(std::string section_name, + Target* target) + { + return (parameters->options().icf_safe_folding() + && target->can_check_for_function_pointers() + && !is_prefix_of(".rodata._ZTV", section_name.c_str()) + && !is_prefix_of(".eh_frame", section_name.c_str())); + } + + // Returns a map of a section to info (Reloc_info) about its relocations. + Reloc_info_list& + reloc_info_list() + { return this->reloc_info_list_; } + + // Returns a mapping of each section to a unique integer. + Uniq_secn_id_map& + section_to_int_map() + { return this->section_id_; } + + private: + + // Maps integers to sections. + std::vector<Section_id> id_section_; + // Does the reverse. + Uniq_secn_id_map section_id_; + // Given a section id, this maps it to the id of the kept + // section. If the id's are the same then this section is + // not folded. + std::vector<unsigned int> kept_section_id_; + // Given a section id, this says if the pointer to this + // function is taken in which case it is dangerous to fold + // this function. + Secn_fptr_taken_set fptr_section_id_; + unsigned int* num_tracked_relocs; + // Flag to indicate if ICF has been run. + bool icf_ready_; + // This list is populated by gc_process_relocs in gc.h. + Reloc_info_list reloc_info_list_; +}; + +// This function returns true if this section corresponds to a function that +// should be considered by icf as a possible candidate for folding. Some +// earlier gcc versions, like 4.0.3, put constructors and destructors in +// .gnu.linkonce.t sections and hence should be included too. +inline bool +is_section_foldable_candidate(const char* section_name) +{ + return (is_prefix_of(".text", section_name) + || is_prefix_of(".gnu.linkonce.t", section_name)); +} + +} // End of namespace gold. + +#endif diff --git a/binutils-2.19/gold/incremental-dump.cc b/binutils-2.19/gold/incremental-dump.cc new file mode 100644 index 0000000..e174b99 --- /dev/null +++ b/binutils-2.19/gold/incremental-dump.cc @@ -0,0 +1,219 @@ +// inremental.cc -- incremental linking test/deubg tool + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Rafael Avila de Espindola <rafael.espindola@gmail.com> + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + + +// This file is a (still incomplete) test/debug tool that should display +// all information available in the incremental linking sections in a +// format that is easy to read. +// Once the format is a bit more stable, this should probably be moved to +// readelf. Because of that, the use of gold's data structures and functions +// is just a short term convenience and not a design decision. + +#include "gold.h" + +#include <stdio.h> +#include <errno.h> + +#include "incremental.h" + +namespace gold +{ + class Output_file; +} + +using namespace gold; + +template<int size, bool big_endian> +static void +dump_incremental_inputs(const char* argv0, + const char* filename, Incremental_binary* inc) +{ + bool t; + unsigned int strtab_shndx; + Incremental_binary::Location location; + + t = inc->find_incremental_inputs_section(&location, &strtab_shndx); + if (!t) + { + fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv0, + filename); + exit (1); + } + + Incremental_binary::View inputs_view(inc->view(location)); + const unsigned char* p = inputs_view.data(); + + Incremental_inputs_header<size, big_endian> incremental_header(p); + + const unsigned char* incremental_inputs_base = + (p + sizeof(Incremental_inputs_header_data)); + + if (incremental_header.get_version() != 1) + { + fprintf(stderr, "%s: %s: unknown incremental version %d\n", argv0, + filename, incremental_header.get_version()); + exit(1); + } + + elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file(inc); + + if (elf_file.section_type(strtab_shndx) != elfcpp::SHT_STRTAB) + { + fprintf(stderr, + "%s: %s: invalid string table section %u (type %d != %d)\n", + argv0, filename, strtab_shndx, + elf_file.section_type(strtab_shndx), elfcpp::SHT_STRTAB); + exit(1); + } + + Incremental_binary::Location + strtab_location(elf_file.section_contents(strtab_shndx)); + + Incremental_binary::View strtab_view(inc->view(strtab_location)); + p = strtab_view.data(); + + elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size); + const char* command_line; + elfcpp::Elf_Word command_line_offset = + incremental_header.get_command_line_offset(); + t = strtab.get_c_string(command_line_offset, &command_line); + + if (!t) + { + fprintf(stderr, + "%s: %s: failed to get link command line: %zu out of range\n", + argv0, filename, + static_cast<size_t>(command_line_offset)); + exit(1); + } + + printf("Link command line: %s\n", command_line); + + printf("Input files:\n"); + for (unsigned i = 0; i < incremental_header.get_input_file_count(); ++i) + { + const unsigned char* input_p = incremental_inputs_base + + i * sizeof(Incremental_inputs_entry_data); + Incremental_inputs_entry<size, big_endian> input(input_p); + const char* objname; + + t = strtab.get_c_string(input.get_filename_offset(), &objname); + if (!t) + { + fprintf(stderr,"%s: %s: failed to get file name for object %u:" + " %zu out of range\n", argv0, filename, i, + static_cast<size_t>(input.get_filename_offset())); + exit(1); + } + printf(" %s\n", objname); + printf(" Timestamp sec = %llu\n", + static_cast<unsigned long long>(input.get_timestamp_sec())); + printf(" Timestamp nsec = %d\n", input.get_timestamp_nsec()); + printf(" Type = "); + // TODO: print the data at input->data_offset once we have it. + elfcpp::Elf_Word input_type = input.get_input_type(); + switch (input_type) + { + case INCREMENTAL_INPUT_OBJECT: + printf("Object\n"); + break; + case INCREMENTAL_INPUT_ARCHIVE: + printf("Archive\n"); + break; + case INCREMENTAL_INPUT_SHARED_LIBRARY: + printf("Shared library\n"); + break; + case INCREMENTAL_INPUT_SCRIPT: + printf("Linker script\n"); + if (input.get_data_offset() != 0) + { + fprintf(stderr,"%s: %s: %u is a script but offset is not zero", + argv0, filename, i); + exit(1); + } + break; + case INCREMENTAL_INPUT_INVALID: + default: + fprintf(stderr, "%s: invalid file type for object %u: %d\n", + argv0, i, input_type); + exit(1); + } + } +} + +int +main(int argc, char** argv) +{ + if (argc != 2) + { + fprintf(stderr, "Usage: %s <file>\n", argv[0]); + return 1; + } + const char* filename = argv[1]; + + Output_file* file = new Output_file(filename); + + bool t = file->open_for_modification(); + if (!t) + { + fprintf(stderr, "%s: open_for_modification(%s): %s\n", argv[0], filename, + strerror(errno)); + return 1; + } + + Incremental_binary* inc = open_incremental_binary(file); + + if (inc == NULL) + { + fprintf(stderr, "%s: open_incremental_binary(%s): %s\n", argv[0], + filename, strerror(errno)); + return 1; + } + + switch (parameters->size_and_endianness()) + { +#ifdef HAVE_TARGET_32_LITTLE + case Parameters::TARGET_32_LITTLE: + dump_incremental_inputs<32, false>(argv[0], filename, inc); + break; +#endif +#ifdef HAVE_TARGET_32_BIG + case Parameters::TARGET_32_BIG: + dump_incremental_inputs<32, true>(argv[0], filename, inc); + break; +#endif +#ifdef HAVE_TARGET_64_LITTLE + case Parameters::TARGET_64_LITTLE: + dump_incremental_inputs<64, false>(argv[0], filename, inc); + break; +#endif +#ifdef HAVE_TARGET_64_BIG + case Parameters::TARGET_64_BIG: + dump_incremental_inputs<64, true>(argv[0], filename, inc); + break; +#endif + default: + gold_unreachable(); + } + + return 0; +} diff --git a/binutils-2.19/gold/incremental.cc b/binutils-2.19/gold/incremental.cc new file mode 100644 index 0000000..bf02834 --- /dev/null +++ b/binutils-2.19/gold/incremental.cc @@ -0,0 +1,544 @@ +// inremental.cc -- incremental linking support for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Mikolaj Zalewski <mikolajz@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstdarg> + +#include "elfcpp.h" +#include "output.h" +#include "incremental.h" +#include "archive.h" +#include "output.h" +#include "target-select.h" + +namespace gold { + +// Version information. Will change frequently during the development, later +// we could think about backward (and forward?) compatibility. +const unsigned int INCREMENTAL_LINK_VERSION = 1; + +// Inform the user why we don't do an incremental link. Not called in +// the obvious case of missing output file. TODO: Is this helpful? + +void +vexplain_no_incremental(const char* format, va_list args) +{ + char* buf = NULL; + if (vasprintf(&buf, format, args) < 0) + gold_nomem(); + gold_info(_("the link might take longer: " + "cannot perform incremental link: %s"), buf); + free(buf); +} + +void +explain_no_incremental(const char* format, ...) +{ + va_list args; + va_start(args, format); + vexplain_no_incremental(format, args); + va_end(args); +} + +// Report an error. + +void +Incremental_binary::error(const char* format, ...) const +{ + va_list args; + va_start(args, format); + // Current code only checks if the file can be used for incremental linking, + // so errors shouldn't fail the build, but only result in a fallback to a + // full build. + // TODO: when we implement incremental editing of the file, we may need a + // flag that will cause errors to be treated seriously. + vexplain_no_incremental(format, args); + va_end(args); +} + +template<int size, bool big_endian> +bool +Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_section( + Location* location, + unsigned int* strtab_shndx) +{ + unsigned int shndx = this->elf_file_.find_section_by_type( + elfcpp::SHT_GNU_INCREMENTAL_INPUTS); + if (shndx == elfcpp::SHN_UNDEF) // Not found. + return false; + *strtab_shndx = this->elf_file_.section_link(shndx); + *location = this->elf_file_.section_contents(shndx); + return true; +} + +template<int size, bool big_endian> +bool +Sized_incremental_binary<size, big_endian>::do_check_inputs( + Incremental_inputs* incremental_inputs) +{ + const int entry_size = + Incremental_inputs_entry_write<size, big_endian>::data_size; + const int header_size = + Incremental_inputs_header_write<size, big_endian>::data_size; + + unsigned int strtab_shndx; + Location location; + + if (!do_find_incremental_inputs_section(&location, &strtab_shndx)) + { + explain_no_incremental(_("no incremental data from previous build")); + return false; + } + if (location.data_size < header_size + || strtab_shndx >= this->elf_file_.shnum() + || this->elf_file_.section_type(strtab_shndx) != elfcpp::SHT_STRTAB) + { + explain_no_incremental(_("invalid incremental build data")); + return false; + } + + Location strtab_location(this->elf_file_.section_contents(strtab_shndx)); + View data_view(view(location)); + View strtab_view(view(strtab_location)); + elfcpp::Elf_strtab strtab(strtab_view.data(), strtab_location.data_size); + Incremental_inputs_header<size, big_endian> header(data_view.data()); + + if (header.get_version() != INCREMENTAL_LINK_VERSION) + { + explain_no_incremental(_("different version of incremental build data")); + return false; + } + + const char* command_line; + // We divide instead of multiplying to make sure there is no integer + // overflow. + size_t max_input_entries = (location.data_size - header_size) / entry_size; + if (header.get_input_file_count() > max_input_entries + || !strtab.get_c_string(header.get_command_line_offset(), &command_line)) + { + explain_no_incremental(_("invalid incremental build data")); + return false; + } + + if (incremental_inputs->command_line() != command_line) + { + explain_no_incremental(_("command line changed")); + return false; + } + + // TODO: compare incremental_inputs->inputs() with entries in data_view. + return true; +} + +namespace +{ + +// Create a Sized_incremental_binary object of the specified size and +// endianness. Fails if the target architecture is not supported. + +template<int size, bool big_endian> +Incremental_binary* +make_sized_incremental_binary(Output_file* file, + const elfcpp::Ehdr<size, big_endian>& ehdr) +{ + Target* target = select_target(ehdr.get_e_machine(), size, big_endian, + ehdr.get_e_ident()[elfcpp::EI_OSABI], + ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]); + if (target == NULL) + { + explain_no_incremental(_("unsupported ELF machine number %d"), + ehdr.get_e_machine()); + return NULL; + } + + if (!parameters->target_valid()) + set_parameters_target(target); + else if (target != ¶meters->target()) + gold_error(_("%s: incompatible target"), file->filename()); + + return new Sized_incremental_binary<size, big_endian>(file, ehdr, target); +} + +} // End of anonymous namespace. + +// Create an Incremental_binary object for FILE. Returns NULL is this is not +// possible, e.g. FILE is not an ELF file or has an unsupported target. FILE +// should be opened. + +Incremental_binary* +open_incremental_binary(Output_file* file) +{ + off_t filesize = file->filesize(); + int want = elfcpp::Elf_recognizer::max_header_size; + if (filesize < want) + want = filesize; + + const unsigned char* p = file->get_input_view(0, want); + if (!elfcpp::Elf_recognizer::is_elf_file(p, want)) + { + explain_no_incremental(_("output is not an ELF file.")); + return NULL; + } + + int size = 0; + bool big_endian = false; + std::string error; + if (!elfcpp::Elf_recognizer::is_valid_header(p, want, &size, &big_endian, + &error)) + { + explain_no_incremental(error.c_str()); + return NULL; + } + + Incremental_binary* result = NULL; + if (size == 32) + { + if (big_endian) + { +#ifdef HAVE_TARGET_32_BIG + result = make_sized_incremental_binary<32, true>( + file, elfcpp::Ehdr<32, true>(p)); +#else + explain_no_incremental(_("unsupported file: 32-bit, big-endian")); +#endif + } + else + { +#ifdef HAVE_TARGET_32_LITTLE + result = make_sized_incremental_binary<32, false>( + file, elfcpp::Ehdr<32, false>(p)); +#else + explain_no_incremental(_("unsupported file: 32-bit, little-endian")); +#endif + } + } + else if (size == 64) + { + if (big_endian) + { +#ifdef HAVE_TARGET_64_BIG + result = make_sized_incremental_binary<64, true>( + file, elfcpp::Ehdr<64, true>(p)); +#else + explain_no_incremental(_("unsupported file: 64-bit, big-endian")); +#endif + } + else + { +#ifdef HAVE_TARGET_64_LITTLE + result = make_sized_incremental_binary<64, false>( + file, elfcpp::Ehdr<64, false>(p)); +#else + explain_no_incremental(_("unsupported file: 64-bit, little-endian")); +#endif + } + } + else + gold_unreachable(); + + return result; +} + +// Analyzes the output file to check if incremental linking is possible and +// (to be done) what files need to be relinked. + +bool +Incremental_checker::can_incrementally_link_output_file() +{ + Output_file output(this->output_name_); + if (!output.open_for_modification()) + return false; + Incremental_binary* binary = open_incremental_binary(&output); + if (binary == NULL) + return false; + return binary->check_inputs(this->incremental_inputs_); +} + +// Add the command line to the string table, setting +// command_line_key_. In incremental builds, the command line is +// stored in .gnu_incremental_inputs so that the next linker run can +// check if the command line options didn't change. + +void +Incremental_inputs::report_command_line(int argc, const char* const* argv) +{ + // Always store 'gold' as argv[0] to avoid a full relink if the user used a + // different path to the linker. + std::string args("gold"); + // Copied from collect_argv in main.cc. + for (int i = 1; i < argc; ++i) + { + // Adding/removing these options should result in a full relink. + if (strcmp(argv[i], "--incremental-changed") == 0 + || strcmp(argv[i], "--incremental-unchanged") == 0 + || strcmp(argv[i], "--incremental-unknown") == 0) + continue; + + args.append(" '"); + // Now append argv[i], but with all single-quotes escaped + const char* argpos = argv[i]; + while (1) + { + const int len = strcspn(argpos, "'"); + args.append(argpos, len); + if (argpos[len] == '\0') + break; + args.append("'\"'\"'"); + argpos += len + 1; + } + args.append("'"); + } + + this->command_line_ = args; + this->strtab_->add(this->command_line_.c_str(), false, + &this->command_line_key_); +} + +// Record that the input argument INPUT is an achive ARCHIVE. This is +// called by Read_symbols after finding out the type of the file. + +void +Incremental_inputs::report_archive(const Input_argument* input, + Archive* archive) +{ + Hold_lock hl(*this->lock_); + + Input_info info; + info.type = INCREMENTAL_INPUT_ARCHIVE; + info.archive = archive; + info.mtime = archive->file().get_mtime(); + this->inputs_map_.insert(std::make_pair(input, info)); +} + +// Record that the input argument INPUT is an object OBJ. This is +// called by Read_symbols after finding out the type of the file. + +void +Incremental_inputs::report_object(const Input_argument* input, + Object* obj) +{ + Hold_lock hl(*this->lock_); + + Input_info info; + info.type = (obj->is_dynamic() + ? INCREMENTAL_INPUT_SHARED_LIBRARY + : INCREMENTAL_INPUT_OBJECT); + info.object = obj; + info.mtime = obj->input_file()->file().get_mtime(); + this->inputs_map_.insert(std::make_pair(input, info)); +} + +// Record that the input argument INPUT is an script SCRIPT. This is +// called by read_script after parsing the script and reading the list +// of inputs added by this script. + +void +Incremental_inputs::report_script(const Input_argument* input, + Timespec mtime, + Script_info* script) +{ + Hold_lock hl(*this->lock_); + + Input_info info; + info.type = INCREMENTAL_INPUT_SCRIPT; + info.script = script; + info.mtime = mtime; + this->inputs_map_.insert(std::make_pair(input, info)); +} + +// Compute indexes in the order in which the inputs should appear in +// .gnu_incremental_inputs. This needs to be done after all the +// scripts are parsed. The function is first called for the command +// line inputs arguments and may call itself recursively for e.g. a +// list of elements of a group or a list of inputs added by a script. +// The [BEGIN; END) interval to analyze and *INDEX is the current +// value of the index (that will be updated). + +void +Incremental_inputs::finalize_inputs( + Input_argument_list::const_iterator begin, + Input_argument_list::const_iterator end, + unsigned int* index) +{ + for (Input_argument_list::const_iterator p = begin; p != end; ++p) + { + if (p->is_group()) + { + finalize_inputs(p->group()->begin(), p->group()->end(), index); + continue; + } + + Inputs_info_map::iterator it = this->inputs_map_.find(&(*p)); + // TODO: turn it into an assert when the code will be more stable. + if (it == this->inputs_map_.end()) + { + gold_error("internal error: %s: incremental build info not provided", + (p->is_file() ? p->file().name() : "[group]")); + continue; + } + Input_info* info = &it->second; + info->index = *index; + (*index)++; + this->strtab_->add(p->file().name(), false, &info->filename_key); + if (info->type == INCREMENTAL_INPUT_SCRIPT) + { + finalize_inputs(info->script->inputs()->begin(), + info->script->inputs()->end(), + index); + } + } +} + +// Finalize the incremental link information. Called from +// Layout::finalize. + +void +Incremental_inputs::finalize() +{ + unsigned int index = 0; + finalize_inputs(this->inputs_->begin(), this->inputs_->end(), &index); + + // Sanity check. + for (Inputs_info_map::const_iterator p = this->inputs_map_.begin(); + p != this->inputs_map_.end(); + ++p) + { + gold_assert(p->second.filename_key != 0); + } + + this->strtab_->set_string_offsets(); +} + +// Create the content of the .gnu_incremental_inputs section. + +Output_section_data* +Incremental_inputs::create_incremental_inputs_section_data() +{ + switch (parameters->size_and_endianness()) + { +#ifdef HAVE_TARGET_32_LITTLE + case Parameters::TARGET_32_LITTLE: + return this->sized_create_inputs_section_data<32, false>(); +#endif +#ifdef HAVE_TARGET_32_BIG + case Parameters::TARGET_32_BIG: + return this->sized_create_inputs_section_data<32, true>(); +#endif +#ifdef HAVE_TARGET_64_LITTLE + case Parameters::TARGET_64_LITTLE: + return this->sized_create_inputs_section_data<64, false>(); +#endif +#ifdef HAVE_TARGET_64_BIG + case Parameters::TARGET_64_BIG: + return this->sized_create_inputs_section_data<64, true>(); +#endif + default: + gold_unreachable(); + } +} + +// Sized creation of .gnu_incremental_inputs section. + +template<int size, bool big_endian> +Output_section_data* +Incremental_inputs::sized_create_inputs_section_data() +{ + const int entry_size = + Incremental_inputs_entry_write<size, big_endian>::data_size; + const int header_size = + Incremental_inputs_header_write<size, big_endian>::data_size; + + unsigned int sz = header_size + entry_size * this->inputs_map_.size(); + unsigned char* buffer = new unsigned char[sz]; + unsigned char* inputs_base = buffer + header_size; + + Incremental_inputs_header_write<size, big_endian> header_writer(buffer); + gold_assert(this->command_line_key_ > 0); + int cmd_offset = this->strtab_->get_offset_from_key(this->command_line_key_); + + header_writer.put_version(INCREMENTAL_LINK_VERSION); + header_writer.put_input_file_count(this->inputs_map_.size()); + header_writer.put_command_line_offset(cmd_offset); + header_writer.put_reserved(0); + + for (Inputs_info_map::const_iterator it = this->inputs_map_.begin(); + it != this->inputs_map_.end(); + ++it) + { + gold_assert(it->second.index < this->inputs_map_.size()); + + unsigned char* entry_buffer = + inputs_base + it->second.index * entry_size; + Incremental_inputs_entry_write<size, big_endian> entry(entry_buffer); + int filename_offset = + this->strtab_->get_offset_from_key(it->second.filename_key); + entry.put_filename_offset(filename_offset); + switch (it->second.type) + { + case INCREMENTAL_INPUT_SCRIPT: + entry.put_data_offset(0); + break; + case INCREMENTAL_INPUT_ARCHIVE: + case INCREMENTAL_INPUT_OBJECT: + case INCREMENTAL_INPUT_SHARED_LIBRARY: + // TODO: add per input data. Currently we store + // an out-of-bounds offset for future version of gold to reject + // such an incremental_inputs section. + entry.put_data_offset(0xffffffff); + break; + default: + gold_unreachable(); + } + entry.put_timestamp_sec(it->second.mtime.seconds); + entry.put_timestamp_nsec(it->second.mtime.nanoseconds); + entry.put_input_type(it->second.type); + entry.put_reserved(0); + } + + return new Output_data_const_buffer(buffer, sz, 8, + "** incremental link inputs list"); +} + +// Instantiate the templates we need. + +#ifdef HAVE_TARGET_32_LITTLE +template +class Sized_incremental_binary<32, false>; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +class Sized_incremental_binary<32, true>; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +class Sized_incremental_binary<64, false>; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +class Sized_incremental_binary<64, true>; +#endif + +} // End namespace gold. diff --git a/binutils-2.19/gold/incremental.h b/binutils-2.19/gold/incremental.h new file mode 100644 index 0000000..a94f397 --- /dev/null +++ b/binutils-2.19/gold/incremental.h @@ -0,0 +1,551 @@ +// inremental.h -- incremental linking support for gold -*- C++ -*- + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Mikolaj Zalewski <mikolajz@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_INCREMENTAL_H +#define GOLD_INCREMENTAL_H + +#include <map> +#include <vector> + +#include "elfcpp_file.h" +#include "stringpool.h" +#include "workqueue.h" +#include "fileread.h" +#include "output.h" + +namespace gold +{ + +class Archive; +class Input_argument; +class Incremental_inputs_checker; +class Object; +class Output_section_data; + +// Incremental input type as stored in .gnu_incremental_inputs. + +enum Incremental_input_type +{ + INCREMENTAL_INPUT_INVALID = 0, + INCREMENTAL_INPUT_OBJECT = 1, + INCREMENTAL_INPUT_ARCHIVE = 2, + INCREMENTAL_INPUT_SHARED_LIBRARY = 3, + INCREMENTAL_INPUT_SCRIPT = 4 +}; + +// Header of the .gnu_incremental_input section. +struct Incremental_inputs_header_data +{ + // Incremental linker version. + elfcpp::Elf_Word version; + + // Numer of input files in the link. + elfcpp::Elf_Word input_file_count; + + // Offset of command line options in .gnu_incremental_strtab. + elfcpp::Elf_Word command_line_offset; + + // Padding. + elfcpp::Elf_Word reserved; +}; + +// Reader class for .gnu_incremental_inputs header. See +// Incremental_inputs_header_data for fields descriptions. + +template<int size, bool big_endian> +class Incremental_inputs_header +{ + private: + typedef Incremental_inputs_header_data Data_type; + typedef elfcpp::Convert<32, big_endian> Convert32; + + public: + Incremental_inputs_header(const unsigned char *p) + : p_(reinterpret_cast<const Data_type*>(p)) + { } + + static const int data_size = sizeof(Data_type); + + elfcpp::Elf_Word + get_version() const + { return Convert32::convert_host(this->p_->version); } + + elfcpp::Elf_Word + get_input_file_count() const + { return Convert32::convert_host(this->p_->input_file_count); } + + elfcpp::Elf_Word + get_command_line_offset() const + { return Convert32::convert_host(this->p_->command_line_offset); } + + elfcpp::Elf_Word + get_reserved() const + { return Convert32::convert_host(this->p_->reserved); } + + private: + const Data_type* p_; +}; + +// Writer class for .gnu_incremental_inputs header. See +// Incremental_inputs_header_data for fields descriptions. + +template<int size, bool big_endian> +class Incremental_inputs_header_write +{ + private: + typedef Incremental_inputs_header_data Data_type; + typedef elfcpp::Convert<32, big_endian> Convert32; + + public: + Incremental_inputs_header_write(unsigned char *p) + : p_(reinterpret_cast<Data_type*>(p)) + { } + + static const int data_size = sizeof(Data_type); + + void + put_version(elfcpp::Elf_Word v) + { this->p_->version = Convert32::convert_host(v); } + + void + put_input_file_count(elfcpp::Elf_Word v) + { this->p_->input_file_count = Convert32::convert_host(v); } + + void + put_command_line_offset(elfcpp::Elf_Word v) + { this->p_->command_line_offset = Convert32::convert_host(v); } + + void + put_reserved(elfcpp::Elf_Word v) + { this->p_->reserved = Convert32::convert_host(v); } + + private: + Data_type* p_; +}; + +// Data stored in .gnu_incremental_input after the header for each of the +// Incremental_input_header_data::input_file_count input entries. +struct Incremental_inputs_entry_data +{ + // Offset of file name in .gnu_incremental_strtab section. + elfcpp::Elf_Word filename_offset; + + // Offset of data in .gnu_incremental_input. + elfcpp::Elf_Word data_offset; + + // Timestamp (in seconds). + elfcpp::Elf_Xword timestamp_sec; + + // Nano-second part of timestamp (if supported). + elfcpp::Elf_Word timestamp_nsec; + + // Type of the input entry. + elfcpp::Elf_Half input_type; + + // Padding. + elfcpp::Elf_Half reserved; +}; + +// Reader class for an .gnu_incremental_inputs entry. See +// Incremental_inputs_entry_data for fields descriptions. +template<int size, bool big_endian> +class Incremental_inputs_entry +{ + private: + typedef Incremental_inputs_entry_data Data_type; + typedef elfcpp::Convert<32, big_endian> Convert32; + typedef elfcpp::Convert<64, big_endian> Convert64; + + public: + Incremental_inputs_entry(const unsigned char *p) + : p_(reinterpret_cast<const Data_type*>(p)) + { } + + static const int data_size = sizeof(Data_type); + + elfcpp::Elf_Word + get_filename_offset() + { return Convert32::convert_host(this->p_->filename_offset); } + + elfcpp::Elf_Word + get_data_offset() + { return Convert32::convert_host(this->p_->data_offset); } + + elfcpp::Elf_Xword + get_timestamp_sec() + { return Convert64::convert_host(this->p_->timestamp_sec); } + + elfcpp::Elf_Word + get_timestamp_nsec() + { return Convert32::convert_host(this->p_->timestamp_nsec); } + + elfcpp::Elf_Word + get_input_type() + { return Convert32::convert_host(this->p_->input_type); } + + elfcpp::Elf_Word + get_reserved() + { return Convert32::convert_host(this->p_->reserved); } + + private: + const Data_type* p_; +}; + +// Writer class for an .gnu_incremental_inputs entry. See +// Incremental_inputs_entry_data for fields descriptions. +template<int size, bool big_endian> +class Incremental_inputs_entry_write +{ + private: + typedef Incremental_inputs_entry_data Data_type; + typedef elfcpp::Convert<32, big_endian> Convert32; + typedef elfcpp::Convert<64, big_endian> Convert64; + + public: + Incremental_inputs_entry_write(unsigned char *p) + : p_(reinterpret_cast<Data_type*>(p)) + { } + + static const int data_size = sizeof(Data_type); + + void + put_filename_offset(elfcpp::Elf_Word v) + { this->p_->filename_offset = Convert32::convert_host(v); } + + void + put_data_offset(elfcpp::Elf_Word v) + { this->p_->data_offset = Convert32::convert_host(v); } + + void + put_timestamp_sec(elfcpp::Elf_Xword v) + { this->p_->timestamp_sec = Convert64::convert_host(v); } + + void + put_timestamp_nsec(elfcpp::Elf_Word v) + { this->p_->timestamp_nsec = Convert32::convert_host(v); } + + void + put_input_type(elfcpp::Elf_Word v) + { this->p_->input_type = Convert32::convert_host(v); } + + void + put_reserved(elfcpp::Elf_Word v) + { this->p_->reserved = Convert32::convert_host(v); } + + private: + Data_type* p_; +}; + +// An object representing the ELF file we edit during an incremental build. +// Similar to Object or Dynobj, but operates on Output_file and contains +// method specific to file edition (TBD). This is the abstract parent class +// implemented in Sized_incremental_binary<size, big_endian> for a specific +// endianness and size. + +class Incremental_binary +{ + public: + Incremental_binary(Output_file* output, Target* target) + : output_(output), target_(target) + { } + + virtual + ~Incremental_binary() + { } + + // Functions and types for the elfcpp::Elf_file interface. This + // permit us to use Incremental_binary as the File template parameter for + // elfcpp::Elf_file. + + // The View class is returned by view. It must support a single + // method, data(). This is trivial, because Output_file::get_output_view + // does what we need. + class View + { + public: + View(const unsigned char* p) + : p_(p) + { } + + const unsigned char* + data() const + { return this->p_; } + + private: + const unsigned char* p_; + }; + + // Return a View. + View + view(off_t file_offset, section_size_type data_size) + { return View(this->output_->get_input_view(file_offset, data_size)); } + + // A location in the file. + struct Location + { + off_t file_offset; + off_t data_size; + + Location(off_t fo, section_size_type ds) + : file_offset(fo), data_size(ds) + { } + + Location() + : file_offset(0), data_size(0) + { } + }; + + // Get a View given a Location. + View view(Location loc) + { return View(this->view(loc.file_offset, loc.data_size)); } + + // Report an error. + void + error(const char* format, ...) const ATTRIBUTE_PRINTF_2; + + // Find the .gnu_incremental_inputs section. It selects the first section + // of type SHT_GNU_INCREMENTAL_INPUTS. Returns false if such a section + // is not found. + bool + find_incremental_inputs_section(Location* location, + unsigned int* strtab_shndx) + { return do_find_incremental_inputs_section(location, strtab_shndx); } + + // Check the .gnu_incremental_inputs section to see whether an incremental + // build is possible. + // TODO: on success, should report what files needs to be rebuilt. + // INCREMENTAL_INPUTS is used to read the canonical form of the command line + // and read the input arguments. TODO: for items that don't need to be + // rebuilt, we should also copy the incremental input information. + virtual bool + check_inputs(Incremental_inputs* incremental_inputs) + { return do_check_inputs(incremental_inputs); } + + protected: + // Find incremental inputs section. + virtual bool + do_find_incremental_inputs_section(Location* location, + unsigned int* strtab_shndx) = 0; + + // Check the .gnu_incremental_inputs section to see whether an incremental + // build is possible. + virtual bool + do_check_inputs(Incremental_inputs* incremental_inputs) = 0; + + private: + // Edited output file object. + Output_file* output_; + // Target of the output file. + Target* target_; +}; + +template<int size, bool big_endian> +class Sized_incremental_binary : public Incremental_binary +{ + public: + Sized_incremental_binary(Output_file* output, + const elfcpp::Ehdr<size, big_endian>& ehdr, + Target* target) + : Incremental_binary(output, target), elf_file_(this, ehdr) + { } + + protected: + virtual bool + do_find_incremental_inputs_section(Location* location, + unsigned int* strtab_shndx); + + virtual bool + do_check_inputs(Incremental_inputs* incremental_inputs); + + private: + // Output as an ELF file. + elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_; +}; + +// Create an Incremental_binary object for FILE. Returns NULL is this is not +// possible, e.g. FILE is not an ELF file or has an unsupported target. +Incremental_binary* +open_incremental_binary(Output_file* file); + +// Code invoked early during an incremental link that checks what files need +// to be relinked. +class Incremental_checker +{ + public: + // Check if the file named OUTPUT_NAME can be linked incrementally. + // INCREMENTAL_INPUTS must have the canonical form of the command line + // and input arguments filled - at this point of linking other fields are + // probably not filled yet. TODO: for inputs that don't need to be + // rebuilt, this function should fill the incremental input information. + Incremental_checker(const char* output_name, + Incremental_inputs* incremental_inputs) + : output_name_(output_name), incremental_inputs_(incremental_inputs) + { } + + // Analyzes the output file to check if incremental linking is possible and + // what files needs to be relinked. + bool + can_incrementally_link_output_file(); + + private: + // Name of the output file to analyze. + const char* output_name_; + + // The Incremental_inputs object. At this stage of link, only the command + // line and inputs are filled. + Incremental_inputs* incremental_inputs_; +}; + +// This class contains the information needed during an incremental +// build about the inputs necessary to build the .gnu_incremental_inputs. +class Incremental_inputs +{ + public: + Incremental_inputs() + : lock_(new Lock()), inputs_(NULL), command_line_key_(0), + strtab_(new Stringpool()) + { } + ~Incremental_inputs() { delete this->strtab_; } + + // Record the command line. + void + report_command_line(int argc, const char* const* argv); + + // Record the input arguments obtained from parsing the command line. + void + report_inputs(const Input_arguments& inputs) + { this->inputs_ = &inputs; } + + // Record that the input argument INPUT is an archive ARCHIVE. + void + report_archive(const Input_argument* input, Archive* archive); + + // Record that the input argument INPUT is to an object OBJ. + void + report_object(const Input_argument* input, Object* obj); + + // Record that the input argument INPUT is to an script SCRIPT. + void + report_script(const Input_argument* input, Timespec mtime, + Script_info* script); + + // Prepare for layout. Called from Layout::finalize. + void + finalize(); + + // Create the content of the .gnu_incremental_inputs section. + Output_section_data* + create_incremental_inputs_section_data(); + + // Return the .gnu_incremental_strtab stringpool. + Stringpool* + get_stringpool() + { return this->strtab_; } + + // Return the canonical form of the command line, as will be stored in + // .gnu_incremental_strtab. + const std::string& + command_line() + { return this->command_line_; } + + // Return the input files found in the command line. + const Input_arguments* + inputs() + { return this->inputs_; } + + private: + // Code for each of the four possible variants of create_inputs_section_data. + template<int size, bool big_endian> + Output_section_data* + sized_create_inputs_section_data(); + + // Compute indexes in the order in which the inputs should appear in + // .gnu_incremental_inputs and put file names to the stringtable. + // This needs to be done after all the scripts are parsed. + + void + finalize_inputs(Input_argument_list::const_iterator begin, + Input_argument_list::const_iterator end, + unsigned int* index); + + // Additional data about an input needed for an incremental link. + // None of these pointers is owned by the structure. + struct Input_info + { + Input_info() + : type(INCREMENTAL_INPUT_INVALID), archive(NULL), filename_key(0), + index(0) + { } + + // Type of the file pointed by this argument. + Incremental_input_type type; + + union + { + // Present if type == INCREMENTAL_INPUT_ARCHIVE. + Archive* archive; + + // Present if type == INCREMENTAL_INPUT_OBJECT or + // INCREMENTAL_INPUT_SHARED_LIBRARY. + Object* object; + + // Present if type == INCREMENTAL_INPUT_SCRIPT. + Script_info* script; + }; + + // Key of the filename string in the section stringtable. + Stringpool::Key filename_key; + + // Position of the entry information in the output section. + unsigned int index; + + // Last modification time of the file. + Timespec mtime; + }; + + typedef std::map<const Input_argument*, Input_info> Inputs_info_map; + + // A lock guarding access to inputs_ during the first phase of linking, when + // report_ function may be called from multiple threads. + Lock* lock_; + + // The list of input arguments obtained from parsing the command line. + const Input_arguments* inputs_; + + // A map containing additional information about the input elements. + Inputs_info_map inputs_map_; + + // Canonical form of the command line, as will be stored in + // .gnu_incremental_strtab. + std::string command_line_; + + // The key of the command line string in the string pool. + Stringpool::Key command_line_key_; + + // The .gnu_incremental_strtab string pool associated with the + // .gnu_incremental_inputs. + Stringpool* strtab_; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_INCREMENTAL_H) diff --git a/binutils-2.19/gold/int_encoding.cc b/binutils-2.19/gold/int_encoding.cc new file mode 100644 index 0000000..ef58749 --- /dev/null +++ b/binutils-2.19/gold/int_encoding.cc @@ -0,0 +1,131 @@ +// varint.cc -- variable length and unaligned integer encoding support. + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com> by refactoring scattered +// contents from other files in gold. Original code written by Ian +// Lance Taylor <iant@google.com> and Caleb Howe <cshowe@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <vector> + +#include "int_encoding.h" + +namespace gold { + +// Read an unsigned LEB128 number. Each byte contains 7 bits of +// information, plus one bit saying whether the number continues or +// not. + +uint64_t +read_unsigned_LEB_128(const unsigned char* buffer, size_t* len) +{ + uint64_t result = 0; + size_t num_read = 0; + unsigned int shift = 0; + unsigned char byte; + + do + { + if (num_read >= 64 / 7) + { + gold_warning(_("Unusually large LEB128 decoded, " + "debug information may be corrupted")); + break; + } + byte = *buffer++; + num_read++; + result |= (static_cast<uint64_t>(byte & 0x7f)) << shift; + shift += 7; + } + while (byte & 0x80); + + *len = num_read; + + return result; +} + +// Read a signed LEB128 number. These are like regular LEB128 +// numbers, except the last byte may have a sign bit set. + +int64_t +read_signed_LEB_128(const unsigned char* buffer, size_t* len) +{ + int64_t result = 0; + int shift = 0; + size_t num_read = 0; + unsigned char byte; + + do + { + if (num_read >= 64 / 7) + { + gold_warning(_("Unusually large LEB128 decoded, " + "debug information may be corrupted")); + break; + } + byte = *buffer++; + num_read++; + result |= (static_cast<uint64_t>(byte & 0x7f) << shift); + shift += 7; + } + while (byte & 0x80); + + if ((shift < 8 * static_cast<int>(sizeof(result))) && (byte & 0x40)) + result |= -((static_cast<int64_t>(1)) << shift); + *len = num_read; + return result; +} + +void +write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value) +{ + do + { + unsigned char current_byte = value & 0x7f; + value >>= 7; + if (value != 0) + { + current_byte |= 0x80; + } + buffer->push_back(current_byte); + } + while (value != 0); +} + +size_t +get_length_as_unsigned_LEB_128(uint64_t value) +{ + size_t length = 0; + do + { + unsigned char current_byte = value & 0x7f; + value >>= 7; + if (value != 0) + { + current_byte |= 0x80; + } + length++; + } + while (value != 0); + return length; +} + +} // End namespace gold. diff --git a/binutils-2.19/gold/int_encoding.h b/binutils-2.19/gold/int_encoding.h new file mode 100644 index 0000000..b60e969 --- /dev/null +++ b/binutils-2.19/gold/int_encoding.h @@ -0,0 +1,112 @@ +// int_encoding.h -- variable length and unaligned integers -*- C++ -*- + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com> by refactoring scattered +// contents from other files in gold. Original code written by Ian +// Lance Taylor <iant@google.com> and Caleb Howe <cshowe@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_INT_ENCODING_H +#define GOLD_INT_ENCODING_H + +#include <vector> +#include "elfcpp.h" +#include "target.h" +#include "parameters.h" + +namespace gold +{ + +// +// LEB 128 encoding support. +// + +// Read a ULEB 128 encoded integer from BUFFER. Return the length of the +// encoded integer at the location PLEN. + +uint64_t +read_unsigned_LEB_128(const unsigned char* buffer, size_t* plen); + +// Read an SLEB 128 encoded integer from BUFFER. Return the length of the +// encoded integer at the location PLEN. + +int64_t +read_signed_LEB_128(const unsigned char* buffer, size_t* plen); + +// Write a ULEB 128 encoded VALUE to BUFFER. + +void +write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value); + +// Return the ULEB 128 encoded size of VALUE. + +size_t +get_length_as_unsigned_LEB_128(uint64_t value); + +// +// Unaligned integer encoding support. +// + +// Insert VALSIZE-bit integer VALUE into DESTINATION. + +template <int valsize> +void insert_into_vector(std::vector<unsigned char>* destination, + typename elfcpp::Valtype_base<valsize>::Valtype value) +{ + unsigned char buffer[valsize / 8]; + if (parameters->target().is_big_endian()) + elfcpp::Swap_unaligned<valsize, true>::writeval(buffer, value); + else + elfcpp::Swap_unaligned<valsize, false>::writeval(buffer, value); + destination->insert(destination->end(), buffer, buffer + valsize / 8); +} + +// Read a possibly unaligned integer of SIZE. Update SOURCE after read. + +template <int valsize> +typename elfcpp::Valtype_base<valsize>::Valtype +read_from_pointer(unsigned char** source) +{ + typename elfcpp::Valtype_base<valsize>::Valtype return_value; + if (parameters->target().is_big_endian()) + return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source); + else + return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source); + *source += valsize / 8; + return return_value; +} + +// Same as the above except for use with const unsigned char data. + +template <int valsize> +typename elfcpp::Valtype_base<valsize>::Valtype +read_from_pointer(const unsigned char** source) +{ + typename elfcpp::Valtype_base<valsize>::Valtype return_value; + if (parameters->target().is_big_endian()) + return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source); + else + return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source); + *source += valsize / 8; + return return_value; +} + +} // End namespace gold. + +#endif // !defined(GOLD_INT_ENCODING_H) diff --git a/binutils-2.19/gold/layout.cc b/binutils-2.19/gold/layout.cc index 99819d6..2ffbdf4 100644 --- a/binutils-2.19/gold/layout.cc +++ b/binutils-2.19/gold/layout.cc @@ -1,6 +1,6 @@ // layout.cc -- lay out output file sections for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -46,11 +46,86 @@ #include "reduced_debug_output.h" #include "reloc.h" #include "descriptors.h" +#include "plugin.h" +#include "incremental.h" #include "layout.h" namespace gold { +// Layout::Relaxation_debug_check methods. + +// Check that sections and special data are in reset states. +// We do not save states for Output_sections and special Output_data. +// So we check that they have not assigned any addresses or offsets. +// clean_up_after_relaxation simply resets their addresses and offsets. +void +Layout::Relaxation_debug_check::check_output_data_for_reset_values( + const Layout::Section_list& sections, + const Layout::Data_list& special_outputs) +{ + for(Layout::Section_list::const_iterator p = sections.begin(); + p != sections.end(); + ++p) + gold_assert((*p)->address_and_file_offset_have_reset_values()); + + for(Layout::Data_list::const_iterator p = special_outputs.begin(); + p != special_outputs.end(); + ++p) + gold_assert((*p)->address_and_file_offset_have_reset_values()); +} + +// Save information of SECTIONS for checking later. + +void +Layout::Relaxation_debug_check::read_sections( + const Layout::Section_list& sections) +{ + for(Layout::Section_list::const_iterator p = sections.begin(); + p != sections.end(); + ++p) + { + Output_section* os = *p; + Section_info info; + info.output_section = os; + info.address = os->is_address_valid() ? os->address() : 0; + info.data_size = os->is_data_size_valid() ? os->data_size() : -1; + info.offset = os->is_offset_valid()? os->offset() : -1 ; + this->section_infos_.push_back(info); + } +} + +// Verify SECTIONS using previously recorded information. + +void +Layout::Relaxation_debug_check::verify_sections( + const Layout::Section_list& sections) +{ + size_t i = 0; + for(Layout::Section_list::const_iterator p = sections.begin(); + p != sections.end(); + ++p, ++i) + { + Output_section* os = *p; + uint64_t address = os->is_address_valid() ? os->address() : 0; + off_t data_size = os->is_data_size_valid() ? os->data_size() : -1; + off_t offset = os->is_offset_valid()? os->offset() : -1 ; + + if (i >= this->section_infos_.size()) + { + gold_fatal("Section_info of %s missing.\n", os->name()); + } + const Section_info& info = this->section_infos_[i]; + if (os != info.output_section) + gold_fatal("Section order changed. Expecting %s but see %s\n", + info.output_section->name(), os->name()); + if (address != info.address + || data_size != info.data_size + || offset != info.offset) + gold_fatal("Section %s changed.\n", os->name()); + } +} + // Layout_task_runner methods. // Lay out the sections. This is called after all the input objects @@ -85,8 +160,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task) // Layout methods. -Layout::Layout(const General_options& options, Script_options* script_options) - : options_(options), +Layout::Layout(int number_of_input_files, Script_options* script_options) + : number_of_input_files_(number_of_input_files), script_options_(script_options), namepool_(), sympool_(), @@ -96,16 +171,17 @@ Layout::Layout(const General_options& options, Script_options* script_options) segment_list_(), section_list_(), unattached_section_list_(), - sections_are_attached_(false), special_output_list_(), section_headers_(NULL), tls_segment_(NULL), relro_segment_(NULL), + increase_relro_(0), symtab_section_(NULL), symtab_xindex_(NULL), dynsym_section_(NULL), dynsym_xindex_(NULL), dynamic_section_(NULL), + dynamic_symbol_(NULL), dynamic_data_(NULL), eh_frame_section_(NULL), eh_frame_data_(NULL), @@ -116,11 +192,20 @@ Layout::Layout(const General_options& options, Script_options* script_options) debug_info_(NULL), group_signatures_(), output_file_size_(-1), + have_added_input_section_(false), + sections_are_attached_(false), input_requires_executable_stack_(false), input_with_gnu_stack_note_(false), input_without_gnu_stack_note_(false), has_static_tls_(false), - any_postprocessing_sections_(false) + any_postprocessing_sections_(false), + resized_signatures_(false), + have_stabstr_section_(false), + incremental_inputs_(NULL), + record_output_section_data_from_script_(false), + script_output_section_data_list_(), + segment_states_(NULL), + relaxation_debug_check_(NULL) { // Make space for more than enough segments for a typical file. // This is just for efficiency--it's OK if we wind up needing more. @@ -129,6 +214,14 @@ Layout::Layout(const General_options& options, Script_options* script_options) // We expect two unattached Output_data objects: the file header and // the segment headers. this->special_output_list_.reserve(2); + + // Initialize structure needed for an incremental build. + if (parameters->options().incremental()) + this->incremental_inputs_ = new Incremental_inputs; + + // The section name pool is worth optimizing in all cases, because + // it is small, but there are often overlaps due to .rel sections. + this->namepool_.set_optimize(); } // Hash a key we use to look up an output section mapping. @@ -139,14 +232,6 @@ Layout::Hash_key::operator()(const Layout::Key& k) const return k.first + k.second.first + k.second.second; } -// Return whether PREFIX is a prefix of STR. - -static inline bool -is_prefix_of(const char* prefix, const char* str) -{ - return strncmp(prefix, str, strlen(prefix)) == 0; -} - // Returns whether the given section is in the list of // debug-sections-used-by-some-version-of-gdb. Currently, // we've checked versions of gdb up to and including 6.7.1. @@ -206,6 +291,9 @@ bool Layout::include_section(Sized_relobj<size, big_endian>*, const char* name, const elfcpp::Shdr<size, big_endian>& shdr) { + if (shdr.get_sh_flags() & elfcpp::SHF_EXCLUDE) + return false; + switch (shdr.get_sh_type()) { case elfcpp::SHT_NULL: @@ -256,6 +344,19 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name, && !is_gdb_debug_section(name)) return false; } + if (parameters->options().strip_lto_sections() + && !parameters->options().relocatable() + && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) + { + // Ignore LTO sections containing intermediate code. + if (is_prefix_of(".gnu.lto_", name)) + return false; + } + // The GNU linker strips .gnu_debuglink sections, so we do too. + // This is a feature used to keep debugging information in + // separate files. + if (strcmp(name, ".gnu_debuglink") == 0) + return false; return true; default: @@ -295,11 +396,18 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set, // Return the output section to use for section NAME with type TYPE // and section flags FLAGS. NAME must be canonicalized in the string -// pool, and NAME_KEY is the key. +// pool, and NAME_KEY is the key. IS_INTERP is true if this is the +// .interp section. IS_DYNAMIC_LINKER_SECTION is true if this section +// is used by the dynamic linker. IS_RELRO is true for a relro +// section. IS_LAST_RELRO is true for the last relro section. +// IS_FIRST_NON_RELRO is true for the first non-relro section. Output_section* Layout::get_output_section(const char* name, Stringpool::Key name_key, - elfcpp::Elf_Word type, elfcpp::Elf_Xword flags) + elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, + bool is_interp, bool is_dynamic_linker_section, + bool is_relro, bool is_last_relro, + bool is_first_non_relro) { elfcpp::Elf_Xword lookup_flags = flags; @@ -348,7 +456,9 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, } if (os == NULL) - os = this->make_output_section(name, type, flags); + os = this->make_output_section(name, type, flags, is_interp, + is_dynamic_linker_section, is_relro, + is_last_relro, is_first_non_relro); ins.first->second = os; return os; } @@ -358,13 +468,19 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, // RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a // linker created section. IS_INPUT_SECTION is true if we are // choosing an output section for an input section found in a input -// file. This will return NULL if the input section should be -// discarded. +// file. IS_INTERP is true if this is the .interp section. +// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the +// dynamic linker. IS_RELRO is true for a relro section. +// IS_LAST_RELRO is true for the last relro section. +// IS_FIRST_NON_RELRO is true for the first non-relro section. This +// will return NULL if the input section should be discarded. Output_section* Layout::choose_output_section(const Relobj* relobj, const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool is_input_section) + bool is_input_section, bool is_interp, + bool is_dynamic_linker_section, bool is_relro, + bool is_last_relro, bool is_first_non_relro) { // We should not see any input sections after we have attached // sections to segments. @@ -386,13 +502,27 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, Script_sections* ss = this->script_options_->script_sections(); const char* file_name = relobj == NULL ? NULL : relobj->name().c_str(); Output_section** output_section_slot; - name = ss->output_section_name(file_name, name, &output_section_slot); + Script_sections::Section_type script_section_type; + name = ss->output_section_name(file_name, name, &output_section_slot, + &script_section_type); if (name == NULL) { // The SECTIONS clause says to discard this input section. return NULL; } + // We can only handle script section types ST_NONE and ST_NOLOAD. + switch (script_section_type) + { + case Script_sections::ST_NONE: + break; + case Script_sections::ST_NOLOAD: + flags &= elfcpp::SHF_ALLOC; + break; + default: + gold_unreachable(); + } + // If this is an orphan section--one not mentioned in the linker // script--then OUTPUT_SECTION_SLOT will be NULL, and we do the // default processing below. @@ -400,7 +530,10 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, if (output_section_slot != NULL) { if (*output_section_slot != NULL) - return *output_section_slot; + { + (*output_section_slot)->update_flags_for_input_section(flags); + return *output_section_slot; + } // We don't put sections found in the linker script into // SECTION_NAME_MAP_. That keeps us from getting confused @@ -409,8 +542,30 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, name = this->namepool_.add(name, false, NULL); - Output_section* os = this->make_output_section(name, type, flags); + Output_section* os = + this->make_output_section(name, type, flags, is_interp, + is_dynamic_linker_section, is_relro, + is_last_relro, is_first_non_relro); os->set_found_in_sections_clause(); + + // Special handling for NOLOAD sections. + if (script_section_type == Script_sections::ST_NOLOAD) + { + os->set_is_noload(); + + // The constructor of Output_section sets addresses of non-ALLOC + // sections to 0 by default. We don't want that for NOLOAD + // sections even if they have no SHF_ALLOC flag. + if ((os->flags() & elfcpp::SHF_ALLOC) == 0 + && os->is_address_valid()) + { + gold_assert(os->address() == 0 + && !os->is_offset_valid() + && !os->is_data_size_valid()); + os->reset_address_and_file_offset(); + } + } + *output_section_slot = os; return os; } @@ -422,7 +577,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, // output section. size_t len = strlen(name); - if (is_input_section && !parameters->options().relocatable()) + if (is_input_section + && !this->script_options_->saw_sections_clause() + && !parameters->options().relocatable()) name = Layout::output_section_name(name, &len); Stringpool::Key name_key; @@ -430,7 +587,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, // Find or make the output section. The output section is selected // based on the section name, type, and flags. - return this->get_output_section(name, name_key, type, flags); + return this->get_output_section(name, name_key, type, flags, is_interp, + is_dynamic_linker_section, is_relro, + is_last_relro, is_first_non_relro); } // Return the output section to use for input section SHNDX, with name @@ -456,19 +615,42 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx, Output_section* os; + // Sometimes .init_array*, .preinit_array* and .fini_array* do not have + // correct section types. Force them here. + elfcpp::Elf_Word sh_type = shdr.get_sh_type(); + if (sh_type == elfcpp::SHT_PROGBITS) + { + static const char init_array_prefix[] = ".init_array"; + static const char preinit_array_prefix[] = ".preinit_array"; + static const char fini_array_prefix[] = ".fini_array"; + static size_t init_array_prefix_size = sizeof(init_array_prefix) - 1; + static size_t preinit_array_prefix_size = + sizeof(preinit_array_prefix) - 1; + static size_t fini_array_prefix_size = sizeof(fini_array_prefix) - 1; + + if (strncmp(name, init_array_prefix, init_array_prefix_size) == 0) + sh_type = elfcpp::SHT_INIT_ARRAY; + else if (strncmp(name, preinit_array_prefix, preinit_array_prefix_size) + == 0) + sh_type = elfcpp::SHT_PREINIT_ARRAY; + else if (strncmp(name, fini_array_prefix, fini_array_prefix_size) == 0) + sh_type = elfcpp::SHT_FINI_ARRAY; + } + // In a relocatable link a grouped section must not be combined with // any other sections. if (parameters->options().relocatable() && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0) { name = this->namepool_.add(name, true, NULL); - os = this->make_output_section(name, shdr.get_sh_type(), - shdr.get_sh_flags()); + os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false, + false, false, false, false); } else { - os = this->choose_output_section(object, name, shdr.get_sh_type(), - shdr.get_sh_flags(), true); + os = this->choose_output_section(object, name, sh_type, + shdr.get_sh_flags(), true, false, + false, false, false, false); if (os == NULL) return NULL; } @@ -488,6 +670,7 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx, *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx, this->script_options_->saw_sections_clause()); + this->have_added_input_section_ = true; return os; } @@ -519,7 +702,8 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object, Output_section* os = this->choose_output_section(object, name.c_str(), sh_type, shdr.get_sh_flags(), - false); + false, false, false, + false, false, false); os->set_should_link_to_symtab(); os->set_info_section(data_section); @@ -566,7 +750,9 @@ Layout::layout_group(Symbol_table* symtab, group_section_name = this->namepool_.add(group_section_name, true, NULL); Output_section* os = this->make_output_section(group_section_name, elfcpp::SHT_GROUP, - shdr.get_sh_flags()); + shdr.get_sh_flags(), + false, false, false, + false, false); // We need to find a symbol with the signature in the symbol table. // If we don't find one now, we need to look again later. @@ -575,6 +761,10 @@ Layout::layout_group(Symbol_table* symtab, os->set_info_symndx(sym); else { + // Reserve some space to minimize reallocations. + if (this->group_signatures_.empty()) + this->group_signatures_.reserve(this->number_of_input_files_ * 16); + // We will wind up using a symbol whose name is the signature. // So just put the signature in the symbol name pool to save it. signature = symtab->canonicalize_name(signature); @@ -616,7 +806,8 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, name, elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false); + false, false, false, + false, false, false); if (os == NULL) return NULL; @@ -625,14 +816,15 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, this->eh_frame_section_ = os; this->eh_frame_data_ = new Eh_frame(); - if (this->options_.eh_frame_hdr()) + if (parameters->options().eh_frame_hdr()) { Output_section* hdr_os = this->choose_output_section(NULL, ".eh_frame_hdr", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false); + false, false, false, + false, false, false); if (hdr_os != NULL) { @@ -647,7 +839,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, Output_segment* hdr_oseg; hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME, elfcpp::PF_R); - hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R); + hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false); } this->eh_frame_data_->set_eh_frame_hdr(hdr_posd); @@ -687,6 +879,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, bool saw_sections_clause = this->script_options_->saw_sections_clause(); *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx, saw_sections_clause); + this->have_added_input_section_ = true; } return os; @@ -698,10 +891,16 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, Output_section* Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - Output_section_data* posd) + Output_section_data* posd, + bool is_dynamic_linker_section, + bool is_relro, bool is_last_relro, + bool is_first_non_relro) { Output_section* os = this->choose_output_section(NULL, name, type, flags, - false); + false, false, + is_dynamic_linker_section, + is_relro, is_last_relro, + is_first_non_relro); if (os != NULL) os->add_output_section_data(posd); return os; @@ -723,12 +922,11 @@ Layout::section_flags_to_segment(elfcpp::Elf_Xword flags) // Sometimes we compress sections. This is typically done for // sections that are not part of normal program execution (such as // .debug_* sections), and where the readers of these sections know -// how to deal with compressed sections. (To make it easier for them, -// we will rename the ouput section in such cases from .foo to -// .foo.zlib.nnnn, where nnnn is the uncompressed size.) This routine -// doesn't say for certain whether we'll compress -- it depends on -// commandline options as well -- just whether this section is a -// candidate for compression. +// how to deal with compressed sections. This routine doesn't say for +// certain whether we'll compress -- it depends on commandline options +// as well -- just whether this section is a candidate for compression. +// (The Output_compressed_section class decides whether to compress +// a given section, and picks the name of the compressed section.) static bool is_compressible_debug_section(const char* secname) @@ -737,20 +935,26 @@ is_compressible_debug_section(const char* secname) } // Make a new Output_section, and attach it to segments as -// appropriate. +// appropriate. IS_INTERP is true if this is the .interp section. +// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the +// dynamic linker. IS_RELRO is true if this is a relro section. +// IS_LAST_RELRO is true if this is the last relro section. +// IS_FIRST_NON_RELRO is true if this is the first non relro section. Output_section* Layout::make_output_section(const char* name, elfcpp::Elf_Word type, - elfcpp::Elf_Xword flags) + elfcpp::Elf_Xword flags, bool is_interp, + bool is_dynamic_linker_section, bool is_relro, + bool is_last_relro, bool is_first_non_relro) { Output_section* os; if ((flags & elfcpp::SHF_ALLOC) == 0 - && strcmp(this->options_.compress_debug_sections(), "none") != 0 + && strcmp(parameters->options().compress_debug_sections(), "none") != 0 && is_compressible_debug_section(name)) - os = new Output_compressed_section(&this->options_, name, type, flags); - + os = new Output_compressed_section(¶meters->options(), name, type, + flags); else if ((flags & elfcpp::SHF_ALLOC) == 0 - && this->options_.strip_debug_non_line() + && parameters->options().strip_debug_non_line() && strcmp(".debug_abbrev", name) == 0) { os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section( @@ -759,7 +963,7 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, this->debug_info_->set_abbreviations(this->debug_abbrev_); } else if ((flags & elfcpp::SHF_ALLOC) == 0 - && this->options_.strip_debug_non_line() + && parameters->options().strip_debug_non_line() && strcmp(".debug_info", name) == 0) { os = this->debug_info_ = new Output_reduced_debug_info_section( @@ -768,7 +972,24 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, this->debug_info_->set_abbreviations(this->debug_abbrev_); } else - os = new Output_section(name, type, flags); + { + // FIXME: const_cast is ugly. + Target* target = const_cast<Target*>(¶meters->target()); + os = target->make_output_section(name, type, flags); + } + + if (is_interp) + os->set_is_interp(); + if (is_dynamic_linker_section) + os->set_is_dynamic_linker_section(); + if (is_relro) + os->set_is_relro(); + if (is_last_relro) + os->set_is_last_relro(); + if (is_first_non_relro) + os->set_is_first_non_relro(); + + parameters->target().new_output_section(os); this->section_list_.push_back(os); @@ -799,6 +1020,14 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, } } + // Check for .stab*str sections, as .stab* sections need to link to + // them. + if (type == elfcpp::SHT_STRTAB + && !this->have_stabstr_section_ + && strncmp(name, ".stab", 5) == 0 + && strcmp(name + strlen(name) - 3, "str") == 0) + this->have_stabstr_section_ = true; + // If we have already attached the sections to segments, then we // need to attach this one now. This happens for sections created // directly by the linker. @@ -855,9 +1084,14 @@ Layout::attach_allocated_section_to_segment(Output_section* os) elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags); + // Check for --section-start. + uint64_t addr; + bool is_address_set = parameters->options().section_start(os->name(), &addr); + // In general the only thing we really care about for PT_LOAD // segments is whether or not they are writable, so that is how we - // search for them. People who need segments sorted on some other + // search for them. Large data sections also go into their own + // PT_LOAD segment. People who need segments sorted on some other // basis will have to use a linker script. Segment_list::const_iterator p; @@ -865,29 +1099,46 @@ Layout::attach_allocated_section_to_segment(Output_section* os) p != this->segment_list_.end(); ++p) { - if ((*p)->type() == elfcpp::PT_LOAD - && (parameters->options().omagic() - || ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))) - { - // If -Tbss was specified, we need to separate the data - // and BSS segments. - if (this->options_.user_set_Tbss()) - { - if ((os->type() == elfcpp::SHT_NOBITS) - == (*p)->has_any_data_sections()) - continue; - } + if ((*p)->type() != elfcpp::PT_LOAD) + continue; + if (!parameters->options().omagic() + && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W)) + continue; + // If -Tbss was specified, we need to separate the data and BSS + // segments. + if (parameters->options().user_set_Tbss()) + { + if ((os->type() == elfcpp::SHT_NOBITS) + == (*p)->has_any_data_sections()) + continue; + } + if (os->is_large_data_section() && !(*p)->is_large_data_segment()) + continue; - (*p)->add_output_section(os, seg_flags); - break; - } + if (is_address_set) + { + if ((*p)->are_addresses_set()) + continue; + + (*p)->add_initial_output_data(os); + (*p)->update_flags_for_output_section(seg_flags); + (*p)->set_addresses(addr, addr); + break; + } + + (*p)->add_output_section(os, seg_flags, true); + break; } if (p == this->segment_list_.end()) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD, seg_flags); - oseg->add_output_section(os, seg_flags); + if (os->is_large_data_section()) + oseg->set_is_large_data_segment(); + oseg->add_output_section(os, seg_flags, true); + if (is_address_set) + oseg->set_addresses(addr, addr); } // If we see a loadable SHT_NOTE section, we create a PT_NOTE @@ -903,7 +1154,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) && (((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))) { - (*p)->add_output_section(os, seg_flags); + (*p)->add_output_section(os, seg_flags, false); break; } } @@ -912,7 +1163,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE, seg_flags); - oseg->add_output_section(os, seg_flags); + oseg->add_output_section(os, seg_flags, false); } } @@ -922,7 +1173,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { if (this->tls_segment_ == NULL) this->make_output_segment(elfcpp::PT_TLS, seg_flags); - this->tls_segment_->add_output_section(os, seg_flags); + this->tls_segment_->add_output_section(os, seg_flags, false); } // If -z relro is in effect, and we see a relro section, we create a @@ -932,19 +1183,27 @@ Layout::attach_allocated_section_to_segment(Output_section* os) gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W)); if (this->relro_segment_ == NULL) this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags); - this->relro_segment_->add_output_section(os, seg_flags); + this->relro_segment_->add_output_section(os, seg_flags, false); } } // Make an output section for a script. Output_section* -Layout::make_output_section_for_script(const char* name) +Layout::make_output_section_for_script( + const char* name, + Script_sections::Section_type section_type) { name = this->namepool_.add(name, false, NULL); + elfcpp::Elf_Xword sh_flags = elfcpp::SHF_ALLOC; + if (section_type == Script_sections::ST_NOLOAD) + sh_flags = 0; Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC); + sh_flags, false, + false, false, false, false); os->set_found_in_sections_clause(); + if (section_type == Script_sections::ST_NOLOAD) + os->set_is_noload(); return os; } @@ -990,6 +1249,16 @@ Layout::layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags) } } +// Create automatic note sections. + +void +Layout::create_notes() +{ + this->create_gold_note(); + this->create_executable_stack_info(); + this->create_build_id(); +} + // Create the dynamic sections which are needed before we read the // relocs. @@ -1003,12 +1272,14 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab) elfcpp::SHT_DYNAMIC, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - false); - this->dynamic_section_->set_is_relro(); + false, false, true, + true, false, false); - symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0, - elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, - elfcpp::STV_HIDDEN, 0, false, false); + this->dynamic_symbol_ = + symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED, + this->dynamic_section_, 0, 0, + elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, false, false); this->dynamic_data_ = new Output_data_dynamic(&this->dynpool_); @@ -1027,19 +1298,17 @@ Layout::define_section_symbols(Symbol_table* symtab) ++p) { const char* const name = (*p)->name(); - if (name[strspn(name, - ("0123456789" - "ABCDEFGHIJKLMNOPWRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "_"))] - == '\0') + if (is_cident(name)) { const std::string name_string(name); - const std::string start_name("__start_" + name_string); - const std::string stop_name("__stop_" + name_string); + const std::string start_name(cident_section_start_prefix + + name_string); + const std::string stop_name(cident_section_stop_prefix + + name_string); symtab->define_in_output_data(start_name.c_str(), NULL, // version + Symbol_table::PREDEFINED, *p, 0, // value 0, // symsize @@ -1052,6 +1321,7 @@ Layout::define_section_symbols(Symbol_table* symtab) symtab->define_in_output_data(stop_name.c_str(), NULL, // version + Symbol_table::PREDEFINED, *p, 0, // value 0, // symsize @@ -1120,6 +1390,249 @@ Layout::find_first_load_seg() return load_seg; } +// Save states of all current output segments. Store saved states +// in SEGMENT_STATES. + +void +Layout::save_segments(Segment_states* segment_states) +{ + for (Segment_list::const_iterator p = this->segment_list_.begin(); + p != this->segment_list_.end(); + ++p) + { + Output_segment* segment = *p; + // Shallow copy. + Output_segment* copy = new Output_segment(*segment); + (*segment_states)[segment] = copy; + } +} + +// Restore states of output segments and delete any segment not found in +// SEGMENT_STATES. + +void +Layout::restore_segments(const Segment_states* segment_states) +{ + // Go through the segment list and remove any segment added in the + // relaxation loop. + this->tls_segment_ = NULL; + this->relro_segment_ = NULL; + Segment_list::iterator list_iter = this->segment_list_.begin(); + while (list_iter != this->segment_list_.end()) + { + Output_segment* segment = *list_iter; + Segment_states::const_iterator states_iter = + segment_states->find(segment); + if (states_iter != segment_states->end()) + { + const Output_segment* copy = states_iter->second; + // Shallow copy to restore states. + *segment = *copy; + + // Also fix up TLS and RELRO segment pointers as appropriate. + if (segment->type() == elfcpp::PT_TLS) + this->tls_segment_ = segment; + else if (segment->type() == elfcpp::PT_GNU_RELRO) + this->relro_segment_ = segment; + + ++list_iter; + } + else + { + list_iter = this->segment_list_.erase(list_iter); + // This is a segment created during section layout. It should be + // safe to remove it since we should have removed all pointers to it. + delete segment; + } + } +} + +// Clean up after relaxation so that sections can be laid out again. + +void +Layout::clean_up_after_relaxation() +{ + // Restore the segments to point state just prior to the relaxation loop. + Script_sections* script_section = this->script_options_->script_sections(); + script_section->release_segments(); + this->restore_segments(this->segment_states_); + + // Reset section addresses and file offsets + for (Section_list::iterator p = this->section_list_.begin(); + p != this->section_list_.end(); + ++p) + { + (*p)->restore_states(); + + // If an input section changes size because of relaxation, + // we need to adjust the section offsets of all input sections. + // after such a section. + if ((*p)->section_offsets_need_adjustment()) + (*p)->adjust_section_offsets(); + + (*p)->reset_address_and_file_offset(); + } + + // Reset special output object address and file offsets. + for (Data_list::iterator p = this->special_output_list_.begin(); + p != this->special_output_list_.end(); + ++p) + (*p)->reset_address_and_file_offset(); + + // A linker script may have created some output section data objects. + // They are useless now. + for (Output_section_data_list::const_iterator p = + this->script_output_section_data_list_.begin(); + p != this->script_output_section_data_list_.end(); + ++p) + delete *p; + this->script_output_section_data_list_.clear(); +} + +// Prepare for relaxation. + +void +Layout::prepare_for_relaxation() +{ + // Create an relaxation debug check if in debugging mode. + if (is_debugging_enabled(DEBUG_RELAXATION)) + this->relaxation_debug_check_ = new Relaxation_debug_check(); + + // Save segment states. + this->segment_states_ = new Segment_states(); + this->save_segments(this->segment_states_); + + for(Section_list::const_iterator p = this->section_list_.begin(); + p != this->section_list_.end(); + ++p) + (*p)->save_states(); + + if (is_debugging_enabled(DEBUG_RELAXATION)) + this->relaxation_debug_check_->check_output_data_for_reset_values( + this->section_list_, this->special_output_list_); + + // Also enable recording of output section data from scripts. + this->record_output_section_data_from_script_ = true; +} + +// Relaxation loop body: If target has no relaxation, this runs only once +// Otherwise, the target relaxation hook is called at the end of +// each iteration. If the hook returns true, it means re-layout of +// section is required. +// +// The number of segments created by a linking script without a PHDRS +// clause may be affected by section sizes and alignments. There is +// a remote chance that relaxation causes different number of PT_LOAD +// segments are created and sections are attached to different segments. +// Therefore, we always throw away all segments created during section +// layout. In order to be able to restart the section layout, we keep +// a copy of the segment list right before the relaxation loop and use +// that to restore the segments. +// +// PASS is the current relaxation pass number. +// SYMTAB is a symbol table. +// PLOAD_SEG is the address of a pointer for the load segment. +// PHDR_SEG is a pointer to the PHDR segment. +// SEGMENT_HEADERS points to the output segment header. +// FILE_HEADER points to the output file header. +// PSHNDX is the address to store the output section index. + +off_t inline +Layout::relaxation_loop_body( + int pass, + Target* target, + Symbol_table* symtab, + Output_segment** pload_seg, + Output_segment* phdr_seg, + Output_segment_headers* segment_headers, + Output_file_header* file_header, + unsigned int* pshndx) +{ + // If this is not the first iteration, we need to clean up after + // relaxation so that we can lay out the sections again. + if (pass != 0) + this->clean_up_after_relaxation(); + + // If there is a SECTIONS clause, put all the input sections into + // the required order. + Output_segment* load_seg; + if (this->script_options_->saw_sections_clause()) + load_seg = this->set_section_addresses_from_script(symtab); + else if (parameters->options().relocatable()) + load_seg = NULL; + else + load_seg = this->find_first_load_seg(); + + if (parameters->options().oformat_enum() + != General_options::OBJECT_FORMAT_ELF) + load_seg = NULL; + + // If the user set the address of the text segment, that may not be + // compatible with putting the segment headers and file headers into + // that segment. + if (parameters->options().user_set_Ttext()) + load_seg = NULL; + + gold_assert(phdr_seg == NULL + || load_seg != NULL + || this->script_options_->saw_sections_clause()); + + // If the address of the load segment we found has been set by + // --section-start rather than by a script, then we don't want to + // use it for the file and segment headers. + if (load_seg != NULL + && load_seg->are_addresses_set() + && !this->script_options_->saw_sections_clause()) + load_seg = NULL; + + // Lay out the segment headers. + if (!parameters->options().relocatable()) + { + gold_assert(segment_headers != NULL); + if (load_seg != NULL) + load_seg->add_initial_output_data(segment_headers); + if (phdr_seg != NULL) + phdr_seg->add_initial_output_data(segment_headers); + } + + // Lay out the file header. + if (load_seg != NULL) + load_seg->add_initial_output_data(file_header); + + if (this->script_options_->saw_phdrs_clause() + && !parameters->options().relocatable()) + { + // Support use of FILEHDRS and PHDRS attachments in a PHDRS + // clause in a linker script. + Script_sections* ss = this->script_options_->script_sections(); + ss->put_headers_in_phdrs(file_header, segment_headers); + } + + // We set the output section indexes in set_segment_offsets and + // set_section_indexes. + *pshndx = 1; + + // Set the file offsets of all the segments, and all the sections + // they contain. + off_t off; + if (!parameters->options().relocatable()) + off = this->set_segment_offsets(target, load_seg, pshndx); + else + off = this->set_relocatable_section_offsets(file_header, pshndx); + + // Verify that the dummy relaxation does not change anything. + if (is_debugging_enabled(DEBUG_RELAXATION)) + { + if (pass == 0) + this->relaxation_debug_check_->read_sections(this->section_list_); + else + this->relaxation_debug_check_->verify_sections(this->section_list_); + } + + *pload_seg = load_seg; + return off; +} + // Finalize the layout. When this is called, we have created all the // output sections and all the output segments which are based on // input sections. We have several things to do, and we have to do @@ -1156,13 +1669,11 @@ off_t Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, Target* target, const Task* task) { - target->finalize_sections(this); + target->finalize_sections(this, input_objects, symtab); this->count_local_symbols(task, input_objects); - this->create_gold_note(); - this->create_executable_stack_info(target); - this->create_build_id(); + this->link_stabs_sections(); Output_segment* phdr_seg = NULL; if (!parameters->options().relocatable() && !parameters->doing_static_link()) @@ -1202,67 +1713,57 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // dynamic string table is complete. this->create_version_sections(&versions, symtab, local_dynamic_count, dynamic_symbols, dynstr); - } - // If there is a SECTIONS clause, put all the input sections into - // the required order. - Output_segment* load_seg; - if (this->script_options_->saw_sections_clause()) - load_seg = this->set_section_addresses_from_script(symtab); - else if (parameters->options().relocatable()) - load_seg = NULL; - else - load_seg = this->find_first_load_seg(); - - if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF) - load_seg = NULL; - - gold_assert(phdr_seg == NULL || load_seg != NULL); - - // Lay out the segment headers. - Output_segment_headers* segment_headers; - if (parameters->options().relocatable()) - segment_headers = NULL; - else + // Set the size of the _DYNAMIC symbol. We can't do this until + // after we call create_version_sections. + this->set_dynamic_symbol_size(symtab); + } + + if (this->incremental_inputs_) { - segment_headers = new Output_segment_headers(this->segment_list_); - if (load_seg != NULL) - load_seg->add_initial_output_data(segment_headers); - if (phdr_seg != NULL) - phdr_seg->add_initial_output_data(segment_headers); + this->incremental_inputs_->finalize(); + this->create_incremental_info_sections(); } + // Create segment headers. + Output_segment_headers* segment_headers = + (parameters->options().relocatable() + ? NULL + : new Output_segment_headers(this->segment_list_)); + // Lay out the file header. - Output_file_header* file_header; - file_header = new Output_file_header(target, symtab, segment_headers, - this->options_.entry()); - if (load_seg != NULL) - load_seg->add_initial_output_data(file_header); + Output_file_header* file_header + = new Output_file_header(target, symtab, segment_headers, + parameters->options().entry()); this->special_output_list_.push_back(file_header); if (segment_headers != NULL) this->special_output_list_.push_back(segment_headers); - if (this->script_options_->saw_phdrs_clause() - && !parameters->options().relocatable()) + // Find approriate places for orphan output sections if we are using + // a linker script. + if (this->script_options_->saw_sections_clause()) + this->place_orphan_sections_in_script(); + + Output_segment* load_seg; + off_t off; + unsigned int shndx; + int pass = 0; + + // Take a snapshot of the section layout as needed. + if (target->may_relax()) + this->prepare_for_relaxation(); + + // Run the relaxation loop to lay out sections. + do { - // Support use of FILEHDRS and PHDRS attachments in a PHDRS - // clause in a linker script. - Script_sections* ss = this->script_options_->script_sections(); - ss->put_headers_in_phdrs(file_header, segment_headers); + off = this->relaxation_loop_body(pass, target, symtab, &load_seg, + phdr_seg, segment_headers, file_header, + &shndx); + pass++; } - - // We set the output section indexes in set_segment_offsets and - // set_section_indexes. - unsigned int shndx = 1; - - // Set the file offsets of all the segments, and all the sections - // they contain. - off_t off; - if (!parameters->options().relocatable()) - off = this->set_segment_offsets(target, load_seg, &shndx); - else - off = this->set_relocatable_section_offsets(file_header, &shndx); + while (target->may_relax() + && target->relax(pass, input_objects, symtab, this)); // Set the file offsets of all the non-data sections we've seen so // far which don't have to wait for the input sections. We need @@ -1315,13 +1816,15 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, } // Create a note header following the format defined in the ELF ABI. -// NAME is the name, NOTE_TYPE is the type, DESCSZ is the size of the -// descriptor. ALLOCATE is true if the section should be allocated in -// memory. This returns the new note section. It sets -// *TRAILING_PADDING to the number of trailing zero bytes required. +// NAME is the name, NOTE_TYPE is the type, SECTION_NAME is the name +// of the section to create, DESCSZ is the size of the descriptor. +// ALLOCATE is true if the section should be allocated in memory. +// This returns the new note section. It sets *TRAILING_PADDING to +// the number of trailing zero bytes required. Output_section* -Layout::create_note(const char* name, int note_type, size_t descsz, +Layout::create_note(const char* name, int note_type, + const char* section_name, size_t descsz, bool allocate, size_t* trailing_padding) { // Authorities all agree that the values in a .note field should @@ -1388,13 +1891,16 @@ Layout::create_note(const char* name, int note_type, size_t descsz, memcpy(buffer + 3 * (size / 8), name, namesz); - const char* note_name = this->namepool_.add(".note", false, NULL); elfcpp::Elf_Xword flags = 0; if (allocate) flags = elfcpp::SHF_ALLOC; - Output_section* os = this->make_output_section(note_name, - elfcpp::SHT_NOTE, - flags); + Output_section* os = this->choose_output_section(NULL, section_name, + elfcpp::SHT_NOTE, + flags, false, false, + false, false, false, false); + if (os == NULL) + return NULL; + Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz, size / 8, "** note header"); @@ -1418,7 +1924,10 @@ Layout::create_gold_note() size_t trailing_padding; Output_section *os = this->create_note("GNU", elfcpp::NT_GNU_GOLD_VERSION, - desc.size(), false, &trailing_padding); + ".note.gnu.gold-version", desc.size(), + false, &trailing_padding); + if (os == NULL) + return; Output_section_data* posd = new Output_data_const(desc, 4); os->add_output_section_data(posd); @@ -1443,11 +1952,11 @@ Layout::create_gold_note() // library, we create a PT_GNU_STACK segment. void -Layout::create_executable_stack_info(const Target* target) +Layout::create_executable_stack_info() { bool is_stack_executable; - if (this->options_.is_execstack_set()) - is_stack_executable = this->options_.is_stack_executable(); + if (parameters->options().is_execstack_set()) + is_stack_executable = parameters->options().is_stack_executable(); else if (!this->input_with_gnu_stack_note_) return; else @@ -1455,7 +1964,8 @@ Layout::create_executable_stack_info(const Target* target) if (this->input_requires_executable_stack_) is_stack_executable = true; else if (this->input_without_gnu_stack_note_) - is_stack_executable = target->is_default_stack_executable(); + is_stack_executable = + parameters->target().is_default_stack_executable(); else is_stack_executable = false; } @@ -1466,7 +1976,8 @@ Layout::create_executable_stack_info(const Target* target) elfcpp::Elf_Xword flags = 0; if (is_stack_executable) flags |= elfcpp::SHF_EXECINSTR; - this->make_output_section(name, elfcpp::SHT_PROGBITS, flags); + this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false, + false, false, false, false); } else { @@ -1550,7 +2061,10 @@ Layout::create_build_id() // Create the note. size_t trailing_padding; Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_BUILD_ID, - descsz, true, &trailing_padding); + ".note.gnu.build-id", descsz, true, + &trailing_padding); + if (os == NULL) + return; if (!desc.empty()) { @@ -1573,10 +2087,76 @@ Layout::create_build_id() gold_assert(trailing_padding == 0); this->build_id_note_ = new Output_data_zero_fill(descsz, 4); os->add_output_section_data(this->build_id_note_); - os->set_after_input_sections(); } } +// If we have both .stabXX and .stabXXstr sections, then the sh_link +// field of the former should point to the latter. I'm not sure who +// started this, but the GNU linker does it, and some tools depend +// upon it. + +void +Layout::link_stabs_sections() +{ + if (!this->have_stabstr_section_) + return; + + for (Section_list::iterator p = this->section_list_.begin(); + p != this->section_list_.end(); + ++p) + { + if ((*p)->type() != elfcpp::SHT_STRTAB) + continue; + + const char* name = (*p)->name(); + if (strncmp(name, ".stab", 5) != 0) + continue; + + size_t len = strlen(name); + if (strcmp(name + len - 3, "str") != 0) + continue; + + std::string stab_name(name, len - 3); + Output_section* stab_sec; + stab_sec = this->find_output_section(stab_name.c_str()); + if (stab_sec != NULL) + stab_sec->set_link_section(*p); + } +} + +// Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed +// for the next run of incremental linking to check what has changed. + +void +Layout::create_incremental_info_sections() +{ + gold_assert(this->incremental_inputs_ != NULL); + + // Add the .gnu_incremental_inputs section. + const char *incremental_inputs_name = + this->namepool_.add(".gnu_incremental_inputs", false, NULL); + Output_section* inputs_os = + this->make_output_section(incremental_inputs_name, + elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0, + false, false, false, false, false); + Output_section_data* posd = + this->incremental_inputs_->create_incremental_inputs_section_data(); + inputs_os->add_output_section_data(posd); + + // Add the .gnu_incremental_strtab section. + const char *incremental_strtab_name = + this->namepool_.add(".gnu_incremental_strtab", false, NULL); + Output_section* strtab_os = this->make_output_section(incremental_strtab_name, + elfcpp::SHT_STRTAB, + 0, false, false, + false, false, false); + Output_data_strtab* strtab_data = + new Output_data_strtab(this->incremental_inputs_->get_stringpool()); + strtab_os->add_output_section_data(strtab_data); + + inputs_os->set_link_section(strtab_data); +} + // Return whether SEG1 should be before SEG2 in the output file. This // is based entirely on the segment type and flags. When this is // called the segment addresses has normally not yet been set. @@ -1670,14 +2250,25 @@ Layout::segment_precedes(const Output_segment* seg1, else if (seg2->are_addresses_set()) return false; - // We sort PT_LOAD segments based on the flags. Readonly segments - // come before writable segments. Then writable segments with data - // come before writable segments without data. Then executable - // segments come before non-executable segments. Then the unlikely - // case of a non-readable segment comes before the normal case of a - // readable segment. If there are multiple segments with the same - // type and flags, we require that the address be set, and we sort - // by virtual address and then physical address. + // A segment which holds large data comes after a segment which does + // not hold large data. + if (seg1->is_large_data_segment()) + { + if (!seg2->is_large_data_segment()) + return false; + } + else if (seg2->is_large_data_segment()) + return true; + + // Otherwise, we sort PT_LOAD segments based on the flags. Readonly + // segments come before writable segments. Then writable segments + // with data come before writable segments without data. Then + // executable segments come before non-executable segments. Then + // the unlikely case of a non-readable segment comes before the + // normal case of a readable segment. If there are multiple + // segments with the same type and flags, we require that the + // address be set, and we sort by virtual address and then physical + // address. if ((flags1 & elfcpp::PF_W) != (flags2 & elfcpp::PF_W)) return (flags1 & elfcpp::PF_W) == 0; if ((flags1 & elfcpp::PF_W) != 0 @@ -1693,6 +2284,19 @@ Layout::segment_precedes(const Output_segment* seg1, gold_unreachable(); } +// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE. + +static off_t +align_file_offset(off_t off, uint64_t addr, uint64_t abi_pagesize) +{ + uint64_t unsigned_off = off; + uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1)) + | (addr & (abi_pagesize - 1))); + if (aligned_off < unsigned_off) + aligned_off += abi_pagesize; + return aligned_off; +} + // Set the file offsets of all the segments, and all the sections they // contain. They have all been created. LOAD_SEG must be be laid out // first. Return the offset of the data to follow. @@ -1708,9 +2312,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // Find the PT_LOAD segments, and set their addresses and offsets // and their section's addresses and offsets. uint64_t addr; - if (this->options_.user_set_Ttext()) - addr = this->options_.Ttext(); - else if (parameters->options().shared()) + if (parameters->options().user_set_Ttext()) + addr = parameters->options().Ttext(); + else if (parameters->options().output_is_position_independent()) addr = 0; else addr = target->default_text_segment_address(); @@ -1731,6 +2335,10 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, } } + unsigned int increase_relro = this->increase_relro_; + if (this->script_options_->saw_sections_clause()) + increase_relro = 0; + const bool check_sections = parameters->options().check_sections(); Output_segment* last_load_segment = NULL; @@ -1752,19 +2360,19 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // the physical address. addr = (*p)->paddr(); } - else if (this->options_.user_set_Tdata() + else if (parameters->options().user_set_Tdata() && ((*p)->flags() & elfcpp::PF_W) != 0 - && (!this->options_.user_set_Tbss() + && (!parameters->options().user_set_Tbss() || (*p)->has_any_data_sections())) { - addr = this->options_.Tdata(); + addr = parameters->options().Tdata(); are_addresses_set = true; } - else if (this->options_.user_set_Tbss() + else if (parameters->options().user_set_Tbss() && ((*p)->flags() & elfcpp::PF_W) != 0 && !(*p)->has_any_data_sections()) { - addr = this->options_.Tbss(); + addr = parameters->options().Tbss(); are_addresses_set = true; } @@ -1779,22 +2387,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, && !parameters->options().omagic()) (*p)->set_minimum_p_align(common_pagesize); - if (are_addresses_set) - { - if (!parameters->options().nmagic() - && !parameters->options().omagic()) - { - // Adjust the file offset to the same address modulo - // the page size. - uint64_t unsigned_off = off; - uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1)) - | (addr & (abi_pagesize - 1))); - if (aligned_off < unsigned_off) - aligned_off += abi_pagesize; - off = aligned_off; - } - } - else + if (!are_addresses_set) { // If the last segment was readonly, and this one is // not, then skip the address forward one page, @@ -1815,8 +2408,26 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1)); } + if (!parameters->options().nmagic() + && !parameters->options().omagic()) + off = align_file_offset(off, addr, abi_pagesize); + else if (load_seg == NULL) + { + // This is -N or -n with a section script which prevents + // us from using a load segment. We need to ensure that + // the file offset is aligned to the alignment of the + // segment. This is because the linker script + // implicitly assumed a zero offset. If we don't align + // here, then the alignment of the sections in the + // linker script may not match the alignment of the + // sections in the set_section_addresses call below, + // causing an error about dot moving backward. + off = align_address(off, (*p)->maximum_alignment()); + } + unsigned int shndx_hold = *pshndx; uint64_t new_addr = (*p)->set_section_addresses(this, false, addr, + increase_relro, &off, pshndx); // Now that we know the size of this segment, we may be able @@ -1841,7 +2452,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, addr = align_address(aligned_addr, common_pagesize); addr = align_address(addr, (*p)->maximum_alignment()); off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1)); + off = align_file_offset(off, addr, abi_pagesize); new_addr = (*p)->set_section_addresses(this, true, addr, + increase_relro, &off, pshndx); } } @@ -1879,7 +2492,9 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, ++p) { if ((*p)->type() != elfcpp::PT_LOAD) - (*p)->set_offset(); + (*p)->set_offset((*p)->type() == elfcpp::PT_GNU_RELRO + ? increase_relro + : 0); } // Set the TLS offsets for each section in the PT_TLS segment. @@ -2007,6 +2622,16 @@ Layout::set_section_addresses_from_script(Symbol_table* symtab) { Script_sections* ss = this->script_options_->script_sections(); gold_assert(ss->saw_sections_clause()); + return this->script_options_->set_section_addresses(symtab, this); +} + +// Place the orphan sections in the linker script. + +void +Layout::place_orphan_sections_in_script() +{ + Script_sections* ss = this->script_options_->script_sections(); + gold_assert(ss->saw_sections_clause()); // Place each orphaned output section in the script. for (Section_list::iterator p = this->section_list_.begin(); @@ -2016,8 +2641,6 @@ Layout::set_section_addresses_from_script(Symbol_table* symtab) if (!(*p)->found_in_sections_clause()) ss->place_orphan(*p); } - - return this->script_options_->set_section_addresses(symtab, this); } // Count the local symbols in the regular symbol table and the dynamic @@ -2109,13 +2732,13 @@ Layout::create_symtab_sections(const Input_objects* input_objects, ++p) { unsigned int index = (*p)->finalize_local_symbols(local_symbol_index, - off); + off, symtab); off += (index - local_symbol_index) * symsize; local_symbol_index = index; } unsigned int local_symcount = local_symbol_index; - gold_assert(local_symcount * symsize == off - startoff); + gold_assert(static_cast<off_t>(local_symcount * symsize) == off - startoff); off_t dynoff; size_t dyn_global_index; @@ -2146,7 +2769,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, const char* symtab_name = this->namepool_.add(".symtab", false, NULL); Output_section* osymtab = this->make_output_section(symtab_name, elfcpp::SHT_SYMTAB, - 0); + 0, false, false, + false, false, false); this->symtab_section_ = osymtab; Output_section_data* pos = new Output_data_fixed_space(off - startoff, @@ -2167,7 +2791,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, false, NULL); Output_section* osymtab_xindex = this->make_output_section(symtab_xindex_name, - elfcpp::SHT_SYMTAB_SHNDX, 0); + elfcpp::SHT_SYMTAB_SHNDX, 0, false, + false, false, false, false); size_t symcount = (off - startoff) / symsize; this->symtab_xindex_ = new Output_symtab_xindex(symcount); @@ -2189,7 +2814,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, const char* strtab_name = this->namepool_.add(".strtab", false, NULL); Output_section* ostrtab = this->make_output_section(strtab_name, elfcpp::SHT_STRTAB, - 0); + 0, false, false, + false, false, false); Output_section_data* pstr = new Output_data_strtab(&this->sympool_); ostrtab->add_output_section_data(pstr); @@ -2216,12 +2842,18 @@ Layout::create_shstrtab() const char* name = this->namepool_.add(".shstrtab", false, NULL); - Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0); + Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0, + false, false, false, false, + false); - // We can't write out this section until we've set all the section - // names, and we don't set the names of compressed output sections - // until relocations are complete. - os->set_after_input_sections(); + if (strcmp(parameters->options().compress_debug_sections(), "none") != 0) + { + // We can't write out this section until we've set all the + // section names, and we don't set the names of compressed + // output sections until relocations are complete. FIXME: With + // the current names we use, this is unnecessary. + os->set_after_input_sections(); + } Output_section_data* posd = new Output_data_strtab(&this->namepool_); os->add_output_section_data(posd); @@ -2329,7 +2961,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* dynsym = this->choose_output_section(NULL, ".dynsym", elfcpp::SHT_DYNSYM, elfcpp::SHF_ALLOC, - false); + false, false, true, + false, false, false); Output_section_data* odata = new Output_data_fixed_space(index * symsize, align, @@ -2359,7 +2992,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, this->choose_output_section(NULL, ".dynsym_shndx", elfcpp::SHT_SYMTAB_SHNDX, elfcpp::SHF_ALLOC, - false); + false, false, true, false, false, false); this->dynsym_xindex_ = new Output_symtab_xindex(index); @@ -2382,7 +3015,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* dynstr = this->choose_output_section(NULL, ".dynstr", elfcpp::SHT_STRTAB, elfcpp::SHF_ALLOC, - false); + false, false, true, + false, false, false); Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); dynstr->add_output_section_data(strdata); @@ -2408,6 +3042,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* hashsec = this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, elfcpp::SHF_ALLOC, + false, false, true, + false, false, false); Output_section_data* hashdata = new Output_data_const_buffer(phash, @@ -2433,6 +3069,8 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, elfcpp::SHF_ALLOC, + false, false, true, + false, false, false); Output_section_data* hashdata = new Output_data_const_buffer(phash, @@ -2442,7 +3080,12 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, hashsec->add_output_section_data(hashdata); hashsec->set_link_section(dynsym); - hashsec->set_entsize(4); + + // For a 64-bit target, the entries in .gnu.hash do not have a + // uniform size, so we only set the entry size for a 32-bit + // target. + if (parameters->target().get_size() == 32) + hashsec->set_entsize(4); odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); } @@ -2531,7 +3174,8 @@ Layout::sized_create_version_sections( Output_section* vsec = this->choose_output_section(NULL, ".gnu.version", elfcpp::SHT_GNU_versym, elfcpp::SHF_ALLOC, - false); + false, false, true, + false, false, false); unsigned char* vbuf; unsigned int vsize; @@ -2556,6 +3200,7 @@ Layout::sized_create_version_sections( vdsec= this->choose_output_section(NULL, ".gnu.version_d", elfcpp::SHT_GNU_verdef, elfcpp::SHF_ALLOC, + false, false, true, false, false, false); unsigned char* vdbuf; @@ -2581,6 +3226,7 @@ Layout::sized_create_version_sections( vnsec = this->choose_output_section(NULL, ".gnu.version_r", elfcpp::SHT_GNU_verneed, elfcpp::SHF_ALLOC, + false, false, true, false, false, false); unsigned char* vnbuf; @@ -2607,7 +3253,7 @@ Layout::sized_create_version_sections( void Layout::create_interp(const Target* target) { - const char* interp = this->options_.dynamic_linker(); + const char* interp = parameters->options().dynamic_linker(); if (interp == NULL) { interp = target->dynamic_linker(); @@ -2621,14 +3267,108 @@ Layout::create_interp(const Target* target) Output_section* osec = this->choose_output_section(NULL, ".interp", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false); + false, true, true, + false, false, false); osec->add_output_section_data(odata); if (!this->script_options_->saw_phdrs_clause()) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP, elfcpp::PF_R); - oseg->add_output_section(osec, elfcpp::PF_R); + oseg->add_output_section(osec, elfcpp::PF_R, false); + } +} + +// Add dynamic tags for the PLT and the dynamic relocs. This is +// called by the target-specific code. This does nothing if not doing +// a dynamic link. + +// USE_REL is true for REL relocs rather than RELA relocs. + +// If PLT_GOT is not NULL, then DT_PLTGOT points to it. + +// If PLT_REL is not NULL, it is used for DT_PLTRELSZ, and DT_JMPREL, +// and we also set DT_PLTREL. We use PLT_REL's output section, since +// some targets have multiple reloc sections in PLT_REL. + +// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA, +// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT. + +// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an +// executable. + +void +Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, + const Output_data* plt_rel, + const Output_data_reloc_generic* dyn_rel, + bool add_debug, bool dynrel_includes_plt) +{ + Output_data_dynamic* odyn = this->dynamic_data_; + if (odyn == NULL) + return; + + if (plt_got != NULL && plt_got->output_section() != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, plt_got); + + if (plt_rel != NULL && plt_rel->output_section() != NULL) + { + odyn->add_section_size(elfcpp::DT_PLTRELSZ, plt_rel->output_section()); + odyn->add_section_address(elfcpp::DT_JMPREL, plt_rel->output_section()); + odyn->add_constant(elfcpp::DT_PLTREL, + use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA); + } + + if (dyn_rel != NULL && dyn_rel->output_section() != NULL) + { + odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA, + dyn_rel); + if (plt_rel != NULL && dynrel_includes_plt) + odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ, + dyn_rel, plt_rel); + else + odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ, + dyn_rel); + const int size = parameters->target().get_size(); + elfcpp::DT rel_tag; + int rel_size; + if (use_rel) + { + rel_tag = elfcpp::DT_RELENT; + if (size == 32) + rel_size = Reloc_types<elfcpp::SHT_REL, 32, false>::reloc_size; + else if (size == 64) + rel_size = Reloc_types<elfcpp::SHT_REL, 64, false>::reloc_size; + else + gold_unreachable(); + } + else + { + rel_tag = elfcpp::DT_RELAENT; + if (size == 32) + rel_size = Reloc_types<elfcpp::SHT_RELA, 32, false>::reloc_size; + else if (size == 64) + rel_size = Reloc_types<elfcpp::SHT_RELA, 64, false>::reloc_size; + else + gold_unreachable(); + } + odyn->add_constant(rel_tag, rel_size); + + if (parameters->options().combreloc()) + { + size_t c = dyn_rel->relative_reloc_count(); + if (c > 0) + odyn->add_constant((use_rel + ? elfcpp::DT_RELCOUNT + : elfcpp::DT_RELACOUNT), + c); + } + } + + if (add_debug && !parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); } } @@ -2644,7 +3384,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, (elfcpp::PF_R | elfcpp::PF_W)); oseg->add_output_section(this->dynamic_section_, - elfcpp::PF_R | elfcpp::PF_W); + elfcpp::PF_R | elfcpp::PF_W, + false); } Output_data_dynamic* const odyn = this->dynamic_data_; @@ -2653,30 +3394,57 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, p != input_objects->dynobj_end(); ++p) { - // FIXME: Handle --as-needed. + if (!(*p)->is_needed() + && (*p)->input_file()->options().as_needed()) + { + // This dynamic object was linked with --as-needed, but it + // is not needed. + continue; + } + odyn->add_string(elfcpp::DT_NEEDED, (*p)->soname()); } if (parameters->options().shared()) { - const char* soname = this->options_.soname(); + const char* soname = parameters->options().soname(); if (soname != NULL) odyn->add_string(elfcpp::DT_SONAME, soname); } - // FIXME: Support --init and --fini. - Symbol* sym = symtab->lookup("_init"); + Symbol* sym = symtab->lookup(parameters->options().init()); if (sym != NULL && sym->is_defined() && !sym->is_from_dynobj()) odyn->add_symbol(elfcpp::DT_INIT, sym); - sym = symtab->lookup("_fini"); + sym = symtab->lookup(parameters->options().fini()); if (sym != NULL && sym->is_defined() && !sym->is_from_dynobj()) odyn->add_symbol(elfcpp::DT_FINI, sym); - // FIXME: Support DT_INIT_ARRAY and DT_FINI_ARRAY. - + // Look for .init_array, .preinit_array and .fini_array by checking + // section types. + for(Layout::Section_list::const_iterator p = this->section_list_.begin(); + p != this->section_list_.end(); + ++p) + switch((*p)->type()) + { + case elfcpp::SHT_FINI_ARRAY: + odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p); + odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p); + break; + case elfcpp::SHT_INIT_ARRAY: + odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p); + odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p); + break; + case elfcpp::SHT_PREINIT_ARRAY: + odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p); + odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p); + break; + default: + break; + } + // Add a DT_RPATH entry if needed. - const General_options::Dir_list& rpath(this->options_.rpath()); + const General_options::Dir_list& rpath(parameters->options().rpath()); if (!rpath.empty()) { std::string rpath_val; @@ -2750,9 +3518,25 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, // Add a DT_TEXTREL for compatibility with older loaders. odyn->add_constant(elfcpp::DT_TEXTREL, 0); flags |= elfcpp::DF_TEXTREL; + + if (parameters->options().text()) + gold_error(_("read-only segment has dynamic relocations")); + else if (parameters->options().warn_shared_textrel() + && parameters->options().shared()) + gold_warning(_("shared library text segment is not shareable")); } if (parameters->options().shared() && this->has_static_tls()) flags |= elfcpp::DF_STATIC_TLS; + if (parameters->options().origin()) + flags |= elfcpp::DF_ORIGIN; + if (parameters->options().Bsymbolic()) + { + flags |= elfcpp::DF_SYMBOLIC; + // Add DT_SYMBOLIC for compatibility with older loaders. + odyn->add_constant(elfcpp::DT_SYMBOLIC, 0); + } + if (parameters->options().now()) + flags |= elfcpp::DF_BIND_NOW; odyn->add_constant(elfcpp::DT_FLAGS, flags); flags = 0; @@ -2774,61 +3558,88 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, flags &= ~(elfcpp::DF_1_INITFIRST | elfcpp::DF_1_NODELETE | elfcpp::DF_1_NOOPEN); + if (parameters->options().origin()) + flags |= elfcpp::DF_1_ORIGIN; + if (parameters->options().now()) + flags |= elfcpp::DF_1_NOW; if (flags) odyn->add_constant(elfcpp::DT_FLAGS_1, flags); } -// The mapping of .gnu.linkonce section names to real section names. +// Set the size of the _DYNAMIC symbol table to be the size of the +// dynamic data. + +void +Layout::set_dynamic_symbol_size(const Symbol_table* symtab) +{ + Output_data_dynamic* const odyn = this->dynamic_data_; + odyn->finalize_data_size(); + off_t data_size = odyn->data_size(); + const int size = parameters->target().get_size(); + if (size == 32) + symtab->get_sized_symbol<32>(this->dynamic_symbol_)->set_symsize(data_size); + else if (size == 64) + symtab->get_sized_symbol<64>(this->dynamic_symbol_)->set_symsize(data_size); + else + gold_unreachable(); +} + +// The mapping of input section name prefixes to output section names. +// In some cases one prefix is itself a prefix of another prefix; in +// such a case the longer prefix must come first. These prefixes are +// based on the GNU linker default ELF linker script. #define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 } -const Layout::Linkonce_mapping Layout::linkonce_mapping[] = -{ - MAPPING_INIT("d.rel.ro.local", ".data.rel.ro.local"), // Before "d.rel.ro". - MAPPING_INIT("d.rel.ro", ".data.rel.ro"), // Before "d". - MAPPING_INIT("t", ".text"), - MAPPING_INIT("r", ".rodata"), - MAPPING_INIT("d", ".data"), - MAPPING_INIT("b", ".bss"), - MAPPING_INIT("s", ".sdata"), - MAPPING_INIT("sb", ".sbss"), - MAPPING_INIT("s2", ".sdata2"), - MAPPING_INIT("sb2", ".sbss2"), - MAPPING_INIT("wi", ".debug_info"), - MAPPING_INIT("td", ".tdata"), - MAPPING_INIT("tb", ".tbss"), - MAPPING_INIT("lr", ".lrodata"), - MAPPING_INIT("l", ".ldata"), - MAPPING_INIT("lb", ".lbss"), +const Layout::Section_name_mapping Layout::section_name_mapping[] = +{ + MAPPING_INIT(".text.", ".text"), + MAPPING_INIT(".ctors.", ".ctors"), + MAPPING_INIT(".dtors.", ".dtors"), + MAPPING_INIT(".rodata.", ".rodata"), + MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"), + MAPPING_INIT(".data.rel.ro", ".data.rel.ro"), + MAPPING_INIT(".data.", ".data"), + MAPPING_INIT(".bss.", ".bss"), + MAPPING_INIT(".tdata.", ".tdata"), + MAPPING_INIT(".tbss.", ".tbss"), + MAPPING_INIT(".init_array.", ".init_array"), + MAPPING_INIT(".fini_array.", ".fini_array"), + MAPPING_INIT(".sdata.", ".sdata"), + MAPPING_INIT(".sbss.", ".sbss"), + // FIXME: In the GNU linker, .sbss2 and .sdata2 are handled + // differently depending on whether it is creating a shared library. + MAPPING_INIT(".sdata2.", ".sdata"), + MAPPING_INIT(".sbss2.", ".sbss"), + MAPPING_INIT(".lrodata.", ".lrodata"), + MAPPING_INIT(".ldata.", ".ldata"), + MAPPING_INIT(".lbss.", ".lbss"), + MAPPING_INIT(".gcc_except_table.", ".gcc_except_table"), + MAPPING_INIT(".gnu.linkonce.d.rel.ro.local.", ".data.rel.ro.local"), + MAPPING_INIT(".gnu.linkonce.d.rel.ro.", ".data.rel.ro"), + MAPPING_INIT(".gnu.linkonce.t.", ".text"), + MAPPING_INIT(".gnu.linkonce.r.", ".rodata"), + MAPPING_INIT(".gnu.linkonce.d.", ".data"), + MAPPING_INIT(".gnu.linkonce.b.", ".bss"), + MAPPING_INIT(".gnu.linkonce.s.", ".sdata"), + MAPPING_INIT(".gnu.linkonce.sb.", ".sbss"), + MAPPING_INIT(".gnu.linkonce.s2.", ".sdata"), + MAPPING_INIT(".gnu.linkonce.sb2.", ".sbss"), + MAPPING_INIT(".gnu.linkonce.wi.", ".debug_info"), + MAPPING_INIT(".gnu.linkonce.td.", ".tdata"), + MAPPING_INIT(".gnu.linkonce.tb.", ".tbss"), + MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"), + MAPPING_INIT(".gnu.linkonce.l.", ".ldata"), + MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"), + MAPPING_INIT(".ARM.extab", ".ARM.extab"), + MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"), + MAPPING_INIT(".ARM.exidx", ".ARM.exidx"), + MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"), }; #undef MAPPING_INIT -const int Layout::linkonce_mapping_count = - sizeof(Layout::linkonce_mapping) / sizeof(Layout::linkonce_mapping[0]); - -// Return the name of the output section to use for a .gnu.linkonce -// section. This is based on the default ELF linker script of the old -// GNU linker. For example, we map a name like ".gnu.linkonce.t.foo" -// to ".text". Set *PLEN to the length of the name. *PLEN is -// initialized to the length of NAME. - -const char* -Layout::linkonce_output_name(const char* name, size_t *plen) -{ - const char* s = name + sizeof(".gnu.linkonce") - 1; - if (*s != '.') - return name; - ++s; - const Linkonce_mapping* plm = linkonce_mapping; - for (int i = 0; i < linkonce_mapping_count; ++i, ++plm) - { - if (strncmp(s, plm->from, plm->fromlen) == 0 && s[plm->fromlen] == '.') - { - *plen = plm->tolen; - return plm->to; - } - } - return name; -} +const int Layout::section_name_mapping_count = + (sizeof(Layout::section_name_mapping) + / sizeof(Layout::section_name_mapping[0])); // Choose the output section name to use given an input section name. // Set *PLEN to the length of the name. *PLEN is initialized to the @@ -2837,13 +3648,6 @@ Layout::linkonce_output_name(const char* name, size_t *plen) const char* Layout::output_section_name(const char* name, size_t* plen) { - if (Layout::is_linkonce(name)) - { - // .gnu.linkonce sections are laid out as though they were named - // for the sections are placed into. - return Layout::linkonce_output_name(name, plen); - } - // gcc 4.3 generates the following sorts of section names when it // needs a section name specific to a function: // .text.FN @@ -2870,88 +3674,95 @@ Layout::output_section_name(const char* name, size_t* plen) // Also of interest: .rodata.strN.N, .rodata.cstN, both of which the // GNU linker maps to .rodata. - // The .data.rel.ro sections enable a security feature triggered by - // the -z relro option. Section which need to be relocated at - // program startup time but which may be readonly after startup are - // grouped into .data.rel.ro. They are then put into a PT_GNU_RELRO - // segment. The dynamic linker will make that segment writable, - // perform relocations, and then make it read-only. FIXME: We do - // not yet implement this optimization. - - // It is hard to handle this in a principled way. - - // These are the rules we follow: - - // If the section name has no initial '.', or no dot other than an - // initial '.', we use the name unchanged (i.e., "mysection" and - // ".text" are unchanged). - - // If the name starts with ".data.rel.ro.local" we use - // ".data.rel.ro.local". + // The .data.rel.ro sections are used with -z relro. The sections + // are recognized by name. We use the same names that the GNU + // linker does for these sections. - // If the name starts with ".data.rel.ro" we use ".data.rel.ro". + // It is hard to handle this in a principled way, so we don't even + // try. We use a table of mappings. If the input section name is + // not found in the table, we simply use it as the output section + // name. - // Otherwise, we drop the second '.' and everything that comes after - // it (i.e., ".text.XXX" becomes ".text"). - - const char* s = name; - if (*s != '.') - return name; - ++s; - const char* sdot = strchr(s, '.'); - if (sdot == NULL) - return name; - - const char* const data_rel_ro_local = ".data.rel.ro.local"; - if (strncmp(name, data_rel_ro_local, strlen(data_rel_ro_local)) == 0) - { - *plen = strlen(data_rel_ro_local); - return data_rel_ro_local; - } - - const char* const data_rel_ro = ".data.rel.ro"; - if (strncmp(name, data_rel_ro, strlen(data_rel_ro)) == 0) + const Section_name_mapping* psnm = section_name_mapping; + for (int i = 0; i < section_name_mapping_count; ++i, ++psnm) { - *plen = strlen(data_rel_ro); - return data_rel_ro; + if (strncmp(name, psnm->from, psnm->fromlen) == 0) + { + *plen = psnm->tolen; + return psnm->to; + } } - *plen = sdot - name; return name; } -// Record the signature of a comdat section, and return whether to -// include it in the link. If GROUP is true, this is a regular -// section group. If GROUP is false, this is a group signature -// derived from the name of a linkonce section. We want linkonce -// signatures and group signatures to block each other, but we don't -// want a linkonce signature to block another linkonce signature. +// Check if a comdat group or .gnu.linkonce section with the given +// NAME is selected for the link. If there is already a section, +// *KEPT_SECTION is set to point to the existing section and the +// function returns false. Otherwise, OBJECT, SHNDX, IS_COMDAT, and +// IS_GROUP_NAME are recorded for this NAME in the layout object, +// *KEPT_SECTION is set to the internal copy and the function returns +// true. bool -Layout::add_comdat(Relobj* object, unsigned int shndx, - const std::string& signature, bool group) +Layout::find_or_add_kept_section(const std::string& name, + Relobj* object, + unsigned int shndx, + bool is_comdat, + bool is_group_name, + Kept_section** kept_section) { - Kept_section kept(object, shndx, group); - std::pair<Signatures::iterator, bool> ins( - this->signatures_.insert(std::make_pair(signature, kept))); + // It's normal to see a couple of entries here, for the x86 thunk + // sections. If we see more than a few, we're linking a C++ + // program, and we resize to get more space to minimize rehashing. + if (this->signatures_.size() > 4 + && !this->resized_signatures_) + { + reserve_unordered_map(&this->signatures_, + this->number_of_input_files_ * 64); + this->resized_signatures_ = true; + } + Kept_section candidate; + std::pair<Signatures::iterator, bool> ins = + this->signatures_.insert(std::make_pair(name, candidate)); + + if (kept_section != NULL) + *kept_section = &ins.first->second; if (ins.second) { // This is the first time we've seen this signature. + ins.first->second.set_object(object); + ins.first->second.set_shndx(shndx); + if (is_comdat) + ins.first->second.set_is_comdat(); + if (is_group_name) + ins.first->second.set_is_group_name(); return true; } - if (ins.first->second.group_) + // We have already seen this signature. + + if (ins.first->second.is_group_name()) { // We've already seen a real section group with this signature. + // If the kept group is from a plugin object, and we're in the + // replacement phase, accept the new one as a replacement. + if (ins.first->second.object() == NULL + && parameters->options().plugins()->in_replacement_phase()) + { + ins.first->second.set_object(object); + ins.first->second.set_shndx(shndx); + return true; + } return false; } - else if (group) + else if (is_group_name) { // This is a real section group, and we've already seen a // linkonce section with this signature. Record that we've seen // a section group, and don't include this section group. - ins.first->second.group_ = true; + ins.first->second.set_is_group_name(); return false; } else @@ -2963,20 +3774,6 @@ Layout::add_comdat(Relobj* object, unsigned int shndx, } } -// Find the given comdat signature, and return the object and section -// index of the kept group. -Relobj* -Layout::find_kept_object(const std::string& signature, - unsigned int* pshndx) const -{ - Signatures::const_iterator p = this->signatures_.find(signature); - if (p == this->signatures_.end()) - return NULL; - if (pshndx != NULL) - *pshndx = p->second.shndx_; - return p->second.object_; -} - // Store the allocated sections into the section list. void @@ -3083,7 +3880,7 @@ Layout::write_sections_after_input_sections(Output_file* of) { off_t off = this->output_file_size_; off = this->set_section_offsets(off, POSTPROCESSING_SECTIONS_PASS); - + // Now that we've finalized the names, we can finalize the shstrab. off = this->set_section_offsets(off, @@ -3157,7 +3954,7 @@ Layout::write_build_id(Output_file* of) const void Layout::write_binary(Output_file* in) const { - gold_assert(this->options_.oformat_enum() + gold_assert(parameters->options().oformat_enum() == General_options::OBJECT_FORMAT_BINARY); // Get the size of the binary file. @@ -3299,8 +4096,8 @@ Write_symbols_task::locks(Task_locker* tl) void Write_symbols_task::run(Workqueue*) { - this->symtab_->write_globals(this->input_objects_, this->sympool_, - this->dynpool_, this->layout_->symtab_xindex(), + this->symtab_->write_globals(this->sympool_, this->dynpool_, + this->layout_->symtab_xindex(), this->layout_->dynsym_xindex(), this->of_); } diff --git a/binutils-2.19/gold/layout.h b/binutils-2.19/gold/layout.h index ca8b7c7..912be31 100644 --- a/binutils-2.19/gold/layout.h +++ b/binutils-2.19/gold/layout.h @@ -1,6 +1,6 @@ // layout.h -- lay out output file sections for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -25,6 +25,7 @@ #include <cstring> #include <list> +#include <map> #include <string> #include <utility> #include <vector> @@ -39,14 +40,18 @@ namespace gold { class General_options; +class Incremental_inputs; class Input_objects; class Mapfile; class Symbol_table; class Output_section_data; class Output_section; class Output_section_headers; +class Output_segment_headers; +class Output_file_header; class Output_segment; class Output_data; +class Output_data_reloc_generic; class Output_data_dynamic; class Output_symtab_xindex; class Output_reduced_debug_abbrev_section; @@ -89,12 +94,206 @@ class Layout_task_runner : public Task_function_runner Mapfile* mapfile_; }; +// This class holds information about the comdat group or +// .gnu.linkonce section that will be kept for a given signature. + +class Kept_section +{ + private: + // For a comdat group, we build a mapping from the name of each + // section in the group to the section index and the size in object. + // When we discard a group in some other object file, we use this + // map to figure out which kept section the discarded section is + // associated with. We then use that mapping when processing relocs + // against discarded sections. + struct Comdat_section_info + { + // The section index. + unsigned int shndx; + // The section size. + uint64_t size; + + Comdat_section_info(unsigned int a_shndx, uint64_t a_size) + : shndx(a_shndx), size(a_size) + { } + }; + + // Most comdat groups have only one or two sections, so we use a + // std::map rather than an Unordered_map to optimize for that case + // without paying too heavily for groups with more sections. + typedef std::map<std::string, Comdat_section_info> Comdat_group; + + public: + Kept_section() + : object_(NULL), shndx_(0), is_comdat_(false), is_group_name_(false) + { this->u_.linkonce_size = 0; } + + // We need to support copies for the signature map in the Layout + // object, but we should never copy an object after it has been + // marked as a comdat section. + Kept_section(const Kept_section& k) + : object_(k.object_), shndx_(k.shndx_), is_comdat_(false), + is_group_name_(k.is_group_name_) + { + gold_assert(!k.is_comdat_); + this->u_.linkonce_size = 0; + } + + ~Kept_section() + { + if (this->is_comdat_) + delete this->u_.group_sections; + } + + // The object where this section lives. + Relobj* + object() const + { return this->object_; } + + // Set the object. + void + set_object(Relobj* object) + { + gold_assert(this->object_ == NULL); + this->object_ = object; + } + + // The section index. + unsigned int + shndx() const + { return this->shndx_; } + + // Set the section index. + void + set_shndx(unsigned int shndx) + { + gold_assert(this->shndx_ == 0); + this->shndx_ = shndx; + } + + // Whether this is a comdat group. + bool + is_comdat() const + { return this->is_comdat_; } + + // Set that this is a comdat group. + void + set_is_comdat() + { + gold_assert(!this->is_comdat_); + this->is_comdat_ = true; + this->u_.group_sections = new Comdat_group(); + } + + // Whether this is associated with the name of a group or section + // rather than the symbol name derived from a linkonce section. + bool + is_group_name() const + { return this->is_group_name_; } + + // Note that this represents a comdat group rather than a single + // linkonce section. + void + set_is_group_name() + { this->is_group_name_ = true; } + + // Add a section to the group list. + void + add_comdat_section(const std::string& name, unsigned int shndx, + uint64_t size) + { + gold_assert(this->is_comdat_); + Comdat_section_info sinfo(shndx, size); + this->u_.group_sections->insert(std::make_pair(name, sinfo)); + } + + // Look for a section name in the group list, and return whether it + // was found. If found, returns the section index and size. + bool + find_comdat_section(const std::string& name, unsigned int *pshndx, + uint64_t *psize) const + { + gold_assert(this->is_comdat_); + Comdat_group::const_iterator p = this->u_.group_sections->find(name); + if (p == this->u_.group_sections->end()) + return false; + *pshndx = p->second.shndx; + *psize = p->second.size; + return true; + } + + // If there is only one section in the group list, return true, and + // return the section index and size. + bool + find_single_comdat_section(unsigned int *pshndx, uint64_t *psize) const + { + gold_assert(this->is_comdat_); + if (this->u_.group_sections->size() != 1) + return false; + Comdat_group::const_iterator p = this->u_.group_sections->begin(); + *pshndx = p->second.shndx; + *psize = p->second.size; + return true; + } + + // Return the size of a linkonce section. + uint64_t + linkonce_size() const + { + gold_assert(!this->is_comdat_); + return this->u_.linkonce_size; + } + + // Set the size of a linkonce section. + void + set_linkonce_size(uint64_t size) + { + gold_assert(!this->is_comdat_); + this->u_.linkonce_size = size; + } + + private: + // No assignment. + Kept_section& operator=(const Kept_section&); + + // The object containing the comdat group or .gnu.linkonce section. + Relobj* object_; + // Index of the group section for comdats and the section itself for + // .gnu.linkonce. + unsigned int shndx_; + // True if this is for a comdat group rather than a .gnu.linkonce + // section. + bool is_comdat_; + // The Kept_sections are values of a mapping, that maps names to + // them. This field is true if this struct is associated with the + // name of a comdat or .gnu.linkonce, false if it is associated with + // the name of a symbol obtained from the .gnu.linkonce.* name + // through some heuristics. + bool is_group_name_; + union + { + // If the is_comdat_ field is true, this holds a map from names of + // the sections in the group to section indexes in object_ and to + // section sizes. + Comdat_group* group_sections; + // If the is_comdat_ field is false, this holds the size of the + // single section. + uint64_t linkonce_size; + } u_; +}; + // This class handles the details of laying out input sections. class Layout { public: - Layout(const General_options& options, Script_options*); + Layout(int number_of_input_files, Script_options*); + + ~Layout() + { + delete this->relaxation_debug_check_; + delete this->segment_states_; + } // Given an input section SHNDX, named NAME, with data in SHDR, from // the object file OBJECT, return the output section where this @@ -162,11 +361,23 @@ class Layout layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags); // Add an Output_section_data to the layout. This is used for - // special sections like the GOT section. + // special sections like the GOT section. IS_DYNAMIC_LINKER_SECTION + // is true for sections which are used by the dynamic linker, such + // as dynamic reloc sections. IS_RELRO is true for relro sections. + // IS_LAST_RELRO is true for the last relro section. + // IS_FIRST_NON_RELRO is true for the first section after the relro + // sections. Output_section* add_output_section_data(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - Output_section_data*); + Output_section_data*, bool is_dynamic_linker_section, + bool is_relro, bool is_last_relro, + bool is_first_non_relro); + + // Increase the size of the relro segment by this much. + void + increase_relro(unsigned int s) + { this->increase_relro_ += s; } // Create dynamic sections if necessary. void @@ -176,6 +387,10 @@ class Layout void define_section_symbols(Symbol_table*); + // Create automatic note sections. + void + create_notes(); + // Create sections for linker scripts. void create_script_sections() @@ -219,29 +434,34 @@ class Layout is_linkonce(const char* name) { return strncmp(name, ".gnu.linkonce", sizeof(".gnu.linkonce") - 1) == 0; } + // Whether we have added an input section. + bool + have_added_input_section() const + { return this->have_added_input_section_; } + // Return true if a section is a debugging section. static inline bool is_debug_info_section(const char* name) { // Debugging sections can only be recognized by name. return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0 - || strncmp(name, ".gnu.linkonce.wi.", + || strncmp(name, ".gnu.linkonce.wi.", sizeof(".gnu.linkonce.wi.") - 1) == 0 || strncmp(name, ".line", sizeof(".line") - 1) == 0 || strncmp(name, ".stab", sizeof(".stab") - 1) == 0); } - // Record the signature of a comdat section, and return whether to - // include it in the link. The GROUP parameter is true for a - // section group signature, false for a signature derived from a - // .gnu.linkonce section. + // Check if a comdat group or .gnu.linkonce section with the given + // NAME is selected for the link. If there is already a section, + // *KEPT_SECTION is set to point to the signature and the function + // returns false. Otherwise, OBJECT, SHNDX,IS_COMDAT, and + // IS_GROUP_NAME are recorded for this NAME in the layout object, + // *KEPT_SECTION is set to the internal copy and the function return + // false. bool - add_comdat(Relobj*, unsigned int, const std::string&, bool group); - - // Find the given comdat signature, and return the object and section - // index of the kept group. - Relobj* - find_kept_object(const std::string&, unsigned int*) const; + find_or_add_kept_section(const std::string& name, Relobj* object, + unsigned int shndx, bool is_comdat, + bool is_group_name, Kept_section** kept_section); // Finalize the layout after all the input sections have been added. off_t @@ -331,6 +551,20 @@ class Layout script_options() const { return this->script_options_; } + // Return the object managing inputs in incremental build. NULL in + // non-incremental builds. + Incremental_inputs* + incremental_inputs() + { return this->incremental_inputs_; } + + // For the target-specific code to add dynamic tags which are common + // to most targets. + void + add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, + const Output_data* plt_rel, + const Output_data_reloc_generic* dyn_rel, + bool add_debug, bool dynrel_includes_plt); + // Compute and write out the build ID if needed. void write_build_id(Output_file*) const; @@ -366,7 +600,8 @@ class Layout // Make a section for a linker script to hold data. Output_section* - make_output_section_for_script(const char* name); + make_output_section_for_script(const char* name, + Script_sections::Section_type section_type); // Make a segment. This is used by the linker script code. Output_segment* @@ -385,20 +620,34 @@ class Layout void attach_sections_to_segments(); + // For relaxation clean up, we need to know output section data created + // from a linker script. + void + new_output_section_data_from_script(Output_section_data* posd) + { + if (this->record_output_section_data_from_script_) + this->script_output_section_data_list_.push_back(posd); + } + + // Return section list. + const Section_list& + section_list() const + { return this->section_list_; } + private: Layout(const Layout&); Layout& operator=(const Layout&); - // Mapping from .gnu.linkonce section names to output section names. - struct Linkonce_mapping + // Mapping from input section names to output section names. + struct Section_name_mapping { const char* from; int fromlen; const char* to; int tolen; }; - static const Linkonce_mapping linkonce_mapping[]; - static const int linkonce_mapping_count; + static const Section_name_mapping section_name_mapping[]; + static const int section_name_mapping_count; // During a relocatable link, a list of group sections and // signatures. @@ -419,23 +668,32 @@ class Layout }; typedef std::vector<Group_signature> Group_signatures; - // Create a .note section, filling in the header. + // Create a note section, filling in the header. Output_section* - create_note(const char* name, int note_type, size_t descsz, - bool allocate, size_t* trailing_padding); + create_note(const char* name, int note_type, const char *section_name, + size_t descsz, bool allocate, size_t* trailing_padding); - // Create a .note section for gold. + // Create a note section for gold version. void create_gold_note(); // Record whether the stack must be executable. void - create_executable_stack_info(const Target*); + create_executable_stack_info(); // Create a build ID note if needed. void create_build_id(); + // Link .stab and .stabstr sections. + void + link_stabs_sections(); + + // Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed + // for the next run of incremental linking to check what has changed. + void + create_incremental_info_sections(); + // Find the first read-only PT_LOAD segment, creating one if // necessary. Output_segment* @@ -475,6 +733,10 @@ class Layout void finish_dynamic_section(const Input_objects*, const Symbol_table*); + // Set the size of the _DYNAMIC symbol. + void + set_dynamic_symbol_size(const Symbol_table*); + // Create the .interp section and PT_INTERP segment. void create_interp(const Target* target); @@ -507,11 +769,6 @@ class Layout static const char* output_section_name(const char* name, size_t* plen); - // Return the output section name to use for a linkonce section - // name. PLEN is as for output_section_name. - static const char* - linkonce_output_name(const char* name, size_t* plen); - // Return the number of allocated output sections. size_t allocated_output_section_count() const; @@ -519,18 +776,25 @@ class Layout // Return the output section for NAME, TYPE and FLAGS. Output_section* get_output_section(const char* name, Stringpool::Key name_key, - elfcpp::Elf_Word type, elfcpp::Elf_Xword flags); + elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, + bool is_interp, bool is_dynamic_linker_section, + bool is_relro, bool is_last_relro, + bool is_first_non_relro); // Choose the output section for NAME in RELOBJ. Output_section* choose_output_section(const Relobj* relobj, const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool is_input_section); + bool is_input_section, bool is_interp, + bool is_dynamic_linker_section, bool is_relro, + bool is_last_relro, bool is_first_non_relro); // Create a new Output_section. Output_section* make_output_section(const char* name, elfcpp::Elf_Word type, - elfcpp::Elf_Xword flags); + elfcpp::Elf_Xword flags, bool is_interp, + bool is_dynamic_linker_section, bool is_relro, + bool is_last_relro, bool is_first_non_relro); // Attach a section to a segment. void @@ -573,23 +837,43 @@ class Layout Output_segment* set_section_addresses_from_script(Symbol_table*); + // Find appropriate places or orphan sections in a script. + void + place_orphan_sections_in_script(); + // Return whether SEG1 comes before SEG2 in the output file. static bool segment_precedes(const Output_segment* seg1, const Output_segment* seg2); - // A mapping used for group signatures. - struct Kept_section - { - Kept_section() - : object_(NULL), shndx_(0), group_(false) - { } - Kept_section(Relobj* object, unsigned int shndx, bool group) - : object_(object), shndx_(shndx), group_(group) - { } - Relobj* object_; - unsigned int shndx_; - bool group_; - }; + // Use to save and restore segments during relaxation. + typedef Unordered_map<const Output_segment*, const Output_segment*> + Segment_states; + + // Save states of current output segments. + void + save_segments(Segment_states*); + + // Restore output segment states. + void + restore_segments(const Segment_states*); + + // Clean up after relaxation so that it is possible to lay out the + // sections and segments again. + void + clean_up_after_relaxation(); + + // Doing preparation work for relaxation. This is factored out to make + // Layout::finalized a bit smaller and easier to read. + void + prepare_for_relaxation(); + + // Main body of the relaxation loop, which lays out the section. + off_t + relaxation_loop_body(int, Target*, Symbol_table*, Output_segment**, + Output_segment*, Output_segment_headers*, + Output_file_header*, unsigned int*); + + // A mapping used for kept comdats/.gnu.linkonce group signatures. typedef Unordered_map<std::string, Kept_section> Signatures; // Mapping from input section name/type/flags to output section. We @@ -615,8 +899,49 @@ class Layout { return Layout::segment_precedes(seg1, seg2); } }; - // A reference to the options on the command line. - const General_options& options_; + typedef std::vector<Output_section_data*> Output_section_data_list; + + // Debug checker class. + class Relaxation_debug_check + { + public: + Relaxation_debug_check() + : section_infos_() + { } + + // Check that sections and special data are in reset states. + void + check_output_data_for_reset_values(const Layout::Section_list&, + const Layout::Data_list&); + + // Record information of a section list. + void + read_sections(const Layout::Section_list&); + + // Verify a section list with recorded information. + void + verify_sections(const Layout::Section_list&); + + private: + // Information we care about a section. + struct Section_info + { + // Output section described by this. + Output_section* output_section; + // Load address. + uint64_t address; + // Data size. + off_t data_size; + // File offset. + off_t offset; + }; + + // Section information. + std::vector<Section_info> section_infos_; + }; + + // The number of input files, for sizing tables. + int number_of_input_files_; // Information set by scripts or by command line options. Script_options* script_options_; // The output section names. @@ -636,8 +961,6 @@ class Layout // The list of output sections which are not attached to any output // segment. Section_list unattached_section_list_; - // Whether we have attached the sections to the segments. - bool sections_are_attached_; // The list of unattached Output_data objects which require special // handling because they are not Output_sections. Data_list special_output_list_; @@ -647,6 +970,9 @@ class Layout Output_segment* tls_segment_; // A pointer to the PT_GNU_RELRO segment if there is one. Output_segment* relro_segment_; + // A backend may increase the size of the PT_GNU_RELRO segment if + // there is one. This is the amount to increase it by. + unsigned int increase_relro_; // The SHT_SYMTAB output section. Output_section* symtab_section_; // The SHT_SYMTAB_SHNDX for the regular symbol table if there is one. @@ -657,6 +983,8 @@ class Layout Output_symtab_xindex* dynsym_xindex_; // The SHT_DYNAMIC output section if there is one. Output_section* dynamic_section_; + // The _DYNAMIC symbol if there is one. + Symbol* dynamic_symbol_; // The dynamic data which goes into dynamic_section_. Output_data_dynamic* dynamic_data_; // The exception frame output section if there is one. @@ -677,6 +1005,10 @@ class Layout Group_signatures group_signatures_; // The size of the output file. off_t output_file_size_; + // Whether we have added an input section to an output section. + bool have_added_input_section_; + // Whether we have attached the sections to the segments. + bool sections_are_attached_; // Whether we have seen an object file marked to require an // executable stack. bool input_requires_executable_stack_; @@ -690,6 +1022,21 @@ class Layout bool has_static_tls_; // Whether any sections require postprocessing. bool any_postprocessing_sections_; + // Whether we have resized the signatures_ hash table. + bool resized_signatures_; + // Whether we have created a .stab*str output section. + bool have_stabstr_section_; + // In incremental build, holds information check the inputs and build the + // .gnu_incremental_inputs section. + Incremental_inputs* incremental_inputs_; + // Whether we record output section data created in script + bool record_output_section_data_from_script_; + // List of output data that needs to be removed at relexation clean up. + Output_section_data_list script_output_section_data_list_; + // Structure to save segment states before entering the relaxation loop. + Segment_states* segment_states_; + // A relaxation debug checker. We only create one when in debugging mode. + Relaxation_debug_check* relaxation_debug_check_; }; // This task handles writing out data in output sections which is not diff --git a/binutils-2.19/gold/main.cc b/binutils-2.19/gold/main.cc index b842159..9be4972 100644 --- a/binutils-2.19/gold/main.cc +++ b/binutils-2.19/gold/main.cc @@ -1,6 +1,6 @@ // main.cc -- gold main function. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -42,6 +42,11 @@ #include "archive.h" #include "symtab.h" #include "layout.h" +#include "plugin.h" +#include "gc.h" +#include "icf.h" +#include "incremental.h" +#include "timer.h" using namespace gold; @@ -157,9 +162,9 @@ main(int argc, char** argv) Command_line command_line; command_line.process(argc - 1, const_cast<const char**>(argv + 1)); - long start_time = 0; + Timer timer; if (command_line.options().stats()) - start_time = get_run_time(); + timer.start(); // Store some options in the globally accessible parameters. set_parameters_options(&command_line.options()); @@ -190,12 +195,22 @@ main(int argc, char** argv) if (parameters->options().relocatable()) command_line.script_options().version_script_info()->clear(); + // Load plugin libraries. + if (command_line.options().has_plugins()) + command_line.options().plugins()->load_plugins(); + // The work queue. Workqueue workqueue(command_line.options()); // The list of input objects. Input_objects input_objects; + // The Garbage Collection (GC, --gc-sections) Object. + Garbage_collection gc; + + // The Identical Code Folding (ICF, --icf) Object. + Icf icf; + // The symbol table. We're going to guess here how many symbols // we're going to see based on the number of input files. Even when // this is off, it means at worst we don't quite optimize hashtable @@ -203,8 +218,21 @@ main(int argc, char** argv) Symbol_table symtab(command_line.number_of_input_files() * 1024, command_line.version_script()); + if (parameters->options().gc_sections()) + symtab.set_gc(&gc); + + if (parameters->options().icf_enabled()) + symtab.set_icf(&icf); + // The layout object. - Layout layout(command_line.options(), &command_line.script_options()); + Layout layout(command_line.number_of_input_files(), + &command_line.script_options()); + + if (layout.incremental_inputs() != NULL) + { + layout.incremental_inputs()->report_command_line(argc, argv); + layout.incremental_inputs()->report_inputs(command_line.inputs()); + } // Get the search path from the -L options. Dirsearch search_path; @@ -220,9 +248,15 @@ main(int argc, char** argv) if (command_line.options().stats()) { - long run_time = get_run_time() - start_time; - fprintf(stderr, _("%s: total run time: %ld.%06ld seconds\n"), - program_name, run_time / 1000000, run_time % 1000000); + Timer::TimeStats elapsed = timer.get_elapsed_time(); + fprintf(stderr, + _("%s: total run time: " \ + "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"), + program_name, + elapsed.user / 1000, (elapsed.user % 1000) * 1000, + elapsed.sys / 1000, (elapsed.sys % 1000) * 1000, + elapsed.wall / 1000, (elapsed.wall % 1000) * 1000); + #ifdef HAVE_MALLINFO struct mallinfo m = mallinfo(); fprintf(stderr, _("%s: total space allocated by malloc: %d bytes\n"), @@ -236,13 +270,18 @@ main(int argc, char** argv) layout.print_stats(); } - if (mapfile != NULL) - mapfile->close(); - // Issue defined symbol report. if (command_line.options().user_set_print_symbol_counts()) input_objects.print_symbol_counts(&symtab); + // Output cross reference table. + if (command_line.options().cref()) + input_objects.print_cref(&symtab, + mapfile == NULL ? stdout : mapfile->file()); + + if (mapfile != NULL) + mapfile->close(); + if (parameters->options().fatal_warnings() && errors.warning_count() > 0 && errors.error_count() == 0) diff --git a/binutils-2.19/gold/mapfile.cc b/binutils-2.19/gold/mapfile.cc index 9cec366..a3ba52b 100644 --- a/binutils-2.19/gold/mapfile.cc +++ b/binutils-2.19/gold/mapfile.cc @@ -253,7 +253,7 @@ Mapfile::print_input_section(Relobj* relobj, unsigned int shndx) { os = relobj->output_section(shndx); addr = relobj->output_section_offset(shndx); - if (addr != -1U) + if (addr != -1ULL) addr += os->address(); } diff --git a/binutils-2.19/gold/mapfile.h b/binutils-2.19/gold/mapfile.h index ab55c38..908a208 100644 --- a/binutils-2.19/gold/mapfile.h +++ b/binutils-2.19/gold/mapfile.h @@ -1,6 +1,6 @@ // mapfile.h -- map file generation for gold -*- C++ -*- -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -54,6 +54,11 @@ class Mapfile void close(); + // Return the underlying file. + FILE* + file() + { return this->map_file_; } + // Report that we are including a member from an archive. This is // called by the archive reading code. void diff --git a/binutils-2.19/gold/merge.cc b/binutils-2.19/gold/merge.cc index 1369938..e2b6eef 100644 --- a/binutils-2.19/gold/merge.cc +++ b/binutils-2.19/gold/merge.cc @@ -204,6 +204,12 @@ Object_merge_map::initialize_input_to_output_map( Input_merge_map* map = this->get_input_merge_map(shndx); gold_assert(map != NULL); + gold_assert(initialize_map->empty()); + // We know how many entries we are going to add. + // reserve_unordered_map takes an expected count of buckets, not a + // count of elements, so double it to try to reduce collisions. + reserve_unordered_map(initialize_map, map->entries.size() * 2); + for (Input_merge_map::Entries::const_iterator p = map->entries.begin(); p != map->entries.end(); ++p) @@ -419,7 +425,10 @@ Output_merge_data::set_final_data_size() { // Release the memory we don't need. this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->len_)); - gold_assert(this->p_ != NULL); + // An Output_merge_data object may be empty and realloc is allowed + // to return a NULL pointer in this case. An Output_merge_data is empty + // if all its input sections have sizes that are not multiples of entsize. + gold_assert(this->p_ != NULL || this->len_ == 0); this->set_data_size(this->len_); } @@ -465,7 +474,7 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object, const unsigned char* pdata = object->section_contents(shndx, &len, false); const Char_type* p = reinterpret_cast<const Char_type*>(pdata); - const Char_type* pend = p + len; + const Char_type* pend = p + len / sizeof(Char_type); if (len % sizeof(Char_type) != 0) { @@ -485,8 +494,10 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object, { if (pl >= pend) { - object->error(_("entry in mergeable string section " - "not null terminated")); + gold_warning(_("%s: last entry in mergeable string section '%s' " + "not null terminated"), + object->name().c_str(), + object->section_name(shndx).c_str()); break; } } diff --git a/binutils-2.19/gold/merge.h b/binutils-2.19/gold/merge.h index fb6721d..345b115 100644 --- a/binutils-2.19/gold/merge.h +++ b/binutils-2.19/gold/merge.h @@ -219,6 +219,17 @@ class Output_merge_base : public Output_section_data : Output_section_data(addralign), merge_map_(), entsize_(entsize) { } + // Return the entry size. + uint64_t + entsize() const + { return this->entsize_; } + + // Whether this is a merge string section. This is only true of + // Output_merge_string. + bool + is_string() + { return this->do_is_string(); } + protected: // Return the output offset for an input offset. bool @@ -230,11 +241,6 @@ class Output_merge_base : public Output_section_data bool do_is_merge_section_for(const Relobj*, unsigned int shndx) const; - // Return the entry size. - uint64_t - entsize() const - { return this->entsize_; } - // Add a mapping from an OFFSET in input section SHNDX in object // OBJECT to an OUTPUT_OFFSET in the output section. OUTPUT_OFFSET // is the offset from the start of the merged data in the output @@ -246,6 +252,11 @@ class Output_merge_base : public Output_section_data this->merge_map_.add_mapping(object, shndx, offset, length, output_offset); } + // This may be overriden by the child class. + virtual bool + do_is_string() + { return false; } + private: // A mapping from input object/section/offset to offset in output // section. @@ -424,6 +435,11 @@ class Output_merge_string : public Output_merge_base clear_stringpool() { this->stringpool_.clear(); } + // Whether this is a merge string section. + virtual bool + do_is_string() + { return true; } + private: // The name of the string type, for stats. const char* diff --git a/binutils-2.19/gold/mremap.c b/binutils-2.19/gold/mremap.c new file mode 100644 index 0000000..332fded --- /dev/null +++ b/binutils-2.19/gold/mremap.c @@ -0,0 +1,59 @@ +/* mremap.c -- version of mremap for gold. */ + +/* Copyright 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor <iant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include "ansidecl.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/mman.h> + +/* This file implements mremap for systems which don't have it. The + gold code requires support for mmap. However, there are systems + which have mmap but not mremap. This is not a general replacement + for mremap; it only supports the features which are required for + gold. In particular, we assume that the MREMAP_MAYMOVE flag is + set. */ + +/* Some BSD systems still use MAP_ANON instead of MAP_ANONYMOUS. */ + +#ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS MAP_ANON +#endif + +extern void *mremap (void *, size_t, size_t, int, ...); + +void * +mremap (void *old_address, size_t old_size, size_t new_size, + int flags ATTRIBUTE_UNUSED, ...) +{ + void *ret; + + ret = mmap (0, new_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) + return ret; + memcpy (ret, old_address, + old_size < new_size ? old_size : new_size); + (void) munmap (old_address, old_size); + return ret; +} diff --git a/binutils-2.19/gold/object.cc b/binutils-2.19/gold/object.cc index d8f5ec8..73bf370 100644 --- a/binutils-2.19/gold/object.cc +++ b/binutils-2.19/gold/object.cc @@ -1,6 +1,6 @@ // object.cc -- support for an object file for linking in gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -28,6 +28,7 @@ #include "demangle.h" #include "libiberty.h" +#include "gc.h" #include "target-select.h" #include "dwarf_reader.h" #include "layout.h" @@ -37,6 +38,7 @@ #include "reloc.h" #include "object.h" #include "dynobj.h" +#include "plugin.h" namespace gold { @@ -130,19 +132,6 @@ Xindex::sym_xindex_to_shndx(Object* object, unsigned int symndx) // Class Object. -// Set the target based on fields in the ELF file header. - -void -Object::set_target(int machine, int size, bool big_endian, int osabi, - int abiversion) -{ - Target* target = select_target(machine, size, big_endian, osabi, abiversion); - if (target == NULL) - gold_fatal(_("%s: unsupported ELF machine number %d"), - this->name().c_str(), machine); - this->target_ = target; -} - // Report an error for this object file. This is used by the // elfcpp::Elf_file interface, and also called by the Object code // itself. @@ -168,6 +157,11 @@ Object::section_contents(unsigned int shndx, section_size_type* plen, { Location loc(this->do_section_contents(shndx)); *plen = convert_to_section_size_type(loc.data_size); + if (*plen == 0) + { + static const unsigned char empty[1] = { '\0' }; + return empty; + } return this->get_view(loc.file_offset, *plen, true, cache); } @@ -224,6 +218,12 @@ Object::handle_gnu_warning_section(const char* name, unsigned int shndx, section_size_type len; const unsigned char* contents = this->section_contents(shndx, &len, false); + if (len == 0) + { + const char* warning = name + warn_prefix_len; + contents = reinterpret_cast<const unsigned char*>(warning); + len = strlen(warning); + } std::string warning(reinterpret_cast<const char*>(contents), len); symtab->add_warning(name + warn_prefix_len, this, warning); return true; @@ -231,6 +231,98 @@ Object::handle_gnu_warning_section(const char* name, unsigned int shndx, return false; } +// If NAME is the name of the special section which indicates that +// this object was compiled with -fstack-split, mark it accordingly. + +bool +Object::handle_split_stack_section(const char* name) +{ + if (strcmp(name, ".note.GNU-split-stack") == 0) + { + this->uses_split_stack_ = true; + return true; + } + if (strcmp(name, ".note.GNU-no-split-stack") == 0) + { + this->has_no_split_stack_ = true; + return true; + } + return false; +} + +// Class Relobj + +// To copy the symbols data read from the file to a local data structure. +// This function is called from do_layout only while doing garbage +// collection. + +void +Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd, + unsigned int section_header_size) +{ + gc_sd->section_headers_data = + new unsigned char[(section_header_size)]; + memcpy(gc_sd->section_headers_data, sd->section_headers->data(), + section_header_size); + gc_sd->section_names_data = + new unsigned char[sd->section_names_size]; + memcpy(gc_sd->section_names_data, sd->section_names->data(), + sd->section_names_size); + gc_sd->section_names_size = sd->section_names_size; + if (sd->symbols != NULL) + { + gc_sd->symbols_data = + new unsigned char[sd->symbols_size]; + memcpy(gc_sd->symbols_data, sd->symbols->data(), + sd->symbols_size); + } + else + { + gc_sd->symbols_data = NULL; + } + gc_sd->symbols_size = sd->symbols_size; + gc_sd->external_symbols_offset = sd->external_symbols_offset; + if (sd->symbol_names != NULL) + { + gc_sd->symbol_names_data = + new unsigned char[sd->symbol_names_size]; + memcpy(gc_sd->symbol_names_data, sd->symbol_names->data(), + sd->symbol_names_size); + } + else + { + gc_sd->symbol_names_data = NULL; + } + gc_sd->symbol_names_size = sd->symbol_names_size; +} + +// This function determines if a particular section name must be included +// in the link. This is used during garbage collection to determine the +// roots of the worklist. + +bool +Relobj::is_section_name_included(const char* name) +{ + if (is_prefix_of(".ctors", name) + || is_prefix_of(".dtors", name) + || is_prefix_of(".note", name) + || is_prefix_of(".init", name) + || is_prefix_of(".fini", name) + || is_prefix_of(".gcc_except_table", name) + || is_prefix_of(".jcr", name) + || is_prefix_of(".preinit_array", name) + || (is_prefix_of(".text", name) + && strstr(name, "personality")) + || (is_prefix_of(".data", name) + && strstr(name, "personality")) + || (is_prefix_of(".gnu.linkonce.d", name) + && strstr(name, "personality"))) + { + return true; + } + return false; +} + // Class Sized_relobj. template<int size, bool big_endian> @@ -252,8 +344,8 @@ Sized_relobj<size, big_endian>::Sized_relobj( local_values_(), local_got_offsets_(), kept_comdat_sections_(), - comdat_groups_(), - has_eh_frame_(false) + has_eh_frame_(false), + discarded_eh_frame_shndx_(-1U) { } @@ -263,17 +355,12 @@ Sized_relobj<size, big_endian>::~Sized_relobj() } // Set up an object file based on the file header. This sets up the -// target and reads the section information. +// section information. template<int size, bool big_endian> void -Sized_relobj<size, big_endian>::setup( - const elfcpp::Ehdr<size, big_endian>& ehdr) +Sized_relobj<size, big_endian>::do_setup() { - this->set_target(ehdr.get_e_machine(), size, big_endian, - ehdr.get_e_ident()[elfcpp::EI_OSABI], - ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]); - const unsigned int shnum = this->elf_file_.shnum(); this->set_shnum(shnum); } @@ -599,29 +686,21 @@ Sized_relobj<size, big_endian>::include_section_group( // Record this section group in the layout, and see whether we've already // seen one with the same signature. - bool include_group = ((flags & elfcpp::GRP_COMDAT) == 0 - || layout->add_comdat(this, index, signature, true)); - - Sized_relobj<size, big_endian>* kept_object = NULL; - Comdat_group* kept_group = NULL; + bool include_group; + bool is_comdat; + Kept_section* kept_section = NULL; - if (!include_group) + if ((flags & elfcpp::GRP_COMDAT) == 0) { - // This group is being discarded. Find the object and group - // that was kept in its place. - unsigned int kept_group_index = 0; - Relobj* kept_relobj = layout->find_kept_object(signature, - &kept_group_index); - kept_object = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj); - if (kept_object != NULL) - kept_group = kept_object->find_comdat_group(kept_group_index); + include_group = true; + is_comdat = false; } - else if (flags & elfcpp::GRP_COMDAT) + else { - // This group is being kept. Create the table to map section names - // to section indexes and add it to the table of groups. - kept_group = new Comdat_group(); - this->add_comdat_group(index, kept_group); + include_group = layout->find_or_add_kept_section(signature, + this, index, true, + true, &kept_section); + is_comdat = true; } size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word); @@ -633,27 +712,27 @@ Sized_relobj<size, big_endian>::include_section_group( for (size_t i = 1; i < count; ++i) { - elfcpp::Elf_Word secnum = + elfcpp::Elf_Word shndx = this->adjust_shndx(elfcpp::Swap<32, big_endian>::readval(pword + i)); if (relocate_group) - shndxes.push_back(secnum); + shndxes.push_back(shndx); - if (secnum >= this->shnum()) + if (shndx >= this->shnum()) { this->error(_("section %u in section group %u out of range"), - secnum, index); + shndx, index); continue; } // Check for an earlier section number, since we're going to get // it wrong--we may have already decided to include the section. - if (secnum < index) + if (shndx < index) this->error(_("invalid section group %u refers to earlier section %u"), - index, secnum); + index, shndx); // Get the name of the member section. - typename This::Shdr member_shdr(shdrs + secnum * This::shdr_size); + typename This::Shdr member_shdr(shdrs + shndx * This::shdr_size); if (member_shdr.get_sh_name() >= section_names_size) { // This is an error, but it will be diagnosed eventually @@ -663,28 +742,53 @@ Sized_relobj<size, big_endian>::include_section_group( } std::string mname(section_names + member_shdr.get_sh_name()); - if (!include_group) + if (include_group) + { + if (is_comdat) + kept_section->add_comdat_section(mname, shndx, + member_shdr.get_sh_size()); + } + else { - (*omit)[secnum] = true; - if (kept_group != NULL) + (*omit)[shndx] = true; + + if (is_comdat) { - // Find the corresponding kept section, and store that info - // in the discarded section table. - Comdat_group::const_iterator p = kept_group->find(mname); - if (p != kept_group->end()) - { - Kept_comdat_section* kept = - new Kept_comdat_section(kept_object, p->second); - this->set_kept_comdat_section(secnum, kept); - } + Relobj* kept_object = kept_section->object(); + if (kept_section->is_comdat()) + { + // Find the corresponding kept section, and store + // that info in the discarded section table. + unsigned int kept_shndx; + uint64_t kept_size; + if (kept_section->find_comdat_section(mname, &kept_shndx, + &kept_size)) + { + // We don't keep a mapping for this section if + // it has a different size. The mapping is only + // used for relocation processing, and we don't + // want to treat the sections as similar if the + // sizes are different. Checking the section + // size is the approach used by the GNU linker. + if (kept_size == member_shdr.get_sh_size()) + this->set_kept_comdat_section(shndx, kept_object, + kept_shndx); + } + } + else + { + // The existing section is a linkonce section. Add + // a mapping if there is exactly one section in the + // group (which is true when COUNT == 2) and if it + // is the same size. + if (count == 2 + && (kept_section->linkonce_size() + == member_shdr.get_sh_size())) + this->set_kept_comdat_section(shndx, kept_object, + kept_section->shndx()); + } } } - else if (flags & elfcpp::GRP_COMDAT) - { - // Add the section to the kept group table. - gold_assert(kept_group != NULL); - kept_group->insert(std::make_pair(mname, secnum)); - } } if (relocate_group) @@ -715,8 +819,9 @@ Sized_relobj<size, big_endian>::include_linkonce_section( Layout* layout, unsigned int index, const char* name, - const elfcpp::Shdr<size, big_endian>&) + const elfcpp::Shdr<size, big_endian>& shdr) { + typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size(); // In general the symbol name we want will be the string following // the last '.'. However, we have to handle the case of // .gnu.linkonce.t.__i686.get_pc_thunk.bx, which was generated by @@ -733,25 +838,24 @@ Sized_relobj<size, big_endian>::include_linkonce_section( symname = strrchr(name, '.') + 1; std::string sig1(symname); std::string sig2(name); - bool include1 = layout->add_comdat(this, index, sig1, false); - bool include2 = layout->add_comdat(this, index, sig2, true); + Kept_section* kept1; + Kept_section* kept2; + bool include1 = layout->find_or_add_kept_section(sig1, this, index, false, + false, &kept1); + bool include2 = layout->find_or_add_kept_section(sig2, this, index, false, + true, &kept2); if (!include2) { - // The section is being discarded on the basis of its section - // name (i.e., the kept section was also a linkonce section). - // In this case, the section index stored with the layout object - // is the linkonce section that was kept. - unsigned int kept_group_index = 0; - Relobj* kept_relobj = layout->find_kept_object(sig2, &kept_group_index); - if (kept_relobj != NULL) - { - Sized_relobj<size, big_endian>* kept_object - = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj); - Kept_comdat_section* kept = - new Kept_comdat_section(kept_object, kept_group_index); - this->set_kept_comdat_section(index, kept); - } + // We are not including this section because we already saw the + // name of the section as a signature. This normally implies + // that the kept section is another linkonce section. If it is + // the same size, record it as the section which corresponds to + // this one. + if (kept2->object() != NULL + && !kept2->is_comdat() + && kept2->linkonce_size() == sh_size) + this->set_kept_comdat_section(index, kept2->object(), kept2->shndx()); } else if (!include1) { @@ -762,32 +866,64 @@ Sized_relobj<size, big_endian>::include_linkonce_section( // this linkonce section. We'll handle the simple case where // the group has only one member section. Otherwise, it's not // worth the effort. - unsigned int kept_group_index = 0; - Relobj* kept_relobj = layout->find_kept_object(sig1, &kept_group_index); - if (kept_relobj != NULL) - { - Sized_relobj<size, big_endian>* kept_object = - static_cast<Sized_relobj<size, big_endian>*>(kept_relobj); - Comdat_group* kept_group = - kept_object->find_comdat_group(kept_group_index); - if (kept_group != NULL && kept_group->size() == 1) - { - Comdat_group::const_iterator p = kept_group->begin(); - gold_assert(p != kept_group->end()); - Kept_comdat_section* kept = - new Kept_comdat_section(kept_object, p->second); - this->set_kept_comdat_section(index, kept); - } - } + unsigned int kept_shndx; + uint64_t kept_size; + if (kept1->object() != NULL + && kept1->is_comdat() + && kept1->find_single_comdat_section(&kept_shndx, &kept_size) + && kept_size == sh_size) + this->set_kept_comdat_section(index, kept1->object(), kept_shndx); + } + else + { + kept1->set_linkonce_size(sh_size); + kept2->set_linkonce_size(sh_size); } return include1 && include2; } +// Layout an input section. + +template<int size, bool big_endian> +inline void +Sized_relobj<size, big_endian>::layout_section(Layout* layout, + unsigned int shndx, + const char* name, + typename This::Shdr& shdr, + unsigned int reloc_shndx, + unsigned int reloc_type) +{ + off_t offset; + Output_section* os = layout->layout(this, shndx, name, shdr, + reloc_shndx, reloc_type, &offset); + + this->output_sections()[shndx] = os; + if (offset == -1) + this->section_offsets_[shndx] = invalid_address; + else + this->section_offsets_[shndx] = convert_types<Address, off_t>(offset); + + // If this section requires special handling, and if there are + // relocs that apply to it, then we must do the special handling + // before we apply the relocs. + if (offset == -1 && reloc_shndx != 0) + this->set_relocs_must_follow_section_writes(); +} + // Lay out the input sections. We walk through the sections and check // whether they should be included in the link. If they should, we // pass them to the Layout object, which will return an output section -// and an offset. +// and an offset. +// During garbage collection (--gc-sections) and identical code folding +// (--icf), this function is called twice. When it is called the first +// time, it is for setting up some sections as roots to a work-list for +// --gc-sections and to do comdat processing. Actual layout happens the +// second time around after all the relevant sections have been determined. +// The first time, is_worklist_ready or is_icf_ready is false. It is then +// set to true after the garbage collection worklist or identical code +// folding is processed and the relevant sections to be kept are +// determined. Then, this function is called again to layout the sections. template<int size, bool big_endian> void @@ -796,17 +932,87 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, Read_symbols_data* sd) { const unsigned int shnum = this->shnum(); + bool is_gc_pass_one = ((parameters->options().gc_sections() + && !symtab->gc()->is_worklist_ready()) + || (parameters->options().icf_enabled() + && !symtab->icf()->is_icf_ready())); + + bool is_gc_pass_two = ((parameters->options().gc_sections() + && symtab->gc()->is_worklist_ready()) + || (parameters->options().icf_enabled() + && symtab->icf()->is_icf_ready())); + + bool is_gc_or_icf = (parameters->options().gc_sections() + || parameters->options().icf_enabled()); + + // Both is_gc_pass_one and is_gc_pass_two should not be true. + gold_assert(!(is_gc_pass_one && is_gc_pass_two)); + if (shnum == 0) return; + Symbols_data* gc_sd = NULL; + if (is_gc_pass_one) + { + // During garbage collection save the symbols data to use it when + // re-entering this function. + gc_sd = new Symbols_data; + this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum); + this->set_symbols_data(gc_sd); + } + else if (is_gc_pass_two) + { + gc_sd = this->get_symbols_data(); + } + + const unsigned char* section_headers_data = NULL; + section_size_type section_names_size; + const unsigned char* symbols_data = NULL; + section_size_type symbols_size; + section_offset_type external_symbols_offset; + const unsigned char* symbol_names_data = NULL; + section_size_type symbol_names_size; + + if (is_gc_or_icf) + { + section_headers_data = gc_sd->section_headers_data; + section_names_size = gc_sd->section_names_size; + symbols_data = gc_sd->symbols_data; + symbols_size = gc_sd->symbols_size; + external_symbols_offset = gc_sd->external_symbols_offset; + symbol_names_data = gc_sd->symbol_names_data; + symbol_names_size = gc_sd->symbol_names_size; + } + else + { + section_headers_data = sd->section_headers->data(); + section_names_size = sd->section_names_size; + if (sd->symbols != NULL) + symbols_data = sd->symbols->data(); + symbols_size = sd->symbols_size; + external_symbols_offset = sd->external_symbols_offset; + if (sd->symbol_names != NULL) + symbol_names_data = sd->symbol_names->data(); + symbol_names_size = sd->symbol_names_size; + } // Get the section headers. - const unsigned char* shdrs = sd->section_headers->data(); + const unsigned char* shdrs = section_headers_data; const unsigned char* pshdrs; // Get the section names. - const unsigned char* pnamesu = sd->section_names->data(); + const unsigned char* pnamesu = (is_gc_or_icf) + ? gc_sd->section_names_data + : sd->section_names->data(); + const char* pnames = reinterpret_cast<const char*>(pnamesu); + // If any input files have been claimed by plugins, we need to defer + // actual layout until the replacement files have arrived. + const bool should_defer_layout = + (parameters->options().has_plugins() + && parameters->options().plugins()->should_defer_layout()); + unsigned int num_sections_to_defer = 0; + // For each section, record the index of the reloc section if any. // Use 0 to mean that there is no reloc section, -1U to mean that // there is more than one. @@ -818,6 +1024,10 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, { typename This::Shdr shdr(pshdrs); + // Count the number of sections whose layout will be deferred. + if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC)) + ++num_sections_to_defer; + unsigned int sh_type = shdr.get_sh_type(); if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA) { @@ -842,20 +1052,32 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, Output_sections& out_sections(this->output_sections()); std::vector<Address>& out_section_offsets(this->section_offsets_); - out_sections.resize(shnum); - out_section_offsets.resize(shnum); + if (!is_gc_pass_two) + { + out_sections.resize(shnum); + out_section_offsets.resize(shnum); + } // If we are only linking for symbols, then there is nothing else to // do here. if (this->input_file()->just_symbols()) { - delete sd->section_headers; - sd->section_headers = NULL; - delete sd->section_names; - sd->section_names = NULL; + if (!is_gc_pass_two) + { + delete sd->section_headers; + sd->section_headers = NULL; + delete sd->section_names; + sd->section_names = NULL; + } return; } + if (num_sections_to_defer > 0) + { + parameters->options().plugins()->add_deferred_layout_object(this); + this->deferred_layout_.reserve(num_sections_to_defer); + } + // Whether we've seen a .note.GNU-stack section. bool seen_gnu_stack = false; // The flags of a .note.GNU-stack section. @@ -879,7 +1101,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, { typename This::Shdr shdr(pshdrs); - if (shdr.get_sh_name() >= sd->section_names_size) + if (shdr.get_sh_name() >= section_names_size) { this->error(_("bad section name offset for section %u: %lu"), i, static_cast<unsigned long>(shdr.get_sh_name())); @@ -888,53 +1110,92 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, const char* name = pnames + shdr.get_sh_name(); - if (this->handle_gnu_warning_section(name, i, symtab)) - { - if (!relocatable) - omit[i] = true; - } + if (!is_gc_pass_two) + { + if (this->handle_gnu_warning_section(name, i, symtab)) + { + if (!relocatable) + omit[i] = true; + } - // The .note.GNU-stack section is special. It gives the - // protection flags that this object file requires for the stack - // in memory. - if (strcmp(name, ".note.GNU-stack") == 0) - { - seen_gnu_stack = true; - gnu_stack_flags |= shdr.get_sh_flags(); - omit[i] = true; - } + // The .note.GNU-stack section is special. It gives the + // protection flags that this object file requires for the stack + // in memory. + if (strcmp(name, ".note.GNU-stack") == 0) + { + seen_gnu_stack = true; + gnu_stack_flags |= shdr.get_sh_flags(); + omit[i] = true; + } - bool discard = omit[i]; - if (!discard) - { - if (shdr.get_sh_type() == elfcpp::SHT_GROUP) + // The .note.GNU-split-stack section is also special. It + // indicates that the object was compiled with + // -fsplit-stack. + if (this->handle_split_stack_section(name)) { - if (!this->include_section_group(symtab, layout, i, name, shdrs, - pnames, sd->section_names_size, - &omit)) - discard = true; + if (!parameters->options().relocatable() + && !parameters->options().shared()) + omit[i] = true; } - else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0 - && Layout::is_linkonce(name)) + + // Skip attributes section. + if (parameters->target().is_attributes_section(name)) { - if (!this->include_linkonce_section(layout, i, name, shdr)) - discard = true; + omit[i] = true; } - } - if (discard) - { - // Do not include this section in the link. - out_sections[i] = NULL; - out_section_offsets[i] = -1U; - continue; - } + bool discard = omit[i]; + if (!discard) + { + if (shdr.get_sh_type() == elfcpp::SHT_GROUP) + { + if (!this->include_section_group(symtab, layout, i, name, + shdrs, pnames, + section_names_size, + &omit)) + discard = true; + } + else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0 + && Layout::is_linkonce(name)) + { + if (!this->include_linkonce_section(layout, i, name, shdr)) + discard = true; + } + } + + if (discard) + { + // Do not include this section in the link. + out_sections[i] = NULL; + out_section_offsets[i] = invalid_address; + continue; + } + } + + if (is_gc_pass_one && parameters->options().gc_sections()) + { + if (is_section_name_included(name) + || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY + || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY) + { + symtab->gc()->worklist().push(Section_id(this, i)); + } + // If the section name XXX can be represented as a C identifier + // it cannot be discarded if there are references to + // __start_XXX and __stop_XXX symbols. These need to be + // specially handled. + if (is_cident(name)) + { + symtab->gc()->add_cident_section(name, Section_id(this, i)); + } + } // When doing a relocatable link we are going to copy input // reloc sections into the output. We only want to copy the // ones associated with sections which are not being discarded. // However, we don't know that yet for all sections. So save - // reloc sections and process them later. + // reloc sections and process them later. Garbage collection is + // not triggered when relocatable code is desired. if (emit_relocs && (shdr.get_sh_type() == elfcpp::SHT_REL || shdr.get_sh_type() == elfcpp::SHT_RELA)) @@ -953,44 +1214,131 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, // determine which sections are being discarded, and discard the // corresponding information. if (!relocatable - && strcmp(name, ".eh_frame") == 0 - && this->check_eh_frame_flags(&shdr)) - { - eh_frame_sections.push_back(i); - continue; - } + && strcmp(name, ".eh_frame") == 0 + && this->check_eh_frame_flags(&shdr)) + { + if (is_gc_pass_one) + { + out_sections[i] = reinterpret_cast<Output_section*>(1); + out_section_offsets[i] = invalid_address; + } + else + eh_frame_sections.push_back(i); + continue; + } - off_t offset; - Output_section* os = layout->layout(this, i, name, shdr, - reloc_shndx[i], reloc_type[i], - &offset); + if (is_gc_pass_two && parameters->options().gc_sections()) + { + // This is executed during the second pass of garbage + // collection. do_layout has been called before and some + // sections have been already discarded. Simply ignore + // such sections this time around. + if (out_sections[i] == NULL) + { + gold_assert(out_section_offsets[i] == invalid_address); + continue; + } + if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0) + && symtab->gc()->is_section_garbage(this, i)) + { + if (parameters->options().print_gc_sections()) + gold_info(_("%s: removing unused section from '%s'" + " in file '%s'"), + program_name, this->section_name(i).c_str(), + this->name().c_str()); + out_sections[i] = NULL; + out_section_offsets[i] = invalid_address; + continue; + } + } - out_sections[i] = os; - if (offset == -1) - out_section_offsets[i] = -1U; - else - out_section_offsets[i] = convert_types<Address, off_t>(offset); + if (is_gc_pass_two && parameters->options().icf_enabled()) + { + if (out_sections[i] == NULL) + { + gold_assert(out_section_offsets[i] == invalid_address); + continue; + } + if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0) + && symtab->icf()->is_section_folded(this, i)) + { + if (parameters->options().print_icf_sections()) + { + Section_id folded = + symtab->icf()->get_folded_section(this, i); + Relobj* folded_obj = + reinterpret_cast<Relobj*>(folded.first); + gold_info(_("%s: ICF folding section '%s' in file '%s'" + "into '%s' in file '%s'"), + program_name, this->section_name(i).c_str(), + this->name().c_str(), + folded_obj->section_name(folded.second).c_str(), + folded_obj->name().c_str()); + } + out_sections[i] = NULL; + out_section_offsets[i] = invalid_address; + continue; + } + } - // If this section requires special handling, and if there are - // relocs that apply to it, then we must do the special handling - // before we apply the relocs. - if (offset == -1 && reloc_shndx[i] != 0) - this->set_relocs_must_follow_section_writes(); + // Defer layout here if input files are claimed by plugins. When gc + // is turned on this function is called twice. For the second call + // should_defer_layout should be false. + if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC)) + { + gold_assert(!is_gc_pass_two); + this->deferred_layout_.push_back(Deferred_layout(i, name, + pshdrs, + reloc_shndx[i], + reloc_type[i])); + // Put dummy values here; real values will be supplied by + // do_layout_deferred_sections. + out_sections[i] = reinterpret_cast<Output_section*>(2); + out_section_offsets[i] = invalid_address; + continue; + } + + // During gc_pass_two if a section that was previously deferred is + // found, do not layout the section as layout_deferred_sections will + // do it later from gold.cc. + if (is_gc_pass_two + && (out_sections[i] == reinterpret_cast<Output_section*>(2))) + continue; + + if (is_gc_pass_one) + { + // This is during garbage collection. The out_sections are + // assigned in the second call to this function. + out_sections[i] = reinterpret_cast<Output_section*>(1); + out_section_offsets[i] = invalid_address; + } + else + { + // When garbage collection is switched on the actual layout + // only happens in the second call. + this->layout_section(layout, i, name, shdr, reloc_shndx[i], + reloc_type[i]); + } } - layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags); + if (!is_gc_pass_two) + layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags); // When doing a relocatable link handle the reloc sections at the - // end. + // end. Garbage collection and Identical Code Folding is not + // turned on for relocatable code. if (emit_relocs) this->size_relocatable_relocs(); + + gold_assert(!(is_gc_or_icf) || reloc_sections.empty()); + for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin(); p != reloc_sections.end(); ++p) { unsigned int i = *p; const unsigned char* pshdr; - pshdr = sd->section_headers->data() + i * This::shdr_size; + pshdr = section_headers_data + i * This::shdr_size; typename This::Shdr shdr(pshdr); unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info()); @@ -1004,7 +1352,7 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, if (data_section == NULL) { out_sections[i] = NULL; - out_section_offsets[i] = -1U; + out_section_offsets[i] = invalid_address; continue; } @@ -1014,49 +1362,88 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, Output_section* os = layout->layout_reloc(this, i, shdr, data_section, rr); out_sections[i] = os; - out_section_offsets[i] = -1U; + out_section_offsets[i] = invalid_address; } // Handle the .eh_frame sections at the end. + gold_assert(!is_gc_pass_one || eh_frame_sections.empty()); for (std::vector<unsigned int>::const_iterator p = eh_frame_sections.begin(); p != eh_frame_sections.end(); ++p) { gold_assert(this->has_eh_frame_); - gold_assert(sd->external_symbols_offset != 0); + gold_assert(external_symbols_offset != 0); unsigned int i = *p; const unsigned char *pshdr; - pshdr = sd->section_headers->data() + i * This::shdr_size; + pshdr = section_headers_data + i * This::shdr_size; typename This::Shdr shdr(pshdr); off_t offset; Output_section* os = layout->layout_eh_frame(this, - sd->symbols->data(), - sd->symbols_size, - sd->symbol_names->data(), - sd->symbol_names_size, + symbols_data, + symbols_size, + symbol_names_data, + symbol_names_size, i, shdr, reloc_shndx[i], reloc_type[i], &offset); out_sections[i] = os; - if (offset == -1) - out_section_offsets[i] = -1U; + if (os == NULL || offset == -1) + { + // An object can contain at most one section holding exception + // frame information. + gold_assert(this->discarded_eh_frame_shndx_ == -1U); + this->discarded_eh_frame_shndx_ = i; + out_section_offsets[i] = invalid_address; + } else out_section_offsets[i] = convert_types<Address, off_t>(offset); // If this section requires special handling, and if there are // relocs that apply to it, then we must do the special handling // before we apply the relocs. - if (offset == -1 && reloc_shndx[i] != 0) + if (os != NULL && offset == -1 && reloc_shndx[i] != 0) this->set_relocs_must_follow_section_writes(); } - delete sd->section_headers; - sd->section_headers = NULL; - delete sd->section_names; - sd->section_names = NULL; + if (is_gc_pass_two) + { + delete[] gc_sd->section_headers_data; + delete[] gc_sd->section_names_data; + delete[] gc_sd->symbols_data; + delete[] gc_sd->symbol_names_data; + this->set_symbols_data(NULL); + } + else + { + delete sd->section_headers; + sd->section_headers = NULL; + delete sd->section_names; + sd->section_names = NULL; + } +} + +// Layout sections whose layout was deferred while waiting for +// input files from a plugin. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout) +{ + typename std::vector<Deferred_layout>::iterator deferred; + + for (deferred = this->deferred_layout_.begin(); + deferred != this->deferred_layout_.end(); + ++deferred) + { + typename This::Shdr shdr(deferred->shdr_data_); + this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(), + shdr, deferred->reloc_shndx_, deferred->reloc_type_); + } + + this->deferred_layout_.clear(); } // Add the symbols to the symbol table. @@ -1064,7 +1451,8 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, template<int size, bool big_endian> void Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab, - Read_symbols_data* sd) + Read_symbols_data* sd, + Layout*) { if (sd->symbols == NULL) { @@ -1147,6 +1535,8 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, unsigned int dyncount = 0; // Skip the first, dummy, symbol. psyms += sym_size; + bool discard_all = parameters->options().discard_all(); + bool discard_locals = parameters->options().discard_locals(); for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size) { elfcpp::Sym<size, big_endian> sym(psyms); @@ -1168,7 +1558,8 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, // Decide whether this symbol should go into the output file. - if (shndx < shnum && out_sections[shndx] == NULL) + if ((shndx < shnum && out_sections[shndx] == NULL) + || shndx == this->discarded_eh_frame_shndx_) { lv.set_no_output_symtab_entry(); gold_assert(!lv.needs_output_dynsym_entry()); @@ -1191,10 +1582,7 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, continue; } - // Add the symbol to the symbol table string pool. const char* name = pnames + sym.get_st_name(); - pool->add(name, true, NULL); - ++count; // If needed, add the symbol to the dynamic symbol table string pool. if (lv.needs_output_dynsym_entry()) @@ -1202,6 +1590,46 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, dynpool->add(name, true, NULL); ++dyncount; } + + if (discard_all && lv.may_be_discarded_from_output_symtab()) + { + lv.set_no_output_symtab_entry(); + continue; + } + + // If --discard-locals option is used, discard all temporary local + // symbols. These symbols start with system-specific local label + // prefixes, typically .L for ELF system. We want to be compatible + // with GNU ld so here we essentially use the same check in + // bfd_is_local_label(). The code is different because we already + // know that: + // + // - the symbol is local and thus cannot have global or weak binding. + // - the symbol is not a section symbol. + // - the symbol has a name. + // + // We do not discard a symbol if it needs a dynamic symbol entry. + if (discard_locals + && sym.get_st_type() != elfcpp::STT_FILE + && !lv.needs_output_dynsym_entry() + && lv.may_be_discarded_from_output_symtab() + && parameters->target().is_local_label_name(name)) + { + lv.set_no_output_symtab_entry(); + continue; + } + + // Discard the local symbol if -retain_symbols_file is specified + // and the local symbol is not in that file. + if (!parameters->options().should_retain_symbol(name)) + { + lv.set_no_output_symtab_entry(); + continue; + } + + // Add the symbol to the symbol table string pool. + pool->add(name, true, NULL); + ++count; } this->output_local_symbol_count_ = count; @@ -1216,13 +1644,15 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool, template<int size, bool big_endian> unsigned int Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, - off_t off) + off_t off, + Symbol_table* symtab) { gold_assert(off == static_cast<off_t>(align_address(off, size >> 3))); const unsigned int loccount = this->local_symbol_count_; this->local_symbol_offset_ = off; + const bool relocatable = parameters->options().relocatable(); const Output_sections& out_sections(this->output_sections()); const std::vector<Address>& out_offsets(this->section_offsets_); unsigned int shnum = this->shnum(); @@ -1238,7 +1668,7 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, if (!is_ordinary) { - if (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON) + if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx)) lv.set_output_value(lv.input_value()); else { @@ -1257,6 +1687,29 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, } Output_section* os = out_sections[shndx]; + Address secoffset = out_offsets[shndx]; + if (symtab->is_section_folded(this, shndx)) + { + gold_assert (os == NULL && secoffset == invalid_address); + // Get the os of the section it is folded onto. + Section_id folded = symtab->icf()->get_folded_section(this, + shndx); + gold_assert(folded.first != NULL); + Sized_relobj<size, big_endian>* folded_obj = reinterpret_cast + <Sized_relobj<size, big_endian>*>(folded.first); + os = folded_obj->output_section(folded.second); + gold_assert(os != NULL); + secoffset = folded_obj->get_output_section_offset(folded.second); + + // This could be a relaxed input section. + if (secoffset == invalid_address) + { + const Output_relaxed_input_section* relaxed_section = + os->find_relaxed_input_section(folded_obj, folded.second); + gold_assert(relaxed_section != NULL); + secoffset = relaxed_section->address() - os->address(); + } + } if (os == NULL) { @@ -1266,22 +1719,47 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, // so we leave the input value unchanged here. continue; } - else if (out_offsets[shndx] == -1U) + else if (secoffset == invalid_address) { + uint64_t start; + // This is a SHF_MERGE section or one which otherwise - // requires special handling. We get the output address - // of the start of the merged section. If this is not a - // section symbol, we can then determine the final - // value. If it is a section symbol, we can not, as in - // that case we have to consider the addend to determine - // the value to use in a relocation. - if (!lv.is_section_symbol()) - lv.set_output_value(os->output_address(this, shndx, - lv.input_value())); + // requires special handling. + if (shndx == this->discarded_eh_frame_shndx_) + { + // This local symbol belongs to a discarded .eh_frame + // section. Just treat it like the case in which + // os == NULL above. + gold_assert(this->has_eh_frame_); + continue; + } + else if (!lv.is_section_symbol()) + { + // This is not a section symbol. We can determine + // the final value now. + lv.set_output_value(os->output_address(this, shndx, + lv.input_value())); + } + else if (!os->find_starting_output_address(this, shndx, &start)) + { + // This is a section symbol, but apparently not one in a + // merged section. First check to see if this is a relaxed + // input section. If so, use its address. Otherwise just + // use the start of the output section. This happens with + // relocatable links when the input object has section + // symbols for arbitrary non-merge sections. + const Output_section_data* posd = + os->find_relaxed_input_section(this, shndx); + if (posd != NULL) + lv.set_output_value(posd->address()); + else + lv.set_output_value(os->address()); + } else { - section_offset_type start = - os->starting_output_address(this, shndx); + // We have to consider the addend to determine the + // value to use in a relocation. START is the start + // of this input section. Merged_symbol_value<size>* msv = new Merged_symbol_value<size>(lv.input_value(), start); lv.set_merged_symbol_value(msv); @@ -1289,15 +1767,15 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, } else if (lv.is_tls_symbol()) lv.set_output_value(os->tls_offset() - + out_offsets[shndx] + + secoffset + lv.input_value()); else - lv.set_output_value(os->address() - + out_offsets[shndx] + lv.set_output_value((relocatable ? 0 : os->address()) + + secoffset + lv.input_value()); } - if (lv.needs_output_symtab_entry()) + if (!lv.is_output_symtab_index_set()) { lv.set_output_symtab_index(index); ++index; @@ -1338,6 +1816,42 @@ Sized_relobj<size, big_endian>::do_set_local_dynsym_offset(off_t off) return this->output_local_dynsym_count_; } +// If Symbols_data is not NULL get the section flags from here otherwise +// get it from the file. + +template<int size, bool big_endian> +uint64_t +Sized_relobj<size, big_endian>::do_section_flags(unsigned int shndx) +{ + Symbols_data* sd = this->get_symbols_data(); + if (sd != NULL) + { + const unsigned char* pshdrs = sd->section_headers_data + + This::shdr_size * shndx; + typename This::Shdr shdr(pshdrs); + return shdr.get_sh_flags(); + } + // If sd is NULL, read the section header from the file. + return this->elf_file_.section_flags(shndx); +} + +// Get the section's ent size from Symbols_data. Called by get_section_contents +// in icf.cc + +template<int size, bool big_endian> +uint64_t +Sized_relobj<size, big_endian>::do_section_entsize(unsigned int shndx) +{ + Symbols_data* sd = this->get_symbols_data(); + gold_assert (sd != NULL); + + const unsigned char* pshdrs = sd->section_headers_data + + This::shdr_size * shndx; + typename This::Shdr shdr(pshdrs); + return shdr.get_sh_entsize(); +} + + // Write out the local symbols. template<int size, bool big_endian> @@ -1349,9 +1863,13 @@ Sized_relobj<size, big_endian>::write_local_symbols( Output_symtab_xindex* symtab_xindex, Output_symtab_xindex* dynsym_xindex) { - if (parameters->options().strip_all() - && this->output_local_dynsym_count_ == 0) - return; + const bool strip_all = parameters->options().strip_all(); + if (strip_all) + { + if (this->output_local_dynsym_count_ == 0) + return; + this->output_local_symbol_count_ = 0; + } gold_assert(this->symtab_shndx_ != -1U); if (this->symtab_shndx_ == 0) @@ -1420,17 +1938,16 @@ Sized_relobj<size, big_endian>::write_local_symbols( st_shndx = out_sections[st_shndx]->out_shndx(); if (st_shndx >= elfcpp::SHN_LORESERVE) { - if (lv.needs_output_symtab_entry()) + if (lv.has_output_symtab_entry()) symtab_xindex->add(lv.output_symtab_index(), st_shndx); - if (lv.needs_output_dynsym_entry()) + if (lv.has_output_dynsym_entry()) dynsym_xindex->add(lv.output_dynsym_index(), st_shndx); st_shndx = elfcpp::SHN_XINDEX; } } // Write the symbol to the output symbol table. - if (!parameters->options().strip_all() - && lv.needs_output_symtab_entry()) + if (lv.has_output_symtab_entry()) { elfcpp::Sym_write<size, big_endian> osym(ov); @@ -1447,7 +1964,7 @@ Sized_relobj<size, big_endian>::write_local_symbols( } // Write the symbol to the output dynamic symbol table. - if (lv.needs_output_dynsym_entry()) + if (lv.has_output_dynsym_entry()) { gold_assert(dyn_ov < dyn_oview + dyn_output_size); elfcpp::Sym_write<size, big_endian> osym(dyn_ov); @@ -1566,15 +2083,19 @@ Sized_relobj<size, big_endian>::map_to_kept_section( unsigned int shndx, bool* found) const { - Kept_comdat_section *kept = this->get_kept_comdat_section(shndx); - if (kept != NULL) + Relobj* kept_object; + unsigned int kept_shndx; + if (this->get_kept_comdat_section(shndx, &kept_object, &kept_shndx)) { - gold_assert(kept->object_ != NULL); - *found = true; - Output_section* os = kept->object_->output_section(kept->shndx_); - Address offset = kept->object_->get_output_section_offset(kept->shndx_); - gold_assert(os != NULL && offset != -1U); - return os->address() + offset; + Sized_relobj<size, big_endian>* kept_relobj = + static_cast<Sized_relobj<size, big_endian>*>(kept_object); + Output_section* os = kept_relobj->output_section(kept_shndx); + Address offset = kept_relobj->get_output_section_offset(kept_shndx); + if (os != NULL && offset != invalid_address) + { + *found = true; + return os->address() + offset; + } } *found = false; return 0; @@ -1610,16 +2131,6 @@ Sized_relobj<size, big_endian>::do_get_global_symbol_counts( bool Input_objects::add_object(Object* obj) { - // Set the global target from the first object file we recognize. - Target* target = obj->target(); - if (!parameters->target_valid()) - set_parameters_target(target); - else if (target != ¶meters->target()) - { - obj->error(_("incompatible target")); - return false; - } - // Print the filename if the -t/--trace option is selected. if (parameters->options().trace()) gold_info("%s", obj->name().c_str()); @@ -1641,23 +2152,11 @@ Input_objects::add_object(Object* obj) } this->dynobj_list_.push_back(dynobj); - - // If this is -lc, remember the directory in which we found it. - // We use this when issuing warnings about undefined symbols: as - // a heuristic, we don't warn about system libraries found in - // the same directory as -lc. - if (strncmp(soname, "libc.so", 7) == 0) - { - const char* object_name = dynobj->name().c_str(); - const char* base = lbasename(object_name); - if (base != object_name) - this->system_library_directory_.assign(object_name, - base - 1 - object_name); - } } // Add this object to the cross-referencer if requested. - if (parameters->options().user_set_print_symbol_counts()) + if (parameters->options().user_set_print_symbol_counts() + || parameters->options().cref()) { if (this->cref_ == NULL) this->cref_ = new Cref(); @@ -1667,32 +2166,21 @@ Input_objects::add_object(Object* obj) return true; } -// Return whether an object was found in the system library directory. - -bool -Input_objects::found_in_system_library_directory(const Object* object) const -{ - return (!this->system_library_directory_.empty() - && object->name().compare(0, - this->system_library_directory_.size(), - this->system_library_directory_) == 0); -} - // For each dynamic object, record whether we've seen all of its // explicit dependencies. void Input_objects::check_dynamic_dependencies() const { + bool issued_copy_dt_needed_error = false; for (Dynobj_list::const_iterator p = this->dynobj_list_.begin(); p != this->dynobj_list_.end(); ++p) { const Dynobj::Needed& needed((*p)->needed()); bool found_all = true; - for (Dynobj::Needed::const_iterator pneeded = needed.begin(); - pneeded != needed.end(); - ++pneeded) + Dynobj::Needed::const_iterator pneeded; + for (pneeded = needed.begin(); pneeded != needed.end(); ++pneeded) { if (this->sonames_.find(*pneeded) == this->sonames_.end()) { @@ -1701,6 +2189,25 @@ Input_objects::check_dynamic_dependencies() const } } (*p)->set_has_unknown_needed_entries(!found_all); + + // --copy-dt-needed-entries aka --add-needed is a GNU ld option + // that gold does not support. However, they cause no trouble + // unless there is a DT_NEEDED entry that we don't know about; + // warn only in that case. + if (!found_all + && !issued_copy_dt_needed_error + && (parameters->options().copy_dt_needed_entries() + || parameters->options().add_needed())) + { + const char* optname; + if (parameters->options().copy_dt_needed_entries()) + optname = "--copy-dt-needed-entries"; + else + optname = "--add-needed"; + gold_error(_("%s is not supported but is required for %s in %s"), + optname, (*pneeded).c_str(), (*p)->name().c_str()); + issued_copy_dt_needed_error = true; + } } } @@ -1709,7 +2216,8 @@ Input_objects::check_dynamic_dependencies() const void Input_objects::archive_start(Archive* archive) { - if (parameters->options().user_set_print_symbol_counts()) + if (parameters->options().user_set_print_symbol_counts() + || parameters->options().cref()) { if (this->cref_ == NULL) this->cref_ = new Cref(); @@ -1722,7 +2230,8 @@ Input_objects::archive_start(Archive* archive) void Input_objects::archive_stop(Archive* archive) { - if (parameters->options().user_set_print_symbol_counts()) + if (parameters->options().user_set_print_symbol_counts() + || parameters->options().cref()) this->cref_->add_archive_stop(archive); } @@ -1736,6 +2245,15 @@ Input_objects::print_symbol_counts(const Symbol_table* symtab) const this->cref_->print_symbol_counts(symtab); } +// Print a cross reference table. + +void +Input_objects::print_cref(const Symbol_table* symtab, FILE* f) const +{ + if (parameters->options().cref() && this->cref_ != NULL) + this->cref_->print_cref(symtab, f); +} + // Relocate_info methods. // Return a string describing the location of a relocation. This is @@ -1794,29 +2312,29 @@ using namespace gold; template<int size, bool big_endian> Object* make_elf_sized_object(const std::string& name, Input_file* input_file, - off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr) + off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr, + bool* punconfigured) { - int et = ehdr.get_e_type(); - if (et == elfcpp::ET_REL) - { - Sized_relobj<size, big_endian>* obj = - new Sized_relobj<size, big_endian>(name, input_file, offset, ehdr); - obj->setup(ehdr); - return obj; - } - else if (et == elfcpp::ET_DYN) - { - Sized_dynobj<size, big_endian>* obj = - new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr); - obj->setup(ehdr); - return obj; - } - else + Target* target = select_target(ehdr.get_e_machine(), size, big_endian, + ehdr.get_e_ident()[elfcpp::EI_OSABI], + ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]); + if (target == NULL) + gold_fatal(_("%s: unsupported ELF machine number %d"), + name.c_str(), ehdr.get_e_machine()); + + if (!parameters->target_valid()) + set_parameters_target(target); + else if (target != ¶meters->target()) { - gold_error(_("%s: unsupported ELF file type %d"), - name.c_str(), et); + if (punconfigured != NULL) + *punconfigured = true; + else + gold_error(_("%s: incompatible target"), name.c_str()); return NULL; } + + return target->make_elf_object<size, big_endian>(name, input_file, offset, + ehdr); } } // End anonymous namespace. @@ -1824,73 +2342,60 @@ make_elf_sized_object(const std::string& name, Input_file* input_file, namespace gold { -// Read an ELF file and return the appropriate instance of Object. +// Return whether INPUT_FILE is an ELF object. -Object* -make_elf_object(const std::string& name, Input_file* input_file, off_t offset, - const unsigned char* p, section_offset_type bytes) +bool +is_elf_object(Input_file* input_file, off_t offset, + const unsigned char** start, int *read_size) { - if (bytes < elfcpp::EI_NIDENT) - { - gold_error(_("%s: ELF file too short"), name.c_str()); - return NULL; - } + off_t filesize = input_file->file().filesize(); + int want = elfcpp::Elf_recognizer::max_header_size; + if (filesize - offset < want) + want = filesize - offset; - int v = p[elfcpp::EI_VERSION]; - if (v != elfcpp::EV_CURRENT) - { - if (v == elfcpp::EV_NONE) - gold_error(_("%s: invalid ELF version 0"), name.c_str()); - else - gold_error(_("%s: unsupported ELF version %d"), name.c_str(), v); - return NULL; - } + const unsigned char* p = input_file->file().get_view(offset, 0, want, + true, false); + *start = p; + *read_size = want; - int c = p[elfcpp::EI_CLASS]; - if (c == elfcpp::ELFCLASSNONE) - { - gold_error(_("%s: invalid ELF class 0"), name.c_str()); - return NULL; - } - else if (c != elfcpp::ELFCLASS32 - && c != elfcpp::ELFCLASS64) - { - gold_error(_("%s: unsupported ELF class %d"), name.c_str(), c); - return NULL; - } + return elfcpp::Elf_recognizer::is_elf_file(p, want); +} - int d = p[elfcpp::EI_DATA]; - if (d == elfcpp::ELFDATANONE) - { - gold_error(_("%s: invalid ELF data encoding"), name.c_str()); - return NULL; - } - else if (d != elfcpp::ELFDATA2LSB - && d != elfcpp::ELFDATA2MSB) +// Read an ELF file and return the appropriate instance of Object. + +Object* +make_elf_object(const std::string& name, Input_file* input_file, off_t offset, + const unsigned char* p, section_offset_type bytes, + bool* punconfigured) +{ + if (punconfigured != NULL) + *punconfigured = false; + + std::string error; + bool big_endian = false; + int size = 0; + if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size, + &big_endian, &error)) { - gold_error(_("%s: unsupported ELF data encoding %d"), name.c_str(), d); + gold_error(_("%s: %s"), name.c_str(), error.c_str()); return NULL; } - bool big_endian = d == elfcpp::ELFDATA2MSB; - - if (c == elfcpp::ELFCLASS32) + if (size == 32) { - if (bytes < elfcpp::Elf_sizes<32>::ehdr_size) - { - gold_error(_("%s: ELF file too short"), name.c_str()); - return NULL; - } if (big_endian) { #ifdef HAVE_TARGET_32_BIG elfcpp::Ehdr<32, true> ehdr(p); return make_elf_sized_object<32, true>(name, input_file, - offset, ehdr); + offset, ehdr, punconfigured); #else - gold_error(_("%s: not configured to support " - "32-bit big-endian object"), - name.c_str()); + if (punconfigured != NULL) + *punconfigured = true; + else + gold_error(_("%s: not configured to support " + "32-bit big-endian object"), + name.c_str()); return NULL; #endif } @@ -1899,32 +2404,33 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset, #ifdef HAVE_TARGET_32_LITTLE elfcpp::Ehdr<32, false> ehdr(p); return make_elf_sized_object<32, false>(name, input_file, - offset, ehdr); + offset, ehdr, punconfigured); #else - gold_error(_("%s: not configured to support " - "32-bit little-endian object"), - name.c_str()); + if (punconfigured != NULL) + *punconfigured = true; + else + gold_error(_("%s: not configured to support " + "32-bit little-endian object"), + name.c_str()); return NULL; #endif } } - else + else if (size == 64) { - if (bytes < elfcpp::Elf_sizes<64>::ehdr_size) - { - gold_error(_("%s: ELF file too short"), name.c_str()); - return NULL; - } if (big_endian) { #ifdef HAVE_TARGET_64_BIG elfcpp::Ehdr<64, true> ehdr(p); return make_elf_sized_object<64, true>(name, input_file, - offset, ehdr); + offset, ehdr, punconfigured); #else - gold_error(_("%s: not configured to support " - "64-bit big-endian object"), - name.c_str()); + if (punconfigured != NULL) + *punconfigured = true; + else + gold_error(_("%s: not configured to support " + "64-bit big-endian object"), + name.c_str()); return NULL; #endif } @@ -1933,15 +2439,20 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset, #ifdef HAVE_TARGET_64_LITTLE elfcpp::Ehdr<64, false> ehdr(p); return make_elf_sized_object<64, false>(name, input_file, - offset, ehdr); + offset, ehdr, punconfigured); #else - gold_error(_("%s: not configured to support " - "64-bit little-endian object"), - name.c_str()); + if (punconfigured != NULL) + *punconfigured = true; + else + gold_error(_("%s: not configured to support " + "64-bit little-endian object"), + name.c_str()); return NULL; #endif } } + else + gold_unreachable(); } // Instantiate the templates we need. @@ -2014,4 +2525,48 @@ template struct Relocate_info<64, true>; #endif +#ifdef HAVE_TARGET_32_LITTLE +template +void +Xindex::initialize_symtab_xindex<32, false>(Object*, unsigned int); + +template +void +Xindex::read_symtab_xindex<32, false>(Object*, unsigned int, + const unsigned char*); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Xindex::initialize_symtab_xindex<32, true>(Object*, unsigned int); + +template +void +Xindex::read_symtab_xindex<32, true>(Object*, unsigned int, + const unsigned char*); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Xindex::initialize_symtab_xindex<64, false>(Object*, unsigned int); + +template +void +Xindex::read_symtab_xindex<64, false>(Object*, unsigned int, + const unsigned char*); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Xindex::initialize_symtab_xindex<64, true>(Object*, unsigned int); + +template +void +Xindex::read_symtab_xindex<64, true>(Object*, unsigned int, + const unsigned char*); +#endif + } // End namespace gold. diff --git a/binutils-2.19/gold/object.h b/binutils-2.19/gold/object.h index 188f1f2..59da7c1 100644 --- a/binutils-2.19/gold/object.h +++ b/binutils-2.19/gold/object.h @@ -1,6 +1,6 @@ // object.h -- support for an object file for linking in gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -42,9 +42,11 @@ class Layout; class Output_section; class Output_file; class Output_symtab_xindex; +class Pluginobj; class Dynobj; class Object_merge_map; class Relocatable_relocs; +class Symbols_data; template<typename Stringpool_char> class Stringpool_template; @@ -186,6 +188,8 @@ class Xindex class Object { public: + typedef std::vector<Symbol*> Symbols; + // NAME is the name of the object as we would report it to the user // (e.g., libfoo.a(bar.o) if this is in an archive. INPUT_FILE is // used to read the file. OFFSET is the offset within the input @@ -193,7 +197,8 @@ class Object Object(const std::string& name, Input_file* input_file, bool is_dynamic, off_t offset = 0) : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U), - is_dynamic_(is_dynamic), target_(NULL), xindex_(NULL) + is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false), + has_no_split_stack_(false), no_export_(false), xindex_(NULL) { input_file->file().add_object(); } virtual ~Object() @@ -214,10 +219,44 @@ class Object is_dynamic() const { return this->is_dynamic_; } - // Return the target structure associated with this object. - Target* - target() const - { return this->target_; } + // Return whether this object is needed--true if it is a dynamic + // object which defines some symbol referenced by a regular object. + // We keep the flag here rather than in Dynobj for convenience when + // setting it. + bool + is_needed() const + { return this->is_needed_; } + + // Record that this object is needed. + void + set_is_needed() + { this->is_needed_ = true; } + + // Return whether this object was compiled with -fsplit-stack. + bool + uses_split_stack() const + { return this->uses_split_stack_; } + + // Return whether this object contains any functions compiled with + // the no_split_stack attribute. + bool + has_no_split_stack() const + { return this->has_no_split_stack_; } + + // Returns NULL for Objects that are not plugin objects. This method + // is overridden in the Pluginobj class. + Pluginobj* + pluginobj() + { return this->do_pluginobj(); } + + // Get the file. We pass on const-ness. + Input_file* + input_file() + { return this->input_file_; } + + const Input_file* + input_file() const + { return this->input_file_; } // Lock the underlying file. void @@ -249,13 +288,6 @@ class Object just_symbols() const { return this->input_file()->just_symbols(); } - // Return the sized target structure associated with this object. - // This is like the target method but it returns a pointer of - // appropriate checked type. - template<int size, bool big_endian> - Sized_target<size, big_endian>* - sized_target() const; - // Get the number of sections. unsigned int shnum() const @@ -304,6 +336,11 @@ class Object section_flags(unsigned int shndx) { return this->do_section_flags(shndx); } + // Return the section entsize given a section index. + uint64_t + section_entsize(unsigned int shndx) + { return this->do_section_entsize(shndx); } + // Return the section address given a section index. uint64_t section_address(unsigned int shndx) @@ -342,8 +379,8 @@ class Object // Add symbol information to the global symbol table. void - add_symbols(Symbol_table* symtab, Read_symbols_data* sd) - { this->do_add_symbols(symtab, sd); } + add_symbols(Symbol_table* symtab, Read_symbols_data* sd, Layout *layout) + { this->do_add_symbols(symtab, sd, layout); } // Functions and types for the elfcpp::Elf_file interface. This // permit us to use Object as the File template parameter for @@ -431,7 +468,36 @@ class Object size_t* used) const { this->do_get_global_symbol_counts(symtab, defined, used); } + // Get the symbols defined in this object. + const Symbols* + get_global_symbols() const + { return this->do_get_global_symbols(); } + + // Return whether this object was found in a system directory. + bool + is_in_system_directory() const + { return this->input_file()->is_in_system_directory(); } + + // Return whether we found this object by searching a directory. + bool + searched_for() const + { return this->input_file()->will_search_for(); } + + bool + no_export() const + { return this->no_export_; } + + void + set_no_export(bool value) + { this->no_export_ = value; } + protected: + // Returns NULL for Objects that are not plugin objects. This method + // is overridden in the Pluginobj class. + virtual Pluginobj* + do_pluginobj() + { return NULL; } + // Read the symbols--implemented by child class. virtual void do_read_symbols(Read_symbols_data*) = 0; @@ -443,7 +509,7 @@ class Object // Add symbol information to the global symbol table--implemented by // child class. virtual void - do_add_symbols(Symbol_table*, Read_symbols_data*) = 0; + do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0; // Return the location of the contents of a section. Implemented by // child class. @@ -462,6 +528,10 @@ class Object virtual uint64_t do_section_flags(unsigned int shndx) = 0; + // Get section entsize--implemented by child class. + virtual uint64_t + do_section_entsize(unsigned int shndx) = 0; + // Get section address--implemented by child class. virtual uint64_t do_section_address(unsigned int shndx) = 0; @@ -490,19 +560,8 @@ class Object virtual void do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0; - // Get the file. We pass on const-ness. - Input_file* - input_file() - { return this->input_file_; } - - const Input_file* - input_file() const - { return this->input_file_; } - - // Set the target. - void - set_target(int machine, int size, bool big_endian, int osabi, - int abiversion); + virtual const Symbols* + do_get_global_symbols() const = 0; // Set the number of sections. void @@ -532,6 +591,12 @@ class Object handle_gnu_warning_section(const char* name, unsigned int shndx, Symbol_table*); + // If NAME is the name of the special section which indicates that + // this object was compiled with -fstack-split, mark it accordingly, + // and return true. Otherwise return false. + bool + handle_split_stack_section(const char* name); + private: // This class may not be copied. Object(const Object&); @@ -547,25 +612,23 @@ class Object // Number of input sections. unsigned int shnum_; // Whether this is a dynamic object. - bool is_dynamic_; - // Target functions--may be NULL if the target is not known. - Target* target_; + bool is_dynamic_ : 1; + // Whether this object is needed. This is only set for dynamic + // objects, and means that the object defined a symbol which was + // used by a reference from a regular object. + bool is_needed_ : 1; + // Whether this object was compiled with -fsplit-stack. + bool uses_split_stack_ : 1; + // Whether this object contains any functions compiled with the + // no_split_stack attribute. + bool has_no_split_stack_ : 1; + // True if exclude this object from automatic symbol export. + // This is used only for archive objects. + bool no_export_ : 1; // Many sections for objects with more than SHN_LORESERVE sections. Xindex* xindex_; }; -// Implement sized_target inline for efficiency. This approach breaks -// static type checking, but is made safe using asserts. - -template<int size, bool big_endian> -inline Sized_target<size, big_endian>* -Object::sized_target() const -{ - gold_assert(this->target_->get_size() == size); - gold_assert(this->target_->is_big_endian() ? big_endian : !big_endian); - return static_cast<Sized_target<size, big_endian>*>(this->target_); -} - // A regular object (ET_REL). This is an abstract base class itself. // The implementation is the template class Sized_relobj. @@ -577,19 +640,59 @@ class Relobj : public Object output_sections_(), map_to_relocatable_relocs_(NULL), object_merge_map_(NULL), - relocs_must_follow_section_writes_(false) + relocs_must_follow_section_writes_(false), + sd_(NULL) { } + // During garbage collection, the Read_symbols_data pass for + // each object is stored as layout needs to be done after + // reloc processing. + Symbols_data* + get_symbols_data() + { return this->sd_; } + + // Decides which section names have to be included in the worklist + // as roots. + bool + is_section_name_included(const char *name); + + void + copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd, + unsigned int section_header_size); + + void + set_symbols_data(Symbols_data* sd) + { this->sd_ = sd; } + + // During garbage collection, the Read_relocs pass for all objects + // is done before scanning the relocs. In that case, this->rd_ is + // used to store the information from Read_relocs for each object. + // This data is also used to compute the list of relevant sections. + Read_relocs_data* + get_relocs_data() + { return this->rd_; } + + void + set_relocs_data(Read_relocs_data* rd) + { this->rd_ = rd; } + + virtual bool + is_output_section_offset_invalid(unsigned int shndx) const = 0; + // Read the relocs. void read_relocs(Read_relocs_data* rd) { return this->do_read_relocs(rd); } + // Process the relocs, during garbage collection only. + void + gc_process_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd) + { return this->do_gc_process_relocs(symtab, layout, rd); } + // Scan the relocs and adjust the symbol table. void - scan_relocs(const General_options& options, Symbol_table* symtab, - Layout* layout, Read_relocs_data* rd) - { return this->do_scan_relocs(options, symtab, layout, rd); } + scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd) + { return this->do_scan_relocs(symtab, layout, rd); } // The number of local symbols in the input symbol table. virtual unsigned int @@ -608,8 +711,8 @@ class Relobj : public Object // indexes for the local variables, and set the offset where local // symbol information will be stored. Returns the new local symbol index. unsigned int - finalize_local_symbols(unsigned int index, off_t off) - { return this->do_finalize_local_symbols(index, off); } + finalize_local_symbols(unsigned int index, off_t off, Symbol_table* symtab) + { return this->do_finalize_local_symbols(index, off, symtab); } // Set the output dynamic symbol table indexes for the local variables. unsigned int @@ -623,9 +726,8 @@ class Relobj : public Object // Relocate the input sections and write out the local symbols. void - relocate(const General_options& options, const Symbol_table* symtab, - const Layout* layout, Output_file* of) - { return this->do_relocate(options, symtab, layout, of); } + relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of) + { return this->do_relocate(symtab, layout, of); } // Return whether an input section is being included in the link. bool @@ -645,6 +747,16 @@ class Relobj : public Object return this->output_sections_[shndx]; } + // The the output section of the input section with index SHNDX. + // This is only used currently to remove a section from the link in + // relaxation. + void + set_output_section(unsigned int shndx, Output_section* os) + { + gold_assert(shndx < this->output_sections_.size()); + this->output_sections_[shndx] = os; + } + // Given a section index, return the offset in the Output_section. // The return value will be -1U if the section is specially mapped, // such as a merge section. @@ -653,7 +765,7 @@ class Relobj : public Object { return this->do_output_section_offset(shndx); } // Set the offset of an input section within its output section. - virtual void + void set_section_offset(unsigned int shndx, uint64_t off) { this->do_set_section_offset(shndx, off); } @@ -694,6 +806,12 @@ class Relobj : public Object return (*this->map_to_relocatable_relocs_)[reloc_shndx]; } + // Layout sections whose layout was deferred while waiting for + // input files from a plugin. + void + layout_deferred_sections(Layout* layout) + { this->do_layout_deferred_sections(layout); } + protected: // The output section to be used for each input section, indexed by // the input section number. The output section is NULL if the @@ -704,10 +822,13 @@ class Relobj : public Object virtual void do_read_relocs(Read_relocs_data*) = 0; + // Process the relocs--implemented by child class. + virtual void + do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0; + // Scan the relocs--implemented by child class. virtual void - do_scan_relocs(const General_options&, Symbol_table*, Layout*, - Read_relocs_data*) = 0; + do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0; // Return the number of local symbols--implemented by child class. virtual unsigned int @@ -722,7 +843,7 @@ class Relobj : public Object // for the local variables, and set the offset where local symbol // information will be stored. virtual unsigned int - do_finalize_local_symbols(unsigned int, off_t) = 0; + do_finalize_local_symbols(unsigned int, off_t, Symbol_table*) = 0; // Set the output dynamic symbol table indexes for the local variables. virtual unsigned int @@ -735,8 +856,7 @@ class Relobj : public Object // Relocate the input sections and write out the local // symbols--implemented by child class. virtual void - do_relocate(const General_options& options, const Symbol_table* symtab, - const Layout*, Output_file* of) = 0; + do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of) = 0; // Get the offset of a section--implemented by child class. virtual uint64_t @@ -746,6 +866,11 @@ class Relobj : public Object virtual void do_set_section_offset(unsigned int shndx, uint64_t off) = 0; + // Layout sections whose layout was deferred while waiting for + // input files from a plugin--implemented by child class. + virtual void + do_layout_deferred_sections(Layout*) = 0; + // Return the vector mapping input sections to output sections. Output_sections& output_sections() @@ -781,6 +906,13 @@ class Relobj : public Object // Whether we need to wait for output sections to be written before // we can apply relocations. bool relocs_must_follow_section_writes_; + // Used to store the relocs data computed by the Read_relocs pass. + // Used during garbage collection of unused sections. + Read_relocs_data* rd_; + // Used to store the symbols data computed by the Read_symbols pass. + // Again used during garbage collection when laying out referenced + // sections. + gold::Symbols_data *sd_; }; // This class is used to handle relocations against a section symbol @@ -955,17 +1087,39 @@ class Symbol_value input_value() const { return this->u_.value; } - // Return whether this symbol should go into the output symbol + // Return whether we have set the index in the output symbol table + // yet. + bool + is_output_symtab_index_set() const + { + return (this->output_symtab_index_ != 0 + && this->output_symtab_index_ != -2U); + } + + // Return whether this symbol may be discarded from the normal + // symbol table. + bool + may_be_discarded_from_output_symtab() const + { + gold_assert(!this->is_output_symtab_index_set()); + return this->output_symtab_index_ != -2U; + } + + // Return whether this symbol has an entry in the output symbol // table. bool - needs_output_symtab_entry() const - { return this->output_symtab_index_ != -1U; } + has_output_symtab_entry() const + { + gold_assert(this->is_output_symtab_index_set()); + return this->output_symtab_index_ != -1U; + } // Return the index in the output symbol table. unsigned int output_symtab_index() const { - gold_assert(this->output_symtab_index_ != 0); + gold_assert(this->is_output_symtab_index_set() + && this->output_symtab_index_ != -1U); return this->output_symtab_index_; } @@ -973,7 +1127,8 @@ class Symbol_value void set_output_symtab_index(unsigned int i) { - gold_assert(this->output_symtab_index_ == 0); + gold_assert(!this->is_output_symtab_index_set()); + gold_assert(i != 0 && i != -1U && i != -2U); this->output_symtab_index_ = i; } @@ -986,6 +1141,15 @@ class Symbol_value this->output_symtab_index_ = -1U; } + // Record that this symbol must go into the output symbol table, + // because it there is a relocation that uses it. + void + set_must_have_output_symtab_entry() + { + gold_assert(!this->is_output_symtab_index_set()); + this->output_symtab_index_ = -2U; + } + // Set the index in the output dynamic symbol table. void set_needs_output_dynsym_entry() @@ -994,7 +1158,7 @@ class Symbol_value this->output_dynsym_index_ = 0; } - // Return whether this symbol should go into the output symbol + // Return whether this symbol should go into the dynamic symbol // table. bool needs_output_dynsym_entry() const @@ -1002,11 +1166,21 @@ class Symbol_value return this->output_dynsym_index_ != -1U; } + // Return whether this symbol has an entry in the dynamic symbol + // table. + bool + has_output_dynsym_entry() const + { + gold_assert(this->output_dynsym_index_ != 0); + return this->output_dynsym_index_ != -1U; + } + // Record that this symbol should go into the dynamic symbol table. void set_output_dynsym_index(unsigned int i) { gold_assert(this->output_dynsym_index_ == 0); + gold_assert(i != 0 && i != -1U); this->output_dynsym_index_ = i; } @@ -1063,10 +1237,13 @@ class Symbol_value private: // The index of this local symbol in the output symbol table. This - // will be -1 if the symbol should not go into the symbol table. + // will be 0 if no value has been assigned yet, and the symbol may + // be omitted. This will be -1U if the symbol should not go into + // the symbol table. This will be -2U if the symbol must go into + // the symbol table, but no index has been assigned yet. unsigned int output_symtab_index_; // The index of this local symbol in the dynamic symbol table. This - // will be -1 if the symbol should not go into the symbol table. + // will be -1U if the symbol should not go into the symbol table. unsigned int output_dynsym_index_; // The section index in the input file in which this symbol is // defined. @@ -1174,6 +1351,30 @@ class Got_offset_list Got_offset_list* got_next_; }; +// This type is used to modify relocations for -fsplit-stack. It is +// indexed by relocation index, and means that the relocation at that +// index should use the symbol from the vector, rather than the one +// indicated by the relocation. + +class Reloc_symbol_changes +{ + public: + Reloc_symbol_changes(size_t count) + : vec_(count, NULL) + { } + + void + set(size_t i, Symbol* sym) + { this->vec_[i] = sym; } + + const Symbol* + operator[](size_t i) const + { return this->vec_[i]; } + + private: + std::vector<Symbol*> vec_; +}; + // A regular object file. This is size and endian specific. template<int size, bool big_endian> @@ -1184,14 +1385,23 @@ class Sized_relobj : public Relobj typedef std::vector<Symbol*> Symbols; typedef std::vector<Symbol_value<size> > Local_values; + static const Address invalid_address = static_cast<Address>(0) - 1; + Sized_relobj(const std::string& name, Input_file* input_file, off_t offset, const typename elfcpp::Ehdr<size, big_endian>&); ~Sized_relobj(); - // Set up the object file based on the ELF header. + // Checks if the offset of input section SHNDX within its output + // section is invalid. + bool + is_output_section_offset_invalid(unsigned int shndx) const + { return this->get_output_section_offset(shndx) == invalid_address; } + + // Set up the object file based on TARGET. void - setup(const typename elfcpp::Ehdr<size, big_endian>&); + setup() + { this->do_setup(); } // Return the number of symbols. This is only valid after // Object::add_symbols has been called. @@ -1256,10 +1466,13 @@ class Sized_relobj : public Relobj return this->local_values_[sym].input_shndx(is_ordinary); } - // Return the appropriate Sized_target structure. - Sized_target<size, big_endian>* - sized_target() - { return this->Object::sized_target<size, big_endian>(); } + // Record that local symbol SYM must be in the output symbol table. + void + set_must_have_output_symtab_entry(unsigned int sym) + { + gold_assert(sym < this->local_values_.size()); + this->local_values_[sym].set_must_have_output_symtab_entry(); + } // Record that local symbol SYM needs a dynamic symbol entry. void @@ -1335,6 +1548,10 @@ class Sized_relobj : public Relobj map_to_kept_section(unsigned int shndx, bool* found) const; protected: + // Set up. + virtual void + do_setup(); + // Read the symbols. void do_read_symbols(Read_symbols_data*); @@ -1348,18 +1565,27 @@ class Sized_relobj : public Relobj void do_layout(Symbol_table*, Layout*, Read_symbols_data*); + // Layout sections whose layout was deferred while waiting for + // input files from a plugin. + void + do_layout_deferred_sections(Layout*); + // Add the symbols to the symbol table. void - do_add_symbols(Symbol_table*, Read_symbols_data*); + do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*); // Read the relocs. void do_read_relocs(Read_relocs_data*); + // Process the relocs to find list of referenced sections. Used only + // during garbage collection. + void + do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*); + // Scan the relocs and adjust the symbol table. void - do_scan_relocs(const General_options&, Symbol_table*, Layout*, - Read_relocs_data*); + do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*); // Count the local symbols. void @@ -1368,7 +1594,7 @@ class Sized_relobj : public Relobj // Finalize the local symbols. unsigned int - do_finalize_local_symbols(unsigned int, off_t); + do_finalize_local_symbols(unsigned int, off_t, Symbol_table*); // Set the offset where local dynamic symbol information will be stored. unsigned int @@ -1380,8 +1606,7 @@ class Sized_relobj : public Relobj // Relocate the input sections and write out the local symbols. void - do_relocate(const General_options& options, const Symbol_table* symtab, - const Layout*, Output_file* of); + do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of); // Get the size of a section. uint64_t @@ -1400,8 +1625,11 @@ class Sized_relobj : public Relobj // Return section flags. uint64_t - do_section_flags(unsigned int shndx) - { return this->elf_file_.section_flags(shndx); } + do_section_flags(unsigned int shndx); + + // Return section entsize. + uint64_t + do_section_entsize(unsigned int shndx); // Return section address. uint64_t @@ -1436,19 +1664,89 @@ class Sized_relobj : public Relobj void do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const; + // Get the global symbols. + const Symbols* + do_get_global_symbols() const + { return &this->symbols_; } + // Get the offset of a section. uint64_t do_output_section_offset(unsigned int shndx) const - { return this->get_output_section_offset(shndx); } + { + Address off = this->get_output_section_offset(shndx); + if (off == invalid_address) + return -1ULL; + return off; + } // Set the offset of a section. void do_set_section_offset(unsigned int shndx, uint64_t off) { gold_assert(shndx < this->section_offsets_.size()); - this->section_offsets_[shndx] = convert_types<Address, uint64_t>(off); + this->section_offsets_[shndx] = + (off == static_cast<uint64_t>(-1) + ? invalid_address + : convert_types<Address, uint64_t>(off)); } + // Adjust a section index if necessary. + unsigned int + adjust_shndx(unsigned int shndx) + { + if (shndx >= elfcpp::SHN_LORESERVE) + shndx += this->elf_file_.large_shndx_offset(); + return shndx; + } + + // Initialize input to output maps for section symbols in merged + // sections. + void + initialize_input_to_output_maps(); + + // Free the input to output maps for section symbols in merged + // sections. + void + free_input_to_output_maps(); + + // Return symbol table section index. + unsigned int + symtab_shndx() const + { return this->symtab_shndx_; } + + // Allow a child class to access the ELF file. + elfcpp::Elf_file<size, big_endian, Object>* + elf_file() + { return &this->elf_file_; } + + // Allow a child class to access the local values. + Local_values* + local_values() + { return &this->local_values_; } + + // Views and sizes when relocating. + struct View_size + { + unsigned char* view; + typename elfcpp::Elf_types<size>::Elf_Addr address; + off_t offset; + section_size_type view_size; + bool is_input_output_view; + bool is_postprocessing_view; + }; + + typedef std::vector<View_size> Views; + + // This may be overriden by a child class. + virtual void + do_relocate_sections(const Symbol_table* symtab, const Layout* layout, + const unsigned char* pshdrs, Views* pviews); + + // Allow a child to set output local symbol count. + void + set_output_local_symbol_count(unsigned int value) + { this->output_local_symbol_count_ = value; } + private: // For convenience. typedef Sized_relobj<size, big_endian> This; @@ -1462,51 +1760,15 @@ class Sized_relobj : public Relobj // kept section. struct Kept_comdat_section { - Kept_comdat_section(Sized_relobj<size, big_endian>* object, - unsigned int shndx) - : object_(object), shndx_(shndx) + Kept_comdat_section(Relobj* a_object, unsigned int a_shndx) + : object(a_object), shndx(a_shndx) { } - Sized_relobj<size, big_endian>* object_; - unsigned int shndx_; + Relobj* object; + unsigned int shndx; }; - typedef std::map<unsigned int, Kept_comdat_section*> + typedef std::map<unsigned int, Kept_comdat_section> Kept_comdat_section_table; - // Information needed to keep track of kept comdat groups. This is - // simply a map from the section name to its section index. This may - // not be a one-to-one mapping, but we ignore that possibility since - // this is used only to attempt to handle stray relocations from - // non-comdat debug sections that refer to comdat loadable sections. - typedef Unordered_map<std::string, unsigned int> Comdat_group; - - // A map from group section index to the table of group members. - typedef std::map<unsigned int, Comdat_group*> Comdat_group_table; - - // Find a comdat group table given its group section SHNDX. - Comdat_group* - find_comdat_group(unsigned int shndx) const - { - Comdat_group_table::const_iterator p = - this->comdat_groups_.find(shndx); - if (p != this->comdat_groups_.end()) - return p->second; - return NULL; - } - - // Record a new comdat group whose group section index is SHNDX. - void - add_comdat_group(unsigned int shndx, Comdat_group* group) - { this->comdat_groups_[shndx] = group; } - - // Adjust a section index if necessary. - unsigned int - adjust_shndx(unsigned int shndx) - { - if (shndx >= elfcpp::SHN_LORESERVE) - shndx += this->elf_file_.large_shndx_offset(); - return shndx; - } - // Find the SHT_SYMTAB section, given the section headers. void find_symtab(const unsigned char* pshdrs); @@ -1533,18 +1795,11 @@ class Sized_relobj : public Relobj include_linkonce_section(Layout*, unsigned int, const char*, const elfcpp::Shdr<size, big_endian>&); - // Views and sizes when relocating. - struct View_size - { - unsigned char* view; - typename elfcpp::Elf_types<size>::Elf_Addr address; - off_t offset; - section_size_type view_size; - bool is_input_output_view; - bool is_postprocessing_view; - }; - - typedef std::vector<View_size> Views; + // Layout an input section. + void + layout_section(Layout* layout, unsigned int shndx, const char* name, + typename This::Shdr& shdr, unsigned int reloc_shndx, + unsigned int reloc_type); // Write section data to the output file. Record the views and // sizes in VIEWS for use when relocating. @@ -1553,20 +1808,20 @@ class Sized_relobj : public Relobj // Relocate the sections in the output file. void - relocate_sections(const General_options& options, const Symbol_table*, - const Layout*, const unsigned char* pshdrs, Views*); + relocate_sections(const Symbol_table* symtab, const Layout* layout, + const unsigned char* pshdrs, Views* pviews) + { this->do_relocate_sections(symtab, layout, pshdrs, pviews); } // Scan the input relocations for --emit-relocs. void - emit_relocs_scan(const General_options&, Symbol_table*, Layout*, - const unsigned char* plocal_syms, + emit_relocs_scan(Symbol_table*, Layout*, const unsigned char* plocal_syms, const Read_relocs_data::Relocs_list::iterator&); // Scan the input relocations for --emit-relocs, templatized on the // type of the relocation section. template<int sh_type> void - emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*, + emit_relocs_scan_reltype(Symbol_table*, Layout*, const unsigned char* plocal_syms, const Read_relocs_data::Relocs_list::iterator&, Relocatable_relocs*); @@ -1592,15 +1847,29 @@ class Sized_relobj : public Relobj unsigned char* reloc_view, section_size_type reloc_view_size); - // Initialize input to output maps for section symbols in merged - // sections. + // A type shared by split_stack_adjust_reltype and find_functions. + typedef std::map<section_offset_type, section_size_type> Function_offsets; + + // Check for -fsplit-stack routines calling non-split-stack routines. void - initialize_input_to_output_maps(); + split_stack_adjust(const Symbol_table*, const unsigned char* pshdrs, + unsigned int sh_type, unsigned int shndx, + const unsigned char* prelocs, size_t reloc_count, + unsigned char* view, section_size_type view_size, + Reloc_symbol_changes** reloc_map); - // Free the input to output maps for section symbols in merged - // sections. + template<int sh_type> void - free_input_to_output_maps(); + split_stack_adjust_reltype(const Symbol_table*, const unsigned char* pshdrs, + unsigned int shndx, const unsigned char* prelocs, + size_t reloc_count, unsigned char* view, + section_size_type view_size, + Reloc_symbol_changes** reloc_map); + + // Find all functions in a section. + void + find_functions(const unsigned char* pshdrs, unsigned int shndx, + Function_offsets*); // Write out the local symbols. void @@ -1621,20 +1890,26 @@ class Sized_relobj : public Relobj // Record a mapping from discarded section SHNDX to the corresponding // kept section. void - set_kept_comdat_section(unsigned int shndx, Kept_comdat_section* kept) + set_kept_comdat_section(unsigned int shndx, Relobj* kept_object, + unsigned int kept_shndx) { - this->kept_comdat_sections_[shndx] = kept; + Kept_comdat_section kept(kept_object, kept_shndx); + this->kept_comdat_sections_.insert(std::make_pair(shndx, kept)); } - // Find the kept section corresponding to the discarded section SHNDX. - Kept_comdat_section* - get_kept_comdat_section(unsigned int shndx) const + // Find the kept section corresponding to the discarded section + // SHNDX. Return true if found. + bool + get_kept_comdat_section(unsigned int shndx, Relobj** kept_object, + unsigned int* kept_shndx) const { typename Kept_comdat_section_table::const_iterator p = this->kept_comdat_sections_.find(shndx); if (p == this->kept_comdat_sections_.end()) - return NULL; - return p->second; + return false; + *kept_object = p->second.object; + *kept_shndx = p->second.shndx; + return true; } // The GOT offsets of local symbols. This map also stores GOT offsets @@ -1656,6 +1931,25 @@ class Sized_relobj : public Relobj }; typedef Unordered_map<unsigned int, Tls_got_entry> Local_tls_got_offsets; + // Saved information for sections whose layout was deferred. + struct Deferred_layout + { + static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size; + Deferred_layout(unsigned int shndx, const char* name, + const unsigned char* pshdr, + unsigned int reloc_shndx, unsigned int reloc_type) + : shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx), + reloc_type_(reloc_type) + { + memcpy(this->shdr_data_, pshdr, shdr_size); + } + unsigned int shndx_; + std::string name_; + unsigned int reloc_shndx_; + unsigned int reloc_type_; + unsigned char shdr_data_[shdr_size]; + }; + // General access to the ELF file. elfcpp::Elf_file<size, big_endian, Object> elf_file_; // Index of SHT_SYMTAB section. @@ -1681,15 +1975,18 @@ class Sized_relobj : public Relobj // for TLS symbols, indexed by symbol number. Local_got_offsets local_got_offsets_; // For each input section, the offset of the input section in its - // output section. This is -1U if the input section requires a + // output section. This is INVALID_ADDRESS if the input section requires a // special mapping. std::vector<Address> section_offsets_; // Table mapping discarded comdat sections to corresponding kept sections. Kept_comdat_section_table kept_comdat_sections_; - // Table of kept comdat groups. - Comdat_group_table comdat_groups_; // Whether this object has a GNU style .eh_frame section. bool has_eh_frame_; + // If this object has a GNU style .eh_frame section that is discarded in + // output, record the index here. Otherwise it is -1U. + unsigned int discarded_eh_frame_shndx_; + // The list of sections whose layout was deferred. + std::vector<Deferred_layout> deferred_layout_; }; // A class to manage the list of all objects. @@ -1698,8 +1995,7 @@ class Input_objects { public: Input_objects() - : relobj_list_(), dynobj_list_(), sonames_(), system_library_directory_(), - cref_(NULL) + : relobj_list_(), dynobj_list_(), sonames_(), cref_(NULL) { } // The type of the list of input relocateable objects. @@ -1737,6 +2033,10 @@ class Input_objects void print_symbol_counts(const Symbol_table*) const; + // Print a cross reference table. + void + print_cref(const Symbol_table*, FILE*) const; + // Iterate over all regular objects. Relobj_iterator @@ -1762,6 +2062,11 @@ class Input_objects any_dynamic() const { return !this->dynobj_list_.empty(); } + // Return the number of non dynamic objects. + int + number_of_relobjs() const + { return this->relobj_list_.size(); } + // Return the number of input objects. int number_of_input_objects() const @@ -1777,8 +2082,6 @@ class Input_objects Dynobj_list dynobj_list_; // SONAMEs that we have seen. Unordered_set<std::string> sonames_; - // The directory in which we find the libc.so. - std::string system_library_directory_; // Manage cross-references if requested. Cref* cref_; }; @@ -1789,8 +2092,6 @@ class Input_objects template<int size, bool big_endian> struct Relocate_info { - // Command line options. - const General_options* options; // Symbol table. const Symbol_table* symtab; // Layout. @@ -1799,8 +2100,12 @@ struct Relocate_info Sized_relobj<size, big_endian>* object; // Section index of relocation section. unsigned int reloc_shndx; + // Section header of relocation section. + const unsigned char* reloc_shdr; // Section index of section being relocated. unsigned int data_shndx; + // Section header of data section. + const unsigned char* data_shdr; // Return a string showing the location of a relocation. This is // only used for error messages. @@ -1808,13 +2113,49 @@ struct Relocate_info location(size_t relnum, off_t reloffset) const; }; +// This is used to represent a section in an object and is used as the +// key type for various section maps. +typedef std::pair<Object*, unsigned int> Section_id; + +// This is similar to Section_id but is used when the section +// pointers are const. +typedef std::pair<const Object*, unsigned int> Const_section_id; + +// The hash value is based on the address of an object in memory during +// linking. It is okay to use this for looking up sections but never use +// this in an unordered container that we want to traverse in a repeatable +// manner. + +struct Section_id_hash +{ + size_t operator()(const Section_id& loc) const + { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; } +}; + +struct Const_section_id_hash +{ + size_t operator()(const Const_section_id& loc) const + { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; } +}; + +// Return whether INPUT_FILE contains an ELF object start at file +// offset OFFSET. This sets *START to point to a view of the start of +// the file. It sets *READ_SIZE to the number of bytes in the view. + +extern bool +is_elf_object(Input_file* input_file, off_t offset, + const unsigned char** start, int *read_size); + // Return an Object appropriate for the input file. P is BYTES long, -// and holds the ELF header. +// and holds the ELF header. If PUNCONFIGURED is not NULL, then if +// this sees an object the linker is not configured to support, it +// sets *PUNCONFIGURED to true and returns NULL without giving an +// error message. extern Object* make_elf_object(const std::string& name, Input_file*, off_t offset, const unsigned char* p, - section_offset_type bytes); + section_offset_type bytes, bool* punconfigured); } // end namespace gold diff --git a/binutils-2.19/gold/options.cc b/binutils-2.19/gold/options.cc index 78f0b1a..cf29fe7 100644 --- a/binutils-2.19/gold/options.cc +++ b/binutils-2.19/gold/options.cc @@ -1,6 +1,6 @@ // options.c -- handle command line options for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -22,8 +22,10 @@ #include "gold.h" +#include <cerrno> #include <cstdlib> #include <cstring> +#include <fstream> #include <vector> #include <iostream> #include <sys/stat.h> @@ -36,6 +38,7 @@ #include "script.h" #include "target-select.h" #include "options.h" +#include "plugin.h" namespace gold { @@ -46,6 +49,11 @@ Position_dependent_options::default_options_; namespace options { +// This flag is TRUE if we should register the command-line options as they +// are constructed. It is set after contruction of the options within +// class Position_dependent_options. +static bool ready_to_register = false; + // This global variable is set up as General_options is constructed. static std::vector<const One_option*> registered_options; @@ -59,6 +67,9 @@ static One_option* short_options[128]; void One_option::register_option() { + if (!ready_to_register) + return; + registered_options.push_back(this); // We can't make long_options a static Option_map because we can't @@ -74,7 +85,10 @@ One_option::register_option() const int shortname_as_int = static_cast<int>(this->shortname); gold_assert(shortname_as_int >= 0 && shortname_as_int < 128); if (this->shortname != '\0') - short_options[shortname_as_int] = this; + { + gold_assert(short_options[shortname_as_int] == NULL); + short_options[shortname_as_int] = this; + } } void @@ -181,6 +195,16 @@ parse_uint(const char* option_name, const char* arg, int* retval) } void +parse_int(const char* option_name, const char* arg, int* retval) +{ + char* endptr; + *retval = strtol(arg, &endptr, 0); + if (*endptr != '\0') + gold_fatal(_("%s: invalid option value (expected an integer): %s"), + option_name, arg); +} + +void parse_uint64(const char* option_name, const char* arg, uint64_t *retval) { char* endptr; @@ -264,14 +288,18 @@ General_options::parse_help(const char*, const char*, Command_line*) void General_options::parse_version(const char* opt, const char*, Command_line*) { - gold::print_version(opt[0] == '-' && opt[1] == 'v'); - ::exit(EXIT_SUCCESS); + bool print_short = (opt[0] == '-' && opt[1] == 'v'); + gold::print_version(print_short); + this->printed_version_ = true; + if (!print_short) + ::exit(EXIT_SUCCESS); } void General_options::parse_V(const char*, const char*, Command_line*) { gold::print_version(true); + this->printed_version_ = true; printf(_(" Supported targets:\n")); std::vector<const char*> supported_names; gold::supported_target_names(&supported_names); @@ -289,13 +317,67 @@ General_options::parse_defsym(const char*, const char* arg, } void +General_options::parse_incremental_changed(const char*, const char*, + Command_line*) +{ + this->implicit_incremental_ = true; + this->incremental_disposition_ = INCREMENTAL_CHANGED; +} + +void +General_options::parse_incremental_unchanged(const char*, const char*, + Command_line*) +{ + this->implicit_incremental_ = true; + this->incremental_disposition_ = INCREMENTAL_UNCHANGED; +} + +void +General_options::parse_incremental_unknown(const char*, const char*, + Command_line*) +{ + this->implicit_incremental_ = true; + this->incremental_disposition_ = INCREMENTAL_CHECK; +} + +void General_options::parse_library(const char*, const char* arg, Command_line* cmdline) { - Input_file_argument file(arg, true, "", false, *this); + Input_file_argument::Input_file_type type; + const char *name; + if (arg[0] == ':') + { + type = Input_file_argument::INPUT_FILE_TYPE_SEARCHED_FILE; + name = arg + 1; + } + else + { + type = Input_file_argument::INPUT_FILE_TYPE_LIBRARY; + name = arg; + } + Input_file_argument file(name, type, "", false, *this); cmdline->inputs().add_file(file); } +#ifdef ENABLE_PLUGINS +void +General_options::parse_plugin(const char*, const char* arg, + Command_line*) +{ + this->add_plugin(arg); +} + +// Parse --plugin-opt. + +void +General_options::parse_plugin_opt(const char*, const char* arg, + Command_line*) +{ + this->add_plugin_option(arg); +} +#endif // ENABLE_PLUGINS + void General_options::parse_R(const char* option, const char* arg, Command_line* cmdline) @@ -311,10 +393,68 @@ void General_options::parse_just_symbols(const char*, const char* arg, Command_line* cmdline) { - Input_file_argument file(arg, false, "", true, *this); + Input_file_argument file(arg, Input_file_argument::INPUT_FILE_TYPE_FILE, + "", true, *this); cmdline->inputs().add_file(file); } +// Handle --section-start. + +void +General_options::parse_section_start(const char*, const char* arg, + Command_line*) +{ + const char* eq = strchr(arg, '='); + if (eq == NULL) + { + gold_error(_("invalid argument to --section-start; " + "must be SECTION=ADDRESS")); + return; + } + + std::string section_name(arg, eq - arg); + + ++eq; + const char* val_start = eq; + if (eq[0] == '0' && (eq[1] == 'x' || eq[1] == 'X')) + eq += 2; + if (*eq == '\0') + { + gold_error(_("--section-start address missing")); + return; + } + uint64_t addr = 0; + hex_init(); + for (; *eq != '\0'; ++eq) + { + if (!hex_p(*eq)) + { + gold_error(_("--section-start argument %s is not a valid hex number"), + val_start); + return; + } + addr <<= 4; + addr += hex_value(*eq); + } + + this->section_starts_[section_name] = addr; +} + +// Look up a --section-start value. + +bool +General_options::section_start(const char* secname, uint64_t* paddr) const +{ + if (this->section_starts_.empty()) + return false; + std::map<std::string, uint64_t>::const_iterator p = + this->section_starts_.find(secname); + if (p == this->section_starts_.end()) + return false; + *paddr = p->second; + return true; +} + void General_options::parse_static(const char*, const char*, Command_line*) { @@ -338,6 +478,14 @@ General_options::parse_version_script(const char*, const char* arg, } void +General_options::parse_dynamic_list(const char*, const char* arg, + Command_line* cmdline) +{ + if (!read_dynamic_list(arg, cmdline, &this->dynamic_list_)) + gold::gold_fatal(_("unable to parse dynamic-list script file %s"), arg); +} + +void General_options::parse_start_group(const char*, const char*, Command_line* cmdline) { @@ -351,27 +499,68 @@ General_options::parse_end_group(const char*, const char*, cmdline->inputs().end_group(); } -} // End namespace gold. - -namespace -{ +// The function add_excluded_libs() in ld/ldlang.c of GNU ld breaks up a list +// of names seperated by commas or colons and puts them in a linked list. +// We implement the same parsing of names here but store names in an unordered +// map to speed up searching of names. void -usage() +General_options::parse_exclude_libs(const char*, const char* arg, + Command_line*) { - fprintf(stderr, - _("%s: use the --help option for usage information\n"), - gold::program_name); - ::exit(EXIT_FAILURE); + const char *p = arg; + + while (*p != '\0') + { + size_t length = strcspn(p, ",:"); + this->excluded_libs_.insert(std::string(p, length)); + p += (p[length] ? length + 1 : length); + } } -void -usage(const char* msg, const char *opt) +// The checking logic is based on the function check_excluded_libs() in +// ld/ldlang.c of GNU ld but our implementation is different because we use +// an unordered map instead of a linked list, which is what GNU ld uses. GNU +// ld searches sequentially in the excluded libs list. For a given archive, +// a match is found if the archive's name matches exactly one of the list +// entry or if the archive's name is of the form FOO.a and FOO matches exactly +// one of the list entry. An entry "ALL" in the list is considered as a +// wild-card and matches any given name. + +bool +General_options::check_excluded_libs (const std::string &name) const { - fprintf(stderr, - _("%s: %s: %s\n"), - gold::program_name, opt, msg); - usage(); + Unordered_set<std::string>::const_iterator p; + + // Exit early for the most common case. + if (excluded_libs_.empty()) + return false; + + // If we see "ALL", all archives are excluded from automatic export. + p = excluded_libs_.find(std::string("ALL")); + if (p != excluded_libs_.end()) + return true; + + // First strip off any directories in name. + const char *basename = lbasename(name.c_str()); + + // Try finding an exact match. + p = excluded_libs_.find(std::string(basename)); + if (p != excluded_libs_.end()) + return true; + + // Try matching NAME without ".a" at the end. + size_t length = strlen(basename); + if ((length >= 2) + && (basename[length - 2] == '.') + && (basename[length - 1] == 'a')) + { + p = excluded_libs_.find(std::string(basename, length - 2)); + if (p != excluded_libs_.end()) + return true; + } + + return false; } // Recognize input and output target names. The GNU linker accepts @@ -381,8 +570,8 @@ usage(const char* msg, const char *opt) // "elf". Non-ELF targets would be "srec", "symbolsrec", "tekhex", // "binary", "ihex". -gold::General_options::Object_format -string_to_object_format(const char* arg) +General_options::Object_format +General_options::string_to_object_format(const char* arg) { if (strncmp(arg, "elf", 3) == 0) return gold::General_options::OBJECT_FORMAT_ELF; @@ -397,10 +586,59 @@ string_to_object_format(const char* arg) } } +void +General_options::parse_fix_v4bx(const char*, const char*, + Command_line*) +{ + this->fix_v4bx_ = FIX_V4BX_REPLACE; +} + +void +General_options::parse_fix_v4bx_interworking(const char*, const char*, + Command_line*) +{ + this->fix_v4bx_ = FIX_V4BX_INTERWORKING; +} + +void +General_options::parse_EB(const char*, const char*, Command_line*) +{ + this->endianness_ = ENDIANNESS_BIG; +} + +void +General_options::parse_EL(const char*, const char*, Command_line*) +{ + this->endianness_ = ENDIANNESS_LITTLE; +} + +} // End namespace gold. + +namespace +{ + +void +usage() +{ + fprintf(stderr, + _("%s: use the --help option for usage information\n"), + gold::program_name); + ::exit(EXIT_FAILURE); +} + +void +usage(const char* msg, const char *opt) +{ + fprintf(stderr, + _("%s: %s: %s\n"), + gold::program_name, opt, msg); + usage(); +} + // If the default sysroot is relocatable, try relocating it based on // the prefix FROM. -char* +static char* get_relative_sysroot(const char* from) { char* path = make_relative_prefix(gold::program_name, from, @@ -421,7 +659,7 @@ get_relative_sysroot(const char* from) // get_relative_sysroot, which is a small memory leak, but is // necessary since we store this pointer directly in General_options. -const char* +static const char* get_default_sysroot() { const char* sysroot = TARGET_SYSTEM_ROOT; @@ -536,7 +774,7 @@ parse_short_option(int argc, const char** argv, int pos_in_argv_i, // We handle -z as a special case. static gold::options::One_option dash_z("", gold::options::DASH_Z, - 'z', "", "-z", "Z-OPTION", false, + 'z', "", NULL, "Z-OPTION", false, NULL); gold::options::One_option* retval = NULL; if (this_argv[pos_in_argv_i] == 'z') @@ -593,21 +831,35 @@ namespace gold { General_options::General_options() - : execstack_status_(General_options::EXECSTACK_FROM_INPUT), static_(false), - do_demangle_(false) + : printed_version_(false), + execstack_status_(EXECSTACK_FROM_INPUT), + icf_status_(ICF_NONE), + static_(false), + do_demangle_(false), + plugins_(NULL), + dynamic_list_(), + incremental_disposition_(INCREMENTAL_CHECK), + implicit_incremental_(false), + excluded_libs_(), + symbols_to_retain_(), + section_starts_(), + fix_v4bx_(FIX_V4BX_NONE), + endianness_(ENDIANNESS_NOT_SET) { + // Turn off option registration once construction is complete. + gold::options::ready_to_register = false; } General_options::Object_format General_options::format_enum() const { - return string_to_object_format(this->format()); + return General_options::string_to_object_format(this->format()); } General_options::Object_format General_options::oformat_enum() const { - return string_to_object_format(this->oformat()); + return General_options::string_to_object_format(this->oformat()); } // Add the sysroot, if any, to the search paths. @@ -632,6 +884,46 @@ General_options::add_sysroot() free(canonical_sysroot); } +// Return whether FILENAME is in a system directory. + +bool +General_options::is_in_system_directory(const std::string& filename) const +{ + for (Dir_list::const_iterator p = this->library_path_.value.begin(); + p != this->library_path_.value.end(); + ++p) + { + // We use a straight string comparison rather than calling + // FILENAME_CMP because we are only interested in the cases + // where we found the file in a system directory, which means + // that we used the directory name as a prefix for a -L search. + if (p->is_system_directory() + && filename.compare(0, p->name().size(), p->name()) == 0) + return true; + } + return false; +} + +// Add a plugin to the list of plugins. + +void +General_options::add_plugin(const char* filename) +{ + if (this->plugins_ == NULL) + this->plugins_ = new Plugin_manager(*this); + this->plugins_->add_plugin(filename); +} + +// Add a plugin option to a plugin. + +void +General_options::add_plugin_option(const char* arg) +{ + if (this->plugins_ == NULL) + gold_fatal("--plugin-opt requires --plugin."); + this->plugins_->add_plugin_option(arg); +} + // Set up variables and other state that isn't set up automatically by // the parse routine, and ensure options don't contradict each other // and are otherwise kosher. @@ -649,6 +941,9 @@ General_options::finalize() if (this->strip_debug_non_line()) this->set_strip_debug_gdb(true); + if (this->Bshareable()) + this->set_shared(true); + // If the user specifies both -s and -r, convert the -s to -S. // -r requires us to keep externally visible symbols! if (this->strip_all() && this->relocatable()) @@ -675,6 +970,15 @@ General_options::finalize() else if (this->noexecstack()) this->set_execstack_status(EXECSTACK_NO); + // icf_status_ is a three-state variable; update it based on the + // value of this->icf(). + if (strcmp(this->icf(), "none") == 0) + this->set_icf_status(ICF_NONE); + else if (strcmp(this->icf(), "safe") == 0) + this->set_icf_status(ICF_SAFE); + else + this->set_icf_status(ICF_ALL); + // Handle the optional argument for --demangle. if (this->user_set_demangle()) { @@ -764,6 +1068,25 @@ General_options::finalize() this->add_to_library_path_with_sysroot("/usr/lib"); } + // Parse the contents of -retain-symbols-file into a set. + if (this->retain_symbols_file()) + { + std::ifstream in; + in.open(this->retain_symbols_file()); + if (!in) + gold_fatal(_("unable to open -retain-symbols-file file %s: %s"), + this->retain_symbols_file(), strerror(errno)); + std::string line; + std::getline(in, line); // this chops off the trailing \n, if any + while (in) + { + if (!line.empty() && line[line.length() - 1] == '\r') // Windows + line.resize(line.length() - 1); + this->symbols_to_retain_.insert(line); + std::getline(in, line); + } + } + if (this->shared() && !this->user_set_allow_shlib_undefined()) this->set_allow_shlib_undefined(true); @@ -772,12 +1095,26 @@ General_options::finalize() this->add_sysroot(); // Now that we've normalized the options, check for contradictory ones. + if (this->shared() && this->is_static()) + gold_fatal(_("-shared and -static are incompatible")); + if (this->shared() && this->pie()) + gold_fatal(_("-shared and -pie are incompatible")); + if (this->shared() && this->relocatable()) gold_fatal(_("-shared and -r are incompatible")); + if (this->pie() && this->relocatable()) + gold_fatal(_("-pie and -r are incompatible")); + + // TODO: implement support for -retain-symbols-file with -r, if needed. + if (this->relocatable() && this->retain_symbols_file()) + gold_fatal(_("-retain-symbols-file does not yet work with -r")); if (this->oformat_enum() != General_options::OBJECT_FORMAT_ELF - && (this->shared() || this->relocatable())) - gold_fatal(_("binary output format not compatible with -shared or -r")); + && (this->shared() + || this->pie() + || this->relocatable())) + gold_fatal(_("binary output format not compatible " + "with -shared or -pie or -r")); if (this->user_set_hash_bucket_empty_fraction() && (this->hash_bucket_empty_fraction() < 0.0 @@ -786,6 +1123,10 @@ General_options::finalize() "[0.0, 1.0)"), this->hash_bucket_empty_fraction()); + if (this->implicit_incremental_ && !this->incremental()) + gold_fatal(_("Options --incremental-changed, --incremental-unchanged, " + "--incremental-unknown require the use of --incremental")); + // FIXME: we can/should be doing a lot more sanity checking here. } @@ -871,6 +1212,13 @@ Command_line::Command_line() { } +// Pre_options is the hook that sets the ready_to_register flag. + +Command_line::Pre_options::Pre_options() +{ + gold::options::ready_to_register = true; +} + // Process the command line options. For process_one_option, i is the // index of argv to process next, and must be an option (that is, // start with a dash). The return value is the index of the next @@ -934,8 +1282,9 @@ Command_line::process(int argc, const char** argv) this->position_options_.copy_from_options(this->options()); if (no_more_options || argv[i][0] != '-') { - Input_file_argument file(argv[i], false, "", false, - this->position_options_); + Input_file_argument file(argv[i], + Input_file_argument::INPUT_FILE_TYPE_FILE, + "", false, this->position_options_); this->inputs_.add_file(file); ++i; } @@ -953,4 +1302,15 @@ Command_line::process(int argc, const char** argv) this->options_.finalize(); } +// Finalize the version script options and return them. + +const Version_script_info& +Command_line::version_script() +{ + this->options_.finalize_dynamic_list(); + Version_script_info* vsi = this->script_options_.version_script_info(); + vsi->finalize(); + return *vsi; +} + } // End namespace gold. diff --git a/binutils-2.19/gold/options.h b/binutils-2.19/gold/options.h index 46ad761..2e427ce 100644 --- a/binutils-2.19/gold/options.h +++ b/binutils-2.19/gold/options.h @@ -1,6 +1,6 @@ // options.h -- handle command line options for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -39,6 +39,7 @@ #include <cstdlib> #include <cstring> #include <list> +#include <map> #include <string> #include <vector> @@ -54,6 +55,19 @@ class Search_directory; class Input_file_group; class Position_dependent_options; class Target; +class Plugin_manager; + +// Incremental build action for a specific file, as selected by the user. + +enum Incremental_disposition +{ + // Determine the status from the timestamp (default). + INCREMENTAL_CHECK, + // Assume the file changed from the previous build. + INCREMENTAL_CHANGED, + // Assume the file didn't change from the previous build. + INCREMENTAL_UNCHANGED +}; // The nested namespace is to contain all the global variables and // structs that need to be defined in the .h file, but do not need to @@ -70,6 +84,9 @@ extern void parse_bool(const char* option_name, const char* arg, bool* retval); extern void +parse_int(const char* option_name, const char* arg, int* retval); + +extern void parse_uint(const char* option_name, const char* arg, int* retval); extern void @@ -227,12 +244,18 @@ struct Struct_special : public Struct_var // var() and set_var() as General_options methods. Arguments as are // for the constructor for One_option. param_type__ is the same as // type__ for built-in types, and "const type__ &" otherwise. +// +// When we define the linker command option "assert", the macro argument +// varname__ of DEFINE_var below will be replaced by "assert". On Mac OSX +// assert.h is included implicitly by one of the library headers we use. To +// avoid unintended macro substitution of "assert()", we need to enclose +// varname__ with parenthese. #define DEFINE_var(varname__, dashes__, shortname__, default_value__, \ default_value_as_string__, helpstring__, helparg__, \ optional_arg__, type__, param_type__, parse_fn__) \ public: \ param_type__ \ - varname__() const \ + (varname__)() const \ { return this->varname__##_.value; } \ \ bool \ @@ -292,7 +315,10 @@ struct Struct_special : public Struct_var void \ parse_to_value(const char*, const char*, \ Command_line*, General_options* options) \ - { options->set_##varname__(false); } \ + { \ + options->set_##varname__(false); \ + options->set_user_set_##varname__(); \ + } \ \ options::One_option option; \ }; \ @@ -320,6 +346,12 @@ struct Struct_special : public Struct_var }; \ Struct_disable_##varname__ disable_##varname__##_initializer_ +#define DEFINE_int(varname__, dashes__, shortname__, default_value__, \ + helpstring__, helparg__) \ + DEFINE_var(varname__, dashes__, shortname__, default_value__, \ + #default_value__, helpstring__, helparg__, false, \ + int, int, options::parse_int) + #define DEFINE_uint(varname__, dashes__, shortname__, default_value__, \ helpstring__, helparg__) \ DEFINE_var(varname__, dashes__, shortname__, default_value__, \ @@ -521,9 +553,22 @@ class Search_directory is_in_sysroot() const { return this->is_in_sysroot_; } + // Return whether this is considered a system directory. + bool + is_system_directory() const + { return this->put_in_sysroot_ || this->is_in_sysroot_; } + private: + // The directory name. std::string name_; + // True if the sysroot should be added as a prefix for this + // directory (if there is a sysroot). This is true for system + // directories that we search by default. bool put_in_sysroot_; + // True if this directory is in the sysroot (if there is a sysroot). + // This is true if there is a sysroot and either 1) put_in_sysroot_ + // is true, or 2) the directory happens to be in the sysroot based + // on a pathname comparison. bool is_in_sysroot_; }; @@ -545,13 +590,25 @@ class General_options // alphabetical order). For both, lowercase sorts before uppercase. // The -z options come last. + DEFINE_bool(add_needed, options::TWO_DASHES, '\0', false, + N_("Not supported"), + N_("Do not copy DT_NEEDED tags from shared libraries")); + + DEFINE_bool_alias(allow_multiple_definition, muldefs, options::TWO_DASHES, + '\0', N_("Allow multiple definitions of symbols"), + N_("Do not allow multiple definitions"), false); + DEFINE_bool(allow_shlib_undefined, options::TWO_DASHES, '\0', false, N_("Allow unresolved references in shared libraries"), N_("Do not allow unresolved references in shared libraries")); DEFINE_bool(as_needed, options::TWO_DASHES, '\0', false, - N_("Only set DT_NEEDED for dynamic libs if used"), - N_("Always DT_NEEDED for dynamic libs")); + N_("Only set DT_NEEDED for shared libraries if used"), + N_("Always DT_NEEDED for shared libraries")); + + DEFINE_enum(assert, options::ONE_DASH, '\0', NULL, + N_("Ignored"), N_("[ignored]"), + {"definitions", "nodefinitions", "nosymbolic", "pure-text"}); // This should really be an "enum", but it's too easy for folks to // forget to update the list as they add new targets. So we just @@ -592,6 +649,14 @@ class General_options {"none"}); #endif + DEFINE_bool(copy_dt_needed_entries, options::TWO_DASHES, '\0', false, + N_("Not supported"), + N_("Do not copy DT_NEEDED tags from shared libraries")); + + DEFINE_bool(cref, options::TWO_DASHES, '\0', false, + N_("Output cross reference table"), + N_("Do not output cross reference table")); + DEFINE_bool(define_common, options::TWO_DASHES, 'd', false, N_("Define common symbols"), N_("Do not define common symbols")); @@ -619,22 +684,72 @@ class General_options N_("Try to detect violations of the One Definition Rule"), NULL); + DEFINE_bool(discard_all, options::TWO_DASHES, 'x', false, + N_("Delete all local symbols"), NULL); + DEFINE_bool(discard_locals, options::TWO_DASHES, 'X', false, + N_("Delete all temporary local symbols"), NULL); + + DEFINE_bool(dynamic_list_data, options::TWO_DASHES, '\0', false, + N_("Add data symbols to dynamic symbols"), NULL); + + DEFINE_bool(dynamic_list_cpp_new, options::TWO_DASHES, '\0', false, + N_("Add C++ operator new/delete to dynamic symbols"), NULL); + + DEFINE_bool(dynamic_list_cpp_typeinfo, options::TWO_DASHES, '\0', false, + N_("Add C++ typeinfo to dynamic symbols"), NULL); + + DEFINE_special(dynamic_list, options::TWO_DASHES, '\0', + N_("Read a list of dynamic symbols"), N_("FILE")); + DEFINE_string(entry, options::TWO_DASHES, 'e', NULL, N_("Set program start address"), N_("ADDRESS")); + DEFINE_special(exclude_libs, options::TWO_DASHES, '\0', + N_("Exclude libraries from automatic export"), + N_(("lib,lib ..."))); + DEFINE_bool(export_dynamic, options::TWO_DASHES, 'E', false, - N_("Export all dynamic symbols"), NULL); + N_("Export all dynamic symbols"), + N_("Do not export all dynamic symbols (default)")); + + DEFINE_special(EB, options::ONE_DASH, '\0', + N_("Link big-endian objects."), NULL); DEFINE_bool(eh_frame_hdr, options::TWO_DASHES, '\0', false, N_("Create exception frame header"), NULL); + DEFINE_special(EL, options::ONE_DASH, '\0', + N_("Link little-endian objects."), NULL); + DEFINE_bool(fatal_warnings, options::TWO_DASHES, '\0', false, N_("Treat warnings as errors"), N_("Do not treat warnings as errors")); + DEFINE_string(fini, options::ONE_DASH, '\0', "_fini", + N_("Call SYMBOL at unload-time"), N_("SYMBOL")); + + DEFINE_bool(fix_cortex_a8, options::TWO_DASHES, '\0', false, + N_("(ARM only) Fix binaries for Cortex-A8 erratum."), + N_("(ARM only) Do not fix binaries for Cortex-A8 erratum.")); + + DEFINE_special(fix_v4bx, options::TWO_DASHES, '\0', + N_("(ARM only) Rewrite BX rn as MOV pc, rn for ARMv4"), + NULL); + + DEFINE_special(fix_v4bx_interworking, options::TWO_DASHES, '\0', + N_("(ARM only) Rewrite BX rn branch to ARMv4 interworking " + "veneer"), + NULL); + + DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false, + N_("Ignored"), NULL); + DEFINE_string(soname, options::ONE_DASH, 'h', NULL, N_("Set shared library name"), N_("FILENAME")); + DEFINE_bool(i, options::EXACTLY_ONE_DASH, '\0', false, + N_("Ignored"), NULL); + DEFINE_double(hash_bucket_empty_fraction, options::TWO_DASHES, '\0', 0.0, N_("Min fraction of empty buckets in dynamic hash"), N_("FRACTION")); @@ -646,9 +761,31 @@ class General_options DEFINE_string(dynamic_linker, options::TWO_DASHES, 'I', NULL, N_("Set dynamic linker path"), N_("PROGRAM")); + DEFINE_bool(incremental, options::TWO_DASHES, '\0', false, + N_("Work in progress; do not use"), + N_("Do a full build")); + + DEFINE_special(incremental_changed, options::TWO_DASHES, '\0', + N_("Assume files changed"), NULL); + + DEFINE_special(incremental_unchanged, options::TWO_DASHES, '\0', + N_("Assume files didn't change"), NULL); + + DEFINE_special(incremental_unknown, options::TWO_DASHES, '\0', + N_("Use timestamps to check files (default)"), NULL); + + DEFINE_string(init, options::ONE_DASH, '\0', "_init", + N_("Call SYMBOL at load-time"), N_("SYMBOL")); + DEFINE_special(just_symbols, options::TWO_DASHES, '\0', N_("Read only symbol values from FILE"), N_("FILE")); + DEFINE_bool(keep_files_mapped, options::TWO_DASHES, '\0', + sizeof(void*) >= 8, + N_("Map whole files to memory (default on 64-bit hosts)"), + N_("Map relevant file parts to memory (default on 32-bit " + "hosts)")); + DEFINE_special(library, options::TWO_DASHES, 'l', N_("Search for library LIBNAME"), N_("LIBNAME")); @@ -689,8 +826,28 @@ class General_options DEFINE_string(oformat, options::EXACTLY_TWO_DASHES, '\0', "elf", N_("Set output format"), N_("[binary]")); + DEFINE_bool(p, options::ONE_DASH, '\0', false, + N_("(ARM only) Ignore for backward compatibility"), NULL); + + DEFINE_bool(pie, options::ONE_DASH, '\0', false, + N_("Create a position independent executable"), NULL); + DEFINE_bool_alias(pic_executable, pie, options::TWO_DASHES, '\0', + N_("Create a position independent executable"), NULL, + false); + + DEFINE_bool(pipeline_knowledge, options::ONE_DASH, '\0', false, + NULL, N_("(ARM only) Ignore for backward compatibility")); + +#ifdef ENABLE_PLUGINS + DEFINE_special(plugin, options::TWO_DASHES, '\0', + N_("Load a plugin library"), N_("PLUGIN")); + DEFINE_special(plugin_opt, options::TWO_DASHES, '\0', + N_("Pass an option to the plugin"), N_("OPTION")); +#endif + DEFINE_bool(preread_archive_symbols, options::TWO_DASHES, '\0', false, N_("Preread archive symbols when multi-threaded"), NULL); + DEFINE_string(print_symbol_counts, options::TWO_DASHES, '\0', NULL, N_("Print symbols defined and used for each input"), N_("FILENAME")); @@ -707,6 +864,9 @@ class General_options DEFINE_bool(relax, options::TWO_DASHES, '\0', false, N_("Relax branches on certain targets"), NULL); + DEFINE_string(retain_symbols_file, options::TWO_DASHES, '\0', NULL, + N_("keep only symbols listed in this file"), N_("FILE")); + // -R really means -rpath, but can mean --just-symbols for // compatibility with GNU ld. -rpath is always -rpath, so we list // it separately. @@ -720,6 +880,13 @@ class General_options N_("Add DIR to link time shared library search path"), N_("DIR")); + DEFINE_special(section_start, options::TWO_DASHES, '\0', + N_("Set address of section"), N_("SECTION=ADDRESS")); + + DEFINE_optional_string(sort_common, options::TWO_DASHES, '\0', NULL, + N_("Sort common symbols by alignment"), + N_("[={ascending,descending}]")); + DEFINE_bool(strip_all, options::TWO_DASHES, 's', false, N_("Strip all symbols"), NULL); DEFINE_bool(strip_debug, options::TWO_DASHES, 'S', false, @@ -729,15 +896,59 @@ class General_options DEFINE_bool(strip_debug_gdb, options::TWO_DASHES, '\0', false, N_("Strip debug symbols that are unused by gdb " "(at least versions <= 6.7)"), NULL); + DEFINE_bool(strip_lto_sections, options::TWO_DASHES, '\0', true, + N_("Strip LTO intermediate code sections"), NULL); + + DEFINE_int(stub_group_size, options::TWO_DASHES , '\0', 1, + N_("(ARM only) The maximum distance from instructions in a group " + "of sections to their stubs. Negative values mean stubs " + "are always after the group. 1 means using default size.\n"), + N_("SIZE")); + + DEFINE_bool(no_keep_memory, options::TWO_DASHES, '\0', false, + N_("Use less memory and more disk I/O " + "(included only for compatibility with GNU ld)"), NULL); - DEFINE_bool(shared, options::ONE_DASH, '\0', false, + DEFINE_bool(shared, options::ONE_DASH, 'G', false, N_("Generate shared library"), NULL); + DEFINE_bool(Bshareable, options::ONE_DASH, '\0', false, + N_("Generate shared library"), NULL); + + DEFINE_uint(split_stack_adjust_size, options::TWO_DASHES, '\0', 0x4000, + N_("Stack size when -fsplit-stack function calls non-split"), + N_("SIZE")); + // This is not actually special in any way, but I need to give it // a non-standard accessor-function name because 'static' is a keyword. DEFINE_special(static, options::ONE_DASH, '\0', N_("Do not link against shared libraries"), NULL); + DEFINE_enum(icf, options::TWO_DASHES, '\0', "none", + N_("Identical Code Folding. " + "\'--icf=safe\' Folds ctors, dtors and functions whose" + " pointers are definitely not taken."), + ("[none,all,safe]"), + {"none", "all", "safe"}); + + DEFINE_uint(icf_iterations, options::TWO_DASHES , '\0', 0, + N_("Number of iterations of ICF (default 2)"), N_("COUNT")); + + DEFINE_bool(print_icf_sections, options::TWO_DASHES, '\0', false, + N_("List folded identical sections on stderr"), + N_("Do not list folded identical sections")); + + DEFINE_set(keep_unique, options::TWO_DASHES, '\0', + N_("Do not fold this symbol during ICF"), N_("SYMBOL")); + + DEFINE_bool(gc_sections, options::TWO_DASHES, '\0', false, + N_("Remove unused sections"), + N_("Don't remove unused sections (default)")); + + DEFINE_bool(print_gc_sections, options::TWO_DASHES, '\0', false, + N_("List removed unused sections on stderr"), + N_("Do not list removed unused sections")); + DEFINE_bool(stats, options::TWO_DASHES, '\0', false, N_("Print resource usage statistics"), NULL); @@ -778,6 +989,35 @@ class General_options DEFINE_special(version_script, options::TWO_DASHES, '\0', N_("Read version script"), N_("FILE")); + DEFINE_bool(warn_common, options::TWO_DASHES, '\0', false, + N_("Warn about duplicate common symbols"), + N_("Do not warn about duplicate common symbols (default)")); + + DEFINE_bool(warn_constructors, options::TWO_DASHES, '\0', false, + N_("Ignored"), N_("Ignored")); + + DEFINE_bool(warn_mismatch, options::TWO_DASHES, '\0', true, + NULL, N_("Don't warn about mismatched input files")); + + DEFINE_bool(warn_multiple_gp, options::TWO_DASHES, '\0', false, + N_("Ignored"), NULL); + + DEFINE_bool(warn_search_mismatch, options::TWO_DASHES, '\0', true, + N_("Warn when skipping an incompatible library"), + N_("Don't warn when skipping an incompatible library")); + + DEFINE_bool(warn_shared_textrel, options::TWO_DASHES, '\0', false, + N_("Warn if text segment is not shareable"), + N_("Do not warn if text segment is not shareable (default)")); + + DEFINE_bool(warn_unresolved_symbols, options::TWO_DASHES, '\0', false, + N_("Report unresolved symbols as warnings"), + NULL); + DEFINE_bool_alias(error_unresolved_symbols, warn_unresolved_symbols, + options::TWO_DASHES, '\0', + N_("Report unresolved symbols as errors"), + NULL, true); + DEFINE_bool(whole_archive, options::TWO_DASHES, '\0', false, N_("Include all archive contents"), N_("Include only needed archive contents")); @@ -788,6 +1028,10 @@ class General_options DEFINE_set(trace_symbol, options::TWO_DASHES, 'y', N_("Trace references to symbol"), N_("SYMBOL")); + DEFINE_bool(undefined_version, options::TWO_DASHES, '\0', true, + N_("Allow unused version in script (default)"), + N_("Do not allow unused version in script")); + DEFINE_string(Y, options::EXACTLY_ONE_DASH, 'Y', "", N_("Default search path for Solaris compatibility"), N_("PATH")); @@ -809,19 +1053,28 @@ class General_options NULL); DEFINE_bool(execstack, options::DASH_Z, '\0', false, N_("Mark output as requiring executable stack"), NULL); - DEFINE_uint64(max_page_size, options::DASH_Z, '\0', 0, - N_("Set maximum page size to SIZE"), N_("SIZE")); - DEFINE_bool(noexecstack, options::DASH_Z, '\0', false, - N_("Mark output as not requiring executable stack"), NULL); DEFINE_bool(initfirst, options::DASH_Z, '\0', false, N_("Mark DSO to be initialized first at runtime"), NULL); DEFINE_bool(interpose, options::DASH_Z, '\0', false, N_("Mark object to interpose all DSOs but executable"), NULL); + DEFINE_bool(lazy, options::DASH_Z, '\0', false, + N_("Mark object for lazy runtime binding (default)"), + NULL); DEFINE_bool(loadfltr, options::DASH_Z, '\0', false, N_("Mark object requiring immediate process"), NULL); + DEFINE_uint64(max_page_size, options::DASH_Z, '\0', 0, + N_("Set maximum page size to SIZE"), N_("SIZE")); + DEFINE_bool(muldefs, options::DASH_Z, '\0', false, + N_("Allow multiple definitions of symbols"), + NULL); + // copyreloc is here in the list because there is only -z + // nocopyreloc, not -z copyreloc. + DEFINE_bool(copyreloc, options::DASH_Z, '\0', true, + NULL, + N_("Do not create copy relocs")); DEFINE_bool(nodefaultlib, options::DASH_Z, '\0', false, N_("Mark object not to use default search paths"), NULL); @@ -834,9 +1087,23 @@ class General_options DEFINE_bool(nodump, options::DASH_Z, '\0', false, N_("Mark DSO not available to dldump"), NULL); + DEFINE_bool(noexecstack, options::DASH_Z, '\0', false, + N_("Mark output as not requiring executable stack"), NULL); + DEFINE_bool(now, options::DASH_Z, '\0', false, + N_("Mark object for immediate function binding"), + NULL); + DEFINE_bool(origin, options::DASH_Z, '\0', false, + N_("Mark DSO to indicate that needs immediate $ORIGIN " + "processing at runtime"), NULL); DEFINE_bool(relro, options::DASH_Z, '\0', false, N_("Where possible mark variables read-only after relocation"), N_("Don't mark variables read-only after relocation")); + DEFINE_bool(text, options::DASH_Z, '\0', false, + N_("Do not permit relocations in read-only segments"), + NULL); + DEFINE_bool_alias(textoff, text, options::DASH_Z, '\0', + N_("Permit relocations in read-only segments (default)"), + NULL, true); public: typedef options::Dir_list Dir_list; @@ -850,6 +1117,11 @@ class General_options // any problems. void finalize(); + // True if we printed the version information. + bool + printed_version() const + { return this->printed_version_; } + // The macro defines output() (based on --output), but that's a // generic name. Provide this alternative name, which is clearer. const char* @@ -860,7 +1132,15 @@ class General_options // the output is position-independent or not. bool output_is_position_independent() const - { return this->shared(); } + { return this->shared() || this->pie(); } + + // Return true if the output is something that can be exec()ed, such + // as a static executable, or a position-dependent or + // position-independent executable, but not a dynamic library or an + // object file. + bool + output_is_executable() const + { return !this->shared() && !this->relocatable(); } // This would normally be static(), and defined automatically, but // since static is a keyword, we need to come up with our own name. @@ -878,10 +1158,28 @@ class General_options OBJECT_FORMAT_BINARY }; + // Convert a string to an Object_format. Gives an error if the + // string is not recognized. + static Object_format + string_to_object_format(const char* arg); + // Note: these functions are not very fast. Object_format format_enum() const; Object_format oformat_enum() const; + // Return whether FILENAME is in a system directory. + bool + is_in_system_directory(const std::string& name) const; + + // RETURN whether SYMBOL_NAME should be kept, according to symbols_to_retain_. + bool + should_retain_symbol(const char* symbol_name) const + { + if (symbols_to_retain_.empty()) // means flag wasn't specified + return true; + return symbols_to_retain_.find(symbol_name) != symbols_to_retain_.end(); + } + // These are the best way to get access to the execstack state, // not execstack() and noexecstack() which are hard to use properly. bool @@ -892,6 +1190,14 @@ class General_options is_stack_executable() const { return this->execstack_status_ == EXECSTACK_YES; } + bool + icf_enabled() const + { return this->icf_status_ != ICF_NONE; } + + bool + icf_safe_folding() const + { return this->icf_status_ == ICF_SAFE; } + // The --demangle option takes an optional string, and there is also // a --no-demangle option. This is the best way to decide whether // to demangle or not. @@ -899,6 +1205,69 @@ class General_options do_demangle() const { return this->do_demangle_; } + // Returns TRUE if any plugin libraries have been loaded. + bool + has_plugins() const + { return this->plugins_ != NULL; } + + // Return a pointer to the plugin manager. + Plugin_manager* + plugins() const + { return this->plugins_; } + + // True iff SYMBOL was found in the file specified by dynamic-list. + bool + in_dynamic_list(const char* symbol) const + { return this->dynamic_list_.version_script_info()->symbol_is_local(symbol); } + + // Finalize the dynamic list. + void + finalize_dynamic_list() + { this->dynamic_list_.version_script_info()->finalize(); } + + // The disposition given by the --incremental-changed, + // --incremental-unchanged or --incremental-unknown option. The + // value may change as we proceed parsing the command line flags. + Incremental_disposition + incremental_disposition() const + { return this->incremental_disposition_; } + + // Return true if S is the name of a library excluded from automatic + // symbol export. + bool + check_excluded_libs (const std::string &s) const; + + // If an explicit start address was given for section SECNAME with + // the --section-start option, return true and set *PADDR to the + // address. Otherwise return false. + bool + section_start(const char* secname, uint64_t* paddr) const; + + enum Fix_v4bx + { + // Leave original instruction. + FIX_V4BX_NONE, + // Replace instruction. + FIX_V4BX_REPLACE, + // Generate an interworking veneer. + FIX_V4BX_INTERWORKING + }; + + Fix_v4bx + fix_v4bx() const + { return (this->fix_v4bx_); } + + enum Endianness + { + ENDIANNESS_NOT_SET, + ENDIANNESS_BIG, + ENDIANNESS_LITTLE + }; + + Endianness + endianness() const + { return this->endianness_; } + private: // Don't copy this structure. General_options(const General_options&); @@ -915,6 +1284,20 @@ class General_options EXECSTACK_NO }; + enum Icf_status + { + // Do not fold any functions (Default or --icf=none). + ICF_NONE, + // All functions are candidates for folding. (--icf=all). + ICF_ALL, + // Only ctors and dtors are candidates for folding. (--icf=safe). + ICF_SAFE + }; + + void + set_icf_status(Icf_status value) + { this->icf_status_ = value; } + void set_execstack_status(Execstack value) { this->execstack_status_ = value; } @@ -936,12 +1319,48 @@ class General_options void add_sysroot(); + // Add a plugin and its arguments to the list of plugins. + void + add_plugin(const char *filename); + + // Add a plugin option. + void + add_plugin_option(const char* opt); + + // Whether we printed version information. + bool printed_version_; // Whether to mark the stack as executable. Execstack execstack_status_; + // Whether to do code folding. + Icf_status icf_status_; // Whether to do a static link. bool static_; // Whether to do demangling. bool do_demangle_; + // List of plugin libraries. + Plugin_manager* plugins_; + // The parsed output of --dynamic-list files. For convenience in + // script.cc, we store this as a Script_options object, even though + // we only use a single Version_tree from it. + Script_options dynamic_list_; + // The disposition given by the --incremental-changed, + // --incremental-unchanged or --incremental-unknown option. The + // value may change as we proceed parsing the command line flags. + Incremental_disposition incremental_disposition_; + // Whether we have seen one of the options that require incremental + // build (--incremental-changed, --incremental-unchanged or + // --incremental-unknown) + bool implicit_incremental_; + // Libraries excluded from automatic export, via --exclude-libs. + Unordered_set<std::string> excluded_libs_; + // List of symbol-names to keep, via -retain-symbol-info. + Unordered_set<std::string> symbols_to_retain_; + // Map from section name to address from --section-start. + std::map<std::string, uint64_t> section_starts_; + // Whether to process armv4 bx instruction relocation. + Fix_v4bx fix_v4bx_; + // Endianness. + Endianness endianness_; }; // The position-dependent options. We use this to store the state of @@ -978,12 +1397,14 @@ class Position_dependent_options this->set_Bdynamic(options.Bdynamic()); this->set_format_enum(options.format_enum()); this->set_whole_archive(options.whole_archive()); + this->set_incremental_disposition(options.incremental_disposition()); } DEFINE_posdep(as_needed, bool); DEFINE_posdep(Bdynamic, bool); DEFINE_posdep(format_enum, General_options::Object_format); DEFINE_posdep(whole_archive, bool); + DEFINE_posdep(incremental_disposition, Incremental_disposition); private: // This is a General_options with everything set to its default @@ -998,9 +1419,20 @@ class Position_dependent_options class Input_file_argument { public: + enum Input_file_type + { + // A regular file, name used as-is, not searched. + INPUT_FILE_TYPE_FILE, + // A library name. When used, "lib" will be prepended and ".so" or + // ".a" appended to make a filename, and that filename will be searched + // for using the -L paths. + INPUT_FILE_TYPE_LIBRARY, + // A regular file, name used as-is, but searched using the -L paths. + INPUT_FILE_TYPE_SEARCHED_FILE + }; + // name: file name or library name - // is_lib: true if name is a library name: that is, emits the leading - // "lib" and trailing ".so"/".a" from the name + // type: the type of this input file. // extra_search_path: an extra directory to look for the file, prior // to checking the normal library search path. If this is "", // then no extra directory is added. @@ -1008,15 +1440,15 @@ class Input_file_argument // options: The position dependent options at this point in the // command line, such as --whole-archive. Input_file_argument() - : name_(), is_lib_(false), extra_search_path_(""), just_symbols_(false), - options_() + : name_(), type_(INPUT_FILE_TYPE_FILE), extra_search_path_(""), + just_symbols_(false), options_() { } - Input_file_argument(const char* name, bool is_lib, + Input_file_argument(const char* name, Input_file_type type, const char* extra_search_path, bool just_symbols, const Position_dependent_options& options) - : name_(name), is_lib_(is_lib), extra_search_path_(extra_search_path), + : name_(name), type_(type), extra_search_path_(extra_search_path), just_symbols_(just_symbols), options_(options) { } @@ -1024,11 +1456,11 @@ class Input_file_argument // Position_dependent_options. In that case, we extract the // position-independent vars from the General_options and only store // those. - Input_file_argument(const char* name, bool is_lib, + Input_file_argument(const char* name, Input_file_type type, const char* extra_search_path, bool just_symbols, const General_options& options) - : name_(name), is_lib_(is_lib), extra_search_path_(extra_search_path), + : name_(name), type_(type), extra_search_path_(extra_search_path), just_symbols_(just_symbols), options_(options) { } @@ -1042,7 +1474,11 @@ class Input_file_argument bool is_lib() const - { return this->is_lib_; } + { return type_ == INPUT_FILE_TYPE_LIBRARY; } + + bool + is_searched_file() const + { return type_ == INPUT_FILE_TYPE_SEARCHED_FILE; } const char* extra_search_path() const @@ -1061,14 +1497,18 @@ class Input_file_argument // options. bool may_need_search() const - { return this->is_lib_ || !this->extra_search_path_.empty(); } + { + return (this->is_lib() + || this->is_searched_file() + || !this->extra_search_path_.empty()); + } private: // We use std::string, not const char*, here for convenience when // using script files, so that we do not have to preserve the string // in that case. std::string name_; - bool is_lib_; + Input_file_type type_; std::string extra_search_path_; bool just_symbols_; Position_dependent_options options_; @@ -1128,14 +1568,15 @@ class Input_argument Input_file_group* group_; }; +typedef std::vector<Input_argument> Input_argument_list; + // A group from the command line. This is a set of arguments within // --start-group ... --end-group. class Input_file_group { public: - typedef std::vector<Input_argument> Files; - typedef Files::const_iterator const_iterator; + typedef Input_argument_list::const_iterator const_iterator; Input_file_group() : files_() @@ -1157,7 +1598,7 @@ class Input_file_group { return this->files_.end(); } private: - Files files_; + Input_argument_list files_; }; // A list of files from the command line or a script. @@ -1165,7 +1606,6 @@ class Input_file_group class Input_arguments { public: - typedef std::vector<Input_argument> Input_argument_list; typedef Input_argument_list::const_iterator const_iterator; Input_arguments() @@ -1256,10 +1696,9 @@ class Command_line script_options() { return this->script_options_; } - // Get the version-script options: a convenience routine. + // Finalize the version-script options and return them. const Version_script_info& - version_script() const - { return *this->script_options_.version_script_info(); } + version_script(); // Get the input files. Input_arguments& @@ -1285,6 +1724,16 @@ class Command_line Command_line(const Command_line&); Command_line& operator=(const Command_line&); + // This is a dummy class to provide a constructor that runs before + // the constructor for the General_options. The Pre_options constructor + // is used as a hook to set the flag enabling the options to register + // themselves. + struct Pre_options { + Pre_options(); + }; + + // This must come before options_! + Pre_options pre_options_; General_options options_; Position_dependent_options position_options_; Script_options script_options_; diff --git a/binutils-2.19/gold/output.cc b/binutils-2.19/gold/output.cc index 2a46195..ff43d53 100644 --- a/binutils-2.19/gold/output.cc +++ b/binutils-2.19/gold/output.cc @@ -1,6 +1,6 @@ // output.cc -- manage the output file for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -30,7 +30,7 @@ #include <sys/mman.h> #include <sys/stat.h> #include <algorithm> -#include "libiberty.h" // for unlink_if_ordinary() +#include "libiberty.h" #include "parameters.h" #include "object.h" @@ -45,6 +45,18 @@ # define MAP_ANONYMOUS MAP_ANON #endif +#ifndef HAVE_POSIX_FALLOCATE +// A dummy, non general, version of posix_fallocate. Here we just set +// the file size and hope that there is enough disk space. FIXME: We +// could allocate disk space by walking block by block and writing a +// zero byte into each block. +static int +posix_fallocate(int o, off_t offset, off_t len) +{ + return ftruncate(o, offset + len); +} +#endif // !defined(HAVE_POSIX_FALLOCATE) + namespace gold { @@ -97,25 +109,34 @@ Output_section_headers::Output_section_headers( secnamepool_(secnamepool), shstrtab_section_(shstrtab_section) { +} + +// Compute the current data size. + +off_t +Output_section_headers::do_size() const +{ // Count all the sections. Start with 1 for the null section. off_t count = 1; if (!parameters->options().relocatable()) { - for (Layout::Segment_list::const_iterator p = segment_list->begin(); - p != segment_list->end(); + for (Layout::Segment_list::const_iterator p = + this->segment_list_->begin(); + p != this->segment_list_->end(); ++p) if ((*p)->type() == elfcpp::PT_LOAD) count += (*p)->output_section_count(); } else { - for (Layout::Section_list::const_iterator p = section_list->begin(); - p != section_list->end(); + for (Layout::Section_list::const_iterator p = + this->section_list_->begin(); + p != this->section_list_->end(); ++p) if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0) ++count; } - count += unattached_section_list->size(); + count += this->unattached_section_list_->size(); const int size = parameters->target().get_size(); int shdr_size; @@ -126,7 +147,7 @@ Output_section_headers::Output_section_headers( else gold_unreachable(); - this->set_data_size(count * shdr_size); + return count * shdr_size; } // Write out the section headers. @@ -192,7 +213,9 @@ Output_section_headers::do_sized_write(Output_file* of) else oshdr.put_sh_link(shstrndx); - oshdr.put_sh_info(0); + size_t segment_count = this->segment_list_->size(); + oshdr.put_sh_info(segment_count >= elfcpp::PN_XNUM ? segment_count : 0); + oshdr.put_sh_addralign(0); oshdr.put_sh_entsize(0); } @@ -257,16 +280,6 @@ Output_segment_headers::Output_segment_headers( const Layout::Segment_list& segment_list) : segment_list_(segment_list) { - const int size = parameters->target().get_size(); - int phdr_size; - if (size == 32) - phdr_size = elfcpp::Elf_sizes<32>::phdr_size; - else if (size == 64) - phdr_size = elfcpp::Elf_sizes<64>::phdr_size; - else - gold_unreachable(); - - this->set_data_size(segment_list.size() * phdr_size); } void @@ -323,6 +336,21 @@ Output_segment_headers::do_sized_write(Output_file* of) of->write_output_view(this->offset(), all_phdrs_size, view); } +off_t +Output_segment_headers::do_size() const +{ + const int size = parameters->target().get_size(); + int phdr_size; + if (size == 32) + phdr_size = elfcpp::Elf_sizes<32>::phdr_size; + else if (size == 64) + phdr_size = elfcpp::Elf_sizes<64>::phdr_size; + else + gold_unreachable(); + + return this->segment_list_.size() * phdr_size; +} + // Output_file_header methods. Output_file_header::Output_file_header(const Target* target, @@ -336,16 +364,7 @@ Output_file_header::Output_file_header(const Target* target, shstrtab_(NULL), entry_(entry) { - const int size = parameters->target().get_size(); - int ehdr_size; - if (size == 32) - ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size; - else if (size == 64) - ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size; - else - gold_unreachable(); - - this->set_data_size(ehdr_size); + this->set_data_size(this->do_size()); } // Set the section table information for a file header. @@ -420,13 +439,12 @@ Output_file_header::do_sized_write(Output_file* of) ? elfcpp::ELFDATA2MSB : elfcpp::ELFDATA2LSB); e_ident[elfcpp::EI_VERSION] = elfcpp::EV_CURRENT; - // FIXME: Some targets may need to set EI_OSABI and EI_ABIVERSION. oehdr.put_e_ident(e_ident); elfcpp::ET e_type; if (parameters->options().relocatable()) e_type = elfcpp::ET_REL; - else if (parameters->options().shared()) + else if (parameters->options().output_is_position_independent()) e_type = elfcpp::ET_DYN; else e_type = elfcpp::ET_EXEC; @@ -443,10 +461,7 @@ Output_file_header::do_sized_write(Output_file* of) oehdr.put_e_phoff(this->segment_header_->offset()); oehdr.put_e_shoff(this->section_header_->offset()); - - // FIXME: The target needs to set the flags. - oehdr.put_e_flags(0); - + oehdr.put_e_flags(this->target_->processor_specific_flags()); oehdr.put_e_ehsize(elfcpp::Elf_sizes<size>::ehdr_size); if (this->segment_header_ == NULL) @@ -457,8 +472,11 @@ Output_file_header::do_sized_write(Output_file* of) else { oehdr.put_e_phentsize(elfcpp::Elf_sizes<size>::phdr_size); - oehdr.put_e_phnum(this->segment_header_->data_size() - / elfcpp::Elf_sizes<size>::phdr_size); + size_t phnum = (this->segment_header_->data_size() + / elfcpp::Elf_sizes<size>::phdr_size); + if (phnum > elfcpp::PN_XNUM) + phnum = elfcpp::PN_XNUM; + oehdr.put_e_phnum(phnum); } oehdr.put_e_shentsize(elfcpp::Elf_sizes<size>::shdr_size); @@ -477,6 +495,10 @@ Output_file_header::do_sized_write(Output_file* of) else oehdr.put_e_shstrndx(elfcpp::SHN_XINDEX); + // Let the target adjust the ELF header, e.g., to set EI_OSABI in + // the e_ident field. + parameters->target().adjust_elf_header(view, ehdr_size); + of->write_output_view(0, ehdr_size, view); } @@ -524,6 +546,20 @@ Output_file_header::entry() return v; } +// Compute the current data size. + +off_t +Output_file_header::do_size() const +{ + const int size = parameters->target().get_size(); + if (size == 32) + return elfcpp::Elf_sizes<32>::ehdr_size; + else if (size == 64) + return elfcpp::Elf_sizes<64>::ehdr_size; + else + gold_unreachable(); +} + // Output_data_const methods. void @@ -602,9 +638,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( unsigned int type, Output_data* od, Address address, - bool is_relative) + bool is_relative, + bool is_symbolless) : address_(address), local_sym_index_(GSYM_CODE), type_(type), - is_relative_(is_relative), is_section_symbol_(false), shndx_(INVALID_CODE) + is_relative_(is_relative), is_symbolless_(is_symbolless), + is_section_symbol_(false), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -621,9 +659,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, - bool is_relative) + bool is_relative, + bool is_symbolless) : address_(address), local_sym_index_(GSYM_CODE), type_(type), - is_relative_(is_relative), is_section_symbol_(false), shndx_(shndx) + is_relative_(is_relative), is_symbolless_(is_symbolless), + is_section_symbol_(false), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -644,10 +684,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( Output_data* od, Address address, bool is_relative, + bool is_symbolless, bool is_section_symbol) : address_(address), local_sym_index_(local_sym_index), type_(type), - is_relative_(is_relative), is_section_symbol_(is_section_symbol), - shndx_(INVALID_CODE) + is_relative_(is_relative), is_symbolless_(is_symbolless), + is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE) { gold_assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE); @@ -667,10 +708,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( unsigned int shndx, Address address, bool is_relative, + bool is_symbolless, bool is_section_symbol) : address_(address), local_sym_index_(local_sym_index), type_(type), - is_relative_(is_relative), is_section_symbol_(is_section_symbol), - shndx_(shndx) + is_relative_(is_relative), is_symbolless_(is_symbolless), + is_section_symbol_(is_section_symbol), shndx_(shndx) { gold_assert(local_sym_index != GSYM_CODE && local_sym_index != INVALID_CODE); @@ -692,7 +734,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( Output_data* od, Address address) : address_(address), local_sym_index_(SECTION_CODE), type_(type), - is_relative_(false), is_section_symbol_(true), shndx_(INVALID_CODE) + is_relative_(false), is_symbolless_(false), + is_section_symbol_(true), shndx_(INVALID_CODE) { // this->type_ is a bitfield; make sure TYPE fits. gold_assert(this->type_ == type); @@ -712,7 +755,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( unsigned int shndx, Address address) : address_(address), local_sym_index_(SECTION_CODE), type_(type), - is_relative_(false), is_section_symbol_(true), shndx_(shndx) + is_relative_(false), is_symbolless_(false), + is_section_symbol_(true), shndx_(shndx) { gold_assert(shndx != INVALID_CODE); // this->type_ is a bitfield; make sure TYPE fits. @@ -725,6 +769,76 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( os->set_needs_symtab_index(); } +// An absolute relocation. + +template<bool dynamic, int size, bool big_endian> +Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( + unsigned int type, + Output_data* od, + Address address) + : address_(address), local_sym_index_(0), type_(type), + is_relative_(false), is_symbolless_(false), + is_section_symbol_(false), shndx_(INVALID_CODE) +{ + // this->type_ is a bitfield; make sure TYPE fits. + gold_assert(this->type_ == type); + this->u1_.relobj = NULL; + this->u2_.od = od; +} + +template<bool dynamic, int size, bool big_endian> +Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( + unsigned int type, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, + Address address) + : address_(address), local_sym_index_(0), type_(type), + is_relative_(false), is_symbolless_(false), + is_section_symbol_(false), shndx_(shndx) +{ + gold_assert(shndx != INVALID_CODE); + // this->type_ is a bitfield; make sure TYPE fits. + gold_assert(this->type_ == type); + this->u1_.relobj = NULL; + this->u2_.relobj = relobj; +} + +// A target specific relocation. + +template<bool dynamic, int size, bool big_endian> +Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( + unsigned int type, + void* arg, + Output_data* od, + Address address) + : address_(address), local_sym_index_(TARGET_CODE), type_(type), + is_relative_(false), is_symbolless_(false), + is_section_symbol_(false), shndx_(INVALID_CODE) +{ + // this->type_ is a bitfield; make sure TYPE fits. + gold_assert(this->type_ == type); + this->u1_.arg = arg; + this->u2_.od = od; +} + +template<bool dynamic, int size, bool big_endian> +Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc( + unsigned int type, + void* arg, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, + Address address) + : address_(address), local_sym_index_(TARGET_CODE), type_(type), + is_relative_(false), is_symbolless_(false), + is_section_symbol_(false), shndx_(shndx) +{ + gold_assert(shndx != INVALID_CODE); + // this->type_ is a bitfield; make sure TYPE fits. + gold_assert(this->type_ == type); + this->u1_.arg = arg; + this->u2_.relobj = relobj; +} + // Record that we need a dynamic symbol index for this relocation. template<bool dynamic, int size, bool big_endian> @@ -732,7 +846,7 @@ void Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>:: set_needs_dynsym_index() { - if (this->is_relative_) + if (this->is_symbolless_) return; switch (this->local_sym_index_) { @@ -747,6 +861,10 @@ set_needs_dynsym_index() this->u1_.os->set_needs_dynsym_index(); break; + case TARGET_CODE: + // The target must take care of this if necessary. + break; + case 0: break; @@ -770,6 +888,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index() const { unsigned int index; + if (this->is_symbolless_) + return 0; switch (this->local_sym_index_) { case INVALID_CODE: @@ -791,6 +911,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index() index = this->u1_.os->symtab_index(); break; + case TARGET_CODE: + index = parameters->target().reloc_symbol_index(this->u1_.arg, + this->type_); + break; + case 0: // Relocations without symbols use a symbol index of 0. index = 0; @@ -832,17 +957,19 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>:: { gold_assert(this->local_sym_index_ != GSYM_CODE && this->local_sym_index_ != SECTION_CODE + && this->local_sym_index_ != TARGET_CODE && this->local_sym_index_ != INVALID_CODE + && this->local_sym_index_ != 0 && this->is_section_symbol_); const unsigned int lsi = this->local_sym_index_; Output_section* os = this->u1_.relobj->output_section(lsi); gold_assert(os != NULL); Address offset = this->u1_.relobj->get_output_section_offset(lsi); - if (offset != -1U) + if (offset != invalid_address) return offset + addend; // This is a merge section. offset = os->output_address(this->u1_.relobj, lsi, addend); - gold_assert(offset != -1U); + gold_assert(offset != invalid_address); return offset; } @@ -858,13 +985,13 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_address() const Output_section* os = this->u2_.relobj->output_section(this->shndx_); gold_assert(os != NULL); Address off = this->u2_.relobj->get_output_section_offset(this->shndx_); - if (off != -1U) + if (off != invalid_address) address += os->address() + off; else { address = os->output_address(this->u2_.relobj, this->shndx_, address); - gold_assert(address != -1U); + gold_assert(address != invalid_address); } } else if (this->u2_.od != NULL) @@ -882,7 +1009,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel( Write_rel* wr) const { wr->put_r_offset(this->get_address()); - unsigned int sym_index = this->is_relative_ ? 0 : this->get_symbol_index(); + unsigned int sym_index = this->get_symbol_index(); wr->put_r_info(elfcpp::elf_r_info<size>(sym_index, this->type_)); } @@ -911,7 +1038,9 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value( return sym->value() + addend; } gold_assert(this->local_sym_index_ != SECTION_CODE + && this->local_sym_index_ != TARGET_CODE && this->local_sym_index_ != INVALID_CODE + && this->local_sym_index_ != 0 && !this->is_section_symbol_); const unsigned int lsi = this->local_sym_index_; const Symbol_value<size>* symval = this->u1_.relobj->local_symbol(lsi); @@ -979,7 +1108,10 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write( elfcpp::Rela_write<size, big_endian> orel(pov); this->rel_.write_rel(&orel); Addend addend = this->addend_; - if (this->rel_.is_relative()) + if (this->rel_.is_target_specific()) + addend = parameters->target().reloc_addend(this->rel_.target_arg(), + this->rel_.type(), addend); + else if (this->rel_.is_symbolless()) addend = this->rel_.symbol_value(addend); else if (this->rel_.is_local_section_symbol()) addend = this->rel_.local_section_offset(addend); @@ -1018,7 +1150,7 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write( const off_t oview_size = this->data_size(); unsigned char* const oview = of->get_output_view(off, oview_size); - if (this->sort_relocs_) + if (this->sort_relocs()) { gold_assert(dynamic); std::sort(this->relocs_.begin(), this->relocs_.end(), @@ -1060,7 +1192,7 @@ Output_data_group<size, big_endian>::Output_data_group( section_size_type entry_count, elfcpp::Elf_Word flags, std::vector<unsigned int>* input_shndxes) - : Output_section_data(entry_count * 4, 4), + : Output_section_data(entry_count * 4, 4, false), relobj_(relobj), flags_(flags) { @@ -1442,6 +1574,8 @@ Output_data_dynamic::Dynamic_entry::write( case DYNAMIC_SECTION_SIZE: val = this->u_.od->data_size(); + if (this->od2 != NULL) + val += this->od2->data_size(); break; case DYNAMIC_SYMBOL: @@ -1486,8 +1620,11 @@ Output_data_dynamic::do_adjust_output_section(Output_section* os) void Output_data_dynamic::set_final_data_size() { - // Add the terminating entry. - this->add_constant(elfcpp::DT_NULL, 0); + // Add the terminating entry if it hasn't been added. + // Because of relaxation, we can run this multiple times. + if (this->entries_.empty() + || this->entries_.rbegin()->tag() != elfcpp::DT_NULL) + this->add_constant(elfcpp::DT_NULL, 0); int dyn_size; if (parameters->target().get_size() == 32) @@ -1587,7 +1724,11 @@ Output_symtab_xindex::endian_do_write(unsigned char* const oview) for (Xindex_entries::const_iterator p = this->entries_.begin(); p != this->entries_.end(); ++p) - elfcpp::Swap<32, big_endian>::writeval(oview + p->first * 4, p->second); + { + unsigned int symndx = p->first; + gold_assert(symndx * 4 < this->data_size()); + elfcpp::Swap<32, big_endian>::writeval(oview + symndx * 4, p->second); + } } // Output_section::Input_section methods. @@ -1705,6 +1846,14 @@ Output_section::Input_section::print_to_mapfile(Mapfile* mapfile) const this->u2_.posd->print_to_mapfile(mapfile); break; + case RELAXED_INPUT_SECTION_CODE: + { + Output_relaxed_input_section* relaxed_section = + this->relaxed_input_section(); + mapfile->print_input_section(relaxed_section->relobj(), + relaxed_section->shndx()); + } + break; default: mapfile->print_input_section(this->u2_.object, this->shndx_); break; @@ -1749,7 +1898,22 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, attached_input_sections_are_sorted_(false), is_relro_(false), is_relro_local_(false), - tls_offset_(0) + is_last_relro_(false), + is_first_non_relro_(false), + is_small_section_(false), + is_large_section_(false), + is_interp_(false), + is_dynamic_linker_section_(false), + generate_code_fills_at_write_(false), + is_entsize_zero_(false), + section_offsets_need_adjustment_(false), + is_noload_(false), + tls_offset_(0), + checkpoint_(NULL), + merge_section_map_(), + merge_section_by_properties_map_(), + relaxed_input_section_map_(), + is_relaxed_input_section_map_valid_(true) { // An unallocated section has no address. Forcing this means that // we don't need special treatment for symbols defined in debug @@ -1760,6 +1924,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, Output_section::~Output_section() { + delete this->checkpoint_; } // Set the entry size. @@ -1767,10 +1932,15 @@ Output_section::~Output_section() void Output_section::set_entsize(uint64_t v) { - if (this->entsize_ == 0) + if (this->is_entsize_zero_) + ; + else if (this->entsize_ == 0) this->entsize_ = v; - else - gold_assert(this->entsize_ == v); + else if (this->entsize_ != v) + { + this->entsize_ = 0; + this->is_entsize_zero_ = 1; + } } // Add the input section SHNDX, with header SHDR, named SECNAME, in @@ -1806,8 +1976,6 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, this->addralign_ = addralign; typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags(); - this->update_flags_for_input_section(sh_flags); - uint64_t entsize = shdr.get_sh_entsize(); // .debug_str is a mergeable string section, but is not always so @@ -1818,6 +1986,9 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, entsize = 1; } + this->update_flags_for_input_section(sh_flags); + this->set_entsize(entsize); + // If this is a SHF_MERGE section, we pass all the input sections to // a Output_data_merge. We don't try to handle relocations for such // a section. We don't try to handle empty merge sections--they @@ -1839,10 +2010,24 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, off_t aligned_offset_in_section = align_address(offset_in_section, addralign); + // Determine if we want to delay code-fill generation until the output + // section is written. When the target is relaxing, we want to delay fill + // generating to avoid adjusting them during relaxation. + if (!this->generate_code_fills_at_write_ + && !have_sections_script + && (sh_flags & elfcpp::SHF_EXECINSTR) != 0 + && parameters->target().has_code_fill() + && parameters->target().may_relax()) + { + gold_assert(this->fills_.empty()); + this->generate_code_fills_at_write_ = true; + } + if (aligned_offset_in_section > offset_in_section + && !this->generate_code_fills_at_write_ && !have_sections_script && (sh_flags & elfcpp::SHF_EXECINSTR) != 0 - && object->target()->has_code_fill()) + && parameters->target().has_code_fill()) { // We need to add some fill data. Using fill_list_ when // possible is an optimization, since we will often have fill @@ -1852,9 +2037,7 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, this->fills_.push_back(Fill(offset_in_section, fill_len)); else { - // FIXME: When relaxing, the size needs to adjust to - // maintain a constant alignment. - std::string fill_data(object->target()->code_fill(fill_len)); + std::string fill_data(parameters->target().code_fill(fill_len)); Output_data_const* odc = new Output_data_const(fill_data, 1); this->input_sections_.push_back(Input_section(odc)); } @@ -1866,13 +2049,13 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object, // We need to keep track of this section if we are already keeping // track of sections, or if we are relaxing. Also, if this is a // section which requires sorting, or which may require sorting in - // the future, we keep track of the sections. FIXME: Add test for - // relaxing. + // the future, we keep track of the sections. if (have_sections_script || !this->input_sections_.empty() || this->may_sort_attached_input_sections() || this->must_sort_attached_input_sections() - || parameters->options().user_set_Map()) + || parameters->options().user_set_Map() + || parameters->target().may_relax()) this->input_sections_.push_back(Input_section(object, shndx, shdr.get_sh_size(), addralign)); @@ -1898,6 +2081,31 @@ Output_section::add_output_section_data(Output_section_data* posd) } } +// Add a relaxed input section. + +void +Output_section::add_relaxed_input_section(Output_relaxed_input_section* poris) +{ + Input_section inp(poris); + this->add_output_section_data(&inp); + if (this->is_relaxed_input_section_map_valid_) + { + Const_section_id csid(poris->relobj(), poris->shndx()); + this->relaxed_input_section_map_[csid] = poris; + } + + // For a relaxed section, we use the current data size. Linker scripts + // get all the input sections, including relaxed one from an output + // section and add them back to them same output section to compute the + // output section size. If we do not account for sizes of relaxed input + // sections, an output section would be incorrectly sized. + off_t offset_in_section = this->current_data_size_for_child(); + off_t aligned_offset_in_section = align_address(offset_in_section, + poris->addralign()); + this->set_current_data_size_for_child(aligned_offset_in_section + + poris->current_data_size()); +} + // Add arbitrary data to an output section by Input_section. void @@ -1939,43 +2147,248 @@ Output_section::add_merge_input_section(Relobj* object, unsigned int shndx, if (is_string && addralign > entsize) return false; - Input_section_list::iterator p; - for (p = this->input_sections_.begin(); - p != this->input_sections_.end(); - ++p) - if (p->is_merge_section(is_string, entsize, addralign)) - { - p->add_input_section(object, shndx); - return true; - } + // We cannot restore merged input section states. + gold_assert(this->checkpoint_ == NULL); - // We handle the actual constant merging in Output_merge_data or - // Output_merge_string_data. - Output_section_data* posd; - if (!is_string) - posd = new Output_merge_data(entsize, addralign); + // Look up merge sections by required properties. + Output_merge_base* pomb; + Merge_section_properties msp(is_string, entsize, addralign); + Merge_section_by_properties_map::const_iterator p = + this->merge_section_by_properties_map_.find(msp); + if (p != this->merge_section_by_properties_map_.end()) + { + pomb = p->second; + gold_assert(pomb->is_string() == is_string + && pomb->entsize() == entsize + && pomb->addralign() == addralign); + } else { - switch (entsize) + // Create a new Output_merge_data or Output_merge_string_data. + if (!is_string) + pomb = new Output_merge_data(entsize, addralign); + else { - case 1: - posd = new Output_merge_string<char>(addralign); - break; - case 2: - posd = new Output_merge_string<uint16_t>(addralign); - break; - case 4: - posd = new Output_merge_string<uint32_t>(addralign); - break; - default: - return false; + switch (entsize) + { + case 1: + pomb = new Output_merge_string<char>(addralign); + break; + case 2: + pomb = new Output_merge_string<uint16_t>(addralign); + break; + case 4: + pomb = new Output_merge_string<uint32_t>(addralign); + break; + default: + return false; + } } + // Add new merge section to this output section and link merge + // section properties to new merge section in map. + this->add_output_merge_section(pomb, is_string, entsize); + this->merge_section_by_properties_map_[msp] = pomb; } - this->add_output_merge_section(posd, is_string, entsize); - posd->add_input_section(object, shndx); + if (pomb->add_input_section(object, shndx)) + { + // Add input section to new merge section and link input section to new + // merge section in map. + Const_section_id csid(object, shndx); + this->merge_section_map_[csid] = pomb; + return true; + } + else + return false; +} - return true; +// Build a relaxation map to speed up relaxation of existing input sections. +// Look up to the first LIMIT elements in INPUT_SECTIONS. + +void +Output_section::build_relaxation_map( + const Input_section_list& input_sections, + size_t limit, + Relaxation_map* relaxation_map) const +{ + for (size_t i = 0; i < limit; ++i) + { + const Input_section& is(input_sections[i]); + if (is.is_input_section() || is.is_relaxed_input_section()) + { + Section_id sid(is.relobj(), is.shndx()); + (*relaxation_map)[sid] = i; + } + } +} + +// Convert regular input sections in INPUT_SECTIONS into relaxed input +// sections in RELAXED_SECTIONS. MAP is a prebuilt map from section id +// indices of INPUT_SECTIONS. + +void +Output_section::convert_input_sections_in_list_to_relaxed_sections( + const std::vector<Output_relaxed_input_section*>& relaxed_sections, + const Relaxation_map& map, + Input_section_list* input_sections) +{ + for (size_t i = 0; i < relaxed_sections.size(); ++i) + { + Output_relaxed_input_section* poris = relaxed_sections[i]; + Section_id sid(poris->relobj(), poris->shndx()); + Relaxation_map::const_iterator p = map.find(sid); + gold_assert(p != map.end()); + gold_assert((*input_sections)[p->second].is_input_section()); + (*input_sections)[p->second] = Input_section(poris); + } +} + +// Convert regular input sections into relaxed input sections. RELAXED_SECTIONS +// is a vector of pointers to Output_relaxed_input_section or its derived +// classes. The relaxed sections must correspond to existing input sections. + +void +Output_section::convert_input_sections_to_relaxed_sections( + const std::vector<Output_relaxed_input_section*>& relaxed_sections) +{ + gold_assert(parameters->target().may_relax()); + + // We want to make sure that restore_states does not undo the effect of + // this. If there is no checkpoint active, just search the current + // input section list and replace the sections there. If there is + // a checkpoint, also replace the sections there. + + // By default, we look at the whole list. + size_t limit = this->input_sections_.size(); + + if (this->checkpoint_ != NULL) + { + // Replace input sections with relaxed input section in the saved + // copy of the input section list. + if (this->checkpoint_->input_sections_saved()) + { + Relaxation_map map; + this->build_relaxation_map( + *(this->checkpoint_->input_sections()), + this->checkpoint_->input_sections()->size(), + &map); + this->convert_input_sections_in_list_to_relaxed_sections( + relaxed_sections, + map, + this->checkpoint_->input_sections()); + } + else + { + // We have not copied the input section list yet. Instead, just + // look at the portion that would be saved. + limit = this->checkpoint_->input_sections_size(); + } + } + + // Convert input sections in input_section_list. + Relaxation_map map; + this->build_relaxation_map(this->input_sections_, limit, &map); + this->convert_input_sections_in_list_to_relaxed_sections( + relaxed_sections, + map, + &this->input_sections_); + + // Update fast look-up map. + if (this->is_relaxed_input_section_map_valid_) + for (size_t i = 0; i < relaxed_sections.size(); ++i) + { + Output_relaxed_input_section* poris = relaxed_sections[i]; + Const_section_id csid(poris->relobj(), poris->shndx()); + this->relaxed_input_section_map_[csid] = poris; + } +} + +// Update the output section flags based on input section flags. + +void +Output_section::update_flags_for_input_section(elfcpp::Elf_Xword flags) +{ + // If we created the section with SHF_ALLOC clear, we set the + // address. If we are now setting the SHF_ALLOC flag, we need to + // undo that. + if ((this->flags_ & elfcpp::SHF_ALLOC) == 0 + && (flags & elfcpp::SHF_ALLOC) != 0) + this->mark_address_invalid(); + + this->flags_ |= (flags + & (elfcpp::SHF_WRITE + | elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR)); + + if ((flags & elfcpp::SHF_MERGE) == 0) + this->flags_ &=~ elfcpp::SHF_MERGE; + else + { + if (this->current_data_size_for_child() == 0) + this->flags_ |= elfcpp::SHF_MERGE; + } + + if ((flags & elfcpp::SHF_STRINGS) == 0) + this->flags_ &=~ elfcpp::SHF_STRINGS; + else + { + if (this->current_data_size_for_child() == 0) + this->flags_ |= elfcpp::SHF_STRINGS; + } +} + +// Find the merge section into which an input section with index SHNDX in +// OBJECT has been added. Return NULL if none found. + +Output_section_data* +Output_section::find_merge_section(const Relobj* object, + unsigned int shndx) const +{ + Const_section_id csid(object, shndx); + Output_section_data_by_input_section_map::const_iterator p = + this->merge_section_map_.find(csid); + if (p != this->merge_section_map_.end()) + { + Output_section_data* posd = p->second; + gold_assert(posd->is_merge_section_for(object, shndx)); + return posd; + } + else + return NULL; +} + +// Find an relaxed input section corresponding to an input section +// in OBJECT with index SHNDX. + +const Output_relaxed_input_section* +Output_section::find_relaxed_input_section(const Relobj* object, + unsigned int shndx) const +{ + // Be careful that the map may not be valid due to input section export + // to scripts or a check-point restore. + if (!this->is_relaxed_input_section_map_valid_) + { + // Rebuild the map as needed. + this->relaxed_input_section_map_.clear(); + for (Input_section_list::const_iterator p = this->input_sections_.begin(); + p != this->input_sections_.end(); + ++p) + if (p->is_relaxed_input_section()) + { + Const_section_id csid(p->relobj(), p->shndx()); + this->relaxed_input_section_map_[csid] = + p->relaxed_input_section(); + } + this->is_relaxed_input_section_map_valid_ = true; + } + + Const_section_id csid(object, shndx); + Output_relaxed_input_section_by_input_section_map::const_iterator p = + this->relaxed_input_section_map_.find(csid); + if (p != this->relaxed_input_section_map_.end()) + return p->second; + else + return NULL; } // Given an address OFFSET relative to the start of input section @@ -1988,6 +2401,20 @@ Output_section::is_input_address_mapped(const Relobj* object, unsigned int shndx, off_t offset) const { + // Look at the Output_section_data_maps first. + const Output_section_data* posd = this->find_merge_section(object, shndx); + if (posd == NULL) + posd = this->find_relaxed_input_section(object, shndx); + + if (posd != NULL) + { + section_offset_type output_offset; + bool found = posd->output_offset(object, shndx, offset, &output_offset); + gold_assert(found); + return output_offset != -1; + } + + // Fall back to the slow look-up. for (Input_section_list::const_iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p) @@ -2012,9 +2439,23 @@ section_offset_type Output_section::output_offset(const Relobj* object, unsigned int shndx, section_offset_type offset) const { - // This can only be called meaningfully when layout is complete. - gold_assert(Output_data::is_layout_complete()); + // This can only be called meaningfully when we know the data size + // of this. + gold_assert(this->is_data_size_valid()); + + // Look at the Output_section_data_maps first. + const Output_section_data* posd = this->find_merge_section(object, shndx); + if (posd == NULL) + posd = this->find_relaxed_input_section(object, shndx); + if (posd != NULL) + { + section_offset_type output_offset; + bool found = posd->output_offset(object, shndx, offset, &output_offset); + gold_assert(found); + return output_offset; + } + // Fall back to the slow look-up. for (Input_section_list::const_iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p) @@ -2034,6 +2475,20 @@ Output_section::output_address(const Relobj* object, unsigned int shndx, off_t offset) const { uint64_t addr = this->address() + this->first_input_offset_; + + // Look at the Output_section_data_maps first. + const Output_section_data* posd = this->find_merge_section(object, shndx); + if (posd == NULL) + posd = this->find_relaxed_input_section(object, shndx); + if (posd != NULL && posd->is_address_valid()) + { + section_offset_type output_offset; + bool found = posd->output_offset(object, shndx, offset, &output_offset); + gold_assert(found); + return posd->address() + output_offset; + } + + // Fall back to the slow look-up. for (Input_section_list::const_iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p) @@ -2043,7 +2498,7 @@ Output_section::output_address(const Relobj* object, unsigned int shndx, if (p->output_offset(object, shndx, offset, &output_offset)) { if (output_offset == -1) - return -1U; + return -1ULL; return addr + output_offset; } addr += p->data_size(); @@ -2057,13 +2512,17 @@ Output_section::output_address(const Relobj* object, unsigned int shndx, gold_unreachable(); } -// Return the output address of the start of the merged section for +// Find the output address of the start of the merged section for // input section SHNDX in object OBJECT. -uint64_t -Output_section::starting_output_address(const Relobj* object, - unsigned int shndx) const +bool +Output_section::find_starting_output_address(const Relobj* object, + unsigned int shndx, + uint64_t* paddr) const { + // FIXME: This becomes a bottle-neck if we have many relaxed sections. + // Looking up the merge section map does not always work as we sometimes + // find a merge section without its address set. uint64_t addr = this->address() + this->first_input_offset_; for (Input_section_list::const_iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); @@ -2076,11 +2535,16 @@ Output_section::starting_output_address(const Relobj* object, // Unfortunately we don't know for sure that input offset 0 is // mapped at all. if (p->is_merge_section_for(object, shndx)) - return addr; + { + *paddr = addr; + return true; + } addr += p->data_size(); } - gold_unreachable(); + + // We couldn't find a merge output section for this input section. + return false; } // Set the data size of an Output_section. This is where we handle @@ -2119,11 +2583,33 @@ Output_section::set_final_data_size() void Output_section::do_reset_address_and_file_offset() { + // An unallocated section has no address. Forcing this means that + // we don't need special treatment for symbols defined in debug + // sections. We do the same in the constructor. This does not + // apply to NOLOAD sections though. + if (((this->flags_ & elfcpp::SHF_ALLOC) == 0) && !this->is_noload_) + this->set_address(0); + for (Input_section_list::iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p) p->reset_address_and_file_offset(); } + +// Return true if address and file offset have the values after reset. + +bool +Output_section::do_address_and_file_offset_have_reset_values() const +{ + if (this->is_offset_valid()) + return false; + + // An unallocated section has address 0 after its construction or a reset. + if ((this->flags_ & elfcpp::SHF_ALLOC) == 0) + return this->is_address_valid() && this->address() == 0; + else + return !this->is_address_valid(); +} // Set the TLS offset. Called only for SHT_TLS sections. @@ -2152,7 +2638,8 @@ class Output_section::Input_section_sort_entry Input_section_sort_entry(const Input_section& input_section, unsigned int index) : input_section_(input_section), index_(index), - section_has_name_(input_section.is_input_section()) + section_has_name_(input_section.is_input_section() + || input_section.is_relaxed_input_section()) { if (this->section_has_name_) { @@ -2160,7 +2647,9 @@ class Output_section::Input_section_sort_entry // so it is OK to lock. Unfortunately we have no way to pass // in a Task token. const Task* dummy_task = reinterpret_cast<const Task*>(-1); - Object* obj = input_section.relobj(); + Object* obj = (input_section.is_input_section() + ? input_section.relobj() + : input_section.relaxed_input_section()->relobj()); Task_lock_obj<Object> tl(dummy_task, obj); // This is a slow operation, which should be cached in @@ -2205,7 +2694,7 @@ class Output_section::Input_section_sort_entry has_priority() const { gold_assert(this->section_has_name_); - return this->section_name_.find('.', 1); + return this->section_name_.find('.', 1) != std::string::npos; } // Return true if this an input file whose base name matches @@ -2283,8 +2772,6 @@ Output_section::Input_section_sort_compare::operator()( } // A section with a priority follows a section without a priority. - // The GNU linker does this for all but .init_array sections; until - // further notice we'll assume that that is an mistake. bool s1_has_priority = s1.has_priority(); bool s2_has_priority = s2.has_priority(); if (s1_has_priority && !s2_has_priority) @@ -2301,6 +2788,42 @@ Output_section::Input_section_sort_compare::operator()( return s1.index() < s2.index(); } +// Return true if S1 should come before S2 in an .init_array or .fini_array +// output section. + +bool +Output_section::Input_section_sort_init_fini_compare::operator()( + const Output_section::Input_section_sort_entry& s1, + const Output_section::Input_section_sort_entry& s2) const +{ + // We sort all the sections with no names to the end. + if (!s1.section_has_name() || !s2.section_has_name()) + { + if (s1.section_has_name()) + return true; + if (s2.section_has_name()) + return false; + return s1.index() < s2.index(); + } + + // A section without a priority follows a section with a priority. + // This is the reverse of .ctors and .dtors sections. + bool s1_has_priority = s1.has_priority(); + bool s2_has_priority = s2.has_priority(); + if (s1_has_priority && !s2_has_priority) + return true; + if (!s1_has_priority && s2_has_priority) + return false; + + // Otherwise we sort by name. + int compare = s1.section_name().compare(s2.section_name()); + if (compare != 0) + return compare < 0; + + // Otherwise we keep the input order. + return s1.index() < s2.index(); +} + // Sort the input sections attached to an output section. void @@ -2309,6 +2832,10 @@ Output_section::sort_attached_input_sections() if (this->attached_input_sections_are_sorted_) return; + if (this->checkpoint_ != NULL + && !this->checkpoint_->input_sections_saved()) + this->checkpoint_->save_input_sections(); + // The only thing we know about an input section is the object and // the section index. We need the section name. Recomputing this // is slow but this is an unusual case. If this becomes a speed @@ -2325,7 +2852,14 @@ Output_section::sort_attached_input_sections() sort_list.push_back(Input_section_sort_entry(*p, i)); // Sort the input sections. - std::sort(sort_list.begin(), sort_list.end(), Input_section_sort_compare()); + if (this->type() == elfcpp::SHT_PREINIT_ARRAY + || this->type() == elfcpp::SHT_INIT_ARRAY + || this->type() == elfcpp::SHT_FINI_ARRAY) + std::sort(sort_list.begin(), sort_list.end(), + Input_section_sort_init_fini_compare()); + else + std::sort(sort_list.begin(), sort_list.end(), + Input_section_sort_compare()); // Copy the sorted input sections back to our list. this->input_sections_.clear(); @@ -2394,6 +2928,9 @@ Output_section::do_write(Output_file* of) { gold_assert(!this->requires_postprocessing()); + // If the target performs relaxation, we delay filler generation until now. + gold_assert(!this->generate_code_fills_at_write_ || this->fills_.empty()); + off_t output_section_file_offset = this->offset(); for (Fill_list::iterator p = this->fills_.begin(); p != this->fills_.end(); @@ -2404,10 +2941,22 @@ Output_section::do_write(Output_file* of) fill_data.data(), fill_data.size()); } + off_t off = this->offset() + this->first_input_offset_; for (Input_section_list::iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); ++p) - p->write(of); + { + off_t aligned_off = align_address(off, p->addralign()); + if (this->generate_code_fills_at_write_ && (off != aligned_off)) + { + size_t fill_len = aligned_off - off; + std::string fill_data(parameters->target().code_fill(fill_len)); + of->write(off, fill_data.data(), fill_data.size()); + } + + p->write(of); + off = aligned_off + p->data_size(); + } } // If a section requires postprocessing, create the buffer to use. @@ -2448,6 +2997,9 @@ Output_section::write_to_postprocessing_buffer() { gold_assert(this->requires_postprocessing()); + // If the target performs relaxation, we delay filler generation until now. + gold_assert(!this->generate_code_fills_at_write_ || this->fills_.empty()); + unsigned char* buffer = this->postprocessing_buffer(); for (Fill_list::iterator p = this->fills_.begin(); p != this->fills_.end(); @@ -2463,9 +3015,16 @@ Output_section::write_to_postprocessing_buffer() p != this->input_sections_.end(); ++p) { - off = align_address(off, p->addralign()); - p->write_to_buffer(buffer + off); - off += p->data_size(); + off_t aligned_off = align_address(off, p->addralign()); + if (this->generate_code_fills_at_write_ && (off != aligned_off)) + { + size_t fill_len = aligned_off - off; + std::string fill_data(parameters->target().code_fill(fill_len)); + memcpy(buffer + off, fill_data.data(), fill_data.size()); + } + + p->write_to_buffer(buffer + aligned_off); + off = aligned_off + p->data_size(); } } @@ -2483,8 +3042,15 @@ uint64_t Output_section::get_input_sections( uint64_t address, const std::string& fill, - std::list<std::pair<Relobj*, unsigned int> >* input_sections) + std::list<Simple_input_section>* input_sections) { + if (this->checkpoint_ != NULL + && !this->checkpoint_->input_sections_saved()) + this->checkpoint_->save_input_sections(); + + // Invalidate the relaxed input section map. + this->is_relaxed_input_section_map_valid_ = false; + uint64_t orig_address = address; address = align_address(address, this->addralign()); @@ -2495,7 +3061,11 @@ Output_section::get_input_sections( ++p) { if (p->is_input_section()) - input_sections->push_back(std::make_pair(p->relobj(), p->shndx())); + input_sections->push_back(Simple_input_section(p->relobj(), + p->shndx())); + else if (p->is_relaxed_input_section()) + input_sections->push_back( + Simple_input_section(p->relaxed_input_section())); else { uint64_t aligned_address = align_address(address, p->addralign()); @@ -2530,13 +3100,12 @@ Output_section::get_input_sections( return data_size; } -// Add an input section from a script. +// Add an simple input section. void -Output_section::add_input_section_for_script(Relobj* object, - unsigned int shndx, - off_t data_size, - uint64_t addralign) +Output_section::add_simple_input_section(const Simple_input_section& sis, + off_t data_size, + uint64_t addralign) { if (addralign > this->addralign_) this->addralign_ = addralign; @@ -2548,8 +3117,96 @@ Output_section::add_input_section_for_script(Relobj* object, this->set_current_data_size_for_child(aligned_offset_in_section + data_size); - this->input_sections_.push_back(Input_section(object, shndx, - data_size, addralign)); + Input_section is = + (sis.is_relaxed_input_section() + ? Input_section(sis.relaxed_input_section()) + : Input_section(sis.relobj(), sis.shndx(), data_size, addralign)); + this->input_sections_.push_back(is); +} + +// Save states for relaxation. + +void +Output_section::save_states() +{ + gold_assert(this->checkpoint_ == NULL); + Checkpoint_output_section* checkpoint = + new Checkpoint_output_section(this->addralign_, this->flags_, + this->input_sections_, + this->first_input_offset_, + this->attached_input_sections_are_sorted_); + this->checkpoint_ = checkpoint; + gold_assert(this->fills_.empty()); +} + +void +Output_section::discard_states() +{ + gold_assert(this->checkpoint_ != NULL); + delete this->checkpoint_; + this->checkpoint_ = NULL; + gold_assert(this->fills_.empty()); + + // Simply invalidate the relaxed input section map since we do not keep + // track of it. + this->is_relaxed_input_section_map_valid_ = false; +} + +void +Output_section::restore_states() +{ + gold_assert(this->checkpoint_ != NULL); + Checkpoint_output_section* checkpoint = this->checkpoint_; + + this->addralign_ = checkpoint->addralign(); + this->flags_ = checkpoint->flags(); + this->first_input_offset_ = checkpoint->first_input_offset(); + + if (!checkpoint->input_sections_saved()) + { + // If we have not copied the input sections, just resize it. + size_t old_size = checkpoint->input_sections_size(); + gold_assert(this->input_sections_.size() >= old_size); + this->input_sections_.resize(old_size); + } + else + { + // We need to copy the whole list. This is not efficient for + // extremely large output with hundreads of thousands of input + // objects. We may need to re-think how we should pass sections + // to scripts. + this->input_sections_ = *checkpoint->input_sections(); + } + + this->attached_input_sections_are_sorted_ = + checkpoint->attached_input_sections_are_sorted(); + + // Simply invalidate the relaxed input section map since we do not keep + // track of it. + this->is_relaxed_input_section_map_valid_ = false; +} + +// Update the section offsets of input sections in this. This is required if +// relaxation causes some input sections to change sizes. + +void +Output_section::adjust_section_offsets() +{ + if (!this->section_offsets_need_adjustment_) + return; + + off_t off = 0; + for (Input_section_list::iterator p = this->input_sections_.begin(); + p != this->input_sections_.end(); + ++p) + { + off = align_address(off, p->addralign()); + if (p->is_input_section()) + p->relobj()->set_section_offset(p->shndx(), off); + off += p->data_size(); + } + + this->section_offsets_need_adjustment_ = false; } // Print to the map file. @@ -2592,21 +3249,28 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) type_(type), flags_(flags), is_max_align_known_(false), - are_addresses_set_(false) + are_addresses_set_(false), + is_large_data_segment_(false) { + // The ELF ABI specifies that a PT_TLS segment always has PF_R as + // the flags. + if (type == elfcpp::PT_TLS) + this->flags_ = elfcpp::PF_R; } // Add an Output_section to an Output_segment. void Output_segment::add_output_section(Output_section* os, - elfcpp::Elf_Word seg_flags) + elfcpp::Elf_Word seg_flags, + bool do_sort) { gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0); gold_assert(!this->is_max_align_known_); + gold_assert(os->is_large_data_section() == this->is_large_data_segment()); + gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort); - // Update the segment flags. - this->flags_ |= seg_flags; + this->update_flags_for_output_section(seg_flags); Output_segment::Output_data_list* pdl; if (os->type() == elfcpp::SHT_NOBITS) @@ -2614,19 +3278,12 @@ Output_segment::add_output_section(Output_section* os, else pdl = &this->output_data_; - // So that PT_NOTE segments will work correctly, we need to ensure - // that all SHT_NOTE sections are adjacent. This will normally - // happen automatically, because all the SHT_NOTE input sections - // will wind up in the same output section. However, it is possible - // for multiple SHT_NOTE input sections to have different section - // flags, and thus be in different output sections, but for the - // different section flags to map into the same segment flags and - // thus the same output segment. - // Note that while there may be many input sections in an output // section, there are normally only a few output sections in an - // output segment. This loop is expected to be fast. + // output segment. The loops below are expected to be fast. + // So that PT_NOTE segments will work correctly, we need to ensure + // that all SHT_NOTE sections are adjacent. if (os->type() == elfcpp::SHT_NOTE && !pdl->empty()) { Output_segment::Output_data_list::iterator p = pdl->end(); @@ -2648,69 +3305,225 @@ Output_segment::add_output_section(Output_section* os, // case: we group the SHF_TLS/SHT_NOBITS sections right after the // SHF_TLS/SHT_PROGBITS sections. This lets us set up PT_TLS // correctly. SHF_TLS sections get added to both a PT_LOAD segment - // and the PT_TLS segment -- we do this grouping only for the - // PT_LOAD segment. + // and the PT_TLS segment; we do this grouping only for the PT_LOAD + // segment. if (this->type_ != elfcpp::PT_TLS && (os->flags() & elfcpp::SHF_TLS) != 0) { pdl = &this->output_data_; - bool nobits = os->type() == elfcpp::SHT_NOBITS; - bool sawtls = false; - Output_segment::Output_data_list::iterator p = pdl->end(); - do + if (!pdl->empty()) { - --p; - bool insert; - if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) + bool nobits = os->type() == elfcpp::SHT_NOBITS; + bool sawtls = false; + Output_segment::Output_data_list::iterator p = pdl->end(); + gold_assert(p != pdl->begin()); + do { - sawtls = true; - // Put a NOBITS section after the first TLS section. - // Put a PROGBITS section after the first TLS/PROGBITS - // section. - insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS); + --p; + bool insert; + if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) + { + sawtls = true; + // Put a NOBITS section after the first TLS section. + // Put a PROGBITS section after the first + // TLS/PROGBITS section. + insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS); + } + else + { + // If we've gone past the TLS sections, but we've + // seen a TLS section, then we need to insert this + // section now. + insert = sawtls; + } + + if (insert) + { + ++p; + pdl->insert(p, os); + return; + } } - else + while (p != pdl->begin()); + } + + // There are no TLS sections yet; put this one at the requested + // location in the section list. + } + + if (do_sort) + { + // For the PT_GNU_RELRO segment, we need to group relro + // sections, and we need to put them before any non-relro + // sections. Any relro local sections go before relro non-local + // sections. One section may be marked as the last relro + // section. + if (os->is_relro()) + { + gold_assert(pdl == &this->output_data_); + Output_segment::Output_data_list::iterator p; + for (p = pdl->begin(); p != pdl->end(); ++p) { - // If we've gone past the TLS sections, but we've seen a - // TLS section, then we need to insert this section now. - insert = sawtls; + if (!(*p)->is_section()) + break; + + Output_section* pos = (*p)->output_section(); + if (!pos->is_relro() + || (os->is_relro_local() && !pos->is_relro_local()) + || (!os->is_last_relro() && pos->is_last_relro())) + break; } - if (insert) + pdl->insert(p, os); + return; + } + + // One section may be marked as the first section which follows + // the relro sections. + if (os->is_first_non_relro()) + { + gold_assert(pdl == &this->output_data_); + Output_segment::Output_data_list::iterator p; + for (p = pdl->begin(); p != pdl->end(); ++p) + { + if (!(*p)->is_section()) + break; + + Output_section* pos = (*p)->output_section(); + if (!pos->is_relro()) + break; + } + + pdl->insert(p, os); + return; + } + } + + // Small data sections go at the end of the list of data sections. + // If OS is not small, and there are small sections, we have to + // insert it before the first small section. + if (os->type() != elfcpp::SHT_NOBITS + && !os->is_small_section() + && !pdl->empty() + && pdl->back()->is_section() + && pdl->back()->output_section()->is_small_section()) + { + for (Output_segment::Output_data_list::iterator p = pdl->begin(); + p != pdl->end(); + ++p) + { + if ((*p)->is_section() + && (*p)->output_section()->is_small_section()) { - ++p; pdl->insert(p, os); return; } } - while (p != pdl->begin()); + gold_unreachable(); + } - // There are no TLS sections yet; put this one at the requested - // location in the section list. + // A small BSS section goes at the start of the BSS sections, after + // other small BSS sections. + if (os->type() == elfcpp::SHT_NOBITS && os->is_small_section()) + { + for (Output_segment::Output_data_list::iterator p = pdl->begin(); + p != pdl->end(); + ++p) + { + if (!(*p)->is_section() + || !(*p)->output_section()->is_small_section()) + { + pdl->insert(p, os); + return; + } + } } - // For the PT_GNU_RELRO segment, we need to group relro sections, - // and we need to put them before any non-relro sections. Also, - // relro local sections go before relro non-local sections. - if (parameters->options().relro() && os->is_relro()) + // A large BSS section goes at the end of the BSS sections, which + // means that one that is not large must come before the first large + // one. + if (os->type() == elfcpp::SHT_NOBITS + && !os->is_large_section() + && !pdl->empty() + && pdl->back()->is_section() + && pdl->back()->output_section()->is_large_section()) { - gold_assert(pdl == &this->output_data_); - Output_segment::Output_data_list::iterator p; - for (p = pdl->begin(); p != pdl->end(); ++p) + for (Output_segment::Output_data_list::iterator p = pdl->begin(); + p != pdl->end(); + ++p) { - if (!(*p)->is_section()) - break; + if ((*p)->is_section() + && (*p)->output_section()->is_large_section()) + { + pdl->insert(p, os); + return; + } + } + gold_unreachable(); + } - Output_section* pos = (*p)->output_section(); - if (!pos->is_relro() - || (os->is_relro_local() && !pos->is_relro_local())) - break; + // We do some further output section sorting in order to make the + // generated program run more efficiently. We should only do this + // when not using a linker script, so it is controled by the DO_SORT + // parameter. + if (do_sort) + { + // FreeBSD requires the .interp section to be in the first page + // of the executable. That is a more efficient location anyhow + // for any OS, since it means that the kernel will have the data + // handy after it reads the program headers. + if (os->is_interp() && !pdl->empty()) + { + pdl->insert(pdl->begin(), os); + return; } - pdl->insert(p, os); - return; + // Put loadable non-writable notes immediately after the .interp + // sections, so that the PT_NOTE segment is on the first page of + // the executable. + if (os->type() == elfcpp::SHT_NOTE + && (os->flags() & elfcpp::SHF_WRITE) == 0 + && !pdl->empty()) + { + Output_segment::Output_data_list::iterator p = pdl->begin(); + if ((*p)->is_section() && (*p)->output_section()->is_interp()) + ++p; + pdl->insert(p, os); + return; + } + + // If this section is used by the dynamic linker, and it is not + // writable, then put it first, after the .interp section and + // any loadable notes. This makes it more likely that the + // dynamic linker will have to read less data from the disk. + if (os->is_dynamic_linker_section() + && !pdl->empty() + && (os->flags() & elfcpp::SHF_WRITE) == 0) + { + bool is_reloc = (os->type() == elfcpp::SHT_REL + || os->type() == elfcpp::SHT_RELA); + Output_segment::Output_data_list::iterator p = pdl->begin(); + while (p != pdl->end() + && (*p)->is_section() + && ((*p)->output_section()->is_dynamic_linker_section() + || (*p)->output_section()->type() == elfcpp::SHT_NOTE)) + { + // Put reloc sections after the other ones. Putting the + // dynamic reloc sections first confuses BFD, notably + // objcopy and strip. + if (!is_reloc + && ((*p)->output_section()->type() == elfcpp::SHT_REL + || (*p)->output_section()->type() == elfcpp::SHT_RELA)) + break; + ++p; + } + pdl->insert(p, os); + return; + } } + // If there were no constraints on the output section, just add it + // to the end of the list. pdl->push_back(os); } @@ -2735,8 +3548,8 @@ Output_segment::remove_output_section(Output_section* os) gold_unreachable(); } -// Add an Output_data (which is not an Output_section) to the start of -// a segment. +// Add an Output_data (which need not be an Output_section) to the +// start of a segment. void Output_segment::add_initial_output_data(Output_data* od) @@ -2772,19 +3585,6 @@ Output_segment::maximum_alignment() if (addralign > this->max_align_) this->max_align_ = addralign; - // If -z relro is in effect, and the first section in this - // segment is a relro section, then the segment must be aligned - // to at least the common page size. This ensures that the - // PT_GNU_RELRO segment will start at a page boundary. - if (this->type_ == elfcpp::PT_LOAD - && parameters->options().relro() - && this->is_first_section_relro()) - { - addralign = parameters->target().common_pagesize(); - if (addralign > this->max_align_) - this->max_align_ = addralign; - } - this->is_max_align_known_ = true; } @@ -2838,11 +3638,57 @@ Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const uint64_t Output_segment::set_section_addresses(const Layout* layout, bool reset, - uint64_t addr, off_t* poff, + uint64_t addr, + unsigned int increase_relro, + off_t* poff, unsigned int* pshndx) { gold_assert(this->type_ == elfcpp::PT_LOAD); + off_t orig_off = *poff; + + // If we have relro sections, we need to pad forward now so that the + // relro sections plus INCREASE_RELRO end on a common page boundary. + if (parameters->options().relro() + && this->is_first_section_relro() + && (!this->are_addresses_set_ || reset)) + { + uint64_t relro_size = 0; + off_t off = *poff; + for (Output_data_list::iterator p = this->output_data_.begin(); + p != this->output_data_.end(); + ++p) + { + if (!(*p)->is_section()) + break; + Output_section* pos = (*p)->output_section(); + if (!pos->is_relro()) + break; + gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS)); + if ((*p)->is_address_valid()) + relro_size += (*p)->data_size(); + else + { + // FIXME: This could be faster. + (*p)->set_address_and_file_offset(addr + relro_size, + off + relro_size); + relro_size += (*p)->data_size(); + (*p)->reset_address_and_file_offset(); + } + } + relro_size += increase_relro; + + uint64_t page_align = parameters->target().common_pagesize(); + + // Align to offset N such that (N + RELRO_SIZE) % PAGE_ALIGN == 0. + uint64_t desired_align = page_align - (relro_size % page_align); + if (desired_align < *poff % page_align) + *poff += page_align - *poff % page_align; + *poff += desired_align - *poff % page_align; + addr += *poff - orig_off; + orig_off = *poff; + } + if (!reset && this->are_addresses_set_) { gold_assert(this->paddr_ == addr); @@ -2857,15 +3703,10 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, bool in_tls = false; - bool in_relro = (parameters->options().relro() - && this->is_first_section_relro()); - - off_t orig_off = *poff; this->offset_ = orig_off; addr = this->set_section_list_addresses(layout, reset, &this->output_data_, - addr, poff, pshndx, &in_tls, - &in_relro); + addr, poff, pshndx, &in_tls); this->filesz_ = *poff - orig_off; off_t off = *poff; @@ -2873,7 +3714,7 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, uint64_t ret = this->set_section_list_addresses(layout, reset, &this->output_bss_, addr, poff, pshndx, - &in_tls, &in_relro); + &in_tls); // If the last section was a TLS section, align upward to the // alignment of the TLS segment, so that the overall size of the TLS @@ -2884,14 +3725,6 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, *poff = align_address(*poff, segment_align); } - // If all the sections were relro sections, align upward to the - // common page size. - if (in_relro) - { - uint64_t page_align = parameters->target().common_pagesize(); - *poff = align_address(*poff, page_align); - } - this->memsz_ = *poff - orig_off; // Ignore the file offset adjustments made by the BSS Output_data @@ -2909,7 +3742,7 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset, Output_data_list* pdl, uint64_t addr, off_t* poff, unsigned int* pshndx, - bool* in_tls, bool* in_relro) + bool* in_tls) { off_t startoff = *poff; @@ -2960,19 +3793,6 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset, } } - // If this is a non-relro section after a relro section, - // align it to a common page boundary so that the dynamic - // linker has a page to mark as read-only. - if (*in_relro - && (!(*p)->is_section() - || !(*p)->output_section()->is_relro())) - { - uint64_t page_align = parameters->target().common_pagesize(); - if (page_align > align) - align = page_align; - *in_relro = false; - } - off = align_address(off, align); (*p)->set_address_and_file_offset(addr + (off - startoff), off); } @@ -2980,8 +3800,31 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset, { // The script may have inserted a skip forward, but it // better not have moved backward. - gold_assert((*p)->address() >= addr + (off - startoff)); - off += (*p)->address() - (addr + (off - startoff)); + if ((*p)->address() >= addr + (off - startoff)) + off += (*p)->address() - (addr + (off - startoff)); + else + { + if (!layout->script_options()->saw_sections_clause()) + gold_unreachable(); + else + { + Output_section* os = (*p)->output_section(); + + // Cast to unsigned long long to avoid format warnings. + unsigned long long previous_dot = + static_cast<unsigned long long>(addr + (off - startoff)); + unsigned long long dot = + static_cast<unsigned long long>((*p)->address()); + + if (os == NULL) + gold_error(_("dot moves backward in linker script " + "from 0x%llx to 0x%llx"), previous_dot, dot); + else + gold_error(_("address of section '%s' moves backward " + "from 0x%llx to 0x%llx"), + os->name(), previous_dot, dot); + } + } (*p)->set_file_offset(off); (*p)->finalize_data_size(); } @@ -3005,10 +3848,10 @@ Output_segment::set_section_list_addresses(const Layout* layout, bool reset, } // For a non-PT_LOAD segment, set the offset from the sections, if -// any. +// any. Add INCREASE to the file size and the memory size. void -Output_segment::set_offset() +Output_segment::set_offset(unsigned int increase) { gold_assert(this->type_ != elfcpp::PT_LOAD); @@ -3016,6 +3859,7 @@ Output_segment::set_offset() if (this->output_data_.empty() && this->output_bss_.empty()) { + gold_assert(increase == 0); this->vaddr_ = 0; this->paddr_ = 0; this->are_addresses_set_ = true; @@ -3057,6 +3901,9 @@ Output_segment::set_offset() + last->data_size() - this->vaddr_); + this->filesz_ += increase; + this->memsz_ += increase; + // If this is a TLS segment, align the memory size. The code in // set_section_list ensures that the section after the TLS segment // is aligned to give us room. @@ -3066,16 +3913,6 @@ Output_segment::set_offset() gold_assert(this->vaddr_ == align_address(this->vaddr_, segment_align)); this->memsz_ = align_address(this->memsz_, segment_align); } - - // If this is a RELRO segment, align the memory size. The code in - // set_section_list ensures that the section after the RELRO segment - // is aligned to give us room. - if (this->type_ == elfcpp::PT_GNU_RELRO) - { - uint64_t page_align = parameters->target().common_pagesize(); - gold_assert(this->vaddr_ == align_address(this->vaddr_, page_align)); - this->memsz_ = align_address(this->memsz_, page_align); - } } // Set the TLS offsets of the sections in the PT_TLS segment. @@ -3291,6 +4128,42 @@ Output_file::Output_file(const char* name) { } +// Try to open an existing file. Returns false if the file doesn't +// exist, has a size of 0 or can't be mmapped. + +bool +Output_file::open_for_modification() +{ + // The name "-" means "stdout". + if (strcmp(this->name_, "-") == 0) + return false; + + // Don't bother opening files with a size of zero. + struct stat s; + if (::stat(this->name_, &s) != 0 || s.st_size == 0) + return false; + + int o = open_descriptor(-1, this->name_, O_RDWR, 0); + if (o < 0) + gold_fatal(_("%s: open: %s"), this->name_, strerror(errno)); + this->o_ = o; + this->file_size_ = s.st_size; + + // If the file can't be mmapped, copying the content to an anonymous + // map will probably negate the performance benefits of incremental + // linking. This could be helped by using views and loading only + // the necessary parts, but this is not supported as of now. + if (!this->map_no_anonymous()) + { + release_descriptor(o, true); + this->o_ = -1; + this->file_size_ = 0; + return false; + } + + return true; +} + // Open the output file. void @@ -3319,8 +4192,22 @@ Output_file::open(off_t file_size) else { struct stat s; - if (::stat(this->name_, &s) == 0 && s.st_size != 0) - unlink_if_ordinary(this->name_); + if (::stat(this->name_, &s) == 0 + && (S_ISREG (s.st_mode) || S_ISLNK (s.st_mode))) + { + if (s.st_size != 0) + ::unlink(this->name_); + else if (!parameters->options().relocatable()) + { + // If we don't unlink the existing file, add execute + // permission where read permissions already exist + // and where the umask permits. + int mask = ::umask(0); + ::umask(mask); + s.st_mode |= (s.st_mode & 0444) >> 2; + ::chmod(this->name_, s.st_mode & ~mask); + } + } int mode = parameters->options().relocatable() ? 0666 : 0777; int o = open_descriptor(-1, this->name_, O_RDWR | O_CREAT | O_TRUNC, @@ -3355,14 +4242,32 @@ Output_file::resize(off_t file_size) { this->unmap(); this->file_size_ = file_size; - this->map(); + if (!this->map_no_anonymous()) + gold_fatal(_("%s: mmap: %s"), this->name_, strerror(errno)); } } -// Map the file into memory. +// Map an anonymous block of memory which will later be written to the +// file. Return whether the map succeeded. -void -Output_file::map() +bool +Output_file::map_anonymous() +{ + void* base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (base != MAP_FAILED) + { + this->map_is_anonymous_ = true; + this->base_ = static_cast<unsigned char*>(base); + return true; + } + return false; +} + +// Map the file into memory. Return whether the mapping succeeded. + +bool +Output_file::map_no_anonymous() { const int o = this->o_; @@ -3375,28 +4280,52 @@ Output_file::map() || ::fstat(o, &statbuf) != 0 || !S_ISREG(statbuf.st_mode) || this->is_temporary_) - { - this->map_is_anonymous_ = true; - base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - } - else - { - // Write out one byte to make the file the right size. - if (::lseek(o, this->file_size_ - 1, SEEK_SET) < 0) - gold_fatal(_("%s: lseek: %s"), this->name_, strerror(errno)); - char b = 0; - if (::write(o, &b, 1) != 1) - gold_fatal(_("%s: write: %s"), this->name_, strerror(errno)); + return false; - // Map the file into memory. - this->map_is_anonymous_ = false; - base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE, - MAP_SHARED, o, 0); - } + // Ensure that we have disk space available for the file. If we + // don't do this, it is possible that we will call munmap, close, + // and exit with dirty buffers still in the cache with no assigned + // disk blocks. If the disk is out of space at that point, the + // output file will wind up incomplete, but we will have already + // exited. The alternative to fallocate would be to use fdatasync, + // but that would be a more significant performance hit. + if (::posix_fallocate(o, 0, this->file_size_) < 0) + gold_fatal(_("%s: %s"), this->name_, strerror(errno)); + + // Map the file into memory. + base = ::mmap(NULL, this->file_size_, PROT_READ | PROT_WRITE, + MAP_SHARED, o, 0); + + // The mmap call might fail because of file system issues: the file + // system might not support mmap at all, or it might not support + // mmap with PROT_WRITE. if (base == MAP_FAILED) - gold_fatal(_("%s: mmap: %s"), this->name_, strerror(errno)); + return false; + + this->map_is_anonymous_ = false; this->base_ = static_cast<unsigned char*>(base); + return true; +} + +// Map the file into memory. + +void +Output_file::map() +{ + if (this->map_no_anonymous()) + return; + + // The mmap call might fail because of file system issues: the file + // system might not support mmap at all, or it might not support + // mmap with PROT_WRITE. I'm not sure which errno values we will + // see in all cases, so if the mmap fails for any reason and we + // don't care about file contents, try for an anonymous map. + if (this->map_anonymous()) + return; + + gold_fatal(_("%s: mmap: failed to allocate %lu bytes for output file: %s"), + this->name_, static_cast<unsigned long>(this->file_size_), + strerror(errno)); } // Unmap the file from memory. @@ -3418,15 +4347,20 @@ Output_file::close() if (this->map_is_anonymous_ && !this->is_temporary_) { size_t bytes_to_write = this->file_size_; + size_t offset = 0; while (bytes_to_write > 0) { - ssize_t bytes_written = ::write(this->o_, this->base_, bytes_to_write); + ssize_t bytes_written = ::write(this->o_, this->base_ + offset, + bytes_to_write); if (bytes_written == 0) gold_error(_("%s: write: unexpected 0 return-value"), this->name_); else if (bytes_written < 0) gold_error(_("%s: write: %s"), this->name_, strerror(errno)); else - bytes_to_write -= bytes_written; + { + bytes_to_write -= bytes_written; + offset += bytes_written; + } } } this->unmap(); @@ -3493,6 +4427,86 @@ Output_section::add_input_section<64, true>( #ifdef HAVE_TARGET_32_LITTLE template +class Output_reloc<elfcpp::SHT_REL, false, 32, false>; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +class Output_reloc<elfcpp::SHT_REL, false, 32, true>; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +class Output_reloc<elfcpp::SHT_REL, false, 64, false>; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +class Output_reloc<elfcpp::SHT_REL, false, 64, true>; +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +class Output_reloc<elfcpp::SHT_REL, true, 32, false>; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +class Output_reloc<elfcpp::SHT_REL, true, 32, true>; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +class Output_reloc<elfcpp::SHT_REL, true, 64, false>; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +class Output_reloc<elfcpp::SHT_REL, true, 64, true>; +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +class Output_reloc<elfcpp::SHT_RELA, false, 32, false>; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +class Output_reloc<elfcpp::SHT_RELA, false, 32, true>; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +class Output_reloc<elfcpp::SHT_RELA, false, 64, false>; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +class Output_reloc<elfcpp::SHT_RELA, false, 64, true>; +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +class Output_reloc<elfcpp::SHT_RELA, true, 32, false>; +#endif + +#ifdef HAVE_TARGET_32_BIG +template +class Output_reloc<elfcpp::SHT_RELA, true, 32, true>; +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +class Output_reloc<elfcpp::SHT_RELA, true, 64, false>; +#endif + +#ifdef HAVE_TARGET_64_BIG +template +class Output_reloc<elfcpp::SHT_RELA, true, 64, true>; +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template class Output_data_reloc<elfcpp::SHT_REL, false, 32, false>; #endif diff --git a/binutils-2.19/gold/output.h b/binutils-2.19/gold/output.h index 1c95881..8088565 100644 --- a/binutils-2.19/gold/output.h +++ b/binutils-2.19/gold/output.h @@ -1,6 +1,6 @@ // output.h -- manage the output file for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -38,6 +38,7 @@ class General_options; class Object; class Symbol; class Output_file; +class Output_merge_base; class Output_section; class Relocatable_relocs; class Target; @@ -54,7 +55,7 @@ class Output_data explicit Output_data() : address_(0), data_size_(0), offset_(-1), is_address_valid_(false), is_data_size_valid_(false), - is_offset_valid_(false), + is_offset_valid_(false), is_data_size_fixed_(false), dynamic_reloc_count_(0) { } @@ -80,6 +81,11 @@ class Output_data return this->data_size_; } + // Return true if data size is fixed. + bool + is_data_size_fixed() const + { return this->is_data_size_fixed_; } + // Return the file offset. This is only valid after // Layout::finalize is finished. For some non-allocated sections, // it may not be valid until near the end of the link. @@ -97,10 +103,17 @@ class Output_data { this->is_address_valid_ = false; this->is_offset_valid_ = false; - this->is_data_size_valid_ = false; + if (!this->is_data_size_fixed_) + this->is_data_size_valid_ = false; this->do_reset_address_and_file_offset(); } + // Return true if address and file offset already have reset values. In + // other words, calling reset_address_and_file_offset will not change them. + bool + address_and_file_offset_have_reset_values() const + { return this->do_address_and_file_offset_have_reset_values(); } + // Return the required alignment. uint64_t addralign() const @@ -137,6 +150,10 @@ class Output_data output_section() { return this->do_output_section(); } + const Output_section* + output_section() const + { return this->do_output_section(); } + // Return the output section index, if there is an output section. unsigned int out_shndx() const @@ -289,6 +306,10 @@ class Output_data do_output_section() { return NULL; } + virtual const Output_section* + do_output_section() const + { return NULL; } + // Return the output section index, if there is an output section. virtual unsigned int do_out_shndx() const @@ -311,6 +332,14 @@ class Output_data do_reset_address_and_file_offset() { } + // Return true if address and file offset already have reset values. In + // other words, calling reset_address_and_file_offset will not change them. + // A child class overriding do_reset_address_and_file_offset may need to + // also override this. + virtual bool + do_address_and_file_offset_have_reset_values() const + { return !this->is_address_valid_ && !this->is_offset_valid_; } + // Set the TLS offset. Called only for SHT_TLS sections. virtual void do_set_tls_offset(uint64_t) @@ -330,15 +359,32 @@ class Output_data // Functions that child classes may call. + // Reset the address. The Output_section class needs this when an + // SHF_ALLOC input section is added to an output section which was + // formerly not SHF_ALLOC. + void + mark_address_invalid() + { this->is_address_valid_ = false; } + // Set the size of the data. void set_data_size(off_t data_size) { - gold_assert(!this->is_data_size_valid_); + gold_assert(!this->is_data_size_valid_ + && !this->is_data_size_fixed_); this->data_size_ = data_size; this->is_data_size_valid_ = true; } + // Fix the data size. Once it is fixed, it cannot be changed + // and the data size remains always valid. + void + fix_data_size() + { + gold_assert(this->is_data_size_valid_); + this->is_data_size_fixed_ = true; + } + // Get the current data size--this is for the convenience of // sections which build up their size over time. off_t @@ -383,6 +429,8 @@ class Output_data bool is_data_size_valid_; // Whether offset_ is valid. bool is_offset_valid_; + // Whether data size is fixed. + bool is_data_size_fixed_; // Count of dynamic relocations applied to this section. unsigned int dynamic_reloc_count_; }; @@ -414,12 +462,21 @@ class Output_section_headers : public Output_data do_print_to_mapfile(Mapfile* mapfile) const { mapfile->print_output_data(this, _("** section headers")); } + // Set final data size. + void + set_final_data_size() + { this->set_data_size(this->do_size()); } + private: // Write the data to the file with the right size and endianness. template<int size, bool big_endian> void do_sized_write(Output_file*); + // Compute data size. + off_t + do_size() const; + const Layout* layout_; const Layout::Segment_list* segment_list_; const Layout::Section_list* section_list_; @@ -450,12 +507,21 @@ class Output_segment_headers : public Output_data do_print_to_mapfile(Mapfile* mapfile) const { mapfile->print_output_data(this, _("** segment headers")); } + // Set final data size. + void + set_final_data_size() + { this->set_data_size(this->do_size()); } + private: // Write the data to the file with the right size and endianness. template<int size, bool big_endian> void do_sized_write(Output_file*); + // Compute the current size. + off_t + do_size() const; + const Layout::Segment_list& segment_list_; }; @@ -489,6 +555,11 @@ class Output_file_header : public Output_data do_print_to_mapfile(Mapfile* mapfile) const { mapfile->print_output_data(this, _("** file header")); } + // Set final data size. + void + set_final_data_size(void) + { this->set_data_size(this->do_size()); } + private: // Write the data to the file with the right size and endianness. template<int size, bool big_endian> @@ -500,6 +571,10 @@ class Output_file_header : public Output_data typename elfcpp::Elf_types<size>::Elf_Addr entry(); + // Compute the current data size. + off_t + do_size() const; + const Target* target_; const Symbol_table* symtab_; const Output_segment_headers* segment_header_; @@ -516,9 +591,14 @@ class Output_file_header : public Output_data class Output_section_data : public Output_data { public: - Output_section_data(off_t data_size, uint64_t addralign) + Output_section_data(off_t data_size, uint64_t addralign, + bool is_data_size_fixed) : Output_data(), output_section_(NULL), addralign_(addralign) - { this->set_data_size(data_size); } + { + this->set_data_size(data_size); + if (is_data_size_fixed) + this->fix_data_size(); + } Output_section_data(uint64_t addralign) : Output_data(), output_section_(NULL), addralign_(addralign) @@ -618,6 +698,10 @@ class Output_section_data : public Output_data do_output_section() { return this->output_section_; } + const Output_section* + do_output_section() const + { return this->output_section_; } + // Return the section index of the output section. unsigned int do_out_shndx() const; @@ -668,15 +752,15 @@ class Output_data_const : public Output_section_data { public: Output_data_const(const std::string& data, uint64_t addralign) - : Output_section_data(data.size(), addralign), data_(data) + : Output_section_data(data.size(), addralign, true), data_(data) { } Output_data_const(const char* p, off_t len, uint64_t addralign) - : Output_section_data(len, addralign), data_(p, len) + : Output_section_data(len, addralign, true), data_(p, len) { } Output_data_const(const unsigned char* p, off_t len, uint64_t addralign) - : Output_section_data(len, addralign), + : Output_section_data(len, addralign, true), data_(reinterpret_cast<const char*>(p), len) { } @@ -707,7 +791,7 @@ class Output_data_const_buffer : public Output_section_data public: Output_data_const_buffer(const unsigned char* p, off_t len, uint64_t addralign, const char* map_name) - : Output_section_data(len, addralign), + : Output_section_data(len, addralign, true), p_(p), map_name_(map_name) { } @@ -742,7 +826,7 @@ class Output_data_fixed_space : public Output_section_data public: Output_data_fixed_space(off_t data_size, uint64_t addralign, const char* map_name) - : Output_section_data(data_size, addralign), + : Output_section_data(data_size, addralign, true), map_name_(map_name) { } @@ -805,7 +889,7 @@ class Output_data_zero_fill : public Output_section_data { public: Output_data_zero_fill(off_t data_size, uint64_t addralign) - : Output_section_data(data_size, addralign) + : Output_section_data(data_size, addralign, true) { } protected: @@ -874,6 +958,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> typedef typename elfcpp::Elf_types<size>::Elf_Addr Address; typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend; + static const Address invalid_address = static_cast<Address>(0) - 1; + // An uninitialized entry. We need this because we want to put // instances of this class into an STL container. Output_reloc() @@ -888,23 +974,24 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> // A reloc against a global symbol. Output_reloc(Symbol* gsym, unsigned int type, Output_data* od, - Address address, bool is_relative); + Address address, bool is_relative, bool is_symbolless); Output_reloc(Symbol* gsym, unsigned int type, Sized_relobj<size, big_endian>* relobj, - unsigned int shndx, Address address, bool is_relative); + unsigned int shndx, Address address, bool is_relative, + bool is_symbolless); // A reloc against a local symbol or local section symbol. Output_reloc(Sized_relobj<size, big_endian>* relobj, unsigned int local_sym_index, unsigned int type, Output_data* od, Address address, bool is_relative, - bool is_section_symbol); + bool is_symbolless, bool is_section_symbol); Output_reloc(Sized_relobj<size, big_endian>* relobj, unsigned int local_sym_index, unsigned int type, unsigned int shndx, Address address, bool is_relative, - bool is_section_symbol); + bool is_symbolless, bool is_section_symbol); // A reloc against the STT_SECTION symbol of an output section. @@ -915,11 +1002,40 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address); - // Return TRUE if this is a RELATIVE relocation. + // An absolute relocation with no symbol. + + Output_reloc(unsigned int type, Output_data* od, Address address); + + Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address); + + // A target specific relocation. The target will be called to get + // the symbol index, passing ARG. The type and offset will be set + // as for other relocation types. + + Output_reloc(unsigned int type, void* arg, Output_data* od, + Address address); + + Output_reloc(unsigned int type, void* arg, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address); + + // Return the reloc type. + unsigned int + type() const + { return this->type_; } + + // Return whether this is a RELATIVE relocation. bool is_relative() const { return this->is_relative_; } + // Return whether this is a relocation which should not use + // a symbol, but which obtains its addend from a symbol. + bool + is_symbolless() const + { return this->is_symbolless_; } + // Return whether this is against a local section symbol. bool is_local_section_symbol() const @@ -927,9 +1043,24 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> return (this->local_sym_index_ != GSYM_CODE && this->local_sym_index_ != SECTION_CODE && this->local_sym_index_ != INVALID_CODE + && this->local_sym_index_ != TARGET_CODE && this->is_section_symbol_); } + // Return whether this is a target specific relocation. + bool + is_target_specific() const + { return this->local_sym_index_ == TARGET_CODE; } + + // Return the argument to pass to the target for a target specific + // relocation. + void* + target_arg() const + { + gold_assert(this->local_sym_index_ == TARGET_CODE); + return this->u1_.arg; + } + // For a local section symbol, return the offset of the input // section within the output section. ADDEND is the addend being // applied to the input section. @@ -982,8 +1113,10 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> GSYM_CODE = -1U, // Output section. SECTION_CODE = -2U, + // Target specific. + TARGET_CODE = -3U, // Invalid uninitialized entry. - INVALID_CODE = -3U + INVALID_CODE = -4U }; union @@ -1001,6 +1134,9 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> // For a relocation against an output section // (this->local_sym_index_ == SECTION_CODE), the output section. Output_section* os; + // For a target specific relocation, an argument to pass to the + // target. + void* arg; } u1_; union { @@ -1015,16 +1151,20 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> // The address offset within the input section or the Output_data. Address address_; // This is GSYM_CODE for a global symbol, or SECTION_CODE for a - // relocation against an output section, or INVALID_CODE for an - // uninitialized value. Otherwise, for a local symbol - // (this->is_section_symbol_ is false), the local symbol index. For - // a local section symbol (this->is_section_symbol_ is true), the - // section index in the input file. + // relocation against an output section, or TARGET_CODE for a target + // specific relocation, or INVALID_CODE for an uninitialized value. + // Otherwise, for a local symbol (this->is_section_symbol_ is + // false), the local symbol index. For a local section symbol + // (this->is_section_symbol_ is true), the section index in the + // input file. unsigned int local_sym_index_; // The reloc type--a processor specific code. - unsigned int type_ : 30; + unsigned int type_ : 29; // True if the relocation is a RELATIVE relocation. bool is_relative_ : 1; + // True if the relocation is one which should not use + // a symbol, but which obtains its addend from a symbol. + bool is_symbolless_ : 1; // True if the relocation is against a section symbol. bool is_section_symbol_ : 1; // If the reloc address is an input section in an object, the @@ -1051,15 +1191,18 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> // A reloc against a global symbol. Output_reloc(Symbol* gsym, unsigned int type, Output_data* od, - Address address, Addend addend, bool is_relative) - : rel_(gsym, type, od, address, is_relative), addend_(addend) + Address address, Addend addend, bool is_relative, + bool is_symbolless) + : rel_(gsym, type, od, address, is_relative, is_symbolless), + addend_(addend) { } Output_reloc(Symbol* gsym, unsigned int type, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, Addend addend, - bool is_relative) - : rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend) + bool is_relative, bool is_symbolless) + : rel_(gsym, type, relobj, shndx, address, is_relative, + is_symbolless), addend_(addend) { } // A reloc against a local symbol. @@ -1067,18 +1210,20 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Output_reloc(Sized_relobj<size, big_endian>* relobj, unsigned int local_sym_index, unsigned int type, Output_data* od, Address address, - Addend addend, bool is_relative, bool is_section_symbol) + Addend addend, bool is_relative, + bool is_symbolless, bool is_section_symbol) : rel_(relobj, local_sym_index, type, od, address, is_relative, - is_section_symbol), + is_symbolless, is_section_symbol), addend_(addend) { } Output_reloc(Sized_relobj<size, big_endian>* relobj, unsigned int local_sym_index, unsigned int type, unsigned int shndx, Address address, - Addend addend, bool is_relative, bool is_section_symbol) + Addend addend, bool is_relative, + bool is_symbolless, bool is_section_symbol) : rel_(relobj, local_sym_index, type, shndx, address, is_relative, - is_section_symbol), + is_symbolless, is_section_symbol), addend_(addend) { } @@ -1095,6 +1240,44 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> : rel_(os, type, relobj, shndx, address), addend_(addend) { } + // An absolute relocation with no symbol. + + Output_reloc(unsigned int type, Output_data* od, Address address, + Addend addend) + : rel_(type, od, address), addend_(addend) + { } + + Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address, Addend addend) + : rel_(type, relobj, shndx, address), addend_(addend) + { } + + // A target specific relocation. The target will be called to get + // the symbol index and the addend, passing ARG. The type and + // offset will be set as for other relocation types. + + Output_reloc(unsigned int type, void* arg, Output_data* od, + Address address, Addend addend) + : rel_(type, arg, od, address), addend_(addend) + { } + + Output_reloc(unsigned int type, void* arg, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address, Addend addend) + : rel_(type, arg, relobj, shndx, address), addend_(addend) + { } + + // Return whether this is a RELATIVE relocation. + bool + is_relative() const + { return this->rel_.is_relative(); } + + // Return whether this is a relocation which should not use + // a symbol, but which obtains its addend from a symbol. + bool + is_symbolless() const + { return this->rel_.is_symbolless(); } + // Write the reloc entry to an output view. void write(unsigned char* pov) const; @@ -1121,6 +1304,43 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Addend addend_; }; +// Output_data_reloc_generic is a non-template base class for +// Output_data_reloc_base. This gives the generic code a way to hold +// a pointer to a reloc section. + +class Output_data_reloc_generic : public Output_section_data_build +{ + public: + Output_data_reloc_generic(int size, bool sort_relocs) + : Output_section_data_build(Output_data::default_alignment_for_size(size)), + relative_reloc_count_(0), sort_relocs_(sort_relocs) + { } + + // Return the number of relative relocs in this section. + size_t + relative_reloc_count() const + { return this->relative_reloc_count_; } + + // Whether we should sort the relocs. + bool + sort_relocs() const + { return this->sort_relocs_; } + + protected: + // Note that we've added another relative reloc. + void + bump_relative_reloc_count() + { ++this->relative_reloc_count_; } + + private: + // The number of relative relocs added to this section. This is to + // support DT_RELCOUNT. + size_t relative_reloc_count_; + // Whether to sort the relocations when writing them out, to make + // the dynamic linker more efficient. + bool sort_relocs_; +}; + // Output_data_reloc is used to manage a section containing relocs. // SH_TYPE is either elfcpp::SHT_REL or elfcpp::SHT_RELA. DYNAMIC // indicates whether this is a dynamic relocation or a normal @@ -1129,7 +1349,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> // the reloc type. template<int sh_type, bool dynamic, int size, bool big_endian> -class Output_data_reloc_base : public Output_section_data_build +class Output_data_reloc_base : public Output_data_reloc_generic { public: typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type; @@ -1139,8 +1359,7 @@ class Output_data_reloc_base : public Output_section_data_build // Construct the section. Output_data_reloc_base(bool sort_relocs) - : Output_section_data_build(Output_data::default_alignment_for_size(size)), - sort_relocs_(sort_relocs) + : Output_data_reloc_generic(size, sort_relocs) { } protected: @@ -1169,6 +1388,8 @@ class Output_data_reloc_base : public Output_section_data_build this->relocs_.push_back(reloc); this->set_current_data_size(this->relocs_.size() * reloc_size); od->add_dynamic_reloc(); + if (reloc.is_relative()) + this->bump_relative_reloc_count(); } private: @@ -1184,9 +1405,6 @@ class Output_data_reloc_base : public Output_section_data_build // The relocations in this section. Relocs relocs_; - // Whether to sort the relocations when writing them out, to make - // the dynamic linker more efficient. - bool sort_relocs_; }; // The class which callers actually create. @@ -1216,14 +1434,14 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> void add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, false)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, false, false)); } void add_global(Symbol* gsym, unsigned int type, Output_data* od, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - false)); } + false, false)); } // These are to simplify the Copy_relocs class. @@ -1250,7 +1468,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, Address address) - { this->add(od, Output_reloc_type(gsym, type, od, address, true)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, true, true)); } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, @@ -1258,7 +1476,25 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> unsigned int shndx, Address address) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - true)); + true, true)); + } + + // Add a global relocation which does not use a symbol for the relocation, + // but which gets its addend from a symbol. + + void + add_symbolless_global_addend(Symbol* gsym, unsigned int type, + Output_data* od, Address address) + { this->add(od, Output_reloc_type(gsym, type, od, address, false, true)); } + + void + add_symbolless_global_addend(Symbol* gsym, unsigned int type, + Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address) + { + this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + false, true)); } // Add a reloc against a local symbol. @@ -1269,7 +1505,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, false, false)); + address, false, false, false)); } void @@ -1278,7 +1514,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, false, false)); + address, false, false, false)); } // Add a RELATIVE reloc against a local symbol. @@ -1289,7 +1525,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, - address, true, false)); + address, true, true, false)); } void @@ -1298,7 +1534,29 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, true, false)); + address, true, true, false)); + } + + // Add a local relocation which does not use a symbol for the relocation, + // but which gets its addend from a symbol. + + void + add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj, + unsigned int local_sym_index, unsigned int type, + Output_data* od, Address address) + { + this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, + address, false, true, false)); + } + + void + add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj, + unsigned int local_sym_index, unsigned int type, + Output_data* od, unsigned int shndx, + Address address) + { + this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, + address, false, true, false)); } // Add a reloc against a local section symbol. This will be @@ -1311,7 +1569,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, - address, false, true)); + address, false, false, true)); } void @@ -1320,7 +1578,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Output_data* od, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, false, true)); + address, false, false, true)); } // A reloc against the STT_SECTION symbol of an output section. @@ -1337,6 +1595,32 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address) { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); } + + // Add an absolute relocation. + + void + add_absolute(unsigned int type, Output_data* od, Address address) + { this->add(od, Output_reloc_type(type, od, address)); } + + void + add_absolute(unsigned int type, Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address) + { this->add(od, Output_reloc_type(type, relobj, shndx, address)); } + + // Add a target specific relocation. A target which calls this must + // define the reloc_symbol_index and reloc_addend virtual functions. + + void + add_target_specific(unsigned int type, void* arg, Output_data* od, + Address address) + { this->add(od, Output_reloc_type(type, arg, od, address)); } + + void + add_target_specific(unsigned int type, void* arg, Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address) + { this->add(od, Output_reloc_type(type, arg, relobj, shndx, address)); } }; // The SHT_RELA version of Output_data_reloc. @@ -1364,7 +1648,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, od, address, addend, - false)); } + false, false)); } void add_global(Symbol* gsym, unsigned int type, Output_data* od, @@ -1372,7 +1656,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> unsigned int shndx, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, false)); } + addend, false, false)); } // Add a RELATIVE reloc against a global symbol. The final output // relocation will not reference the symbol, but we must keep the symbol @@ -1382,14 +1666,32 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, Address address, Addend addend) - { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true)); } + { this->add(od, Output_reloc_type(gsym, type, od, address, addend, true, + true)); } void add_global_relative(Symbol* gsym, unsigned int type, Output_data* od, Sized_relobj<size, big_endian>* relobj, unsigned int shndx, Address address, Addend addend) { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, - addend, true)); } + addend, true, true)); } + + // Add a global relocation which does not use a symbol for the relocation, + // but which gets its addend from a symbol. + + void + add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od, + Address address, Addend addend) + { this->add(od, Output_reloc_type(gsym, type, od, address, addend, + false, true)); } + + void + add_symbolless_global_addend(Symbol* gsym, unsigned int type, + Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address, Addend addend) + { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address, + addend, false, true)); } // Add a reloc against a local symbol. @@ -1399,7 +1701,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, - addend, false, false)); + addend, false, false, false)); } void @@ -1409,7 +1711,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, false, false)); + address, addend, false, false, false)); } // Add a RELATIVE reloc against a local symbol. @@ -1420,7 +1722,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, - addend, true, false)); + addend, true, true, false)); } void @@ -1430,7 +1732,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Addend addend) { this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, - address, addend, true, false)); + address, addend, true, true, false)); + } + + // Add a local relocation which does not use a symbol for the relocation, + // but which gets it's addend from a symbol. + + void + add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj, + unsigned int local_sym_index, unsigned int type, + Output_data* od, Address address, Addend addend) + { + this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address, + addend, false, true, false)); + } + + void + add_symbolless_local_addend(Sized_relobj<size, big_endian>* relobj, + unsigned int local_sym_index, unsigned int type, + Output_data* od, unsigned int shndx, + Address address, Addend addend) + { + this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx, + address, addend, false, true, false)); } // Add a reloc against a local section symbol. This will be @@ -1443,7 +1767,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Output_data* od, Address address, Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address, - addend, false, true)); + addend, false, false, true)); } void @@ -1453,7 +1777,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> Addend addend) { this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx, - address, addend, false, true)); + address, addend, false, false, true)); } // A reloc against the STT_SECTION symbol of an output section. @@ -1469,6 +1793,36 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian> unsigned int shndx, Address address, Addend addend) { this->add(os, Output_reloc_type(os, type, relobj, shndx, address, addend)); } + + // Add an absolute relocation. + + void + add_absolute(unsigned int type, Output_data* od, Address address, + Addend addend) + { this->add(od, Output_reloc_type(type, od, address, addend)); } + + void + add_absolute(unsigned int type, Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address, Addend addend) + { this->add(od, Output_reloc_type(type, relobj, shndx, address, addend)); } + + // Add a target specific relocation. A target which calls this must + // define the reloc_symbol_index and reloc_addend virtual functions. + + void + add_target_specific(unsigned int type, void* arg, Output_data* od, + Address address, Addend addend) + { this->add(od, Output_reloc_type(type, arg, od, address, addend)); } + + void + add_target_specific(unsigned int type, void* arg, Output_data* od, + Sized_relobj<size, big_endian>* relobj, + unsigned int shndx, Address address, Addend addend) + { + this->add(od, Output_reloc_type(type, arg, relobj, shndx, address, + addend)); + } }; // Output_relocatable_relocs represents a relocation section in a @@ -1522,6 +1876,11 @@ class Output_data_group : public Output_section_data do_print_to_mapfile(Mapfile* mapfile) const { mapfile->print_output_data(this, _("** group")); } + // Set final data size. + void + set_final_data_size() + { this->set_data_size((this->input_shndxes_.size() + 1) * 4); } + private: // The input object. Sized_relobj<size, big_endian>* relobj_; @@ -1739,6 +2098,12 @@ class Output_data_dynamic : public Output_section_data add_section_size(elfcpp::DT tag, const Output_data* od) { this->add_entry(Dynamic_entry(tag, od, true)); } + // Add a new dynamic entry with the total size of two output datas. + void + add_section_size(elfcpp::DT tag, const Output_data* od, + const Output_data* od2) + { this->add_entry(Dynamic_entry(tag, od, od2)); } + // Add a new dynamic entry with the address of a symbol. void add_symbol(elfcpp::DT tag, const Symbol* sym) @@ -1787,7 +2152,19 @@ class Output_data_dynamic : public Output_section_data offset_(section_size ? DYNAMIC_SECTION_SIZE : DYNAMIC_SECTION_ADDRESS) - { this->u_.od = od; } + { + this->u_.od = od; + this->od2 = NULL; + } + + // Create an entry with the size of two sections. + Dynamic_entry(elfcpp::DT tag, const Output_data* od, const Output_data* od2) + : tag_(tag), + offset_(DYNAMIC_SECTION_SIZE) + { + this->u_.od = od; + this->od2 = od2; + } // Create an entry with the address of a section plus a constant offset. Dynamic_entry(elfcpp::DT tag, const Output_data* od, unsigned int offset) @@ -1805,6 +2182,11 @@ class Output_data_dynamic : public Output_section_data : tag_(tag), offset_(DYNAMIC_STRING) { this->u_.str = str; } + // Return the tag of this entry. + elfcpp::DT + tag() const + { return this->tag_; } + // Write the dynamic entry to an output view. template<int size, bool big_endian> void @@ -1838,6 +2220,8 @@ class Output_data_dynamic : public Output_section_data // For DYNAMIC_STRING. const char* str; } u_; + // For DYNAMIC_SYMBOL with two sections. + const Output_data* od2; // The dynamic tag. elfcpp::DT tag_; // The type of entry (Classification) or offset within a section. @@ -1871,7 +2255,7 @@ class Output_symtab_xindex : public Output_section_data { public: Output_symtab_xindex(size_t symcount) - : Output_section_data(symcount * 4, 4), + : Output_section_data(symcount * 4, 4, true), entries_() { } @@ -1903,6 +2287,33 @@ class Output_symtab_xindex : public Output_section_data Xindex_entries entries_; }; +// A relaxed input section. +class Output_relaxed_input_section : public Output_section_data_build +{ + public: + // We would like to call relobj->section_addralign(shndx) to get the + // alignment but we do not want the constructor to fail. So callers + // are repsonsible for ensuring that. + Output_relaxed_input_section(Relobj* relobj, unsigned int shndx, + uint64_t addralign) + : Output_section_data_build(addralign), relobj_(relobj), shndx_(shndx) + { } + + // Return the Relobj of this relaxed input section. + Relobj* + relobj() const + { return this->relobj_; } + + // Return the section index of this relaxed input section. + unsigned int + shndx() const + { return this->shndx_; } + + private: + Relobj* relobj_; + unsigned int shndx_; +}; + // An output section. We don't expect to have too many output // sections, so we don't bother to do a template on the size. @@ -1915,7 +2326,7 @@ class Output_section : public Output_data // Add a new input section SHNDX, named NAME, with header SHDR, from // object OBJECT. RELOC_SHNDX is the index of a relocation section - // which applies to this section, or 0 if none, or -1U if more than + // which applies to this section, or 0 if none, or -1 if more than // one. HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause // in a linker script; in that case we need to keep track of input // sections associated with an output section. Return the offset @@ -1931,6 +2342,10 @@ class Output_section : public Output_data void add_output_section_data(Output_section_data* posd); + // Add a relaxed input section PORIS to this output section. + void + add_relaxed_input_section(Output_relaxed_input_section* poris); + // Return the section name. const char* name() const @@ -1946,22 +2361,9 @@ class Output_section : public Output_data flags() const { return this->flags_; } - // Set the section flags. This may only be used with the Layout - // code when it is prepared to move the section to a different - // segment. - void - set_flags(elfcpp::Elf_Xword flags) - { this->flags_ = flags; } - // Update the output section flags based on input section flags. void - update_flags_for_input_section(elfcpp::Elf_Xword flags) - { - this->flags_ |= (flags - & (elfcpp::SHF_WRITE - | elfcpp::SHF_ALLOC - | elfcpp::SHF_EXECINSTR)); - } + update_flags_for_input_section(elfcpp::Elf_Xword flags); // Return the entsize field. uint64_t @@ -2193,6 +2595,83 @@ class Output_section : public Output_data set_is_relro_local() { this->is_relro_local_ = true; } + // True if this must be the last relro section. + bool + is_last_relro() const + { return this->is_last_relro_; } + + // Record that this must be the last relro section. + void + set_is_last_relro() + { + gold_assert(this->is_relro_); + this->is_last_relro_ = true; + } + + // True if this must be the first section following the relro sections. + bool + is_first_non_relro() const + { + gold_assert(!this->is_relro_); + return this->is_first_non_relro_; + } + + // Record that this must be the first non-relro section. + void + set_is_first_non_relro() + { + gold_assert(!this->is_relro_); + this->is_first_non_relro_ = true; + } + + // True if this is a small section: a section which holds small + // variables. + bool + is_small_section() const + { return this->is_small_section_; } + + // Record that this is a small section. + void + set_is_small_section() + { this->is_small_section_ = true; } + + // True if this is a large section: a section which holds large + // variables. + bool + is_large_section() const + { return this->is_large_section_; } + + // Record that this is a large section. + void + set_is_large_section() + { this->is_large_section_ = true; } + + // True if this is a large data (not BSS) section. + bool + is_large_data_section() + { return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; } + + // True if this is the .interp section which goes into the PT_INTERP + // segment. + bool + is_interp() const + { return this->is_interp_; } + + // Record that this is the interp section. + void + set_is_interp() + { this->is_interp_ = true; } + + // True if this is a section used by the dynamic linker. + bool + is_dynamic_linker_section() const + { return this->is_dynamic_linker_section_; } + + // Record that this is a section used by the dynamic linker. + void + set_is_dynamic_linker_section() + { this->is_dynamic_linker_section_ = true; } + // Return whether this section should be written after all the input // sections are complete. bool @@ -2258,12 +2737,14 @@ class Output_section : public Output_data output_address(const Relobj* object, unsigned int shndx, off_t offset) const; - // Return the output address of the start of the merged section for - // input section SHNDX in object OBJECT. This is not necessarily - // the offset corresponding to input offset 0 in the section, since - // the section may be mapped arbitrarily. - uint64_t - starting_output_address(const Relobj* object, unsigned int shndx) const; + // Look for the merged section for input section SHNDX in object + // OBJECT. If found, return true, and set *ADDR to the address of + // the start of the merged section. This is not necessary the + // output offset corresponding to input offset 0 in the section, + // since the section may be mapped arbitrarily. + bool + find_starting_output_address(const Relobj* object, unsigned int shndx, + uint64_t* addr) const; // Record that this output section was found in the SECTIONS clause // of a linker script. @@ -2285,6 +2766,69 @@ class Output_section : public Output_data // The next few calls are for linker script support. + // We need to export the input sections to linker scripts. Previously + // we export a pair of Relobj pointer and section index. We now need to + // handle relaxed input sections as well. So we use this class. + class Simple_input_section + { + private: + static const unsigned int invalid_shndx = static_cast<unsigned int>(-1); + + public: + Simple_input_section(Relobj *relobj, unsigned int shndx) + : shndx_(shndx) + { + gold_assert(shndx != invalid_shndx); + this->u_.relobj = relobj; + } + + Simple_input_section(Output_relaxed_input_section* section) + : shndx_(invalid_shndx) + { this->u_.relaxed_input_section = section; } + + // Whether this is a relaxed section. + bool + is_relaxed_input_section() const + { return this->shndx_ == invalid_shndx; } + + // Return object of an input section. + Relobj* + relobj() const + { + return ((this->shndx_ != invalid_shndx) + ? this->u_.relobj + : this->u_.relaxed_input_section->relobj()); + } + + // Return index of an input section. + unsigned int + shndx() const + { + return ((this->shndx_ != invalid_shndx) + ? this->shndx_ + : this->u_.relaxed_input_section->shndx()); + } + + // Return the Output_relaxed_input_section object of a relaxed section. + Output_relaxed_input_section* + relaxed_input_section() const + { + gold_assert(this->shndx_ == invalid_shndx); + return this->u_.relaxed_input_section; + } + + private: + // Pointer to either an Relobj or an Output_relaxed_input_section. + union + { + Relobj* relobj; + Output_relaxed_input_section* relaxed_input_section; + } u_; + // Section index for an non-relaxed section or invalid_shndx for + // a relaxed section. + unsigned int shndx_; + }; + // Store the list of input sections for this Output_section into the // list passed in. This removes the input sections, leaving only // any Output_section_data elements. This returns the size of those @@ -2293,12 +2837,12 @@ class Output_section : public Output_data // any spaces between the remaining Output_section_data elements. uint64_t get_input_sections(uint64_t address, const std::string& fill, - std::list<std::pair<Relobj*, unsigned int > >*); + std::list<Simple_input_section>*); - // Add an input section from a script. + // Add a simple input section. void - add_input_section_for_script(Relobj* object, unsigned int shndx, - off_t data_size, uint64_t addralign); + add_simple_input_section(const Simple_input_section& input_section, + off_t data_size, uint64_t addralign); // Set the current size of the output section. void @@ -2312,6 +2856,54 @@ class Output_section : public Output_data // End of linker script support. + // Save states before doing section layout. + // This is used for relaxation. + void + save_states(); + + // Restore states prior to section layout. + void + restore_states(); + + // Discard states. + void + discard_states(); + + // Convert existing input sections to relaxed input sections. + void + convert_input_sections_to_relaxed_sections( + const std::vector<Output_relaxed_input_section*>& sections); + + // Find a relaxed input section to an input section in OBJECT + // with index SHNDX. Return NULL if none is found. + const Output_relaxed_input_section* + find_relaxed_input_section(const Relobj* object, unsigned int shndx) const; + + // Whether section offsets need adjustment due to relaxation. + bool + section_offsets_need_adjustment() const + { return this->section_offsets_need_adjustment_; } + + // Set section_offsets_need_adjustment to be true. + void + set_section_offsets_need_adjustment() + { this->section_offsets_need_adjustment_ = true; } + + // Adjust section offsets of input sections in this. This is + // requires if relaxation caused some input sections to change sizes. + void + adjust_section_offsets(); + + // Whether this is a NOLOAD section. + bool + is_noload() const + { return this->is_noload_; } + + // Set NOLOAD flag. + void + set_is_noload() + { this->is_noload_ = true; } + // Print merge statistics to stderr. void print_merge_stats(); @@ -2322,6 +2914,10 @@ class Output_section : public Output_data do_output_section() { return this; } + const Output_section* + do_output_section() const + { return this; } + // Return the section index in the output file. unsigned int do_out_shndx() const @@ -2349,6 +2945,11 @@ class Output_section : public Output_data void do_reset_address_and_file_offset(); + // Return true if address and file offset already have reset values. In + // other words, calling reset_address_and_file_offset will not change them. + bool + do_address_and_file_offset_have_reset_values() const; + // Write the data to the file. For a typical Output_section, this // does nothing: the data is written out by calling Object::Relocate // on each input object. But if there are any Output_section_data @@ -2422,7 +3023,6 @@ class Output_section : public Output_data void write_to_postprocessing_buffer(); - private: // In some cases we need to keep a list of the input sections // associated with this output section. We only need the list if we // might have to change the offsets of the input section within the @@ -2451,7 +3051,8 @@ class Output_section : public Output_data { gold_assert(shndx != OUTPUT_SECTION_CODE && shndx != MERGE_DATA_SECTION_CODE - && shndx != MERGE_STRING_SECTION_CODE); + && shndx != MERGE_STRING_SECTION_CODE + && shndx != RELAXED_INPUT_SECTION_CODE); this->u1_.data_size = data_size; this->u2_.object = object; } @@ -2475,6 +3076,14 @@ class Output_section : public Output_data this->u2_.posd = posd; } + // For a relaxed input section. + Input_section(Output_relaxed_input_section *psection) + : shndx_(RELAXED_INPUT_SECTION_CODE), p2align_(0) + { + this->u1_.data_size = 0; + this->u2_.poris = psection; + } + // The required alignment. uint64_t addralign() const @@ -2496,7 +3105,8 @@ class Output_section : public Output_data { return (this->shndx_ != OUTPUT_SECTION_CODE && this->shndx_ != MERGE_DATA_SECTION_CODE - && this->shndx_ != MERGE_STRING_SECTION_CODE); + && this->shndx_ != MERGE_STRING_SECTION_CODE + && this->shndx_ != RELAXED_INPUT_SECTION_CODE); } // Return whether this is a merge section which matches the @@ -2512,20 +3122,57 @@ class Output_section : public Output_data && this->addralign() == addralign); } + // Return whether this is a relaxed input section. + bool + is_relaxed_input_section() const + { return this->shndx_ == RELAXED_INPUT_SECTION_CODE; } + + // Return whether this is a generic Output_section_data. + bool + is_output_section_data() const + { + return this->shndx_ == OUTPUT_SECTION_CODE; + } + // Return the object for an input section. Relobj* relobj() const { - gold_assert(this->is_input_section()); - return this->u2_.object; + if (this->is_input_section()) + return this->u2_.object; + else if (this->is_relaxed_input_section()) + return this->u2_.poris->relobj(); + else + gold_unreachable(); } // Return the input section index for an input section. unsigned int shndx() const { - gold_assert(this->is_input_section()); - return this->shndx_; + if (this->is_input_section()) + return this->shndx_; + else if (this->is_relaxed_input_section()) + return this->u2_.poris->shndx(); + else + gold_unreachable(); + } + + // For non-input-sections, return the associated Output_section_data + // object. + Output_section_data* + output_section_data() const + { + gold_assert(!this->is_input_section()); + return this->u2_.posd; + } + + // Return the Output_relaxed_input_section object. + Output_relaxed_input_section* + relaxed_input_section() const + { + gold_assert(this->is_relaxed_input_section()); + return this->u2_.poris; } // Set the output section. @@ -2533,7 +3180,9 @@ class Output_section : public Output_data set_output_section(Output_section* os) { gold_assert(!this->is_input_section()); - this->u2_.posd->set_output_section(os); + Output_section_data *posd = + this->is_relaxed_input_section() ? this->u2_.poris : this->u2_.posd; + posd->set_output_section(os); } // Set the address and file offset. This is called during @@ -2611,7 +3260,9 @@ class Output_section : public Output_data MERGE_DATA_SECTION_CODE = -2U, // An Output_section_data for an SHF_MERGE section with // SHF_STRINGS set. - MERGE_STRING_SECTION_CODE = -3U + MERGE_STRING_SECTION_CODE = -3U, + // An Output_section_data for a relaxed input section. + RELAXED_INPUT_SECTION_CODE = -4U }; // For an ordinary input section, this is the section index in the @@ -2625,8 +3276,8 @@ class Output_section : public Output_data { // For an ordinary input section, the section size. off_t data_size; - // For OUTPUT_SECTION_CODE, this is not used. For - // MERGE_DATA_SECTION_CODE or MERGE_STRING_SECTION_CODE, the + // For OUTPUT_SECTION_CODE or RELAXED_INPUT_SECTION_CODE, this is not + // used. For MERGE_DATA_SECTION_CODE or MERGE_STRING_SECTION_CODE, the // entity size. uint64_t entsize; } u1_; @@ -2638,15 +3289,106 @@ class Output_section : public Output_data // For OUTPUT_SECTION_CODE or MERGE_DATA_SECTION_CODE or // MERGE_STRING_SECTION_CODE, the data. Output_section_data* posd; + // For RELAXED_INPUT_SECTION_CODE, the data. + Output_relaxed_input_section* poris; } u2_; }; typedef std::vector<Input_section> Input_section_list; + // Allow a child class to access the input sections. + const Input_section_list& + input_sections() const + { return this->input_sections_; } + + private: + // We only save enough information to undo the effects of section layout. + class Checkpoint_output_section + { + public: + Checkpoint_output_section(uint64_t addralign, elfcpp::Elf_Xword flags, + const Input_section_list& input_sections, + off_t first_input_offset, + bool attached_input_sections_are_sorted) + : addralign_(addralign), flags_(flags), + input_sections_(input_sections), + input_sections_size_(input_sections_.size()), + input_sections_copy_(), first_input_offset_(first_input_offset), + attached_input_sections_are_sorted_(attached_input_sections_are_sorted) + { } + + virtual + ~Checkpoint_output_section() + { } + + // Return the address alignment. + uint64_t + addralign() const + { return this->addralign_; } + + // Return the section flags. + elfcpp::Elf_Xword + flags() const + { return this->flags_; } + + // Return a reference to the input section list copy. + Input_section_list* + input_sections() + { return &this->input_sections_copy_; } + + // Return the size of input_sections at the time when checkpoint is + // taken. + size_t + input_sections_size() const + { return this->input_sections_size_; } + + // Whether input sections are copied. + bool + input_sections_saved() const + { return this->input_sections_copy_.size() == this->input_sections_size_; } + + off_t + first_input_offset() const + { return this->first_input_offset_; } + + bool + attached_input_sections_are_sorted() const + { return this->attached_input_sections_are_sorted_; } + + // Save input sections. + void + save_input_sections() + { + this->input_sections_copy_.reserve(this->input_sections_size_); + this->input_sections_copy_.clear(); + Input_section_list::const_iterator p = this->input_sections_.begin(); + gold_assert(this->input_sections_size_ >= this->input_sections_.size()); + for(size_t i = 0; i < this->input_sections_size_ ; i++, ++p) + this->input_sections_copy_.push_back(*p); + } + + private: + // The section alignment. + uint64_t addralign_; + // The section flags. + elfcpp::Elf_Xword flags_; + // Reference to the input sections to be checkpointed. + const Input_section_list& input_sections_; + // Size of the checkpointed portion of input_sections_; + size_t input_sections_size_; + // Copy of input sections. + Input_section_list input_sections_copy_; + // The offset of the first entry in input_sections_. + off_t first_input_offset_; + // True if the input sections attached to this output section have + // already been sorted. + bool attached_input_sections_are_sorted_; + }; + // This class is used to sort the input sections. class Input_section_sort_entry; - // This is the sort comparison function. + // This is the sort comparison function for ctors and dtors. struct Input_section_sort_compare { bool @@ -2654,6 +3396,14 @@ class Output_section : public Output_data const Input_section_sort_entry&) const; }; + // This is the sort comparison function for .init_array and .fini_array. + struct Input_section_sort_init_fini_compare + { + bool + operator()(const Input_section_sort_entry&, + const Input_section_sort_entry&) const; + }; + // Fill data. This is used to fill in data between input sections. // It is also used for data statements (BYTE, WORD, etc.) in linker // scripts. When we have to keep track of the input sections, we @@ -2686,6 +3436,83 @@ class Output_section : public Output_data typedef std::vector<Fill> Fill_list; + // This class describes properties of merge data sections. It is used + // as a key type for maps. + class Merge_section_properties + { + public: + Merge_section_properties(bool is_string, uint64_t entsize, + uint64_t addralign) + : is_string_(is_string), entsize_(entsize), addralign_(addralign) + { } + + // Whether this equals to another Merge_section_properties MSP. + bool + eq(const Merge_section_properties& msp) const + { + return ((this->is_string_ == msp.is_string_) + && (this->entsize_ == msp.entsize_) + && (this->addralign_ == msp.addralign_)); + } + + // Compute a hash value for this using 64-bit FNV-1a hash. + size_t + hash_value() const + { + uint64_t h = 14695981039346656037ULL; // FNV offset basis. + uint64_t prime = 1099511628211ULL; + h = (h ^ static_cast<uint64_t>(this->is_string_)) * prime; + h = (h ^ static_cast<uint64_t>(this->entsize_)) * prime; + h = (h ^ static_cast<uint64_t>(this->addralign_)) * prime; + return h; + } + + // Functors for associative containers. + struct equal_to + { + bool + operator()(const Merge_section_properties& msp1, + const Merge_section_properties& msp2) const + { return msp1.eq(msp2); } + }; + + struct hash + { + size_t + operator()(const Merge_section_properties& msp) const + { return msp.hash_value(); } + }; + + private: + // Whether this merge data section is for strings. + bool is_string_; + // Entsize of this merge data section. + uint64_t entsize_; + // Address alignment. + uint64_t addralign_; + }; + + // Map that link Merge_section_properties to Output_merge_base. + typedef Unordered_map<Merge_section_properties, Output_merge_base*, + Merge_section_properties::hash, + Merge_section_properties::equal_to> + Merge_section_by_properties_map; + + // Map that link Const_section_id to Output_section_data. + typedef Unordered_map<Const_section_id, Output_section_data*, + Const_section_id_hash> + Output_section_data_by_input_section_map; + + // Map that link Const_section_id to Output_relaxed_input_section. + typedef Unordered_map<Const_section_id, Output_relaxed_input_section*, + Const_section_id_hash> + Output_relaxed_input_section_by_input_section_map; + + // Map used during relaxation of existing sections. This map + // a section id an input section list index. We assume that + // Input_section_list is a vector. + typedef Unordered_map<Section_id, size_t, Section_id_hash> Relaxation_map; + // Add a new output section by Input_section. void add_output_section_data(Input_section*); @@ -2708,6 +3535,25 @@ class Output_section : public Output_data void sort_attached_input_sections(); + // Find the merge section into which an input section with index SHNDX in + // OBJECT has been added. Return NULL if none found. + Output_section_data* + find_merge_section(const Relobj* object, unsigned int shndx) const; + + // Build a relaxation map. + void + build_relaxation_map( + const Input_section_list& input_sections, + size_t limit, + Relaxation_map* map) const; + + // Convert input sections in an input section list into relaxed sections. + void + convert_input_sections_in_list_to_relaxed_sections( + const std::vector<Output_relaxed_input_section*>& relaxed_sections, + const Relaxation_map& map, + Input_section_list* input_sections); + // Most of these fields are only valid after layout. // The name of the section. This will point into a Stringpool. @@ -2804,14 +3650,54 @@ class Output_section : public Output_data bool is_relro_ : 1; // True if this section holds relro local data. bool is_relro_local_ : 1; + // True if this must be the last relro section. + bool is_last_relro_ : 1; + // True if this must be the first section after the relro sections. + bool is_first_non_relro_ : 1; + // True if this is a small section. + bool is_small_section_ : 1; + // True if this is a large section. + bool is_large_section_ : 1; + // True if this is the .interp section going into the PT_INTERP + // segment. + bool is_interp_ : 1; + // True if this is section is read by the dynamic linker. + bool is_dynamic_linker_section_ : 1; + // Whether code-fills are generated at write. + bool generate_code_fills_at_write_ : 1; + // Whether the entry size field should be zero. + bool is_entsize_zero_ : 1; + // Whether section offsets need adjustment due to relaxation. + bool section_offsets_need_adjustment_ : 1; + // Whether this is a NOLOAD section. + bool is_noload_ : 1; // For SHT_TLS sections, the offset of this section relative to the base // of the TLS segment. uint64_t tls_offset_; + // Saved checkpoint. + Checkpoint_output_section* checkpoint_; + // Map from input sections to merge sections. + Output_section_data_by_input_section_map merge_section_map_; + // Map from merge section properties to merge_sections; + Merge_section_by_properties_map merge_section_by_properties_map_; + // Map from input sections to relaxed input sections. This is mutable + // because it is updated lazily. We may need to update it in a + // const qualified method. + mutable Output_relaxed_input_section_by_input_section_map + relaxed_input_section_map_; + // Whether relaxed_input_section_map_ is valid. + mutable bool is_relaxed_input_section_map_valid_; }; // An output segment. PT_LOAD segments are built from collections of // output sections. Other segments typically point within PT_LOAD // segments, and are built directly as needed. +// +// NOTE: We want to use the copy constructor for this class. During +// relaxation, we may try built the segments multiple times. We do +// that by copying the original segment list before lay-out, doing +// a trial lay-out and roll-back to the saved copied if we need to +// to the lay-out again. class Output_segment { @@ -2854,21 +3740,35 @@ class Output_segment offset() const { return this->offset_; } + // Whether this is a segment created to hold large data sections. + bool + is_large_data_segment() const + { return this->is_large_data_segment_; } + + // Record that this is a segment created to hold large data + // sections. + void + set_is_large_data_segment() + { this->is_large_data_segment_ = true; } + // Return the maximum alignment of the Output_data. uint64_t maximum_alignment(); - // Add an Output_section to this segment. + // Add the Output_section OS to this segment. SEG_FLAGS is the + // segment flags to use. DO_SORT is true if we should sort the + // placement of the input section for more efficient generated code. void - add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags); + add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags, + bool do_sort); // Remove an Output_section from this segment. It is an error if it // is not present. void remove_output_section(Output_section* os); - // Add an Output_data (which is not an Output_section) to the start - // of this segment. + // Add an Output_data (which need not be an Output_section) to the + // start of this segment. void add_initial_output_data(Output_data*); @@ -2900,6 +3800,17 @@ class Output_segment this->are_addresses_set_ = true; } + // Update the flags for the flags of an output section added to this + // segment. + void + update_flags_for_output_section(elfcpp::Elf_Xword flags) + { + // The ELF ABI specifies that a PT_TLS segment should always have + // PF_R as the flags. + if (this->type() != elfcpp::PT_TLS) + this->flags_ |= flags; + } + // Set the segment flags. This is only used if we have a PHDRS // clause which explicitly specifies the flags. void @@ -2914,7 +3825,8 @@ class Output_segment // address of the immediately following segment. Update *POFF and // *PSHNDX. This should only be called for a PT_LOAD segment. uint64_t - set_section_addresses(const Layout*, bool reset, uint64_t addr, off_t* poff, + set_section_addresses(const Layout*, bool reset, uint64_t addr, + unsigned int increase_relro, off_t* poff, unsigned int* pshndx); // Set the minimum alignment of this segment. This may be adjusted @@ -2926,7 +3838,7 @@ class Output_segment // Set the offset of this segment based on the section. This should // only be called for a non-PT_LOAD segment. void - set_offset(); + set_offset(unsigned int increase); // Set the TLS offsets of the sections contained in the PT_TLS segment. void @@ -2958,9 +3870,6 @@ class Output_segment print_sections_to_mapfile(Mapfile*) const; private: - Output_segment(const Output_segment&); - Output_segment& operator=(const Output_segment&); - typedef std::list<Output_data*> Output_data_list; // Find the maximum alignment in an Output_data_list. @@ -2975,7 +3884,7 @@ class Output_segment uint64_t set_section_list_addresses(const Layout*, bool reset, Output_data_list*, uint64_t addr, off_t* poff, unsigned int* pshndx, - bool* in_tls, bool* in_relro); + bool* in_tls); // Return the number of Output_sections in an Output_data_list. unsigned int @@ -3003,6 +3912,9 @@ class Output_segment void print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const; + // NOTE: We want to use the copy constructor. Currently, shallow copy + // works for us so we do not need to write our own copy constructor. + // The list of output data with contents attached to this segment. Output_data_list output_data_; // The list of output data without contents attached to this segment. @@ -3036,6 +3948,8 @@ class Output_segment bool is_max_align_known_ : 1; // Whether vaddr and paddr were set by a linker script. bool are_addresses_set_ : 1; + // Whether this segment holds large data sections. + bool is_large_data_segment_ : 1; }; // This class represents the output file. @@ -3051,19 +3965,37 @@ class Output_file set_is_temporary() { this->is_temporary_ = true; } + // Try to open an existing file. Returns false if the file doesn't + // exist, has a size of 0 or can't be mmaped. This method is + // thread-unsafe. + bool + open_for_modification(); + // Open the output file. FILE_SIZE is the final size of the file. + // If the file already exists, it is deleted/truncated. This method + // is thread-unsafe. void open(off_t file_size); - // Resize the output file. + // Resize the output file. This method is thread-unsafe. void resize(off_t file_size); // Close the output file (flushing all buffered data) and make sure - // there are no errors. + // there are no errors. This method is thread-unsafe. void close(); + // Return the size of this file. + off_t + filesize() + { return this->file_size_; } + + // Return the name of this file. + const char* + filename() + { return this->name_; } + // We currently always use mmap which makes the view handling quite // simple. In the future we may support other approaches. @@ -3111,10 +4043,19 @@ class Output_file { } private: - // Map the file into memory and return a pointer to the map. + // Map the file into memory or, if that fails, allocate anonymous + // memory. void map(); + // Allocate anonymous memory for the file. + bool + map_anonymous(); + + // Map the file into memory. + bool + map_no_anonymous(); + // Unmap the file from memory (and flush to disk buffers). void unmap(); diff --git a/binutils-2.19/gold/parameters.cc b/binutils-2.19/gold/parameters.cc index 7293051..4430388 100644 --- a/binutils-2.19/gold/parameters.cc +++ b/binutils-2.19/gold/parameters.cc @@ -1,6 +1,6 @@ // parameters.cc -- general parameters for a link using gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -30,6 +30,47 @@ namespace gold { +// Our local version of the variable, which is not const. + +static Parameters static_parameters; + +// The global variable. + +const Parameters* parameters = &static_parameters; + +// A helper class to set the target once. + +class Set_parameters_target_once : public Once +{ + public: + Set_parameters_target_once(Parameters* parameters) + : parameters_(parameters) + { } + + protected: + void + do_run_once(void* arg) + { this->parameters_->set_target_once(static_cast<Target*>(arg)); } + + private: + Parameters* parameters_; +}; + +// We only need one Set_parameters_target_once. + +static +Set_parameters_target_once set_parameters_target_once(&static_parameters); + +// Class Parameters. + +Parameters::Parameters() + : errors_(NULL), options_(NULL), target_(NULL), + doing_static_link_valid_(false), doing_static_link_(false), + debug_(0), + set_parameters_target_once_(&set_parameters_target_once) + { + } + void Parameters::set_errors(Errors* errors) { @@ -48,6 +89,8 @@ Parameters::set_options(const General_options* options) // If --verbose is set, it acts as "--debug=files". if (options->verbose()) this->debug_ |= DEBUG_FILES; + if (this->target_valid()) + this->check_target_endianness(); } void @@ -59,42 +102,42 @@ Parameters::set_doing_static_link(bool doing_static_link) } void -Parameters::set_target(const Target* target) +Parameters::set_target(Target* target) { - if (!this->target_valid()) - this->target_ = target; - else - gold_assert(target == this->target_); + this->set_parameters_target_once_->run_once(static_cast<void*>(target)); + gold_assert(target == this->target_); } -// The x86_64 kernel build converts a binary file to an object file -// using -r --format binary --oformat elf32-i386 foo.o. In order to -// support that for gold we support determining the default target -// choice from the output format. We recognize names that the GNU -// linker uses. +// This is called at most once. -const Target& -Parameters::default_target() const +void +Parameters::set_target_once(Target* target) { - gold_assert(this->options_valid()); - if (this->options().user_set_oformat()) - { - const Target* target - = select_target_by_name(this->options().oformat()); - if (target != NULL) - return *target; + gold_assert(this->target_ == NULL); + this->target_ = target; + if (this->options_valid()) + this->check_target_endianness(); +} - gold_error(_("unrecognized output format %s"), - this->options().oformat()); - } +// Clear the target, for testing. - // The GOLD_DEFAULT_xx macros are defined by the configure script. - const Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE, - GOLD_DEFAULT_SIZE, - GOLD_DEFAULT_BIG_ENDIAN, - 0, 0); - gold_assert(target != NULL); - return *target; +void +Parameters::clear_target() +{ + this->target_ = NULL; + // We need a new Set_parameters_target_once so that we can set the + // target again. + this->set_parameters_target_once_ = new Set_parameters_target_once(this); +} + +// Return whether TARGET is compatible with the target we are using. + +bool +Parameters::is_compatible_target(const Target* target) const +{ + if (this->target_ == NULL) + return true; + return target == this->target_; } Parameters::Target_size_endianness @@ -142,14 +185,28 @@ Parameters::size_and_endianness() const gold_unreachable(); } +// If output endianness is specified in command line, check that it does +// not conflict with the target. -// Our local version of the variable, which is not const. - -static Parameters static_parameters; - -// The global variable. - -const Parameters* parameters = &static_parameters; +void +Parameters::check_target_endianness() +{ + General_options::Endianness endianness = this->options().endianness(); + if (endianness != General_options::ENDIANNESS_NOT_SET) + { + bool big_endian; + if (endianness == General_options::ENDIANNESS_BIG) + big_endian = true; + else + { + gold_assert(endianness == General_options::ENDIANNESS_LITTLE); + big_endian = false;; + } + + if (this->target().is_big_endian() != big_endian) + gold_error(_("input file does not match -EB/EL option")); + } +} void set_parameters_errors(Errors* errors) @@ -160,11 +217,67 @@ set_parameters_options(const General_options* options) { static_parameters.set_options(options); } void -set_parameters_target(const Target* target) -{ static_parameters.set_target(target); } +set_parameters_target(Target* target) +{ + static_parameters.set_target(target); + target->select_as_default_target(); +} void set_parameters_doing_static_link(bool doing_static_link) { static_parameters.set_doing_static_link(doing_static_link); } +// Force the target to be valid by using the default. Use the +// --oformat option is set; this supports the x86_64 kernel build, +// which converts a binary file to an object file using -r --format +// binary --oformat elf32-i386 foo.o. Otherwise use the configured +// default. + +void +parameters_force_valid_target() +{ + if (parameters->target_valid()) + return; + + gold_assert(parameters->options_valid()); + if (parameters->options().user_set_oformat()) + { + Target* target = select_target_by_name(parameters->options().oformat()); + if (target != NULL) + { + set_parameters_target(target); + return; + } + + gold_error(_("unrecognized output format %s"), + parameters->options().oformat()); + } + + // The GOLD_DEFAULT_xx macros are defined by the configure script. + bool is_big_endian; + General_options::Endianness endianness = parameters->options().endianness(); + if (endianness == General_options::ENDIANNESS_BIG) + is_big_endian = true; + else if (endianness == General_options::ENDIANNESS_LITTLE) + is_big_endian = false; + else + is_big_endian = GOLD_DEFAULT_BIG_ENDIAN; + + Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE, + GOLD_DEFAULT_SIZE, + is_big_endian, + elfcpp::GOLD_DEFAULT_OSABI, + 0); + gold_assert(target != NULL); + set_parameters_target(target); +} + +// Clear the current target, for testing. + +void +parameters_clear_target() +{ + static_parameters.clear_target(); +} + } // End namespace gold. diff --git a/binutils-2.19/gold/parameters.h b/binutils-2.19/gold/parameters.h index ce165dd..0ca2941 100644 --- a/binutils-2.19/gold/parameters.h +++ b/binutils-2.19/gold/parameters.h @@ -1,6 +1,6 @@ // parameters.h -- general parameters for a link using gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -29,6 +29,9 @@ namespace gold class General_options; class Errors; class Target; +template<int size, bool big_endian> +class Sized_target; +class Set_parameters_target_once; // Here we define the Parameters class which simply holds simple // general parameters which apply to the entire link. We use a global @@ -47,11 +50,7 @@ class Target; class Parameters { public: - Parameters() - : errors_(NULL), options_(NULL), target_(NULL), - doing_static_link_valid_(false), doing_static_link_(false), - debug_(0) - { } + Parameters(); // These should be called as soon as they are known. void @@ -61,7 +60,7 @@ class Parameters set_options(const General_options* options); void - set_target(const Target* target); + set_target(Target* target); void set_doing_static_link(bool doing_static_link); @@ -98,10 +97,23 @@ class Parameters return *this->target_; } - // When we don't have an output file to associate a target, make a - // default one, with guesses about size and endianness. - const Target& - default_target() const; + // The Sized_target of the output file. The caller must request the + // right size and endianness. + template<int size, bool big_endian> + Sized_target<size, big_endian>* + sized_target() const + { + gold_assert(this->target_valid()); + return static_cast<Sized_target<size, big_endian>*>(this->target_); + } + + // Clear the target, for testing. + void + clear_target(); + + // Return true if TARGET is compatible with the current target. + bool + is_compatible_target(const Target*) const; bool doing_static_link() const @@ -134,12 +146,21 @@ class Parameters private: + void + set_target_once(Target*); + + void + check_target_endianness(); + + friend class Set_parameters_target_once; + Errors* errors_; const General_options* options_; - const Target* target_; + Target* target_; bool doing_static_link_valid_; bool doing_static_link_; int debug_; + Set_parameters_target_once* set_parameters_target_once_; }; // This is a global variable. @@ -155,11 +176,22 @@ extern void set_parameters_options(const General_options* options); extern void -set_parameters_target(const Target* target); +set_parameters_target(Target* target); extern void set_parameters_doing_static_link(bool doing_static_link); - + +// Ensure that the target to be valid by using the default target if +// necessary. + +extern void +parameters_force_valid_target(); + +// Clear the current target, for testing. + +extern void +parameters_clear_target(); + // Return whether we are doing a particular debugging type. The // argument is one of the flags from debug.h. diff --git a/binutils-2.19/gold/plugin.cc b/binutils-2.19/gold/plugin.cc new file mode 100644 index 0000000..2831c2b --- /dev/null +++ b/binutils-2.19/gold/plugin.cc @@ -0,0 +1,1073 @@ +// plugin.cc -- plugin manager for gold -*- C++ -*- + +// Copyright 2008, 2009, 2010 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <cstdio> +#include <cstdarg> +#include <cstring> +#include <string> +#include <vector> + +#ifdef ENABLE_PLUGINS +#include <dlfcn.h> +#endif + +#include "parameters.h" +#include "errors.h" +#include "fileread.h" +#include "layout.h" +#include "options.h" +#include "plugin.h" +#include "target.h" +#include "readsyms.h" +#include "symtab.h" +#include "elfcpp.h" + +namespace gold +{ + +#ifdef ENABLE_PLUGINS + +// The linker's exported interfaces. + +extern "C" +{ + +static enum ld_plugin_status +register_claim_file(ld_plugin_claim_file_handler handler); + +static enum ld_plugin_status +register_all_symbols_read(ld_plugin_all_symbols_read_handler handler); + +static enum ld_plugin_status +register_cleanup(ld_plugin_cleanup_handler handler); + +static enum ld_plugin_status +add_symbols(void *handle, int nsyms, const struct ld_plugin_symbol *syms); + +static enum ld_plugin_status +get_input_file(const void *handle, struct ld_plugin_input_file *file); + +static enum ld_plugin_status +release_input_file(const void *handle); + +static enum ld_plugin_status +get_symbols(const void *handle, int nsyms, struct ld_plugin_symbol *syms); + +static enum ld_plugin_status +add_input_file(char *pathname); + +static enum ld_plugin_status +add_input_library(char *pathname); + +static enum ld_plugin_status +message(int level, const char *format, ...); + +}; + +#endif // ENABLE_PLUGINS + +static Pluginobj* make_sized_plugin_object(Input_file* input_file, + off_t offset, off_t filesize); + +// Plugin methods. + +// Load one plugin library. + +void +Plugin::load() +{ +#ifdef ENABLE_PLUGINS + // Load the plugin library. + // FIXME: Look for the library in standard locations. + this->handle_ = dlopen(this->filename_.c_str(), RTLD_NOW); + if (this->handle_ == NULL) + { + gold_error(_("%s: could not load plugin library"), + this->filename_.c_str()); + return; + } + + // Find the plugin's onload entry point. + void* ptr = dlsym(this->handle_, "onload"); + if (ptr == NULL) + { + gold_error(_("%s: could not find onload entry point"), + this->filename_.c_str()); + return; + } + ld_plugin_onload onload; + gold_assert(sizeof(onload) == sizeof(ptr)); + memcpy(&onload, &ptr, sizeof(ptr)); + + // Get the linker's version number. + const char* ver = get_version_string(); + int major = 0; + int minor = 0; + sscanf(ver, "%d.%d", &major, &minor); + + // Allocate and populate a transfer vector. + const int tv_fixed_size = 14; + int tv_size = this->args_.size() + tv_fixed_size; + ld_plugin_tv *tv = new ld_plugin_tv[tv_size]; + + // Put LDPT_MESSAGE at the front of the list so the plugin can use it + // while processing subsequent entries. + int i = 0; + tv[i].tv_tag = LDPT_MESSAGE; + tv[i].tv_u.tv_message = message; + + ++i; + tv[i].tv_tag = LDPT_API_VERSION; + tv[i].tv_u.tv_val = LD_PLUGIN_API_VERSION; + + ++i; + tv[i].tv_tag = LDPT_GOLD_VERSION; + tv[i].tv_u.tv_val = major * 100 + minor; + + ++i; + tv[i].tv_tag = LDPT_LINKER_OUTPUT; + if (parameters->options().relocatable()) + tv[i].tv_u.tv_val = LDPO_REL; + else if (parameters->options().shared()) + tv[i].tv_u.tv_val = LDPO_DYN; + else + tv[i].tv_u.tv_val = LDPO_EXEC; + + for (unsigned int j = 0; j < this->args_.size(); ++j) + { + ++i; + tv[i].tv_tag = LDPT_OPTION; + tv[i].tv_u.tv_string = this->args_[j].c_str(); + } + + ++i; + tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK; + tv[i].tv_u.tv_register_claim_file = register_claim_file; + + ++i; + tv[i].tv_tag = LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK; + tv[i].tv_u.tv_register_all_symbols_read = register_all_symbols_read; + + ++i; + tv[i].tv_tag = LDPT_REGISTER_CLEANUP_HOOK; + tv[i].tv_u.tv_register_cleanup = register_cleanup; + + ++i; + tv[i].tv_tag = LDPT_ADD_SYMBOLS; + tv[i].tv_u.tv_add_symbols = add_symbols; + + ++i; + tv[i].tv_tag = LDPT_GET_INPUT_FILE; + tv[i].tv_u.tv_get_input_file = get_input_file; + + ++i; + tv[i].tv_tag = LDPT_RELEASE_INPUT_FILE; + tv[i].tv_u.tv_release_input_file = release_input_file; + + ++i; + tv[i].tv_tag = LDPT_GET_SYMBOLS; + tv[i].tv_u.tv_get_symbols = get_symbols; + + ++i; + tv[i].tv_tag = LDPT_ADD_INPUT_FILE; + tv[i].tv_u.tv_add_input_file = add_input_file; + + ++i; + tv[i].tv_tag = LDPT_ADD_INPUT_LIBRARY; + tv[i].tv_u.tv_add_input_library = add_input_library; + + ++i; + tv[i].tv_tag = LDPT_NULL; + tv[i].tv_u.tv_val = 0; + + gold_assert(i == tv_size - 1); + + // Call the onload entry point. + (*onload)(tv); + + delete[] tv; +#endif // ENABLE_PLUGINS +} + +// Call the plugin claim-file handler. + +inline bool +Plugin::claim_file(struct ld_plugin_input_file *plugin_input_file) +{ + int claimed = 0; + + if (this->claim_file_handler_ != NULL) + { + (*this->claim_file_handler_)(plugin_input_file, &claimed); + if (claimed) + return true; + } + return false; +} + +// Call the all-symbols-read handler. + +inline void +Plugin::all_symbols_read() +{ + if (this->all_symbols_read_handler_ != NULL) + (*this->all_symbols_read_handler_)(); +} + +// Call the cleanup handler. + +inline void +Plugin::cleanup() +{ + if (this->cleanup_handler_ != NULL && !this->cleanup_done_) + { + // Set this flag before calling to prevent a recursive plunge + // in the event that a plugin's cleanup handler issues a + // fatal error. + this->cleanup_done_ = true; + (*this->cleanup_handler_)(); + } +} + +// Plugin_manager methods. + +Plugin_manager::~Plugin_manager() +{ + for (Plugin_list::iterator p = this->plugins_.begin(); + p != this->plugins_.end(); + ++p) + delete *p; + this->plugins_.clear(); + for (Object_list::iterator obj = this->objects_.begin(); + obj != this->objects_.end(); + ++obj) + delete *obj; + this->objects_.clear(); +} + +// Load all plugin libraries. + +void +Plugin_manager::load_plugins() +{ + for (this->current_ = this->plugins_.begin(); + this->current_ != this->plugins_.end(); + ++this->current_) + (*this->current_)->load(); +} + +// Call the plugin claim-file handlers in turn to see if any claim the file. + +Pluginobj* +Plugin_manager::claim_file(Input_file* input_file, off_t offset, + off_t filesize) +{ + if (this->in_replacement_phase_) + return NULL; + + unsigned int handle = this->objects_.size(); + this->input_file_ = input_file; + this->plugin_input_file_.name = input_file->filename().c_str(); + this->plugin_input_file_.fd = input_file->file().descriptor(); + this->plugin_input_file_.offset = offset; + this->plugin_input_file_.filesize = filesize; + this->plugin_input_file_.handle = reinterpret_cast<void*>(handle); + + for (this->current_ = this->plugins_.begin(); + this->current_ != this->plugins_.end(); + ++this->current_) + { + if ((*this->current_)->claim_file(&this->plugin_input_file_)) + { + if (this->objects_.size() > handle) + return this->objects_[handle]; + + // If the plugin claimed the file but did not call the + // add_symbols callback, we need to create the Pluginobj now. + Pluginobj* obj = this->make_plugin_object(handle); + return obj; + } + } + + return NULL; +} + +// Call the all-symbols-read handlers. + +void +Plugin_manager::all_symbols_read(Workqueue* workqueue, Task* task, + Input_objects* input_objects, + Symbol_table* symtab, Layout* layout, + Dirsearch* dirpath, Mapfile* mapfile, + Task_token** last_blocker) +{ + this->in_replacement_phase_ = true; + this->workqueue_ = workqueue; + this->task_ = task; + this->input_objects_ = input_objects; + this->symtab_ = symtab; + this->layout_ = layout; + this->dirpath_ = dirpath; + this->mapfile_ = mapfile; + this->this_blocker_ = NULL; + + for (this->current_ = this->plugins_.begin(); + this->current_ != this->plugins_.end(); + ++this->current_) + (*this->current_)->all_symbols_read(); + + *last_blocker = this->this_blocker_; +} + +// Layout deferred objects. + +void +Plugin_manager::layout_deferred_objects() +{ + Deferred_layout_list::iterator obj; + + for (obj = this->deferred_layout_objects_.begin(); + obj != this->deferred_layout_objects_.end(); + ++obj) + (*obj)->layout_deferred_sections(this->layout_); +} + +// Call the cleanup handlers. + +void +Plugin_manager::cleanup() +{ + for (this->current_ = this->plugins_.begin(); + this->current_ != this->plugins_.end(); + ++this->current_) + (*this->current_)->cleanup(); +} + +// Make a new Pluginobj object. This is called when the plugin calls +// the add_symbols API. + +Pluginobj* +Plugin_manager::make_plugin_object(unsigned int handle) +{ + // Make sure we aren't asked to make an object for the same handle twice. + if (this->objects_.size() != handle) + return NULL; + + Pluginobj* obj = make_sized_plugin_object(this->input_file_, + this->plugin_input_file_.offset, + this->plugin_input_file_.filesize); + this->objects_.push_back(obj); + return obj; +} + +// Get the input file information with an open (possibly re-opened) +// file descriptor. + +ld_plugin_status +Plugin_manager::get_input_file(unsigned int handle, + struct ld_plugin_input_file *file) +{ + Pluginobj* obj = this->object(handle); + if (obj == NULL) + return LDPS_BAD_HANDLE; + + obj->lock(this->task_); + file->name = obj->filename().c_str(); + file->fd = obj->descriptor(); + file->offset = obj->offset(); + file->filesize = obj->filesize(); + file->handle = reinterpret_cast<void*>(handle); + return LDPS_OK; +} + +// Release the input file. + +ld_plugin_status +Plugin_manager::release_input_file(unsigned int handle) +{ + Pluginobj* obj = this->object(handle); + if (obj == NULL) + return LDPS_BAD_HANDLE; + + obj->unlock(this->task_); + return LDPS_OK; +} + +// Add a new input file. + +ld_plugin_status +Plugin_manager::add_input_file(char *pathname, bool is_lib) +{ + Input_file_argument file(pathname, + (is_lib + ? Input_file_argument::INPUT_FILE_TYPE_LIBRARY + : Input_file_argument::INPUT_FILE_TYPE_FILE), + "", false, this->options_); + Input_argument* input_argument = new Input_argument(file); + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + if (this->layout_->incremental_inputs()) + gold_error(_("input files added by plug-ins in --incremental mode not " + "supported yet")); + this->workqueue_->queue_soon(new Read_symbols(this->input_objects_, + this->symtab_, + this->layout_, + this->dirpath_, + 0, + this->mapfile_, + input_argument, + NULL, + this->this_blocker_, + next_blocker)); + this->this_blocker_ = next_blocker; + return LDPS_OK; +} + +// Class Pluginobj. + +Pluginobj::Pluginobj(const std::string& name, Input_file* input_file, + off_t offset, off_t filesize) + : Object(name, input_file, false, offset), + nsyms_(0), syms_(NULL), symbols_(), filesize_(filesize), comdat_map_() +{ +} + +// Return TRUE if a defined symbol might be reachable from outside the +// universe of claimed objects. + +static inline bool +is_visible_from_outside(Symbol* lsym) +{ + if (lsym->in_real_elf()) + return true; + if (parameters->options().relocatable()) + return true; + if (parameters->options().export_dynamic() || parameters->options().shared()) + return lsym->is_externally_visible(); + return false; +} + +// Get symbol resolution info. + +ld_plugin_status +Pluginobj::get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const +{ + if (nsyms > this->nsyms_) + return LDPS_NO_SYMS; + for (int i = 0; i < nsyms; i++) + { + ld_plugin_symbol* isym = &syms[i]; + Symbol* lsym = this->symbols_[i]; + ld_plugin_symbol_resolution res = LDPR_UNKNOWN; + + if (lsym->is_undefined()) + // The symbol remains undefined. + res = LDPR_UNDEF; + else if (isym->def == LDPK_UNDEF + || isym->def == LDPK_WEAKUNDEF + || isym->def == LDPK_COMMON) + { + // The original symbol was undefined or common. + if (lsym->source() != Symbol::FROM_OBJECT) + res = LDPR_RESOLVED_EXEC; + else if (lsym->object()->pluginobj() != NULL) + res = LDPR_RESOLVED_IR; + else if (lsym->object()->is_dynamic()) + res = LDPR_RESOLVED_DYN; + else + res = LDPR_RESOLVED_EXEC; + } + else + { + // The original symbol was a definition. + if (lsym->source() != Symbol::FROM_OBJECT) + res = LDPR_PREEMPTED_REG; + else if (lsym->object() == static_cast<const Object*>(this)) + res = (is_visible_from_outside(lsym) + ? LDPR_PREVAILING_DEF + : LDPR_PREVAILING_DEF_IRONLY); + else + res = (lsym->object()->pluginobj() != NULL + ? LDPR_PREEMPTED_IR + : LDPR_PREEMPTED_REG); + } + isym->resolution = res; + } + return LDPS_OK; +} + +// Return TRUE if the comdat group with key COMDAT_KEY from this object +// should be kept. + +bool +Pluginobj::include_comdat_group(std::string comdat_key, Layout* layout) +{ + std::pair<Comdat_map::iterator, bool> ins = + this->comdat_map_.insert(std::make_pair(comdat_key, false)); + + // If this is the first time we've seen this comdat key, ask the + // layout object whether it should be included. + if (ins.second) + ins.first->second = layout->find_or_add_kept_section(comdat_key, + NULL, 0, true, + true, NULL); + + return ins.first->second; +} + +// Class Sized_pluginobj. + +template<int size, bool big_endian> +Sized_pluginobj<size, big_endian>::Sized_pluginobj( + const std::string& name, + Input_file* input_file, + off_t offset, + off_t filesize) + : Pluginobj(name, input_file, offset, filesize) +{ +} + +// Read the symbols. Not used for plugin objects. + +template<int size, bool big_endian> +void +Sized_pluginobj<size, big_endian>::do_read_symbols(Read_symbols_data*) +{ + gold_unreachable(); +} + +// Lay out the input sections. Not used for plugin objects. + +template<int size, bool big_endian> +void +Sized_pluginobj<size, big_endian>::do_layout(Symbol_table*, Layout*, + Read_symbols_data*) +{ + gold_unreachable(); +} + +// Add the symbols to the symbol table. + +template<int size, bool big_endian> +void +Sized_pluginobj<size, big_endian>::do_add_symbols(Symbol_table* symtab, + Read_symbols_data*, + Layout* layout) +{ + const int sym_size = elfcpp::Elf_sizes<size>::sym_size; + unsigned char symbuf[sym_size]; + elfcpp::Sym<size, big_endian> sym(symbuf); + elfcpp::Sym_write<size, big_endian> osym(symbuf); + + typedef typename elfcpp::Elf_types<size>::Elf_WXword Elf_size_type; + + this->symbols_.resize(this->nsyms_); + + for (int i = 0; i < this->nsyms_; ++i) + { + const struct ld_plugin_symbol *isym = &this->syms_[i]; + const char* name = isym->name; + const char* ver = isym->version; + elfcpp::Elf_Half shndx; + elfcpp::STB bind; + elfcpp::STV vis; + + if (name != NULL && name[0] == '\0') + name = NULL; + if (ver != NULL && ver[0] == '\0') + ver = NULL; + + switch (isym->def) + { + case LDPK_WEAKDEF: + case LDPK_WEAKUNDEF: + bind = elfcpp::STB_WEAK; + break; + case LDPK_DEF: + case LDPK_UNDEF: + case LDPK_COMMON: + default: + bind = elfcpp::STB_GLOBAL; + break; + } + + switch (isym->def) + { + case LDPK_DEF: + case LDPK_WEAKDEF: + shndx = elfcpp::SHN_ABS; + break; + case LDPK_COMMON: + shndx = elfcpp::SHN_COMMON; + break; + case LDPK_UNDEF: + case LDPK_WEAKUNDEF: + default: + shndx = elfcpp::SHN_UNDEF; + break; + } + + switch (isym->visibility) + { + case LDPV_PROTECTED: + vis = elfcpp::STV_DEFAULT; + break; + case LDPV_INTERNAL: + vis = elfcpp::STV_DEFAULT; + break; + case LDPV_HIDDEN: + vis = elfcpp::STV_DEFAULT; + break; + case LDPV_DEFAULT: + default: + vis = elfcpp::STV_DEFAULT; + break; + } + + if (isym->comdat_key != NULL + && isym->comdat_key[0] != '\0' + && !this->include_comdat_group(isym->comdat_key, layout)) + shndx = elfcpp::SHN_UNDEF; + + osym.put_st_name(0); + osym.put_st_value(0); + osym.put_st_size(static_cast<Elf_size_type>(isym->size)); + osym.put_st_info(bind, elfcpp::STT_NOTYPE); + osym.put_st_other(vis, 0); + osym.put_st_shndx(shndx); + + this->symbols_[i] = + symtab->add_from_pluginobj<size, big_endian>(this, name, ver, &sym); + } +} + +// Get the size of a section. Not used for plugin objects. + +template<int size, bool big_endian> +uint64_t +Sized_pluginobj<size, big_endian>::do_section_size(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Get the name of a section. Not used for plugin objects. + +template<int size, bool big_endian> +std::string +Sized_pluginobj<size, big_endian>::do_section_name(unsigned int) +{ + gold_unreachable(); + return std::string(); +} + +// Return a view of the contents of a section. Not used for plugin objects. + +template<int size, bool big_endian> +Object::Location +Sized_pluginobj<size, big_endian>::do_section_contents(unsigned int) +{ + Location loc(0, 0); + + gold_unreachable(); + return loc; +} + +// Return section flags. Not used for plugin objects. + +template<int size, bool big_endian> +uint64_t +Sized_pluginobj<size, big_endian>::do_section_flags(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return section entsize. Not used for plugin objects. + +template<int size, bool big_endian> +uint64_t +Sized_pluginobj<size, big_endian>::do_section_entsize(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return section address. Not used for plugin objects. + +template<int size, bool big_endian> +uint64_t +Sized_pluginobj<size, big_endian>::do_section_address(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return section type. Not used for plugin objects. + +template<int size, bool big_endian> +unsigned int +Sized_pluginobj<size, big_endian>::do_section_type(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return the section link field. Not used for plugin objects. + +template<int size, bool big_endian> +unsigned int +Sized_pluginobj<size, big_endian>::do_section_link(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return the section link field. Not used for plugin objects. + +template<int size, bool big_endian> +unsigned int +Sized_pluginobj<size, big_endian>::do_section_info(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return the section alignment. Not used for plugin objects. + +template<int size, bool big_endian> +uint64_t +Sized_pluginobj<size, big_endian>::do_section_addralign(unsigned int) +{ + gold_unreachable(); + return 0; +} + +// Return the Xindex structure to use. Not used for plugin objects. + +template<int size, bool big_endian> +Xindex* +Sized_pluginobj<size, big_endian>::do_initialize_xindex() +{ + gold_unreachable(); + return NULL; +} + +// Get symbol counts. Not used for plugin objects. + +template<int size, bool big_endian> +void +Sized_pluginobj<size, big_endian>::do_get_global_symbol_counts(const Symbol_table*, + size_t*, size_t*) const +{ + gold_unreachable(); +} + +// Get symbols. Not used for plugin objects. + +template<int size, bool big_endian> +const Object::Symbols* +Sized_pluginobj<size, big_endian>::do_get_global_symbols() const +{ + gold_unreachable(); +} + +// Class Plugin_finish. This task runs after all replacement files have +// been added. It calls each plugin's cleanup handler. + +class Plugin_finish : public Task +{ + public: + Plugin_finish(Task_token* this_blocker, Task_token* next_blocker) + : this_blocker_(this_blocker), next_blocker_(next_blocker) + { } + + ~Plugin_finish() + { + if (this->this_blocker_ != NULL) + delete this->this_blocker_; + } + + Task_token* + is_runnable() + { + if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) + return this->this_blocker_; + return NULL; + } + + void + locks(Task_locker* tl) + { tl->add(this, this->next_blocker_); } + + void + run(Workqueue*) + { + Plugin_manager* plugins = parameters->options().plugins(); + gold_assert(plugins != NULL); + plugins->cleanup(); + } + + std::string + get_name() const + { return "Plugin_finish"; } + + private: + Task_token* this_blocker_; + Task_token* next_blocker_; +}; + +// Class Plugin_hook. + +Plugin_hook::~Plugin_hook() +{ +} + +// Return whether a Plugin_hook task is runnable. + +Task_token* +Plugin_hook::is_runnable() +{ + if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) + return this->this_blocker_; + return NULL; +} + +// Return a Task_locker for a Plugin_hook task. We don't need any +// locks here. + +void +Plugin_hook::locks(Task_locker*) +{ +} + +// Run the "all symbols read" plugin hook. + +void +Plugin_hook::run(Workqueue* workqueue) +{ + gold_assert(this->options_.has_plugins()); + this->options_.plugins()->all_symbols_read(workqueue, + this, + this->input_objects_, + this->symtab_, + this->layout_, + this->dirpath_, + this->mapfile_, + &this->this_blocker_); + workqueue->queue_soon(new Plugin_finish(this->this_blocker_, + this->next_blocker_)); +} + +// The C interface routines called by the plugins. + +#ifdef ENABLE_PLUGINS + +// Register a claim-file handler. + +static enum ld_plugin_status +register_claim_file(ld_plugin_claim_file_handler handler) +{ + gold_assert(parameters->options().has_plugins()); + parameters->options().plugins()->set_claim_file_handler(handler); + return LDPS_OK; +} + +// Register an all-symbols-read handler. + +static enum ld_plugin_status +register_all_symbols_read(ld_plugin_all_symbols_read_handler handler) +{ + gold_assert(parameters->options().has_plugins()); + parameters->options().plugins()->set_all_symbols_read_handler(handler); + return LDPS_OK; +} + +// Register a cleanup handler. + +static enum ld_plugin_status +register_cleanup(ld_plugin_cleanup_handler handler) +{ + gold_assert(parameters->options().has_plugins()); + parameters->options().plugins()->set_cleanup_handler(handler); + return LDPS_OK; +} + +// Add symbols from a plugin-claimed input file. + +static enum ld_plugin_status +add_symbols(void* handle, int nsyms, const ld_plugin_symbol *syms) +{ + gold_assert(parameters->options().has_plugins()); + Pluginobj* obj = parameters->options().plugins()->make_plugin_object( + static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle))); + if (obj == NULL) + return LDPS_ERR; + obj->store_incoming_symbols(nsyms, syms); + return LDPS_OK; +} + +// Get the input file information with an open (possibly re-opened) +// file descriptor. + +static enum ld_plugin_status +get_input_file(const void *handle, struct ld_plugin_input_file *file) +{ + gold_assert(parameters->options().has_plugins()); + unsigned int obj_index = + static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)); + return parameters->options().plugins()->get_input_file(obj_index, file); +} + +// Release the input file. + +static enum ld_plugin_status +release_input_file(const void *handle) +{ + gold_assert(parameters->options().has_plugins()); + unsigned int obj_index = + static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle)); + return parameters->options().plugins()->release_input_file(obj_index); +} + +// Get the symbol resolution info for a plugin-claimed input file. + +static enum ld_plugin_status +get_symbols(const void * handle, int nsyms, ld_plugin_symbol* syms) +{ + gold_assert(parameters->options().has_plugins()); + Pluginobj* obj = parameters->options().plugins()->object( + static_cast<unsigned int>(reinterpret_cast<intptr_t>(handle))); + if (obj == NULL) + return LDPS_ERR; + return obj->get_symbol_resolution_info(nsyms, syms); +} + +// Add a new (real) input file generated by a plugin. + +static enum ld_plugin_status +add_input_file(char *pathname) +{ + gold_assert(parameters->options().has_plugins()); + return parameters->options().plugins()->add_input_file(pathname, false); +} + +// Add a new (real) library required by a plugin. + +static enum ld_plugin_status +add_input_library(char *pathname) +{ + gold_assert(parameters->options().has_plugins()); + return parameters->options().plugins()->add_input_file(pathname, true); +} + +// Issue a diagnostic message from a plugin. + +static enum ld_plugin_status +message(int level, const char * format, ...) +{ + va_list args; + va_start(args, format); + + switch (level) + { + case LDPL_INFO: + parameters->errors()->info(format, args); + break; + case LDPL_WARNING: + parameters->errors()->warning(format, args); + break; + case LDPL_ERROR: + default: + parameters->errors()->error(format, args); + break; + case LDPL_FATAL: + parameters->errors()->fatal(format, args); + break; + } + + va_end(args); + return LDPS_OK; +} + +#endif // ENABLE_PLUGINS + +// Allocate a Pluginobj object of the appropriate size and endianness. + +static Pluginobj* +make_sized_plugin_object(Input_file* input_file, off_t offset, off_t filesize) +{ + Pluginobj* obj = NULL; + + parameters_force_valid_target(); + const Target& target(parameters->target()); + + if (target.get_size() == 32) + { + if (target.is_big_endian()) +#ifdef HAVE_TARGET_32_BIG + obj = new Sized_pluginobj<32, true>(input_file->filename(), + input_file, offset, filesize); +#else + gold_error(_("%s: not configured to support " + "32-bit big-endian object"), + input_file->filename().c_str()); +#endif + else +#ifdef HAVE_TARGET_32_LITTLE + obj = new Sized_pluginobj<32, false>(input_file->filename(), + input_file, offset, filesize); +#else + gold_error(_("%s: not configured to support " + "32-bit little-endian object"), + input_file->filename().c_str()); +#endif + } + else if (target.get_size() == 64) + { + if (target.is_big_endian()) +#ifdef HAVE_TARGET_64_BIG + obj = new Sized_pluginobj<64, true>(input_file->filename(), + input_file, offset, filesize); +#else + gold_error(_("%s: not configured to support " + "64-bit big-endian object"), + input_file->filename().c_str()); +#endif + else +#ifdef HAVE_TARGET_64_LITTLE + obj = new Sized_pluginobj<64, false>(input_file->filename(), + input_file, offset, filesize); +#else + gold_error(_("%s: not configured to support " + "64-bit little-endian object"), + input_file->filename().c_str()); +#endif + } + + gold_assert(obj != NULL); + return obj; +} + +} // End namespace gold. diff --git a/binutils-2.19/gold/plugin.h b/binutils-2.19/gold/plugin.h new file mode 100644 index 0000000..635ed6f --- /dev/null +++ b/binutils-2.19/gold/plugin.h @@ -0,0 +1,477 @@ +// plugin.h -- plugin manager for gold -*- C++ -*- + +// Copyright 2008, 2009, 2010 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_PLUGIN_H +#define GOLD_PLUGIN_H + +#include <list> +#include <string> + +#include "object.h" +#include "plugin-api.h" +#include "workqueue.h" + +namespace gold +{ + +class General_options; +class Input_file; +class Input_objects; +class Symbol_table; +class Layout; +class Dirsearch; +class Mapfile; +class Task_token; +class Pluginobj; + +// This class represents a single plugin library. + +class Plugin +{ + public: + Plugin(const char* filename) + : handle_(NULL), + filename_(filename), + args_(), + claim_file_handler_(NULL), + all_symbols_read_handler_(NULL), + cleanup_handler_(NULL), + cleanup_done_(false) + { } + + ~Plugin() + { } + + // Load the library and call its entry point. + void + load(); + + // Call the claim-file handler. + bool + claim_file(struct ld_plugin_input_file *plugin_input_file); + + // Call the all-symbols-read handler. + void + all_symbols_read(); + + // Call the cleanup handler. + void + cleanup(); + + // Register a claim-file handler. + void + set_claim_file_handler(ld_plugin_claim_file_handler handler) + { this->claim_file_handler_ = handler; } + + // Register an all-symbols-read handler. + void + set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler) + { this->all_symbols_read_handler_ = handler; } + + // Register a claim-file handler. + void + set_cleanup_handler(ld_plugin_cleanup_handler handler) + { this->cleanup_handler_ = handler; } + + // Add an argument + void + add_option(const char *arg) + { + this->args_.push_back(arg); + } + + private: + Plugin(const Plugin&); + Plugin& operator=(const Plugin&); + + // The shared library handle returned by dlopen. + void* handle_; + // The argument string given to --plugin. + std::string filename_; + // The list of argument string given to --plugin-opt. + std::vector<std::string> args_; + // The plugin's event handlers. + ld_plugin_claim_file_handler claim_file_handler_; + ld_plugin_all_symbols_read_handler all_symbols_read_handler_; + ld_plugin_cleanup_handler cleanup_handler_; + // TRUE if the cleanup handlers have been called. + bool cleanup_done_; +}; + +// A manager class for plugins. + +class Plugin_manager +{ + public: + Plugin_manager(const General_options& options) + : plugins_(), objects_(), deferred_layout_objects_(), input_file_(NULL), + plugin_input_file_(), in_replacement_phase_(false), + options_(options), workqueue_(NULL), task_(NULL), input_objects_(NULL), + symtab_(NULL), layout_(NULL), dirpath_(NULL), mapfile_(NULL), + this_blocker_(NULL) + { this->current_ = plugins_.end(); } + + ~Plugin_manager(); + + // Add a plugin library. + void + add_plugin(const char* filename) + { this->plugins_.push_back(new Plugin(filename)); } + + // Add an argument to the current plugin. + void + add_plugin_option(const char* opt) + { + Plugin* last = this->plugins_.back(); + last->add_option(opt); + } + + // Load all plugin libraries. + void + load_plugins(); + + // Call the plugin claim-file handlers in turn to see if any claim the file. + Pluginobj* + claim_file(Input_file *input_file, off_t offset, off_t filesize); + + // Call the all-symbols-read handlers. + void + all_symbols_read(Workqueue* workqueue, Task* task, + Input_objects* input_objects, Symbol_table* symtab, + Layout* layout, Dirsearch* dirpath, Mapfile* mapfile, + Task_token** last_blocker); + + // Run deferred layout. + void + layout_deferred_objects(); + + // Call the cleanup handlers. + void + cleanup(); + + // Register a claim-file handler. + void + set_claim_file_handler(ld_plugin_claim_file_handler handler) + { + gold_assert(this->current_ != plugins_.end()); + (*this->current_)->set_claim_file_handler(handler); + } + + // Register an all-symbols-read handler. + void + set_all_symbols_read_handler(ld_plugin_all_symbols_read_handler handler) + { + gold_assert(this->current_ != plugins_.end()); + (*this->current_)->set_all_symbols_read_handler(handler); + } + + // Register a claim-file handler. + void + set_cleanup_handler(ld_plugin_cleanup_handler handler) + { + gold_assert(this->current_ != plugins_.end()); + (*this->current_)->set_cleanup_handler(handler); + } + + // Make a new Pluginobj object. This is called when the plugin calls + // the add_symbols API. + Pluginobj* + make_plugin_object(unsigned int handle); + + // Return the Pluginobj associated with the given HANDLE. + Pluginobj* + object(unsigned int handle) const + { + if (handle >= this->objects_.size()) + return NULL; + return this->objects_[handle]; + } + + // Return TRUE if any input files have been claimed by a plugin + // and we are still in the initial input phase. + bool + should_defer_layout() const + { return !this->objects_.empty() && !this->in_replacement_phase_; } + + // Add a regular object to the deferred layout list. These are + // objects whose layout has been deferred until after the + // replacement files have arrived. + void + add_deferred_layout_object(Relobj* obj) + { this->deferred_layout_objects_.push_back(obj); } + + // Get input file information with an open (possibly re-opened) + // file descriptor. + ld_plugin_status + get_input_file(unsigned int handle, struct ld_plugin_input_file *file); + + // Release an input file. + ld_plugin_status + release_input_file(unsigned int handle); + + // Add a new input file. + ld_plugin_status + add_input_file(char *pathname, bool is_lib); + + // Return TRUE if we are in the replacement phase. + bool + in_replacement_phase() const + { return this->in_replacement_phase_; } + + private: + Plugin_manager(const Plugin_manager&); + Plugin_manager& operator=(const Plugin_manager&); + + typedef std::list<Plugin*> Plugin_list; + typedef std::vector<Pluginobj*> Object_list; + typedef std::vector<Relobj*> Deferred_layout_list; + + // The list of plugin libraries. + Plugin_list plugins_; + // A pointer to the current plugin. Used while loading plugins. + Plugin_list::iterator current_; + + // The list of plugin objects. The index of an item in this list + // serves as the "handle" that we pass to the plugins. + Object_list objects_; + + // The list of regular objects whose layout has been deferred. + Deferred_layout_list deferred_layout_objects_; + + // The file currently up for claim by the plugins. + Input_file* input_file_; + struct ld_plugin_input_file plugin_input_file_; + + // TRUE after the all symbols read event; indicates that we are + // processing replacement files whose symbols should replace the + // placeholder symbols from the Pluginobj objects. + bool in_replacement_phase_; + + const General_options& options_; + Workqueue* workqueue_; + Task* task_; + Input_objects* input_objects_; + Symbol_table* symtab_; + Layout* layout_; + Dirsearch* dirpath_; + Mapfile* mapfile_; + Task_token* this_blocker_; +}; + + +// An object file claimed by a plugin. This is an abstract base class. +// The implementation is the template class Sized_pluginobj. + +class Pluginobj : public Object +{ + public: + + typedef std::vector<Symbol*> Symbols; + + Pluginobj(const std::string& name, Input_file* input_file, off_t offset, + off_t filesize); + + // Fill in the symbol resolution status for the given plugin symbols. + ld_plugin_status + get_symbol_resolution_info(int nsyms, ld_plugin_symbol* syms) const; + + // Store the incoming symbols from the plugin for later processing. + void + store_incoming_symbols(int nsyms, const struct ld_plugin_symbol* syms) + { + this->nsyms_ = nsyms; + this->syms_ = syms; + } + + // Return TRUE if the comdat group with key COMDAT_KEY from this object + // should be kept. + bool + include_comdat_group(std::string comdat_key, Layout* layout); + + // Return the filename. + const std::string& + filename() const + { return this->input_file()->filename(); } + + // Return the file descriptor. + int + descriptor() + { return this->input_file()->file().descriptor(); } + + // Return the size of the file or archive member. + off_t + filesize() + { return this->filesize_; } + + protected: + // Return TRUE if this is an object claimed by a plugin. + virtual Pluginobj* + do_pluginobj() + { return this; } + + // The number of symbols provided by the plugin. + int nsyms_; + + // The symbols provided by the plugin. + const struct ld_plugin_symbol* syms_; + + // The entries in the symbol table for the external symbols. + Symbols symbols_; + + private: + // Size of the file (or archive member). + off_t filesize_; + // Map a comdat key symbol to a boolean indicating whether the comdat + // group in this object with that key should be kept. + typedef Unordered_map<std::string, bool> Comdat_map; + Comdat_map comdat_map_; +}; + +// A plugin object, size-specific version. + +template<int size, bool big_endian> +class Sized_pluginobj : public Pluginobj +{ + public: + Sized_pluginobj(const std::string& name, Input_file* input_file, + off_t offset, off_t filesize); + + // Read the symbols. + void + do_read_symbols(Read_symbols_data*); + + // Lay out the input sections. + void + do_layout(Symbol_table*, Layout*, Read_symbols_data*); + + // Add the symbols to the symbol table. + void + do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*); + + // Get the size of a section. + uint64_t + do_section_size(unsigned int shndx); + + // Get the name of a section. + std::string + do_section_name(unsigned int shndx); + + // Return a view of the contents of a section. + Object::Location + do_section_contents(unsigned int shndx); + + // Return section flags. + uint64_t + do_section_flags(unsigned int shndx); + + // Return section entsize. + uint64_t + do_section_entsize(unsigned int shndx); + + // Return section address. + uint64_t + do_section_address(unsigned int shndx); + + // Return section type. + unsigned int + do_section_type(unsigned int shndx); + + // Return the section link field. + unsigned int + do_section_link(unsigned int shndx); + + // Return the section link field. + unsigned int + do_section_info(unsigned int shndx); + + // Return the section alignment. + uint64_t + do_section_addralign(unsigned int shndx); + + // Return the Xindex structure to use. + Xindex* + do_initialize_xindex(); + + // Get symbol counts. + void + do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const; + + // Get global symbols. + const Symbols* + do_get_global_symbols() const; + + // Add placeholder symbols from a claimed file. + ld_plugin_status + add_symbols_from_plugin(int nsyms, const ld_plugin_symbol* syms); + + protected: + + private: +}; + +// This Task handles handles the "all symbols read" event hook. +// The plugin may add additional input files at this time, which must +// be queued for reading. + +class Plugin_hook : public Task +{ + public: + Plugin_hook(const General_options& options, Input_objects* input_objects, + Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, + Mapfile* mapfile, Task_token* this_blocker, + Task_token* next_blocker) + : options_(options), input_objects_(input_objects), symtab_(symtab), + layout_(layout), dirpath_(dirpath), mapfile_(mapfile), + this_blocker_(this_blocker), next_blocker_(next_blocker) + { } + + ~Plugin_hook(); + + // The standard Task methods. + + Task_token* + is_runnable(); + + void + locks(Task_locker*); + + void + run(Workqueue*); + + std::string + get_name() const + { return "Plugin_hook"; } + + private: + const General_options& options_; + Input_objects* input_objects_; + Symbol_table* symtab_; + Layout* layout_; + Dirsearch* dirpath_; + Mapfile* mapfile_; + Task_token* this_blocker_; + Task_token* next_blocker_; +}; + +} // End namespace gold. + +#endif // !defined(GOLD_PLUGIN_H) diff --git a/binutils-2.19/gold/po/Make-in b/binutils-2.19/gold/po/Make-in index 88ce78f..3f0fc76 100644 --- a/binutils-2.19/gold/po/Make-in +++ b/binutils-2.19/gold/po/Make-in @@ -1,6 +1,6 @@ # Makefile for program source directory in GNU NLS utilities package. # Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> -# Copyright 2003, 2006 Free Software Foundation, Inc. +# Copyright 2003, 2006, 2007, 2009 Free Software Foundation, Inc. # # This file may be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License @@ -73,7 +73,7 @@ INSTOBJEXT = @INSTOBJEXT@ $(MSGFMT) -o $@ $< .po.gmo: - file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + file=`echo $* | sed 's,.*/,,'`.gmo \ && rm -f $$file && $(GMSGFMT) -o $$file $< .po.cat: @@ -88,7 +88,8 @@ all-no: $(srcdir)/$(PACKAGE).pot: $(POTFILES) $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ - --add-comments --keyword=_ --keyword=N_ \ + --add-comments -C --keyword=_ --keyword=N_ \ + --msgid-bugs-address=bug-binutils@gnu.org \ --files-from=$(srcdir)/POTFILES.in rm -f $(srcdir)/$(PACKAGE).pot mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot @@ -112,13 +113,14 @@ install: install-exec install-data install-exec: install-info: install-html: +install-pdf: install-data: install-data-@USE_NLS@ install-data-no: all install-data-yes: all if test -r $(MKINSTALLDIRS); then \ $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ else \ - $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \ + $(top_srcdir)/../mkinstalldirs $(DESTDIR)$(datadir); \ fi @catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ diff --git a/binutils-2.19/gold/powerpc.cc b/binutils-2.19/gold/powerpc.cc index 421cfdb..0eda0a9 100644 --- a/binutils-2.19/gold/powerpc.cc +++ b/binutils-2.19/gold/powerpc.cc @@ -1,6 +1,6 @@ // powerpc.cc -- powerpc target support for gold. -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by David S. Miller <davem@davemloft.net> // and David Edelsohn <edelsohn@gnu.org> @@ -37,6 +37,7 @@ #include "target-select.h" #include "tls.h" #include "errors.h" +#include "gc.h" namespace { @@ -61,10 +62,24 @@ class Target_powerpc : public Sized_target<size, big_endian> { } + // Process the relocations to determine unreferenced sections for + // garbage collection. + void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Scan the relocations to look for symbol adjustments. void - scan_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, @@ -77,7 +92,7 @@ class Target_powerpc : public Sized_target<size, big_endian> const unsigned char* plocal_symbols); // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); // Return the value to use for a dynamic which requires special // treatment. @@ -94,12 +109,12 @@ class Target_powerpc : public Sized_target<size, big_endian> bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr view_address, - section_size_type view_size); + section_size_type view_size, + const Reloc_symbol_changes*); // Scan the relocs during a relocatable link. void - scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, @@ -129,7 +144,7 @@ class Target_powerpc : public Sized_target<size, big_endian> // Return whether SYM is defined by the ABI. bool - do_is_defined_by_abi(Symbol* sym) const + do_is_defined_by_abi(const Symbol* sym) const { return strcmp(sym->name(), "___tls_get_addr") == 0; } @@ -153,8 +168,7 @@ class Target_powerpc : public Sized_target<size, big_endian> { } inline void - local(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_powerpc* target, + local(Symbol_table* symtab, Layout* layout, Target_powerpc* target, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, Output_section* output_section, @@ -162,14 +176,35 @@ class Target_powerpc : public Sized_target<size, big_endian> const elfcpp::Sym<size, big_endian>& lsym); inline void - global(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_powerpc* target, + global(Symbol_table* symtab, Layout* layout, Target_powerpc* target, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, Symbol* gsym); + inline bool + local_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_powerpc* , + Sized_relobj<size, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rela<size, big_endian>& , + unsigned int , + const elfcpp::Sym<size, big_endian>&) + { return false; } + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_powerpc* , + Sized_relobj<size, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rela<size, + big_endian>& , + unsigned int , Symbol*) + { return false; } + private: static void unsupported_reloc_local(Sized_relobj<size, big_endian>*, @@ -198,7 +233,8 @@ class Target_powerpc : public Sized_target<size, big_endian> // any warnings about this relocation. inline bool relocate(const Relocate_info<size, big_endian>*, Target_powerpc*, - size_t relnum, const elfcpp::Rela<size, big_endian>&, + Output_section*, size_t relnum, + const elfcpp::Rela<size, big_endian>&, unsigned int r_type, const Sized_symbol<size>*, const Symbol_value<size>*, unsigned char*, @@ -267,17 +303,6 @@ class Target_powerpc : public Sized_target<size, big_endian> Reloc_section* rela_dyn_section(Layout*); - // Return true if the symbol may need a COPY relocation. - // References from an executable object to non-function symbols - // defined in a dynamic object may need a COPY relocation. - bool - may_need_copy_reloc(Symbol* gsym) - { - return (!parameters->options().shared() - && gsym->is_from_dynobj() - && gsym->type() != elfcpp::STT_FUNC); - } - // Copy a relocation against a global symbol. void copy_reloc(Symbol_table* symtab, Layout* layout, @@ -335,7 +360,13 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info = "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 4 * 1024 // common_pagesize (overridable by -z common-page-size) + 4 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -352,7 +383,13 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info = "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 4 * 1024 // common_pagesize (overridable by -z common-page-size) + 4 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -369,7 +406,13 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info = "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 8 * 1024 // common_pagesize (overridable by -z common-page-size) + 8 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -386,7 +429,13 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info = "/usr/lib/ld.so.1", // dynamic_linker 0x10000000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 8 * 1024 // common_pagesize (overridable by -z common-page-size) + 8 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<int size, bool big_endian> @@ -663,9 +712,6 @@ public: typename elfcpp::Elf_types<size>::Elf_Addr addend, typename elfcpp::Elf_types<size>::Elf_Addr address) { - typedef typename elfcpp::Swap<16, true>::Valtype Valtype; - Valtype* wv = reinterpret_cast<Valtype*>(view); - Valtype val = elfcpp::Swap<16, true>::readval(wv); typename elfcpp::Elf_types<size>::Elf_Addr reloc; reloc = (psymval->value(object, addend) - address); @@ -673,10 +719,7 @@ public: reloc += 0x10000; reloc >>= 16; - val &= ~static_cast<Valtype>(0xffff); - reloc &= static_cast<Valtype>(0xffff); - - elfcpp::Swap<16, true>::writeval(wv, val | reloc); + elfcpp::Swap<16, big_endian>::writeval(view, reloc); } }; @@ -695,7 +738,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got_); + this->got_, false, false, false, false); // Create the GOT2 or TOC in the .got section. if (size == 32) @@ -704,7 +747,8 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got2_); + this->got2_, false, false, false, + false); } else { @@ -712,11 +756,13 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->toc_); + this->toc_, false, false, false, + false); } // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, this->got_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -738,7 +784,8 @@ Target_powerpc<size, big_endian>::rela_dyn_section(Layout* layout) gold_assert(layout != NULL); this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rela_dyn_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true, + false, false, false); } return this->rela_dyn_; } @@ -798,7 +845,8 @@ Output_data_plt_powerpc<size, big_endian>::Output_data_plt_powerpc(Layout* layou { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_); + elfcpp::SHF_ALLOC, this->rel_, true, false, + false, false); } template<int size, bool big_endian> @@ -922,15 +970,21 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab, // Create the GOT section first. this->got_section(symtab, layout); + // Ensure that .rela.dyn always appears before .rela.plt This is + // necessary due to how, on PowerPC and some other targets, .rela.dyn + // needs to include .rela.plt in it's range. + this->rela_dyn_section(layout); + this->plt_ = new Output_data_plt_powerpc<size, big_endian>(layout); layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR | elfcpp::SHF_WRITE), - this->plt_); + this->plt_, false, false, false, false); // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, + Symbol_table::PREDEFINED, this->plt_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -1083,6 +1137,7 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object, // error per object file. if (this->issued_non_pic_error_) return; + gold_assert(parameters->options().output_is_position_independent()); object->error(_("requires unsupported dynamic reloc; " "recompile with -fPIC")); this->issued_non_pic_error_ = true; @@ -1094,7 +1149,6 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object, template<int size, bool big_endian> inline void Target_powerpc<size, big_endian>::Scan::local( - const General_options&, Symbol_table* symtab, Layout* layout, Target_powerpc<size, big_endian>* target, @@ -1229,7 +1283,6 @@ Target_powerpc<size, big_endian>::Scan::unsupported_reloc_global( template<int size, bool big_endian> inline void Target_powerpc<size, big_endian>::Scan::global( - const General_options&, Symbol_table* symtab, Layout* layout, Target_powerpc<size, big_endian>* target, @@ -1283,7 +1336,7 @@ Target_powerpc<size, big_endian>::Scan::global( // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -1336,7 +1389,7 @@ Target_powerpc<size, big_endian>::Scan::global( flags |= Symbol::FUNCTION_CALL; if (gsym->needs_dynamic_reloc(flags)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, @@ -1420,12 +1473,45 @@ Target_powerpc<size, big_endian>::Scan::global( } } +// Process relocations for gc. + +template<int size, bool big_endian> +void +Target_powerpc<size, big_endian>::gc_process_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef Target_powerpc<size, big_endian> Powerpc; + typedef typename Target_powerpc<size, big_endian>::Scan Scan; + + gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + // Scan relocations for a section. template<int size, bool big_endian> void Target_powerpc<size, big_endian>::scan_relocs( - const General_options& options, Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, @@ -1457,8 +1543,10 @@ Target_powerpc<size, big_endian>::scan_relocs( Output_section* os = layout->add_output_section_data(".sdata", 0, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - sdata); + sdata, false, + false, false, false); symtab->define_in_output_data("_SDA_BASE_", NULL, + Symbol_table::PREDEFINED, os, 32768, 0, elfcpp::STT_OBJECT, @@ -1468,7 +1556,6 @@ Target_powerpc<size, big_endian>::scan_relocs( } gold::scan_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>( - options, symtab, layout, this, @@ -1486,38 +1573,17 @@ Target_powerpc<size, big_endian>::scan_relocs( template<int size, bool big_endian> void -Target_powerpc<size, big_endian>::do_finalize_sections(Layout* layout) +Target_powerpc<size, big_endian>::do_finalize_sections( + Layout* layout, + const Input_objects*, + Symbol_table*) { // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->plt_ != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - - odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); - } - - if (this->rela_dyn_ != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<size>::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->plt_, rel_plt, + this->rela_dyn_, true, size == 32); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. @@ -1532,6 +1598,7 @@ inline bool Target_powerpc<size, big_endian>::Relocate::relocate( const Relocate_info<size, big_endian>* relinfo, Target_powerpc* target, + Output_section*, size_t relnum, const elfcpp::Rela<size, big_endian>& rela, unsigned int r_type, @@ -1681,7 +1748,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate( break; case elfcpp::R_PPC_REL16_HA: - Reloc::rel16_lo(view, object, psymval, addend, address); + Reloc::rel16_ha(view, object, psymval, addend, address); break; case elfcpp::R_POWERPC_GOT16: @@ -1800,7 +1867,8 @@ Target_powerpc<size, big_endian>::relocate_section( bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr address, - section_size_type view_size) + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) { typedef Target_powerpc<size, big_endian> Powerpc; typedef typename Target_powerpc<size, big_endian>::Relocate Powerpc_relocate; @@ -1817,7 +1885,8 @@ Target_powerpc<size, big_endian>::relocate_section( needs_special_offset_handling, view, address, - view_size); + view_size, + reloc_symbol_changes); } // Return the size of a relocation while scanning during a relocatable @@ -1839,7 +1908,6 @@ Target_powerpc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc template<int size, bool big_endian> void Target_powerpc<size, big_endian>::scan_relocatable_relocs( - const General_options& options, Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, @@ -1860,7 +1928,6 @@ Target_powerpc<size, big_endian>::scan_relocatable_relocs( gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA, Scan_relocatable_relocs>( - options, symtab, layout, object, @@ -1934,8 +2001,6 @@ public: (big_endian ? "elf32-powerpc" : "elf32-powerpcle"))) { } - Target* instantiated_target_; - Target* do_recognize(int machine, int, int) { switch (size) @@ -1954,15 +2019,11 @@ public: return NULL; } - return do_instantiate_target(); + return this->instantiate_target(); } Target* do_instantiate_target() - { - if (this->instantiated_target_ == NULL) - this->instantiated_target_ = new Target_powerpc<size, big_endian>(); - return this->instantiated_target_; - } + { return new Target_powerpc<size, big_endian>(); } }; Target_selector_powerpc<32, true> target_selector_ppc32; diff --git a/binutils-2.19/gold/pread.c b/binutils-2.19/gold/pread.c index 1b0cf40..2f47565 100644 --- a/binutils-2.19/gold/pread.c +++ b/binutils-2.19/gold/pread.c @@ -1,6 +1,6 @@ /* pread.c -- version of pread for gold. */ -/* Copyright 2006, 2007 Free Software Foundation, Inc. +/* Copyright 2006, 2007, 2009 Free Software Foundation, Inc. Written by Ian Lance Taylor <iant@google.com>. This file is part of gold. @@ -27,11 +27,14 @@ #include "config.h" +#include <stdio.h> #include <sys/types.h> #include <unistd.h> +extern ssize_t pread (int, void *, size_t, off_t); + ssize_t -pread(int fd, void* buf, size_t count, off_t offset) +pread (int fd, void *buf, size_t count, off_t offset) { if (lseek(fd, offset, SEEK_SET) != offset) return -1; diff --git a/binutils-2.19/gold/readsyms.cc b/binutils-2.19/gold/readsyms.cc index 05c80f8..cd8814c 100644 --- a/binutils-2.19/gold/readsyms.cc +++ b/binutils-2.19/gold/readsyms.cc @@ -1,6 +1,6 @@ // readsyms.cc -- read input file symbols for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -32,6 +32,9 @@ #include "archive.h" #include "script.h" #include "readsyms.h" +#include "plugin.h" +#include "layout.h" +#include "incremental.h" namespace gold { @@ -89,6 +92,44 @@ Read_symbols::~Read_symbols() // Add_symbols task. } +// If appropriate, issue a warning about skipping an incompatible +// file. + +void +Read_symbols::incompatible_warning(const Input_argument* input_argument, + const Input_file* input_file) +{ + if (parameters->options().warn_search_mismatch()) + gold_warning("skipping incompatible %s while searching for %s", + input_file->filename().c_str(), + input_argument->file().name()); +} + +// Requeue a Read_symbols task to search for the next object with the +// same name. + +void +Read_symbols::requeue(Workqueue* workqueue, Input_objects* input_objects, + Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, + int dirindex, Mapfile* mapfile, + const Input_argument* input_argument, + Input_group* input_group, Task_token* next_blocker) +{ + // Bump the directory search index. + ++dirindex; + + // We don't need to worry about this_blocker, since we already + // reached it. However, we are removing the blocker on next_blocker + // because the calling task is completing. So we need to add a new + // blocker. Since next_blocker may be shared by several tasks, we + // need to increment the count with the workqueue lock held. + workqueue->add_blocker(next_blocker); + + workqueue->queue(new Read_symbols(input_objects, symtab, layout, dirpath, + dirindex, mapfile, input_argument, + input_group, NULL, next_blocker)); +} + // Return whether a Read_symbols task is runnable. We can read an // ordinary input file immediately. For an archive specified using // -l, we have to wait until the search path is complete. @@ -138,7 +179,7 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) } Input_file* input_file = new Input_file(&this->input_argument_->file()); - if (!input_file->open(this->options_, *this->dirpath_, this)) + if (!input_file->open(*this->dirpath_, this, &this->dirindex_)) return false; // Read enough of the file to pick up the entire ELF header. @@ -152,75 +193,39 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) return false; } - int read_size = elfcpp::Elf_sizes<64>::ehdr_size; - if (filesize < read_size) - read_size = filesize; - - const unsigned char* ehdr = input_file->file().get_view(0, 0, read_size, - true, false); - - if (read_size >= 4) - { - static unsigned char elfmagic[4] = - { - elfcpp::ELFMAG0, elfcpp::ELFMAG1, - elfcpp::ELFMAG2, elfcpp::ELFMAG3 - }; - if (memcmp(ehdr, elfmagic, 4) == 0) - { - // This is an ELF object. - - Object* obj = make_elf_object(input_file->filename(), - input_file, 0, ehdr, read_size); - if (obj == NULL) - return false; - - Read_symbols_data* sd = new Read_symbols_data; - obj->read_symbols(sd); - - // Opening the file locked it, so now we need to unlock it. - // We need to unlock it before queuing the Add_symbols task, - // because the workqueue doesn't know about our lock on the - // file. If we queue the Add_symbols task first, it will be - // stuck on the end of the file lock, but since the - // workqueue doesn't know about that lock, it will never - // release the Add_symbols task. - - input_file->file().unlock(this); - - // We use queue_next because everything is cached for this - // task to run right away if possible. - - workqueue->queue_next(new Add_symbols(this->input_objects_, - this->symtab_, this->layout_, - obj, sd, - this->this_blocker_, - this->next_blocker_)); - - return true; - } - } + const unsigned char* ehdr; + int read_size; + bool is_elf = is_elf_object(input_file, 0, &ehdr, &read_size); if (read_size >= Archive::sarmag) { bool is_thin_archive = memcmp(ehdr, Archive::armagt, Archive::sarmag) == 0; - if (is_thin_archive + if (is_thin_archive || memcmp(ehdr, Archive::armag, Archive::sarmag) == 0) { // This is an archive. Archive* arch = new Archive(this->input_argument_->file().name(), input_file, is_thin_archive, this->dirpath_, this); - arch->setup(this->input_objects_); - + arch->setup(); + + if (this->layout_->incremental_inputs()) + { + const Input_argument* ia = this->input_argument_; + this->layout_->incremental_inputs()->report_archive(ia, arch); + } + // Unlock the archive so it can be used in the next task. arch->unlock(this); workqueue->queue_next(new Add_archive_symbols(this->symtab_, this->layout_, this->input_objects_, + this->dirpath_, + this->dirindex_, this->mapfile_, + this->input_argument_, arch, this->input_group_, this->this_blocker_, @@ -229,16 +234,107 @@ Read_symbols::do_read_symbols(Workqueue* workqueue) } } + if (parameters->options().has_plugins()) + { + Pluginobj* obj = parameters->options().plugins()->claim_file(input_file, + 0, filesize); + if (obj != NULL) + { + // The input file was claimed by a plugin, and its symbols + // have been provided by the plugin. + + // We are done with the file at this point, so unlock it. + obj->unlock(this); + + workqueue->queue_next(new Add_symbols(this->input_objects_, + this->symtab_, + this->layout_, + this->dirpath_, + this->dirindex_, + this->mapfile_, + this->input_argument_, + this->input_group_, + obj, + NULL, + this->this_blocker_, + this->next_blocker_)); + return true; + } + } + + if (is_elf) + { + // This is an ELF object. + + bool unconfigured = false; + bool* punconfigured = (input_file->will_search_for() + ? &unconfigured + : NULL); + Object* obj = make_elf_object(input_file->filename(), + input_file, 0, ehdr, read_size, + punconfigured); + if (obj == NULL) + { + if (unconfigured) + { + Read_symbols::incompatible_warning(this->input_argument_, + input_file); + input_file->file().release(); + input_file->file().unlock(this); + delete input_file; + ++this->dirindex_; + return this->do_read_symbols(workqueue); + } + return false; + } + + Read_symbols_data* sd = new Read_symbols_data; + obj->read_symbols(sd); + + if (this->layout_->incremental_inputs()) + { + const Input_argument* ia = this->input_argument_; + this->layout_->incremental_inputs()->report_object(ia, obj); + } + + // Opening the file locked it, so now we need to unlock it. We + // need to unlock it before queuing the Add_symbols task, + // because the workqueue doesn't know about our lock on the + // file. If we queue the Add_symbols task first, it will be + // stuck on the end of the file lock, but since the workqueue + // doesn't know about that lock, it will never release the + // Add_symbols task. + + input_file->file().unlock(this); + + // We use queue_next because everything is cached for this + // task to run right away if possible. + + workqueue->queue_next(new Add_symbols(this->input_objects_, + this->symtab_, this->layout_, + this->dirpath_, + this->dirindex_, + this->mapfile_, + this->input_argument_, + this->input_group_, + obj, + sd, + this->this_blocker_, + this->next_blocker_)); + + return true; + } + // Queue up a task to try to parse this file as a script. We use a // separate task so that the script will be read in order with other // objects named on the command line. Also so that we don't try to // read multiple scripts simultaneously, which could lead to // unpredictable changes to the General_options structure. - workqueue->queue_soon(new Read_script(this->options_, - this->symtab_, + workqueue->queue_soon(new Read_script(this->symtab_, this->layout_, this->dirpath_, + this->dirindex_, this->input_objects_, this->mapfile_, this->input_group_, @@ -264,6 +360,19 @@ Read_symbols::do_group(Workqueue* workqueue) const Input_file_group* group = this->input_argument_->group(); Task_token* this_blocker = this->this_blocker_; + Finish_group* finish_group = new Finish_group(this->input_objects_, + this->symtab_, + this->layout_, + this->mapfile_, + input_group, + this->next_blocker_); + + Task_token* next_blocker = new Task_token(true); + next_blocker->add_blocker(); + workqueue->queue_soon(new Start_group(this->symtab_, finish_group, + this_blocker, next_blocker)); + this_blocker = next_blocker; + for (Input_file_group::const_iterator p = group->begin(); p != group->end(); ++p) @@ -271,26 +380,19 @@ Read_symbols::do_group(Workqueue* workqueue) const Input_argument* arg = &*p; gold_assert(arg->is_file()); - Task_token* next_blocker = new Task_token(true); + next_blocker = new Task_token(true); next_blocker->add_blocker(); - workqueue->queue_soon(new Read_symbols(this->options_, - this->input_objects_, + workqueue->queue_soon(new Read_symbols(this->input_objects_, this->symtab_, this->layout_, - this->dirpath_, this->mapfile_, - arg, input_group, + this->dirpath_, this->dirindex_, + this->mapfile_, arg, input_group, this_blocker, next_blocker)); this_blocker = next_blocker; } - const int saw_undefined = this->symtab_->saw_undefined(); - workqueue->queue_soon(new Finish_group(this->input_objects_, - this->symtab_, - this->layout_, - this->mapfile_, - input_group, - saw_undefined, - this_blocker, - this->next_blocker_)); + finish_group->set_blocker(this_blocker); + + workqueue->queue_soon(finish_group); } // Return a debugging name for a Read_symbols task. @@ -303,6 +405,8 @@ Read_symbols::get_name() const std::string ret("Read_symbols "); if (this->input_argument_->file().is_lib()) ret += "-l"; + else if (this->input_argument_->file().is_searched_file()) + ret += "-l:"; ret += this->input_argument_->file().name(); return ret; } @@ -357,21 +461,62 @@ Add_symbols::locks(Task_locker* tl) void Add_symbols::run(Workqueue*) { + Pluginobj* pluginobj = this->object_->pluginobj(); + if (pluginobj != NULL) + { + this->object_->add_symbols(this->symtab_, this->sd_, this->layout_); + return; + } + if (!this->input_objects_->add_object(this->object_)) { - // FIXME: We need to close the descriptor here. + this->object_->release(); delete this->object_; } else { this->object_->layout(this->symtab_, this->layout_, this->sd_); - this->object_->add_symbols(this->symtab_, this->sd_); + this->object_->add_symbols(this->symtab_, this->sd_, this->layout_); this->object_->release(); } delete this->sd_; this->sd_ = NULL; } +// Class Start_group. + +Start_group::~Start_group() +{ + if (this->this_blocker_ != NULL) + delete this->this_blocker_; + // next_blocker_ is deleted by the task associated with the first + // file in the group. +} + +// We need to wait for THIS_BLOCKER_ and unblock NEXT_BLOCKER_. + +Task_token* +Start_group::is_runnable() +{ + if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) + return this->this_blocker_; + return NULL; +} + +void +Start_group::locks(Task_locker* tl) +{ + tl->add(this, this->next_blocker_); +} + +// Store the number of undefined symbols we see now. + +void +Start_group::run(Workqueue*) +{ + this->finish_group_->set_saw_undefined(this->symtab_->saw_undefined()); +} + // Class Finish_group. Finish_group::~Finish_group() @@ -403,7 +548,7 @@ Finish_group::locks(Task_locker* tl) void Finish_group::run(Workqueue*) { - int saw_undefined = this->saw_undefined_; + size_t saw_undefined = this->saw_undefined_; while (saw_undefined != this->symtab_->saw_undefined()) { saw_undefined = this->symtab_->saw_undefined(); @@ -461,8 +606,8 @@ void Read_script::run(Workqueue* workqueue) { bool used_next_blocker; - if (!read_input_script(workqueue, this->options_, this->symtab_, - this->layout_, this->dirpath_, this->input_objects_, + if (!read_input_script(workqueue, this->symtab_, this->layout_, + this->dirpath_, this->dirindex_, this->input_objects_, this->mapfile_, this->input_group_, this->input_argument_, this->input_file_, this->next_blocker_, &used_next_blocker)) @@ -488,6 +633,8 @@ Read_script::get_name() const std::string ret("Read_script "); if (this->input_argument_->file().is_lib()) ret += "-l"; + else if (this->input_argument_->file().is_searched_file()) + ret += "-l:"; ret += this->input_argument_->file().name(); return ret; } diff --git a/binutils-2.19/gold/readsyms.h b/binutils-2.19/gold/readsyms.h index f93d6db..626cb38 100644 --- a/binutils-2.19/gold/readsyms.h +++ b/binutils-2.19/gold/readsyms.h @@ -1,6 +1,6 @@ // readsyms.h -- read input file symbols for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -35,6 +35,7 @@ class Input_objects; class Symbol_table; class Input_group; class Archive; +class Finish_group; // This Task is responsible for reading the symbols from an input // file. This also includes reading the relocations so that we can @@ -54,19 +55,31 @@ class Read_symbols : public Task // one has completed; it will be NULL for the first task. // NEXT_BLOCKER is used to block the next input file from adding // symbols. - Read_symbols(const General_options& options, Input_objects* input_objects, - Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, + Read_symbols(Input_objects* input_objects, Symbol_table* symtab, + Layout* layout, Dirsearch* dirpath, int dirindex, Mapfile* mapfile, const Input_argument* input_argument, Input_group* input_group, Task_token* this_blocker, Task_token* next_blocker) - : options_(options), input_objects_(input_objects), symtab_(symtab), - layout_(layout), dirpath_(dirpath), mapfile_(mapfile), + : input_objects_(input_objects), symtab_(symtab), layout_(layout), + dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile), input_argument_(input_argument), input_group_(input_group), this_blocker_(this_blocker), next_blocker_(next_blocker) { } ~Read_symbols(); + // If appropriate, issue a warning about skipping an incompatible + // object. + static void + incompatible_warning(const Input_argument*, const Input_file*); + + // Requeue a Read_symbols task to search for the next object with + // the same name. + static void + requeue(Workqueue*, Input_objects*, Symbol_table*, Layout*, Dirsearch*, + int dirindex, Mapfile*, const Input_argument*, Input_group*, + Task_token* next_blocker); + // The standard Task methods. Task_token* @@ -90,11 +103,11 @@ class Read_symbols : public Task bool do_read_symbols(Workqueue*); - const General_options& options_; Input_objects* input_objects_; Symbol_table* symtab_; Layout* layout_; Dirsearch* dirpath_; + int dirindex_; Mapfile* mapfile_; const Input_argument* input_argument_; Input_group* input_group_; @@ -113,10 +126,14 @@ class Add_symbols : public Task // one for the previous input file. NEXT_BLOCKER is used to prevent // the next task from running. Add_symbols(Input_objects* input_objects, Symbol_table* symtab, - Layout* layout, Object* object, + Layout* layout, Dirsearch* dirpath, int dirindex, + Mapfile* mapfile, const Input_argument* input_argument, + Input_group* input_group, Object* object, Read_symbols_data* sd, Task_token* this_blocker, Task_token* next_blocker) : input_objects_(input_objects), symtab_(symtab), layout_(layout), + dirpath_(dirpath), dirindex_(dirindex), mapfile_(mapfile), + input_argument_(input_argument), input_group_(input_group), object_(object), sd_(sd), this_blocker_(this_blocker), next_blocker_(next_blocker) { } @@ -142,6 +159,11 @@ private: Input_objects* input_objects_; Symbol_table* symtab_; Layout* layout_; + Dirsearch* dirpath_; + int dirindex_; + Mapfile* mapfile_; + const Input_argument* input_argument_; + Input_group* input_group_; Object* object_; Read_symbols_data* sd_; Task_token* this_blocker_; @@ -179,6 +201,43 @@ class Input_group Archives archives_; }; +// This class starts the handling of a group. It exists only to pick +// up the number of undefined symbols at that point, so that we only +// run back through the group if we saw a new undefined symbol. + +class Start_group : public Task +{ + public: + Start_group(Symbol_table* symtab, Finish_group* finish_group, + Task_token* this_blocker, Task_token* next_blocker) + : symtab_(symtab), finish_group_(finish_group), + this_blocker_(this_blocker), next_blocker_(next_blocker) + { } + + ~Start_group(); + + // The standard Task methods. + + Task_token* + is_runnable(); + + void + locks(Task_locker*); + + void + run(Workqueue*); + + std::string + get_name() const + { return "Start_group"; } + + private: + Symbol_table* symtab_; + Finish_group* finish_group_; + Task_token* this_blocker_; + Task_token* next_blocker_; +}; + // This class is used to finish up handling a group. It is just a // closure. @@ -187,16 +246,28 @@ class Finish_group : public Task public: Finish_group(Input_objects* input_objects, Symbol_table* symtab, Layout* layout, Mapfile* mapfile, Input_group* input_group, - int saw_undefined, Task_token* this_blocker, Task_token* next_blocker) : input_objects_(input_objects), symtab_(symtab), layout_(layout), mapfile_(mapfile), input_group_(input_group), - saw_undefined_(saw_undefined), this_blocker_(this_blocker), - next_blocker_(next_blocker) + saw_undefined_(0), this_blocker_(NULL), next_blocker_(next_blocker) { } ~Finish_group(); + // Set the number of undefined symbols when we start processing the + // group. This is called by the Start_group task. + void + set_saw_undefined(size_t saw_undefined) + { this->saw_undefined_ = saw_undefined; } + + // Set the blocker to use for this task. + void + set_blocker(Task_token* this_blocker) + { + gold_assert(this->this_blocker_ == NULL); + this->this_blocker_ = this_blocker; + } + // The standard Task methods. Task_token* @@ -218,7 +289,7 @@ class Finish_group : public Task Layout* layout_; Mapfile* mapfile_; Input_group* input_group_; - int saw_undefined_; + size_t saw_undefined_; Task_token* this_blocker_; Task_token* next_blocker_; }; @@ -230,13 +301,12 @@ class Finish_group : public Task class Read_script : public Task { public: - Read_script(const General_options& options, Symbol_table* symtab, - Layout* layout, Dirsearch* dirpath, Input_objects* input_objects, - Mapfile* mapfile, Input_group* input_group, - const Input_argument* input_argument, + Read_script(Symbol_table* symtab, Layout* layout, Dirsearch* dirpath, + int dirindex, Input_objects* input_objects, Mapfile* mapfile, + Input_group* input_group, const Input_argument* input_argument, Input_file* input_file, Task_token* this_blocker, Task_token* next_blocker) - : options_(options), symtab_(symtab), layout_(layout), dirpath_(dirpath), + : symtab_(symtab), layout_(layout), dirpath_(dirpath), dirindex_(dirindex), input_objects_(input_objects), mapfile_(mapfile), input_group_(input_group), input_argument_(input_argument), input_file_(input_file), this_blocker_(this_blocker), @@ -260,10 +330,10 @@ class Read_script : public Task get_name() const; private: - const General_options& options_; Symbol_table* symtab_; Layout* layout_; Dirsearch* dirpath_; + int dirindex_; Input_objects* input_objects_; Mapfile* mapfile_; Input_group* input_group_; diff --git a/binutils-2.19/gold/reduced_debug_output.cc b/binutils-2.19/gold/reduced_debug_output.cc index d195cfd..5bc8053 100644 --- a/binutils-2.19/gold/reduced_debug_output.cc +++ b/binutils-2.19/gold/reduced_debug_output.cc @@ -27,75 +27,13 @@ #include "dwarf.h" #include "dwarf_reader.h" #include "reduced_debug_output.h" +#include "int_encoding.h" #include <vector> namespace gold { -void -write_unsigned_LEB_128(std::vector<unsigned char>* buffer, uint64_t value) -{ - do - { - unsigned char current_byte = value & 0x7f; - value >>= 7; - if (value != 0) - { - current_byte |= 0x80; - } - buffer->push_back(current_byte); - } - while (value != 0); -} - -size_t -get_length_as_unsigned_LEB_128(uint64_t value) -{ - size_t length = 0; - do - { - unsigned char current_byte = value & 0x7f; - value >>= 7; - if (value != 0) - { - current_byte |= 0x80; - } - length++; - } - while (value != 0); - return length; -} - -template <int valsize> -void Insert_into_vector(std::vector<unsigned char>* destination, - typename elfcpp::Valtype_base<valsize>::Valtype value) -{ - union - { - unsigned char buffer[valsize / 8]; - long long align; - } u; - if (parameters->target().is_big_endian()) - elfcpp::Swap<valsize, true>::writeval(u.buffer, value); - else - elfcpp::Swap<valsize, false>::writeval(u.buffer, value); - destination->insert(destination->end(), u.buffer, u.buffer + valsize / 8); -} - -template <int valsize> -typename elfcpp::Valtype_base<valsize>::Valtype -read_from_pointer(unsigned char** source) -{ - typename elfcpp::Valtype_base<valsize>::Valtype return_value; - if (parameters->target().is_big_endian()) - return_value = elfcpp::Swap_unaligned<valsize, true>::readval(*source); - else - return_value = elfcpp::Swap_unaligned<valsize, false>::readval(*source); - *source += valsize / 8; - return return_value; -} - // Given a pointer to the beginning of a die and the beginning of the associated // abbreviation fills in die_end with the end of the information entry. If // successful returns true. Get_die_end also takes a pointer to the end of the @@ -356,15 +294,15 @@ void Output_reduced_debug_info_section::set_final_data_size() return; } - Insert_into_vector<32>(&this->data_, 0xFFFFFFFF); - Insert_into_vector<32>(&this->data_, 0); - Insert_into_vector<64>( + insert_into_vector<32>(&this->data_, 0xFFFFFFFF); + insert_into_vector<32>(&this->data_, 0); + insert_into_vector<64>( &this->data_, (11 + get_length_as_unsigned_LEB_128(abbreviation_number) + die_end - debug_info)); - Insert_into_vector<16>(&this->data_, version); - Insert_into_vector<64>(&this->data_, 0); - Insert_into_vector<8>(&this->data_, address_size); + insert_into_vector<16>(&this->data_, version); + insert_into_vector<64>(&this->data_, 0); + insert_into_vector<8>(&this->data_, address_size); write_unsigned_LEB_128(&this->data_, abbreviation_number); this->data_.insert(this->data_.end(), debug_info, die_end); } @@ -398,13 +336,13 @@ void Output_reduced_debug_info_section::set_final_data_size() return; } - Insert_into_vector<32>( + insert_into_vector<32>( &this->data_, (7 + get_length_as_unsigned_LEB_128(abbreviation_number) + die_end - debug_info)); - Insert_into_vector<16>(&this->data_, version); - Insert_into_vector<32>(&this->data_, 0); - Insert_into_vector<8>(&this->data_, address_size); + insert_into_vector<16>(&this->data_, version); + insert_into_vector<32>(&this->data_, 0); + insert_into_vector<8>(&this->data_, address_size); write_unsigned_LEB_128(&this->data_, abbreviation_number); this->data_.insert(this->data_.end(), debug_info, die_end); } diff --git a/binutils-2.19/gold/reduced_debug_output.h b/binutils-2.19/gold/reduced_debug_output.h index bd8da22..d168228 100644 --- a/binutils-2.19/gold/reduced_debug_output.h +++ b/binutils-2.19/gold/reduced_debug_output.h @@ -64,7 +64,7 @@ class Output_reduced_debug_abbrev_section : public Output_section void failed(std::string reason) { - gold_warning(reason.c_str()); + gold_warning("%s", reason.c_str()); failed_ = true; } @@ -110,7 +110,7 @@ class Output_reduced_debug_info_section : public Output_section void failed(std::string reason) { - gold_warning(reason.c_str()); + gold_warning("%s", reason.c_str()); this->failed_ = true; } diff --git a/binutils-2.19/gold/reloc.cc b/binutils-2.19/gold/reloc.cc index daa0ea8..0061059 100644 --- a/binutils-2.19/gold/reloc.cc +++ b/binutils-2.19/gold/reloc.cc @@ -1,6 +1,6 @@ // reloc.cc -- relocate input files for gold. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -31,6 +31,7 @@ #include "object.h" #include "target-reloc.h" #include "reloc.h" +#include "icf.h" namespace gold { @@ -62,11 +63,28 @@ Read_relocs::run(Workqueue* workqueue) { Read_relocs_data *rd = new Read_relocs_data; this->object_->read_relocs(rd); + this->object_->set_relocs_data(rd); this->object_->release(); - workqueue->queue_next(new Scan_relocs(this->options_, this->symtab_, - this->layout_, this->object_, rd, - this->symtab_lock_, this->blocker_)); + // If garbage collection or identical comdat folding is desired, we + // process the relocs first before scanning them. Scanning of relocs is + // done only after garbage or identical sections is identified. + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + workqueue->queue_next(new Gc_process_relocs(this->symtab_, + this->layout_, + this->object_, rd, + this->this_blocker_, + this->next_blocker_)); + } + else + { + workqueue->queue_next(new Scan_relocs(this->symtab_, this->layout_, + this->object_, rd, + this->this_blocker_, + this->next_blocker_)); + } } // Return a debugging name for the task. @@ -77,8 +95,59 @@ Read_relocs::get_name() const return "Read_relocs " + this->object_->name(); } +// Gc_process_relocs methods. + +Gc_process_relocs::~Gc_process_relocs() +{ + if (this->this_blocker_ != NULL) + delete this->this_blocker_; +} + +// These tasks process the relocations read by Read_relocs and +// determine which sections are referenced and which are garbage. +// This task is done only when --gc-sections is used. This is blocked +// by THIS_BLOCKER_. It unblocks NEXT_BLOCKER_. + +Task_token* +Gc_process_relocs::is_runnable() +{ + if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) + return this->this_blocker_; + if (this->object_->is_locked()) + return this->object_->token(); + return NULL; +} + +void +Gc_process_relocs::locks(Task_locker* tl) +{ + tl->add(this, this->object_->token()); + tl->add(this, this->next_blocker_); +} + +void +Gc_process_relocs::run(Workqueue*) +{ + this->object_->gc_process_relocs(this->symtab_, this->layout_, this->rd_); + this->object_->release(); +} + +// Return a debugging name for the task. + +std::string +Gc_process_relocs::get_name() const +{ + return "Gc_process_relocs " + this->object_->name(); +} + // Scan_relocs methods. +Scan_relocs::~Scan_relocs() +{ + if (this->this_blocker_ != NULL) + delete this->this_blocker_; +} + // These tasks scan the relocations read by Read_relocs and mark up // the symbol table to indicate which relocations are required. We // use a lock on the symbol table to keep them from interfering with @@ -87,8 +156,8 @@ Read_relocs::get_name() const Task_token* Scan_relocs::is_runnable() { - if (!this->symtab_lock_->is_writable()) - return this->symtab_lock_; + if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked()) + return this->this_blocker_; if (this->object_->is_locked()) return this->object_->token(); return NULL; @@ -101,8 +170,7 @@ void Scan_relocs::locks(Task_locker* tl) { tl->add(this, this->object_->token()); - tl->add(this, this->symtab_lock_); - tl->add(this, this->blocker_); + tl->add(this, this->next_blocker_); } // Scan the relocs. @@ -110,8 +178,7 @@ Scan_relocs::locks(Task_locker* tl) void Scan_relocs::run(Workqueue*) { - this->object_->scan_relocs(this->options_, this->symtab_, this->layout_, - this->rd_); + this->object_->scan_relocs(this->symtab_, this->layout_, this->rd_); this->object_->release(); delete this->rd_; this->rd_ = NULL; @@ -160,8 +227,7 @@ Relocate_task::locks(Task_locker* tl) void Relocate_task::run(Workqueue*) { - this->object_->relocate(this->options_, this->symtab_, this->layout_, - this->of_); + this->object_->relocate(this->symtab_, this->layout_, this->of_); // This is normally the last thing we will do with an object, so // uncache all views. @@ -225,7 +291,9 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) // PLT sections. Relocations for sections which are not // allocated (typically debugging sections) should not add new // GOT and PLT entries. So we skip them unless this is a - // relocatable link or we need to emit relocations. + // relocatable link or we need to emit relocations. FIXME: What + // should we do if a linker script maps a section with SHF_ALLOC + // clear to a section with SHF_ALLOC set? typename This::Shdr secshdr(pshdrs + shndx * This::shdr_size); bool is_section_allocated = ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0); @@ -274,7 +342,7 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) sr.sh_type = sh_type; sr.reloc_count = reloc_count; sr.output_section = os; - sr.needs_special_offset_handling = out_offsets[shndx] == -1U; + sr.needs_special_offset_handling = out_offsets[shndx] == invalid_address; sr.is_data_section_allocated = is_section_allocated; } @@ -296,17 +364,58 @@ Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd) } } +// Process the relocs to generate mappings from source sections to referenced +// sections. This is used during garbage colletion to determine garbage +// sections. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd) +{ + Sized_target<size, big_endian>* target = + parameters->sized_target<size, big_endian>(); + + const unsigned char* local_symbols; + if (rd->local_symbols == NULL) + local_symbols = NULL; + else + local_symbols = rd->local_symbols->data(); + + for (Read_relocs_data::Relocs_list::iterator p = rd->relocs.begin(); + p != rd->relocs.end(); + ++p) + { + if (!parameters->options().relocatable()) + { + // As noted above, when not generating an object file, we + // only scan allocated sections. We may see a non-allocated + // section here if we are emitting relocs. + if (p->is_data_section_allocated) + target->gc_process_relocs(symtab, layout, this, + p->data_shndx, p->sh_type, + p->contents->data(), p->reloc_count, + p->output_section, + p->needs_special_offset_handling, + this->local_symbol_count_, + local_symbols); + } + } +} + + // Scan the relocs and adjust the symbol table. This looks for // relocations which require GOT/PLT/COPY relocations. template<int size, bool big_endian> void -Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options, - Symbol_table* symtab, +Sized_relobj<size, big_endian>::do_scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd) { - Sized_target<size, big_endian>* target = this->sized_target(); + Sized_target<size, big_endian>* target = + parameters->sized_target<size, big_endian>(); const unsigned char* local_symbols; if (rd->local_symbols == NULL) @@ -318,27 +427,36 @@ Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options, p != rd->relocs.end(); ++p) { + // When garbage collection is on, unreferenced sections are not included + // in the link that would have been included normally. This is known only + // after Read_relocs hence this check has to be done again. + if (parameters->options().gc_sections() + || parameters->options().icf_enabled()) + { + if (p->output_section == NULL) + continue; + } if (!parameters->options().relocatable()) { // As noted above, when not generating an object file, we // only scan allocated sections. We may see a non-allocated // section here if we are emitting relocs. if (p->is_data_section_allocated) - target->scan_relocs(options, symtab, layout, this, p->data_shndx, + target->scan_relocs(symtab, layout, this, p->data_shndx, p->sh_type, p->contents->data(), p->reloc_count, p->output_section, p->needs_special_offset_handling, this->local_symbol_count_, local_symbols); if (parameters->options().emit_relocs()) - this->emit_relocs_scan(options, symtab, layout, local_symbols, p); + this->emit_relocs_scan(symtab, layout, local_symbols, p); } else { Relocatable_relocs* rr = this->relocatable_relocs(p->reloc_shndx); gold_assert(rr != NULL); rr->set_reloc_count(p->reloc_count); - target->scan_relocatable_relocs(options, symtab, layout, this, + target->scan_relocatable_relocs(symtab, layout, this, p->data_shndx, p->sh_type, p->contents->data(), p->reloc_count, @@ -368,7 +486,7 @@ class Emit_relocs_strategy public: // A local non-section symbol. inline Relocatable_relocs::Reloc_strategy - local_non_section_strategy(unsigned int, Relobj*) + local_non_section_strategy(unsigned int, Relobj*, unsigned int) { return Relocatable_relocs::RELOC_COPY; } // A local section symbol. @@ -400,7 +518,6 @@ class Emit_relocs_strategy template<int size, bool big_endian> void Sized_relobj<size, big_endian>::emit_relocs_scan( - const General_options& options, Symbol_table* symtab, Layout* layout, const unsigned char* plocal_syms, @@ -411,14 +528,13 @@ Sized_relobj<size, big_endian>::emit_relocs_scan( rr->set_reloc_count(p->reloc_count); if (p->sh_type == elfcpp::SHT_REL) - this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(options, symtab, layout, + this->emit_relocs_scan_reltype<elfcpp::SHT_REL>(symtab, layout, plocal_syms, p, rr); else { gold_assert(p->sh_type == elfcpp::SHT_RELA); - this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(options, symtab, - layout, plocal_syms, p, - rr); + this->emit_relocs_scan_reltype<elfcpp::SHT_RELA>(symtab, layout, + plocal_syms, p, rr); } } @@ -429,7 +545,6 @@ template<int size, bool big_endian> template<int sh_type> void Sized_relobj<size, big_endian>::emit_relocs_scan_reltype( - const General_options& options, Symbol_table* symtab, Layout* layout, const unsigned char* plocal_syms, @@ -438,7 +553,6 @@ Sized_relobj<size, big_endian>::emit_relocs_scan_reltype( { scan_relocatable_relocs<size, big_endian, sh_type, Emit_relocs_strategy<sh_type> >( - options, symtab, layout, this, @@ -456,8 +570,7 @@ Sized_relobj<size, big_endian>::emit_relocs_scan_reltype( template<int size, bool big_endian> void -Sized_relobj<size, big_endian>::do_relocate(const General_options& options, - const Symbol_table* symtab, +Sized_relobj<size, big_endian>::do_relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of) { @@ -483,7 +596,7 @@ Sized_relobj<size, big_endian>::do_relocate(const General_options& options, // Apply relocations. - this->relocate_sections(options, symtab, layout, pshdrs, &views); + this->relocate_sections(symtab, layout, pshdrs, &views); // After we've done the relocations, we release the hash tables, // since we no longer need them. @@ -586,8 +699,8 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, // In the normal case, this input section is simply mapped to // the output section at offset OUTPUT_OFFSET. - // However, if OUTPUT_OFFSET == -1U, then input data is handled - // specially--e.g., a .eh_frame section. The relocation + // However, if OUTPUT_OFFSET == INVALID_ADDRESS, then input data is + // handled specially--e.g., a .eh_frame section. The relocation // routines need to check for each reloc where it should be // applied. For this case, we need an input/output view for the // entire contents of the section in the output file. We don't @@ -619,7 +732,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, off_t view_start; section_size_type view_size; - if (output_offset != -1U) + if (output_offset != invalid_address) { view_start = output_section_offset + output_offset; view_size = convert_to_section_size_type(shdr.get_sh_size()); @@ -633,7 +746,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, if (view_size == 0) continue; - gold_assert(output_offset == -1U + gold_assert(output_offset == invalid_address || output_offset + view_size <= output_section_size); unsigned char* view; @@ -641,7 +754,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, { unsigned char* buffer = os->postprocessing_buffer(); view = buffer + view_start; - if (output_offset != -1U) + if (output_offset != invalid_address) { off_t sh_offset = shdr.get_sh_offset(); if (!rm.empty() && rm.back().file_offset > sh_offset) @@ -652,7 +765,7 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, } else { - if (output_offset == -1U) + if (output_offset == invalid_address) view = of->get_input_output_view(view_start, view_size); else { @@ -667,11 +780,11 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, pvs->view = view; pvs->address = os->address(); - if (output_offset != -1U) + if (output_offset != invalid_address) pvs->address += output_offset; pvs->offset = view_start; pvs->view_size = view_size; - pvs->is_input_output_view = output_offset == -1U; + pvs->is_input_output_view = output_offset == invalid_address; pvs->is_postprocessing_view = os->requires_postprocessing(); } @@ -689,21 +802,20 @@ Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs, template<int size, bool big_endian> void -Sized_relobj<size, big_endian>::relocate_sections( - const General_options& options, +Sized_relobj<size, big_endian>::do_relocate_sections( const Symbol_table* symtab, const Layout* layout, const unsigned char* pshdrs, Views* pviews) { unsigned int shnum = this->shnum(); - Sized_target<size, big_endian>* target = this->sized_target(); + Sized_target<size, big_endian>* target = + parameters->sized_target<size, big_endian>(); const Output_sections& out_sections(this->output_sections()); const std::vector<Address>& out_offsets(this->section_offsets_); Relocate_info<size, big_endian> relinfo; - relinfo.options = &options; relinfo.symtab = symtab; relinfo.layout = layout; relinfo.object = this; @@ -717,6 +829,10 @@ Sized_relobj<size, big_endian>::relocate_sections( if (sh_type != elfcpp::SHT_REL && sh_type != elfcpp::SHT_RELA) continue; + off_t sh_size = shdr.get_sh_size(); + if (sh_size == 0) + continue; + unsigned int index = this->adjust_shndx(shdr.get_sh_info()); if (index >= this->shnum()) { @@ -746,7 +862,6 @@ Sized_relobj<size, big_endian>::relocate_sections( continue; } - off_t sh_size = shdr.get_sh_size(); const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(), sh_size, true, false); @@ -772,44 +887,43 @@ Sized_relobj<size, big_endian>::relocate_sections( continue; } - gold_assert(output_offset != -1U + gold_assert(output_offset != invalid_address || this->relocs_must_follow_section_writes()); relinfo.reloc_shndx = i; + relinfo.reloc_shdr = p; relinfo.data_shndx = index; + relinfo.data_shdr = pshdrs + index * This::shdr_size; + unsigned char* view = (*pviews)[index].view; + Address address = (*pviews)[index].address; + section_size_type view_size = (*pviews)[index].view_size; + + Reloc_symbol_changes* reloc_map = NULL; + if (this->uses_split_stack() && output_offset != invalid_address) + { + typename This::Shdr data_shdr(pshdrs + index * This::shdr_size); + if ((data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0) + this->split_stack_adjust(symtab, pshdrs, sh_type, index, + prelocs, reloc_count, view, view_size, + &reloc_map); + } + if (!parameters->options().relocatable()) { - target->relocate_section(&relinfo, - sh_type, - prelocs, - reloc_count, - os, - output_offset == -1U, - (*pviews)[index].view, - (*pviews)[index].address, - (*pviews)[index].view_size); + target->relocate_section(&relinfo, sh_type, prelocs, reloc_count, os, + output_offset == invalid_address, + view, address, view_size, reloc_map); if (parameters->options().emit_relocs()) this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count, - os, output_offset, - (*pviews)[index].view, - (*pviews)[index].address, - (*pviews)[index].view_size, - (*pviews)[i].view, - (*pviews)[i].view_size); + os, output_offset, view, address, view_size, + (*pviews)[i].view, (*pviews)[i].view_size); } else { Relocatable_relocs* rr = this->relocatable_relocs(i); - target->relocate_for_relocatable(&relinfo, - sh_type, - prelocs, - reloc_count, - os, - output_offset, - rr, - (*pviews)[index].view, - (*pviews)[index].address, - (*pviews)[index].view_size, + target->relocate_for_relocatable(&relinfo, sh_type, prelocs, + reloc_count, os, output_offset, rr, + view, address, view_size, (*pviews)[i].view, (*pviews)[i].view_size); } @@ -914,6 +1028,244 @@ Sized_relobj<size, big_endian>::free_input_to_output_maps() } } +// If an object was compiled with -fsplit-stack, this is called to +// check whether any relocations refer to functions defined in objects +// which were not compiled with -fsplit-stack. If they were, then we +// need to apply some target-specific adjustments to request +// additional stack space. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::split_stack_adjust( + const Symbol_table* symtab, + const unsigned char* pshdrs, + unsigned int sh_type, + unsigned int shndx, + const unsigned char* prelocs, + size_t reloc_count, + unsigned char* view, + section_size_type view_size, + Reloc_symbol_changes** reloc_map) +{ + if (sh_type == elfcpp::SHT_REL) + this->split_stack_adjust_reltype<elfcpp::SHT_REL>(symtab, pshdrs, shndx, + prelocs, reloc_count, + view, view_size, + reloc_map); + else + { + gold_assert(sh_type == elfcpp::SHT_RELA); + this->split_stack_adjust_reltype<elfcpp::SHT_RELA>(symtab, pshdrs, shndx, + prelocs, reloc_count, + view, view_size, + reloc_map); + } +} + +// Adjust for -fsplit-stack, templatized on the type of the relocation +// section. + +template<int size, bool big_endian> +template<int sh_type> +void +Sized_relobj<size, big_endian>::split_stack_adjust_reltype( + const Symbol_table* symtab, + const unsigned char* pshdrs, + unsigned int shndx, + const unsigned char* prelocs, + size_t reloc_count, + unsigned char* view, + section_size_type view_size, + Reloc_symbol_changes** reloc_map) +{ + typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; + const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + + size_t local_count = this->local_symbol_count(); + + std::vector<section_offset_type> non_split_refs; + + const unsigned char* pr = prelocs; + for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size) + { + Reltype reloc(pr); + + typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info(); + unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + if (r_sym < local_count) + continue; + + const Symbol* gsym = this->global_symbol(r_sym); + gold_assert(gsym != NULL); + if (gsym->is_forwarder()) + gsym = symtab->resolve_forwards(gsym); + + // See if this relocation refers to a function defined in an + // object compiled without -fsplit-stack. Note that we don't + // care about the type of relocation--this means that in some + // cases we will ask for a large stack unnecessarily, but this + // is not fatal. FIXME: Some targets have symbols which are + // functions but are not type STT_FUNC, e.g., STT_ARM_TFUNC. + if (gsym->type() == elfcpp::STT_FUNC + && !gsym->is_undefined() + && gsym->source() == Symbol::FROM_OBJECT + && !gsym->object()->uses_split_stack()) + { + section_offset_type offset = + convert_to_section_size_type(reloc.get_r_offset()); + non_split_refs.push_back(offset); + } + } + + if (non_split_refs.empty()) + return; + + // At this point, every entry in NON_SPLIT_REFS indicates a + // relocation which refers to a function in an object compiled + // without -fsplit-stack. We now have to convert that list into a + // set of offsets to functions. First, we find all the functions. + + Function_offsets function_offsets; + this->find_functions(pshdrs, shndx, &function_offsets); + if (function_offsets.empty()) + return; + + // Now get a list of the function with references to non split-stack + // code. + + Function_offsets calls_non_split; + for (std::vector<section_offset_type>::const_iterator p + = non_split_refs.begin(); + p != non_split_refs.end(); + ++p) + { + Function_offsets::const_iterator low = function_offsets.lower_bound(*p); + if (low == function_offsets.end()) + --low; + else if (low->first == *p) + ; + else if (low == function_offsets.begin()) + continue; + else + --low; + + calls_non_split.insert(*low); + } + if (calls_non_split.empty()) + return; + + // Now we have a set of functions to adjust. The adjustments are + // target specific. Besides changing the output section view + // however, it likes, the target may request a relocation change + // from one global symbol name to another. + + for (Function_offsets::const_iterator p = calls_non_split.begin(); + p != calls_non_split.end(); + ++p) + { + std::string from; + std::string to; + parameters->target().calls_non_split(this, shndx, p->first, p->second, + view, view_size, &from, &to); + if (!from.empty()) + { + gold_assert(!to.empty()); + Symbol* tosym = NULL; + + // Find relocations in the relevant function which are for + // FROM. + pr = prelocs; + for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size) + { + Reltype reloc(pr); + + typename elfcpp::Elf_types<size>::Elf_WXword r_info = + reloc.get_r_info(); + unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info); + if (r_sym < local_count) + continue; + + section_offset_type offset = + convert_to_section_size_type(reloc.get_r_offset()); + if (offset < p->first + || (offset + >= (p->first + + static_cast<section_offset_type>(p->second)))) + continue; + + const Symbol* gsym = this->global_symbol(r_sym); + if (from == gsym->name()) + { + if (tosym == NULL) + { + tosym = symtab->lookup(to.c_str()); + if (tosym == NULL) + { + this->error(_("could not convert call " + "to '%s' to '%s'"), + from.c_str(), to.c_str()); + break; + } + } + + if (*reloc_map == NULL) + *reloc_map = new Reloc_symbol_changes(reloc_count); + (*reloc_map)->set(i, tosym); + } + } + } + } +} + +// Find all the function in this object defined in section SHNDX. +// Store their offsets in the section in FUNCTION_OFFSETS. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::find_functions( + const unsigned char* pshdrs, + unsigned int shndx, + Sized_relobj<size, big_endian>::Function_offsets* function_offsets) +{ + // We need to read the symbols to find the functions. If we wanted + // to, we could cache reading the symbols across all sections in the + // object. + const unsigned int symtab_shndx = this->symtab_shndx_; + typename This::Shdr symtabshdr(pshdrs + symtab_shndx * This::shdr_size); + gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB); + + typename elfcpp::Elf_types<size>::Elf_WXword sh_size = + symtabshdr.get_sh_size(); + const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(), + sh_size, true, true); + + const int sym_size = This::sym_size; + const unsigned int symcount = sh_size / sym_size; + for (unsigned int i = 0; i < symcount; ++i, psyms += sym_size) + { + typename elfcpp::Sym<size, big_endian> isym(psyms); + + // FIXME: Some targets can have functions which do not have type + // STT_FUNC, e.g., STT_ARM_TFUNC. + if (isym.get_st_type() != elfcpp::STT_FUNC + || isym.get_st_size() == 0) + continue; + + bool is_ordinary; + unsigned int sym_shndx = this->adjust_sym_shndx(i, isym.get_st_shndx(), + &is_ordinary); + if (!is_ordinary || sym_shndx != shndx) + continue; + + section_offset_type value = + convert_to_section_size_type(isym.get_st_value()); + section_size_type fnsize = + convert_to_section_size_type(isym.get_st_size()); + + (*function_offsets)[value] = fnsize; + } +} + // Class Merged_symbol_value. template<int size> @@ -1080,8 +1432,39 @@ Sized_relobj<64, true>::do_read_relocs(Read_relocs_data* rd); #ifdef HAVE_TARGET_32_LITTLE template void -Sized_relobj<32, false>::do_scan_relocs(const General_options& options, - Symbol_table* symtab, +Sized_relobj<32, false>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Sized_relobj<32, true>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Sized_relobj<64, false>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Sized_relobj<64, true>::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd); +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +void +Sized_relobj<32, false>::do_scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); #endif @@ -1089,8 +1472,7 @@ Sized_relobj<32, false>::do_scan_relocs(const General_options& options, #ifdef HAVE_TARGET_32_BIG template void -Sized_relobj<32, true>::do_scan_relocs(const General_options& options, - Symbol_table* symtab, +Sized_relobj<32, true>::do_scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); #endif @@ -1098,8 +1480,7 @@ Sized_relobj<32, true>::do_scan_relocs(const General_options& options, #ifdef HAVE_TARGET_64_LITTLE template void -Sized_relobj<64, false>::do_scan_relocs(const General_options& options, - Symbol_table* symtab, +Sized_relobj<64, false>::do_scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); #endif @@ -1107,8 +1488,7 @@ Sized_relobj<64, false>::do_scan_relocs(const General_options& options, #ifdef HAVE_TARGET_64_BIG template void -Sized_relobj<64, true>::do_scan_relocs(const General_options& options, - Symbol_table* symtab, +Sized_relobj<64, true>::do_scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd); #endif @@ -1116,8 +1496,7 @@ Sized_relobj<64, true>::do_scan_relocs(const General_options& options, #ifdef HAVE_TARGET_32_LITTLE template void -Sized_relobj<32, false>::do_relocate(const General_options& options, - const Symbol_table* symtab, +Sized_relobj<32, false>::do_relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of); #endif @@ -1125,8 +1504,7 @@ Sized_relobj<32, false>::do_relocate(const General_options& options, #ifdef HAVE_TARGET_32_BIG template void -Sized_relobj<32, true>::do_relocate(const General_options& options, - const Symbol_table* symtab, +Sized_relobj<32, true>::do_relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of); #endif @@ -1134,8 +1512,7 @@ Sized_relobj<32, true>::do_relocate(const General_options& options, #ifdef HAVE_TARGET_64_LITTLE template void -Sized_relobj<64, false>::do_relocate(const General_options& options, - const Symbol_table* symtab, +Sized_relobj<64, false>::do_relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of); #endif @@ -1143,12 +1520,91 @@ Sized_relobj<64, false>::do_relocate(const General_options& options, #ifdef HAVE_TARGET_64_BIG template void -Sized_relobj<64, true>::do_relocate(const General_options& options, - const Symbol_table* symtab, +Sized_relobj<64, true>::do_relocate(const Symbol_table* symtab, const Layout* layout, Output_file* of); #endif +#ifdef HAVE_TARGET_32_LITTLE +template +void +Sized_relobj<32, false>::do_relocate_sections( + const Symbol_table* symtab, + const Layout* layout, + const unsigned char* pshdrs, + Views* pviews); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Sized_relobj<32, true>::do_relocate_sections( + const Symbol_table* symtab, + const Layout* layout, + const unsigned char* pshdrs, + Views* pviews); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Sized_relobj<64, false>::do_relocate_sections( + const Symbol_table* symtab, + const Layout* layout, + const unsigned char* pshdrs, + Views* pviews); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Sized_relobj<64, true>::do_relocate_sections( + const Symbol_table* symtab, + const Layout* layout, + const unsigned char* pshdrs, + Views* pviews); +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template +void +Sized_relobj<32, false>::initialize_input_to_output_maps(); + +template +void +Sized_relobj<32, false>::free_input_to_output_maps(); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Sized_relobj<32, true>::initialize_input_to_output_maps(); + +template +void +Sized_relobj<32, true>::free_input_to_output_maps(); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Sized_relobj<64, false>::initialize_input_to_output_maps(); + +template +void +Sized_relobj<64, false>::free_input_to_output_maps(); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Sized_relobj<64, true>::initialize_input_to_output_maps(); + +template +void +Sized_relobj<64, true>::free_input_to_output_maps(); +#endif + #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) template class Merged_symbol_value<32>; diff --git a/binutils-2.19/gold/reloc.h b/binutils-2.19/gold/reloc.h index 61f05e7..f99da0c 100644 --- a/binutils-2.19/gold/reloc.h +++ b/binutils-2.19/gold/reloc.h @@ -1,6 +1,6 @@ // reloc.h -- relocate input files for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -24,7 +24,9 @@ #define GOLD_RELOC_H #include <vector> +#ifdef HAVE_BYTESWAP_H #include <byteswap.h> +#endif #include "elfcpp.h" #include "workqueue.h" @@ -60,13 +62,13 @@ class Output_data_reloc; class Read_relocs : public Task { public: - // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be - // unblocked when the Scan_relocs task completes. - Read_relocs(const General_options& options, Symbol_table* symtab, - Layout* layout, Relobj* object, Task_token* symtab_lock, - Task_token* blocker) - : options_(options), symtab_(symtab), layout_(layout), object_(object), - symtab_lock_(symtab_lock), blocker_(blocker) + // THIS_BLOCKER and NEXT_BLOCKER are passed along to a Scan_relocs + // or Gc_process_relocs task, so that they run in a deterministic + // order. + Read_relocs(Symbol_table* symtab, Layout* layout, Relobj* object, + Task_token* this_blocker, Task_token* next_blocker) + : symtab_(symtab), layout_(layout), object_(object), + this_blocker_(this_blocker), next_blocker_(next_blocker) { } // The standard Task methods. @@ -84,12 +86,52 @@ class Read_relocs : public Task get_name() const; private: - const General_options& options_; Symbol_table* symtab_; Layout* layout_; Relobj* object_; - Task_token* symtab_lock_; - Task_token* blocker_; + Task_token* this_blocker_; + Task_token* next_blocker_; +}; + +// Process the relocs to figure out which sections are garbage. +// Very similar to scan relocs. + +class Gc_process_relocs : public Task +{ + public: + // THIS_BLOCKER prevents this task from running until the previous + // one is finished. NEXT_BLOCKER prevents the next task from + // running. + Gc_process_relocs(Symbol_table* symtab, Layout* layout, Relobj* object, + Read_relocs_data* rd, Task_token* this_blocker, + Task_token* next_blocker) + : symtab_(symtab), layout_(layout), object_(object), rd_(rd), + this_blocker_(this_blocker), next_blocker_(next_blocker) + { } + + ~Gc_process_relocs(); + + // The standard Task methods. + + Task_token* + is_runnable(); + + void + locks(Task_locker*); + + void + run(Workqueue*); + + std::string + get_name() const; + + private: + Symbol_table* symtab_; + Layout* layout_; + Relobj* object_; + Read_relocs_data* rd_; + Task_token* this_blocker_; + Task_token* next_blocker_; }; // Scan the relocations for an object to see if they require any @@ -98,15 +140,18 @@ class Read_relocs : public Task class Scan_relocs : public Task { public: - // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be - // unblocked when the task completes. - Scan_relocs(const General_options& options, Symbol_table* symtab, - Layout* layout, Relobj* object, Read_relocs_data* rd, - Task_token* symtab_lock, Task_token* blocker) - : options_(options), symtab_(symtab), layout_(layout), object_(object), - rd_(rd), symtab_lock_(symtab_lock), blocker_(blocker) + // THIS_BLOCKER prevents this task from running until the previous + // one is finished. NEXT_BLOCKER prevents the next task from + // running. + Scan_relocs(Symbol_table* symtab, Layout* layout, Relobj* object, + Read_relocs_data* rd, Task_token* this_blocker, + Task_token* next_blocker) + : symtab_(symtab), layout_(layout), object_(object), rd_(rd), + this_blocker_(this_blocker), next_blocker_(next_blocker) { } + ~Scan_relocs(); + // The standard Task methods. Task_token* @@ -122,13 +167,12 @@ class Scan_relocs : public Task get_name() const; private: - const General_options& options_; Symbol_table* symtab_; Layout* layout_; Relobj* object_; Read_relocs_data* rd_; - Task_token* symtab_lock_; - Task_token* blocker_; + Task_token* this_blocker_; + Task_token* next_blocker_; }; // A class to perform all the relocations for an object file. @@ -136,12 +180,12 @@ class Scan_relocs : public Task class Relocate_task : public Task { public: - Relocate_task(const General_options& options, const Symbol_table* symtab, - const Layout* layout, Relobj* object, Output_file* of, + Relocate_task(const Symbol_table* symtab, const Layout* layout, + Relobj* object, Output_file* of, Task_token* input_sections_blocker, Task_token* output_sections_blocker, Task_token* final_blocker) - : options_(options), symtab_(symtab), layout_(layout), object_(object), - of_(of), input_sections_blocker_(input_sections_blocker), + : symtab_(symtab), layout_(layout), object_(object), of_(of), + input_sections_blocker_(input_sections_blocker), output_sections_blocker_(output_sections_blocker), final_blocker_(final_blocker) { } @@ -161,7 +205,6 @@ class Relocate_task : public Task get_name() const; private: - const General_options& options_; const Symbol_table* symtab_; const Layout* layout_; Relobj* object_; diff --git a/binutils-2.19/gold/resolve.cc b/binutils-2.19/gold/resolve.cc index 0ad990c..8b1c321 100644 --- a/binutils-2.19/gold/resolve.cc +++ b/binutils-2.19/gold/resolve.cc @@ -1,6 +1,6 @@ // resolve.cc -- symbol resolution for gold -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -26,6 +26,7 @@ #include "target.h" #include "object.h" #include "symtab.h" +#include "plugin.h" namespace gold { @@ -62,6 +63,26 @@ Symbol::override_version(const char* version) } } +// This symbol is being overidden by another symbol whose visibility +// is VISIBILITY. Updated the VISIBILITY_ field accordingly. + +inline void +Symbol::override_visibility(elfcpp::STV visibility) +{ + // The rule for combining visibility is that we always choose the + // most constrained visibility. In order of increasing constraint, + // visibility goes PROTECTED, HIDDEN, INTERNAL. This is the reverse + // of the numeric values, so the effect is that we always want the + // smallest non-zero value. + if (visibility != elfcpp::STV_DEFAULT) + { + if (this->visibility_ == elfcpp::STV_DEFAULT) + this->visibility_ = visibility; + else if (this->visibility_ > visibility) + this->visibility_ = visibility; + } +} + // Override the fields in Symbol. template<int size, bool big_endian> @@ -77,7 +98,7 @@ Symbol::override_base(const elfcpp::Sym<size, big_endian>& sym, this->is_ordinary_shndx_ = is_ordinary; this->type_ = sym.get_st_type(); this->binding_ = sym.get_st_bind(); - this->visibility_ = sym.get_st_visibility(); + this->override_visibility(sym.get_st_visibility()); this->nonvis_ = sym.get_st_nonvis(); if (object->is_dynamic()) this->in_dyn_ = true; @@ -157,6 +178,7 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic, switch (binding) { case elfcpp::STB_GLOBAL: + case elfcpp::STB_GNU_UNIQUE: bits = global_flag; break; @@ -196,6 +218,8 @@ symbol_to_bits(elfcpp::STB binding, bool is_dynamic, default: if (type == elfcpp::STT_COMMON) bits |= common_flag; + else if (!is_ordinary && Symbol::is_common_shndx(shndx)) + bits |= common_flag; else bits |= def_flag; break; @@ -221,10 +245,10 @@ Symbol_table::resolve(Sized_symbol<size>* to, unsigned int orig_st_shndx, Object* object, const char* version) { - if (object->target()->has_resolve()) + if (parameters->target().has_resolve()) { Sized_target<size, big_endian>* sized_target; - sized_target = object->sized_target<size, big_endian>(); + sized_target = parameters->sized_target<size, big_endian>(); sized_target->resolve(to, sym, object, version); return; } @@ -234,45 +258,58 @@ Symbol_table::resolve(Sized_symbol<size>* to, // Record that we've seen this symbol in a regular object. to->set_in_reg(); } + else if (st_shndx == elfcpp::SHN_UNDEF + && (to->visibility() == elfcpp::STV_HIDDEN + || to->visibility() == elfcpp::STV_INTERNAL)) + { + // A dynamic object cannot reference a hidden or internal symbol + // defined in another object. + gold_warning(_("%s symbol '%s' in %s is referenced by DSO %s"), + (to->visibility() == elfcpp::STV_HIDDEN + ? "hidden" + : "internal"), + to->demangled_name().c_str(), + to->object()->name().c_str(), + object->name().c_str()); + return; + } else { // Record that we've seen this symbol in a dynamic object. to->set_in_dyn(); } - unsigned int frombits = symbol_to_bits(sym.get_st_bind(), - object->is_dynamic(), - st_shndx, is_ordinary, - sym.get_st_type()); + // Record if we've seen this symbol in a real ELF object (i.e., the + // symbol is referenced from outside the world known to the plugin). + if (object->pluginobj() == NULL) + to->set_in_real_elf(); - bool adjust_common_sizes; - if (Symbol_table::should_override(to, frombits, object, - &adjust_common_sizes)) + // If we're processing replacement files, allow new symbols to override + // the placeholders from the plugin objects. + if (to->source() == Symbol::FROM_OBJECT) { - typename Sized_symbol<size>::Size_type tosize = to->symsize(); - - this->override(to, sym, st_shndx, is_ordinary, object, version); - - if (adjust_common_sizes && tosize > to->symsize()) - to->set_symsize(tosize); - } - else - { - if (adjust_common_sizes && sym.get_st_size() > to->symsize()) - to->set_symsize(sym.get_st_size()); + Pluginobj* obj = to->object()->pluginobj(); + if (obj != NULL + && parameters->options().plugins()->in_replacement_phase()) + { + this->override(to, sym, st_shndx, is_ordinary, object, version); + return; + } } // A new weak undefined reference, merging with an old weak // reference, could be a One Definition Rule (ODR) violation -- // especially if the types or sizes of the references differ. We'll // store such pairs and look them up later to make sure they - // actually refer to the same lines of code. (Note: not all ODR - // violations can be found this way, and not everything this finds - // is an ODR violation. But it's helpful to warn about.) + // actually refer to the same lines of code. We also check + // combinations of weak and strong, which might occur if one case is + // inline and the other is not. (Note: not all ODR violations can + // be found this way, and not everything this finds is an ODR + // violation. But it's helpful to warn about.) bool to_is_ordinary; if (parameters->options().detect_odr_violations() - && sym.get_st_bind() == elfcpp::STB_WEAK - && to->binding() == elfcpp::STB_WEAK + && (sym.get_st_bind() == elfcpp::STB_WEAK + || to->binding() == elfcpp::STB_WEAK) && orig_st_shndx != elfcpp::SHN_UNDEF && to->shndx(&to_is_ordinary) != elfcpp::SHN_UNDEF && to_is_ordinary @@ -291,6 +328,47 @@ Symbol_table::resolve(Sized_symbol<size>* to, this->candidate_odr_violations_[to->name()].insert(fromloc); this->candidate_odr_violations_[to->name()].insert(toloc); } + + unsigned int frombits = symbol_to_bits(sym.get_st_bind(), + object->is_dynamic(), + st_shndx, is_ordinary, + sym.get_st_type()); + + bool adjust_common_sizes; + typename Sized_symbol<size>::Size_type tosize = to->symsize(); + if (Symbol_table::should_override(to, frombits, OBJECT, object, + &adjust_common_sizes)) + { + this->override(to, sym, st_shndx, is_ordinary, object, version); + if (adjust_common_sizes && tosize > to->symsize()) + to->set_symsize(tosize); + } + else + { + if (adjust_common_sizes && sym.get_st_size() > tosize) + to->set_symsize(sym.get_st_size()); + // The ELF ABI says that even for a reference to a symbol we + // merge the visibility. + to->override_visibility(sym.get_st_visibility()); + } + + if (adjust_common_sizes && parameters->options().warn_common()) + { + if (tosize > sym.get_st_size()) + Symbol_table::report_resolve_problem(false, + _("common of '%s' overriding " + "smaller common"), + to, OBJECT, object); + else if (tosize < sym.get_st_size()) + Symbol_table::report_resolve_problem(false, + _("common of '%s' overidden by " + "larger common"), + to, OBJECT, object); + else + Symbol_table::report_resolve_problem(false, + _("multiple common of '%s'"), + to, OBJECT, object); + } } // Handle the core of symbol resolution. This is called with the @@ -302,7 +380,8 @@ Symbol_table::resolve(Sized_symbol<size>* to, bool Symbol_table::should_override(const Symbol* to, unsigned int frombits, - Object* object, bool* adjust_common_sizes) + Defined defined, Object* object, + bool* adjust_common_sizes) { *adjust_common_sizes = false; @@ -360,17 +439,13 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, // --just-symbols, then don't warn. This is for compatibility // with the GNU linker. FIXME: This is a hack. if ((to->source() == Symbol::FROM_OBJECT && to->object()->just_symbols()) - || object->just_symbols()) + || (object != NULL && object->just_symbols())) return false; - // FIXME: Do a better job of reporting locations. - gold_error(_("%s: multiple definition of %s"), - object != NULL ? object->name().c_str() : _("command line"), - to->demangled_name().c_str()); - gold_error(_("%s: previous definition here"), - (to->source() == Symbol::FROM_OBJECT - ? to->object()->name().c_str() - : _("command line"))); + if (!parameters->options().muldefs()) + Symbol_table::report_resolve_problem(true, + _("multiple definition of '%s'"), + to, defined, object); return false; case WEAK_DEF * 16 + DEF: @@ -405,8 +480,12 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, case DYN_COMMON * 16 + DEF: case DYN_WEAK_COMMON * 16 + DEF: // We've seen a common symbol and now we see a definition. The - // definition overrides. FIXME: We should optionally issue, version a - // warning. + // definition overrides. + if (parameters->options().warn_common()) + Symbol_table::report_resolve_problem(false, + _("definition of '%s' overriding " + "common"), + to, defined, object); return true; case DEF * 16 + WEAK_DEF: @@ -436,7 +515,12 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, case DYN_COMMON * 16 + WEAK_DEF: case DYN_WEAK_COMMON * 16 + WEAK_DEF: // A weak definition does override a definition in a dynamic - // object. FIXME: We should optionally issue a warning. + // object. + if (parameters->options().warn_common()) + Symbol_table::report_resolve_problem(false, + _("definition of '%s' overriding " + "dynamic common definition"), + to, defined, object); return true; case DEF * 16 + DYN_DEF: @@ -552,6 +636,11 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, case DEF * 16 + COMMON: // A common symbol does not override a definition. + if (parameters->options().warn_common()) + Symbol_table::report_resolve_problem(false, + _("common '%s' overridden by " + "previous definition"), + to, defined, object); return false; case WEAK_DEF * 16 + COMMON: @@ -657,16 +746,73 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, } } +// Issue an error or warning due to symbol resolution. IS_ERROR +// indicates an error rather than a warning. MSG is the error +// message; it is expected to have a %s for the symbol name. TO is +// the existing symbol. DEFINED/OBJECT is where the new symbol was +// found. + +// FIXME: We should have better location information here. When the +// symbol is defined, we should be able to pull the location from the +// debug info if there is any. + +void +Symbol_table::report_resolve_problem(bool is_error, const char* msg, + const Symbol* to, Defined defined, + Object* object) +{ + std::string demangled(to->demangled_name()); + size_t len = strlen(msg) + demangled.length() + 10; + char* buf = new char[len]; + snprintf(buf, len, msg, demangled.c_str()); + + const char* objname; + switch (defined) + { + case OBJECT: + objname = object->name().c_str(); + break; + case COPY: + objname = _("COPY reloc"); + break; + case DEFSYM: + case UNDEFINED: + objname = _("command line"); + break; + case SCRIPT: + objname = _("linker script"); + break; + case PREDEFINED: + objname = _("linker defined"); + break; + default: + gold_unreachable(); + } + + if (is_error) + gold_error("%s: %s", objname, buf); + else + gold_warning("%s: %s", objname, buf); + + delete[] buf; + + if (to->source() == Symbol::FROM_OBJECT) + objname = to->object()->name().c_str(); + else + objname = _("command line"); + gold_info("%s: %s: previous definition here", program_name, objname); +} + // A special case of should_override which is only called for a strong // defined symbol from a regular object file. This is used when // defining special symbols. bool -Symbol_table::should_override_with_special(const Symbol* to) +Symbol_table::should_override_with_special(const Symbol* to, Defined defined) { bool adjust_common_sizes; unsigned int frombits = global_flag | regular_flag | def_flag; - bool ret = Symbol_table::should_override(to, frombits, NULL, + bool ret = Symbol_table::should_override(to, frombits, defined, NULL, &adjust_common_sizes); gold_assert(!adjust_common_sizes); return ret; @@ -702,7 +848,7 @@ Symbol::override_base_with_special(const Symbol* from) this->override_version(from->version_); this->type_ = from->type_; this->binding_ = from->binding_; - this->visibility_ = from->visibility_; + this->override_visibility(from->visibility_); this->nonvis_ = from->nonvis_; // Special symbols are always considered to be regular symbols. @@ -715,9 +861,8 @@ Symbol::override_base_with_special(const Symbol* from) // We shouldn't see these flags. If we do, we need to handle them // somehow. - gold_assert(!from->is_target_special_ || this->is_target_special_); gold_assert(!from->is_forwarder_); - gold_assert(!from->has_plt_offset_); + gold_assert(!from->has_plt_offset()); gold_assert(!from->has_warning_); gold_assert(!from->is_copied_from_dynobj_); gold_assert(!from->is_forced_local_); @@ -757,7 +902,13 @@ Symbol_table::override_with_special(Sized_symbol<size>* tosym, } while (ssym != tosym); } - if (tosym->binding() == elfcpp::STB_LOCAL) + if (tosym->binding() == elfcpp::STB_LOCAL + || ((tosym->visibility() == elfcpp::STV_HIDDEN + || tosym->visibility() == elfcpp::STV_INTERNAL) + && (tosym->binding() == elfcpp::STB_GLOBAL + || tosym->binding() == elfcpp::STB_GNU_UNIQUE + || tosym->binding() == elfcpp::STB_WEAK) + && !parameters->options().relocatable())) this->force_local(tosym); } @@ -765,7 +916,10 @@ Symbol_table::override_with_special(Sized_symbol<size>* tosym, // script to restrict this to only the ones needed for implemented // targets. -#ifdef HAVE_TARGET_32_LITTLE +// We have to instantiate both big and little endian versions because +// these are used by other templates that depends on size only. + +#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) template void Symbol_table::resolve<32, false>( @@ -776,9 +930,7 @@ Symbol_table::resolve<32, false>( unsigned int orig_st_shndx, Object* object, const char* version); -#endif -#ifdef HAVE_TARGET_32_BIG template void Symbol_table::resolve<32, true>( @@ -791,7 +943,7 @@ Symbol_table::resolve<32, true>( const char* version); #endif -#ifdef HAVE_TARGET_64_LITTLE +#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) template void Symbol_table::resolve<64, false>( @@ -802,9 +954,7 @@ Symbol_table::resolve<64, false>( unsigned int orig_st_shndx, Object* object, const char* version); -#endif -#ifdef HAVE_TARGET_64_BIG template void Symbol_table::resolve<64, true>( diff --git a/binutils-2.19/gold/script-c.h b/binutils-2.19/gold/script-c.h index d94ba51..77b4aa4 100644 --- a/binutils-2.19/gold/script-c.h +++ b/binutils-2.19/gold/script-c.h @@ -61,6 +61,18 @@ typedef Expression* Expression_ptr; typedef void* Expression_ptr; #endif +/* Script_section type. */ +enum Script_section_type +{ + /* No section type. */ + SCRIPT_SECTION_TYPE_NONE, + SCRIPT_SECTION_TYPE_NOLOAD, + SCRIPT_SECTION_TYPE_DSECT, + SCRIPT_SECTION_TYPE_COPY, + SCRIPT_SECTION_TYPE_INFO, + SCRIPT_SECTION_TYPE_OVERLAY +}; + /* A constraint for whether to use a particular output section definition. */ @@ -83,6 +95,8 @@ struct Parser_output_section_header { /* The address. This may be NULL. */ Expression_ptr address; + /* Section type. May be NULL string. */ + enum Script_section_type section_type; /* The load address, from the AT specifier. This may be NULL. */ Expression_ptr load_address; /* The alignment, from the ALIGN specifier. This may be NULL. */ @@ -211,6 +225,12 @@ yylex(YYSTYPE*, void* closure); extern void yyerror(void* closure, const char*); +/* Called by the bison parser to add an external symbol (a symbol in + an EXTERN declaration) to the link. */ + +extern void +script_add_extern(void* closure, const char*, size_t); + /* Called by the bison parser to add a file to the link. */ extern void @@ -245,6 +265,17 @@ script_set_common_allocation(void* closure, int); extern void script_parse_option(void* closure, const char*, size_t); +/* Called by the bison parser to handle OUTPUT_FORMAT. This return 0 + if the parse should be aborted. */ + +extern int +script_check_output_format(void* closure, const char*, size_t, + const char*, size_t, const char*, size_t); + +/* Called by the bison parser to handle TARGET. */ +extern void +script_set_target(void* closure, const char*, size_t); + /* Called by the bison parser to handle SEARCH_DIR. */ extern void @@ -372,6 +403,11 @@ script_data_segment_align(void* closure); extern void script_data_segment_relro_end(void* closure); +/* Record the fact that a SEGMENT_START expression is seen. */ + +extern void +script_saw_segment_start_expression(void* closure); + /* Called by the bison parser for expressions. */ extern Expression_ptr diff --git a/binutils-2.19/gold/script-sections.cc b/binutils-2.19/gold/script-sections.cc index 990a1a2..99f0dbf 100644 --- a/binutils-2.19/gold/script-sections.cc +++ b/binutils-2.19/gold/script-sections.cc @@ -1,6 +1,6 @@ // script-sections.cc -- linker script SECTIONS for gold -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -43,6 +43,259 @@ namespace gold { +// Manage orphan sections. This is intended to be largely compatible +// with the GNU linker. The Linux kernel implicitly relies on +// something similar to the GNU linker's orphan placement. We +// originally used a simpler scheme here, but it caused the kernel +// build to fail, and was also rather inefficient. + +class Orphan_section_placement +{ + private: + typedef Script_sections::Elements_iterator Elements_iterator; + + public: + Orphan_section_placement(); + + // Handle an output section during initialization of this mapping. + void + output_section_init(const std::string& name, Output_section*, + Elements_iterator location); + + // Initialize the last location. + void + last_init(Elements_iterator location); + + // Set *PWHERE to the address of an iterator pointing to the + // location to use for an orphan section. Return true if the + // iterator has a value, false otherwise. + bool + find_place(Output_section*, Elements_iterator** pwhere); + + // Return the iterator being used for sections at the very end of + // the linker script. + Elements_iterator + last_place() const; + + private: + // The places that we specifically recognize. This list is copied + // from the GNU linker. + enum Place_index + { + PLACE_TEXT, + PLACE_RODATA, + PLACE_DATA, + PLACE_BSS, + PLACE_REL, + PLACE_INTERP, + PLACE_NONALLOC, + PLACE_LAST, + PLACE_MAX + }; + + // The information we keep for a specific place. + struct Place + { + // The name of sections for this place. + const char* name; + // Whether we have a location for this place. + bool have_location; + // The iterator for this place. + Elements_iterator location; + }; + + // Initialize one place element. + void + initialize_place(Place_index, const char*); + + // The places. + Place places_[PLACE_MAX]; + // True if this is the first call to output_section_init. + bool first_init_; +}; + +// Initialize Orphan_section_placement. + +Orphan_section_placement::Orphan_section_placement() + : first_init_(true) +{ + this->initialize_place(PLACE_TEXT, ".text"); + this->initialize_place(PLACE_RODATA, ".rodata"); + this->initialize_place(PLACE_DATA, ".data"); + this->initialize_place(PLACE_BSS, ".bss"); + this->initialize_place(PLACE_REL, NULL); + this->initialize_place(PLACE_INTERP, ".interp"); + this->initialize_place(PLACE_NONALLOC, NULL); + this->initialize_place(PLACE_LAST, NULL); +} + +// Initialize one place element. + +void +Orphan_section_placement::initialize_place(Place_index index, const char* name) +{ + this->places_[index].name = name; + this->places_[index].have_location = false; +} + +// While initializing the Orphan_section_placement information, this +// is called once for each output section named in the linker script. +// If we found an output section during the link, it will be passed in +// OS. + +void +Orphan_section_placement::output_section_init(const std::string& name, + Output_section* os, + Elements_iterator location) +{ + bool first_init = this->first_init_; + this->first_init_ = false; + + for (int i = 0; i < PLACE_MAX; ++i) + { + if (this->places_[i].name != NULL && this->places_[i].name == name) + { + if (this->places_[i].have_location) + { + // We have already seen a section with this name. + return; + } + + this->places_[i].location = location; + this->places_[i].have_location = true; + + // If we just found the .bss section, restart the search for + // an unallocated section. This follows the GNU linker's + // behaviour. + if (i == PLACE_BSS) + this->places_[PLACE_NONALLOC].have_location = false; + + return; + } + } + + // Relocation sections. + if (!this->places_[PLACE_REL].have_location + && os != NULL + && (os->type() == elfcpp::SHT_REL || os->type() == elfcpp::SHT_RELA) + && (os->flags() & elfcpp::SHF_ALLOC) != 0) + { + this->places_[PLACE_REL].location = location; + this->places_[PLACE_REL].have_location = true; + } + + // We find the location for unallocated sections by finding the + // first debugging or comment section after the BSS section (if + // there is one). + if (!this->places_[PLACE_NONALLOC].have_location + && (name == ".comment" || Layout::is_debug_info_section(name.c_str()))) + { + // We add orphan sections after the location in PLACES_. We + // want to store unallocated sections before LOCATION. If this + // is the very first section, we can't use it. + if (!first_init) + { + --location; + this->places_[PLACE_NONALLOC].location = location; + this->places_[PLACE_NONALLOC].have_location = true; + } + } +} + +// Initialize the last location. + +void +Orphan_section_placement::last_init(Elements_iterator location) +{ + this->places_[PLACE_LAST].location = location; + this->places_[PLACE_LAST].have_location = true; +} + +// Set *PWHERE to the address of an iterator pointing to the location +// to use for an orphan section. Return true if the iterator has a +// value, false otherwise. + +bool +Orphan_section_placement::find_place(Output_section* os, + Elements_iterator** pwhere) +{ + // Figure out where OS should go. This is based on the GNU linker + // code. FIXME: The GNU linker handles small data sections + // specially, but we don't. + elfcpp::Elf_Word type = os->type(); + elfcpp::Elf_Xword flags = os->flags(); + Place_index index; + if ((flags & elfcpp::SHF_ALLOC) == 0 + && !Layout::is_debug_info_section(os->name())) + index = PLACE_NONALLOC; + else if ((flags & elfcpp::SHF_ALLOC) == 0) + index = PLACE_LAST; + else if (type == elfcpp::SHT_NOTE) + index = PLACE_INTERP; + else if (type == elfcpp::SHT_NOBITS) + index = PLACE_BSS; + else if ((flags & elfcpp::SHF_WRITE) != 0) + index = PLACE_DATA; + else if (type == elfcpp::SHT_REL || type == elfcpp::SHT_RELA) + index = PLACE_REL; + else if ((flags & elfcpp::SHF_EXECINSTR) == 0) + index = PLACE_RODATA; + else + index = PLACE_TEXT; + + // If we don't have a location yet, try to find one based on a + // plausible ordering of sections. + if (!this->places_[index].have_location) + { + Place_index follow; + switch (index) + { + default: + follow = PLACE_MAX; + break; + case PLACE_RODATA: + follow = PLACE_TEXT; + break; + case PLACE_BSS: + follow = PLACE_DATA; + break; + case PLACE_REL: + follow = PLACE_TEXT; + break; + case PLACE_INTERP: + follow = PLACE_TEXT; + break; + } + if (follow != PLACE_MAX && this->places_[follow].have_location) + { + // Set the location of INDEX to the location of FOLLOW. The + // location of INDEX will then be incremented by the caller, + // so anything in INDEX will continue to be after anything + // in FOLLOW. + this->places_[index].location = this->places_[follow].location; + this->places_[index].have_location = true; + } + } + + *pwhere = &this->places_[index].location; + bool ret = this->places_[index].have_location; + + // The caller will set the location. + this->places_[index].have_location = true; + + return ret; +} + +// Return the iterator being used for sections at the very end of the +// linker script. + +Orphan_section_placement::Elements_iterator +Orphan_section_placement::last_place() const +{ + gold_assert(this->places_[PLACE_LAST].have_location); + return this->places_[PLACE_LAST].location; +} + // An element in a SECTIONS clause. class Sections_element @@ -54,6 +307,11 @@ class Sections_element virtual ~Sections_element() { } + // Return whether an output section is relro. + virtual bool + is_relro() const + { return false; } + // Record that an output section is relro. virtual void set_is_relro() @@ -79,14 +337,15 @@ class Sections_element // section name. This only real implementation is in // Output_section_definition. virtual const char* - output_section_name(const char*, const char*, Output_section***) + output_section_name(const char*, const char*, Output_section***, + Script_sections::Section_type*) { return NULL; } - // Return whether to place an orphan output section after this - // element. - virtual bool - place_orphan_here(const Output_section *, bool*, bool*) const - { return false; } + // Initialize OSP with an output section. + virtual void + orphan_section_init(Orphan_section_placement*, + Script_sections::Elements_iterator) + { } // Set section addresses. This includes applying assignments if the // the expression is an absolute value. @@ -148,7 +407,7 @@ class Sections_element_assignment : public Sections_element public: Sections_element_assignment(const char* name, size_t namelen, Expression* val, bool provide, bool hidden) - : assignment_(name, namelen, val, provide, hidden) + : assignment_(name, namelen, false, val, provide, hidden) { } // Add the symbol to the symbol table. @@ -266,7 +525,7 @@ class Output_section_element { public: // A list of input sections. - typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list; + typedef std::list<Output_section::Simple_input_section> Input_section_list; Output_section_element() { } @@ -335,7 +594,7 @@ class Output_section_element_assignment : public Output_section_element Output_section_element_assignment(const char* name, size_t namelen, Expression* val, bool provide, bool hidden) - : assignment_(name, namelen, val, provide, hidden) + : assignment_(name, namelen, false, val, provide, hidden) { } // Add the symbol to the symbol table. @@ -443,6 +702,7 @@ Output_section_element_dot_assignment::set_section_addresses( posd = new Output_data_const(this_fill, 0); } output_section->add_output_section_data(posd); + layout->new_output_section_data_from_script(posd); } *dot_value = next_dot; } @@ -478,7 +738,7 @@ class Output_data_expression : public Output_section_data Output_data_expression(int size, bool is_signed, Expression* val, const Symbol_table* symtab, const Layout* layout, uint64_t dot_value, Output_section* dot_section) - : Output_section_data(size, 0), + : Output_section_data(size, 0, true), is_signed_(is_signed), val_(val), symtab_(symtab), layout_(layout), dot_value_(dot_value), dot_section_(dot_section) { } @@ -619,13 +879,11 @@ Output_section_element_data::set_section_addresses( Input_section_list*) { gold_assert(os != NULL); - os->add_output_section_data(new Output_data_expression(this->size_, - this->is_signed_, - this->val_, - symtab, - layout, - *dot_value, - *dot_section)); + Output_data_expression* expression = + new Output_data_expression(this->size_, this->is_signed_, this->val_, + symtab, layout, *dot_value, *dot_section); + os->add_output_section_data(expression); + layout->new_output_section_data_from_script(expression); *dot_value += this->size_; } @@ -911,13 +1169,68 @@ Output_section_element_input::match_name(const char* file_name, // Information we use to sort the input sections. -struct Input_section_info +class Input_section_info { - Relobj* relobj; - unsigned int shndx; - std::string section_name; - uint64_t size; - uint64_t addralign; + public: + Input_section_info(const Output_section::Simple_input_section& input_section) + : input_section_(input_section), section_name_(), + size_(0), addralign_(1) + { } + + // Return the simple input section. + const Output_section::Simple_input_section& + input_section() const + { return this->input_section_; } + + // Return the object. + Relobj* + relobj() const + { return this->input_section_.relobj(); } + + // Return the section index. + unsigned int + shndx() + { return this->input_section_.shndx(); } + + // Return the section name. + const std::string& + section_name() const + { return this->section_name_; } + + // Set the section name. + void + set_section_name(const std::string name) + { this->section_name_ = name; } + + // Return the section size. + uint64_t + size() const + { return this->size_; } + + // Set the section size. + void + set_size(uint64_t size) + { this->size_ = size; } + + // Return the address alignment. + uint64_t + addralign() const + { return this->addralign_; } + + // Set the address alignment. + void + set_addralign(uint64_t addralign) + { this->addralign_ = addralign; } + + private: + // Input section, can be a relaxed section. + Output_section::Simple_input_section input_section_; + // Name of the section. + std::string section_name_; + // Section size. + uint64_t size_; + // Address alignment. + uint64_t addralign_; }; // A class to sort the input sections. @@ -944,22 +1257,22 @@ Input_section_sorter::operator()(const Input_section_info& isi1, if (this->section_sort_ == SORT_WILDCARD_BY_NAME || this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT || (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME - && isi1.addralign == isi2.addralign)) + && isi1.addralign() == isi2.addralign())) { - if (isi1.section_name != isi2.section_name) - return isi1.section_name < isi2.section_name; + if (isi1.section_name() != isi2.section_name()) + return isi1.section_name() < isi2.section_name(); } if (this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT || this->section_sort_ == SORT_WILDCARD_BY_NAME_BY_ALIGNMENT || this->section_sort_ == SORT_WILDCARD_BY_ALIGNMENT_BY_NAME) { - if (isi1.addralign != isi2.addralign) - return isi1.addralign < isi2.addralign; + if (isi1.addralign() != isi2.addralign()) + return isi1.addralign() < isi2.addralign(); } if (this->filename_sort_ == SORT_WILDCARD_BY_NAME) { - if (isi1.relobj->name() != isi2.relobj->name()) - return isi1.relobj->name() < isi2.relobj->name(); + if (isi1.relobj()->name() != isi2.relobj()->name()) + return (isi1.relobj()->name() < isi2.relobj()->name()); } // Otherwise we leave them in the same order. @@ -973,7 +1286,7 @@ Input_section_sorter::operator()(const Input_section_info& isi1, void Output_section_element_input::set_section_addresses( Symbol_table*, - Layout*, + Layout* layout, Output_section* output_section, uint64_t subalign, uint64_t* dot_value, @@ -997,25 +1310,36 @@ Output_section_element_input::set_section_addresses( Input_section_list::iterator p = input_sections->begin(); while (p != input_sections->end()) { + Relobj* relobj = p->relobj(); + unsigned int shndx = p->shndx(); + Input_section_info isi(*p); + // Calling section_name and section_addralign is not very // efficient. - Input_section_info isi; - isi.relobj = p->first; - isi.shndx = p->second; // Lock the object so that we can get information about the // section. This is OK since we know we are single-threaded // here. { const Task* task = reinterpret_cast<const Task*>(-1); - Task_lock_obj<Object> tl(task, p->first); - - isi.section_name = p->first->section_name(p->second); - isi.size = p->first->section_size(p->second); - isi.addralign = p->first->section_addralign(p->second); + Task_lock_obj<Object> tl(task, relobj); + + isi.set_section_name(relobj->section_name(shndx)); + if (p->is_relaxed_input_section()) + { + // We use current data size because relxed section sizes may not + // have finalized yet. + isi.set_size(p->relaxed_input_section()->current_data_size()); + isi.set_addralign(p->relaxed_input_section()->addralign()); + } + else + { + isi.set_size(relobj->section_size(shndx)); + isi.set_addralign(relobj->section_addralign(shndx)); + } } - if (!this->match_file_name(isi.relobj->name().c_str())) + if (!this->match_file_name(relobj->name().c_str())) ++p; else if (this->input_section_patterns_.empty()) { @@ -1029,7 +1353,7 @@ Output_section_element_input::set_section_addresses( { const Input_section_pattern& isp(this->input_section_patterns_[i]); - if (match(isi.section_name.c_str(), isp.pattern.c_str(), + if (match(isi.section_name().c_str(), isp.pattern.c_str(), isp.pattern_is_wildcard)) break; } @@ -1049,6 +1373,7 @@ Output_section_element_input::set_section_addresses( // sections are otherwise equal. Add each input section to the // output section. + uint64_t dot = *dot_value; for (size_t i = 0; i < input_pattern_count; ++i) { if (matching_sections[i].empty()) @@ -1069,30 +1394,37 @@ Output_section_element_input::set_section_addresses( p != matching_sections[i].end(); ++p) { - uint64_t this_subalign = p->addralign; + uint64_t this_subalign = p->addralign(); if (this_subalign < subalign) this_subalign = subalign; - uint64_t address = align_address(*dot_value, this_subalign); + uint64_t address = align_address(dot, this_subalign); - if (address > *dot_value && !fill->empty()) + if (address > dot && !fill->empty()) { section_size_type length = - convert_to_section_size_type(address - *dot_value); + convert_to_section_size_type(address - dot); std::string this_fill = this->get_fill_string(fill, length); Output_section_data* posd = new Output_data_const(this_fill, 0); output_section->add_output_section_data(posd); + layout->new_output_section_data_from_script(posd); } - output_section->add_input_section_for_script(p->relobj, - p->shndx, - p->size, - this_subalign); + output_section->add_simple_input_section(p->input_section(), + p->size(), + this_subalign); - *dot_value = address + p->size; + dot = address + p->size(); } } + // An SHF_TLS/SHT_NOBITS section does not take up any + // address space. + if (output_section == NULL + || (output_section->flags() & elfcpp::SHF_TLS) == 0 + || output_section->type() != elfcpp::SHT_NOBITS) + *dot_value = dot; + this->final_dot_value_ = *dot_value; this->final_dot_section_ = *dot_section; } @@ -1241,6 +1573,11 @@ class Output_section_definition : public Sections_element void add_input_section(const Input_section_spec* spec, bool keep); + // Return whether the output section is relro. + bool + is_relro() const + { return this->is_relro_; } + // Record that the output section is relro. void set_is_relro() @@ -1262,11 +1599,13 @@ class Output_section_definition : public Sections_element // section name. const char* output_section_name(const char* file_name, const char* section_name, - Output_section***); + Output_section***, Script_sections::Section_type*); - // Return whether to place an orphan section after this one. - bool - place_orphan_here(const Output_section *os, bool* exact, bool*) const; + // Initialize OSP with an output section. + void + orphan_section_init(Orphan_section_placement* osp, + Script_sections::Elements_iterator p) + { osp->output_section_init(this->name_, this->output_section_, p); } // Set the section address. void @@ -1308,7 +1647,14 @@ class Output_section_definition : public Sections_element void print(FILE*) const; + // Return the output section type if specified or Script_sections::ST_NONE. + Script_sections::Section_type + section_type() const; + private: + static const char* + script_section_type_name(Script_section_type); + typedef std::vector<Output_section_element*> Output_section_elements; // The output section name. @@ -1341,6 +1687,8 @@ class Output_section_definition : public Sections_element uint64_t evaluated_addralign_; // The output section is relro. bool is_relro_; + // The output section type if specified. + enum Script_section_type script_section_type_; }; // Constructor. @@ -1362,7 +1710,8 @@ Output_section_definition::Output_section_definition( evaluated_address_(0), evaluated_load_address_(0), evaluated_addralign_(0), - is_relro_(false) + is_relro_(false), + script_section_type_(header->section_type) { } @@ -1458,7 +1807,8 @@ Output_section_definition::create_sections(Layout* layout) if ((*p)->needs_output_section()) { const char* name = this->name_.c_str(); - this->output_section_ = layout->make_output_section_for_script(name); + this->output_section_ = + layout->make_output_section_for_script(name, this->section_type()); return; } } @@ -1516,9 +1866,11 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, // Return the output section name to use for an input section name. const char* -Output_section_definition::output_section_name(const char* file_name, - const char* section_name, - Output_section*** slot) +Output_section_definition::output_section_name( + const char* file_name, + const char* section_name, + Output_section*** slot, + Script_sections::Section_type *psection_type) { // Ask each element whether it matches NAME. for (Output_section_elements::const_iterator p = this->elements_.begin(); @@ -1530,6 +1882,7 @@ Output_section_definition::output_section_name(const char* file_name, // We found a match for NAME, which means that it should go // into this output section. *slot = &this->output_section_; + *psection_type = this->section_type(); return this->name_.c_str(); } } @@ -1538,124 +1891,6 @@ Output_section_definition::output_section_name(const char* file_name, return NULL; } -// Return whether to place an orphan output section after this -// section. - -bool -Output_section_definition::place_orphan_here(const Output_section *os, - bool* exact, - bool* is_relro) const -{ - *is_relro = this->is_relro_; - - // Check for the simple case first. - if (this->output_section_ != NULL - && this->output_section_->type() == os->type() - && this->output_section_->flags() == os->flags()) - { - *exact = true; - return true; - } - - // Otherwise use some heuristics. - - if ((os->flags() & elfcpp::SHF_ALLOC) == 0) - return false; - - if (os->type() == elfcpp::SHT_NOBITS) - { - if (this->name_ == ".bss") - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_NOBITS) - return true; - } - else if (os->type() == elfcpp::SHT_NOTE) - { - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_NOTE) - { - *exact = true; - return true; - } - if (this->name_.compare(0, 5, ".note") == 0) - { - *exact = true; - return true; - } - if (this->name_ == ".interp") - return true; - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_PROGBITS - && (this->output_section_->flags() & elfcpp::SHF_WRITE) == 0) - return true; - } - else if (os->type() == elfcpp::SHT_REL || os->type() == elfcpp::SHT_RELA) - { - if (this->name_.compare(0, 4, ".rel") == 0) - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && (this->output_section_->type() == elfcpp::SHT_REL - || this->output_section_->type() == elfcpp::SHT_RELA)) - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_PROGBITS - && (this->output_section_->flags() & elfcpp::SHF_WRITE) == 0) - return true; - } - else if (os->type() == elfcpp::SHT_PROGBITS - && (os->flags() & elfcpp::SHF_WRITE) != 0) - { - if (this->name_ == ".data") - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_PROGBITS - && (this->output_section_->flags() & elfcpp::SHF_WRITE) != 0) - return true; - } - else if (os->type() == elfcpp::SHT_PROGBITS - && (os->flags() & elfcpp::SHF_EXECINSTR) != 0) - { - if (this->name_ == ".text") - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_PROGBITS - && (this->output_section_->flags() & elfcpp::SHF_EXECINSTR) != 0) - return true; - } - else if (os->type() == elfcpp::SHT_PROGBITS - || (os->type() != elfcpp::SHT_PROGBITS - && (os->flags() & elfcpp::SHF_WRITE) == 0)) - { - if (this->name_ == ".rodata") - { - *exact = true; - return true; - } - if (this->output_section_ != NULL - && this->output_section_->type() == elfcpp::SHT_PROGBITS - && (this->output_section_->flags() & elfcpp::SHF_WRITE) == 0) - return true; - } - - return false; -} - // Set the section address. Note that the OUTPUT_SECTION_ field will // be NULL if no input sections were mapped to this output section. // We still have to adjust dot and process symbol assignments. @@ -1667,6 +1902,9 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, uint64_t* load_address) { uint64_t address; + uint64_t old_dot_value = *dot_value; + uint64_t old_load_address = *load_address; + if (this->address_ == NULL) address = *dot_value; else @@ -1702,10 +1940,11 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, *dot_value = address; - // The address of non-SHF_ALLOC sections is forced to zero, - // regardless of what the linker script wants. + // Except for NOLOAD sections, the address of non-SHF_ALLOC sections is + // forced to zero, regardless of what the linker script wants. if (this->output_section_ != NULL - && (this->output_section_->flags() & elfcpp::SHF_ALLOC) != 0) + && ((this->output_section_->flags() & elfcpp::SHF_ALLOC) != 0 + || this->output_section_->is_noload())) this->output_section_->set_address(address); this->evaluated_address_ = address; @@ -1716,12 +1955,12 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, else { Output_section* dummy; - uint64_t load_address = + uint64_t laddr = this->load_address_->eval_with_dot(symtab, layout, true, *dot_value, this->output_section_, &dummy); if (this->output_section_ != NULL) - this->output_section_->set_load_address(load_address); - this->evaluated_load_address_ = load_address; + this->output_section_->set_load_address(laddr); + this->evaluated_load_address_ = laddr; } uint64_t subalign; @@ -1790,6 +2029,13 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, this->output_section_->set_is_relro(); else this->output_section_->clear_is_relro(); + + // If this is a NOLOAD section, keep dot and load address unchanged. + if (this->output_section_->is_noload()) + { + *dot_value = old_dot_value; + *load_address = old_load_address; + } } } @@ -1947,6 +2193,10 @@ Output_section_definition::print(FILE* f) const fprintf(f, " "); } + if (this->script_section_type_ != SCRIPT_SECTION_TYPE_NONE) + fprintf(f, "(%s) ", + this->script_section_type_name(this->script_section_type_)); + fprintf(f, ": "); if (this->load_address_ != NULL) @@ -1996,6 +2246,52 @@ Output_section_definition::print(FILE* f) const fprintf(f, "\n"); } +Script_sections::Section_type +Output_section_definition::section_type() const +{ + switch (this->script_section_type_) + { + case SCRIPT_SECTION_TYPE_NONE: + return Script_sections::ST_NONE; + case SCRIPT_SECTION_TYPE_NOLOAD: + return Script_sections::ST_NOLOAD; + case SCRIPT_SECTION_TYPE_COPY: + case SCRIPT_SECTION_TYPE_DSECT: + case SCRIPT_SECTION_TYPE_INFO: + case SCRIPT_SECTION_TYPE_OVERLAY: + // There are not really support so we treat them as ST_NONE. The + // parse should have issued errors for them already. + return Script_sections::ST_NONE; + default: + gold_unreachable(); + } +} + +// Return the name of a script section type. + +const char* +Output_section_definition::script_section_type_name ( + Script_section_type script_section_type) +{ + switch (script_section_type) + { + case SCRIPT_SECTION_TYPE_NONE: + return "NONE"; + case SCRIPT_SECTION_TYPE_NOLOAD: + return "NOLOAD"; + case SCRIPT_SECTION_TYPE_DSECT: + return "DSECT"; + case SCRIPT_SECTION_TYPE_COPY: + return "COPY"; + case SCRIPT_SECTION_TYPE_INFO: + return "INFO"; + case SCRIPT_SECTION_TYPE_OVERLAY: + return "OVERLAY"; + default: + gold_unreachable(); + } +} + // An output section created to hold orphaned input sections. These // do not actually appear in linker scripts. However, for convenience // when setting the output section addresses, we put a marker to these @@ -2008,9 +2304,19 @@ class Orphan_output_section : public Sections_element : os_(os) { } - // Return whether to place an orphan section after this one. + // Return whether the orphan output section is relro. We can just + // check the output section because we always set the flag, if + // needed, just after we create the Orphan_output_section. bool - place_orphan_here(const Output_section *os, bool* exact, bool*) const; + is_relro() const + { return this->os_->is_relro(); } + + // Initialize OSP with an output section. This should have been + // done already. + void + orphan_section_init(Orphan_section_placement*, + Script_sections::Elements_iterator) + { gold_unreachable(); } // Set section addresses. void @@ -2038,23 +2344,6 @@ class Orphan_output_section : public Sections_element Output_section* os_; }; -// Whether to place another orphan section after this one. - -bool -Orphan_output_section::place_orphan_here(const Output_section* os, - bool* exact, - bool* is_relro) const -{ - if (this->os_->type() == os->type() - && this->os_->flags() == os->flags()) - { - *exact = true; - *is_relro = this->os_->is_relro(); - return true; - } - return false; -} - // Set section addresses. void @@ -2062,7 +2351,7 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, uint64_t* dot_value, uint64_t* load_address) { - typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list; + typedef std::list<Output_section::Simple_input_section> Input_section_list; bool have_load_address = *load_address != *dot_value; @@ -2091,23 +2380,33 @@ Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, // object. { const Task* task = reinterpret_cast<const Task*>(-1); - Task_lock_obj<Object> tl(task, p->first); - addralign = p->first->section_addralign(p->second); - size = p->first->section_size(p->second); + Task_lock_obj<Object> tl(task, p->relobj()); + addralign = p->relobj()->section_addralign(p->shndx()); + if (p->is_relaxed_input_section()) + // We use current data size because relxed section sizes may not + // have finalized yet. + size = p->relaxed_input_section()->current_data_size(); + else + size = p->relobj()->section_size(p->shndx()); } address = align_address(address, addralign); - this->os_->add_input_section_for_script(p->first, p->second, size, - addralign); + this->os_->add_simple_input_section(*p, size, addralign); address += size; } - if (!have_load_address) - *load_address = address; - else - *load_address += address - *dot_value; + // An SHF_TLS/SHT_NOBITS section does not take up any address space. + if (this->os_ == NULL + || (this->os_->flags() & elfcpp::SHF_TLS) == 0 + || this->os_->type() != elfcpp::SHT_NOBITS) + { + if (!have_load_address) + *load_address = address; + else + *load_address += address - *dot_value; - *dot_value = address; + *dot_value = address; + } } // Get the list of segments to use for an allocated section when using @@ -2193,6 +2492,11 @@ class Phdrs_element segment() { return this->segment_; } + // Release the segment. + void + release_segment() + { this->segment_ = NULL; } + // Set the segment flags if appropriate. void set_flags_if_valid() @@ -2256,8 +2560,11 @@ Script_sections::Script_sections() sections_elements_(NULL), output_section_(NULL), phdrs_elements_(NULL), - data_segment_align_index_(-1U), - saw_relro_end_(false) + orphan_section_placement_(NULL), + data_segment_align_start_(), + saw_data_segment_align_(false), + saw_relro_end_(false), + saw_segment_start_expression_(false) { } @@ -2310,6 +2617,15 @@ Script_sections::add_dot_assignment(Expression* val) this->output_section_->add_dot_assignment(val); else { + // The GNU linker permits assignments to . to appears outside of + // a SECTIONS clause, and treats it as appearing inside, so + // sections_elements_ may be NULL here. + if (this->sections_elements_ == NULL) + { + this->sections_elements_ = new Sections_elements; + this->saw_sections_clause_ = true; + } + Sections_element* p = new Sections_element_dot_assignment(val); this->sections_elements_->push_back(p); } @@ -2391,9 +2707,13 @@ Script_sections::add_input_section(const Input_section_spec* spec, bool keep) void Script_sections::data_segment_align() { - if (this->data_segment_align_index_ != -1U) + if (this->saw_data_segment_align_) gold_error(_("DATA_SEGMENT_ALIGN may only appear once in a linker script")); - this->data_segment_align_index_ = this->sections_elements_->size(); + gold_assert(!this->sections_elements_->empty()); + Sections_elements::iterator p = this->sections_elements_->end(); + --p; + this->data_segment_align_start_ = p; + this->saw_data_segment_align_ = true; } // This is called when we see DATA_SEGMENT_RELRO_END. It means that @@ -2407,14 +2727,13 @@ Script_sections::data_segment_relro_end() "in a linker script")); this->saw_relro_end_ = true; - if (this->data_segment_align_index_ == -1U) + if (!this->saw_data_segment_align_) gold_error(_("DATA_SEGMENT_RELRO_END must follow DATA_SEGMENT_ALIGN")); else { - for (size_t i = this->data_segment_align_index_; - i < this->sections_elements_->size(); - ++i) - (*this->sections_elements_)[i]->set_is_relro(); + Sections_elements::iterator p = this->data_segment_align_start_; + for (++p; p != this->sections_elements_->end(); ++p) + (*p)->set_is_relro(); } } @@ -2462,16 +2781,19 @@ Script_sections::finalize_symbols(Symbol_table* symtab, const Layout* layout) // and section name. const char* -Script_sections::output_section_name(const char* file_name, - const char* section_name, - Output_section*** output_section_slot) +Script_sections::output_section_name( + const char* file_name, + const char* section_name, + Output_section*** output_section_slot, + Script_sections::Section_type *psection_type) { for (Sections_elements::const_iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) { const char* ret = (*p)->output_section_name(file_name, section_name, - output_section_slot); + output_section_slot, + psection_type); if (ret != NULL) { @@ -2480,6 +2802,7 @@ Script_sections::output_section_name(const char* file_name, if (strcmp(ret, "/DISCARD/") == 0) { *output_section_slot = NULL; + *psection_type = Script_sections::ST_NONE; return NULL; } return ret; @@ -2490,6 +2813,7 @@ Script_sections::output_section_name(const char* file_name, // gets the name of the input section. *output_section_slot = NULL; + *psection_type = Script_sections::ST_NONE; return section_name; } @@ -2500,35 +2824,49 @@ Script_sections::output_section_name(const char* file_name, void Script_sections::place_orphan(Output_section* os) { - // Look for an output section definition which matches the output - // section. Put a marker after that section. - bool is_relro = false; - Sections_elements::iterator place = this->sections_elements_->end(); - for (Sections_elements::iterator p = this->sections_elements_->begin(); - p != this->sections_elements_->end(); - ++p) + Orphan_section_placement* osp = this->orphan_section_placement_; + if (osp == NULL) { - bool exact = false; - bool is_relro_here; - if ((*p)->place_orphan_here(os, &exact, &is_relro_here)) - { - place = p; - is_relro = is_relro_here; - if (exact) - break; - } + // Initialize the Orphan_section_placement structure. + osp = new Orphan_section_placement(); + for (Sections_elements::iterator p = this->sections_elements_->begin(); + p != this->sections_elements_->end(); + ++p) + (*p)->orphan_section_init(osp, p); + gold_assert(!this->sections_elements_->empty()); + Sections_elements::iterator last = this->sections_elements_->end(); + --last; + osp->last_init(last); + this->orphan_section_placement_ = osp; } - // The insert function puts the new element before the iterator. - if (place != this->sections_elements_->end()) - ++place; + Orphan_output_section* orphan = new Orphan_output_section(os); - this->sections_elements_->insert(place, new Orphan_output_section(os)); + // Look for where to put ORPHAN. + Sections_elements::iterator* where; + if (osp->find_place(os, &where)) + { + if ((**where)->is_relro()) + os->set_is_relro(); + else + os->clear_is_relro(); - if (is_relro) - os->set_is_relro(); + // We want to insert ORPHAN after *WHERE, and then update *WHERE + // so that the next one goes after this one. + Sections_elements::iterator p = *where; + gold_assert(p != this->sections_elements_->end()); + ++p; + *where = this->sections_elements_->insert(p, orphan); + } else - os->clear_is_relro(); + { + os->clear_is_relro(); + // We don't have a place to put this orphan section. Put it, + // and all other sections like it, at the end, but before the + // sections which always come at the end. + Sections_elements::iterator last = osp->last_place(); + *where = this->sections_elements_->insert(last, orphan); + } } // Set the addresses of all the output sections. Walk through all the @@ -2594,10 +2932,52 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) // For a relocatable link, we implicitly set dot to zero. uint64_t dot_value = 0; uint64_t load_address = 0; + + // Check to see if we want to use any of -Ttext, -Tdata and -Tbss options + // to set section addresses. If the script has any SEGMENT_START + // expression, we do not set the section addresses. + bool use_tsection_options = + (!this->saw_segment_start_expression_ + && (parameters->options().user_set_Ttext() + || parameters->options().user_set_Tdata() + || parameters->options().user_set_Tbss())); + for (Sections_elements::iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) - (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address); + { + Output_section* os = (*p)->get_output_section(); + + // Handle -Ttext, -Tdata and -Tbss options. We do this by looking for + // the special sections by names and doing dot assignments. + if (use_tsection_options + && os != NULL + && (os->flags() & elfcpp::SHF_ALLOC) != 0) + { + uint64_t new_dot_value = dot_value; + + if (parameters->options().user_set_Ttext() + && strcmp(os->name(), ".text") == 0) + new_dot_value = parameters->options().Ttext(); + else if (parameters->options().user_set_Tdata() + && strcmp(os->name(), ".data") == 0) + new_dot_value = parameters->options().Tdata(); + else if (parameters->options().user_set_Tbss() + && strcmp(os->name(), ".bss") == 0) + new_dot_value = parameters->options().Tbss(); + + // Update dot and load address if necessary. + if (new_dot_value < dot_value) + gold_error(_("dot may not move backward")); + else if (new_dot_value != dot_value) + { + dot_value = new_dot_value; + load_address = new_dot_value; + } + } + + (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address); + } if (this->phdrs_elements_ != NULL) { @@ -2649,6 +3029,12 @@ Sort_output_sections::operator()(const Output_section* os1, if (os1->type() == elfcpp::SHT_NOBITS && os2->type() == elfcpp::SHT_PROGBITS) return false; + // Sort non-NOLOAD before NOLOAD. + if (os1->is_noload() && !os2->is_noload()) + return true; + if (!os1->is_noload() && os2->is_noload()) + return true; + // Otherwise we don't care. return false; } @@ -2795,7 +3181,7 @@ Script_sections::create_segments(Layout* layout) is_current_seg_readonly = true; } - current_seg->add_output_section(*p, seg_flags); + current_seg->add_output_section(*p, seg_flags, false); if (((*p)->flags() & elfcpp::SHF_WRITE) != 0) is_current_seg_readonly = false; @@ -2822,6 +3208,11 @@ Script_sections::create_segments(Layout* layout) if (first_seg == NULL) return NULL; + // -n or -N mean that the program is not demand paged and there is + // no need to put the program headers in a PT_LOAD segment. + if (parameters->options().nmagic() || parameters->options().omagic()) + return NULL; + size_t sizeof_headers = this->total_header_size(layout); uint64_t vma = first_seg->vaddr(); @@ -2869,7 +3260,7 @@ Script_sections::create_note_and_tls_segments( Layout::section_flags_to_segment((*p)->flags()); Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE, seg_flags); - oseg->add_output_section(*p, seg_flags); + oseg->add_output_section(*p, seg_flags, false); // Incorporate any subsequent SHT_NOTE sections, in the // hopes that the script is sensible. @@ -2878,7 +3269,7 @@ Script_sections::create_note_and_tls_segments( && (*pnext)->type() == elfcpp::SHT_NOTE) { seg_flags = Layout::section_flags_to_segment((*pnext)->flags()); - oseg->add_output_section(*pnext, seg_flags); + oseg->add_output_section(*pnext, seg_flags, false); p = pnext; ++pnext; } @@ -2893,14 +3284,14 @@ Script_sections::create_note_and_tls_segments( Layout::section_flags_to_segment((*p)->flags()); Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS, seg_flags); - oseg->add_output_section(*p, seg_flags); + oseg->add_output_section(*p, seg_flags, false); Layout::Section_list::const_iterator pnext = p + 1; while (pnext != sections->end() && ((*pnext)->flags() & elfcpp::SHF_TLS) != 0) { seg_flags = Layout::section_flags_to_segment((*pnext)->flags()); - oseg->add_output_section(*pnext, seg_flags); + oseg->add_output_section(*pnext, seg_flags, false); p = pnext; ++pnext; } @@ -2912,7 +3303,7 @@ Script_sections::create_note_and_tls_segments( // Add a program header. The PHDRS clause is syntactically distinct // from the SECTIONS clause, but we implement it with the SECTIONS -// support becauase PHDRS is useless if there is no SECTIONS clause. +// support because PHDRS is useless if there is no SECTIONS clause. void Script_sections::add_phdr(const char* name, size_t namelen, unsigned int type, @@ -3001,12 +3392,15 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // Output sections in the script which do not list segments are // attached to the same set of segments as the immediately preceding // output section. + String_list* phdr_names = NULL; + bool load_segments_only = false; for (Sections_elements::const_iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) { bool orphan; + String_list* old_phdr_names = phdr_names; Output_section* os = (*p)->allocate_to_segment(&phdr_names, &orphan); if (os == NULL) continue; @@ -3017,6 +3411,11 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) continue; } + // We see a list of segments names. Disable PT_LOAD segment only + // filtering. + if (old_phdr_names != phdr_names) + load_segments_only = false; + // If this is an orphan section--one that was not explicitly // mentioned in the linker script--then it should not inherit // any segment type other than PT_LOAD. Otherwise, e.g., the @@ -3025,17 +3424,9 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) // we trust the linker script. if (orphan) { - String_list::iterator q = phdr_names->begin(); - while (q != phdr_names->end()) - { - Name_to_segment::const_iterator r = name_to_segment.find(*q); - // We give errors about unknown segments below. - if (r == name_to_segment.end() - || r->second->type() == elfcpp::PT_LOAD) - ++q; - else - q = phdr_names->erase(q); - } + // Enable PT_LOAD segments only filtering until we see another + // list of segment names. + load_segments_only = true; } bool in_load_segment = false; @@ -3048,9 +3439,13 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) gold_error(_("no segment %s"), q->c_str()); else { + if (load_segments_only + && r->second->type() != elfcpp::PT_LOAD) + continue; + elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(os->flags()); - r->second->add_output_section(os, seg_flags); + r->second->add_output_section(os, seg_flags, false); if (r->second->type() == elfcpp::PT_LOAD) { @@ -3202,6 +3597,21 @@ Script_sections::get_output_section_info(const char* name, uint64_t* address, return false; } +// Release all Output_segments. This remove all pointers to all +// Output_segments. + +void +Script_sections::release_segments() +{ + if (this->saw_phdrs_clause()) + { + for (Phdrs_elements::const_iterator p = this->phdrs_elements_->begin(); + p != this->phdrs_elements_->end(); + ++p) + (*p)->release_segment(); + } +} + // Print the SECTIONS clause to F for debugging. void diff --git a/binutils-2.19/gold/script-sections.h b/binutils-2.19/gold/script-sections.h index 465c24e..725d1a2 100644 --- a/binutils-2.19/gold/script-sections.h +++ b/binutils-2.19/gold/script-sections.h @@ -1,6 +1,6 @@ // script-sections.h -- linker script SECTIONS for gold -*- C++ -*- -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -26,6 +26,7 @@ #define GOLD_SCRIPT_SECTIONS_H #include <cstdio> +#include <list> #include <vector> namespace gold @@ -41,10 +42,30 @@ class Output_data; class Output_section_definition; class Output_section; class Output_segment; +class Orphan_section_placement; class Script_sections { + private: + // This is a list, not a vector, because we insert orphan sections + // in the middle. + typedef std::list<Sections_element*> Sections_elements; + public: + + // Logical script section types. We map section types returned by the + // parser into these since some section types have the same semantics. + enum Section_type + { + // No section type specified. + ST_NONE, + // Section is NOLOAD. We allocate space in the output but section + // is not loaded in runtime. + ST_NOLOAD, + // No space is allocated to section. + ST_NOALLOC + }; + Script_sections(); // Start a SECTIONS clause. @@ -140,9 +161,13 @@ class Script_sections // 3) If the input section is not mapped by the SECTIONS clause, // this returns SECTION_NAME, and sets *OUTPUT_SECTION_SLOT to // NULL. + // PSCRIPT_SECTION_TYPE points to a location for returning the section + // type specified in script. This can be SCRIPT_SECTION_TYPE_NONE if + // no type is specified. const char* output_section_name(const char* file_name, const char* section_name, - Output_section*** output_section_slot); + Output_section*** output_section_slot, + Section_type* pscript_section_type); // Place a marker for an orphan output section into the SECTIONS // clause. @@ -180,13 +205,29 @@ class Script_sections uint64_t* load_address, uint64_t* addralign, uint64_t* size) const; + // Release all Output_segments. This is used in relaxation. + void + release_segments(); + + // Whether we ever saw a SEGMENT_START expression, the presence of which + // changes the behaviour of -Ttext, -Tdata and -Tbss options. + bool + saw_segment_start_expression() const + { return this->saw_segment_start_expression_; } + + // Set the flag which indicates whether we saw a SEGMENT_START expression. + void + set_saw_segment_start_expression(bool value) + { this->saw_segment_start_expression_ = value; } + // Print the contents to the FILE. This is for debugging. void print(FILE*) const; - private: - typedef std::vector<Sections_element*> Sections_elements; + // Used for orphan sections. + typedef Sections_elements::iterator Elements_iterator; + private: typedef std::vector<Phdrs_element*> Phdrs_elements; // Create segments. @@ -232,11 +273,17 @@ class Script_sections Output_section_definition* output_section_; // The list of program headers in the PHDRS clause. Phdrs_elements* phdrs_elements_; - // The index of the next Sections_element when we see + // Where to put orphan sections. + Orphan_section_placement* orphan_section_placement_; + // A pointer to the last Sections_element when we see // DATA_SEGMENT_ALIGN. - size_t data_segment_align_index_; + Sections_elements::iterator data_segment_align_start_; + // Whether we have seen DATA_SEGMENT_ALIGN. + bool saw_data_segment_align_; // Whether we have seen DATA_SEGMENT_RELRO_END. bool saw_relro_end_; + // Whether we have seen SEGMENT_START. + bool saw_segment_start_expression_; }; } // End namespace gold. diff --git a/binutils-2.19/gold/script.cc b/binutils-2.19/gold/script.cc index 53fcf66..199e7b6 100644 --- a/binutils-2.19/gold/script.cc +++ b/binutils-2.19/gold/script.cc @@ -1,6 +1,6 @@ // script.cc -- handle linker scripts for gold. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -40,8 +40,10 @@ #include "parameters.h" #include "layout.h" #include "symtab.h" +#include "target-select.h" #include "script.h" #include "script-c.h" +#include "incremental.h" namespace gold { @@ -184,7 +186,9 @@ class Lex // Reading an expression in a linker script. EXPRESSION, // Reading a version script. - VERSION_SCRIPT + VERSION_SCRIPT, + // Reading a --dynamic-list file. + DYNAMIC_LIST }; Lex(const char* input_string, size_t input_length, int parsing_token) @@ -393,8 +397,9 @@ Lex::can_start_name(char c, char c2) case '~': return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2); - case '*': case '[': + case '*': case '[': return (this->mode_ == VERSION_SCRIPT + || this->mode_ == DYNAMIC_LIST || (this->mode_ == LINKER_SCRIPT && can_continue_name(&c2))); @@ -429,6 +434,7 @@ Lex::can_continue_name(const char* c) case '5': case '6': case '7': case '8': case '9': return c + 1; + // TODO(csilvers): why not allow ~ in names for version-scripts? case '/': case '\\': case '~': case '=': case '+': case ',': @@ -437,19 +443,22 @@ Lex::can_continue_name(const char* c) return NULL; case '[': case ']': case '*': case '?': case '-': - if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT) + if (this->mode_ == LINKER_SCRIPT || this->mode_ == VERSION_SCRIPT + || this->mode_ == DYNAMIC_LIST) return c + 1; return NULL; + // TODO(csilvers): why allow this? ^ is meaningless in version scripts. case '^': - if (this->mode_ == VERSION_SCRIPT) + if (this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST) return c + 1; return NULL; case ':': if (this->mode_ == LINKER_SCRIPT) return c + 1; - else if (this->mode_ == VERSION_SCRIPT && (c[1] == ':')) + else if ((this->mode_ == VERSION_SCRIPT || this->mode_ == DYNAMIC_LIST) + && (c[1] == ':')) { // A name can have '::' in it, as that's a c++ namespace // separator. But a single colon is not part of a name. @@ -734,7 +743,7 @@ Lex::get_token(const char** pp) } // Skip whitespace quickly. - while (*p == ' ' || *p == '\t') + while (*p == ' ' || *p == '\t' || *p == '\r') ++p; if (*p == '\n') @@ -865,6 +874,9 @@ Symbol_assignment::add_to_table(Symbol_table* symtab) elfcpp::STV vis = this->hidden_ ? elfcpp::STV_HIDDEN : elfcpp::STV_DEFAULT; this->sym_ = symtab->define_as_constant(this->name_.c_str(), NULL, // version + (this->is_defsym_ + ? Symbol_table::DEFSYM + : Symbol_table::SCRIPT), 0, // value 0, // size elfcpp::STT_NOTYPE, @@ -1042,18 +1054,21 @@ Script_options::Script_options() void Script_options::add_symbol_assignment(const char* name, size_t length, - Expression* value, bool provide, - bool hidden) + bool is_defsym, Expression* value, + bool provide, bool hidden) { if (length != 1 || name[0] != '.') { if (this->script_sections_.in_sections_clause()) - this->script_sections_.add_symbol_assignment(name, length, value, - provide, hidden); - else { - Symbol_assignment* p = new Symbol_assignment(name, length, value, + gold_assert(!is_defsym); + this->script_sections_.add_symbol_assignment(name, length, value, provide, hidden); + } + else + { + Symbol_assignment* p = new Symbol_assignment(name, length, is_defsym, + value, provide, hidden); this->symbol_assignments_.push_back(p); } } @@ -1061,10 +1076,11 @@ Script_options::add_symbol_assignment(const char* name, size_t length, { if (provide || hidden) gold_error(_("invalid use of PROVIDE for dot symbol")); - if (!this->script_sections_.in_sections_clause()) - gold_error(_("invalid assignment to dot outside of SECTIONS")); - else - this->script_sections_.add_dot_assignment(value); + + // The GNU linker permits assignments to dot outside of SECTIONS + // clauses and treats them as occurring inside, so we don't + // check in_sections_clause here. + this->script_sections_.add_dot_assignment(value); } } @@ -1152,19 +1168,23 @@ class Parser_closure public: Parser_closure(const char* filename, const Position_dependent_options& posdep_options, - bool in_group, bool is_in_sysroot, + bool parsing_defsym, bool in_group, bool is_in_sysroot, Command_line* command_line, Script_options* script_options, - Lex* lex) + Lex* lex, + bool skip_on_incompatible_target) : filename_(filename), posdep_options_(posdep_options), - in_group_(in_group), is_in_sysroot_(is_in_sysroot), + parsing_defsym_(parsing_defsym), in_group_(in_group), + is_in_sysroot_(is_in_sysroot), + skip_on_incompatible_target_(skip_on_incompatible_target), + found_incompatible_target_(false), command_line_(command_line), script_options_(script_options), version_script_info_(script_options->version_script_info()), lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL) - { + { // We start out processing C symbols in the default lex mode. - language_stack_.push_back(""); - lex_mode_stack_.push_back(lex->mode()); + this->language_stack_.push_back(Version_script_info::LANGUAGE_C); + this->lex_mode_stack_.push_back(lex->mode()); } // Return the file name. @@ -1178,6 +1198,11 @@ class Parser_closure position_dependent_options() { return this->posdep_options_; } + // Whether we are parsing a --defsym. + bool + parsing_defsym() const + { return this->parsing_defsym_; } + // Return whether this script is being run in a group. bool in_group() const @@ -1189,6 +1214,30 @@ class Parser_closure is_in_sysroot() const { return this->is_in_sysroot_; } + // Whether to skip to the next file with the same name if we find an + // incompatible target in an OUTPUT_FORMAT statement. + bool + skip_on_incompatible_target() const + { return this->skip_on_incompatible_target_; } + + // Stop skipping to the next file on an incompatible target. This + // is called when we make some unrevocable change to the data + // structures. + void + clear_skip_on_incompatible_target() + { this->skip_on_incompatible_target_ = false; } + + // Whether we found an incompatible target in an OUTPUT_FORMAT + // statement. + bool + found_incompatible_target() const + { return this->found_incompatible_target_; } + + // Note that we found an incompatible target. + void + set_found_incompatible_target() + { this->found_incompatible_target_ = true; } + // Returns the Command_line structure passed in at constructor time. // This value may be NULL. The caller may modify this, which modifies // the passed-in Command_line object (not a copy). @@ -1265,16 +1314,18 @@ class Parser_closure // Return the current language being processed in a version script // (eg, "C++"). The empty string represents unmangled C names. - const std::string& + Version_script_info::Language get_current_language() const { return this->language_stack_.back(); } // Push a language onto the stack when entering an extern block. - void push_language(const std::string& lang) + void + push_language(Version_script_info::Language lang) { this->language_stack_.push_back(lang); } // Pop a language off of the stack when exiting an extern block. - void pop_language() + void + pop_language() { gold_assert(!this->language_stack_.empty()); this->language_stack_.pop_back(); @@ -1285,10 +1336,18 @@ class Parser_closure const char* filename_; // The position dependent options. Position_dependent_options posdep_options_; + // True if we are parsing a --defsym. + bool parsing_defsym_; // Whether we are currently in a --start-group/--end-group. bool in_group_; // Whether the script was found in a sysrooted directory. bool is_in_sysroot_; + // If this is true, then if we find an OUTPUT_FORMAT with an + // incompatible target, then we tell the parser to abort so that we + // can search for the next file with the same name. + bool skip_on_incompatible_target_; + // True if we found an OUTPUT_FORMAT with an incompatible target. + bool found_incompatible_target_; // May be NULL if the user chooses not to pass one in. Command_line* command_line_; // Options which may be set from any linker script. @@ -1305,7 +1364,7 @@ class Parser_closure std::vector<Lex::Mode> lex_mode_stack_; // A stack of which extern/language block we're inside. Can be C++, // java, or empty for C. - std::vector<std::string> language_stack_; + std::vector<Version_script_info::Language> language_stack_; // New input files found to add to the link. Input_arguments* inputs_; }; @@ -1314,10 +1373,10 @@ class Parser_closure // as a script. Return true if the file was handled. bool -read_input_script(Workqueue* workqueue, const General_options& options, - Symbol_table* symtab, Layout* layout, - Dirsearch* dirsearch, Input_objects* input_objects, - Mapfile* mapfile, Input_group* input_group, +read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout, + Dirsearch* dirsearch, int dirindex, + Input_objects* input_objects, Mapfile* mapfile, + Input_group* input_group, const Input_argument* input_argument, Input_file* input_file, Task_token* next_blocker, bool* used_next_blocker) @@ -1331,14 +1390,35 @@ read_input_script(Workqueue* workqueue, const General_options& options, Parser_closure closure(input_file->filename().c_str(), input_argument->file().options(), + false, input_group != NULL, input_file->is_in_sysroot(), NULL, layout->script_options(), - &lex); + &lex, + input_file->will_search_for()); + + bool old_saw_sections_clause = + layout->script_options()->saw_sections_clause(); if (yyparse(&closure) != 0) - return false; + { + if (closure.found_incompatible_target()) + { + Read_symbols::incompatible_warning(input_argument, input_file); + Read_symbols::requeue(workqueue, input_objects, symtab, layout, + dirsearch, dirindex, mapfile, input_argument, + input_group, next_blocker); + return true; + } + return false; + } + + if (!old_saw_sections_clause + && layout->script_options()->saw_sections_clause() + && layout->have_added_input_section()) + gold_error(_("%s: SECTIONS seen after other input files; try -T/--script"), + input_file->filename().c_str()); if (!closure.saw_inputs()) return true; @@ -1356,12 +1436,22 @@ read_input_script(Workqueue* workqueue, const General_options& options, nb = new Task_token(true); nb->add_blocker(); } - workqueue->queue_soon(new Read_symbols(options, input_objects, symtab, - layout, dirsearch, mapfile, &*p, + workqueue->queue_soon(new Read_symbols(input_objects, symtab, + layout, dirsearch, 0, mapfile, &*p, input_group, this_blocker, nb)); this_blocker = nb; } + if (layout->incremental_inputs()) + { + // Like new Read_symbols(...) above, we rely on close.inputs() + // getting leaked by closure. + Script_info* info = new Script_info(closure.inputs()); + layout->incremental_inputs()->report_script( + input_argument, + input_file->file().get_mtime(), + info); + } *used_next_blocker = true; return true; @@ -1373,6 +1463,7 @@ read_input_script(Workqueue* workqueue, const General_options& options, static bool read_script_file(const char* filename, Command_line* cmdline, + Script_options* script_options, int first_token, Lex::Mode lex_mode) { // TODO: if filename is a relative filename, search for it manually @@ -1388,9 +1479,12 @@ read_script_file(const char* filename, Command_line* cmdline, Position_dependent_options posdep = cmdline->position_dependent_options(); if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY) posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF); - Input_file_argument input_argument(filename, false, "", false, posdep); + Input_file_argument input_argument(filename, + Input_file_argument::INPUT_FILE_TYPE_FILE, + "", false, posdep); Input_file input_file(&input_argument); - if (!input_file.open(cmdline->options(), dirsearch, task)) + int dummy = 0; + if (!input_file.open(dirsearch, task, &dummy)) return false; std::string input_string; @@ -1401,11 +1495,13 @@ read_script_file(const char* filename, Command_line* cmdline, Parser_closure closure(filename, cmdline->position_dependent_options(), + first_token == Lex::DYNAMIC_LIST, false, input_file.is_in_sysroot(), cmdline, - &cmdline->script_options(), - &lex); + script_options, + &lex, + false); if (yyparse(&closure) != 0) { input_file.file().unlock(task); @@ -1425,21 +1521,32 @@ read_script_file(const char* filename, Command_line* cmdline, bool read_commandline_script(const char* filename, Command_line* cmdline) { - return read_script_file(filename, cmdline, + return read_script_file(filename, cmdline, &cmdline->script_options(), PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT); } -// FILE was found as an argument to --version-script. Read it as a -// version script, and store its contents in +// FILENAME was found as an argument to --version-script. Read it as +// a version script, and store its contents in // cmdline->script_options()->version_script_info(). bool read_version_script(const char* filename, Command_line* cmdline) { - return read_script_file(filename, cmdline, + return read_script_file(filename, cmdline, &cmdline->script_options(), PARSING_VERSION_SCRIPT, Lex::VERSION_SCRIPT); } +// FILENAME was found as an argument to --dynamic-list. Read it as a +// list of symbols, and store its contents in DYNAMIC_LIST. + +bool +read_dynamic_list(const char* filename, Command_line* cmdline, + Script_options* dynamic_list) +{ + return read_script_file(filename, cmdline, dynamic_list, + PARSING_DYNAMIC_LIST, Lex::DYNAMIC_LIST); +} + // Implement the --defsym option on the command line. Return true if // all is well. @@ -1452,8 +1559,8 @@ Script_options::define_symbol(const char* definition) // Dummy value. Position_dependent_options posdep_options; - Parser_closure closure("command line", posdep_options, false, false, NULL, - this, &lex); + Parser_closure closure("command line", posdep_options, true, + false, false, NULL, this, &lex, false); if (yyparse(&closure) != 0) return false; @@ -1539,11 +1646,13 @@ script_keyword_parsecodes[] = { "BYTE", BYTE }, { "CONSTANT", CONSTANT }, { "CONSTRUCTORS", CONSTRUCTORS }, + { "COPY", COPY }, { "CREATE_OBJECT_SYMBOLS", CREATE_OBJECT_SYMBOLS }, { "DATA_SEGMENT_ALIGN", DATA_SEGMENT_ALIGN }, { "DATA_SEGMENT_END", DATA_SEGMENT_END }, { "DATA_SEGMENT_RELRO_END", DATA_SEGMENT_RELRO_END }, { "DEFINED", DEFINED }, + { "DSECT", DSECT }, { "ENTRY", ENTRY }, { "EXCLUDE_FILE", EXCLUDE_FILE }, { "EXTERN", EXTERN }, @@ -1553,6 +1662,7 @@ script_keyword_parsecodes[] = { "GROUP", GROUP }, { "HLL", HLL }, { "INCLUDE", INCLUDE }, + { "INFO", INFO }, { "INHIBIT_COMMON_ALLOCATION", INHIBIT_COMMON_ALLOCATION }, { "INPUT", INPUT }, { "KEEP", KEEP }, @@ -1566,6 +1676,7 @@ script_keyword_parsecodes[] = { "NEXT", NEXT }, { "NOCROSSREFS", NOCROSSREFS }, { "NOFLOAT", NOFLOAT }, + { "NOLOAD", NOLOAD }, { "ONLY_IF_RO", ONLY_IF_RO }, { "ONLY_IF_RW", ONLY_IF_RW }, { "OPTION", OPTION }, @@ -1622,6 +1733,19 @@ version_script_keywords(&version_script_keyword_parsecodes[0], (sizeof(version_script_keyword_parsecodes) / sizeof(version_script_keyword_parsecodes[0]))); +static const Keyword_to_parsecode::Keyword_parsecode +dynamic_list_keyword_parsecodes[] = +{ + { "extern", EXTERN }, +}; + +static const Keyword_to_parsecode +dynamic_list_keywords(&dynamic_list_keyword_parsecodes[0], + (sizeof(dynamic_list_keyword_parsecodes) + / sizeof(dynamic_list_keyword_parsecodes[0]))); + + + // Comparison function passed to bsearch. extern "C" @@ -1673,38 +1797,45 @@ Keyword_to_parsecode::keyword_to_parsecode(const char* keyword, // A single version expression. // For example, pattern="std::map*" and language="C++". -// pattern and language should be from the stringpool -struct Version_expression { - Version_expression(const std::string& pattern, - const std::string& language, - bool exact_match) - : pattern(pattern), language(language), exact_match(exact_match) {} +struct Version_expression +{ + Version_expression(const std::string& a_pattern, + Version_script_info::Language a_language, + bool a_exact_match) + : pattern(a_pattern), language(a_language), exact_match(a_exact_match), + was_matched_by_symbol(false) + { } std::string pattern; - std::string language; + Version_script_info::Language language; // If false, we use glob() to match pattern. If true, we use strcmp(). bool exact_match; + // True if --no-undefined-version is in effect and we found this + // version in get_symbol_version. We use mutable because this + // struct is generally not modifiable after it has been created. + mutable bool was_matched_by_symbol; }; - // A list of expressions. -struct Version_expression_list { +struct Version_expression_list +{ std::vector<struct Version_expression> expressions; }; - // A list of which versions upon which another version depends. // Strings should be from the Stringpool. -struct Version_dependency_list { +struct Version_dependency_list +{ std::vector<std::string> dependencies; }; - // The total definition of a version. It includes the tag for the // version, its global and local expressions, and any dependencies. -struct Version_tree { +struct Version_tree +{ Version_tree() - : tag(), global(NULL), local(NULL), dependencies(NULL) {} + : tag(), global(NULL), local(NULL), dependencies(NULL) + { } std::string tag; const struct Version_expression_list* global; @@ -1712,44 +1843,116 @@ struct Version_tree { const struct Version_dependency_list* dependencies; }; +// Helper class that calls cplus_demangle when needed and takes care of freeing +// the result. + +class Lazy_demangler +{ + public: + Lazy_demangler(const char* symbol, int options) + : symbol_(symbol), options_(options), demangled_(NULL), did_demangle_(false) + { } + + ~Lazy_demangler() + { free(this->demangled_); } + + // Return the demangled name. The actual demangling happens on the first call, + // and the result is later cached. + inline char* + get(); + + private: + // The symbol to demangle. + const char *symbol_; + // Option flags to pass to cplus_demagle. + const int options_; + // The cached demangled value, or NULL if demangling didn't happen yet or + // failed. + char *demangled_; + // Whether we already called cplus_demangle + bool did_demangle_; +}; + +// Return the demangled name. The actual demangling happens on the first call, +// and the result is later cached. Returns NULL if the symbol cannot be +// demangled. + +inline char* +Lazy_demangler::get() +{ + if (!this->did_demangle_) + { + this->demangled_ = cplus_demangle(this->symbol_, this->options_); + this->did_demangle_ = true; + } + return this->demangled_; +} + +// Class Version_script_info. + +Version_script_info::Version_script_info() + : dependency_lists_(), expression_lists_(), version_trees_(), globs_(), + default_version_(NULL), default_is_global_(false), is_finalized_(false) +{ + for (int i = 0; i < LANGUAGE_COUNT; ++i) + this->exact_[i] = NULL; +} + Version_script_info::~Version_script_info() { - this->clear(); } +// Forget all the known version script information. + void Version_script_info::clear() { - for (size_t k = 0; k < dependency_lists_.size(); ++k) - delete dependency_lists_[k]; + for (size_t k = 0; k < this->dependency_lists_.size(); ++k) + delete this->dependency_lists_[k]; this->dependency_lists_.clear(); - for (size_t k = 0; k < version_trees_.size(); ++k) - delete version_trees_[k]; + for (size_t k = 0; k < this->version_trees_.size(); ++k) + delete this->version_trees_[k]; this->version_trees_.clear(); - for (size_t k = 0; k < expression_lists_.size(); ++k) - delete expression_lists_[k]; + for (size_t k = 0; k < this->expression_lists_.size(); ++k) + delete this->expression_lists_[k]; this->expression_lists_.clear(); } +// Finalize the version script information. + +void +Version_script_info::finalize() +{ + if (!this->is_finalized_) + { + this->build_lookup_tables(); + this->is_finalized_ = true; + } +} + +// Return all the versions. + std::vector<std::string> Version_script_info::get_versions() const { std::vector<std::string> ret; - for (size_t j = 0; j < version_trees_.size(); ++j) + for (size_t j = 0; j < this->version_trees_.size(); ++j) if (!this->version_trees_[j]->tag.empty()) ret.push_back(this->version_trees_[j]->tag); return ret; } +// Return the dependencies of VERSION. + std::vector<std::string> Version_script_info::get_dependencies(const char* version) const { std::vector<std::string> ret; - for (size_t j = 0; j < version_trees_.size(); ++j) - if (version_trees_[j]->tag == version) + for (size_t j = 0; j < this->version_trees_.size(); ++j) + if (this->version_trees_[j]->tag == version) { const struct Version_dependency_list* deps = - version_trees_[j]->dependencies; + this->version_trees_[j]->dependencies; if (deps != NULL) for (size_t k = 0; k < deps->dependencies.size(); ++k) ret.push_back(deps->dependencies[k]); @@ -1758,66 +1961,389 @@ Version_script_info::get_dependencies(const char* version) const return ret; } -// Look up SYMBOL_NAME in the list of versions. If CHECK_GLOBAL is -// true look at the globally visible symbols, otherwise look at the -// symbols listed as "local:". Return true if the symbol is found, -// false otherwise. If the symbol is found, then if PVERSION is not -// NULL, set *PVERSION to the version. +// A version script essentially maps a symbol name to a version tag +// and an indication of whether symbol is global or local within that +// version tag. Each symbol maps to at most one version tag. +// Unfortunately, in practice, version scripts are ambiguous, and list +// symbols multiple times. Thus, we have to document the matching +// process. + +// This is a description of what the GNU linker does as of 2010-01-11. +// It walks through the version tags in the order in which they appear +// in the version script. For each tag, it first walks through the +// global patterns for that tag, then the local patterns. When +// looking at a single pattern, it first applies any language specific +// demangling as specified for the pattern, and then matches the +// resulting symbol name to the pattern. If it finds an exact match +// for a literal pattern (a pattern enclosed in quotes or with no +// wildcard characters), then that is the match that it uses. If +// finds a match with a wildcard pattern, then it saves it and +// continues searching. Wildcard patterns that are exactly "*" are +// saved separately. + +// If no exact match with a literal pattern is ever found, then if a +// wildcard match with a global pattern was found it is used, +// otherwise if a wildcard match with a local pattern was found it is +// used. + +// This is the result: +// * If there is an exact match, then we use the first tag in the +// version script where it matches. +// + If the exact match in that tag is global, it is used. +// + Otherwise the exact match in that tag is local, and is used. +// * Otherwise, if there is any match with a global wildcard pattern: +// + If there is any match with a wildcard pattern which is not +// "*", then we use the tag in which the *last* such pattern +// appears. +// + Otherwise, we matched "*". If there is no match with a local +// wildcard pattern which is not "*", then we use the *last* +// match with a global "*". Otherwise, continue. +// * Otherwise, if there is any match with a local wildcard pattern: +// + If there is any match with a wildcard pattern which is not +// "*", then we use the tag in which the *last* such pattern +// appears. +// + Otherwise, we matched "*", and we use the tag in which the +// *last* such match occurred. + +// There is an additional wrinkle. When the GNU linker finds a symbol +// with a version defined in an object file due to a .symver +// directive, it looks up that symbol name in that version tag. If it +// finds it, it matches the symbol name against the patterns for that +// version. If there is no match with a global pattern, but there is +// a match with a local pattern, then the GNU linker marks the symbol +// as local. + +// We want gold to be generally compatible, but we also want gold to +// be fast. These are the rules that gold implements: +// * If there is an exact match for the mangled name, we use it. +// + If there is more than one exact match, we give a warning, and +// we use the first tag in the script which matches. +// + If a symbol has an exact match as both global and local for +// the same version tag, we give an error. +// * Otherwise, we look for an extern C++ or an extern Java exact +// match. If we find an exact match, we use it. +// + If there is more than one exact match, we give a warning, and +// we use the first tag in the script which matches. +// + If a symbol has an exact match as both global and local for +// the same version tag, we give an error. +// * Otherwise, we look through the wildcard patterns, ignoring "*" +// patterns. We look through the version tags in reverse order. +// For each version tag, we look through the global patterns and +// then the local patterns. We use the first match we find (i.e., +// the last matching version tag in the file). +// * Otherwise, we use the "*" pattern if there is one. We give an +// error if there are multiple "*" patterns. + +// At least for now, gold does not look up the version tag for a +// symbol version found in an object file to see if it should be +// forced local. There are other ways to force a symbol to be local, +// and I don't understand why this one is useful. + +// Build a set of fast lookup tables for a version script. + +void +Version_script_info::build_lookup_tables() +{ + size_t size = this->version_trees_.size(); + for (size_t j = 0; j < size; ++j) + { + const Version_tree* v = this->version_trees_[j]; + this->build_expression_list_lookup(v->local, v, false); + this->build_expression_list_lookup(v->global, v, true); + } +} + +// If a pattern has backlashes but no unquoted wildcard characters, +// then we apply backslash unquoting and look for an exact match. +// Otherwise we treat it as a wildcard pattern. This function returns +// true for a wildcard pattern. Otherwise, it does backslash +// unquoting on *PATTERN and returns false. If this returns true, +// *PATTERN may have been partially unquoted. bool -Version_script_info::get_symbol_version_helper(const char* symbol_name, - bool check_global, - std::string* pversion) const +Version_script_info::unquote(std::string* pattern) const { - for (size_t j = 0; j < version_trees_.size(); ++j) + bool saw_backslash = false; + size_t len = pattern->length(); + size_t j = 0; + for (size_t i = 0; i < len; ++i) { - // Is it a global symbol for this version? - const Version_expression_list* explist = - check_global ? version_trees_[j]->global : version_trees_[j]->local; - if (explist != NULL) - for (size_t k = 0; k < explist->expressions.size(); ++k) - { - const char* name_to_match = symbol_name; - const struct Version_expression& exp = explist->expressions[k]; - char* demangled_name = NULL; - if (exp.language == "C++") - { - demangled_name = cplus_demangle(symbol_name, - DMGL_ANSI | DMGL_PARAMS); - // This isn't a C++ symbol. - if (demangled_name == NULL) - continue; - name_to_match = demangled_name; - } - else if (exp.language == "Java") - { - demangled_name = cplus_demangle(symbol_name, - (DMGL_ANSI | DMGL_PARAMS - | DMGL_JAVA)); - // This isn't a Java symbol. - if (demangled_name == NULL) - continue; - name_to_match = demangled_name; - } - bool matched; - if (exp.exact_match) - matched = strcmp(exp.pattern.c_str(), name_to_match) == 0; - else - matched = fnmatch(exp.pattern.c_str(), name_to_match, - FNM_NOESCAPE) == 0; - if (demangled_name != NULL) - free(demangled_name); - if (matched) - { - if (pversion != NULL) - *pversion = this->version_trees_[j]->tag; - return true; - } - } + if (saw_backslash) + saw_backslash = false; + else + { + switch ((*pattern)[i]) + { + case '?': case '[': case '*': + return true; + case '\\': + saw_backslash = true; + continue; + default: + break; + } + } + + if (i != j) + (*pattern)[j] = (*pattern)[i]; + ++j; + } + return false; +} + +// Add an exact match for MATCH to *PE. The result of the match is +// V/IS_GLOBAL. + +void +Version_script_info::add_exact_match(const std::string& match, + const Version_tree* v, bool is_global, + const Version_expression* ve, + Exact *pe) +{ + std::pair<Exact::iterator, bool> ins = + pe->insert(std::make_pair(match, Version_tree_match(v, is_global, ve))); + if (ins.second) + { + // This is the first time we have seen this match. + return; } + + Version_tree_match& vtm(ins.first->second); + if (vtm.real->tag != v->tag) + { + // This is an ambiguous match. We still return the + // first version that we found in the script, but we + // record the new version to issue a warning if we + // wind up looking up this symbol. + if (vtm.ambiguous == NULL) + vtm.ambiguous = v; + } + else if (is_global != vtm.is_global) + { + // We have a match for both the global and local entries for a + // version tag. That's got to be wrong. + gold_error(_("'%s' appears as both a global and a local symbol " + "for version '%s' in script"), + match.c_str(), v->tag.c_str()); + } +} + +// Build fast lookup information for EXPLIST and store it in LOOKUP. +// All matches go to V, and IS_GLOBAL is true if they are global +// matches. + +void +Version_script_info::build_expression_list_lookup( + const Version_expression_list* explist, + const Version_tree* v, + bool is_global) +{ + if (explist == NULL) + return; + size_t size = explist->expressions.size(); + for (size_t i = 0; i < size; ++i) + { + const Version_expression& exp(explist->expressions[i]); + + if (exp.pattern.length() == 1 && exp.pattern[0] == '*') + { + if (this->default_version_ != NULL + && this->default_version_->tag != v->tag) + gold_warning(_("wildcard match appears in both version '%s' " + "and '%s' in script"), + this->default_version_->tag.c_str(), v->tag.c_str()); + else if (this->default_version_ != NULL + && this->default_is_global_ != is_global) + gold_error(_("wildcard match appears as both global and local " + "in version '%s' in script"), + v->tag.c_str()); + this->default_version_ = v; + this->default_is_global_ = is_global; + continue; + } + + std::string pattern = exp.pattern; + if (!exp.exact_match) + { + if (this->unquote(&pattern)) + { + this->globs_.push_back(Glob(&exp, v, is_global)); + continue; + } + } + + if (this->exact_[exp.language] == NULL) + this->exact_[exp.language] = new Exact(); + this->add_exact_match(pattern, v, is_global, &exp, + this->exact_[exp.language]); + } +} + +// Return the name to match given a name, a language code, and two +// lazy demanglers. + +const char* +Version_script_info::get_name_to_match(const char* name, + int language, + Lazy_demangler* cpp_demangler, + Lazy_demangler* java_demangler) const +{ + switch (language) + { + case LANGUAGE_C: + return name; + case LANGUAGE_CXX: + return cpp_demangler->get(); + case LANGUAGE_JAVA: + return java_demangler->get(); + default: + gold_unreachable(); + } +} + +// Look up SYMBOL_NAME in the list of versions. Return true if the +// symbol is found, false if not. If the symbol is found, then if +// PVERSION is not NULL, set *PVERSION to the version tag, and if +// P_IS_GLOBAL is not NULL, set *P_IS_GLOBAL according to whether the +// symbol is global or not. + +bool +Version_script_info::get_symbol_version(const char* symbol_name, + std::string* pversion, + bool* p_is_global) const +{ + Lazy_demangler cpp_demangled_name(symbol_name, DMGL_ANSI | DMGL_PARAMS); + Lazy_demangler java_demangled_name(symbol_name, + DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA); + + gold_assert(this->is_finalized_); + for (int i = 0; i < LANGUAGE_COUNT; ++i) + { + Exact* exact = this->exact_[i]; + if (exact == NULL) + continue; + + const char* name_to_match = this->get_name_to_match(symbol_name, i, + &cpp_demangled_name, + &java_demangled_name); + if (name_to_match == NULL) + { + // If the name can not be demangled, the GNU linker goes + // ahead and tries to match it anyhow. That does not + // make sense to me and I have not implemented it. + continue; + } + + Exact::const_iterator pe = exact->find(name_to_match); + if (pe != exact->end()) + { + const Version_tree_match& vtm(pe->second); + if (vtm.ambiguous != NULL) + gold_warning(_("using '%s' as version for '%s' which is also " + "named in version '%s' in script"), + vtm.real->tag.c_str(), name_to_match, + vtm.ambiguous->tag.c_str()); + + if (pversion != NULL) + *pversion = vtm.real->tag; + if (p_is_global != NULL) + *p_is_global = vtm.is_global; + + // If we are using --no-undefined-version, and this is a + // global symbol, we have to record that we have found this + // symbol, so that we don't warn about it. We have to do + // this now, because otherwise we have no way to get from a + // non-C language back to the demangled name that we + // matched. + if (p_is_global != NULL && vtm.is_global) + vtm.expression->was_matched_by_symbol = true; + + return true; + } + } + + // Look through the glob patterns in reverse order. + + for (Globs::const_reverse_iterator p = this->globs_.rbegin(); + p != this->globs_.rend(); + ++p) + { + int language = p->expression->language; + const char* name_to_match = this->get_name_to_match(symbol_name, + language, + &cpp_demangled_name, + &java_demangled_name); + if (name_to_match == NULL) + continue; + + if (fnmatch(p->expression->pattern.c_str(), name_to_match, + FNM_NOESCAPE) == 0) + { + if (pversion != NULL) + *pversion = p->version->tag; + if (p_is_global != NULL) + *p_is_global = p->is_global; + return true; + } + } + + // Finally, there may be a wildcard. + if (this->default_version_ != NULL) + { + if (pversion != NULL) + *pversion = this->default_version_->tag; + if (p_is_global != NULL) + *p_is_global = this->default_is_global_; + return true; + } + return false; } +// Give an error if any exact symbol names (not wildcards) appear in a +// version script, but there is no such symbol. + +void +Version_script_info::check_unmatched_names(const Symbol_table* symtab) const +{ + for (size_t i = 0; i < this->version_trees_.size(); ++i) + { + const Version_tree* vt = this->version_trees_[i]; + if (vt->global == NULL) + continue; + for (size_t j = 0; j < vt->global->expressions.size(); ++j) + { + const Version_expression& expression(vt->global->expressions[j]); + + // Ignore cases where we used the version because we saw a + // symbol that we looked up. Note that + // WAS_MATCHED_BY_SYMBOL will be true even if the symbol was + // not a definition. That's OK as in that case we most + // likely gave an undefined symbol error anyhow. + if (expression.was_matched_by_symbol) + continue; + + // Just ignore names which are in languages other than C. + // We have no way to look them up in the symbol table. + if (expression.language != LANGUAGE_C) + continue; + + // Remove backslash quoting, and ignore wildcard patterns. + std::string pattern = expression.pattern; + if (!expression.exact_match) + { + if (this->unquote(&pattern)) + continue; + } + + if (symtab->lookup(pattern.c_str(), vt->tag.c_str()) == NULL) + gold_error(_("version script assignment of %s to symbol %s " + "failed: symbol not defined"), + vt->tag.c_str(), pattern.c_str()); + } + } +} + struct Version_dependency_list* Version_script_info::allocate_dependency_list() { @@ -1892,21 +2418,33 @@ Version_script_info::print_expression_list( FILE* f, const Version_expression_list* vel) const { - std::string current_language; + Version_script_info::Language current_language = LANGUAGE_C; for (size_t i = 0; i < vel->expressions.size(); ++i) { const Version_expression& ve(vel->expressions[i]); if (ve.language != current_language) { - if (!current_language.empty()) + if (current_language != LANGUAGE_C) fprintf(f, " }\n"); - fprintf(f, " extern \"%s\" {\n", ve.language.c_str()); + switch (ve.language) + { + case LANGUAGE_C: + break; + case LANGUAGE_CXX: + fprintf(f, " extern \"C++\" {\n"); + break; + case LANGUAGE_JAVA: + fprintf(f, " extern \"Java\" {\n"); + break; + default: + gold_unreachable(); + } current_language = ve.language; } fprintf(f, " "); - if (!current_language.empty()) + if (current_language != LANGUAGE_C) fprintf(f, " "); if (ve.exact_match) @@ -1918,7 +2456,7 @@ Version_script_info::print_expression_list( fprintf(f, "\n"); } - if (!current_language.empty()) + if (current_language != LANGUAGE_C) fprintf(f, " }\n"); } @@ -1963,6 +2501,9 @@ yylex(YYSTYPE* lvalp, void* closurev) case Lex::VERSION_SCRIPT: parsecode = version_script_keywords.keyword_to_parsecode(str, len); break; + case Lex::DYNAMIC_LIST: + parsecode = dynamic_list_keywords.keyword_to_parsecode(str, len); + break; default: break; } @@ -1996,6 +2537,19 @@ yyerror(void* closurev, const char* message) closure->charpos(), message); } +// Called by the bison parser to add an external symbol to the link. + +extern "C" void +script_add_extern(void* closurev, const char* name, size_t length) +{ + // We treat exactly like -u NAME. FIXME: If it seems useful, we + // could handle this after the command line has been read, by adding + // entries to the symbol table directly. + std::string arg("--undefined="); + arg.append(name, length); + script_parse_option(closurev, arg.c_str(), arg.size()); +} + // Called by the bison parser to add a file to the link. extern "C" void @@ -2032,8 +2586,10 @@ script_add_file(void* closurev, const char* name, size_t length) } } - Input_file_argument file(name_string.c_str(), false, extra_search_path, - false, closure->position_dependent_options()); + Input_file_argument file(name_string.c_str(), + Input_file_argument::INPUT_FILE_TYPE_FILE, + extra_search_path, false, + closure->position_dependent_options()); closure->inputs()->add_file(file); } @@ -2114,8 +2670,10 @@ script_set_symbol(void* closurev, const char* name, size_t length, Parser_closure* closure = static_cast<Parser_closure*>(closurev); const bool provide = providei != 0; const bool hidden = hiddeni != 0; - closure->script_options()->add_symbol_assignment(name, length, value, - provide, hidden); + closure->script_options()->add_symbol_assignment(name, length, + closure->parsing_defsym(), + value, provide, hidden); + closure->clear_skip_on_incompatible_target(); } // Called by the bison parser to add an assertion. @@ -2126,6 +2684,7 @@ script_add_assertion(void* closurev, Expression* check, const char* message, { Parser_closure* closure = static_cast<Parser_closure*>(closurev); closure->script_options()->add_assertion(check, message, messagelen); + closure->clear_skip_on_incompatible_target(); } // Called by the bison parser to parse an OPTION. @@ -2155,6 +2714,46 @@ script_parse_option(void* closurev, const char* option, size_t length) // into mutable_option, so we can't free it. In cases the class // does not store such a pointer, this is a memory leak. Alas. :( } + closure->clear_skip_on_incompatible_target(); +} + +// Called by the bison parser to handle OUTPUT_FORMAT. OUTPUT_FORMAT +// takes either one or three arguments. In the three argument case, +// the format depends on the endianness option, which we don't +// currently support (FIXME). If we see an OUTPUT_FORMAT for the +// wrong format, then we want to search for a new file. Returning 0 +// here will cause the parser to immediately abort. + +extern "C" int +script_check_output_format(void* closurev, + const char* default_name, size_t default_length, + const char*, size_t, const char*, size_t) +{ + Parser_closure* closure = static_cast<Parser_closure*>(closurev); + std::string name(default_name, default_length); + Target* target = select_target_by_name(name.c_str()); + if (target == NULL || !parameters->is_compatible_target(target)) + { + if (closure->skip_on_incompatible_target()) + { + closure->set_found_incompatible_target(); + return 0; + } + // FIXME: Should we warn about the unknown target? + } + return 1; +} + +// Called by the bison parser to handle TARGET. + +extern "C" void +script_set_target(void* closurev, const char* target, size_t len) +{ + Parser_closure* closure = static_cast<Parser_closure*>(closurev); + std::string s(target, len); + General_options::Object_format format_enum; + format_enum = General_options::string_to_object_format(s.c_str()); + closure->position_dependent_options().set_format_enum(format_enum); } // Called by the bison parser to handle SEARCH_DIR. This is handled @@ -2192,6 +2791,9 @@ extern "C" void script_push_lex_into_version_mode(void* closurev) { Parser_closure* closure = static_cast<Parser_closure*>(closurev); + if (closure->version_script()->is_finalized()) + gold_error(_("%s:%d:%d: invalid use of VERSION in input file"), + closure->filename(), closure->lineno(), closure->charpos()); closure->push_lex_mode(Lex::VERSION_SCRIPT); } @@ -2243,8 +2845,6 @@ script_add_vers_depend(void* closurev, } // Add a pattern expression to an existing list of expressions, if any. -// TODO: In the old linker, the last argument used to be a bool, but I -// don't know what it meant. extern "C" struct Version_expression_list * script_new_vers_pattern(void* closurev, @@ -2296,7 +2896,25 @@ extern "C" void version_script_push_lang(void* closurev, const char* lang, int langlen) { Parser_closure* closure = static_cast<Parser_closure*>(closurev); - closure->push_language(std::string(lang, langlen)); + std::string language(lang, langlen); + Version_script_info::Language code; + if (language.empty() || language == "C") + code = Version_script_info::LANGUAGE_C; + else if (language == "C++") + code = Version_script_info::LANGUAGE_CXX; + else if (language == "Java") + code = Version_script_info::LANGUAGE_JAVA; + else + { + char* buf = new char[langlen + 100]; + snprintf(buf, langlen + 100, + _("unrecognized version script language '%s'"), + language.c_str()); + yyerror(closurev, buf); + delete[] buf; + code = Version_script_info::LANGUAGE_C; + } + closure->push_language(code); } extern "C" void @@ -2313,6 +2931,7 @@ script_start_sections(void* closurev) { Parser_closure* closure = static_cast<Parser_closure*>(closurev); closure->script_options()->script_sections()->start_sections(); + closure->clear_skip_on_incompatible_target(); } // Called by the bison parser to finish a SECTIONS clause. @@ -2339,7 +2958,7 @@ script_start_output_section(void* closurev, const char* name, size_t namelen, // Finish processing entries for an output section. extern "C" void -script_finish_output_section(void* closurev, +script_finish_output_section(void* closurev, const struct Parser_output_section_trailer* trail) { Parser_closure* closure = static_cast<Parser_closure*>(closurev); @@ -2505,6 +3124,7 @@ script_add_phdr(void* closurev, const char* name, size_t namelen, Script_sections* ss = closure->script_options()->script_sections(); ss->add_phdr(name, namelen, type, includes_filehdr, includes_phdrs, is_flags_valid, info->flags, info->load_address); + closure->clear_skip_on_incompatible_target(); } // Convert a program header string to a type. @@ -2543,3 +3163,11 @@ script_phdr_string_to_type(void* closurev, const char* name, size_t namelen) yyerror(closurev, _("unknown PHDR type (try integer)")); return elfcpp::PT_NULL; } + +extern "C" void +script_saw_segment_start_expression(void* closurev) +{ + Parser_closure* closure = static_cast<Parser_closure*>(closurev); + Script_sections* ss = closure->script_options()->script_sections(); + ss->set_saw_segment_start_expression(true); +} diff --git a/binutils-2.19/gold/script.h b/binutils-2.19/gold/script.h index 3397bf0..f4c3f22 100644 --- a/binutils-2.19/gold/script.h +++ b/binutils-2.19/gold/script.h @@ -1,6 +1,6 @@ // script.h -- handle linker scripts for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -45,6 +45,7 @@ class Symbol_table; class Layout; class Mapfile; class Input_argument; +class Input_arguments; class Input_objects; class Input_group; class Input_file; @@ -54,6 +55,8 @@ class Workqueue; struct Version_dependency_list; struct Version_expression_list; struct Version_tree; +struct Version_expression; +class Lazy_demangler; // This class represents an expression in a linker script. @@ -127,32 +130,55 @@ class Expression class Version_script_info { public: + // The languages which can be specified in a versionn script. + enum Language + { + LANGUAGE_C, // No demangling. + LANGUAGE_CXX, // C++ demangling. + LANGUAGE_JAVA, // Java demangling. + LANGUAGE_COUNT + }; + + Version_script_info(); + ~Version_script_info(); // Clear everything. void clear(); + // Finalize the version control information. + void + finalize(); + + // Return whether the information is finalized. + bool + is_finalized() const + { return this->is_finalized_; } + // Return whether any version were defined in the version script. bool empty() const { return this->version_trees_.empty(); } // If there is a version associated with SYMBOL, return true, and - // set *VERSION to the version. Otherwise, return false. + // set *VERSION to the version, and *IS_GLOBAL to whether the symbol + // should be global. Otherwise, return false. bool - get_symbol_version(const char* symbol, std::string* version) const - { return this->get_symbol_version_helper(symbol, true, version); } + get_symbol_version(const char* symbol, std::string* version, + bool* is_global) const; // Return whether this symbol matches the local: section of some // version. bool symbol_is_local(const char* symbol) const - { return this->get_symbol_version_helper(symbol, false, NULL); } + { + bool is_global; + return (this->get_symbol_version(symbol, NULL, &is_global) + && !is_global); + } // Return the names of versions defined in the version script. - // Strings are allocated out of the stringpool given in the - // constructor. std::vector<std::string> get_versions() const; @@ -173,6 +199,15 @@ class Version_script_info struct Version_tree* allocate_version_tree(); + // Build the lookup tables after all data have been read. + void + build_lookup_tables(); + + // Give an error if there are any unmatched names in the version + // script. + void + check_unmatched_names(const Symbol_table*) const; + // Print contents to the FILE. This is for debugging. void print(FILE*) const; @@ -181,13 +216,95 @@ class Version_script_info void print_expression_list(FILE* f, const Version_expression_list*) const; - bool get_symbol_version_helper(const char* symbol, - bool check_global, - std::string* pversion) const; + bool + get_symbol_version_helper(const char* symbol, + bool check_global, + std::string* pversion) const; + + // Fast lookup information for a given language. + + // We map from exact match strings to Version_tree's. Historically + // version scripts sometimes have the same symbol multiple times, + // which is ambiguous. We warn about that case by storing the + // second Version_tree we see. + struct Version_tree_match + { + Version_tree_match(const Version_tree* r, bool ig, + const Version_expression* e) + : real(r), is_global(ig), expression(e), ambiguous(NULL) + { } + + // The Version_tree that we return. + const Version_tree* real; + // True if this is a global match for the REAL member, false if it + // is a local match. + bool is_global; + // Point back to the Version_expression for which we created this + // match. + const Version_expression* expression; + // If not NULL, another Version_tree that defines the symbol. + const Version_tree* ambiguous; + }; + + // Map from an exact match string to a Version_tree. + + typedef Unordered_map<std::string, Version_tree_match> Exact; + + // Fast lookup information for a glob pattern. + struct Glob + { + Glob() + : expression(NULL), version(NULL), is_global(false) + { } + + Glob(const Version_expression* e, const Version_tree* v, bool ig) + : expression(e), version(v), is_global(ig) + { } + + // A pointer to the version expression holding the pattern to + // match and the language to use for demangling the symbol before + // doing the match. + const Version_expression* expression; + // The Version_tree we use if this pattern matches. + const Version_tree* version; + // True if this is a global symbol. + bool is_global; + }; + + typedef std::vector<Glob> Globs; + + bool + unquote(std::string*) const; + + void + add_exact_match(const std::string&, const Version_tree*, bool is_global, + const Version_expression*, Exact*); - std::vector<struct Version_dependency_list*> dependency_lists_; - std::vector<struct Version_expression_list*> expression_lists_; - std::vector<struct Version_tree*> version_trees_; + void + build_expression_list_lookup(const Version_expression_list*, + const Version_tree*, bool); + + const char* + get_name_to_match(const char*, int, + Lazy_demangler*, Lazy_demangler*) const; + + // All the version dependencies we allocate. + std::vector<Version_dependency_list*> dependency_lists_; + // All the version expressions we allocate. + std::vector<Version_expression_list*> expression_lists_; + // The list of versions. + std::vector<Version_tree*> version_trees_; + // Exact matches for global symbols, by language. + Exact* exact_[LANGUAGE_COUNT]; + // A vector of glob patterns mapping to Version_trees. + Globs globs_; + // The default version to use, if there is one. This is from a + // pattern of "*". + const Version_tree* default_version_; + // True if the default version is global. + bool default_is_global_; + // Whether this has been finalized. + bool is_finalized_; }; // This class manages assignments to symbols. These can appear in @@ -199,10 +316,10 @@ class Version_script_info class Symbol_assignment { public: - Symbol_assignment(const char* name, size_t namelen, Expression* val, - bool provide, bool hidden) - : name_(name, namelen), val_(val), provide_(provide), hidden_(hidden), - sym_(NULL) + Symbol_assignment(const char* name, size_t namelen, bool is_defsym, + Expression* val, bool provide, bool hidden) + : name_(name, namelen), val_(val), is_defsym_(is_defsym), + provide_(provide), hidden_(hidden), sym_(NULL) { } // Add the symbol to the symbol table. @@ -245,6 +362,9 @@ class Symbol_assignment std::string name_; // Expression to assign to symbol. Expression* val_; + // True if this symbol is defined by a --defsym, false if it is + // defined in a linker script. + bool is_defsym_; // Whether the assignment should be provided (only set if there is // an undefined reference to the symbol. bool provide_; @@ -297,8 +417,8 @@ class Script_options // Add a symbol to be defined. void - add_symbol_assignment(const char* name, size_t length, Expression* value, - bool provide, bool hidden); + add_symbol_assignment(const char* name, size_t length, bool is_defsym, + Expression* value, bool provide, bool hidden); // Add an assertion. void @@ -382,6 +502,26 @@ class Script_options Script_sections script_sections_; }; +// Information about a script input that will persist during the whole linker +// run. Needed only during an incremental build to retrieve the input files +// added by this script. + +class Script_info +{ + public: + Script_info(Input_arguments* inputs) + : inputs_(inputs) + { } + + // Returns the input files included because of this script. + Input_arguments* + inputs() + { return this->inputs_; } + + private: + Input_arguments* inputs_; +}; + // FILE was found as an argument on the command line, but was not // recognized as an ELF file. Try to read it as a script. Return // true if the file was handled. This has to handle /usr/lib/libc.so @@ -389,8 +529,8 @@ class Script_options // whether the function took over NEXT_BLOCKER. bool -read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*, - Dirsearch*, Input_objects*, Mapfile*, Input_group*, +read_input_script(Workqueue*, Symbol_table*, Layout*, Dirsearch*, int, + Input_objects*, Mapfile*, Input_group*, const Input_argument*, Input_file*, Task_token* next_blocker, bool* used_next_blocker); @@ -398,7 +538,7 @@ read_input_script(Workqueue*, const General_options&, Symbol_table*, Layout*, // Read it as a script, and execute its contents immediately. bool -read_commandline_script(const char* filename, Command_line*); +read_commandline_script(const char* filename, Command_line* cmdline); // FILE was found as an argument to --version-script. Read it as a // version script, and store its contents in @@ -407,6 +547,14 @@ read_commandline_script(const char* filename, Command_line*); bool read_version_script(const char* filename, Command_line* cmdline); +// FILENAME was found as an argument to --dynamic-list. Read it as a +// version script (actually, a versym_node from a version script), and +// store its contents in DYNAMIC_LIST. + +bool +read_dynamic_list(const char* filename, Command_line* cmdline, + Script_options* dynamic_list); + } // End namespace gold. #endif // !defined(GOLD_SCRIPT_H) diff --git a/binutils-2.19/gold/sparc.cc b/binutils-2.19/gold/sparc.cc index 7da59dd..5355c7b 100644 --- a/binutils-2.19/gold/sparc.cc +++ b/binutils-2.19/gold/sparc.cc @@ -1,6 +1,6 @@ // sparc.cc -- sparc target support for gold. -// Copyright 2008 Free Software Foundation, Inc. +// Copyright 2008, 2009 Free Software Foundation, Inc. // Written by David S. Miller <davem@davemloft.net>. // This file is part of gold. @@ -40,6 +40,7 @@ #include "target-select.h" #include "tls.h" #include "errors.h" +#include "gc.h" namespace { @@ -63,10 +64,24 @@ class Target_sparc : public Sized_target<size, big_endian> { } + // Process the relocations to determine unreferenced sections for + // garbage collection. + void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Scan the relocations to look for symbol adjustments. void - scan_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, @@ -79,7 +94,7 @@ class Target_sparc : public Sized_target<size, big_endian> const unsigned char* plocal_symbols); // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); // Return the value to use for a dynamic which requires special // treatment. @@ -96,12 +111,12 @@ class Target_sparc : public Sized_target<size, big_endian> bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr view_address, - section_size_type view_size); + section_size_type view_size, + const Reloc_symbol_changes*); // Scan the relocs during a relocatable link. void - scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, @@ -130,7 +145,7 @@ class Target_sparc : public Sized_target<size, big_endian> section_size_type reloc_view_size); // Return whether SYM is defined by the ABI. bool - do_is_defined_by_abi(Symbol* sym) const + do_is_defined_by_abi(const Symbol* sym) const { // XXX Really need to support this better... if (sym->type() == elfcpp::STT_SPARC_REGISTER) @@ -139,6 +154,11 @@ class Target_sparc : public Sized_target<size, big_endian> return strcmp(sym->name(), "___tls_get_addr") == 0; } + // Return whether there is a GOT section. + bool + has_got_section() const + { return this->got_ != NULL; } + // Return the size of the GOT section. section_size_type got_size() @@ -158,8 +178,7 @@ class Target_sparc : public Sized_target<size, big_endian> { } inline void - local(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_sparc* target, + local(Symbol_table* symtab, Layout* layout, Target_sparc* target, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, Output_section* output_section, @@ -167,14 +186,36 @@ class Target_sparc : public Sized_target<size, big_endian> const elfcpp::Sym<size, big_endian>& lsym); inline void - global(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_sparc* target, + global(Symbol_table* symtab, Layout* layout, Target_sparc* target, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type, Symbol* gsym); + inline bool + local_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_sparc* , + Sized_relobj<size, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rela<size, big_endian>& , + unsigned int , + const elfcpp::Sym<size, big_endian>&) + { return false; } + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* , Layout* , + Target_sparc* , + Sized_relobj<size, big_endian>* , + unsigned int , + Output_section* , + const elfcpp::Rela<size, + big_endian>& , + unsigned int , Symbol*) + { return false; } + + private: static void unsupported_reloc_local(Sized_relobj<size, big_endian>*, @@ -216,7 +257,8 @@ class Target_sparc : public Sized_target<size, big_endian> // any warnings about this relocation. inline bool relocate(const Relocate_info<size, big_endian>*, Target_sparc*, - size_t relnum, const elfcpp::Rela<size, big_endian>&, + Output_section*, size_t relnum, + const elfcpp::Rela<size, big_endian>&, unsigned int r_type, const Sized_symbol<size>*, const Symbol_value<size>*, unsigned char*, @@ -283,17 +325,6 @@ class Target_sparc : public Sized_target<size, big_endian> Reloc_section* rela_dyn_section(Layout*); - // Return true if the symbol may need a COPY relocation. - // References from an executable object to non-function symbols - // defined in a dynamic object may need a COPY relocation. - bool - may_need_copy_reloc(Symbol* gsym) - { - return (!parameters->options().shared() - && gsym->is_from_dynobj() - && gsym->type() != elfcpp::STT_FUNC); - } - // Copy a relocation against a global symbol. void copy_reloc(Symbol_table* symtab, Layout* layout, @@ -349,7 +380,13 @@ Target::Target_info Target_sparc<32, true>::sparc_info = "/usr/lib/ld.so.1", // dynamic_linker 0x00010000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 8 * 1024 // common_pagesize (overridable by -z common-page-size) + 8 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; template<> @@ -366,7 +403,13 @@ Target::Target_info Target_sparc<64, true>::sparc_info = "/usr/lib/sparcv9/ld.so.1", // dynamic_linker 0x100000, // default_text_segment_address 64 * 1024, // abi_pagesize (overridable by -z max-page-size) - 8 * 1024 // common_pagesize (overridable by -z common-page-size) + 8 * 1024, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; // We have to take care here, even when operating in little-endian @@ -1006,11 +1049,12 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab, os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_); - os->set_is_relro(); + this->got_, false, true, false, + false); // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, this->got_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -1032,7 +1076,8 @@ Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout) gold_assert(layout != NULL); this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rela_dyn_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true, + false, false, false); } return this->rela_dyn_; } @@ -1134,7 +1179,8 @@ Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout) { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_); + elfcpp::SHF_ALLOC, this->rel_, true, + false, false, false); } template<int size, bool big_endian> @@ -1346,15 +1392,21 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab, // Create the GOT sections first. this->got_section(symtab, layout); + // Ensure that .rela.dyn always appears before .rela.plt This is + // necessary due to how, on Sparc and some other targets, .rela.dyn + // needs to include .rela.plt in it's range. + this->rela_dyn_section(layout); + this->plt_ = new Output_data_plt_sparc<size, big_endian>(layout); layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR | elfcpp::SHF_WRITE), - this->plt_); + this->plt_, false, false, false, false); // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, + Symbol_table::PREDEFINED, this->plt_, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, @@ -1438,6 +1490,7 @@ optimize_tls_reloc(bool is_final, int r_type) case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: // These are Initial-Exec relocs which get the thread offset // from the GOT. If we know that we are linking against the // local symbol, we can switch to Local-Exec, which links the @@ -1566,6 +1619,7 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int // error per object file. if (this->issued_non_pic_error_) return; + gold_assert(parameters->options().output_is_position_independent()); object->error(_("requires unsupported dynamic reloc; " "recompile with -fPIC")); this->issued_non_pic_error_ = true; @@ -1577,7 +1631,6 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int template<int size, bool big_endian> inline void Target_sparc<size, big_endian>::Scan::local( - const General_options&, Symbol_table* symtab, Layout* layout, Target_sparc<size, big_endian>* target, @@ -1645,23 +1698,22 @@ Target_sparc<size, big_endian>::Scan::local( if (parameters->options().output_is_position_independent()) { Reloc_section* rela_dyn = target->rela_dyn_section(layout); + unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); check_non_pic(object, r_type); if (lsym.get_st_type() != elfcpp::STT_SECTION) { - unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); rela_dyn->add_local(object, r_sym, orig_r_type, output_section, data_shndx, reloc.get_r_offset(), reloc.get_r_addend()); } else { - unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); gold_assert(lsym.get_st_value() == 0); - rela_dyn->add_local_relative(object, r_sym, orig_r_type, - output_section, data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend()); + rela_dyn->add_symbolless_local_addend(object, r_sym, orig_r_type, + output_section, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); } } break; @@ -1678,6 +1730,9 @@ Target_sparc<size, big_endian>::Scan::local( case elfcpp::R_SPARC_PC22: break; + case elfcpp::R_SPARC_GOTDATA_OP: + case elfcpp::R_SPARC_GOTDATA_OP_HIX22: + case elfcpp::R_SPARC_GOTDATA_OP_LOX10: case elfcpp::R_SPARC_GOT10: case elfcpp::R_SPARC_GOT13: case elfcpp::R_SPARC_GOT22: @@ -1727,6 +1782,7 @@ Target_sparc<size, big_endian>::Scan::local( case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: case elfcpp::R_SPARC_TLS_LE_HIX22: // Local-exec case elfcpp::R_SPARC_TLS_LE_LOX10: { @@ -1793,6 +1849,7 @@ Target_sparc<size, big_endian>::Scan::local( case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: layout->set_has_static_tls(); if (optimized_type == tls::TLSOPT_NONE) { @@ -1806,13 +1863,13 @@ Target_sparc<size, big_endian>::Scan::local( Reloc_section* rela_dyn = target->rela_dyn_section(layout); unsigned int off = got->add_constant(0); - object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET, - off); - rela_dyn->add_local_relative(object, r_sym, - (size == 64 ? - elfcpp::R_SPARC_TLS_TPOFF64 : - elfcpp::R_SPARC_TLS_TPOFF32), - got, off, 0); + object->set_local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET, off); + + rela_dyn->add_symbolless_local_addend(object, r_sym, + (size == 64 ? + elfcpp::R_SPARC_TLS_TPOFF64 : + elfcpp::R_SPARC_TLS_TPOFF32), + got, off, 0); } } else if (optimized_type != tls::TLSOPT_TO_LE) @@ -1828,9 +1885,9 @@ Target_sparc<size, big_endian>::Scan::local( gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_local_relative(object, r_sym, r_type, - output_section, data_shndx, - reloc.get_r_offset(), 0); + rela_dyn->add_symbolless_local_addend(object, r_sym, r_type, + output_section, data_shndx, + reloc.get_r_offset(), 0); } break; } @@ -1877,7 +1934,6 @@ Target_sparc<size, big_endian>::Scan::unsupported_reloc_global( template<int size, bool big_endian> inline void Target_sparc<size, big_endian>::Scan::global( - const General_options&, Symbol_table* symtab, Layout* layout, Target_sparc<size, big_endian>* target, @@ -1890,6 +1946,13 @@ Target_sparc<size, big_endian>::Scan::global( { unsigned int orig_r_type = r_type; + // A reference to _GLOBAL_OFFSET_TABLE_ implies that we need a got + // section. We check here to avoid creating a dynamic reloc against + // _GLOBAL_OFFSET_TABLE_. + if (!target->has_got_section() + && strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0) + target->got_section(symtab, layout); + r_type &= 0xff; switch (r_type) { @@ -1943,7 +2006,7 @@ Target_sparc<size, big_endian>::Scan::global( flags |= Symbol::FUNCTION_CALL; if (gsym->needs_dynamic_reloc(flags)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, @@ -1999,7 +2062,39 @@ Target_sparc<size, big_endian>::Scan::global( // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) { - if (target->may_need_copy_reloc(gsym)) + unsigned int r_off = reloc.get_r_offset(); + + // The assembler can sometimes emit unaligned relocations + // for dwarf2 cfi directives. + switch (r_type) + { + case elfcpp::R_SPARC_16: + if (r_off & 0x1) + orig_r_type = r_type = elfcpp::R_SPARC_UA16; + break; + case elfcpp::R_SPARC_32: + if (r_off & 0x3) + orig_r_type = r_type = elfcpp::R_SPARC_UA32; + break; + case elfcpp::R_SPARC_64: + if (r_off & 0x7) + orig_r_type = r_type = elfcpp::R_SPARC_UA64; + break; + case elfcpp::R_SPARC_UA16: + if (!(r_off & 0x1)) + orig_r_type = r_type = elfcpp::R_SPARC_16; + break; + case elfcpp::R_SPARC_UA32: + if (!(r_off & 0x3)) + orig_r_type = r_type = elfcpp::R_SPARC_32; + break; + case elfcpp::R_SPARC_UA64: + if (!(r_off & 0x7)) + orig_r_type = r_type = elfcpp::R_SPARC_64; + break; + } + + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -2027,16 +2122,19 @@ Target_sparc<size, big_endian>::Scan::global( reloc.get_r_offset(), reloc.get_r_addend()); else - rela_dyn->add_global_relative(gsym, orig_r_type, - output_section, object, - data_shndx, - reloc.get_r_offset(), - reloc.get_r_addend()); + rela_dyn->add_symbolless_global_addend(gsym, orig_r_type, + output_section, + object, data_shndx, + reloc.get_r_offset(), + reloc.get_r_addend()); } } } break; + case elfcpp::R_SPARC_GOTDATA_OP: + case elfcpp::R_SPARC_GOTDATA_OP_HIX22: + case elfcpp::R_SPARC_GOTDATA_OP_LOX10: case elfcpp::R_SPARC_GOT10: case elfcpp::R_SPARC_GOT13: case elfcpp::R_SPARC_GOT22: @@ -2088,6 +2186,7 @@ Target_sparc<size, big_endian>::Scan::global( case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: { const bool is_final = gsym->final_value_is_known(); const tls::Tls_optimization optimized_type @@ -2159,10 +2258,10 @@ Target_sparc<size, big_endian>::Scan::global( if (parameters->options().shared()) { Reloc_section* rela_dyn = target->rela_dyn_section(layout); - rela_dyn->add_global_relative(gsym, orig_r_type, - output_section, object, - data_shndx, reloc.get_r_offset(), - 0); + rela_dyn->add_symbolless_global_addend(gsym, orig_r_type, + output_section, object, + data_shndx, reloc.get_r_offset(), + 0); } break; @@ -2170,6 +2269,7 @@ Target_sparc<size, big_endian>::Scan::global( case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: layout->set_has_static_tls(); if (optimized_type == tls::TLSOPT_NONE) { @@ -2211,12 +2311,45 @@ Target_sparc<size, big_endian>::Scan::global( } } +// Process relocations for gc. + +template<int size, bool big_endian> +void +Target_sparc<size, big_endian>::gc_process_relocs( + Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + typedef Target_sparc<size, big_endian> Sparc; + typedef typename Target_sparc<size, big_endian>::Scan Scan; + + gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); +} + // Scan relocations for a section. template<int size, bool big_endian> void Target_sparc<size, big_endian>::scan_relocs( - const General_options& options, Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, @@ -2240,7 +2373,6 @@ Target_sparc<size, big_endian>::scan_relocs( } gold::scan_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>( - options, symtab, layout, this, @@ -2258,38 +2390,17 @@ Target_sparc<size, big_endian>::scan_relocs( template<int size, bool big_endian> void -Target_sparc<size, big_endian>::do_finalize_sections(Layout* layout) +Target_sparc<size, big_endian>::do_finalize_sections( + Layout* layout, + const Input_objects*, + Symbol_table*) { // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->plt_ != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - - odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); - } - - if (this->rela_dyn_ != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<size>::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->plt_, rel_plt, + this->rela_dyn_, true, true); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. @@ -2304,6 +2415,7 @@ inline bool Target_sparc<size, big_endian>::Relocate::relocate( const Relocate_info<size, big_endian>* relinfo, Target_sparc* target, + Output_section*, size_t relnum, const elfcpp::Rela<size, big_endian>& rela, unsigned int r_type, @@ -2365,6 +2477,9 @@ Target_sparc<size, big_endian>::Relocate::relocate( unsigned int got_offset = 0; switch (r_type) { + case elfcpp::R_SPARC_GOTDATA_OP: + case elfcpp::R_SPARC_GOTDATA_OP_HIX22: + case elfcpp::R_SPARC_GOTDATA_OP_LOX10: case elfcpp::R_SPARC_GOT10: case elfcpp::R_SPARC_GOT13: case elfcpp::R_SPARC_GOT22: @@ -2400,14 +2515,30 @@ Target_sparc<size, big_endian>::Relocate::relocate( break; case elfcpp::R_SPARC_16: - Relocate_functions<size, big_endian>::rela16(view, object, - psymval, addend); + if (rela.get_r_offset() & 0x1) + { + // The assembler can sometimes emit unaligned relocations + // for dwarf2 cfi directives. + Reloc::ua16(view, object, psymval, addend); + } + else + Relocate_functions<size, big_endian>::rela16(view, object, + psymval, addend); break; case elfcpp::R_SPARC_32: if (!parameters->options().output_is_position_independent()) - Relocate_functions<size, big_endian>::rela32(view, object, - psymval, addend); + { + if (rela.get_r_offset() & 0x3) + { + // The assembler can sometimes emit unaligned relocations + // for dwarf2 cfi directives. + Reloc::ua32(view, object, psymval, addend); + } + else + Relocate_functions<size, big_endian>::rela32(view, object, + psymval, addend); + } break; case elfcpp::R_SPARC_DISP8: @@ -2463,10 +2594,15 @@ Target_sparc<size, big_endian>::Relocate::relocate( Reloc::lo10(view, got_offset, addend); break; + case elfcpp::R_SPARC_GOTDATA_OP: + break; + + case elfcpp::R_SPARC_GOTDATA_OP_LOX10: case elfcpp::R_SPARC_GOT13: Reloc::rela32_13(view, got_offset, addend); break; + case elfcpp::R_SPARC_GOTDATA_OP_HIX22: case elfcpp::R_SPARC_GOT22: Reloc::hi22(view, got_offset, addend); break; @@ -2516,8 +2652,17 @@ Target_sparc<size, big_endian>::Relocate::relocate( case elfcpp::R_SPARC_64: if (!parameters->options().output_is_position_independent()) - Relocate_functions<size, big_endian>::rela64(view, object, - psymval, addend); + { + if (rela.get_r_offset() & 0x7) + { + // The assembler can sometimes emit unaligned relocations + // for dwarf2 cfi directives. + Reloc::ua64(view, object, psymval, addend); + } + else + Relocate_functions<size, big_endian>::rela64(view, object, + psymval, addend); + } break; case elfcpp::R_SPARC_OLO10: @@ -2616,6 +2761,7 @@ Target_sparc<size, big_endian>::Relocate::relocate( case elfcpp::R_SPARC_TLS_IE_LO10: case elfcpp::R_SPARC_TLS_IE_LD: case elfcpp::R_SPARC_TLS_IE_LDX: + case elfcpp::R_SPARC_TLS_IE_ADD: case elfcpp::R_SPARC_TLS_LE_HIX22: case elfcpp::R_SPARC_TLS_LE_LOX10: this->relocate_tls(relinfo, target, relnum, rela, @@ -2995,6 +3141,12 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls( r_type); break; + case elfcpp::R_SPARC_TLS_IE_ADD: + // This seems to be mainly so that we can find the addition + // instruction if there is one. There doesn't seem to be any + // actual relocation to apply. + break; + case elfcpp::R_SPARC_TLS_LE_HIX22: // If we're creating a shared library, a dynamic relocation will // have been created for this location, so do not apply it now. @@ -3030,7 +3182,8 @@ Target_sparc<size, big_endian>::relocate_section( bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr address, - section_size_type view_size) + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) { typedef Target_sparc<size, big_endian> Sparc; typedef typename Target_sparc<size, big_endian>::Relocate Sparc_relocate; @@ -3047,7 +3200,8 @@ Target_sparc<size, big_endian>::relocate_section( needs_special_offset_handling, view, address, - view_size); + view_size, + reloc_symbol_changes); } // Return the size of a relocation while scanning during a relocatable @@ -3069,7 +3223,6 @@ Target_sparc<size, big_endian>::Relocatable_size_for_reloc::get_size_for_reloc( template<int size, bool big_endian> void Target_sparc<size, big_endian>::scan_relocatable_relocs( - const General_options& options, Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, @@ -3090,7 +3243,6 @@ Target_sparc<size, big_endian>::scan_relocatable_relocs( gold::scan_relocatable_relocs<size, big_endian, elfcpp::SHT_RELA, Scan_relocatable_relocs>( - options, symtab, layout, object, @@ -3162,8 +3314,6 @@ public: (size == 64 ? "elf64-sparc" : "elf32-sparc")) { } - Target* instantiated_target_; - Target* do_recognize(int machine, int, int) { switch (size) @@ -3183,15 +3333,11 @@ public: return NULL; } - return do_instantiate_target(); + return this->instantiate_target(); } Target* do_instantiate_target() - { - if (this->instantiated_target_ == NULL) - this->instantiated_target_ = new Target_sparc<size, big_endian>(); - return this->instantiated_target_; - } + { return new Target_sparc<size, big_endian>(); } }; Target_selector_sparc<32, true> target_selector_sparc32; diff --git a/binutils-2.19/gold/stringpool.cc b/binutils-2.19/gold/stringpool.cc index e37846b..10d6d27 100644 --- a/binutils-2.19/gold/stringpool.cc +++ b/binutils-2.19/gold/stringpool.cc @@ -36,8 +36,10 @@ namespace gold template<typename Stringpool_char> Stringpool_template<Stringpool_char>::Stringpool_template() : string_set_(), key_to_offset_(), strings_(), strtab_size_(0), - zero_null_(true) + zero_null_(true), optimize_(false), offset_(sizeof(Stringpool_char)) { + if (parameters->options_valid() && parameters->options().optimize() >= 2) + this->optimize_ = true; } template<typename Stringpool_char> @@ -151,16 +153,7 @@ size_t Stringpool_template<Stringpool_char>::string_hash(const Stringpool_char* s, size_t length) { - // This is the hash function used by the dynamic linker for - // DT_GNU_HASH entries. I compared this to a Fowler/Noll/Vo hash - // for a C++ program with 385,775 global symbols. This hash - // function was very slightly worse. However, it is much faster to - // compute. Overall wall clock time was a win. - const unsigned char* p = reinterpret_cast<const unsigned char*>(s); - size_t h = 5381; - for (size_t i = 0; i < length * sizeof(Stringpool_char); ++i) - h = h * 33 + *p++; - return h; + return gold::string_hash<Stringpool_char>(s, length); } // Add the string S to the list of canonical strings. Return a @@ -239,6 +232,23 @@ Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, bool copy, return this->add_with_length(s, string_length(s), copy, pkey); } +// Add a new key offset entry. + +template<typename Stringpool_char> +void +Stringpool_template<Stringpool_char>::new_key_offset(size_t length) +{ + section_offset_type offset; + if (this->zero_null_ && length == 0) + offset = 0; + else + { + offset = this->offset_; + this->offset_ += (length + 1) * sizeof(Stringpool_char); + } + this->key_to_offset_.push_back(offset); +} + template<typename Stringpool_char> const Stringpool_char* Stringpool_template<Stringpool_char>::add_with_length(const Stringpool_char* s, @@ -266,7 +276,7 @@ Stringpool_template<Stringpool_char>::add_with_length(const Stringpool_char* s, { // We just added the string. The key value has now been // used. - this->key_to_offset_.push_back(0); + this->new_key_offset(length); } else { @@ -292,7 +302,7 @@ Stringpool_template<Stringpool_char>::add_with_length(const Stringpool_char* s, return p->first.string; } - this->key_to_offset_.push_back(0); + this->new_key_offset(length); hk.string = this->add_string(s, length); // The contents of the string stay the same, so we don't need to @@ -395,21 +405,10 @@ Stringpool_template<Stringpool_char>::set_string_offsets() // the strtab size, and gives a relatively small benefit (it's // typically rare for a symbol to be a suffix of another), we only // take the time to sort when the user asks for heavy optimization. - if (parameters->options().optimize() < 2) + if (!this->optimize_) { - for (typename String_set_type::iterator curr = this->string_set_.begin(); - curr != this->string_set_.end(); - curr++) - { - section_offset_type* poff = &this->key_to_offset_[curr->second - 1]; - if (this->zero_null_ && curr->first.string[0] == 0) - *poff = 0; - else - { - *poff = offset; - offset += (curr->first.length + 1) * charsize; - } - } + // If we are not optimizing, the offsets are already assigned. + offset = this->offset_; } else { diff --git a/binutils-2.19/gold/stringpool.h b/binutils-2.19/gold/stringpool.h index 6fe2066..f353c9d 100644 --- a/binutils-2.19/gold/stringpool.h +++ b/binutils-2.19/gold/stringpool.h @@ -77,48 +77,50 @@ class Chunked_vector { public: Chunked_vector() - : chunks_() + : chunks_(), size_(0) { } // Clear the elements. void clear() - { this->chunks_.clear(); } + { + this->chunks_.clear(); + this->size_ = 0; + } // Reserve elements. void reserve(unsigned int n) { - n += chunk_size - 1; - while (n >= chunk_size) + if (n > this->chunks_.size() * chunk_size) { - this->chunks_.push_back(Element_vector()); - this->chunks_.back().reserve(chunk_size); - n -= chunk_size; + this->chunks_.resize((n + chunk_size - 1) / chunk_size); + // We need to call reserve() of all chunks since changing + // this->chunks_ casues Element_vectors to be copied. The + // reserved capacity of an Element_vector may be lost in copying. + for (size_t i = 0; i < this->chunks_.size(); ++i) + this->chunks_[i].reserve(chunk_size); } } // Get the number of elements. size_t size() const - { - if (this->chunks_.empty()) - return 0; - else - return ((this->chunks_.size() - 1) * chunk_size - + this->chunks_.back().size()); - } + { return this->size_; } // Push a new element on the back of the vector. void push_back(const Element& element) { - if (this->chunks_.empty() || this->chunks_.back().size() == chunk_size) + size_t chunk_index = this->size_ / chunk_size; + if (chunk_index >= this->chunks_.size()) { this->chunks_.push_back(Element_vector()); this->chunks_.back().reserve(chunk_size); + gold_assert(chunk_index < this->chunks_.size()); } - this->chunks_.back().push_back(element); + this->chunks_[chunk_index].push_back(element); + this->size_++; } // Return a reference to an entry in the vector. @@ -137,6 +139,7 @@ class Chunked_vector typedef std::vector<Element_vector> Chunk_vector; Chunk_vector chunks_; + size_t size_; }; @@ -174,7 +177,18 @@ class Stringpool_template // should not be called for a proper ELF SHT_STRTAB section. void set_no_zero_null() - { this->zero_null_ = false; } + { + gold_assert(this->string_set_.empty() + && this->offset_ == sizeof(Stringpool_char)); + this->zero_null_ = false; + this->offset_ = 0; + } + + // Indicate that this string pool should be optimized, even if not + // running with -O2. + void + set_optimize() + { this->optimize_ = true; } // Add the string S to the pool. This returns a canonical permanent // pointer to the string in the pool. If COPY is true, the string @@ -276,6 +290,10 @@ class Stringpool_template char data[1]; }; + // Add a new key offset entry. + void + new_key_offset(size_t); + // Copy a string into the buffers, returning a canonical string. const Stringpool_char* add_string(const Stringpool_char*, size_t); @@ -364,6 +382,10 @@ class Stringpool_template section_size_type strtab_size_; // Whether to reserve offset 0 to hold the null string. bool zero_null_; + // Whether to optimize the string table. + bool optimize_; + // offset of the next string. + section_offset_type offset_; }; // The most common type of Stringpool. diff --git a/binutils-2.19/gold/symtab.cc b/binutils-2.19/gold/symtab.cc index 393d71a..c2a811f 100644 --- a/binutils-2.19/gold/symtab.cc +++ b/binutils-2.19/gold/symtab.cc @@ -1,6 +1,6 @@ // symtab.cc -- the gold symbol table -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -30,6 +30,7 @@ #include <utility> #include "demangle.h" +#include "gc.h" #include "object.h" #include "dwarf_reader.h" #include "dynobj.h" @@ -37,6 +38,8 @@ #include "target.h" #include "workqueue.h" #include "symtab.h" +#include "demangle.h" // needed for --dynamic-list-cpp-new +#include "plugin.h" namespace gold { @@ -56,23 +59,23 @@ Symbol::init_fields(const char* name, const char* version, this->symtab_index_ = 0; this->dynsym_index_ = 0; this->got_offsets_.init(); - this->plt_offset_ = 0; + this->plt_offset_ = -1U; this->type_ = type; this->binding_ = binding; this->visibility_ = visibility; this->nonvis_ = nonvis; - this->is_target_special_ = false; this->is_def_ = false; this->is_forwarder_ = false; this->has_alias_ = false; this->needs_dynsym_entry_ = false; this->in_reg_ = false; this->in_dyn_ = false; - this->has_plt_offset_ = false; this->has_warning_ = false; this->is_copied_from_dynobj_ = false; this->is_forced_local_ = false; this->is_ordinary_shndx_ = false; + this->in_real_elf_ = false; + this->is_defined_in_discarded_section_ = false; } // Return the demangled version of the symbol's name, but only @@ -117,6 +120,7 @@ Symbol::init_base_object(const char* name, const char* version, Object* object, this->source_ = FROM_OBJECT; this->in_reg_ = !object->is_dynamic(); this->in_dyn_ = object->is_dynamic(); + this->in_real_elf_ = object->pluginobj() == NULL; } // Initialize the fields in the base class Symbol for a symbol defined @@ -133,6 +137,7 @@ Symbol::init_base_output_data(const char* name, const char* version, this->u_.in_output_data.offset_is_from_end = offset_is_from_end; this->source_ = IN_OUTPUT_DATA; this->in_reg_ = true; + this->in_real_elf_ = true; } // Initialize the fields in the base class Symbol for a symbol defined @@ -150,6 +155,7 @@ Symbol::init_base_output_segment(const char* name, const char* version, this->u_.in_output_segment.offset_base = offset_base; this->source_ = IN_OUTPUT_SEGMENT; this->in_reg_ = true; + this->in_real_elf_ = true; } // Initialize the fields in the base class Symbol for a symbol defined @@ -163,6 +169,7 @@ Symbol::init_base_constant(const char* name, const char* version, this->init_fields(name, version, type, binding, visibility, nonvis); this->source_ = IS_CONSTANT; this->in_reg_ = true; + this->in_real_elf_ = true; } // Initialize the fields in the base class Symbol for an undefined @@ -177,6 +184,7 @@ Symbol::init_base_undefined(const char* name, const char* version, this->dynsym_index_ = -1U; this->source_ = IS_UNDEFINED; this->in_reg_ = true; + this->in_real_elf_ = true; } // Allocate a common symbol in the base. @@ -271,6 +279,16 @@ Sized_symbol<size>::init_undefined(const char* name, const char* version, this->symsize_ = 0; } +// Return true if SHNDX represents a common symbol. + +bool +Symbol::is_common_shndx(unsigned int shndx) +{ + return (shndx == elfcpp::SHN_COMMON + || shndx == parameters->target().small_common_shndx() + || shndx == parameters->target().large_common_shndx()); +} + // Allocate a common symbol. template<int size> @@ -281,6 +299,9 @@ Sized_symbol<size>::allocate_common(Output_data* od, Value_type value) this->value_ = value; } +// The ""'s around str ensure str is a string literal, so sizeof works. +#define strprefix(var, str) (strncmp(var, str, sizeof("" str "") - 1) == 0) + // Return true if this symbol should be added to the dynamic symbol // table. @@ -291,10 +312,68 @@ Symbol::should_add_dynsym_entry() const if (this->needs_dynsym_entry()) return true; + // If this symbol's section is not added, the symbol need not be added. + // The section may have been GCed. Note that export_dynamic is being + // overridden here. This should not be done for shared objects. + if (parameters->options().gc_sections() + && !parameters->options().shared() + && this->source() == Symbol::FROM_OBJECT + && !this->object()->is_dynamic()) + { + Relobj* relobj = static_cast<Relobj*>(this->object()); + bool is_ordinary; + unsigned int shndx = this->shndx(&is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF + && !relobj->is_section_included(shndx)) + return false; + } + // If the symbol was forced local in a version script, do not add it. if (this->is_forced_local()) return false; + // If the symbol was forced dynamic in a --dynamic-list file, add it. + if (parameters->options().in_dynamic_list(this->name())) + return true; + + // If dynamic-list-data was specified, add any STT_OBJECT. + if (parameters->options().dynamic_list_data() + && !this->is_from_dynobj() + && this->type() == elfcpp::STT_OBJECT) + return true; + + // If --dynamic-list-cpp-new was specified, add any new/delete symbol. + // If --dynamic-list-cpp-typeinfo was specified, add any typeinfo symbols. + if ((parameters->options().dynamic_list_cpp_new() + || parameters->options().dynamic_list_cpp_typeinfo()) + && !this->is_from_dynobj()) + { + // TODO(csilvers): We could probably figure out if we're an operator + // new/delete or typeinfo without the need to demangle. + char* demangled_name = cplus_demangle(this->name(), + DMGL_ANSI | DMGL_PARAMS); + if (demangled_name == NULL) + { + // Not a C++ symbol, so it can't satisfy these flags + } + else if (parameters->options().dynamic_list_cpp_new() + && (strprefix(demangled_name, "operator new") + || strprefix(demangled_name, "operator delete"))) + { + free(demangled_name); + return true; + } + else if (parameters->options().dynamic_list_cpp_typeinfo() + && (strprefix(demangled_name, "typeinfo name for") + || strprefix(demangled_name, "typeinfo for"))) + { + free(demangled_name); + return true; + } + else + free(demangled_name); + } + // If exporting all symbols or building a shared library, // and the symbol is defined in a regular object and is // externally visible, we need to add it. @@ -314,7 +393,8 @@ Symbol::final_value_is_known() const { // If we are not generating an executable, then no final values are // known, since they will change at runtime. - if (parameters->options().shared() || parameters->options().relocatable()) + if (parameters->options().output_is_position_independent() + || parameters->options().relocatable()) return false; // If the symbol is not from an object file, and is not undefined, @@ -357,6 +437,7 @@ Symbol::output_section() const if (shndx != elfcpp::SHN_UNDEF && this->is_ordinary_shndx_) { gold_assert(!this->u_.from_object.object->is_dynamic()); + gold_assert(this->u_.from_object.object->pluginobj() == NULL); Relobj* relobj = static_cast<Relobj*>(this->u_.from_object.object); return relobj->output_section(shndx); } @@ -406,8 +487,9 @@ Symbol::set_output_section(Output_section* os) Symbol_table::Symbol_table(unsigned int count, const Version_script_info& version_script) : saw_undefined_(0), offset_(0), table_(count), namepool_(), - forwarders_(), commons_(), tls_commons_(), forced_locals_(), warnings_(), - version_script_(version_script) + forwarders_(), commons_(), tls_commons_(), small_commons_(), + large_commons_(), forced_locals_(), warnings_(), + version_script_(version_script), gc_(NULL), icf_(NULL) { namepool_.reserve(count); } @@ -434,6 +516,79 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1, return k1.first == k2.first && k1.second == k2.second; } +bool +Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const +{ + return (parameters->options().icf_enabled() + && this->icf_->is_section_folded(obj, shndx)); +} + +// For symbols that have been listed with -u option, add them to the +// work list to avoid gc'ing them. + +void +Symbol_table::gc_mark_undef_symbols() +{ + for (options::String_set::const_iterator p = + parameters->options().undefined_begin(); + p != parameters->options().undefined_end(); + ++p) + { + const char* name = p->c_str(); + Symbol* sym = this->lookup(name); + gold_assert (sym != NULL); + if (sym->source() == Symbol::FROM_OBJECT + && !sym->object()->is_dynamic()) + { + Relobj* obj = static_cast<Relobj*>(sym->object()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary) + { + gold_assert(this->gc_ != NULL); + this->gc_->worklist().push(Section_id(obj, shndx)); + } + } + } +} + +void +Symbol_table::gc_mark_symbol_for_shlib(Symbol* sym) +{ + if (!sym->is_from_dynobj() + && sym->is_externally_visible()) + { + //Add the object and section to the work list. + Relobj* obj = static_cast<Relobj*>(sym->object()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF) + { + gold_assert(this->gc_!= NULL); + this->gc_->worklist().push(Section_id(obj, shndx)); + } + } +} + +// When doing garbage collection, keep symbols that have been seen in +// dynamic objects. +inline void +Symbol_table::gc_mark_dyn_syms(Symbol* sym) +{ + if (sym->in_dyn() && sym->source() == Symbol::FROM_OBJECT + && !sym->object()->is_dynamic()) + { + Relobj *obj = static_cast<Relobj*>(sym->object()); + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + if (is_ordinary && shndx != elfcpp::SHN_UNDEF) + { + gold_assert(this->gc_ != NULL); + this->gc_->worklist().push(Section_id(obj, shndx)); + } + } +} + // Make TO a symbol which forwards to FROM. void @@ -507,9 +662,12 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from) to->set_in_reg(); if (from->in_dyn()) to->set_in_dyn(); + if (parameters->options().gc_sections()) + this->gc_mark_dyn_syms(to); } -// Record that a symbol is forced to be local by a version script. +// Record that a symbol is forced to be local by a version script or +// by visibility. void Symbol_table::force_local(Symbol* sym) @@ -530,13 +688,12 @@ Symbol_table::force_local(Symbol* sym) // option was used. const char* -Symbol_table::wrap_symbol(Object* object, const char* name, - Stringpool::Key* name_key) +Symbol_table::wrap_symbol(const char* name, Stringpool::Key* name_key) { // For some targets, we need to ignore a specific character when // wrapping, and add it back later. char prefix = '\0'; - if (name[0] == object->target()->wrap_char()) + if (name[0] == parameters->target().wrap_char()) { prefix = name[0]; ++name; @@ -573,19 +730,95 @@ Symbol_table::wrap_symbol(Object* object, const char* name, return name; } +// This is called when we see a symbol NAME/VERSION, and the symbol +// already exists in the symbol table, and VERSION is marked as being +// the default version. SYM is the NAME/VERSION symbol we just added. +// DEFAULT_IS_NEW is true if this is the first time we have seen the +// symbol NAME/NULL. PDEF points to the entry for NAME/NULL. + +template<int size, bool big_endian> +void +Symbol_table::define_default_version(Sized_symbol<size>* sym, + bool default_is_new, + Symbol_table_type::iterator pdef) +{ + if (default_is_new) + { + // This is the first time we have seen NAME/NULL. Make + // NAME/NULL point to NAME/VERSION, and mark SYM as the default + // version. + pdef->second = sym; + sym->set_is_default(); + } + else if (pdef->second == sym) + { + // NAME/NULL already points to NAME/VERSION. Don't mark the + // symbol as the default if it is not already the default. + } + else + { + // This is the unfortunate case where we already have entries + // for both NAME/VERSION and NAME/NULL. We now see a symbol + // NAME/VERSION where VERSION is the default version. We have + // already resolved this new symbol with the existing + // NAME/VERSION symbol. + + // It's possible that NAME/NULL and NAME/VERSION are both + // defined in regular objects. This can only happen if one + // object file defines foo and another defines foo@@ver. This + // is somewhat obscure, but we call it a multiple definition + // error. + + // It's possible that NAME/NULL actually has a version, in which + // case it won't be the same as VERSION. This happens with + // ver_test_7.so in the testsuite for the symbol t2_2. We see + // t2_2@@VER2, so we define both t2_2/VER2 and t2_2/NULL. We + // then see an unadorned t2_2 in an object file and give it + // version VER1 from the version script. This looks like a + // default definition for VER1, so it looks like we should merge + // t2_2/NULL with t2_2/VER1. That doesn't make sense, but it's + // not obvious that this is an error, either. So we just punt. + + // If one of the symbols has non-default visibility, and the + // other is defined in a shared object, then they are different + // symbols. + + // Otherwise, we just resolve the symbols as though they were + // the same. + + if (pdef->second->version() != NULL) + gold_assert(pdef->second->version() != sym->version()); + else if (sym->visibility() != elfcpp::STV_DEFAULT + && pdef->second->is_from_dynobj()) + ; + else if (pdef->second->visibility() != elfcpp::STV_DEFAULT + && sym->is_from_dynobj()) + ; + else + { + const Sized_symbol<size>* symdef; + symdef = this->get_sized_symbol<size>(pdef->second); + Symbol_table::resolve<size, big_endian>(sym, symdef); + this->make_forwarder(pdef->second, sym); + pdef->second = sym; + sym->set_is_default(); + } + } +} + // Add one symbol from OBJECT to the symbol table. NAME is symbol // name and VERSION is the version; both are canonicalized. DEF is // whether this is the default version. ST_SHNDX is the symbol's // section index; IS_ORDINARY is whether this is a normal section // rather than a special code. -// If DEF is true, then this is the definition of a default version of -// a symbol. That means that any lookup of NAME/NULL and any lookup -// of NAME/VERSION should always return the same symbol. This is -// obvious for references, but in particular we want to do this for -// definitions: overriding NAME/NULL should also override -// NAME/VERSION. If we don't do that, it would be very hard to -// override functions in a shared library which uses versioning. +// If IS_DEFAULT_VERSION is true, then this is the definition of a +// default version of a symbol. That means that any lookup of +// NAME/NULL and any lookup of NAME/VERSION should always return the +// same symbol. This is obvious for references, but in particular we +// want to do this for definitions: overriding NAME/NULL should also +// override NAME/VERSION. If we don't do that, it would be very hard +// to override functions in a shared library which uses versioning. // We implement this by simply making both entries in the hash table // point to the same Symbol structure. That is easy enough if this is @@ -610,7 +843,7 @@ Symbol_table::add_from_object(Object* object, Stringpool::Key name_key, const char *version, Stringpool::Key version_key, - bool def, + bool is_default_version, const elfcpp::Sym<size, big_endian>& sym, unsigned int st_shndx, bool is_ordinary, @@ -630,7 +863,7 @@ Symbol_table::add_from_object(Object* object, if (orig_st_shndx == elfcpp::SHN_UNDEF && parameters->options().any_wrap()) { - const char* wrap_name = this->wrap_symbol(object, name, &name_key); + const char* wrap_name = this->wrap_symbol(name, &name_key); if (wrap_name != name) { // If we see a reference to malloc with version GLIBC_2.0, @@ -649,14 +882,14 @@ Symbol_table::add_from_object(Object* object, this->table_.insert(std::make_pair(std::make_pair(name_key, version_key), snull)); - std::pair<typename Symbol_table_type::iterator, bool> insdef = + std::pair<typename Symbol_table_type::iterator, bool> insdefault = std::make_pair(this->table_.end(), false); - if (def) + if (is_default_version) { const Stringpool::Key vnull_key = 0; - insdef = this->table_.insert(std::make_pair(std::make_pair(name_key, - vnull_key), - snull)); + insdefault = this->table_.insert(std::make_pair(std::make_pair(name_key, + vnull_key), + snull)); } // ins.first: an iterator, which is a pointer to a pair. @@ -678,88 +911,31 @@ Symbol_table::add_from_object(Object* object, this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object, version); + if (parameters->options().gc_sections()) + this->gc_mark_dyn_syms(ret); - if (def) - { - if (insdef.second) - { - // This is the first time we have seen NAME/NULL. Make - // NAME/NULL point to NAME/VERSION. - insdef.first->second = ret; - } - else if (insdef.first->second != ret) - { - // This is the unfortunate case where we already have - // entries for both NAME/VERSION and NAME/NULL. We now - // see a symbol NAME/VERSION where VERSION is the - // default version. We have already resolved this new - // symbol with the existing NAME/VERSION symbol. - - // It's possible that NAME/NULL and NAME/VERSION are - // both defined in regular objects. This can only - // happen if one object file defines foo and another - // defines foo@@ver. This is somewhat obscure, but we - // call it a multiple definition error. - - // It's possible that NAME/NULL actually has a version, - // in which case it won't be the same as VERSION. This - // happens with ver_test_7.so in the testsuite for the - // symbol t2_2. We see t2_2@@VER2, so we define both - // t2_2/VER2 and t2_2/NULL. We then see an unadorned - // t2_2 in an object file and give it version VER1 from - // the version script. This looks like a default - // definition for VER1, so it looks like we should merge - // t2_2/NULL with t2_2/VER1. That doesn't make sense, - // but it's not obvious that this is an error, either. - // So we just punt. - - // If one of the symbols has non-default visibility, and - // the other is defined in a shared object, then they - // are different symbols. - - // Otherwise, we just resolve the symbols as though they - // were the same. - - if (insdef.first->second->version() != NULL) - { - gold_assert(insdef.first->second->version() != version); - def = false; - } - else if (ret->visibility() != elfcpp::STV_DEFAULT - && insdef.first->second->is_from_dynobj()) - def = false; - else if (insdef.first->second->visibility() != elfcpp::STV_DEFAULT - && ret->is_from_dynobj()) - def = false; - else - { - const Sized_symbol<size>* sym2; - sym2 = this->get_sized_symbol<size>(insdef.first->second); - Symbol_table::resolve<size, big_endian>(ret, sym2); - this->make_forwarder(insdef.first->second, ret); - insdef.first->second = ret; - } - } - else - def = false; - } + if (is_default_version) + this->define_default_version<size, big_endian>(ret, insdefault.second, + insdefault.first); } else { // This is the first time we have seen NAME/VERSION. gold_assert(ins.first->second == NULL); - if (def && !insdef.second) + if (is_default_version && !insdefault.second) { // We already have an entry for NAME/NULL. If we override // it, then change it to NAME/VERSION. - ret = this->get_sized_symbol<size>(insdef.first->second); + ret = this->get_sized_symbol<size>(insdefault.first->second); was_undefined = ret->is_undefined(); was_common = ret->is_common(); this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object, version); + if (parameters->options().gc_sections()) + this->gc_mark_dyn_syms(ret); ins.first->second = ret; } else @@ -768,7 +944,7 @@ Symbol_table::add_from_object(Object* object, was_common = false; Sized_target<size, big_endian>* target = - object->sized_target<size, big_endian>(); + parameters->sized_target<size, big_endian>(); if (!target->has_make_symbol()) ret = new Sized_symbol<size>(); else @@ -778,12 +954,12 @@ Symbol_table::add_from_object(Object* object, { // This means that we don't want a symbol table // entry after all. - if (!def) + if (!is_default_version) this->table_.erase(ins.first); else { - this->table_.erase(insdef.first); - // Inserting insdef invalidated ins. + this->table_.erase(insdefault.first); + // Inserting INSDEFAULT invalidated INS. this->table_.erase(std::make_pair(name_key, version_key)); } @@ -794,14 +970,17 @@ Symbol_table::add_from_object(Object* object, ret->init_object(name, version, object, sym, st_shndx, is_ordinary); ins.first->second = ret; - if (def) + if (is_default_version) { // This is the first time we have seen NAME/NULL. Point // it at the new entry for NAME/VERSION. - gold_assert(insdef.second); - insdef.first->second = ret; + gold_assert(insdefault.second); + insdefault.first->second = ret; } } + + if (is_default_version) + ret->set_is_default(); } // Record every time we see a new undefined symbol, to speed up @@ -813,14 +992,28 @@ Symbol_table::add_from_object(Object* object, // allocation. if (!was_common && ret->is_common()) { - if (ret->type() != elfcpp::STT_TLS) - this->commons_.push_back(ret); - else + if (ret->type() == elfcpp::STT_TLS) this->tls_commons_.push_back(ret); + else if (!is_ordinary + && st_shndx == parameters->target().small_common_shndx()) + this->small_commons_.push_back(ret); + else if (!is_ordinary + && st_shndx == parameters->target().large_common_shndx()) + this->large_commons_.push_back(ret); + else + this->commons_.push_back(ret); } - if (def) - ret->set_is_default(); + // If we're not doing a relocatable link, then any symbol with + // hidden or internal visibility is local. + if ((ret->visibility() == elfcpp::STV_HIDDEN + || ret->visibility() == elfcpp::STV_INTERNAL) + && (ret->binding() == elfcpp::STB_GLOBAL + || ret->binding() == elfcpp::STB_GNU_UNIQUE + || ret->binding() == elfcpp::STB_WEAK) + && !parameters->options().relocatable()) + this->force_local(ret); + return ret; } @@ -840,7 +1033,6 @@ Symbol_table::add_from_relobj( { *defined = 0; - gold_assert(size == relobj->target()->get_size()); gold_assert(size == parameters->target().get_size()); const int sym_size = elfcpp::Elf_sizes<size>::sym_size; @@ -877,10 +1069,14 @@ Symbol_table::add_from_relobj( // A symbol defined in a section which we are not including must // be treated as an undefined symbol. + bool is_defined_in_discarded_section = false; if (st_shndx != elfcpp::SHN_UNDEF && is_ordinary && !relobj->is_section_included(st_shndx)) - st_shndx = elfcpp::SHN_UNDEF; + { + st_shndx = elfcpp::SHN_UNDEF; + is_defined_in_discarded_section = true; + } // In an object file, an '@' in the name separates the symbol // name from the version name. If there are two '@' characters, @@ -888,9 +1084,10 @@ Symbol_table::add_from_relobj( const char* ver = strchr(name, '@'); Stringpool::Key ver_key = 0; int namelen = 0; - // DEF: is the version default? LOCAL: is the symbol forced local? - bool def = false; - bool local = false; + // IS_DEFAULT_VERSION: is the version default? + // IS_FORCED_LOCAL: is the symbol forced local? + bool is_default_version = false; + bool is_forced_local = false; if (ver != NULL) { @@ -899,7 +1096,7 @@ Symbol_table::add_from_relobj( ++ver; if (*ver == '@') { - def = true; + is_default_version = true; ++ver; } ver = this->namepool_.add(ver, true, &ver_key); @@ -916,21 +1113,21 @@ Symbol_table::add_from_relobj( // The symbol name did not have a version, but the // version script may assign a version anyway. std::string version; - if (this->version_script_.get_symbol_version(name, &version)) + bool is_global; + if (this->version_script_.get_symbol_version(name, &version, + &is_global)) { - // The version can be empty if the version script is - // only used to force some symbols to be local. - if (!version.empty()) + if (!is_global) + is_forced_local = true; + else if (!version.empty()) { ver = this->namepool_.add_with_length(version.c_str(), version.length(), true, &ver_key); - def = true; + is_default_version = true; } } - else if (this->version_script_.symbol_is_local(name)) - local = true; } } @@ -957,22 +1154,116 @@ Symbol_table::add_from_relobj( psym = &sym2; } + // Fix up visibility if object has no-export set. + if (relobj->no_export() + && (orig_st_shndx != elfcpp::SHN_UNDEF || !is_ordinary)) + { + // We may have copied symbol already above. + if (psym != &sym2) + { + memcpy(symbuf, p, sym_size); + psym = &sym2; + } + + elfcpp::STV visibility = sym2.get_st_visibility(); + if (visibility == elfcpp::STV_DEFAULT + || visibility == elfcpp::STV_PROTECTED) + { + elfcpp::Sym_write<size, big_endian> sw(symbuf); + unsigned char nonvis = sym2.get_st_nonvis(); + sw.put_st_other(elfcpp::STV_HIDDEN, nonvis); + } + } + Stringpool::Key name_key; name = this->namepool_.add_with_length(name, namelen, true, &name_key); Sized_symbol<size>* res; res = this->add_from_object(relobj, name, name_key, ver, ver_key, - def, *psym, st_shndx, is_ordinary, - orig_st_shndx); - - if (local) + is_default_version, *psym, st_shndx, + is_ordinary, orig_st_shndx); + + // If building a shared library using garbage collection, do not + // treat externally visible symbols as garbage. + if (parameters->options().gc_sections() + && parameters->options().shared()) + this->gc_mark_symbol_for_shlib(res); + + if (is_forced_local) this->force_local(res); + if (is_defined_in_discarded_section) + res->set_is_defined_in_discarded_section(); + (*sympointers)[i] = res; } } +// Add a symbol from a plugin-claimed file. + +template<int size, bool big_endian> +Symbol* +Symbol_table::add_from_pluginobj( + Sized_pluginobj<size, big_endian>* obj, + const char* name, + const char* ver, + elfcpp::Sym<size, big_endian>* sym) +{ + unsigned int st_shndx = sym->get_st_shndx(); + bool is_ordinary = st_shndx < elfcpp::SHN_LORESERVE; + + Stringpool::Key ver_key = 0; + bool is_default_version = false; + bool is_forced_local = false; + + if (ver != NULL) + { + ver = this->namepool_.add(ver, true, &ver_key); + } + // We don't want to assign a version to an undefined symbol, + // even if it is listed in the version script. FIXME: What + // about a common symbol? + else + { + if (!this->version_script_.empty() + && st_shndx != elfcpp::SHN_UNDEF) + { + // The symbol name did not have a version, but the + // version script may assign a version anyway. + std::string version; + bool is_global; + if (this->version_script_.get_symbol_version(name, &version, + &is_global)) + { + if (!is_global) + is_forced_local = true; + else if (!version.empty()) + { + ver = this->namepool_.add_with_length(version.c_str(), + version.length(), + true, + &ver_key); + is_default_version = true; + } + } + } + } + + Stringpool::Key name_key; + name = this->namepool_.add(name, true, &name_key); + + Sized_symbol<size>* res; + res = this->add_from_object(obj, name, name_key, ver, ver_key, + is_default_version, *sym, st_shndx, + is_ordinary, st_shndx); + + if (is_forced_local) + this->force_local(res); + + return res; +} + // Add all the symbols in a dynamic object to the hash table. template<int size, bool big_endian> @@ -991,7 +1282,6 @@ Symbol_table::add_from_dynobj( { *defined = 0; - gold_assert(size == dynobj->target()->get_size()); gold_assert(size == parameters->target().get_size()); if (dynobj->just_symbols()) @@ -1143,10 +1433,11 @@ Symbol_table::add_from_dynobj( st_shndx); else { - const bool def = (!hidden - && st_shndx != elfcpp::SHN_UNDEF); + const bool is_default_version = + !hidden && st_shndx != elfcpp::SHN_UNDEF; res = this->add_from_object(dynobj, name, name_key, version, - version_key, def, *psym, st_shndx, + version_key, is_default_version, + *psym, st_shndx, is_ordinary, st_shndx); } } @@ -1256,39 +1547,57 @@ Symbol_table::record_weak_aliases(std::vector<Sized_symbol<size>*>* symbols) // Create and return a specially defined symbol. If ONLY_IF_REF is // true, then only create the symbol if there is a reference to it. // If this does not return NULL, it sets *POLDSYM to the existing -// symbol if there is one. This canonicalizes *PNAME and *PVERSION. +// symbol if there is one. This sets *RESOLVE_OLDSYM if we should +// resolve the newly created symbol to the old one. This +// canonicalizes *PNAME and *PVERSION. template<int size, bool big_endian> Sized_symbol<size>* Symbol_table::define_special_symbol(const char** pname, const char** pversion, bool only_if_ref, - Sized_symbol<size>** poldsym) + Sized_symbol<size>** poldsym, + bool *resolve_oldsym) { - Symbol* oldsym; - Sized_symbol<size>* sym; - bool add_to_table = false; - typename Symbol_table_type::iterator add_loc = this->table_.end(); + *resolve_oldsym = false; // If the caller didn't give us a version, see if we get one from // the version script. std::string v; + bool is_default_version = false; if (*pversion == NULL) { - if (this->version_script_.get_symbol_version(*pname, &v)) + bool is_global; + if (this->version_script_.get_symbol_version(*pname, &v, &is_global)) { - if (!v.empty()) - *pversion = v.c_str(); + if (is_global && !v.empty()) + { + *pversion = v.c_str(); + // If we get the version from a version script, then we + // are also the default version. + is_default_version = true; + } } } + Symbol* oldsym; + Sized_symbol<size>* sym; + + bool add_to_table = false; + typename Symbol_table_type::iterator add_loc = this->table_.end(); + bool add_def_to_table = false; + typename Symbol_table_type::iterator add_def_loc = this->table_.end(); + if (only_if_ref) { oldsym = this->lookup(*pname, *pversion); + if (oldsym == NULL && is_default_version) + oldsym = this->lookup(*pname, NULL); if (oldsym == NULL || !oldsym->is_undefined()) return NULL; *pname = oldsym->name(); - *pversion = oldsym->version(); + if (!is_default_version) + *pversion = oldsym->version(); } else { @@ -1306,19 +1615,57 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, version_key), snull)); + std::pair<typename Symbol_table_type::iterator, bool> insdefault = + std::make_pair(this->table_.end(), false); + if (is_default_version) + { + const Stringpool::Key vnull = 0; + insdefault = + this->table_.insert(std::make_pair(std::make_pair(name_key, + vnull), + snull)); + } + if (!ins.second) { // We already have a symbol table entry for NAME/VERSION. oldsym = ins.first->second; gold_assert(oldsym != NULL); + + if (is_default_version) + { + Sized_symbol<size>* soldsym = + this->get_sized_symbol<size>(oldsym); + this->define_default_version<size, big_endian>(soldsym, + insdefault.second, + insdefault.first); + } } else { // We haven't seen this symbol before. gold_assert(ins.first->second == NULL); - add_to_table = true; - add_loc = ins.first; - oldsym = NULL; + + add_to_table = true; + add_loc = ins.first; + + if (is_default_version && !insdefault.second) + { + // We are adding NAME/VERSION, and it is the default + // version. We already have an entry for NAME/NULL. + oldsym = insdefault.first->second; + *resolve_oldsym = true; + } + else + { + oldsym = NULL; + + if (is_default_version) + { + add_def_to_table = true; + add_def_loc = insdefault.first; + } + } } } @@ -1327,11 +1674,8 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, sym = new Sized_symbol<size>(); else { - gold_assert(target.get_size() == size); - gold_assert(target.is_big_endian() ? big_endian : !big_endian); - typedef Sized_target<size, big_endian> My_target; - const My_target* sized_target = - static_cast<const My_target*>(&target); + Sized_target<size, big_endian>* sized_target = + parameters->sized_target<size, big_endian>(); sym = sized_target->make_symbol(); if (sym == NULL) return NULL; @@ -1342,6 +1686,9 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, else gold_assert(oldsym != NULL); + if (add_def_to_table) + add_def_loc->second = sym; + *poldsym = this->get_sized_symbol<size>(oldsym); return sym; @@ -1352,6 +1699,7 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion, Symbol* Symbol_table::define_in_output_data(const char* name, const char* version, + Defined defined, Output_data* od, uint64_t value, uint64_t symsize, @@ -1365,7 +1713,7 @@ Symbol_table::define_in_output_data(const char* name, if (parameters->target().get_size() == 32) { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) - return this->do_define_in_output_data<32>(name, version, od, + return this->do_define_in_output_data<32>(name, version, defined, od, value, symsize, type, binding, visibility, nonvis, offset_is_from_end, @@ -1377,7 +1725,7 @@ Symbol_table::define_in_output_data(const char* name, else if (parameters->target().get_size() == 64) { #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) - return this->do_define_in_output_data<64>(name, version, od, + return this->do_define_in_output_data<64>(name, version, defined, od, value, symsize, type, binding, visibility, nonvis, offset_is_from_end, @@ -1397,6 +1745,7 @@ Sized_symbol<size>* Symbol_table::do_define_in_output_data( const char* name, const char* version, + Defined defined, Output_data* od, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword symsize, @@ -1409,12 +1758,14 @@ Symbol_table::do_define_in_output_data( { Sized_symbol<size>* sym; Sized_symbol<size>* oldsym; + bool resolve_oldsym; if (parameters->target().is_big_endian()) { #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) sym = this->define_special_symbol<size, true>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1423,7 +1774,8 @@ Symbol_table::do_define_in_output_data( { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) sym = this->define_special_symbol<size, false>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1445,17 +1797,25 @@ Symbol_table::do_define_in_output_data( return sym; } - if (Symbol_table::should_override_with_special(oldsym)) + if (Symbol_table::should_override_with_special(oldsym, defined)) this->override_with_special(oldsym, sym); - delete sym; - return oldsym; + + if (resolve_oldsym) + return sym; + else + { + delete sym; + return oldsym; + } } // Define a symbol based on an Output_segment. Symbol* Symbol_table::define_in_output_segment(const char* name, - const char* version, Output_segment* os, + const char* version, + Defined defined, + Output_segment* os, uint64_t value, uint64_t symsize, elfcpp::STT type, @@ -1468,7 +1828,7 @@ Symbol_table::define_in_output_segment(const char* name, if (parameters->target().get_size() == 32) { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) - return this->do_define_in_output_segment<32>(name, version, os, + return this->do_define_in_output_segment<32>(name, version, defined, os, value, symsize, type, binding, visibility, nonvis, offset_base, only_if_ref); @@ -1479,7 +1839,7 @@ Symbol_table::define_in_output_segment(const char* name, else if (parameters->target().get_size() == 64) { #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) - return this->do_define_in_output_segment<64>(name, version, os, + return this->do_define_in_output_segment<64>(name, version, defined, os, value, symsize, type, binding, visibility, nonvis, offset_base, only_if_ref); @@ -1498,6 +1858,7 @@ Sized_symbol<size>* Symbol_table::do_define_in_output_segment( const char* name, const char* version, + Defined defined, Output_segment* os, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword symsize, @@ -1510,12 +1871,14 @@ Symbol_table::do_define_in_output_segment( { Sized_symbol<size>* sym; Sized_symbol<size>* oldsym; + bool resolve_oldsym; if (parameters->target().is_big_endian()) { #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) sym = this->define_special_symbol<size, true>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1524,7 +1887,8 @@ Symbol_table::do_define_in_output_segment( { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) sym = this->define_special_symbol<size, false>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1546,10 +1910,16 @@ Symbol_table::do_define_in_output_segment( return sym; } - if (Symbol_table::should_override_with_special(oldsym)) + if (Symbol_table::should_override_with_special(oldsym, defined)) this->override_with_special(oldsym, sym); - delete sym; - return oldsym; + + if (resolve_oldsym) + return sym; + else + { + delete sym; + return oldsym; + } } // Define a special symbol with a constant value. It is a multiple @@ -1558,6 +1928,7 @@ Symbol_table::do_define_in_output_segment( Symbol* Symbol_table::define_as_constant(const char* name, const char* version, + Defined defined, uint64_t value, uint64_t symsize, elfcpp::STT type, @@ -1570,7 +1941,7 @@ Symbol_table::define_as_constant(const char* name, if (parameters->target().get_size() == 32) { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG) - return this->do_define_as_constant<32>(name, version, value, + return this->do_define_as_constant<32>(name, version, defined, value, symsize, type, binding, visibility, nonvis, only_if_ref, force_override); @@ -1581,7 +1952,7 @@ Symbol_table::define_as_constant(const char* name, else if (parameters->target().get_size() == 64) { #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG) - return this->do_define_as_constant<64>(name, version, value, + return this->do_define_as_constant<64>(name, version, defined, value, symsize, type, binding, visibility, nonvis, only_if_ref, force_override); @@ -1600,6 +1971,7 @@ Sized_symbol<size>* Symbol_table::do_define_as_constant( const char* name, const char* version, + Defined defined, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword symsize, elfcpp::STT type, @@ -1611,12 +1983,14 @@ Symbol_table::do_define_as_constant( { Sized_symbol<size>* sym; Sized_symbol<size>* oldsym; + bool resolve_oldsym; if (parameters->target().is_big_endian()) { #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) sym = this->define_special_symbol<size, true>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1625,7 +1999,8 @@ Symbol_table::do_define_as_constant( { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) sym = this->define_special_symbol<size, false>(&name, &version, - only_if_ref, &oldsym); + only_if_ref, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1653,10 +2028,17 @@ Symbol_table::do_define_as_constant( return sym; } - if (force_override || Symbol_table::should_override_with_special(oldsym)) + if (force_override + || Symbol_table::should_override_with_special(oldsym, defined)) this->override_with_special(oldsym, sym); - delete sym; - return oldsym; + + if (resolve_oldsym) + return sym; + else + { + delete sym; + return oldsym; + } } // Define a set of symbols in output sections. @@ -1670,14 +2052,14 @@ Symbol_table::define_symbols(const Layout* layout, int count, { Output_section* os = layout->find_output_section(p->output_section); if (os != NULL) - this->define_in_output_data(p->name, NULL, os, p->value, + this->define_in_output_data(p->name, NULL, PREDEFINED, os, p->value, p->size, p->type, p->binding, p->visibility, p->nonvis, p->offset_is_from_end, only_if_ref || p->only_if_ref); else - this->define_as_constant(p->name, NULL, 0, p->size, p->type, - p->binding, p->visibility, p->nonvis, + this->define_as_constant(p->name, NULL, PREDEFINED, 0, p->size, + p->type, p->binding, p->visibility, p->nonvis, only_if_ref || p->only_if_ref, false); } @@ -1696,14 +2078,14 @@ Symbol_table::define_symbols(const Layout* layout, int count, p->segment_flags_set, p->segment_flags_clear); if (os != NULL) - this->define_in_output_segment(p->name, NULL, os, p->value, + this->define_in_output_segment(p->name, NULL, PREDEFINED, os, p->value, p->size, p->type, p->binding, p->visibility, p->nonvis, p->offset_base, only_if_ref || p->only_if_ref); else - this->define_as_constant(p->name, NULL, 0, p->size, p->type, - p->binding, p->visibility, p->nonvis, + this->define_as_constant(p->name, NULL, PREDEFINED, 0, p->size, + p->type, p->binding, p->visibility, p->nonvis, only_if_ref || p->only_if_ref, false); } @@ -1732,7 +2114,7 @@ Symbol_table::define_with_copy_reloc( if (binding == elfcpp::STB_WEAK) binding = elfcpp::STB_GLOBAL; - this->define_in_output_data(csym->name(), csym->version(), + this->define_in_output_data(csym->name(), csym->version(), COPY, posd, value, csym->symsize(), csym->type(), binding, csym->visibility(), csym->nonvis(), @@ -1820,11 +2202,13 @@ Symbol_table::do_add_undefined_symbols_from_command_line() Sized_symbol<size>* sym; Sized_symbol<size>* oldsym; + bool resolve_oldsym; if (parameters->target().is_big_endian()) { #if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG) sym = this->define_special_symbol<size, true>(&name, &version, - false, &oldsym); + false, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1833,7 +2217,8 @@ Symbol_table::do_add_undefined_symbols_from_command_line() { #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE) sym = this->define_special_symbol<size, false>(&name, &version, - false, &oldsym); + false, &oldsym, + &resolve_oldsym); #else gold_unreachable(); #endif @@ -1880,6 +2265,12 @@ Symbol_table::set_dynsym_indexes(unsigned int index, // Record any version information. if (sym->version() != NULL) versions->record_version(this, dynpool, sym); + + // If the symbol is defined in a dynamic object and is + // referenced in a regular object, then mark the dynamic + // object as needed. This is used to implement --as-needed. + if (sym->is_from_dynobj() && sym->in_reg()) + sym->object()->set_is_needed(); } } @@ -1994,30 +2385,17 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool, return off; } -// Finalize the symbol SYM. This returns true if the symbol should be -// added to the symbol table, false otherwise. +// Compute the final value of SYM and store status in location PSTATUS. +// During relaxation, this may be called multiple times for a symbol to +// compute its would-be final value in each relaxation pass. template<int size> -bool -Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) +typename Sized_symbol<size>::Value_type +Symbol_table::compute_final_value( + const Sized_symbol<size>* sym, + Compute_final_value_status* pstatus) const { typedef typename Sized_symbol<size>::Value_type Value_type; - - Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(unsized_sym); - - // The default version of a symbol may appear twice in the symbol - // table. We only need to finalize it once. - if (sym->has_symtab_index()) - return false; - - if (!sym->in_reg()) - { - gold_assert(!sym->has_symtab_index()); - sym->set_symtab_index(-1U); - gold_assert(sym->dynsym_index() == -1U); - return false; - } - Value_type value; switch (sym->source()) @@ -2027,14 +2405,12 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) bool is_ordinary; unsigned int shndx = sym->shndx(&is_ordinary); - // FIXME: We need some target specific support here. if (!is_ordinary && shndx != elfcpp::SHN_ABS - && shndx != elfcpp::SHN_COMMON) + && !Symbol::is_common_shndx(shndx)) { - gold_error(_("%s: unsupported symbol section 0x%x"), - sym->demangled_name().c_str(), shndx); - shndx = elfcpp::SHN_UNDEF; + *pstatus = CFVS_UNSUPPORTED_SYMBOL_SECTION; + return 0; } Object* symobj = sym->object(); @@ -2043,29 +2419,66 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) value = 0; shndx = elfcpp::SHN_UNDEF; } + else if (symobj->pluginobj() != NULL) + { + value = 0; + shndx = elfcpp::SHN_UNDEF; + } else if (shndx == elfcpp::SHN_UNDEF) value = 0; else if (!is_ordinary - && (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON)) + && (shndx == elfcpp::SHN_ABS + || Symbol::is_common_shndx(shndx))) value = sym->value(); else { Relobj* relobj = static_cast<Relobj*>(symobj); Output_section* os = relobj->output_section(shndx); - if (os == NULL) + if (this->is_section_folded(relobj, shndx)) + { + gold_assert(os == NULL); + // Get the os of the section it is folded onto. + Section_id folded = this->icf_->get_folded_section(relobj, + shndx); + gold_assert(folded.first != NULL); + Relobj* folded_obj = reinterpret_cast<Relobj*>(folded.first); + unsigned folded_shndx = folded.second; + + os = folded_obj->output_section(folded_shndx); + gold_assert(os != NULL); + + // Replace (relobj, shndx) with canonical ICF input section. + shndx = folded_shndx; + relobj = folded_obj; + } + + uint64_t secoff64 = relobj->output_section_offset(shndx); + if (os == NULL) { - sym->set_symtab_index(-1U); - gold_assert(sym->dynsym_index() == -1U); - return false; + bool static_or_reloc = (parameters->doing_static_link() || + parameters->options().relocatable()); + gold_assert(static_or_reloc || sym->dynsym_index() == -1U); + + *pstatus = CFVS_NO_OUTPUT_SECTION; + return 0; } - uint64_t secoff64 = relobj->output_section_offset(shndx); - Value_type secoff = convert_types<Value_type, uint64_t>(secoff64); - if (sym->type() == elfcpp::STT_TLS) - value = sym->value() + os->tls_offset() + secoff; - else - value = sym->value() + os->address() + secoff; + if (secoff64 == -1ULL) + { + // The section needs special handling (e.g., a merge section). + + value = os->output_address(relobj, shndx, sym->value()); + } + else + { + Value_type secoff = + convert_types<Value_type, uint64_t>(secoff64); + if (sym->type() == elfcpp::STT_TLS) + value = sym->value() + os->tls_offset() + secoff; + else + value = sym->value() + os->address() + secoff; + } } } break; @@ -2121,9 +2534,61 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) gold_unreachable(); } + *pstatus = CFVS_OK; + return value; +} + +// Finalize the symbol SYM. This returns true if the symbol should be +// added to the symbol table, false otherwise. + +template<int size> +bool +Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) +{ + typedef typename Sized_symbol<size>::Value_type Value_type; + + Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(unsized_sym); + + // The default version of a symbol may appear twice in the symbol + // table. We only need to finalize it once. + if (sym->has_symtab_index()) + return false; + + if (!sym->in_reg()) + { + gold_assert(!sym->has_symtab_index()); + sym->set_symtab_index(-1U); + gold_assert(sym->dynsym_index() == -1U); + return false; + } + + // Compute final symbol value. + Compute_final_value_status status; + Value_type value = this->compute_final_value(sym, &status); + + switch (status) + { + case CFVS_OK: + break; + case CFVS_UNSUPPORTED_SYMBOL_SECTION: + { + bool is_ordinary; + unsigned int shndx = sym->shndx(&is_ordinary); + gold_error(_("%s: unsupported symbol section 0x%x"), + sym->demangled_name().c_str(), shndx); + } + break; + case CFVS_NO_OUTPUT_SECTION: + sym->set_symtab_index(-1U); + return false; + default: + gold_unreachable(); + } + sym->set_value(value); - if (parameters->options().strip_all()) + if (parameters->options().strip_all() + || !parameters->options().should_retain_symbol(sym->name())) { sym->set_symtab_index(-1U); return false; @@ -2135,8 +2600,7 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym) // Write out the global symbols. void -Symbol_table::write_globals(const Input_objects* input_objects, - const Stringpool* sympool, +Symbol_table::write_globals(const Stringpool* sympool, const Stringpool* dynpool, Output_symtab_xindex* symtab_xindex, Output_symtab_xindex* dynsym_xindex, @@ -2146,29 +2610,25 @@ Symbol_table::write_globals(const Input_objects* input_objects, { #ifdef HAVE_TARGET_32_LITTLE case Parameters::TARGET_32_LITTLE: - this->sized_write_globals<32, false>(input_objects, sympool, - dynpool, symtab_xindex, + this->sized_write_globals<32, false>(sympool, dynpool, symtab_xindex, dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_32_BIG case Parameters::TARGET_32_BIG: - this->sized_write_globals<32, true>(input_objects, sympool, - dynpool, symtab_xindex, + this->sized_write_globals<32, true>(sympool, dynpool, symtab_xindex, dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_64_LITTLE case Parameters::TARGET_64_LITTLE: - this->sized_write_globals<64, false>(input_objects, sympool, - dynpool, symtab_xindex, + this->sized_write_globals<64, false>(sympool, dynpool, symtab_xindex, dynsym_xindex, of); break; #endif #ifdef HAVE_TARGET_64_BIG case Parameters::TARGET_64_BIG: - this->sized_write_globals<64, true>(input_objects, sympool, - dynpool, symtab_xindex, + this->sized_write_globals<64, true>(sympool, dynpool, symtab_xindex, dynsym_xindex, of); break; #endif @@ -2181,8 +2641,7 @@ Symbol_table::write_globals(const Input_objects* input_objects, template<int size, bool big_endian> void -Symbol_table::sized_write_globals(const Input_objects* input_objects, - const Stringpool* sympool, +Symbol_table::sized_write_globals(const Stringpool* sympool, const Stringpool* dynpool, Output_symtab_xindex* symtab_xindex, Output_symtab_xindex* dynsym_xindex, @@ -2218,7 +2677,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second); // Possibly warn about unresolved symbols in shared libraries. - this->warn_about_undefined_dynobj_symbol(input_objects, sym); + this->warn_about_undefined_dynobj_symbol(sym); unsigned int sym_index = sym->symtab_index(); unsigned int dynsym_index; @@ -2243,10 +2702,9 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, bool is_ordinary; unsigned int in_shndx = sym->shndx(&is_ordinary); - // FIXME: We need some target specific support here. if (!is_ordinary && in_shndx != elfcpp::SHN_ABS - && in_shndx != elfcpp::SHN_COMMON) + && !Symbol::is_common_shndx(in_shndx)) { gold_error(_("%s: unsupported symbol section 0x%x"), sym->demangled_name().c_str(), in_shndx); @@ -2261,15 +2719,30 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, dynsym_value = target.dynsym_value(sym); shndx = elfcpp::SHN_UNDEF; } + else if (symobj->pluginobj() != NULL) + shndx = elfcpp::SHN_UNDEF; else if (in_shndx == elfcpp::SHN_UNDEF || (!is_ordinary && (in_shndx == elfcpp::SHN_ABS - || in_shndx == elfcpp::SHN_COMMON))) + || Symbol::is_common_shndx(in_shndx)))) shndx = in_shndx; else { Relobj* relobj = static_cast<Relobj*>(symobj); Output_section* os = relobj->output_section(in_shndx); + if (this->is_section_folded(relobj, in_shndx)) + { + // This global symbol must be written out even though + // it is folded. + // Get the os of the section it is folded onto. + Section_id folded = + this->icf_->get_folded_section(relobj, in_shndx); + gold_assert(folded.first !=NULL); + Relobj* folded_obj = + reinterpret_cast<Relobj*>(folded.first); + os = folded_obj->output_section(folded.second); + gold_assert(os != NULL); + } gold_assert(os != NULL); shndx = os->out_shndx(); @@ -2363,11 +2836,16 @@ Symbol_table::sized_write_symbol( osym.put_st_size(0); else osym.put_st_size(sym->symsize()); + elfcpp::STT type = sym->type(); + // Turn IFUNC symbols from shared libraries into normal FUNC symbols. + if (type == elfcpp::STT_GNU_IFUNC + && sym->is_from_dynobj()) + type = elfcpp::STT_FUNC; // A version script may have overridden the default binding. if (sym->is_forced_local()) - osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, sym->type())); + osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, type)); else - osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type())); + osym.put_st_info(elfcpp::elf_st_info(sym->binding(), type)); osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis())); osym.put_st_shndx(shndx); } @@ -2381,16 +2859,13 @@ Symbol_table::sized_write_symbol( // entry, we aren't going to be able to reliably report whether the // symbol is undefined. -// We also don't warn about libraries found in the system library -// directory (the directory were we find libc.so); we assume that -// those libraries are OK. This heuristic avoids problems in -// GNU/Linux, in which -ldl can have undefined references satisfied by -// ld-linux.so. +// We also don't warn about libraries found in a system library +// directory (e.g., /lib or /usr/lib); we assume that those libraries +// are OK. This heuristic avoids problems on GNU/Linux, in which -ldl +// can have undefined references satisfied by ld-linux.so. inline void -Symbol_table::warn_about_undefined_dynobj_symbol( - const Input_objects* input_objects, - Symbol* sym) const +Symbol_table::warn_about_undefined_dynobj_symbol(Symbol* sym) const { bool dummy; if (sym->source() == Symbol::FROM_OBJECT @@ -2399,22 +2874,12 @@ Symbol_table::warn_about_undefined_dynobj_symbol( && sym->binding() != elfcpp::STB_WEAK && !parameters->options().allow_shlib_undefined() && !parameters->target().is_defined_by_abi(sym) - && !input_objects->found_in_system_library_directory(sym->object())) + && !sym->object()->is_in_system_directory()) { // A very ugly cast. Dynobj* dynobj = static_cast<Dynobj*>(sym->object()); if (!dynobj->has_unknown_needed_entries()) - { - if (sym->version()) - gold_error(_("%s: undefined reference to '%s', version '%s'"), - sym->object()->name().c_str(), - sym->demangled_name().c_str(), - sym->version()); - else - gold_error(_("%s: undefined reference to '%s'"), - sym->object()->name().c_str(), - sym->demangled_name().c_str()); - } + gold_undefined_symbol(sym); } } @@ -2472,7 +2937,10 @@ Symbol_table::sized_write_section_symbol(const Output_section* os, elfcpp::Sym_write<size, big_endian> osym(pov); osym.put_st_name(0); - osym.put_st_value(os->address()); + if (parameters->options().relocatable()) + osym.put_st_value(0); + else + osym.put_st_value(os->address()); osym.put_st_size(0); osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, elfcpp::STT_SECTION)); @@ -2703,6 +3171,46 @@ Symbol_table::add_from_relobj<64, true>( #ifdef HAVE_TARGET_32_LITTLE template +Symbol* +Symbol_table::add_from_pluginobj<32, false>( + Sized_pluginobj<32, false>* obj, + const char* name, + const char* ver, + elfcpp::Sym<32, false>* sym); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +Symbol* +Symbol_table::add_from_pluginobj<32, true>( + Sized_pluginobj<32, true>* obj, + const char* name, + const char* ver, + elfcpp::Sym<32, true>* sym); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +Symbol* +Symbol_table::add_from_pluginobj<64, false>( + Sized_pluginobj<64, false>* obj, + const char* name, + const char* ver, + elfcpp::Sym<64, false>* sym); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +Symbol* +Symbol_table::add_from_pluginobj<64, true>( + Sized_pluginobj<64, true>* obj, + const char* name, + const char* ver, + elfcpp::Sym<64, true>* sym); +#endif + +#ifdef HAVE_TARGET_32_LITTLE +template void Symbol_table::add_from_dynobj<32, false>( Sized_dynobj<32, false>* dynobj, diff --git a/binutils-2.19/gold/symtab.h b/binutils-2.19/gold/symtab.h index 043fb50..1a81fd1 100644 --- a/binutils-2.19/gold/symtab.h +++ b/binutils-2.19/gold/symtab.h @@ -1,6 +1,6 @@ // symtab.h -- the gold symbol table -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -23,6 +23,9 @@ // Symbol_table // The symbol table. +#ifndef GOLD_SYMTAB_H +#define GOLD_SYMTAB_H + #include <string> #include <utility> #include <vector> @@ -32,9 +35,6 @@ #include "stringpool.h" #include "object.h" -#ifndef GOLD_SYMTAB_H -#define GOLD_SYMTAB_H - namespace gold { @@ -43,6 +43,8 @@ class Object; class Relobj; template<int size, bool big_endian> class Sized_relobj; +template<int size, bool big_endian> +class Sized_pluginobj; class Dynobj; template<int size, bool big_endian> class Sized_dynobj; @@ -54,6 +56,8 @@ class Output_section; class Output_segment; class Output_file; class Output_symtab_xindex; +class Garbage_collection; +class Icf; // The base class of an entry in the symbol table. The symbol table // can have a lot of entries, so we don't want this class to big. @@ -201,11 +205,28 @@ class Symbol type() const { return this->type_; } + // Return true for function symbol. + bool + is_func() const + { + return (this->type_ == elfcpp::STT_FUNC + || this->type_ == elfcpp::STT_GNU_IFUNC); + } + // Return the symbol visibility. elfcpp::STV visibility() const { return this->visibility_; } + // Set the visibility. + void + set_visibility(elfcpp::STV visibility) + { this->visibility_ = visibility; } + + // Override symbol visibility. + void + override_visibility(elfcpp::STV); + // Return the non-visibility part of the st_other field. unsigned char nonvis() const @@ -240,7 +261,9 @@ class Symbol needs_dynsym_entry() const { return (this->needs_dynsym_entry_ - || (this->in_reg() && this->in_dyn())); + || (this->in_reg() + && this->in_dyn() + && this->is_externally_visible())); } // Mark this symbol as needing an entry in the dynamic symbol table. @@ -273,6 +296,30 @@ class Symbol set_in_dyn() { this->in_dyn_ = true; } + // Return whether this symbol has been seen in a real ELF object. + // (IN_REG will return TRUE if the symbol has been seen in either + // a real ELF object or an object claimed by a plugin.) + bool + in_real_elf() const + { return this->in_real_elf_; } + + // Mark this symbol as having been seen in a real ELF object. + void + set_in_real_elf() + { this->in_real_elf_ = true; } + + // Return whether this symbol was defined in a section that was + // discarded from the link. This is used to control some error + // reporting. + bool + is_defined_in_discarded_section() const + { return this->is_defined_in_discarded_section_; } + + // Mark this symbol as having been defined in a discarded section. + void + set_is_defined_in_discarded_section() + { this->is_defined_in_discarded_section_ = true; } + // Return the index of this symbol in the output file symbol table. // A value of -1U means that this symbol is not going into the // output file. This starts out as zero, and is set to a non-zero @@ -348,7 +395,7 @@ class Symbol // Return whether this symbol has an entry in the PLT section. bool has_plt_offset() const - { return this->has_plt_offset_; } + { return this->plt_offset_ != -1U; } // Return the offset into the PLT section of this symbol. unsigned int @@ -362,7 +409,7 @@ class Symbol void set_plt_offset(unsigned int plt_offset) { - this->has_plt_offset_ = true; + gold_assert(plt_offset != -1U); this->plt_offset_ = plt_offset; } @@ -386,6 +433,11 @@ class Symbol bool final_value_is_known() const; + // Return true if SHNDX represents a common symbol. This depends on + // the target. + static bool + is_common_shndx(unsigned int shndx); + // Return whether this is a defined symbol (not undefined or // common). bool @@ -397,7 +449,7 @@ class Symbol unsigned int shndx = this->shndx(&is_ordinary); return (is_ordinary ? shndx != elfcpp::SHN_UNDEF - : shndx != elfcpp::SHN_COMMON); + : !Symbol::is_common_shndx(shndx)); } // Return true if this symbol is from a dynamic object. @@ -438,11 +490,13 @@ class Symbol bool is_common() const { + if (this->source_ != FROM_OBJECT) + return false; + if (this->type_ == elfcpp::STT_COMMON) + return true; bool is_ordinary; - return (this->source_ == FROM_OBJECT - && ((this->shndx(&is_ordinary) == elfcpp::SHN_COMMON - && !is_ordinary) - || this->type_ == elfcpp::STT_COMMON)); + unsigned int shndx = this->shndx(&is_ordinary); + return !is_ordinary && Symbol::is_common_shndx(shndx); } // Return whether this symbol can be seen outside this object. @@ -501,12 +555,17 @@ class Symbol // Return true if this symbol is a function that needs a PLT entry. // If the symbol is defined in a dynamic object or if it is subject // to pre-emption, we need to make a PLT entry. If we're doing a - // static link, we don't create PLT entries. + // static link or a -pie link, we don't create PLT entries. bool needs_plt_entry() const { + // An undefined symbol from an executable does not need a PLT entry. + if (this->is_undefined() && !parameters->options().shared()) + return false; + return (!parameters->doing_static_link() - && this->type() == elfcpp::STT_FUNC + && !parameters->options().pie() + && this->is_func() && (this->is_from_dynobj() || this->is_undefined() || this->is_preemptible())); @@ -536,10 +595,10 @@ class Symbol if (parameters->doing_static_link()) return false; - // A reference to a weak undefined symbol from an executable should be + // A reference to an undefined symbol from an executable should be // statically resolved to 0, and does not need a dynamic relocation. // This matches gnu ld behavior. - if (this->is_weak_undefined() && !parameters->options().shared()) + if (this->is_undefined() && !parameters->options().shared()) return false; // A reference to an absolute symbol does not need a dynamic relocation. @@ -688,6 +747,18 @@ class Symbol set_is_forced_local() { this->is_forced_local_ = true; } + // Return true if this may need a COPY relocation. + // References from an executable object to non-function symbols + // defined in a dynamic object may need a COPY relocation. + bool + may_need_copy_reloc() const + { + return (!parameters->options().shared() + && parameters->options().copyreloc() + && this->is_from_dynobj() + && !this->is_func()); + } + protected: // Instances of this class should always be created at a specific // size. @@ -811,16 +882,14 @@ class Symbol // non-zero value during Layout::finalize. unsigned int dynsym_index_; - // If this symbol has an entry in the GOT section (has_got_offset_ - // is true), this holds the offset from the start of the GOT section. - // A symbol may have more than one GOT offset (e.g., when mixing - // modules compiled with two different TLS models), but will usually - // have at most one. + // The GOT section entries for this symbol. A symbol may have more + // than one GOT offset (e.g., when mixing modules compiled with two + // different TLS models), but will usually have at most one. Got_offset_list got_offsets_; - // If this symbol has an entry in the PLT section (has_plt_offset_ - // is true), then this is the offset from the start of the PLT - // section. + // If this symbol has an entry in the PLT section, then this is the + // offset from the start of the PLT section. This is -1U if there + // is no PLT entry. unsigned int plt_offset_; // Symbol type (bits 0 to 3). @@ -833,10 +902,7 @@ class Symbol unsigned int nonvis_ : 6; // The type of symbol (bits 16 to 18). Source source_ : 3; - // True if this symbol always requires special target-specific - // handling (bit 19). - bool is_target_special_ : 1; - // True if this is the default version of the symbol (bit 20). + // True if this is the default version of the symbol (bit 19). bool is_def_ : 1; // True if this symbol really forwards to another symbol. This is // used when we discover after the fact that two different entries @@ -844,35 +910,38 @@ class Symbol // never be set for a symbol found in the hash table, but may be set // for a symbol found in the list of symbols attached to an Object. // It forwards to the symbol found in the forwarders_ map of - // Symbol_table (bit 21). + // Symbol_table (bit 20). bool is_forwarder_ : 1; // True if the symbol has an alias in the weak_aliases table in - // Symbol_table (bit 22). + // Symbol_table (bit 21). bool has_alias_ : 1; // True if this symbol needs to be in the dynamic symbol table (bit - // 23). + // 22). bool needs_dynsym_entry_ : 1; - // True if we've seen this symbol in a regular object (bit 24). + // True if we've seen this symbol in a regular object (bit 23). bool in_reg_ : 1; - // True if we've seen this symbol in a dynamic object (bit 25). + // True if we've seen this symbol in a dynamic object (bit 24). bool in_dyn_ : 1; - // True if the symbol has an entry in the PLT section (bit 26). - bool has_plt_offset_ : 1; // True if this is a dynamic symbol which needs a special value in - // the dynamic symbol table (bit 27). + // the dynamic symbol table (bit 25). bool needs_dynsym_value_ : 1; - // True if there is a warning for this symbol (bit 28). + // True if there is a warning for this symbol (bit 26). bool has_warning_ : 1; // True if we are using a COPY reloc for this symbol, so that the - // real definition lives in a dynamic object (bit 29). + // real definition lives in a dynamic object (bit 27). bool is_copied_from_dynobj_ : 1; // True if this symbol was forced to local visibility by a version - // script (bit 30). + // script (bit 28). bool is_forced_local_ : 1; // True if the field u_.from_object.shndx is an ordinary section // index, not one of the special codes from SHN_LORESERVE to - // SHN_HIRESERVE. + // SHN_HIRESERVE (bit 29). bool is_ordinary_shndx_ : 1; + // True if we've seen this symbol in a real ELF object (bit 30). + bool in_real_elf_ : 1; + // True if this symbol is defined in a section which was discarded + // (bit 31). + bool is_defined_in_discarded_section_ : 1; }; // The parts of a symbol which are size specific. Using a template @@ -1117,6 +1186,31 @@ class Warnings class Symbol_table { public: + // The different places where a symbol definition can come from. + enum Defined + { + // Defined in an object file--the normal case. + OBJECT, + // Defined for a COPY reloc. + COPY, + // Defined on the command line using --defsym. + DEFSYM, + // Defined (so to speak) on the command line using -u. + UNDEFINED, + // Defined in a linker script. + SCRIPT, + // Predefined by the linker. + PREDEFINED, + }; + + // The order in which we sort common symbols. + enum Sort_commons_order + { + SORT_COMMONS_BY_SIZE_DESCENDING, + SORT_COMMONS_BY_ALIGNMENT_DESCENDING, + SORT_COMMONS_BY_ALIGNMENT_ASCENDING + }; + // COUNT is an estimate of how many symbosl will be inserted in the // symbol table. It's ok to put 0 if you don't know; a correct // guess will just save some CPU by reducing hashtable resizes. @@ -1124,6 +1218,40 @@ class Symbol_table ~Symbol_table(); + void + set_icf(Icf* icf) + { this->icf_ = icf;} + + Icf* + icf() const + { return this->icf_; } + + // Returns true if ICF determined that this is a duplicate section. + bool + is_section_folded(Object* obj, unsigned int shndx) const; + + void + set_gc(Garbage_collection* gc) + { this->gc_ = gc; } + + Garbage_collection* + gc() const + { return this->gc_; } + + // During garbage collection, this keeps undefined symbols. + void + gc_mark_undef_symbols(); + + // During garbage collection, this ensures externally visible symbols + // are not treated as garbage while building shared objects. + void + gc_mark_symbol_for_shlib(Symbol* sym); + + // During garbage collection, this keeps sections that correspond to + // symbols seen in dynamic objects. + inline void + gc_mark_dyn_syms(Symbol* sym); + // Add COUNT external symbols from the relocatable object RELOBJ to // the symbol table. SYMS is the symbols, SYMNDX_OFFSET is the // offset in the symbol table of the first symbol, SYM_NAMES is @@ -1139,6 +1267,14 @@ class Symbol_table typename Sized_relobj<size, big_endian>::Symbols*, size_t* defined); + // Add one external symbol from the plugin object OBJ to the symbol table. + // Returns a pointer to the resolved symbol in the symbol table. + template<int size, bool big_endian> + Symbol* + add_from_pluginobj(Sized_pluginobj<size, big_endian>* obj, + const char* name, const char* ver, + elfcpp::Sym<size, big_endian>* sym); + // Add COUNT dynamic symbols from the dynamic object DYNOBJ to the // symbol table. SYMS is the symbols. SYM_NAMES is their names. // SYM_NAME_SIZE is the size of SYM_NAMES. The other parameters are @@ -1156,7 +1292,7 @@ class Symbol_table // Define a special symbol based on an Output_data. It is a // multiple definition error if this symbol is already defined. Symbol* - define_in_output_data(const char* name, const char* version, + define_in_output_data(const char* name, const char* version, Defined, Output_data*, uint64_t value, uint64_t symsize, elfcpp::STT type, elfcpp::STB binding, elfcpp::STV visibility, unsigned char nonvis, @@ -1165,7 +1301,7 @@ class Symbol_table // Define a special symbol based on an Output_segment. It is a // multiple definition error if this symbol is already defined. Symbol* - define_in_output_segment(const char* name, const char* version, + define_in_output_segment(const char* name, const char* version, Defined, Output_segment*, uint64_t value, uint64_t symsize, elfcpp::STT type, elfcpp::STB binding, elfcpp::STV visibility, unsigned char nonvis, @@ -1174,7 +1310,7 @@ class Symbol_table // Define a special symbol with a constant value. It is a multiple // definition error if this symbol is already defined. Symbol* - define_as_constant(const char* name, const char* version, + define_as_constant(const char* name, const char* version, Defined, uint64_t value, uint64_t symsize, elfcpp::STT type, elfcpp::STB binding, elfcpp::STV visibility, unsigned char nonvis, bool only_if_ref, @@ -1218,7 +1354,7 @@ class Symbol_table get_sized_symbol(const Symbol*) const; // Return the count of undefined symbols seen. - int + size_t saw_undefined() const { return this->saw_undefined_; } @@ -1283,9 +1419,29 @@ class Symbol_table finalize(off_t off, off_t dynoff, size_t dyn_global_index, size_t dyncount, Stringpool* pool, unsigned int *plocal_symcount); + // Status code of Symbol_table::compute_final_value. + enum Compute_final_value_status + { + // No error. + CFVS_OK, + // Unspported symbol section. + CFVS_UNSUPPORTED_SYMBOL_SECTION, + // No output section. + CFVS_NO_OUTPUT_SECTION + }; + + // Compute the final value of SYM and store status in location PSTATUS. + // During relaxation, this may be called multiple times for a symbol to + // compute its would-be final value in each relaxation pass. + + template<int size> + typename Sized_symbol<size>::Value_type + compute_final_value(const Sized_symbol<size>* sym, + Compute_final_value_status* pstatus) const; + // Write out the global symbols. void - write_globals(const Input_objects*, const Stringpool*, const Stringpool*, + write_globals(const Stringpool*, const Stringpool*, Output_symtab_xindex*, Output_symtab_xindex*, Output_file*) const; @@ -1310,6 +1466,25 @@ class Symbol_table // The type of the list of common symbols. typedef std::vector<Symbol*> Commons_type; + // The type of the symbol hash table. + + typedef std::pair<Stringpool::Key, Stringpool::Key> Symbol_table_key; + + struct Symbol_table_hash + { + size_t + operator()(const Symbol_table_key&) const; + }; + + struct Symbol_table_eq + { + bool + operator()(const Symbol_table_key&, const Symbol_table_key&) const; + }; + + typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, + Symbol_table_eq> Symbol_table_type; + // Make FROM a forwarder symbol to TO. void make_forwarder(Symbol* from, Symbol* to); @@ -1323,6 +1498,12 @@ class Symbol_table unsigned int st_shndx, bool is_ordinary, unsigned int orig_st_shndx); + // Define a default symbol. + template<int size, bool big_endian> + void + define_default_version(Sized_symbol<size>*, bool, + Symbol_table_type::iterator); + // Resolve symbols. template<int size, bool big_endian> void @@ -1336,18 +1517,24 @@ class Symbol_table void resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from); - // Record that a symbol is forced to be local by a version script. + // Record that a symbol is forced to be local by a version script or + // by visibility. void force_local(Symbol*); // Adjust NAME and *NAME_KEY for wrapping. const char* - wrap_symbol(Object* object, const char*, Stringpool::Key* name_key); + wrap_symbol(const char* name, Stringpool::Key* name_key); // Whether we should override a symbol, based on flags in // resolve.cc. static bool - should_override(const Symbol*, unsigned int, Object*, bool*); + should_override(const Symbol*, unsigned int, Defined, Object*, bool*); + + // Report a problem in symbol resolution. + static void + report_resolve_problem(bool is_error, const char* msg, const Symbol* to, + Defined, Object* object); // Override a symbol. template<int size, bool big_endian> @@ -1360,7 +1547,7 @@ class Symbol_table // Whether we should override a symbol with a special symbol which // is automatically defined by the linker. static bool - should_override_with_special(const Symbol*); + should_override_with_special(const Symbol*, Defined); // Override a symbol with a special symbol. template<int size> @@ -1377,12 +1564,14 @@ class Symbol_table template<int size, bool big_endian> Sized_symbol<size>* define_special_symbol(const char** pname, const char** pversion, - bool only_if_ref, Sized_symbol<size>** poldsym); + bool only_if_ref, Sized_symbol<size>** poldsym, + bool* resolve_oldsym); // Define a symbol in an Output_data, sized version. template<int size> Sized_symbol<size>* - do_define_in_output_data(const char* name, const char* version, Output_data*, + do_define_in_output_data(const char* name, const char* version, Defined, + Output_data*, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword ssize, elfcpp::STT type, elfcpp::STB binding, @@ -1393,7 +1582,7 @@ class Symbol_table template<int size> Sized_symbol<size>* do_define_in_output_segment( - const char* name, const char* version, Output_segment* os, + const char* name, const char* version, Defined, Output_segment* os, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword ssize, elfcpp::STT type, elfcpp::STB binding, @@ -1404,7 +1593,7 @@ class Symbol_table template<int size> Sized_symbol<size>* do_define_as_constant( - const char* name, const char* version, + const char* name, const char* version, Defined, typename elfcpp::Elf_types<size>::Elf_Addr value, typename elfcpp::Elf_types<size>::Elf_WXword ssize, elfcpp::STT type, elfcpp::STB binding, @@ -1417,15 +1606,26 @@ class Symbol_table void do_add_undefined_symbols_from_command_line(); + // Types of common symbols. + + enum Commons_section_type + { + COMMONS_NORMAL, + COMMONS_TLS, + COMMONS_SMALL, + COMMONS_LARGE + }; + // Allocate the common symbols, sized version. template<int size> void - do_allocate_commons(Layout*, Mapfile*); + do_allocate_commons(Layout*, Mapfile*, Sort_commons_order); // Allocate the common symbols from one list. template<int size> void - do_allocate_commons_list(Layout*, bool is_tls, Commons_type*, Mapfile*); + do_allocate_commons_list(Layout*, Commons_section_type, Commons_type*, + Mapfile*, Sort_commons_order); // Implement detect_odr_violations. template<int size, bool big_endian> @@ -1451,9 +1651,9 @@ class Symbol_table // Write globals specialized for size and endianness. template<int size, bool big_endian> void - sized_write_globals(const Input_objects*, const Stringpool*, - const Stringpool*, Output_symtab_xindex*, - Output_symtab_xindex*, Output_file*) const; + sized_write_globals(const Stringpool*, const Stringpool*, + Output_symtab_xindex*, Output_symtab_xindex*, + Output_file*) const; // Write out a symbol to P. template<int size, bool big_endian> @@ -1465,7 +1665,7 @@ class Symbol_table // Possibly warn about an undefined symbol from a dynamic object. void - warn_about_undefined_dynobj_symbol(const Input_objects*, Symbol*) const; + warn_about_undefined_dynobj_symbol(Symbol*) const; // Write out a section symbol, specialized for size and endianness. template<int size, bool big_endian> @@ -1473,25 +1673,6 @@ class Symbol_table sized_write_section_symbol(const Output_section*, Output_symtab_xindex*, Output_file*, off_t) const; - // The type of the symbol hash table. - - typedef std::pair<Stringpool::Key, Stringpool::Key> Symbol_table_key; - - struct Symbol_table_hash - { - size_t - operator()(const Symbol_table_key&) const; - }; - - struct Symbol_table_eq - { - bool - operator()(const Symbol_table_key&, const Symbol_table_key&) const; - }; - - typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, - Symbol_table_eq> Symbol_table_type; - // The type of the list of symbols which have been forced local. typedef std::vector<Symbol*> Forced_locals; @@ -1528,7 +1709,7 @@ class Symbol_table // We increment this every time we see a new undefined symbol, for // use in archive groups. - int saw_undefined_; + size_t saw_undefined_; // The index of the first global symbol in the output file. unsigned int first_global_index_; // The file offset within the output symtab section where we should @@ -1561,6 +1742,10 @@ class Symbol_table // This is like the commons_ field, except that it holds TLS common // symbols. Commons_type tls_commons_; + // This is for small common symbols. + Commons_type small_commons_; + // This is for large common symbols. + Commons_type large_commons_; // A list of symbols which have been forced to be local. We don't // expect there to be very many of them, so we keep a list of them // rather than walking the whole table to find them. @@ -1578,6 +1763,8 @@ class Symbol_table Copied_symbol_dynobjs copied_symbol_dynobjs_; // Information parsed from the version script, if any. const Version_script_info& version_script_; + Garbage_collection* gc_; + Icf* icf_; }; // We inline get_sized_symbol for efficiency. diff --git a/binutils-2.19/gold/target-reloc.h b/binutils-2.19/gold/target-reloc.h index 6683ddd..510eea0 100644 --- a/binutils-2.19/gold/target-reloc.h +++ b/binutils-2.19/gold/target-reloc.h @@ -1,6 +1,6 @@ // target-reloc.h -- target specific relocation support -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -25,6 +25,7 @@ #include "elfcpp.h" #include "symtab.h" +#include "object.h" #include "reloc.h" #include "reloc-types.h" @@ -42,7 +43,6 @@ template<int size, bool big_endian, typename Target_type, int sh_type, typename Scan> inline void scan_relocs( - const General_options& options, Symbol_table* symtab, Layout* layout, Target_type* target, @@ -103,7 +103,7 @@ scan_relocs( continue; } - scan.local(options, symtab, layout, target, object, data_shndx, + scan.local(symtab, layout, target, object, data_shndx, output_section, reloc, r_type, lsym); } else @@ -113,7 +113,7 @@ scan_relocs( if (gsym->is_forwarder()) gsym = symtab->resolve_forwards(gsym); - scan.global(options, symtab, layout, target, object, data_shndx, + scan.global(symtab, layout, target, object, data_shndx, output_section, reloc, r_type, gsym); } } @@ -144,6 +144,31 @@ get_comdat_behavior(const char* name) return CB_WARNING; } +// Give an error for a symbol with non-default visibility which is not +// defined locally. + +inline void +visibility_error(const Symbol* sym) +{ + const char* v; + switch (sym->visibility()) + { + case elfcpp::STV_INTERNAL: + v = _("internal"); + break; + case elfcpp::STV_HIDDEN: + v = _("hidden"); + break; + case elfcpp::STV_PROTECTED: + v = _("protected"); + break; + default: + gold_unreachable(); + } + gold_error(_("%s symbol '%s' is not defined locally"), + v, sym->name()); +} + // This function implements the generic part of relocation processing. // The template parameter Relocate must be a class type which provides // a single function, relocate(), which implements the machine @@ -163,6 +188,12 @@ get_comdat_behavior(const char* name) // NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to // the output section. +// RELOC_SYMBOL_CHANGES is used for -fsplit-stack support. If it is +// not NULL, it is a vector indexed by relocation index. If that +// entry is not NULL, it points to a global symbol which used as the +// symbol for the relocation, ignoring the symbol index in the +// relocation. + template<int size, bool big_endian, typename Target_type, int sh_type, typename Relocate> inline void @@ -175,7 +206,8 @@ relocate_section( bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr view_address, - section_size_type view_size) + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) { typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype; const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; @@ -210,7 +242,11 @@ relocate_section( Symbol_value<size> symval; const Symbol_value<size> *psymval; - if (r_sym < local_count) + bool is_defined_in_discarded_section; + unsigned int shndx; + if (r_sym < local_count + && (reloc_symbol_changes == NULL + || (*reloc_symbol_changes)[i] == NULL)) { sym = NULL; psymval = object->local_symbol(r_sym); @@ -218,58 +254,82 @@ relocate_section( // If the local symbol belongs to a section we are discarding, // and that section is a debug section, try to find the // corresponding kept section and map this symbol to its - // counterpart in the kept section. + // counterpart in the kept section. The symbol must not + // correspond to a section we are folding. bool is_ordinary; - unsigned int shndx = psymval->input_shndx(&is_ordinary); - if (is_ordinary - && shndx != elfcpp::SHN_UNDEF - && !object->is_section_included(shndx)) - { - if (comdat_behavior == CB_UNDETERMINED) - { - std::string name = object->section_name(relinfo->data_shndx); - comdat_behavior = get_comdat_behavior(name.c_str()); - } - if (comdat_behavior == CB_PRETEND) - { - bool found; - typename elfcpp::Elf_types<size>::Elf_Addr value = - object->map_to_kept_section(shndx, &found); - if (found) - symval.set_output_value(value + psymval->input_value()); - else - symval.set_output_value(0); - } - else - { - if (comdat_behavior == CB_WARNING) - gold_warning_at_location(relinfo, i, offset, - _("Relocation refers to discarded " - "comdat section")); - symval.set_output_value(0); - } - symval.set_no_output_symtab_entry(); - psymval = &symval; - } + shndx = psymval->input_shndx(&is_ordinary); + is_defined_in_discarded_section = + (is_ordinary + && shndx != elfcpp::SHN_UNDEF + && !object->is_section_included(shndx) + && !relinfo->symtab->is_section_folded(object, shndx)); } else { - const Symbol* gsym = object->global_symbol(r_sym); - gold_assert(gsym != NULL); - if (gsym->is_forwarder()) - gsym = relinfo->symtab->resolve_forwards(gsym); + const Symbol* gsym; + if (reloc_symbol_changes != NULL + && (*reloc_symbol_changes)[i] != NULL) + gsym = (*reloc_symbol_changes)[i]; + else + { + gsym = object->global_symbol(r_sym); + gold_assert(gsym != NULL); + if (gsym->is_forwarder()) + gsym = relinfo->symtab->resolve_forwards(gsym); + } sym = static_cast<const Sized_symbol<size>*>(gsym); - if (sym->has_symtab_index()) + if (sym->has_symtab_index() && sym->symtab_index() != -1U) symval.set_output_symtab_index(sym->symtab_index()); else symval.set_no_output_symtab_entry(); symval.set_output_value(sym->value()); psymval = &symval; + + is_defined_in_discarded_section = + (gsym->is_defined_in_discarded_section() + && gsym->is_undefined()); + shndx = 0; + } + + Symbol_value<size> symval2; + if (is_defined_in_discarded_section) + { + if (comdat_behavior == CB_UNDETERMINED) + { + std::string name = object->section_name(relinfo->data_shndx); + comdat_behavior = get_comdat_behavior(name.c_str()); + } + if (comdat_behavior == CB_PRETEND) + { + // FIXME: This case does not work for global symbols. + // We have no place to store the original section index. + // Fortunately this does not matter for comdat sections, + // only for sections explicitly discarded by a linker + // script. + bool found; + typename elfcpp::Elf_types<size>::Elf_Addr value = + object->map_to_kept_section(shndx, &found); + if (found) + symval2.set_output_value(value + psymval->input_value()); + else + symval2.set_output_value(0); + } + else + { + if (comdat_behavior == CB_WARNING) + gold_warning_at_location(relinfo, i, offset, + _("relocation refers to discarded " + "section")); + symval2.set_output_value(0); + } + symval2.set_no_output_symtab_entry(); + psymval = &symval2; } - if (!relocate.relocate(relinfo, target, i, reloc, r_type, sym, psymval, - view + offset, view_address + offset, view_size)) + if (!relocate.relocate(relinfo, target, output_section, i, reloc, + r_type, sym, psymval, view + offset, + view_address + offset, view_size)) continue; if (offset < 0 || static_cast<section_size_type>(offset) >= view_size) @@ -283,9 +343,15 @@ relocate_section( if (sym != NULL && sym->is_undefined() && sym->binding() != elfcpp::STB_WEAK + && !is_defined_in_discarded_section + && !target->is_defined_by_abi(sym) && (!parameters->options().shared() // -shared || parameters->options().defs())) // -z defs - gold_undefined_symbol(sym, relinfo, i, offset); + gold_undefined_symbol_at_location(sym, relinfo, i, offset); + else if (sym != NULL + && sym->visibility() != elfcpp::STV_DEFAULT + && (sym->is_undefined() || sym->is_from_dynobj())) + visibility_error(sym); if (sym != NULL && sym->has_warning()) relinfo->symtab->issue_warning(sym, relinfo, i, offset); @@ -307,8 +373,14 @@ class Default_scan_relocatable_relocs // Return the strategy to use for a local symbol which is not a // section symbol, given the relocation type. inline Relocatable_relocs::Reloc_strategy - local_non_section_strategy(unsigned int, Relobj*) - { return Relocatable_relocs::RELOC_COPY; } + local_non_section_strategy(unsigned int r_type, Relobj*, unsigned int r_sym) + { + // We assume that relocation type 0 is NONE. Targets which are + // different must override. + if (r_type == 0 && r_sym == 0) + return Relocatable_relocs::RELOC_DISCARD; + return Relocatable_relocs::RELOC_COPY; + } // Return the strategy to use for a local symbol which is a section // symbol, given the relocation type. @@ -357,7 +429,6 @@ template<int size, bool big_endian, int sh_type, typename Scan_relocatable_reloc> void scan_relocatable_relocs( - const General_options&, Symbol_table*, Layout*, Sized_relobj<size, big_endian>* object, @@ -412,13 +483,17 @@ scan_relocatable_relocs( strategy = Relocatable_relocs::RELOC_DISCARD; } else if (lsym.get_st_type() != elfcpp::STT_SECTION) - strategy = scan.local_non_section_strategy(r_type, object); + strategy = scan.local_non_section_strategy(r_type, object, + r_sym); else { strategy = scan.local_section_strategy(r_type, object); if (strategy != Relocatable_relocs::RELOC_DISCARD) object->output_section(shndx)->set_needs_symtab_index(); } + + if (strategy == Relocatable_relocs::RELOC_COPY) + object->set_must_have_output_symtab_entry(r_sym); } } @@ -449,6 +524,7 @@ relocate_for_relocatable( typedef typename Reloc_types<sh_type, size, big_endian>::Reloc_write Reltype_write; const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size; + const Address invalid_address = static_cast<Address>(0) - 1; Sized_relobj<size, big_endian>* const object = relinfo->object; const unsigned int local_count = object->local_symbol_count(); @@ -476,8 +552,13 @@ relocate_for_relocatable( switch (strategy) { case Relocatable_relocs::RELOC_COPY: - new_symndx = object->symtab_index(r_sym); - gold_assert(new_symndx != -1U); + if (r_sym == 0) + new_symndx = 0; + else + { + new_symndx = object->symtab_index(r_sym); + gold_assert(new_symndx != -1U); + } break; case Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA: @@ -523,7 +604,7 @@ relocate_for_relocatable( Address offset = reloc.get_r_offset(); Address new_offset; - if (offset_in_output_section != -1U) + if (offset_in_output_section != invalid_address) new_offset = offset + offset_in_output_section; else { @@ -542,7 +623,7 @@ relocate_for_relocatable( if (!parameters->options().relocatable()) { new_offset += view_address; - if (offset_in_output_section != -1U) + if (offset_in_output_section != invalid_address) new_offset -= offset_in_output_section; } diff --git a/binutils-2.19/gold/target-select.cc b/binutils-2.19/gold/target-select.cc index b81f5a2..859bc3b 100644 --- a/binutils-2.19/gold/target-select.cc +++ b/binutils-2.19/gold/target-select.cc @@ -1,6 +1,6 @@ // target-select.cc -- select a target for an object file -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -39,6 +39,14 @@ gold::Target_selector* target_selectors; namespace gold { +// Class Set_target_once. + +void +Set_target_once::do_run_once(void*) +{ + this->target_selector_->set_target(); +} + // Construct a Target_selector, which means adding it to the linked // list. This runs at global constructor time, so we want it to be // fast. @@ -46,13 +54,31 @@ namespace gold Target_selector::Target_selector(int machine, int size, bool is_big_endian, const char* bfd_name) : machine_(machine), size_(size), is_big_endian_(is_big_endian), - bfd_name_(bfd_name), instantiated_target_(NULL) - + bfd_name_(bfd_name), instantiated_target_(NULL), set_target_once_(this) { this->next_ = target_selectors; target_selectors = this; } +// Instantiate the target and return it. Use SET_TARGET_ONCE_ to +// avoid instantiating two instances of the same target. + +Target* +Target_selector::instantiate_target() +{ + this->set_target_once_.run_once(NULL); + return this->instantiated_target_; +} + +// Instantiate the target. This is called at most once. + +void +Target_selector::set_target() +{ + gold_assert(this->instantiated_target_ == NULL); + this->instantiated_target_ = this->do_instantiate_target(); +} + // Find the target for an ELF file. Target* diff --git a/binutils-2.19/gold/target-select.h b/binutils-2.19/gold/target-select.h index 0582e25..4e2ea92 100644 --- a/binutils-2.19/gold/target-select.h +++ b/binutils-2.19/gold/target-select.h @@ -1,6 +1,6 @@ // target-select.h -- select a target for an object file -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -25,10 +25,30 @@ #include <vector> +#include "gold-threads.h" + namespace gold { class Target; +class Target_selector; + +// Used to set the target only once. + +class Set_target_once : public Once +{ + public: + Set_target_once(Target_selector* target_selector) + : target_selector_(target_selector) + { } + + protected: + void + do_run_once(void*); + + private: + Target_selector* target_selector_; +}; // We want to avoid a master list of targets, which implies using a // global constructor. And we also want the program to start up as @@ -106,10 +126,10 @@ class Target_selector virtual Target* do_instantiate_target() = 0; - // Recognize an object file given a machine code, size, and - // endianness. When this is called we already know that they match - // the machine_, size_, and is_big_endian_ fields. The child class - // may implement a different version of this to do additional + // Recognize an object file given a machine code, OSABI code, and + // ELF version value. When this is called we already know that they + // match the machine_, size_, and is_big_endian_ fields. The child + // class may implement a different version of this to do additional // checks, or to check for multiple machine codes if the machine_ // field is EM_NONE. virtual Target* @@ -134,15 +154,16 @@ class Target_selector names->push_back(this->bfd_name_); } - private: // Instantiate the target and return it. Target* - instantiate_target() - { - if (this->instantiated_target_ == NULL) - this->instantiated_target_ = this->do_instantiate_target(); - return this->instantiated_target_; - } + instantiate_target(); + + private: + // Set the target. + void + set_target(); + + friend class Set_target_once; // ELF machine code. const int machine_; @@ -157,6 +178,8 @@ class Target_selector // The singleton Target structure--this points to an instance of the // real implementation. Target* instantiated_target_; + // Used to set the target only once. + Set_target_once set_target_once_; }; // Select the target for an ELF file. diff --git a/binutils-2.19/gold/target.cc b/binutils-2.19/gold/target.cc new file mode 100644 index 0000000..0ddc13d --- /dev/null +++ b/binutils-2.19/gold/target.cc @@ -0,0 +1,193 @@ +// target.cc + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" +#include "target.h" +#include "dynobj.h" +#include "output.h" +#include "elfcpp.h" + +namespace gold +{ + +// Return whether NAME is a local label name. This is used to implement the +// --discard-locals options and can be overriden by children classes to +// implement system-specific behaviour. The logic here is the same as that +// in _bfd_elf_is_local_label_name(). + +bool +Target::do_is_local_label_name (const char* name) const +{ + // Normal local symbols start with ``.L''. + if (name[0] == '.' && name[1] == 'L') + return true; + + // At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate + // DWARF debugging symbols starting with ``..''. + if (name[0] == '.' && name[1] == '.') + return true; + + // gcc will sometimes generate symbols beginning with ``_.L_'' when + // emitting DWARF debugging output. I suspect this is actually a + // small bug in gcc (it calls ASM_OUTPUT_LABEL when it should call + // ASM_GENERATE_INTERNAL_LABEL, and this causes the leading + // underscore to be emitted on some ELF targets). For ease of use, + // we treat such symbols as local. + if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_') + return true; + + return false; +} + +// Implementations of methods Target::do_make_elf_object are almost identical +// except for the address sizes and endianities. So we extract this +// into a template. + +template<int size, bool big_endian> +inline Object* +Target::do_make_elf_object_implementation( + const std::string& name, + Input_file* input_file, + off_t offset, + const elfcpp::Ehdr<size, big_endian>& ehdr) +{ + int et = ehdr.get_e_type(); + if (et == elfcpp::ET_REL) + { + Sized_relobj<size, big_endian>* obj = + new Sized_relobj<size, big_endian>(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else if (et == elfcpp::ET_DYN) + { + Sized_dynobj<size, big_endian>* obj = + new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr); + obj->setup(); + return obj; + } + else + { + gold_error(_("%s: unsupported ELF file type %d"), + name.c_str(), et); + return NULL; + } +} + +// Make an ELF object called NAME by reading INPUT_FILE at OFFSET. EHDR +// is the ELF header of the object. There are four versions of this +// for different address sizes and endianities. + +#ifdef HAVE_TARGET_32_LITTLE +Object* +Target::do_make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<32, false>& ehdr) +{ + return this->do_make_elf_object_implementation<32, false>(name, input_file, + offset, ehdr); +} +#endif + +#ifdef HAVE_TARGET_32_BIG +Object* +Target::do_make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<32, true>& ehdr) +{ + return this->do_make_elf_object_implementation<32, true>(name, input_file, + offset, ehdr); +} +#endif + +#ifdef HAVE_TARGET_64_LITTLE +Object* +Target::do_make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<64, false>& ehdr) +{ + return this->do_make_elf_object_implementation<64, false>(name, input_file, + offset, ehdr); +} +#endif + +#ifdef HAVE_TARGET_64_BIG +Object* +Target::do_make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<64, true>& ehdr) +{ + return this->do_make_elf_object_implementation<64, true>(name, input_file, + offset, ehdr); +} +#endif + +Output_section* +Target::do_make_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags) +{ + return new Output_section(name, type, flags); +} + +// Default conversion for -fsplit-stack is to give an error. + +void +Target::do_calls_non_split(Relobj* object, unsigned int, section_offset_type, + section_size_type, unsigned char*, section_size_type, + std::string*, std::string*) const +{ + static bool warned; + if (!warned) + { + gold_error(_("linker does not include stack split support " + "required by %s"), + object->name().c_str()); + warned = true; + } +} + +// Return whether BYTES/LEN matches VIEW/VIEW_SIZE at OFFSET. + +bool +Target::match_view(const unsigned char* view, section_size_type view_size, + section_offset_type offset, const char* bytes, + size_t len) const +{ + if (offset + len > view_size) + return false; + return memcmp(view + offset, bytes, len) == 0; +} + +// Set the contents of a VIEW/VIEW_SIZE to nops starting at OFFSET +// for LEN bytes. + +void +Target::set_view_to_nop(unsigned char* view, section_size_type view_size, + section_offset_type offset, size_t len) const +{ + gold_assert(offset >= 0 && offset + len <= view_size); + if (!this->has_code_fill()) + memset(view + offset, 0, len); + else + { + std::string fill = this->code_fill(len); + memcpy(view + offset, fill.data(), len); + } +} + +} // End namespace gold. diff --git a/binutils-2.19/gold/target.h b/binutils-2.19/gold/target.h index 30fa008..7429b63 100644 --- a/binutils-2.19/gold/target.h +++ b/binutils-2.19/gold/target.h @@ -1,6 +1,6 @@ // target.h -- target support for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -36,22 +36,25 @@ #include "elfcpp.h" #include "options.h" #include "parameters.h" +#include "debug.h" namespace gold { -class General_options; class Object; +class Relobj; template<int size, bool big_endian> class Sized_relobj; class Relocatable_relocs; template<int size, bool big_endian> class Relocate_info; +class Reloc_symbol_changes; class Symbol; template<int size> class Sized_symbol; class Symbol_table; class Output_section; +class Input_objects; // The abstract class for target specific handling. @@ -61,6 +64,13 @@ class Target virtual ~Target() { } + // Virtual function which is set to return true by a target if + // it can use relocation types to determine if a function's + // pointer is taken. + virtual bool + can_check_for_function_pointers() const + { return false; } + // Return the bit size that this target implements. This should // return 32 or 64. int @@ -77,6 +87,16 @@ class Target machine_code() const { return this->pti_->machine_code; } + // Processor specific flags to store in e_flags field of ELF header. + elfcpp::Elf_Word + processor_specific_flags() const + { return this->processor_specific_flags_; } + + // Whether processor specific flags are set at least once. + bool + are_processor_specific_flags_set() const + { return this->are_processor_specific_flags_set_; } + // Whether this target has a specific make_symbol function. bool has_make_symbol() const @@ -141,11 +161,49 @@ class Target wrap_char() const { return this->pti_->wrap_char; } + // Return the special section index which indicates a small common + // symbol. This will return SHN_UNDEF if there are no small common + // symbols. + elfcpp::Elf_Half + small_common_shndx() const + { return this->pti_->small_common_shndx; } + + // Return values to add to the section flags for the section holding + // small common symbols. + elfcpp::Elf_Xword + small_common_section_flags() const + { + gold_assert(this->pti_->small_common_shndx != elfcpp::SHN_UNDEF); + return this->pti_->small_common_section_flags; + } + + // Return the special section index which indicates a large common + // symbol. This will return SHN_UNDEF if there are no large common + // symbols. + elfcpp::Elf_Half + large_common_shndx() const + { return this->pti_->large_common_shndx; } + + // Return values to add to the section flags for the section holding + // large common symbols. + elfcpp::Elf_Xword + large_common_section_flags() const + { + gold_assert(this->pti_->large_common_shndx != elfcpp::SHN_UNDEF); + return this->pti_->large_common_section_flags; + } + + // This hook is called when an output section is created. + void + new_output_section(Output_section* os) const + { this->do_new_output_section(os); } + // This is called to tell the target to complete any sections it is // handling. After this all sections must have their final size. void - finalize_sections(Layout* layout) - { return this->do_finalize_sections(layout); } + finalize_sections(Layout* layout, const Input_objects* input_objects, + Symbol_table* symtab) + { return this->do_finalize_sections(layout, input_objects, symtab); } // Return the value to use for a global symbol which needs a special // value in the dynamic symbol table. This will only be called if @@ -164,9 +222,122 @@ class Target // Return whether SYM is known to be defined by the ABI. This is // used to avoid inappropriate warnings about undefined symbols. bool - is_defined_by_abi(Symbol* sym) const + is_defined_by_abi(const Symbol* sym) const { return this->do_is_defined_by_abi(sym); } + // Adjust the output file header before it is written out. VIEW + // points to the header in external form. LEN is the length. + void + adjust_elf_header(unsigned char* view, int len) const + { return this->do_adjust_elf_header(view, len); } + + // Return whether NAME is a local label name. This is used to implement the + // --discard-locals options. + bool + is_local_label_name(const char* name) const + { return this->do_is_local_label_name(name); } + + // Get the symbol index to use for a target specific reloc. + unsigned int + reloc_symbol_index(void* arg, unsigned int type) const + { return this->do_reloc_symbol_index(arg, type); } + + // Get the addend to use for a target specific reloc. + uint64_t + reloc_addend(void* arg, unsigned int type, uint64_t addend) const + { return this->do_reloc_addend(arg, type, addend); } + + // A function starts at OFFSET in section SHNDX in OBJECT. That + // function was compiled with -fsplit-stack, but it refers to a + // function which was compiled without -fsplit-stack. VIEW is a + // modifiable view of the section; VIEW_SIZE is the size of the + // view. The target has to adjust the function so that it allocates + // enough stack. + void + calls_non_split(Relobj* object, unsigned int shndx, + section_offset_type fnoffset, section_size_type fnsize, + unsigned char* view, section_size_type view_size, + std::string* from, std::string* to) const + { + this->do_calls_non_split(object, shndx, fnoffset, fnsize, view, view_size, + from, to); + } + + // Make an ELF object. + template<int size, bool big_endian> + Object* + make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr) + { return this->do_make_elf_object(name, input_file, offset, ehdr); } + + // Make an output section. + Output_section* + make_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags) + { return this->do_make_output_section(name, type, flags); } + + // Return true if target wants to perform relaxation. + bool + may_relax() const + { + // Run the dummy relaxation pass twice if relaxation debugging is enabled. + if (is_debugging_enabled(DEBUG_RELAXATION)) + return true; + + return this->do_may_relax(); + } + + // Perform a relaxation pass. Return true if layout may be changed. + bool + relax(int pass, const Input_objects* input_objects, Symbol_table* symtab, + Layout* layout) + { + // Run the dummy relaxation pass twice if relaxation debugging is enabled. + if (is_debugging_enabled(DEBUG_RELAXATION)) + return pass < 2; + + return this->do_relax(pass, input_objects, symtab, layout); + } + + // Return the target-specific name of attributes section. This is + // NULL if a target does not use attributes section or if it uses + // the default section name ".gnu.attributes". + const char* + attributes_section() const + { return this->pti_->attributes_section; } + + // Return the vendor name of vendor attributes. + const char* + attributes_vendor() const + { return this->pti_->attributes_vendor; } + + // Whether a section called NAME is an attribute section. + bool + is_attributes_section(const char* name) const + { + return ((this->pti_->attributes_section != NULL + && strcmp(name, this->pti_->attributes_section) == 0) + || strcmp(name, ".gnu.attributes") == 0); + } + + // Return a bit mask of argument types for attribute with TAG. + int + attribute_arg_type(int tag) const + { return this->do_attribute_arg_type(tag); } + + // Return the attribute tag of the position NUM in the list of fixed + // attributes. Normally there is no reordering and + // attributes_order(NUM) == NUM. + int + attributes_order(int num) const + { return this->do_attributes_order(num); } + + // When a target is selected as the default target, we call this method, + // which may be used for expensive, target-specific initialization. + void + select_as_default_target() + { this->do_select_as_default_target(); } + protected: // This struct holds the constant information for a child class. We // use a struct to avoid the overhead of virtual function calls for @@ -198,15 +369,35 @@ class Target uint64_t abi_pagesize; // The common page size used by actual implementations. uint64_t common_pagesize; + // The special section index for small common symbols; SHN_UNDEF + // if none. + elfcpp::Elf_Half small_common_shndx; + // The special section index for large common symbols; SHN_UNDEF + // if none. + elfcpp::Elf_Half large_common_shndx; + // Section flags for small common section. + elfcpp::Elf_Xword small_common_section_flags; + // Section flags for large common section. + elfcpp::Elf_Xword large_common_section_flags; + // Name of attributes section if it is not ".gnu.attributes". + const char* attributes_section; + // Vendor name of vendor attributes. + const char* attributes_vendor; }; Target(const Target_info* pti) - : pti_(pti) + : pti_(pti), processor_specific_flags_(0), + are_processor_specific_flags_set_(false) { } // Virtual function which may be implemented by the child class. virtual void - do_finalize_sections(Layout*) + do_new_output_section(Output_section*) const + { } + + // Virtual function which may be implemented by the child class. + virtual void + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*) { } // Virtual function which may be implemented by the child class. @@ -222,15 +413,139 @@ class Target // Virtual function which may be implemented by the child class. virtual bool - do_is_defined_by_abi(Symbol*) const + do_is_defined_by_abi(const Symbol*) const + { return false; } + + // Adjust the output file header before it is written out. VIEW + // points to the header in external form. LEN is the length, and + // will be one of the values of elfcpp::Elf_sizes<size>::ehdr_size. + // By default, we do nothing. + virtual void + do_adjust_elf_header(unsigned char*, int) const + { } + + // Virtual function which may be overriden by the child class. + virtual bool + do_is_local_label_name(const char*) const; + + // Virtual function that must be overridden by a target which uses + // target specific relocations. + virtual unsigned int + do_reloc_symbol_index(void*, unsigned int) const + { gold_unreachable(); } + + // Virtual function that must be overidden by a target which uses + // target specific relocations. + virtual uint64_t + do_reloc_addend(void*, unsigned int, uint64_t) const + { gold_unreachable(); } + + // Virtual function which may be overridden by the child class. + virtual void + do_calls_non_split(Relobj* object, unsigned int, section_offset_type, + section_size_type, unsigned char*, section_size_type, + std::string*, std::string*) const; + + // make_elf_object hooks. There are four versions of these for + // different address sizes and endianness. + + // Set processor specific flags. + void + set_processor_specific_flags(elfcpp::Elf_Word flags) + { + this->processor_specific_flags_ = flags; + this->are_processor_specific_flags_set_ = true; + } + +#ifdef HAVE_TARGET_32_LITTLE + // Virtual functions which may be overriden by the child class. + virtual Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, false>&); +#endif + +#ifdef HAVE_TARGET_32_BIG + // Virtual functions which may be overriden by the child class. + virtual Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<32, true>&); +#endif + +#ifdef HAVE_TARGET_64_LITTLE + // Virtual functions which may be overriden by the child class. + virtual Object* + do_make_elf_object(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<64, false>& ehdr); +#endif + +#ifdef HAVE_TARGET_64_BIG + // Virtual functions which may be overriden by the child class. + virtual Object* + do_make_elf_object(const std::string& name, Input_file* input_file, + off_t offset, const elfcpp::Ehdr<64, true>& ehdr); +#endif + + // Virtual functions which may be overriden by the child class. + virtual Output_section* + do_make_output_section(const char* name, elfcpp::Elf_Word type, + elfcpp::Elf_Xword flags); + + // Virtual function which may be overriden by the child class. + virtual bool + do_may_relax() const + { return parameters->options().relax(); } + + // Virtual function which may be overriden by the child class. + virtual bool + do_relax(int, const Input_objects*, Symbol_table*, Layout*) { return false; } + // A function for targets to call. Return whether BYTES/LEN matches + // VIEW/VIEW_SIZE at OFFSET. + bool + match_view(const unsigned char* view, section_size_type view_size, + section_offset_type offset, const char* bytes, size_t len) const; + + // Set the contents of a VIEW/VIEW_SIZE to nops starting at OFFSET + // for LEN bytes. + void + set_view_to_nop(unsigned char* view, section_size_type view_size, + section_offset_type offset, size_t len) const; + + // This must be overriden by the child class if it has target-specific + // attributes subsection in the attribute section. + virtual int + do_attribute_arg_type(int) const + { gold_unreachable(); } + + // This may be overridden by the child class. + virtual int + do_attributes_order(int num) const + { return num; } + + // This may be overridden by the child class. + virtual void + do_select_as_default_target() + { } + private: + // The implementations of the four do_make_elf_object virtual functions are + // almost identical except for their sizes and endianness. We use a template. + // for their implementations. + template<int size, bool big_endian> + inline Object* + do_make_elf_object_implementation(const std::string&, Input_file*, off_t, + const elfcpp::Ehdr<size, big_endian>&); + Target(const Target&); Target& operator=(const Target&); // The target information. const Target_info* pti_; + // Processor-specific flags. + elfcpp::Elf_Word processor_specific_flags_; + // Whether the processor-specific flags are set at least once. + bool are_processor_specific_flags_set_; }; // The abstract class for a specific size and endianness of target. @@ -259,21 +574,37 @@ class Sized_target : public Target const char*) { gold_unreachable(); } + // Process the relocs for a section, and record information of the + // mapping from source to destination sections. This mapping is later + // used to determine unreferenced garbage sections. This procedure is + // only called during garbage collection. + virtual void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<size, big_endian>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) = 0; + // Scan the relocs for a section, and record any information - // required for the symbol. OPTIONS is the command line options. - // SYMTAB is the symbol table. OBJECT is the object in which the - // section appears. DATA_SHNDX is the section index that these - // relocs apply to. SH_TYPE is the type of the relocation section, - // SHT_REL or SHT_RELA. PRELOCS points to the relocation data. - // RELOC_COUNT is the number of relocs. LOCAL_SYMBOL_COUNT is the - // number of local symbols. OUTPUT_SECTION is the output section. + // required for the symbol. SYMTAB is the symbol table. OBJECT is + // the object in which the section appears. DATA_SHNDX is the + // section index that these relocs apply to. SH_TYPE is the type of + // the relocation section, SHT_REL or SHT_RELA. PRELOCS points to + // the relocation data. RELOC_COUNT is the number of relocs. + // LOCAL_SYMBOL_COUNT is the number of local symbols. + // OUTPUT_SECTION is the output section. // NEEDS_SPECIAL_OFFSET_HANDLING is true if offsets to the output // sections are not mapped as usual. PLOCAL_SYMBOLS points to the // local symbol data from OBJECT. GLOBAL_SYMBOLS is the array of // pointers to the global symbol table from OBJECT. virtual void - scan_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, @@ -305,14 +636,14 @@ class Sized_target : public Target bool needs_special_offset_handling, unsigned char* view, typename elfcpp::Elf_types<size>::Elf_Addr view_address, - section_size_type view_size) = 0; + section_size_type view_size, + const Reloc_symbol_changes*) = 0; // Scan the relocs during a relocatable link. The parameters are // like scan_relocs, with an additional Relocatable_relocs // parameter, used to record the disposition of the relocs. virtual void - scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<size, big_endian>* object, unsigned int data_shndx, diff --git a/binutils-2.19/gold/testsuite/Makefile.am b/binutils-2.19/gold/testsuite/Makefile.am index c9dd470..34abf89 100644 --- a/binutils-2.19/gold/testsuite/Makefile.am +++ b/binutils-2.19/gold/testsuite/Makefile.am @@ -4,14 +4,16 @@ # system and the host system are the same. So these tests will not # work when building with a cross-compiler. -AUTOMAKE_OPTIONS = +# Ignore warning about AM_PROG_CC_C_O due to large_CFLAGS +AUTOMAKE_OPTIONS = foreign -Wno-portability # The two_file_test tests -fmerge-constants, so we simply always turn # it on. This may need to be controlled by a configure option # eventually. +AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS) -fmerge-constants AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) -fmerge-constants -INCLUDES = \ +AM_CPPFLAGS = \ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \ -I$(srcdir)/../../elfcpp -I.. \ -DLOCALEDIR="\"$(datadir)/locale\"" \ @@ -21,6 +23,13 @@ TEST_READELF = $(top_builddir)/../binutils/readelf TEST_OBJDUMP = $(top_builddir)/../binutils/objdump TEST_CXXFILT = $(top_builddir)/../binutils/cxxfilt TEST_STRIP = $(top_builddir)/../binutils/strip-new +TEST_AR = $(top_builddir)/../binutils/ar +TEST_NM = $(top_builddir)/../binutils/nm-new +TEST_AS = $(top_builddir)/../gas/as-new + +if PLUGINS +LIBDL = -ldl +endif if THREADS THREADSLIB = -lpthread @@ -34,7 +43,7 @@ endif # .o's), but not all of them (such as .so's and .err files). We # improve on that here. automake-1.9 info docs say "mostlyclean" is # the right choice for files 'make' builds that people rebuild. -MOSTLYCLEANFILES = *.so +MOSTLYCLEANFILES = *.so *.syms *.stdout # We will add to these later, for each individual test. Note @@ -57,7 +66,7 @@ libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc DEPENDENCIES = \ libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADSLIB) + $(THREADSLIB) $(LIBDL) # The unittests themselves @@ -96,6 +105,93 @@ flagstest_debug.o: constructor_test.cc flagstest_ndebug.o: constructor_test.cc $(CXXCOMPILE) -O0 -c -o $@ $< +check_SCRIPTS += incremental_test.sh +check_DATA += incremental_test.stdout +MOSTLYCLEANFILES += incremental_test +incremental_test_1.o: incremental_test_1.c + $(COMPILE) -O0 -c -ffunction-sections -g -o $@ $< +incremental_test_2.o: incremental_test_2.c + $(COMPILE) -O0 -c -ffunction-sections -g -o $@ $< +incremental_test: incremental_test_1.o incremental_test_2.o gcctestdir/ld + $(LINK) -Bgcctestdir/ -Wl,-incremental incremental_test_1.o incremental_test_2.o -Wl,-debug 2> incremental_test.cmdline +incremental_test.stdout: incremental_test ../incremental-dump + ../incremental-dump incremental_test > $@ + +check_SCRIPTS += gc_comdat_test.sh +check_DATA += gc_comdat_test.stdout +MOSTLYCLEANFILES += gc_comdat_test +gc_comdat_test_1.o: gc_comdat_test_1.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +gc_comdat_test_2.o: gc_comdat_test_2.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +gc_comdat_test: gc_comdat_test_1.o gc_comdat_test_2.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_comdat_test_1.o gc_comdat_test_2.o +gc_comdat_test.stdout: gc_comdat_test + $(TEST_NM) -C gc_comdat_test > gc_comdat_test.stdout + +check_SCRIPTS += gc_tls_test.sh +check_DATA += gc_tls_test.stdout +MOSTLYCLEANFILES += gc_tls_test +gc_tls_test.o: gc_tls_test.cc + $(CXXCOMPILE) -O0 -c -g -o $@ $< +gc_tls_test:gc_tls_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_tls_test.o +gc_tls_test.stdout: gc_tls_test + $(TEST_NM) -C gc_tls_test > gc_tls_test.stdout + +check_SCRIPTS += gc_orphan_section_test.sh +check_DATA += gc_orphan_section_test.stdout +MOSTLYCLEANFILES += gc_orphan_section_test +gc_orphan_section_test.o: gc_orphan_section_test.cc + $(CXXCOMPILE) -O0 -c -g -o $@ $< +gc_orphan_section_test:gc_orphan_section_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_orphan_section_test.o +gc_orphan_section_test.stdout: gc_orphan_section_test + $(TEST_NM) gc_orphan_section_test > gc_orphan_section_test.stdout + +check_SCRIPTS += icf_test.sh +check_DATA += icf_test.stdout +MOSTLYCLEANFILES += icf_test +icf_test.o: icf_test.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +icf_test: icf_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_test.o +icf_test.stdout: icf_test + $(TEST_NM) -C icf_test > icf_test.stdout + +check_SCRIPTS += icf_keep_unique_test.sh +check_DATA += icf_keep_unique_test.stdout +MOSTLYCLEANFILES += icf_keep_unique_test +icf_keep_unique_test.o: icf_keep_unique_test.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +icf_keep_unique_test: icf_keep_unique_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o +icf_keep_unique_test.stdout: icf_keep_unique_test + $(TEST_NM) -C icf_keep_unique_test > icf_keep_unique_test.stdout + +check_SCRIPTS += icf_safe_test.sh +check_DATA += icf_safe_test_1.stdout icf_safe_test_2.stdout +MOSTLYCLEANFILES += icf_safe_test +icf_safe_test.o: icf_safe_test.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +icf_safe_test: icf_safe_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_test.o +icf_safe_test_1.stdout: icf_safe_test + $(TEST_NM) icf_safe_test > icf_safe_test_1.stdout +icf_safe_test_2.stdout: icf_safe_test + $(TEST_READELF) -h icf_safe_test > icf_safe_test_2.stdout + +check_SCRIPTS += icf_safe_so_test.sh +check_DATA += icf_safe_so_test_1.stdout icf_safe_so_test_2.stdout +MOSTLYCLEANFILES += icf_safe_so_test +icf_safe_so_test.o: icf_safe_so_test.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $< +icf_safe_so_test: icf_safe_so_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_so_test.o -fPIC -shared +icf_safe_so_test_1.stdout: icf_safe_so_test + $(TEST_NM) icf_safe_so_test > icf_safe_so_test_1.stdout +icf_safe_so_test_2.stdout: icf_safe_so_test + $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout check_PROGRAMS += basic_test check_PROGRAMS += basic_static_test @@ -115,16 +211,23 @@ basic_pic_test: basic_pic_test.o gcctestdir/ld basic_static_pic_test: basic_pic_test.o gcctestdir/ld $(CXXLINK) -Bgcctestdir/ -static basic_pic_test.o +check_PROGRAMS += basic_pie_test +basic_pie_test.o: basic_test.cc + $(CXXCOMPILE) -O0 -c -fpie -o $@ $< +basic_pie_test: basic_pie_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -pie basic_pie_test.o check_PROGRAMS += constructor_test check_PROGRAMS += constructor_static_test constructor_test_SOURCES = constructor_test.cc constructor_test_DEPENDENCIES = gcctestdir/ld constructor_test_LDFLAGS = -Bgcctestdir/ +constructor_test_LDADD = constructor_static_test_SOURCES = $(constructor_test_SOURCES) constructor_static_test_DEPENDENCIES = $(constructor_test_DEPENDENCIES) constructor_static_test_LDFLAGS = $(constructor_test_LDFLAGS) -static +constructor_static_test_LDADD = $(constructor_test_LDADD) check_PROGRAMS += two_file_test @@ -138,10 +241,12 @@ two_file_test_SOURCES = \ two_file_test.h two_file_test_DEPENDENCIES = gcctestdir/ld two_file_test_LDFLAGS = -Bgcctestdir/ +two_file_test_LDADD = two_file_static_test_SOURCES = $(two_file_test_SOURCES) two_file_static_test_DEPENDENCIES = $(two_file_test_DEPENDENCIES) two_file_static_test_LDFLAGS = $(two_file_test_LDFLAGS) -static +two_file_static_test_LDADD = $(two_file_test_LDADD) two_file_pic_test_SOURCES = two_file_test_main.cc two_file_pic_test_DEPENDENCIES = \ @@ -182,7 +287,7 @@ two_file_shared_2_test_LDADD = two_file_shared_2.so two_file_shared_1_pic_2_test_SOURCES = two_file_test_main.cc two_file_shared_1_pic_2_test_DEPENDENCIES = \ - gcctestdir/ld two_file_shared_1.so two_file_test_1_pic.o two_file_test_1b_pic.o + gcctestdir/ld two_file_shared_2.so two_file_test_1_pic.o two_file_test_1b_pic.o two_file_shared_1_pic_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. two_file_shared_1_pic_2_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_shared_2.so @@ -220,6 +325,25 @@ two_file_relocatable_test_LDADD = two_file_relocatable.o two_file_relocatable.o: gcctestdir/ld two_file_test_1.o two_file_test_1b.o two_file_test_2.o gcctestdir/ld -r -o $@ two_file_test_1.o two_file_test_1b.o two_file_test_2.o +check_PROGRAMS += two_file_pie_test +two_file_test_1_pie.o: two_file_test_1.cc + $(CXXCOMPILE) -c -fpie -o $@ $< +two_file_test_1b_pie.o: two_file_test_1b.cc + $(CXXCOMPILE) -c -fpie -o $@ $< +two_file_test_2_pie.o: two_file_test_2.cc + $(CXXCOMPILE) -c -fpie -o $@ $< +two_file_test_main_pie.o: two_file_test_main.cc + $(CXXCOMPILE) -c -fpie -o $@ $< +two_file_pie_test: two_file_test_1_pie.o two_file_test_1b_pie.o \ + two_file_test_2_pie.o two_file_test_main_pie.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -pie two_file_test_1_pie.o two_file_test_1b_pie.o two_file_test_2_pie.o two_file_test_main_pie.o + +check_SCRIPTS += two_file_shared.sh +check_DATA += two_file_shared.dbg +MOSTLYCLEANFILES += two_file_shared.dbg +two_file_shared.dbg: two_file_shared.so + $(TEST_READELF) -w $< >$@ 2>/dev/null + # The nonpic tests will fail on platforms which can not put non-PIC # code into shared libraries, so we just don't run them in that case. if FN_PTRS_IN_SO_WITHOUT_PIC @@ -305,6 +429,21 @@ check_PROGRAMS += common_test_1 common_test_1_SOURCES = common_test_1.c common_test_1_DEPENDENCIES = gcctestdir/ld common_test_1_LDFLAGS = -Bgcctestdir/ +common_test_1_LDADD = + +check_PROGRAMS += common_test_2 +common_test_2_SOURCES = common_test_1.c +common_test_2_DEPENDENCIES = common_test_2.so common_test_3.so gcctestdir/ld +common_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +common_test_2_LDADD = common_test_2.so common_test_3.so +common_test_2_pic.o: common_test_2.c + $(COMPILE) -c -fpic -o $@ $< +common_test_2.so: common_test_2_pic.o common_test_3.so gcctestdir/ld + $(LINK) -Bgcctestdir/ -shared common_test_2_pic.o common_test_3.so +common_test_3_pic.o: common_test_3.c + $(COMPILE) -c -fpic -o $@ $< +common_test_3.so: common_test_3_pic.o ver_test_2.script gcctestdir/ld + $(LINK) -Bgcctestdir/ -shared common_test_3_pic.o -Wl,--version-script,$(srcdir)/ver_test_2.script check_PROGRAMS += exception_test check_PROGRAMS += exception_static_test @@ -331,10 +470,12 @@ exception_test_SOURCES = \ exception_test.h exception_test_DEPENDENCIES = gcctestdir/ld exception_test_LDFLAGS = -Bgcctestdir/ +exception_test_LDADD = exception_static_test_SOURCES = $(exception_test_SOURCES) exception_static_test_DEPENDENCIES = $(exception_test_DEPENDENCIES) exception_static_test_LDFLAGS = $(exception_test_LDFLAGS) -static +exception_static_test_LDADD = $(exception_test_LDADD) exception_shared_1_test_SOURCES = exception_test_2.cc exception_test_main.cc exception_shared_1_test_DEPENDENCIES = gcctestdir/ld exception_shared_1.so @@ -370,8 +511,10 @@ check_PROGRAMS += weak_test weak_test_SOURCES = weak_test.cc weak_test_DEPENDENCIES = gcctestdir/ld weak_test_LDFLAGS = -Bgcctestdir/ +weak_test_LDADD = check_PROGRAMS += weak_undef_test +MOSTLYCLEANFILES += alt/weak_undef_lib.so weak_undef_test_SOURCES = weak_undef_test.cc weak_undef_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib.so alt/weak_undef_lib.so weak_undef_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt @@ -388,6 +531,7 @@ alt/weak_undef_lib.so: weak_undef_file2.o if FN_PTRS_IN_SO_WITHOUT_PIC check_PROGRAMS += weak_undef_nonpic_test +MOSTLYCLEANFILES += alt/weak_undef_lib_nonpic.so weak_undef_nonpic_test_SOURCES = weak_undef_test.cc weak_undef_nonpic_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib_nonpic.so alt/weak_undef_lib_nonpic.so weak_undef_nonpic_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt @@ -458,6 +602,8 @@ if TLS check_PROGRAMS += tls_test check_PROGRAMS += tls_pic_test +check_PROGRAMS += tls_pie_test +check_PROGRAMS += tls_pie_pic_test check_PROGRAMS += tls_shared_test check_PROGRAMS += tls_shared_ie_test check_PROGRAMS += tls_shared_gd_to_ie_test @@ -468,7 +614,7 @@ tls_test_file2_pic.o: tls_test_file2.cc tls_test_c_pic.o: tls_test_c.c $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o gcctestdir/ld - $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o + $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o -Wl,-z,defs tls_test_shared2.so: tls_test_file2_pic.o gcctestdir/ld $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_pic.o @@ -495,6 +641,22 @@ tls_pic_test_LDFLAGS = -Bgcctestdir/ tls_pic_test_LDADD = tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o \ -lpthread +tls_test_main_pie.o: tls_test_main.cc tls_test.h + $(CXXCOMPILE) -c -fpie -o $@ $< +tls_test_pie.o: tls_test.cc tls_test.h + $(CXXCOMPILE) -c -fpie -o $@ $< +tls_test_file2_pie.o: tls_test_file2.cc tls_test.h + $(CXXCOMPILE) -c -fpie -o $@ $< +tls_test_c_pie.o: tls_test_c.c + $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< +tls_pie_test: tls_test_main_pie.o tls_test_pie.o tls_test_file2_pie.o \ + tls_test_c_pie.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -pie tls_test_main_pie.o tls_test_pie.o tls_test_file2_pie.o tls_test_c_pie.o -lpthread + +tls_pie_pic_test: tls_test_main_pie.o tls_test_pic.o tls_test_file2_pic.o \ + tls_test_c_pic.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -pie tls_test_main_pie.o tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o -lpthread + tls_shared_test_SOURCES = tls_test_main.cc tls_shared_test_DEPENDENCIES = gcctestdir/ld tls_test_shared.so tls_shared_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @@ -580,8 +742,10 @@ check_PROGRAMS += many_sections_test many_sections_test_SOURCES = many_sections_test.cc many_sections_test_DEPENDENCIES = gcctestdir/ld many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic +many_sections_test_LDADD = BUILT_SOURCES += many_sections_define.h +MOSTLYCLEANFILES += many_sections_define.h many_sections_define.h: (for i in `seq 1 70000`; do \ echo "int var_$$i __attribute__((section(\"section_$$i\"))) = $$i;"; \ @@ -589,6 +753,7 @@ many_sections_define.h: mv -f $@.tmp $@ BUILT_SOURCES += many_sections_check.h +MOSTLYCLEANFILES += many_sections_check.h many_sections_check.h: (for i in `seq 1 1000 70000`; do \ echo "assert(var_$$i == $$i);"; \ @@ -607,6 +772,7 @@ check_PROGRAMS += initpri1 initpri1_SOURCES = initpri1.c initpri1_DEPENDENCIES = gcctestdir/ld initpri1_LDFLAGS = -Bgcctestdir/ +initpri1_LDADD = endif @@ -736,6 +902,11 @@ ver_test_3.o: ver_test_3.cc ver_test_4.o: ver_test_4.cc $(CXXCOMPILE) -c -fpic -o $@ $< +check_SCRIPTS += ver_test_1.sh +check_DATA += ver_test_1.syms +ver_test_1.syms: ver_test_1.so + $(TEST_READELF) -s $< >$@ 2>/dev/null + check_PROGRAMS += ver_test_2 ver_test_2_SOURCES = ver_test_main_2.cc ver_test_2_DEPENDENCIES = gcctestdir/ld ver_test_4.so ver_test_2.so @@ -803,6 +974,15 @@ ver_test_10.syms: ver_test_10.so ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o +check_PROGRAMS += ver_test_11 +MOSTLYCLEANFILES += ver_test_11.a +ver_test_11_SOURCES = ver_test_main_2.cc +ver_test_11_DEPENDENCIES = gcctestdir/ld ver_test_11.a +ver_test_11_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +ver_test_11_LDADD = ver_test_11.a +ver_test_11.a: ver_test_1.o ver_test_2.o ver_test_4.o + $(TEST_AR) rc $@ $^ + check_PROGRAMS += protected_1 protected_1_SOURCES = \ protected_main_1.cc protected_main_2.cc protected_main_3.cc @@ -825,6 +1005,18 @@ protected_2_DEPENDENCIES = gcctestdir/ld protected_1.so protected_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. protected_2_LDADD = protected_1.so +check_DATA += protected_3.err +MOSTLYCLEANFILES += protected_3.err +protected_4_pic.o: protected_4.cc + $(CXXCOMPILE) -c -fpic -o $@ $< +protected_3.err: protected_4_pic.o gcctestdir/ld + @echo $(CXXLINK) -Bgcctestdir/ -shared -o protected_4.so protected_4_pic.o "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -shared -o protected_4.so protected_4_pic.o 2>$@; then \ + echo 1>&2 "Link of protected_4.so should have failed"; \ + rm -f $@; \ + exit 1; \ + fi + check_PROGRAMS += relro_test relro_test_SOURCES = relro_test_main.cc relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so @@ -847,25 +1039,30 @@ check_PROGRAMS += script_test_1 script_test_1_SOURCES = script_test_1.cc script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t +script_test_1_LDADD = check_PROGRAMS += script_test_2 script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t +script_test_2_LDADD = check_PROGRAMS += justsyms justsyms_SOURCES = justsyms_1.cc justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o +justsyms_LDADD = justsyms_2.o: justsyms_2.cc $(CXXCOMPILE) -c -o $@ $< justsyms_2r.o: justsyms_2.o gcctestdir/ld $(srcdir)/justsyms.t gcctestdir/ld -o $@ -r -T $(srcdir)/justsyms.t justsyms_2.o check_PROGRAMS += binary_test +MOSTLYCLEANFILES += binary.txt binary_test_SOURCES = binary_test.cc binary_test_DEPENDENCIES = gcctestdir/ld binary.txt binary_test_LDFLAGS = -Bgcctestdir/ -Wl,--format,binary,binary.txt,--format,elf +binary_test_LDADD = # Copy the file to the build directory to avoid worrying about the # full pathname in the generated symbols. binary.txt: $(srcdir)/binary.in @@ -875,7 +1072,7 @@ binary.txt: $(srcdir)/binary.in check_SCRIPTS += ver_matching_test.sh check_DATA += ver_matching_test.stdout MOSTLYCLEANFILES += ver_matching_test.stdout -ver_matching_def.so: ver_matching_def.cc gcctestdir/ld +ver_matching_def.so: ver_matching_def.cc $(srcdir)/version_script.map gcctestdir/ld $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map ver_matching_test.stdout: ver_matching_def.so $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout @@ -891,11 +1088,530 @@ script_test_3.stdout: script_test_3 check_SCRIPTS += script_test_4.sh check_DATA += script_test_4.stdout -MOSTLYCLEANFILES += script_test_4.stdout +MOSTLYCLEANFILES += script_test_4 script_test_4: basic_test.o gcctestdir/ld $(srcdir)/script_test_4.t $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t script_test_4.stdout: script_test_4 $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout +check_SCRIPTS += script_test_5.sh +check_DATA += script_test_5.stdout +MOSTLYCLEANFILES += script_test_5 +script_test_5: script_test_5.o gcctestdir/ld $(srcdir)/script_test_5.t + $(CXXLINK) -Bgcctestdir/ script_test_5.o -T $(srcdir)/script_test_5.t +script_test_5.stdout: script_test_5 + $(TEST_READELF) -SW script_test_5 > script_test_5.stdout + +check_SCRIPTS += script_test_6.sh +check_DATA += script_test_6.stdout +MOSTLYCLEANFILES += script_test_6 +script_test_6: basic_test.o gcctestdir/ld $(srcdir)/script_test_6.t + $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_6.t \ + -Wl,-Ttext=0x10001000 -Wl,-Tdata=0x10200000 -Wl,-Tbss=0x10400000 +script_test_6.stdout: script_test_6 + $(TEST_READELF) -SlW script_test_6 > script_test_6.stdout + +check_SCRIPTS += script_test_7.sh +check_DATA += script_test_7.stdout +MOSTLYCLEANFILES += script_test_7 +script_test_7: basic_test.o gcctestdir/ld $(srcdir)/script_test_7.t + $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_7.t +script_test_7.stdout: script_test_7 + $(TEST_READELF) -SlW script_test_7 > script_test_7.stdout + +check_SCRIPTS += script_test_8.sh +check_DATA += script_test_8.stdout +MOSTLYCLEANFILES += script_test_8 +script_test_8: basic_test.o gcctestdir/ld $(srcdir)/script_test_7.t + $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_7.t \ + -Wl,-Ttext=0x20001000 -Wl,-Tdata=0x20200000 -Wl,-Tbss=0x20400000 +script_test_8.stdout: script_test_8 + $(TEST_READELF) -SlW script_test_8 > script_test_8.stdout + +# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, +# and --dynamic-list-cpp-typeinfo + +check_SCRIPTS += dynamic_list.sh +check_DATA += dynamic_list.stdout +MOSTLYCLEANFILES += dynamic_list dynamic_list.stdout +dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t + $(CXXLINK) -Bgcctestdir/ basic_test.o \ + -Wl,--dynamic-list $(srcdir)/dynamic_list.t \ + -Wl,--dynamic-list-data \ + -Wl,--dynamic-list-cpp-new \ + -Wl,--dynamic-list-cpp-typeinfo +dynamic_list.stdout: dynamic_list + $(TEST_READELF) -W -Ds dynamic_list > dynamic_list.stdout + +check_PROGRAMS += thin_archive_test_1 +MOSTLYCLEANFILES += libthin1.a libthin3.a libthinall.a \ + alt/thin_archive_test_2.o alt/thin_archive_test_4.o \ + alt/libthin2.a alt/libthin4.a +thin_archive_test_1_SOURCES = thin_archive_main.cc +thin_archive_test_1_DEPENDENCIES = gcctestdir/ld libthin1.a alt/libthin2.a +thin_archive_test_1_LDFLAGS = -Bgcctestdir/ -Lalt +thin_archive_test_1_LDADD = libthin1.a -lthin2 + +check_PROGRAMS += thin_archive_test_2 +thin_archive_test_2_SOURCES = thin_archive_main.cc +thin_archive_test_2_DEPENDENCIES = gcctestdir/ld libthinall.a +thin_archive_test_2_LDFLAGS = -Bgcctestdir/ -L. +thin_archive_test_2_LDADD = -lthinall + +libthin1.a: thin_archive_test_1.o alt/thin_archive_test_2.o + rm -f $@ + $(TEST_AR) crT $@ $^ +alt/libthin2.a: thin_archive_test_3.o alt/thin_archive_test_4.o + rm -f $@ + $(TEST_AR) crT $@ $^ +libthin3.a: thin_archive_test_1.o alt/thin_archive_test_4.o + rm -f $@ + $(TEST_AR) crT $@ $^ +alt/libthin4.a: alt/thin_archive_test_2.o thin_archive_test_3.o + rm -f $@ + $(TEST_AR) crT $@ $^ +libthinall.a: libthin3.a alt/libthin4.a + rm -f $@ + $(TEST_AR) crT $@ $^ +alt/thin_archive_test_2.o: thin_archive_test_2.cc + test -d alt || mkdir -p alt + $(CXXCOMPILE) -c -o $@ $< +alt/thin_archive_test_4.o: thin_archive_test_4.cc + test -d alt || mkdir -p alt + $(CXXCOMPILE) -c -o $@ $< + +if PLUGINS + +check_PROGRAMS += plugin_test_1 +check_SCRIPTS += plugin_test_1.sh +check_DATA += plugin_test_1.err +MOSTLYCLEANFILES += plugin_test_1.err +plugin_test_1: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so + $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_1.err +plugin_test_1.err: plugin_test_1 + @touch plugin_test_1.err + +check_PROGRAMS += plugin_test_2 +check_SCRIPTS += plugin_test_2.sh +check_DATA += plugin_test_2.err +MOSTLYCLEANFILES += plugin_test_2.err +plugin_test_2: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so gcctestdir/ld plugin_test.so + $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,-R,.,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so 2>plugin_test_2.err +plugin_test_2.err: plugin_test_2 + @touch plugin_test_2.err + +check_PROGRAMS += plugin_test_3 +check_SCRIPTS += plugin_test_3.sh +check_DATA += plugin_test_3.err +MOSTLYCLEANFILES += plugin_test_3.err +plugin_test_3: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so + $(CXXLINK) -Bgcctestdir/ -Wl,--export-dynamic -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_3.err +plugin_test_3.err: plugin_test_3 + @touch plugin_test_3.err + +check_PROGRAMS += plugin_test_4 +check_SCRIPTS += plugin_test_4.sh +check_DATA += plugin_test_4.err +MOSTLYCLEANFILES += plugin_test_4.a plugin_test_4.err +plugin_test_4: two_file_test_main.o plugin_test_4.a gcctestdir/ld plugin_test.so + $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o -Wl,--whole-archive,plugin_test_4.a,--no-whole-archive 2>plugin_test_4.err +plugin_test_4.err: plugin_test_4 + @touch plugin_test_4.err + +plugin_test_4.a: two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms + $(TEST_AR) cr $@ $^ + +check_PROGRAMS += plugin_test_5 +plugin_test_5: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms gcctestdir/ld plugin_test.so + $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv",--gc-sections two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms + +plugin_test.so: plugin_test.o + $(LINK) -Bgcctestdir/ -shared plugin_test.o +plugin_test.o: plugin_test.c + $(COMPILE) -O0 -c -fpic -o $@ $< + +two_file_test_main.syms: two_file_test_main.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null +two_file_test_1.syms: two_file_test_1.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null +two_file_test_1b.syms: two_file_test_1b.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null +two_file_test_2.syms: two_file_test_2.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null + +empty.syms: + @echo "" >$@ + @echo "Symbol table" >>$@ + +MOSTLYCLEANFILES += unused.c +unused.syms: unused.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null + @echo " 1: 00000000 4 FUNC GLOBAL DEFAULT 1 UNUSED" >>$@ +unused.o: unused.c + $(COMPILE) -c -o $@ $< +unused.c: + @cp /dev/null $@ + +endif PLUGINS + +check_PROGRAMS += exclude_libs_test +check_SCRIPTS += exclude_libs_test.sh +check_DATA += exclude_libs_test.syms +MOSTLYCLEANFILES += exclude_libs_test.syms libexclude_libs_test_1.a \ + libexclude_libs_test_2.a alt/libexclude_libs_test_3.a +exclude_libs_test_SOURCES = exclude_libs_test.c +exclude_libs_test_DEPENDENCIES = gcctestdir/ld libexclude_libs_test_1.a \ + libexclude_libs_test_2.a alt/libexclude_libs_test_3.a +exclude_libs_test_LDFLAGS = -Bgcctestdir/ -L. -Lalt \ + -Wl,--exclude-libs,dummy:libexclude_libs_test_1 \ + -Wl,--exclude-libs,libexclude_libs_test_3 +exclude_libs_test_LDADD = -lexclude_libs_test_1 -lexclude_libs_test_2 \ + alt/libexclude_libs_test_3.a +exclude_libs_test.syms: exclude_libs_test + $(TEST_READELF) -sW $< >$@ 2>/dev/null +libexclude_libs_test_1.a: exclude_libs_test_1.o + $(TEST_AR) rc $@ $^ +libexclude_libs_test_2.a: exclude_libs_test_2.o + $(TEST_AR) rc $@ $^ +alt/libexclude_libs_test_3.a: exclude_libs_test_3.o + test -d alt || mkdir -p alt + $(TEST_AR) rc $@ $^ + +check_PROGRAMS += local_labels_test +local_labels_test.o: ver_test_6.c + $(COMPILE) -g -c -Wa,-L -o $@ $< +local_labels_test: local_labels_test.o + $(LINK) -Bgcctestdir/ local_labels_test.o + +check_PROGRAMS += discard_locals_test +check_SCRIPTS += discard_locals_test.sh +check_DATA += discard_locals_test.syms \ + discard_locals_relocatable_test1.syms \ + discard_locals_relocatable_test2.syms +MOSTLYCLEANFILES += discard_locals_test.syms \ + discard_locals_relocatable_test1.syms \ + discard_locals_relocatable_test2.syms \ + discard_locals_relocatable_test1.out \ + discard_locals_relocatable_test2.out +discard_locals_test_SOURCES = discard_locals_test.c +discard_locals_test_LDFLAGS = -Bgcctestdir/ -Wl,--discard-locals +discard_locals_test.syms: discard_locals_test + $(TEST_READELF) -sW $< >$@ 2>/dev/null +# '-Wa,-L' is required to preserve the local label used for testing. +discard_locals_test.o: discard_locals_test.c + $(COMPILE) -c -Wa,-L -o $@ $< + +discard_locals_relocatable_test1.syms: discard_locals_relocatable_test1.out + $(TEST_READELF) -sW $< >$@ 2>/dev/null +discard_locals_relocatable_test.o: discard_locals_relocatable_test.c + $(COMPILE) -c -Wa,-L -fPIC -o $@ $< +discard_locals_relocatable_test1.out: discard_locals_relocatable_test.o ../ld-new + ../ld-new --discard-locals -relocatable -o $@ $< + +discard_locals_relocatable_test2.syms: discard_locals_relocatable_test2.out + $(TEST_READELF) -sW $< >$@ 2>/dev/null +discard_locals_relocatable_test2.out: discard_locals_relocatable_test.o ../ld-new + ../ld-new --discard-all -relocatable -o $@ $< + +if MCMODEL_MEDIUM +check_PROGRAMS += large +large_SOURCES = large.c +large_CFLAGS = -mcmodel=medium +large_DEPENDENCIES = gcctestdir/ld +large_LDFLAGS = -Bgcctestdir/ +large_LDADD = +endif MCMODEL_MEDIUM + +# Test that hidden and internal symbols in the main program cannot be +# referenced by a shared library. +check_SCRIPTS += hidden_test.sh +check_DATA += hidden_test.err +MOSTLYCLEANFILES += hidden_test hidden_test.err +libhidden.so: hidden_test_1.c gcctestdir/ld + $(COMPILE) -Bgcctestdir/ -g -shared -fPIC -w -o $@ $(srcdir)/hidden_test_1.c +hidden_test: hidden_test_main.o libhidden.so gcctestdir/ld + $(LINK) -Bgcctestdir/ -Wl,-R,. hidden_test_main.o libhidden.so 2>hidden_test.err +hidden_test.err: hidden_test + @touch hidden_test.err + +# Test -retain-symbols-file. +check_SCRIPTS += retain_symbols_file_test.sh +check_DATA += retain_symbols_file_test.stdout +MOSTLYCLEANFILES += retain_symbols_file_test retain_symbols_file_test.in \ + retain_symbols_file_test.stdout +retain_symbols_file_test.so: basic_pic_test.o gcctestdir/ld + echo 'main' > retain_symbols_file_test.in + echo 't1' >> retain_symbols_file_test.in + echo '_ZN4t16bC1Ev' >> retain_symbols_file_test.in + echo '_ZNK4t20a3getEv' >> retain_symbols_file_test.in + echo '_Z3t18v' >> retain_symbols_file_test.in + echo '__tcf_0' >> retain_symbols_file_test.in + $(CXXLINK) -Bgcctestdir/ -shared -Wl,-retain-symbols-file,retain_symbols_file_test.in basic_pic_test.o +retain_symbols_file_test.stdout: retain_symbols_file_test.so + $(TEST_NM) -C retain_symbols_file_test.so > $@ + + +# Test that if the output file already exists and is empty, +# it will get execute permission. +check_PROGRAMS += permission_test +permission_test: basic_test.o gcctestdir/ld + umask 022; \ + rm -f $@; \ + touch $@; \ + chmod 600 $@; \ + $(CXXLINK) -Bgcctestdir/ basic_test.o + +# Check -l:foo.a +check_PROGRAMS += searched_file_test +MOSTLYCLEANFILES += searched_file_test searched_file_test_lib.o \ + alt/searched_file_test_lib.a +searched_file_test_SOURCES = searched_file_test.cc +searched_file_test_DEPENDENCIES = alt/searched_file_test_lib.a +searched_file_test_LDFLAGS = -Bgcctestdir/ -Lalt +searched_file_test_LDADD = -l:searched_file_test_lib.a +searched_file_test_lib.o: searched_file_test_lib.cc + $(CXXCOMPILE) -c -o $@ $< +alt/searched_file_test_lib.a: searched_file_test_lib.o + test -d alt || mkdir -p alt + $(TEST_AR) rc $@ $^ + +# Test that no .gnu.version sections are created when +# symbol versioning is not used. +check_SCRIPTS += no_version_test.sh +check_DATA += no_version_test.stdout +MOSTLYCLEANFILES += libno_version_test.so no_version_test.stdout +# We invoke the linker directly since gcc may include additional objects that +# uses symbol versioning. +libno_version_test.so: no_version_test.o gcctestdir/ld + gcctestdir/ld -shared -o $@ no_version_test.o +no_version_test.o: no_version_test.c + $(COMPILE) -o $@ -c -fPIC $< +no_version_test.stdout: libno_version_test.so + $(TEST_OBJDUMP) -h $< > $@ + endif GCC endif NATIVE_LINKER + +# These tests work with cross linkers. + +if DEFAULT_TARGET_I386 + +check_SCRIPTS += split_i386.sh +check_DATA += split_i386_1.stdout split_i386_2.stdout \ + split_i386_3.stdout split_i386_4.stdout split_i386_r.stdout +SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 +split_i386_1.o: split_i386_1.s + $(TEST_AS) -o $@ $< +split_i386_2.o: split_i386_2.s + $(TEST_AS) -o $@ $< +split_i386_3.o: split_i386_3.s + $(TEST_AS) -o $@ $< +split_i386_4.o: split_i386_4.s + $(TEST_AS) -o $@ $< +split_i386_n.o: split_i386_n.s + $(TEST_AS) -o $@ $< +split_i386_1: split_i386_1.o split_i386_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_1.o split_i386_n.o +split_i386_1.stdout: split_i386_1 + $(TEST_OBJDUMP) -d $< > $@ +split_i386_2: split_i386_2.o split_i386_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_2.o split_i386_n.o +split_i386_2.stdout: split_i386_2 + $(TEST_OBJDUMP) -d $< > $@ +split_i386_3.stdout: split_i386_3.o split_i386_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o split_i386_3 split_i386_3.o split_i386_n.o > $@ 2>&1 || exit 0 +split_i386_4: split_i386_4.o split_i386_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_4.o split_i386_n.o +split_i386_4.stdout: split_i386_4 + $(TEST_OBJDUMP) -d $< > $@ +split_i386_r.stdout: split_i386_1.o split_i386_n.o ../ld-new + ../ld-new -r split_i386_1.o split_i386_n.o -o split_i386_r > $@ 2>&1 || exit 0 +MOSTLYCLEANFILES += split_i386_1 split_i386_2 split_i386_3 \ + split_i386_4 split_i386_r + +endif DEFAULT_TARGET_I386 + +if DEFAULT_TARGET_X86_64 + +check_SCRIPTS += split_x86_64.sh +check_DATA += split_x86_64_1.stdout split_x86_64_2.stdout \ + split_x86_64_3.stdout split_x86_64_4.stdout split_x86_64_r.stdout +SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 +split_x86_64_1.o: split_x86_64_1.s + $(TEST_AS) -o $@ $< +split_x86_64_2.o: split_x86_64_2.s + $(TEST_AS) -o $@ $< +split_x86_64_3.o: split_x86_64_3.s + $(TEST_AS) -o $@ $< +split_x86_64_4.o: split_x86_64_4.s + $(TEST_AS) -o $@ $< +split_x86_64_n.o: split_x86_64_n.s + $(TEST_AS) -o $@ $< +split_x86_64_1: split_x86_64_1.o split_x86_64_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_1.o split_x86_64_n.o +split_x86_64_1.stdout: split_x86_64_1 + $(TEST_OBJDUMP) -d $< > $@ +split_x86_64_2: split_x86_64_2.o split_x86_64_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_2.o split_x86_64_n.o +split_x86_64_2.stdout: split_x86_64_2 + $(TEST_OBJDUMP) -d $< > $@ +split_x86_64_3.stdout: split_x86_64_3.o split_x86_64_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o split_x86_64_3 split_x86_64_3.o split_x86_64_n.o > $@ 2>&1 || exit 0 +split_x86_64_4: split_x86_64_4.o split_x86_64_n.o ../ld-new + ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_4.o split_x86_64_n.o +split_x86_64_4.stdout: split_x86_64_4 + $(TEST_OBJDUMP) -d $< > $@ +split_x86_64_r.stdout: split_x86_64_1.o split_x86_64_n.o ../ld-new + ../ld-new -r split_x86_64_1.o split_x86_64_n.o -o split_x86_64_r > $@ 2>&1 || exit 0 +MOSTLYCLEANFILES += split_x86_64_1 split_x86_64_2 split_x86_64_3 \ + split_x86_64_4 split_x86_64_r + +endif DEFAULT_TARGET_X86_64 + +if DEFAULT_TARGET_ARM + +check_SCRIPTS += arm_abs_global.sh +check_DATA += arm_abs_global.stdout +arm_abs_lib.o: arm_abs_lib.s + $(TEST_AS) -march=armv7-a -o $@ $< +libarm_abs.so: arm_abs_lib.o ../ld-new + ../ld-new -shared -o $@ arm_abs_lib.o +arm_abs_global.o: arm_abs_global.s + $(TEST_AS) -march=armv7-a -o $@ $< +arm_abs_global: arm_abs_global.o libarm_abs.so ../ld-new + ../ld-new -o $@ arm_abs_global.o -L. -larm_abs +arm_abs_global.stdout: arm_abs_global + $(TEST_READELF) -r $< > $@ + +MOSTLYCLEANFILES += arm_abs_global + +check_SCRIPTS += arm_branch_in_range.sh +check_DATA += arm_bl_in_range.stdout arm_bl_out_of_range.stdout \ + thumb_bl_in_range.stdout thumb_bl_out_of_range.stdout \ + thumb2_bl_in_range.stdout thumb2_bl_out_of_range.stdout \ + thumb_blx_in_range.stdout thumb_blx_out_of_range.stdout \ + thumb2_blx_in_range.stdout thumb2_blx_out_of_range.stdout + +arm_bl_in_range.stdout: arm_bl_in_range + $(TEST_OBJDUMP) -D $< > $@ + +arm_bl_in_range: arm_bl_in_range.o ../ld-new + ../ld-new -T $(srcdir)/arm_branch_range.t -o $@ $< + +arm_bl_in_range.o: arm_bl_in_range.s + $(TEST_AS) -o $@ $< + +arm_bl_out_of_range.stdout: arm_bl_out_of_range + $(TEST_OBJDUMP) -S $< > $@ + +arm_bl_out_of_range: arm_bl_out_of_range.o ../ld-new + ../ld-new -T $(srcdir)/arm_branch_range.t -o $@ $< + +arm_bl_out_of_range.o: arm_bl_out_of_range.s + $(TEST_AS) -o $@ $< + +thumb_bl_in_range.stdout: thumb_bl_in_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb_bl_in_range: thumb_bl_in_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +thumb_bl_in_range.o: thumb_bl_in_range.s + $(TEST_AS) -o $@ -march=armv5te $< + +thumb_bl_out_of_range.stdout: thumb_bl_out_of_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb_bl_out_of_range: thumb_bl_out_of_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +thumb_bl_out_of_range.o: thumb_bl_out_of_range.s + $(TEST_AS) -o $@ -march=armv5te $< + +thumb2_bl_in_range.stdout: thumb2_bl_in_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb2_bl_in_range: thumb2_bl_in_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +thumb2_bl_in_range.o: thumb_bl_in_range.s + $(TEST_AS) -o $@ -march=armv7-a $< + +thumb2_bl_out_of_range.stdout: thumb2_bl_out_of_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb2_bl_out_of_range: thumb2_bl_out_of_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +thumb2_bl_out_of_range.o: thumb_bl_out_of_range.s + $(TEST_AS) -o $@ -march=armv7-a $< + +thumb_blx_in_range.stdout: thumb_blx_in_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb_blx_in_range: thumb_blx_in_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +thumb_blx_in_range.o: thumb_blx_in_range.s + $(TEST_AS) -o $@ -march=armv5te $< + +thumb_blx_out_of_range.stdout: thumb_blx_out_of_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb_blx_out_of_range: thumb_blx_out_of_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +thumb_blx_out_of_range.o: thumb_blx_out_of_range.s + $(TEST_AS) -o $@ -march=armv5te $< + +thumb2_blx_in_range.stdout: thumb2_blx_in_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb2_blx_in_range: thumb2_blx_in_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +thumb2_blx_in_range.o: thumb_blx_in_range.s + $(TEST_AS) -o $@ -march=armv7-a $< + +thumb2_blx_out_of_range.stdout: thumb2_blx_out_of_range + $(TEST_OBJDUMP) -D $< > $@ + +thumb2_blx_out_of_range: thumb2_blx_out_of_range.o ../ld-new + ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +thumb2_blx_out_of_range.o: thumb_blx_out_of_range.s + $(TEST_AS) -o $@ -march=armv7-a $< + +MOSTLYCLEANFILES += arm_bl_in_range arm_bl_out_of_range thumb_bl_in_range \ + thumb_bl_out_of_range thumb2_bl_in_range thumb2_bl_out_of_range \ + thumb_blx_in_range thumb_blx_out_of_range thumb2_blx_in_range \ + thumb2_blx_out_of_range + +check_SCRIPTS += arm_fix_v4bx.sh +check_DATA += arm_fix_v4bx.stdout arm_fix_v4bx_interworking.stdout \ + arm_no_fix_v4bx.stdout + +arm_fix_v4bx.stdout: arm_fix_v4bx + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_fix_v4bx: arm_fix_v4bx.o ../ld-new + ../ld-new --fix-v4bx -o $@ $< + +arm_fix_v4bx.o: arm_fix_v4bx.s + $(TEST_AS) -o $@ $< + +arm_fix_v4bx_interworking.stdout: arm_fix_v4bx_interworking + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_fix_v4bx_interworking: arm_fix_v4bx.o ../ld-new + ../ld-new --fix-v4bx-interworking -o $@ $< + +arm_no_fix_v4bx.stdout: arm_no_fix_v4bx + $(TEST_OBJDUMP) -D -j.text $< > $@ + +arm_no_fix_v4bx: arm_fix_v4bx.o ../ld-new + ../ld-new -o $@ $< + +MOSTLYCLEANFILES += arm_fix_v4bx arm_fix_v4bx_interworking arm_no_fix_v4bx + +endif DEFAULT_TARGET_ARM diff --git a/binutils-2.19/gold/testsuite/Makefile.in b/binutils-2.19/gold/testsuite/Makefile.in index 9f72b88..8815bc3 100644 --- a/binutils-2.19/gold/testsuite/Makefile.in +++ b/binutils-2.19/gold/testsuite/Makefile.in @@ -1,8 +1,9 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. +# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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. @@ -19,15 +20,12 @@ # As far as I can tell automake testing support assumes that the build # system and the host system are the same. So these tests will not # work when building with a cross-compiler. -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ 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 @@ -47,11 +45,79 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \ $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \ - $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = basic_test \ + $(am__EXEEXT_13) $(am__EXEEXT_14) $(am__EXEEXT_15) \ + $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18) \ + $(am__EXEEXT_19) + +# Test --detect-odr-violations + +# Similar to --detect-odr-violations: check for undefined symbols in .so's + +# Test --dynamic-list, --dynamic-list-data, --dynamic-list-cpp-new, +# and --dynamic-list-cpp-typeinfo +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = incremental_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test.sh gc_tls_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh undef_symbol.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_1.sh ver_test_2.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_5.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_7.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.sh dynamic_list.sh + +# Create the data files that debug_msg.sh analyzes. + +# See if we can also detect problems when we're linking .so's, not .o's. + +# We also want to make sure we do something reasonable when there's no +# debug info available. For the best test, we use .so's. +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = incremental_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_tls_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_1.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_2.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_1.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_2.syms ver_test_4.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_5.syms ver_test_7.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_10.syms protected_3.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_5.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_7.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = incremental_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test gc_tls_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test icf_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/weak_undef_lib.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = basic_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test basic_pic_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pie_test constructor_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_static_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_static_test \ @@ -63,50 +129,26 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test -@GCC_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@constructor_static_test_DEPENDENCIES = libgoldtest.a \ -@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@constructor_static_test_DEPENDENCIES = \ -@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ -@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@two_file_static_test_DEPENDENCIES = libgoldtest.a \ -@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@two_file_static_test_DEPENDENCIES = \ -@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ -@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_pie_test +@GCC_FALSE@constructor_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@constructor_test_DEPENDENCIES = +@GCC_FALSE@two_file_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@two_file_test_DEPENDENCIES = # The nonpic tests will fail on platforms which can not put non-PIC # code into shared libraries, so we just don't run them in that case. -@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = two_file_shared_1_nonpic_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_5 = two_file_shared_1_nonpic_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_nonpic_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_nonpic_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_nonpic_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_shared_test \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_mixed_2_shared_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = two_file_strip_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = two_file_strip_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_strip_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1 exception_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1 common_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_static_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_1_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_2_test \ @@ -114,153 +156,207 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_12_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_separate_shared_21_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_test weak_undef_test -@GCC_FALSE@common_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@common_test_1_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@exception_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@exception_static_test_DEPENDENCIES = libgoldtest.a \ -@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@exception_static_test_DEPENDENCIES = \ -@NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ -@NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@weak_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@weak_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = weak_undef_nonpic_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_5 = weak_alias_test weak_plt \ +@GCC_FALSE@common_test_1_DEPENDENCIES = +@NATIVE_LINKER_FALSE@common_test_1_DEPENDENCIES = +@GCC_FALSE@exception_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = +@GCC_FALSE@weak_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@weak_test_DEPENDENCIES = +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_7 = weak_undef_nonpic_test +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_8 = alt/weak_undef_lib_nonpic.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_9 = weak_alias_test weak_plt \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test - -# Test --detect-odr-violations - -# Similar to --detect-odr-violations: check for undefined symbols in .so's -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_6 = weak_plt.sh debug_msg.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.sh ver_test_2.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.sh ver_test_5.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.sh ver_test_10.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.sh - -# Create the data files that debug_msg.sh analyzes. - -# See if we can also detect problems when we're linking .so's, not .o's. - -# We also want to make sure we do something reasonable when there's no -# debug info available. For the best test, we use .so's. -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_7 = weak_plt_shared.so \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err debug_msg_so.err \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_2.syms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_4.syms ver_test_5.syms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_7.syms ver_test_10.syms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout -@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_8 = tls_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_10 = tls_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pie_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pie_pic_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_ie_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_gd_to_ie_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_9 = tls_shared_gnu2_gd_to_ie_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_10 = tls_shared_gnu2_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__append_11 = tls_static_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_11 = tls_shared_gnu2_gd_to_ie_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am__append_12 = tls_shared_gnu2_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am__append_13 = tls_static_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@ tls_static_pic_test -@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_12 = tls_shared_nonpic_test -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_13 = many_sections_test \ +@FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__append_14 = tls_shared_nonpic_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = many_sections_test \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test -@GCC_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ -@GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_14 = many_sections_define.h \ +@GCC_FALSE@many_sections_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES = +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = many_sections_define.h \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h -@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_15 = initpri1 -@CONSTRUCTOR_PRIORITY_FALSE@initpri1_DEPENDENCIES = libgoldtest.a \ -@CONSTRUCTOR_PRIORITY_FALSE@ ../libgold.a \ -@CONSTRUCTOR_PRIORITY_FALSE@ ../../libiberty/libiberty.a \ -@CONSTRUCTOR_PRIORITY_FALSE@ $(am__DEPENDENCIES_1) \ -@CONSTRUCTOR_PRIORITY_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@initpri1_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_16 = debug_msg.err \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = many_sections_define.h \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_check.h \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.err debug_msg_so.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_ndebug.err \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ undef_symbol.err ver_test_11.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_3.err binary.txt \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_matching_test.stdout \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3.stdout \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_4 script_test_5 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_6 script_test_7 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_8 dynamic_list \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout libthin1.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libthin3.a libthinall.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_2.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/thin_archive_test_4.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libthin2.a alt/libthin4.a +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_18 = initpri1 +@CONSTRUCTOR_PRIORITY_FALSE@initpri1_DEPENDENCIES = +@GCC_FALSE@initpri1_DEPENDENCIES = +@NATIVE_LINKER_FALSE@initpri1_DEPENDENCIES = # Test -o when emitting to a special file (such as something in /dev). -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_17 = flagstest_o_specialfile +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = flagstest_o_specialfile # Test --compress-debug-sections. FIXME: check we actually compress. # The specialfile output has a tricky case when we also compress debug # sections, because it requires output-file resizing. -@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_18 = flagstest_compress_debug_sections \ +@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_20 = flagstest_compress_debug_sections \ @GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections # Test symbol versioning. -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = ver_test ver_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_21 = ver_test ver_test_2 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6 ver_test_8 ver_test_9 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1 protected_2 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test relro_script_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1 script_test_2 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms binary_test \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3 -@GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@script_test_2_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@script_test_2_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@justsyms_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@justsyms_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) -@GCC_FALSE@binary_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) -@NATIVE_LINKER_FALSE@binary_test_DEPENDENCIES = libgoldtest.a \ -@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ -@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_11 protected_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_2 relro_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_script_test script_test_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test script_test_3 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_2 +@GCC_FALSE@script_test_1_DEPENDENCIES = +@NATIVE_LINKER_FALSE@script_test_1_DEPENDENCIES = +@GCC_FALSE@script_test_2_DEPENDENCIES = +@NATIVE_LINKER_FALSE@script_test_2_DEPENDENCIES = +@GCC_FALSE@justsyms_DEPENDENCIES = +@NATIVE_LINKER_FALSE@justsyms_DEPENDENCIES = +@GCC_FALSE@binary_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@binary_test_DEPENDENCIES = +@GCC_FALSE@thin_archive_test_2_DEPENDENCIES = +@NATIVE_LINKER_FALSE@thin_archive_test_2_DEPENDENCIES = +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_22 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_5 +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_23 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_24 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_25 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ unused.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_26 = exclude_libs_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ local_labels_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test + +# Test that hidden and internal symbols in the main program cannot be +# referenced by a shared library. + +# Test -retain-symbols-file. + +# Test that no .gnu.version sections are created when +# symbol versioning is not used. +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = exclude_libs_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ hidden_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_28 = exclude_libs_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test1.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test2.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ hidden_test.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_29 = exclude_libs_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_1.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libexclude_libs_test_3.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test1.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test2.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test1.out \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_relocatable_test2.out \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ hidden_test hidden_test.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.in \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ retain_symbols_file_test.stdout \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test_lib.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/searched_file_test_lib.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libno_version_test.so \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ no_version_test.stdout +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__append_30 = large +@GCC_FALSE@large_DEPENDENCIES = +@MCMODEL_MEDIUM_FALSE@large_DEPENDENCIES = +@NATIVE_LINKER_FALSE@large_DEPENDENCIES = + +# Test that if the output file already exists and is empty, +# it will get execute permission. + +# Check -l:foo.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_31 = permission_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test +@GCC_FALSE@searched_file_test_DEPENDENCIES = +@NATIVE_LINKER_FALSE@searched_file_test_DEPENDENCIES = + +# These tests work with cross linkers. +@DEFAULT_TARGET_I386_TRUE@am__append_32 = split_i386.sh +@DEFAULT_TARGET_I386_TRUE@am__append_33 = split_i386_1.stdout split_i386_2.stdout \ +@DEFAULT_TARGET_I386_TRUE@ split_i386_3.stdout split_i386_4.stdout split_i386_r.stdout + +@DEFAULT_TARGET_I386_TRUE@am__append_34 = split_i386_1 split_i386_2 split_i386_3 \ +@DEFAULT_TARGET_I386_TRUE@ split_i386_4 split_i386_r + +@DEFAULT_TARGET_X86_64_TRUE@am__append_35 = split_x86_64.sh +@DEFAULT_TARGET_X86_64_TRUE@am__append_36 = split_x86_64_1.stdout split_x86_64_2.stdout \ +@DEFAULT_TARGET_X86_64_TRUE@ split_x86_64_3.stdout split_x86_64_4.stdout split_x86_64_r.stdout + +@DEFAULT_TARGET_X86_64_TRUE@am__append_37 = split_x86_64_1 split_x86_64_2 split_x86_64_3 \ +@DEFAULT_TARGET_X86_64_TRUE@ split_x86_64_4 split_x86_64_r + +@DEFAULT_TARGET_ARM_TRUE@am__append_38 = arm_abs_global.sh \ +@DEFAULT_TARGET_ARM_TRUE@ arm_branch_in_range.sh \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.sh +@DEFAULT_TARGET_ARM_TRUE@am__append_39 = arm_abs_global.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_bl_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_in_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_in_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_in_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_in_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_out_of_range.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking.stdout \ +@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx.stdout +@DEFAULT_TARGET_ARM_TRUE@am__append_40 = arm_abs_global \ +@DEFAULT_TARGET_ARM_TRUE@ arm_bl_in_range arm_bl_out_of_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_in_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_bl_out_of_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_in_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_bl_out_of_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_in_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb_blx_out_of_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_in_range \ +@DEFAULT_TARGET_ARM_TRUE@ thumb2_blx_out_of_range arm_fix_v4bx \ +@DEFAULT_TARGET_ARM_TRUE@ arm_fix_v4bx_interworking \ +@DEFAULT_TARGET_ARM_TRUE@ arm_no_fix_v4bx subdir = testsuite DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -270,7 +366,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/nls.m4 \ $(top_srcdir)/../config/override.m4 \ $(top_srcdir)/../config/po.m4 \ - $(top_srcdir)/../config/proginstall.m4 \ $(top_srcdir)/../config/progtest.m4 \ $(top_srcdir)/../bfd/warning.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -278,6 +373,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = AR = ar ARFLAGS = cru libgoldtest_a_AR = $(AR) $(ARFLAGS) @@ -289,6 +385,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pic_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pie_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_static_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test$(EXEEXT) \ @@ -301,7 +398,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_12_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_separate_shared_21_test$(EXEEXT) \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_relocatable_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_pie_test$(EXEEXT) @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_2 = two_file_shared_1_nonpic_test$(EXEEXT) \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared_2_nonpic_test$(EXEEXT) \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_nonpic_test$(EXEEXT) \ @@ -313,6 +411,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_strip_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_same_shared_strip_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_static_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_shared_1_test$(EXEEXT) \ @@ -329,6 +428,8 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__EXEEXT_6 = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pic_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pie_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_pie_pic_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_ie_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_shared_gd_to_ie_test$(EXEEXT) @@ -349,6 +450,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_8$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_9$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_11$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test$(EXEEXT) \ @@ -357,48 +459,77 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test$(EXEEXT) \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_test_2$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__EXEEXT_16 = plugin_test_1$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_2$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_5$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_17 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exclude_libs_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ local_labels_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test$(EXEEXT) +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_18 = large$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_19 = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ permission_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test$(EXEEXT) basic_pic_test_SOURCES = basic_pic_test.c basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT) basic_pic_test_LDADD = $(LDADD) am__DEPENDENCIES_1 = basic_pic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +basic_pie_test_SOURCES = basic_pie_test.c +basic_pie_test_OBJECTS = basic_pie_test.$(OBJEXT) +basic_pie_test_LDADD = $(LDADD) +basic_pie_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) basic_static_pic_test_SOURCES = basic_static_pic_test.c basic_static_pic_test_OBJECTS = basic_static_pic_test.$(OBJEXT) basic_static_pic_test_LDADD = $(LDADD) basic_static_pic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) basic_static_test_SOURCES = basic_static_test.c basic_static_test_OBJECTS = basic_static_test.$(OBJEXT) basic_static_test_LDADD = $(LDADD) basic_static_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) basic_test_SOURCES = basic_test.c basic_test_OBJECTS = basic_test.$(OBJEXT) basic_test_LDADD = $(LDADD) basic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__binary_test_SOURCES_DIST = binary_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_binary_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test.$(OBJEXT) binary_test_OBJECTS = $(am_binary_test_OBJECTS) -binary_test_LDADD = $(LDADD) +binary_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(binary_test_LDFLAGS) $(LDFLAGS) -o $@ am_binary_unittest_OBJECTS = binary_unittest.$(OBJEXT) binary_unittest_OBJECTS = $(am_binary_unittest_OBJECTS) binary_unittest_LDADD = $(LDADD) binary_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__common_test_1_SOURCES_DIST = common_test_1.c @GCC_TRUE@@NATIVE_LINKER_TRUE@am_common_test_1_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1.$(OBJEXT) common_test_1_OBJECTS = $(am_common_test_1_OBJECTS) -common_test_1_LDADD = $(LDADD) +common_test_1_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(common_test_1_LDFLAGS) $(LDFLAGS) -o $@ +am__common_test_2_SOURCES_DIST = common_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_common_test_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ common_test_1.$(OBJEXT) +common_test_2_OBJECTS = $(am_common_test_2_OBJECTS) +common_test_2_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(common_test_2_LDFLAGS) $(LDFLAGS) -o $@ am__constructor_static_test_SOURCES_DIST = constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am__objects_1 = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test.$(OBJEXT) @@ -406,33 +537,55 @@ am__constructor_static_test_SOURCES_DIST = constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_1) constructor_static_test_OBJECTS = \ $(am_constructor_static_test_OBJECTS) -constructor_static_test_LDADD = $(LDADD) +constructor_static_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(constructor_static_test_LDFLAGS) $(LDFLAGS) -o $@ am__constructor_test_SOURCES_DIST = constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_constructor_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_test.$(OBJEXT) constructor_test_OBJECTS = $(am_constructor_test_OBJECTS) -constructor_test_LDADD = $(LDADD) +constructor_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(constructor_test_LDFLAGS) $(LDFLAGS) -o $@ am__copy_test_SOURCES_DIST = copy_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_copy_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ copy_test.$(OBJEXT) copy_test_OBJECTS = $(am_copy_test_OBJECTS) +copy_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(copy_test_LDFLAGS) $(LDFLAGS) -o $@ +am__discard_locals_test_SOURCES_DIST = discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_discard_locals_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ discard_locals_test.$(OBJEXT) +discard_locals_test_OBJECTS = $(am_discard_locals_test_OBJECTS) +discard_locals_test_LDADD = $(LDADD) +discard_locals_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +discard_locals_test_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(discard_locals_test_LDFLAGS) $(LDFLAGS) -o $@ am__exception_same_shared_test_SOURCES_DIST = exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_same_shared_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) exception_same_shared_test_OBJECTS = \ $(am_exception_same_shared_test_OBJECTS) +exception_same_shared_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(exception_same_shared_test_LDFLAGS) $(LDFLAGS) -o $@ am__exception_separate_shared_12_test_SOURCES_DIST = \ exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_separate_shared_12_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) exception_separate_shared_12_test_OBJECTS = \ $(am_exception_separate_shared_12_test_OBJECTS) +exception_separate_shared_12_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(exception_separate_shared_12_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__exception_separate_shared_21_test_SOURCES_DIST = \ exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_separate_shared_21_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) exception_separate_shared_21_test_OBJECTS = \ $(am_exception_separate_shared_21_test_OBJECTS) +exception_separate_shared_21_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(exception_separate_shared_21_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__exception_shared_1_test_SOURCES_DIST = exception_test_2.cc \ exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_shared_1_test_OBJECTS = \ @@ -440,6 +593,8 @@ am__exception_shared_1_test_SOURCES_DIST = exception_test_2.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) exception_shared_1_test_OBJECTS = \ $(am_exception_shared_1_test_OBJECTS) +exception_shared_1_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(exception_shared_1_test_LDFLAGS) $(LDFLAGS) -o $@ am__exception_shared_2_test_SOURCES_DIST = exception_test_1.cc \ exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_shared_2_test_OBJECTS = \ @@ -447,6 +602,8 @@ am__exception_shared_2_test_SOURCES_DIST = exception_test_1.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.$(OBJEXT) exception_shared_2_test_OBJECTS = \ $(am_exception_shared_2_test_OBJECTS) +exception_shared_2_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(exception_shared_2_test_LDFLAGS) $(LDFLAGS) -o $@ am__exception_static_test_SOURCES_DIST = exception_test_main.cc \ exception_test_1.cc exception_test_2.cc exception_test.h @GCC_TRUE@@NATIVE_LINKER_TRUE@am__objects_2 = \ @@ -456,7 +613,8 @@ am__exception_static_test_SOURCES_DIST = exception_test_main.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_static_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_2) exception_static_test_OBJECTS = $(am_exception_static_test_OBJECTS) -exception_static_test_LDADD = $(LDADD) +exception_static_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(exception_static_test_LDFLAGS) $(LDFLAGS) -o $@ am__exception_test_SOURCES_DIST = exception_test_main.cc \ exception_test_1.cc exception_test_2.cc exception_test.h @GCC_TRUE@@NATIVE_LINKER_TRUE@am_exception_test_OBJECTS = \ @@ -464,7 +622,14 @@ am__exception_test_SOURCES_DIST = exception_test_main.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_2.$(OBJEXT) exception_test_OBJECTS = $(am_exception_test_OBJECTS) -exception_test_LDADD = $(LDADD) +exception_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(exception_test_LDFLAGS) $(LDFLAGS) -o $@ +am__exclude_libs_test_SOURCES_DIST = exclude_libs_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_exclude_libs_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exclude_libs_test.$(OBJEXT) +exclude_libs_test_OBJECTS = $(am_exclude_libs_test_OBJECTS) +exclude_libs_test_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(exclude_libs_test_LDFLAGS) $(LDFLAGS) -o $@ flagstest_compress_debug_sections_SOURCES = \ flagstest_compress_debug_sections.c flagstest_compress_debug_sections_OBJECTS = \ @@ -472,13 +637,13 @@ flagstest_compress_debug_sections_OBJECTS = \ flagstest_compress_debug_sections_LDADD = $(LDADD) flagstest_compress_debug_sections_DEPENDENCIES = libgoldtest.a \ ../libgold.a ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) flagstest_o_specialfile_SOURCES = flagstest_o_specialfile.c flagstest_o_specialfile_OBJECTS = flagstest_o_specialfile.$(OBJEXT) flagstest_o_specialfile_LDADD = $(LDADD) flagstest_o_specialfile_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) flagstest_o_specialfile_and_compress_debug_sections_SOURCES = \ flagstest_o_specialfile_and_compress_debug_sections.c flagstest_o_specialfile_and_compress_debug_sections_OBJECTS = \ @@ -486,33 +651,84 @@ flagstest_o_specialfile_and_compress_debug_sections_OBJECTS = \ flagstest_o_specialfile_and_compress_debug_sections_LDADD = $(LDADD) flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES = \ libgoldtest.a ../libgold.a ../../libiberty/libiberty.a \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am__initpri1_SOURCES_DIST = initpri1.c @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri1_OBJECTS = initpri1.$(OBJEXT) initpri1_OBJECTS = $(am_initpri1_OBJECTS) -initpri1_LDADD = $(LDADD) +initpri1_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri1_LDFLAGS) \ + $(LDFLAGS) -o $@ am__justsyms_SOURCES_DIST = justsyms_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_justsyms_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT) justsyms_OBJECTS = $(am_justsyms_OBJECTS) -justsyms_LDADD = $(LDADD) +justsyms_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(justsyms_LDFLAGS) $(LDFLAGS) -o $@ +am__large_SOURCES_DIST = large.c +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@am_large_OBJECTS = large-large.$(OBJEXT) +large_OBJECTS = $(am_large_OBJECTS) +large_LINK = $(CCLD) $(large_CFLAGS) $(CFLAGS) $(large_LDFLAGS) \ + $(LDFLAGS) -o $@ +local_labels_test_SOURCES = local_labels_test.c +local_labels_test_OBJECTS = local_labels_test.$(OBJEXT) +local_labels_test_LDADD = $(LDADD) +local_labels_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) many_sections_r_test_SOURCES = many_sections_r_test.c many_sections_r_test_OBJECTS = many_sections_r_test.$(OBJEXT) many_sections_r_test_LDADD = $(LDADD) many_sections_r_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__many_sections_test_SOURCES_DIST = many_sections_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_many_sections_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_test.$(OBJEXT) many_sections_test_OBJECTS = $(am_many_sections_test_OBJECTS) -many_sections_test_LDADD = $(LDADD) +many_sections_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(many_sections_test_LDFLAGS) $(LDFLAGS) -o $@ am_object_unittest_OBJECTS = object_unittest.$(OBJEXT) object_unittest_OBJECTS = $(am_object_unittest_OBJECTS) object_unittest_LDADD = $(LDADD) object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +permission_test_SOURCES = permission_test.c +permission_test_OBJECTS = permission_test.$(OBJEXT) +permission_test_LDADD = $(LDADD) +permission_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +plugin_test_1_SOURCES = plugin_test_1.c +plugin_test_1_OBJECTS = plugin_test_1.$(OBJEXT) +plugin_test_1_LDADD = $(LDADD) +plugin_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +plugin_test_2_SOURCES = plugin_test_2.c +plugin_test_2_OBJECTS = plugin_test_2.$(OBJEXT) +plugin_test_2_LDADD = $(LDADD) +plugin_test_2_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +plugin_test_3_SOURCES = plugin_test_3.c +plugin_test_3_OBJECTS = plugin_test_3.$(OBJEXT) +plugin_test_3_LDADD = $(LDADD) +plugin_test_3_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +plugin_test_4_SOURCES = plugin_test_4.c +plugin_test_4_OBJECTS = plugin_test_4.$(OBJEXT) +plugin_test_4_LDADD = $(LDADD) +plugin_test_4_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +plugin_test_5_SOURCES = plugin_test_5.c +plugin_test_5_OBJECTS = plugin_test_5.$(OBJEXT) +plugin_test_5_LDADD = $(LDADD) +plugin_test_5_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__protected_1_SOURCES_DIST = protected_main_1.cc protected_main_2.cc \ protected_main_3.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_protected_1_OBJECTS = \ @@ -520,24 +736,33 @@ am__protected_1_SOURCES_DIST = protected_main_1.cc protected_main_2.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_2.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_3.$(OBJEXT) protected_1_OBJECTS = $(am_protected_1_OBJECTS) +protected_1_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(protected_1_LDFLAGS) $(LDFLAGS) -o $@ am__protected_2_SOURCES_DIST = protected_main_1.cc protected_3.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_protected_2_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_3.$(OBJEXT) protected_2_OBJECTS = $(am_protected_2_OBJECTS) +protected_2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(protected_2_LDFLAGS) $(LDFLAGS) -o $@ am__relro_script_test_SOURCES_DIST = relro_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_script_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT) relro_script_test_OBJECTS = $(am_relro_script_test_OBJECTS) +relro_script_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(relro_script_test_LDFLAGS) $(LDFLAGS) -o $@ am__relro_test_SOURCES_DIST = relro_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT) relro_test_OBJECTS = $(am_relro_test_OBJECTS) +relro_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(relro_test_LDFLAGS) $(LDFLAGS) -o $@ am__script_test_1_SOURCES_DIST = script_test_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_1_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1.$(OBJEXT) script_test_1_OBJECTS = $(am_script_test_1_OBJECTS) -script_test_1_LDADD = $(LDADD) +script_test_1_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(script_test_1_LDFLAGS) $(LDFLAGS) -o $@ am__script_test_2_SOURCES_DIST = script_test_2.cc script_test_2a.cc \ script_test_2b.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_script_test_2_OBJECTS = \ @@ -545,36 +770,82 @@ am__script_test_2_SOURCES_DIST = script_test_2.cc script_test_2a.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2a.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2b.$(OBJEXT) script_test_2_OBJECTS = $(am_script_test_2_OBJECTS) -script_test_2_LDADD = $(LDADD) +script_test_2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(script_test_2_LDFLAGS) $(LDFLAGS) -o $@ script_test_3_SOURCES = script_test_3.c script_test_3_OBJECTS = script_test_3.$(OBJEXT) script_test_3_LDADD = $(LDADD) script_test_3_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am__searched_file_test_SOURCES_DIST = searched_file_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_searched_file_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ searched_file_test.$(OBJEXT) +searched_file_test_OBJECTS = $(am_searched_file_test_OBJECTS) +searched_file_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(searched_file_test_LDFLAGS) $(LDFLAGS) -o $@ +am__thin_archive_test_1_SOURCES_DIST = thin_archive_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_thin_archive_test_1_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_main.$(OBJEXT) +thin_archive_test_1_OBJECTS = $(am_thin_archive_test_1_OBJECTS) +thin_archive_test_1_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(thin_archive_test_1_LDFLAGS) $(LDFLAGS) -o $@ +am__thin_archive_test_2_SOURCES_DIST = thin_archive_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_thin_archive_test_2_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ thin_archive_main.$(OBJEXT) +thin_archive_test_2_OBJECTS = $(am_thin_archive_test_2_OBJECTS) +thin_archive_test_2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(thin_archive_test_2_LDFLAGS) $(LDFLAGS) -o $@ am__tls_pic_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_pic_test_OBJECTS = tls_test_main.$(OBJEXT) tls_pic_test_OBJECTS = $(am_tls_pic_test_OBJECTS) +tls_pic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_pic_test_LDFLAGS) $(LDFLAGS) -o $@ +tls_pie_pic_test_SOURCES = tls_pie_pic_test.c +tls_pie_pic_test_OBJECTS = tls_pie_pic_test.$(OBJEXT) +tls_pie_pic_test_LDADD = $(LDADD) +tls_pie_pic_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +tls_pie_test_SOURCES = tls_pie_test.c +tls_pie_test_OBJECTS = tls_pie_test.$(OBJEXT) +tls_pie_test_LDADD = $(LDADD) +tls_pie_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__tls_shared_gd_to_ie_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_gd_to_ie_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_gd_to_ie_test_OBJECTS = \ $(am_tls_shared_gd_to_ie_test_OBJECTS) +tls_shared_gd_to_ie_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_shared_gd_to_ie_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_shared_gnu2_gd_to_ie_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am_tls_shared_gnu2_gd_to_ie_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_gnu2_gd_to_ie_test_OBJECTS = \ $(am_tls_shared_gnu2_gd_to_ie_test_OBJECTS) +tls_shared_gnu2_gd_to_ie_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(tls_shared_gnu2_gd_to_ie_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__tls_shared_gnu2_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_DESCRIPTORS_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@am_tls_shared_gnu2_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_gnu2_test_OBJECTS = $(am_tls_shared_gnu2_test_OBJECTS) +tls_shared_gnu2_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_shared_gnu2_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_shared_ie_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_ie_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_ie_test_OBJECTS = $(am_tls_shared_ie_test_OBJECTS) +tls_shared_ie_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_shared_ie_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_shared_nonpic_test_SOURCES_DIST = tls_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_nonpic_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_nonpic_test_OBJECTS = $(am_tls_shared_nonpic_test_OBJECTS) +tls_shared_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_shared_nonpic_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_shared_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_shared_test_OBJECTS = tls_test_main.$(OBJEXT) tls_shared_test_OBJECTS = $(am_tls_shared_test_OBJECTS) +tls_shared_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_shared_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_static_pic_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__objects_3 = tls_test_main.$(OBJEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@@STATIC_TLS_TRUE@@TLS_TRUE@am_tls_static_pic_test_OBJECTS = $(am__objects_3) @@ -583,6 +854,8 @@ tls_static_pic_test_OBJECTS = $(am_tls_static_pic_test_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_pic.o \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_file2_pic.o \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pic.o +tls_static_pic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_static_pic_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_static_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ tls_test_main.cc tls_test.h @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__objects_4 = \ @@ -593,6 +866,8 @@ am__tls_static_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ tls_static_test_OBJECTS = $(am_tls_static_test_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am__DEPENDENCIES_3 = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c.o +tls_static_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_static_test_LDFLAGS) $(LDFLAGS) -o $@ am__tls_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ tls_test_main.cc tls_test.h @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_test_OBJECTS = \ @@ -600,78 +875,123 @@ am__tls_test_SOURCES_DIST = tls_test.cc tls_test_file2.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_file2.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_main.$(OBJEXT) tls_test_OBJECTS = $(am_tls_test_OBJECTS) +tls_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(tls_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_mixed_2_shared_test_SOURCES_DIST = two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_mixed_2_shared_test_OBJECTS = two_file_test_main.$(OBJEXT) two_file_mixed_2_shared_test_OBJECTS = \ $(am_two_file_mixed_2_shared_test_OBJECTS) +two_file_mixed_2_shared_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_mixed_2_shared_test_LDFLAGS) $(LDFLAGS) \ + -o $@ am__two_file_mixed_shared_test_SOURCES_DIST = two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_mixed_shared_test_OBJECTS = two_file_test_main.$(OBJEXT) two_file_mixed_shared_test_OBJECTS = \ $(am_two_file_mixed_shared_test_OBJECTS) +two_file_mixed_shared_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_mixed_shared_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_pic_test_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_pic_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_pic_test_OBJECTS = $(am_two_file_pic_test_OBJECTS) +two_file_pic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_pic_test_LDFLAGS) $(LDFLAGS) -o $@ +two_file_pie_test_SOURCES = two_file_pie_test.c +two_file_pie_test_OBJECTS = two_file_pie_test.$(OBJEXT) +two_file_pie_test_LDADD = $(LDADD) +two_file_pie_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__two_file_relocatable_test_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_relocatable_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_relocatable_test_OBJECTS = \ $(am_two_file_relocatable_test_OBJECTS) +two_file_relocatable_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_relocatable_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_same_shared_nonpic_test_SOURCES_DIST = \ two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) two_file_same_shared_nonpic_test_OBJECTS = \ $(am_two_file_same_shared_nonpic_test_OBJECTS) +two_file_same_shared_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_same_shared_nonpic_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_same_shared_strip_test_SOURCES_DIST = \ two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_strip_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_same_shared_strip_test_OBJECTS = \ $(am_two_file_same_shared_strip_test_OBJECTS) +two_file_same_shared_strip_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_same_shared_strip_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_same_shared_test_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_same_shared_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_same_shared_test_OBJECTS = \ $(am_two_file_same_shared_test_OBJECTS) +two_file_same_shared_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_same_shared_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_separate_shared_12_nonpic_test_SOURCES_DIST = \ two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_12_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) two_file_separate_shared_12_nonpic_test_OBJECTS = \ $(am_two_file_separate_shared_12_nonpic_test_OBJECTS) +two_file_separate_shared_12_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_separate_shared_12_nonpic_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_separate_shared_12_test_SOURCES_DIST = \ two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_12_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_separate_shared_12_test_OBJECTS = \ $(am_two_file_separate_shared_12_test_OBJECTS) +two_file_separate_shared_12_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_separate_shared_12_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_separate_shared_21_nonpic_test_SOURCES_DIST = \ two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_21_nonpic_test_OBJECTS = two_file_test_main.$(OBJEXT) two_file_separate_shared_21_nonpic_test_OBJECTS = \ $(am_two_file_separate_shared_21_nonpic_test_OBJECTS) +two_file_separate_shared_21_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_separate_shared_21_nonpic_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_separate_shared_21_test_SOURCES_DIST = \ two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_separate_shared_21_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_separate_shared_21_test_OBJECTS = \ $(am_two_file_separate_shared_21_test_OBJECTS) +two_file_separate_shared_21_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_separate_shared_21_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_shared_1_nonpic_test_SOURCES_DIST = two_file_test_2.cc \ two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_nonpic_test_OBJECTS = two_file_test_2.$(OBJEXT) \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_1_nonpic_test_OBJECTS = \ $(am_two_file_shared_1_nonpic_test_OBJECTS) +two_file_shared_1_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_shared_1_nonpic_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_shared_1_pic_2_test_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_pic_2_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_1_pic_2_test_OBJECTS = \ $(am_two_file_shared_1_pic_2_test_OBJECTS) +two_file_shared_1_pic_2_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_shared_1_pic_2_test_LDFLAGS) $(LDFLAGS) \ + -o $@ am__two_file_shared_1_test_SOURCES_DIST = two_file_test_2.cc \ two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_1_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_1_test_OBJECTS = $(am_two_file_shared_1_test_OBJECTS) +two_file_shared_1_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_shared_1_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_shared_2_nonpic_test_SOURCES_DIST = two_file_test_1.cc \ two_file_test_1b.cc two_file_test_main.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_nonpic_test_OBJECTS = two_file_test_1.$(OBJEXT) \ @@ -679,11 +999,17 @@ am__two_file_shared_2_nonpic_test_SOURCES_DIST = two_file_test_1.cc \ @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_2_nonpic_test_OBJECTS = \ $(am_two_file_shared_2_nonpic_test_OBJECTS) +two_file_shared_2_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_shared_2_nonpic_test_LDFLAGS) \ + $(LDFLAGS) -o $@ am__two_file_shared_2_pic_1_test_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_pic_1_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_2_pic_1_test_OBJECTS = \ $(am_two_file_shared_2_pic_1_test_OBJECTS) +two_file_shared_2_pic_1_test_LINK = $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(two_file_shared_2_pic_1_test_LDFLAGS) $(LDFLAGS) \ + -o $@ am__two_file_shared_2_test_SOURCES_DIST = two_file_test_1.cc \ two_file_test_1b.cc two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_shared_2_test_OBJECTS = \ @@ -691,6 +1017,8 @@ am__two_file_shared_2_test_SOURCES_DIST = two_file_test_1.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_shared_2_test_OBJECTS = $(am_two_file_shared_2_test_OBJECTS) +two_file_shared_2_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_shared_2_test_LDFLAGS) $(LDFLAGS) -o $@ am__two_file_static_test_SOURCES_DIST = two_file_test_1.cc \ two_file_test_1b.cc two_file_test_2.cc two_file_test_main.cc \ two_file_test.h @@ -702,13 +1030,14 @@ am__two_file_static_test_SOURCES_DIST = two_file_test_1.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am_two_file_static_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(am__objects_5) two_file_static_test_OBJECTS = $(am_two_file_static_test_OBJECTS) -two_file_static_test_LDADD = $(LDADD) +two_file_static_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_static_test_LDFLAGS) $(LDFLAGS) -o $@ two_file_strip_test_SOURCES = two_file_strip_test.c two_file_strip_test_OBJECTS = two_file_strip_test.$(OBJEXT) two_file_strip_test_LDADD = $(LDADD) two_file_strip_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__two_file_test_SOURCES_DIST = two_file_test_1.cc \ two_file_test_1b.cc two_file_test_2.cc two_file_test_main.cc \ two_file_test.h @@ -718,52 +1047,77 @@ am__two_file_test_SOURCES_DIST = two_file_test_1.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) two_file_test_OBJECTS = $(am_two_file_test_OBJECTS) -two_file_test_LDADD = $(LDADD) +two_file_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(two_file_test_LDFLAGS) $(LDFLAGS) -o $@ am__ver_test_SOURCES_DIST = ver_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main.$(OBJEXT) ver_test_OBJECTS = $(am_ver_test_OBJECTS) +ver_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(ver_test_LDFLAGS) $(LDFLAGS) -o $@ +am__ver_test_11_SOURCES_DIST = ver_test_main_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_11_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main_2.$(OBJEXT) +ver_test_11_OBJECTS = $(am_ver_test_11_OBJECTS) +ver_test_11_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(ver_test_11_LDFLAGS) $(LDFLAGS) -o $@ am__ver_test_2_SOURCES_DIST = ver_test_main_2.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_2_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main_2.$(OBJEXT) ver_test_2_OBJECTS = $(am_ver_test_2_OBJECTS) +ver_test_2_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(ver_test_2_LDFLAGS) $(LDFLAGS) -o $@ am__ver_test_6_SOURCES_DIST = ver_test_6.c @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_6_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6.$(OBJEXT) ver_test_6_OBJECTS = $(am_ver_test_6_OBJECTS) +ver_test_6_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(ver_test_6_LDFLAGS) \ + $(LDFLAGS) -o $@ am__ver_test_8_SOURCES_DIST = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_8_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_main.$(OBJEXT) ver_test_8_OBJECTS = $(am_ver_test_8_OBJECTS) +ver_test_8_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(ver_test_8_LDFLAGS) $(LDFLAGS) -o $@ am__ver_test_9_SOURCES_DIST = ver_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ver_test_9_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_main.$(OBJEXT) ver_test_9_OBJECTS = $(am_ver_test_9_OBJECTS) +ver_test_9_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(ver_test_9_LDFLAGS) $(LDFLAGS) -o $@ am__weak_alias_test_SOURCES_DIST = weak_alias_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_alias_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_alias_test_main.$(OBJEXT) weak_alias_test_OBJECTS = $(am_weak_alias_test_OBJECTS) +weak_alias_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(weak_alias_test_LDFLAGS) $(LDFLAGS) -o $@ weak_plt_SOURCES = weak_plt.c weak_plt_OBJECTS = weak_plt.$(OBJEXT) weak_plt_LDADD = $(LDADD) weak_plt_DEPENDENCIES = libgoldtest.a ../libgold.a \ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__weak_test_SOURCES_DIST = weak_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_test.$(OBJEXT) weak_test_OBJECTS = $(am_weak_test_OBJECTS) -weak_test_LDADD = $(LDADD) +weak_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(weak_test_LDFLAGS) $(LDFLAGS) -o $@ am__weak_undef_nonpic_test_SOURCES_DIST = weak_undef_test.cc @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_undef_nonpic_test_OBJECTS = weak_undef_test.$(OBJEXT) weak_undef_nonpic_test_OBJECTS = $(am_weak_undef_nonpic_test_OBJECTS) +weak_undef_nonpic_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(weak_undef_nonpic_test_LDFLAGS) $(LDFLAGS) -o $@ am__weak_undef_test_SOURCES_DIST = weak_undef_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_weak_undef_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_undef_test.$(OBJEXT) weak_undef_test_OBJECTS = $(am_weak_undef_test_OBJECTS) -DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +weak_undef_test_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(weak_undef_test_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles +am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) @@ -773,25 +1127,32 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ +SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \ basic_static_pic_test.c basic_static_test.c basic_test.c \ $(binary_test_SOURCES) $(binary_unittest_SOURCES) \ - $(common_test_1_SOURCES) $(constructor_static_test_SOURCES) \ - $(constructor_test_SOURCES) $(copy_test_SOURCES) \ + $(common_test_1_SOURCES) $(common_test_2_SOURCES) \ + $(constructor_static_test_SOURCES) $(constructor_test_SOURCES) \ + $(copy_test_SOURCES) $(discard_locals_test_SOURCES) \ $(exception_same_shared_test_SOURCES) \ $(exception_separate_shared_12_test_SOURCES) \ $(exception_separate_shared_21_test_SOURCES) \ $(exception_shared_1_test_SOURCES) \ $(exception_shared_2_test_SOURCES) \ $(exception_static_test_SOURCES) $(exception_test_SOURCES) \ + $(exclude_libs_test_SOURCES) \ flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ flagstest_o_specialfile_and_compress_debug_sections.c \ - $(initpri1_SOURCES) $(justsyms_SOURCES) many_sections_r_test.c \ + $(initpri1_SOURCES) $(justsyms_SOURCES) $(large_SOURCES) \ + local_labels_test.c many_sections_r_test.c \ $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \ + permission_test.c plugin_test_1.c plugin_test_2.c \ + plugin_test_3.c plugin_test_4.c plugin_test_5.c \ $(protected_1_SOURCES) $(protected_2_SOURCES) \ $(relro_script_test_SOURCES) $(relro_test_SOURCES) \ $(script_test_1_SOURCES) $(script_test_2_SOURCES) \ - script_test_3.c $(tls_pic_test_SOURCES) \ + script_test_3.c $(searched_file_test_SOURCES) \ + $(thin_archive_test_1_SOURCES) $(thin_archive_test_2_SOURCES) \ + $(tls_pic_test_SOURCES) tls_pie_pic_test.c tls_pie_test.c \ $(tls_shared_gd_to_ie_test_SOURCES) \ $(tls_shared_gnu2_gd_to_ie_test_SOURCES) \ $(tls_shared_gnu2_test_SOURCES) $(tls_shared_ie_test_SOURCES) \ @@ -799,7 +1160,7 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(tls_static_pic_test_SOURCES) $(tls_static_test_SOURCES) \ $(tls_test_SOURCES) $(two_file_mixed_2_shared_test_SOURCES) \ $(two_file_mixed_shared_test_SOURCES) \ - $(two_file_pic_test_SOURCES) \ + $(two_file_pic_test_SOURCES) two_file_pie_test.c \ $(two_file_relocatable_test_SOURCES) \ $(two_file_same_shared_nonpic_test_SOURCES) \ $(two_file_same_shared_strip_test_SOURCES) \ @@ -816,17 +1177,20 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(two_file_shared_2_test_SOURCES) \ $(two_file_static_test_SOURCES) two_file_strip_test.c \ $(two_file_test_SOURCES) $(ver_test_SOURCES) \ - $(ver_test_2_SOURCES) $(ver_test_6_SOURCES) \ - $(ver_test_8_SOURCES) $(ver_test_9_SOURCES) \ - $(weak_alias_test_SOURCES) weak_plt.c $(weak_test_SOURCES) \ - $(weak_undef_nonpic_test_SOURCES) $(weak_undef_test_SOURCES) + $(ver_test_11_SOURCES) $(ver_test_2_SOURCES) \ + $(ver_test_6_SOURCES) $(ver_test_8_SOURCES) \ + $(ver_test_9_SOURCES) $(weak_alias_test_SOURCES) weak_plt.c \ + $(weak_test_SOURCES) $(weak_undef_nonpic_test_SOURCES) \ + $(weak_undef_test_SOURCES) DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ - basic_static_pic_test.c basic_static_test.c basic_test.c \ - $(am__binary_test_SOURCES_DIST) $(binary_unittest_SOURCES) \ - $(am__common_test_1_SOURCES_DIST) \ + basic_pie_test.c basic_static_pic_test.c basic_static_test.c \ + basic_test.c $(am__binary_test_SOURCES_DIST) \ + $(binary_unittest_SOURCES) $(am__common_test_1_SOURCES_DIST) \ + $(am__common_test_2_SOURCES_DIST) \ $(am__constructor_static_test_SOURCES_DIST) \ $(am__constructor_test_SOURCES_DIST) \ $(am__copy_test_SOURCES_DIST) \ + $(am__discard_locals_test_SOURCES_DIST) \ $(am__exception_same_shared_test_SOURCES_DIST) \ $(am__exception_separate_shared_12_test_SOURCES_DIST) \ $(am__exception_separate_shared_21_test_SOURCES_DIST) \ @@ -834,18 +1198,25 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(am__exception_shared_2_test_SOURCES_DIST) \ $(am__exception_static_test_SOURCES_DIST) \ $(am__exception_test_SOURCES_DIST) \ + $(am__exclude_libs_test_SOURCES_DIST) \ flagstest_compress_debug_sections.c flagstest_o_specialfile.c \ flagstest_o_specialfile_and_compress_debug_sections.c \ $(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \ + $(am__large_SOURCES_DIST) local_labels_test.c \ many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \ - $(object_unittest_SOURCES) $(am__protected_1_SOURCES_DIST) \ + $(object_unittest_SOURCES) permission_test.c plugin_test_1.c \ + plugin_test_2.c plugin_test_3.c plugin_test_4.c \ + plugin_test_5.c $(am__protected_1_SOURCES_DIST) \ $(am__protected_2_SOURCES_DIST) \ $(am__relro_script_test_SOURCES_DIST) \ $(am__relro_test_SOURCES_DIST) \ $(am__script_test_1_SOURCES_DIST) \ $(am__script_test_2_SOURCES_DIST) script_test_3.c \ - $(am__tls_pic_test_SOURCES_DIST) \ - $(am__tls_shared_gd_to_ie_test_SOURCES_DIST) \ + $(am__searched_file_test_SOURCES_DIST) \ + $(am__thin_archive_test_1_SOURCES_DIST) \ + $(am__thin_archive_test_2_SOURCES_DIST) \ + $(am__tls_pic_test_SOURCES_DIST) tls_pie_pic_test.c \ + tls_pie_test.c $(am__tls_shared_gd_to_ie_test_SOURCES_DIST) \ $(am__tls_shared_gnu2_gd_to_ie_test_SOURCES_DIST) \ $(am__tls_shared_gnu2_test_SOURCES_DIST) \ $(am__tls_shared_ie_test_SOURCES_DIST) \ @@ -856,7 +1227,7 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(am__tls_test_SOURCES_DIST) \ $(am__two_file_mixed_2_shared_test_SOURCES_DIST) \ $(am__two_file_mixed_shared_test_SOURCES_DIST) \ - $(am__two_file_pic_test_SOURCES_DIST) \ + $(am__two_file_pic_test_SOURCES_DIST) two_file_pie_test.c \ $(am__two_file_relocatable_test_SOURCES_DIST) \ $(am__two_file_same_shared_nonpic_test_SOURCES_DIST) \ $(am__two_file_same_shared_strip_test_SOURCES_DIST) \ @@ -873,18 +1244,19 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(am__two_file_shared_2_test_SOURCES_DIST) \ $(am__two_file_static_test_SOURCES_DIST) two_file_strip_test.c \ $(am__two_file_test_SOURCES_DIST) $(am__ver_test_SOURCES_DIST) \ - $(am__ver_test_2_SOURCES_DIST) $(am__ver_test_6_SOURCES_DIST) \ - $(am__ver_test_8_SOURCES_DIST) $(am__ver_test_9_SOURCES_DIST) \ + $(am__ver_test_11_SOURCES_DIST) $(am__ver_test_2_SOURCES_DIST) \ + $(am__ver_test_6_SOURCES_DIST) $(am__ver_test_8_SOURCES_DIST) \ + $(am__ver_test_9_SOURCES_DIST) \ $(am__weak_alias_test_SOURCES_DIST) weak_plt.c \ $(am__weak_test_SOURCES_DIST) \ $(am__weak_undef_nonpic_test_SOURCES_DIST) \ $(am__weak_undef_test_SOURCES_DIST) ETAGS = etags CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ @@ -895,8 +1267,6 @@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CONSTRUCTOR_PRIORITY_FALSE = @CONSTRUCTOR_PRIORITY_FALSE@ -CONSTRUCTOR_PRIORITY_TRUE = @CONSTRUCTOR_PRIORITY_TRUE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ @@ -912,15 +1282,11 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -FN_PTRS_IN_SO_WITHOUT_PIC_FALSE = @FN_PTRS_IN_SO_WITHOUT_PIC_FALSE@ -FN_PTRS_IN_SO_WITHOUT_PIC_TRUE = @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@ -GCC_FALSE = @GCC_FALSE@ -GCC_TRUE = @GCC_TRUE@ GENCAT = @GENCAT@ GMSGFMT = @GMSGFMT@ -HAVE_ZLIB_FALSE = @HAVE_ZLIB_FALSE@ -HAVE_ZLIB_TRUE = @HAVE_ZLIB_TRUE@ +GREP = @GREP@ INCINTL = @INCINTL@ +INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ @@ -935,23 +1301,19 @@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ -MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ -MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ -NATIVE_LINKER_FALSE = @NATIVE_LINKER_FALSE@ -NATIVE_LINKER_TRUE = @NATIVE_LINKER_TRUE@ NO_WERROR = @NO_WERROR@ OBJEXT = @OBJEXT@ -OMP_SUPPORT_FALSE = @OMP_SUPPORT_FALSE@ -OMP_SUPPORT_TRUE = @OMP_SUPPORT_TRUE@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSUB = @POSUB@ @@ -959,32 +1321,21 @@ RANDOM_SEED_CFLAGS = @RANDOM_SEED_CFLAGS@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ -STATIC_TLS_FALSE = @STATIC_TLS_FALSE@ -STATIC_TLS_TRUE = @STATIC_TLS_TRUE@ STRIP = @STRIP@ TARGETOBJS = @TARGETOBJS@ -THREADS_FALSE = @THREADS_FALSE@ -THREADS_TRUE = @THREADS_TRUE@ -TLS_DESCRIPTORS_FALSE = @TLS_DESCRIPTORS_FALSE@ -TLS_DESCRIPTORS_TRUE = @TLS_DESCRIPTORS_TRUE@ -TLS_FALSE = @TLS_FALSE@ -TLS_GNU2_DIALECT_FALSE = @TLS_GNU2_DIALECT_FALSE@ -TLS_GNU2_DIALECT_TRUE = @TLS_GNU2_DIALECT_TRUE@ -TLS_TRUE = @TLS_TRUE@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_CXXFLAGS = @WARN_CXXFLAGS@ XGETTEXT = @XGETTEXT@ YACC = @YACC@ +YFLAGS = @YFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ -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__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -996,39 +1347,54 @@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ +builddir = @builddir@ datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ +htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ +psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -AUTOMAKE_OPTIONS = +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Ignore warning about AM_PROG_CC_C_O due to large_CFLAGS +AUTOMAKE_OPTIONS = foreign -Wno-portability # The two_file_test tests -fmerge-constants, so we simply always turn # it on. This may need to be controlled by a configure option # eventually. +AM_CFLAGS = $(WARN_CFLAGS) $(LFS_CFLAGS) -fmerge-constants AM_CXXFLAGS = $(WARN_CXXFLAGS) $(LFS_CFLAGS) -fmerge-constants -INCLUDES = \ +AM_CPPFLAGS = \ -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../../include \ -I$(srcdir)/../../elfcpp -I.. \ -DLOCALEDIR="\"$(datadir)/locale\"" \ @@ -1038,6 +1404,10 @@ TEST_READELF = $(top_builddir)/../binutils/readelf TEST_OBJDUMP = $(top_builddir)/../binutils/objdump TEST_CXXFILT = $(top_builddir)/../binutils/cxxfilt TEST_STRIP = $(top_builddir)/../binutils/strip-new +TEST_AR = $(top_builddir)/../binutils/ar +TEST_NM = $(top_builddir)/../binutils/nm-new +TEST_AS = $(top_builddir)/../gas/as-new +@PLUGINS_TRUE@LIBDL = -ldl @THREADS_TRUE@THREADSLIB = -lpthread @OMP_SUPPORT_TRUE@TLS_TEST_C_CFLAGS = -fopenmp @@ -1045,14 +1415,19 @@ TEST_STRIP = $(top_builddir)/../binutils/strip-new # .o's), but not all of them (such as .so's and .err files). We # improve on that here. automake-1.9 info docs say "mostlyclean" is # the right choice for files 'make' builds that people rebuild. -MOSTLYCLEANFILES = *.so $(am__append_16) +MOSTLYCLEANFILES = *.so *.syms *.stdout $(am__append_3) \ + $(am__append_8) $(am__append_17) $(am__append_25) \ + $(am__append_29) $(am__append_34) $(am__append_37) \ + $(am__append_40) # We will add to these later, for each individual test. Note # that we add each test under check_SCRIPTS or check_PROGRAMS; # the TESTS variable is automatically populated from these. -check_SCRIPTS = $(am__append_6) -check_DATA = $(am__append_7) -BUILT_SOURCES = $(am__append_14) +check_SCRIPTS = $(am__append_1) $(am__append_23) $(am__append_27) \ + $(am__append_32) $(am__append_35) $(am__append_38) +check_DATA = $(am__append_2) $(am__append_24) $(am__append_28) \ + $(am__append_33) $(am__append_36) $(am__append_39) +BUILT_SOURCES = $(am__append_16) TESTS = $(check_SCRIPTS) $(check_PROGRAMS) # --------------------------------------------------------------------- @@ -1065,16 +1440,18 @@ DEPENDENCIES = \ libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ - $(THREADSLIB) + $(THREADSLIB) $(LIBDL) object_unittest_SOURCES = object_unittest.cc binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_SOURCES = constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_SOURCES = $(constructor_test_SOURCES) @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_DEPENDENCIES = $(constructor_test_DEPENDENCIES) @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_LDFLAGS = $(constructor_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_static_test_LDADD = $(constructor_test_LDADD) @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_SOURCES = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_1b.cc \ @@ -1084,9 +1461,11 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_SOURCES = $(two_file_test_SOURCES) @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_DEPENDENCIES = $(two_file_test_DEPENDENCIES) @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_LDFLAGS = $(two_file_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_static_test_LDADD = $(two_file_test_LDADD) @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_SOURCES = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pic_test_DEPENDENCIES = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o @@ -1103,7 +1482,7 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_test_LDADD = two_file_shared_2.so @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_SOURCES = two_file_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_DEPENDENCIES = \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_1.so two_file_test_1_pic.o two_file_test_1b_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld two_file_shared_2.so two_file_test_1_pic.o two_file_test_1b_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_pic_2_test_LDADD = two_file_test_1_pic.o two_file_test_1b_pic.o two_file_shared_2.so @@ -1194,6 +1573,11 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_SOURCES = common_test_1.c @GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_1_LDADD = +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2_SOURCES = common_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2_DEPENDENCIES = common_test_2.so common_test_3.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2_LDADD = common_test_2.so common_test_3.so @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_SOURCES = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_main.cc \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ exception_test_1.cc \ @@ -1202,9 +1586,11 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_SOURCES = $(exception_test_SOURCES) @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_DEPENDENCIES = $(exception_test_DEPENDENCIES) @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_LDFLAGS = $(exception_test_LDFLAGS) -static +@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_static_test_LDADD = $(exception_test_LDADD) @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_SOURCES = exception_test_2.cc exception_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_DEPENDENCIES = gcctestdir/ld exception_shared_1.so @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_shared_1_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @@ -1236,6 +1622,7 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_SOURCES = weak_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@weak_test_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_SOURCES = weak_undef_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_DEPENDENCIES = gcctestdir/ld weak_undef_lib.so alt/weak_undef_lib.so @GCC_TRUE@@NATIVE_LINKER_TRUE@weak_undef_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,alt @@ -1313,9 +1700,11 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_SOURCES = many_sections_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_DEPENDENCIES = gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_LDFLAGS = -Bgcctestdir/ -rdynamic +@GCC_TRUE@@NATIVE_LINKER_TRUE@many_sections_test_LDADD = @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_SOURCES = initpri1.c @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_DEPENDENCIES = gcctestdir/ld @CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_LDFLAGS = -Bgcctestdir/ +@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_SOURCES = ver_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @@ -1336,6 +1725,10 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_DEPENDENCIES = gcctestdir/ld ver_test_9.so @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_9_LDADD = ver_test_9.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_11_SOURCES = ver_test_main_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_11_DEPENDENCIES = gcctestdir/ld ver_test_11.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_11_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_11_LDADD = ver_test_11.a @GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1_SOURCES = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.cc protected_main_2.cc protected_main_3.cc @@ -1357,15 +1750,51 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_SOURCES = script_test_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_SOURCES = justsyms_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o @GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_LDADD = @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_SOURCES = binary_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_DEPENDENCIES = gcctestdir/ld binary.txt @GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_LDFLAGS = -Bgcctestdir/ -Wl,--format,binary,binary.txt,--format,elf +@GCC_TRUE@@NATIVE_LINKER_TRUE@binary_test_LDADD = +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_1_SOURCES = thin_archive_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_1_DEPENDENCIES = gcctestdir/ld libthin1.a alt/libthin2.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_1_LDFLAGS = -Bgcctestdir/ -Lalt +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_1_LDADD = libthin1.a -lthin2 +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_2_SOURCES = thin_archive_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_2_DEPENDENCIES = gcctestdir/ld libthinall.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_2_LDFLAGS = -Bgcctestdir/ -L. +@GCC_TRUE@@NATIVE_LINKER_TRUE@thin_archive_test_2_LDADD = -lthinall +@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test_SOURCES = exclude_libs_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test_DEPENDENCIES = gcctestdir/ld libexclude_libs_test_1.a \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ libexclude_libs_test_2.a alt/libexclude_libs_test_3.a + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test_LDFLAGS = -Bgcctestdir/ -L. -Lalt \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--exclude-libs,dummy:libexclude_libs_test_1 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--exclude-libs,libexclude_libs_test_3 + +@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test_LDADD = -lexclude_libs_test_1 -lexclude_libs_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/libexclude_libs_test_3.a + +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_SOURCES = discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test_LDFLAGS = -Bgcctestdir/ -Wl,--discard-locals +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_SOURCES = large.c +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_CFLAGS = -mcmodel=medium +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_DEPENDENCIES = gcctestdir/ld +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_LDFLAGS = -Bgcctestdir/ +@GCC_TRUE@@MCMODEL_MEDIUM_TRUE@@NATIVE_LINKER_TRUE@large_LDADD = +@GCC_TRUE@@NATIVE_LINKER_TRUE@searched_file_test_SOURCES = searched_file_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@searched_file_test_DEPENDENCIES = alt/searched_file_test_lib.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@searched_file_test_LDFLAGS = -Bgcctestdir/ -Lalt +@GCC_TRUE@@NATIVE_LINKER_TRUE@searched_file_test_LDADD = -l:searched_file_test_lib.a +@DEFAULT_TARGET_I386_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 +@DEFAULT_TARGET_X86_64_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -1375,14 +1804,14 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign testsuite/Makefile + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign testsuite/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -1400,6 +1829,7 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): clean-checkLIBRARIES: -test -z "$(check_LIBRARIES)" || rm -f $(check_LIBRARIES) @@ -1412,259 +1842,370 @@ clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) @GCC_FALSE@basic_pic_test$(EXEEXT): $(basic_pic_test_OBJECTS) $(basic_pic_test_DEPENDENCIES) @GCC_FALSE@ @rm -f basic_pic_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(basic_pic_test_LDFLAGS) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@basic_pic_test$(EXEEXT): $(basic_pic_test_OBJECTS) $(basic_pic_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f basic_pic_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(basic_pic_test_LDFLAGS) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_pic_test_OBJECTS) $(basic_pic_test_LDADD) $(LIBS) +@GCC_FALSE@basic_pie_test$(EXEEXT): $(basic_pie_test_OBJECTS) $(basic_pie_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f basic_pie_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(basic_pie_test_OBJECTS) $(basic_pie_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@basic_pie_test$(EXEEXT): $(basic_pie_test_OBJECTS) $(basic_pie_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f basic_pie_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_pie_test_OBJECTS) $(basic_pie_test_LDADD) $(LIBS) @GCC_FALSE@basic_static_pic_test$(EXEEXT): $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_DEPENDENCIES) @GCC_FALSE@ @rm -f basic_static_pic_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(basic_static_pic_test_LDFLAGS) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@basic_static_pic_test$(EXEEXT): $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f basic_static_pic_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_pic_test_LDFLAGS) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_pic_test_OBJECTS) $(basic_static_pic_test_LDADD) $(LIBS) @GCC_FALSE@basic_static_test$(EXEEXT): $(basic_static_test_OBJECTS) $(basic_static_test_DEPENDENCIES) @GCC_FALSE@ @rm -f basic_static_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(basic_static_test_LDFLAGS) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@basic_static_test$(EXEEXT): $(basic_static_test_OBJECTS) $(basic_static_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f basic_static_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_test_LDFLAGS) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_static_test_OBJECTS) $(basic_static_test_LDADD) $(LIBS) @GCC_FALSE@basic_test$(EXEEXT): $(basic_test_OBJECTS) $(basic_test_DEPENDENCIES) @GCC_FALSE@ @rm -f basic_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(basic_test_LDFLAGS) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@basic_test$(EXEEXT): $(basic_test_OBJECTS) $(basic_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f basic_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(basic_test_LDFLAGS) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(basic_test_OBJECTS) $(basic_test_LDADD) $(LIBS) binary_test$(EXEEXT): $(binary_test_OBJECTS) $(binary_test_DEPENDENCIES) @rm -f binary_test$(EXEEXT) - $(CXXLINK) $(binary_test_LDFLAGS) $(binary_test_OBJECTS) $(binary_test_LDADD) $(LIBS) + $(binary_test_LINK) $(binary_test_OBJECTS) $(binary_test_LDADD) $(LIBS) binary_unittest$(EXEEXT): $(binary_unittest_OBJECTS) $(binary_unittest_DEPENDENCIES) @rm -f binary_unittest$(EXEEXT) - $(CXXLINK) $(binary_unittest_LDFLAGS) $(binary_unittest_OBJECTS) $(binary_unittest_LDADD) $(LIBS) + $(CXXLINK) $(binary_unittest_OBJECTS) $(binary_unittest_LDADD) $(LIBS) common_test_1$(EXEEXT): $(common_test_1_OBJECTS) $(common_test_1_DEPENDENCIES) @rm -f common_test_1$(EXEEXT) - $(LINK) $(common_test_1_LDFLAGS) $(common_test_1_OBJECTS) $(common_test_1_LDADD) $(LIBS) + $(common_test_1_LINK) $(common_test_1_OBJECTS) $(common_test_1_LDADD) $(LIBS) +common_test_2$(EXEEXT): $(common_test_2_OBJECTS) $(common_test_2_DEPENDENCIES) + @rm -f common_test_2$(EXEEXT) + $(common_test_2_LINK) $(common_test_2_OBJECTS) $(common_test_2_LDADD) $(LIBS) constructor_static_test$(EXEEXT): $(constructor_static_test_OBJECTS) $(constructor_static_test_DEPENDENCIES) @rm -f constructor_static_test$(EXEEXT) - $(CXXLINK) $(constructor_static_test_LDFLAGS) $(constructor_static_test_OBJECTS) $(constructor_static_test_LDADD) $(LIBS) + $(constructor_static_test_LINK) $(constructor_static_test_OBJECTS) $(constructor_static_test_LDADD) $(LIBS) constructor_test$(EXEEXT): $(constructor_test_OBJECTS) $(constructor_test_DEPENDENCIES) @rm -f constructor_test$(EXEEXT) - $(CXXLINK) $(constructor_test_LDFLAGS) $(constructor_test_OBJECTS) $(constructor_test_LDADD) $(LIBS) + $(constructor_test_LINK) $(constructor_test_OBJECTS) $(constructor_test_LDADD) $(LIBS) copy_test$(EXEEXT): $(copy_test_OBJECTS) $(copy_test_DEPENDENCIES) @rm -f copy_test$(EXEEXT) - $(CXXLINK) $(copy_test_LDFLAGS) $(copy_test_OBJECTS) $(copy_test_LDADD) $(LIBS) + $(copy_test_LINK) $(copy_test_OBJECTS) $(copy_test_LDADD) $(LIBS) +discard_locals_test$(EXEEXT): $(discard_locals_test_OBJECTS) $(discard_locals_test_DEPENDENCIES) + @rm -f discard_locals_test$(EXEEXT) + $(discard_locals_test_LINK) $(discard_locals_test_OBJECTS) $(discard_locals_test_LDADD) $(LIBS) exception_same_shared_test$(EXEEXT): $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_DEPENDENCIES) @rm -f exception_same_shared_test$(EXEEXT) - $(CXXLINK) $(exception_same_shared_test_LDFLAGS) $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_LDADD) $(LIBS) + $(exception_same_shared_test_LINK) $(exception_same_shared_test_OBJECTS) $(exception_same_shared_test_LDADD) $(LIBS) exception_separate_shared_12_test$(EXEEXT): $(exception_separate_shared_12_test_OBJECTS) $(exception_separate_shared_12_test_DEPENDENCIES) @rm -f exception_separate_shared_12_test$(EXEEXT) - $(CXXLINK) $(exception_separate_shared_12_test_LDFLAGS) $(exception_separate_shared_12_test_OBJECTS) $(exception_separate_shared_12_test_LDADD) $(LIBS) + $(exception_separate_shared_12_test_LINK) $(exception_separate_shared_12_test_OBJECTS) $(exception_separate_shared_12_test_LDADD) $(LIBS) exception_separate_shared_21_test$(EXEEXT): $(exception_separate_shared_21_test_OBJECTS) $(exception_separate_shared_21_test_DEPENDENCIES) @rm -f exception_separate_shared_21_test$(EXEEXT) - $(CXXLINK) $(exception_separate_shared_21_test_LDFLAGS) $(exception_separate_shared_21_test_OBJECTS) $(exception_separate_shared_21_test_LDADD) $(LIBS) + $(exception_separate_shared_21_test_LINK) $(exception_separate_shared_21_test_OBJECTS) $(exception_separate_shared_21_test_LDADD) $(LIBS) exception_shared_1_test$(EXEEXT): $(exception_shared_1_test_OBJECTS) $(exception_shared_1_test_DEPENDENCIES) @rm -f exception_shared_1_test$(EXEEXT) - $(CXXLINK) $(exception_shared_1_test_LDFLAGS) $(exception_shared_1_test_OBJECTS) $(exception_shared_1_test_LDADD) $(LIBS) + $(exception_shared_1_test_LINK) $(exception_shared_1_test_OBJECTS) $(exception_shared_1_test_LDADD) $(LIBS) exception_shared_2_test$(EXEEXT): $(exception_shared_2_test_OBJECTS) $(exception_shared_2_test_DEPENDENCIES) @rm -f exception_shared_2_test$(EXEEXT) - $(CXXLINK) $(exception_shared_2_test_LDFLAGS) $(exception_shared_2_test_OBJECTS) $(exception_shared_2_test_LDADD) $(LIBS) + $(exception_shared_2_test_LINK) $(exception_shared_2_test_OBJECTS) $(exception_shared_2_test_LDADD) $(LIBS) exception_static_test$(EXEEXT): $(exception_static_test_OBJECTS) $(exception_static_test_DEPENDENCIES) @rm -f exception_static_test$(EXEEXT) - $(CXXLINK) $(exception_static_test_LDFLAGS) $(exception_static_test_OBJECTS) $(exception_static_test_LDADD) $(LIBS) + $(exception_static_test_LINK) $(exception_static_test_OBJECTS) $(exception_static_test_LDADD) $(LIBS) exception_test$(EXEEXT): $(exception_test_OBJECTS) $(exception_test_DEPENDENCIES) @rm -f exception_test$(EXEEXT) - $(CXXLINK) $(exception_test_LDFLAGS) $(exception_test_OBJECTS) $(exception_test_LDADD) $(LIBS) + $(exception_test_LINK) $(exception_test_OBJECTS) $(exception_test_LDADD) $(LIBS) +exclude_libs_test$(EXEEXT): $(exclude_libs_test_OBJECTS) $(exclude_libs_test_DEPENDENCIES) + @rm -f exclude_libs_test$(EXEEXT) + $(exclude_libs_test_LINK) $(exclude_libs_test_OBJECTS) $(exclude_libs_test_LDADD) $(LIBS) @GCC_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) @GCC_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) -@GCC_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) @HAVE_ZLIB_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) @HAVE_ZLIB_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) -@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@flagstest_compress_debug_sections$(EXEEXT): $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f flagstest_compress_debug_sections$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_compress_debug_sections_LDFLAGS) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_compress_debug_sections_OBJECTS) $(flagstest_compress_debug_sections_LDADD) $(LIBS) @GCC_FALSE@flagstest_o_specialfile$(EXEEXT): $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_DEPENDENCIES) @GCC_FALSE@ @rm -f flagstest_o_specialfile$(EXEEXT) -@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_LDFLAGS) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@flagstest_o_specialfile$(EXEEXT): $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_LDFLAGS) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_OBJECTS) $(flagstest_o_specialfile_LDADD) $(LIBS) @GCC_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) @GCC_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) -@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) @HAVE_ZLIB_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) @HAVE_ZLIB_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) -@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +@HAVE_ZLIB_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS) initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES) @rm -f initpri1$(EXEEXT) - $(LINK) $(initpri1_LDFLAGS) $(initpri1_OBJECTS) $(initpri1_LDADD) $(LIBS) + $(initpri1_LINK) $(initpri1_OBJECTS) $(initpri1_LDADD) $(LIBS) justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES) @rm -f justsyms$(EXEEXT) - $(CXXLINK) $(justsyms_LDFLAGS) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS) + $(justsyms_LINK) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS) +large$(EXEEXT): $(large_OBJECTS) $(large_DEPENDENCIES) + @rm -f large$(EXEEXT) + $(large_LINK) $(large_OBJECTS) $(large_LDADD) $(LIBS) +@GCC_FALSE@local_labels_test$(EXEEXT): $(local_labels_test_OBJECTS) $(local_labels_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f local_labels_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(local_labels_test_OBJECTS) $(local_labels_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@local_labels_test$(EXEEXT): $(local_labels_test_OBJECTS) $(local_labels_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f local_labels_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(local_labels_test_OBJECTS) $(local_labels_test_LDADD) $(LIBS) @GCC_FALSE@many_sections_r_test$(EXEEXT): $(many_sections_r_test_OBJECTS) $(many_sections_r_test_DEPENDENCIES) @GCC_FALSE@ @rm -f many_sections_r_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(many_sections_r_test_LDFLAGS) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@many_sections_r_test$(EXEEXT): $(many_sections_r_test_OBJECTS) $(many_sections_r_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f many_sections_r_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(many_sections_r_test_LDFLAGS) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(many_sections_r_test_OBJECTS) $(many_sections_r_test_LDADD) $(LIBS) many_sections_test$(EXEEXT): $(many_sections_test_OBJECTS) $(many_sections_test_DEPENDENCIES) @rm -f many_sections_test$(EXEEXT) - $(CXXLINK) $(many_sections_test_LDFLAGS) $(many_sections_test_OBJECTS) $(many_sections_test_LDADD) $(LIBS) + $(many_sections_test_LINK) $(many_sections_test_OBJECTS) $(many_sections_test_LDADD) $(LIBS) object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES) @rm -f object_unittest$(EXEEXT) - $(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS) + $(CXXLINK) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS) +@GCC_FALSE@permission_test$(EXEEXT): $(permission_test_OBJECTS) $(permission_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f permission_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(permission_test_OBJECTS) $(permission_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@permission_test$(EXEEXT): $(permission_test_OBJECTS) $(permission_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f permission_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(permission_test_OBJECTS) $(permission_test_LDADD) $(LIBS) +@GCC_FALSE@plugin_test_1$(EXEEXT): $(plugin_test_1_OBJECTS) $(plugin_test_1_DEPENDENCIES) +@GCC_FALSE@ @rm -f plugin_test_1$(EXEEXT) +@GCC_FALSE@ $(LINK) $(plugin_test_1_OBJECTS) $(plugin_test_1_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@plugin_test_1$(EXEEXT): $(plugin_test_1_OBJECTS) $(plugin_test_1_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f plugin_test_1$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(plugin_test_1_OBJECTS) $(plugin_test_1_LDADD) $(LIBS) +@PLUGINS_FALSE@plugin_test_1$(EXEEXT): $(plugin_test_1_OBJECTS) $(plugin_test_1_DEPENDENCIES) +@PLUGINS_FALSE@ @rm -f plugin_test_1$(EXEEXT) +@PLUGINS_FALSE@ $(LINK) $(plugin_test_1_OBJECTS) $(plugin_test_1_LDADD) $(LIBS) +@GCC_FALSE@plugin_test_2$(EXEEXT): $(plugin_test_2_OBJECTS) $(plugin_test_2_DEPENDENCIES) +@GCC_FALSE@ @rm -f plugin_test_2$(EXEEXT) +@GCC_FALSE@ $(LINK) $(plugin_test_2_OBJECTS) $(plugin_test_2_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@plugin_test_2$(EXEEXT): $(plugin_test_2_OBJECTS) $(plugin_test_2_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f plugin_test_2$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(plugin_test_2_OBJECTS) $(plugin_test_2_LDADD) $(LIBS) +@PLUGINS_FALSE@plugin_test_2$(EXEEXT): $(plugin_test_2_OBJECTS) $(plugin_test_2_DEPENDENCIES) +@PLUGINS_FALSE@ @rm -f plugin_test_2$(EXEEXT) +@PLUGINS_FALSE@ $(LINK) $(plugin_test_2_OBJECTS) $(plugin_test_2_LDADD) $(LIBS) +@GCC_FALSE@plugin_test_3$(EXEEXT): $(plugin_test_3_OBJECTS) $(plugin_test_3_DEPENDENCIES) +@GCC_FALSE@ @rm -f plugin_test_3$(EXEEXT) +@GCC_FALSE@ $(LINK) $(plugin_test_3_OBJECTS) $(plugin_test_3_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@plugin_test_3$(EXEEXT): $(plugin_test_3_OBJECTS) $(plugin_test_3_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f plugin_test_3$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(plugin_test_3_OBJECTS) $(plugin_test_3_LDADD) $(LIBS) +@PLUGINS_FALSE@plugin_test_3$(EXEEXT): $(plugin_test_3_OBJECTS) $(plugin_test_3_DEPENDENCIES) +@PLUGINS_FALSE@ @rm -f plugin_test_3$(EXEEXT) +@PLUGINS_FALSE@ $(LINK) $(plugin_test_3_OBJECTS) $(plugin_test_3_LDADD) $(LIBS) +@GCC_FALSE@plugin_test_4$(EXEEXT): $(plugin_test_4_OBJECTS) $(plugin_test_4_DEPENDENCIES) +@GCC_FALSE@ @rm -f plugin_test_4$(EXEEXT) +@GCC_FALSE@ $(LINK) $(plugin_test_4_OBJECTS) $(plugin_test_4_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@plugin_test_4$(EXEEXT): $(plugin_test_4_OBJECTS) $(plugin_test_4_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f plugin_test_4$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(plugin_test_4_OBJECTS) $(plugin_test_4_LDADD) $(LIBS) +@PLUGINS_FALSE@plugin_test_4$(EXEEXT): $(plugin_test_4_OBJECTS) $(plugin_test_4_DEPENDENCIES) +@PLUGINS_FALSE@ @rm -f plugin_test_4$(EXEEXT) +@PLUGINS_FALSE@ $(LINK) $(plugin_test_4_OBJECTS) $(plugin_test_4_LDADD) $(LIBS) +@GCC_FALSE@plugin_test_5$(EXEEXT): $(plugin_test_5_OBJECTS) $(plugin_test_5_DEPENDENCIES) +@GCC_FALSE@ @rm -f plugin_test_5$(EXEEXT) +@GCC_FALSE@ $(LINK) $(plugin_test_5_OBJECTS) $(plugin_test_5_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@plugin_test_5$(EXEEXT): $(plugin_test_5_OBJECTS) $(plugin_test_5_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f plugin_test_5$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(plugin_test_5_OBJECTS) $(plugin_test_5_LDADD) $(LIBS) +@PLUGINS_FALSE@plugin_test_5$(EXEEXT): $(plugin_test_5_OBJECTS) $(plugin_test_5_DEPENDENCIES) +@PLUGINS_FALSE@ @rm -f plugin_test_5$(EXEEXT) +@PLUGINS_FALSE@ $(LINK) $(plugin_test_5_OBJECTS) $(plugin_test_5_LDADD) $(LIBS) protected_1$(EXEEXT): $(protected_1_OBJECTS) $(protected_1_DEPENDENCIES) @rm -f protected_1$(EXEEXT) - $(CXXLINK) $(protected_1_LDFLAGS) $(protected_1_OBJECTS) $(protected_1_LDADD) $(LIBS) + $(protected_1_LINK) $(protected_1_OBJECTS) $(protected_1_LDADD) $(LIBS) protected_2$(EXEEXT): $(protected_2_OBJECTS) $(protected_2_DEPENDENCIES) @rm -f protected_2$(EXEEXT) - $(CXXLINK) $(protected_2_LDFLAGS) $(protected_2_OBJECTS) $(protected_2_LDADD) $(LIBS) + $(protected_2_LINK) $(protected_2_OBJECTS) $(protected_2_LDADD) $(LIBS) relro_script_test$(EXEEXT): $(relro_script_test_OBJECTS) $(relro_script_test_DEPENDENCIES) @rm -f relro_script_test$(EXEEXT) - $(CXXLINK) $(relro_script_test_LDFLAGS) $(relro_script_test_OBJECTS) $(relro_script_test_LDADD) $(LIBS) + $(relro_script_test_LINK) $(relro_script_test_OBJECTS) $(relro_script_test_LDADD) $(LIBS) relro_test$(EXEEXT): $(relro_test_OBJECTS) $(relro_test_DEPENDENCIES) @rm -f relro_test$(EXEEXT) - $(CXXLINK) $(relro_test_LDFLAGS) $(relro_test_OBJECTS) $(relro_test_LDADD) $(LIBS) + $(relro_test_LINK) $(relro_test_OBJECTS) $(relro_test_LDADD) $(LIBS) script_test_1$(EXEEXT): $(script_test_1_OBJECTS) $(script_test_1_DEPENDENCIES) @rm -f script_test_1$(EXEEXT) - $(CXXLINK) $(script_test_1_LDFLAGS) $(script_test_1_OBJECTS) $(script_test_1_LDADD) $(LIBS) + $(script_test_1_LINK) $(script_test_1_OBJECTS) $(script_test_1_LDADD) $(LIBS) script_test_2$(EXEEXT): $(script_test_2_OBJECTS) $(script_test_2_DEPENDENCIES) @rm -f script_test_2$(EXEEXT) - $(CXXLINK) $(script_test_2_LDFLAGS) $(script_test_2_OBJECTS) $(script_test_2_LDADD) $(LIBS) + $(script_test_2_LINK) $(script_test_2_OBJECTS) $(script_test_2_LDADD) $(LIBS) @GCC_FALSE@script_test_3$(EXEEXT): $(script_test_3_OBJECTS) $(script_test_3_DEPENDENCIES) @GCC_FALSE@ @rm -f script_test_3$(EXEEXT) -@GCC_FALSE@ $(LINK) $(script_test_3_LDFLAGS) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@script_test_3$(EXEEXT): $(script_test_3_OBJECTS) $(script_test_3_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f script_test_3$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_3_LDFLAGS) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(script_test_3_OBJECTS) $(script_test_3_LDADD) $(LIBS) +searched_file_test$(EXEEXT): $(searched_file_test_OBJECTS) $(searched_file_test_DEPENDENCIES) + @rm -f searched_file_test$(EXEEXT) + $(searched_file_test_LINK) $(searched_file_test_OBJECTS) $(searched_file_test_LDADD) $(LIBS) +thin_archive_test_1$(EXEEXT): $(thin_archive_test_1_OBJECTS) $(thin_archive_test_1_DEPENDENCIES) + @rm -f thin_archive_test_1$(EXEEXT) + $(thin_archive_test_1_LINK) $(thin_archive_test_1_OBJECTS) $(thin_archive_test_1_LDADD) $(LIBS) +thin_archive_test_2$(EXEEXT): $(thin_archive_test_2_OBJECTS) $(thin_archive_test_2_DEPENDENCIES) + @rm -f thin_archive_test_2$(EXEEXT) + $(thin_archive_test_2_LINK) $(thin_archive_test_2_OBJECTS) $(thin_archive_test_2_LDADD) $(LIBS) tls_pic_test$(EXEEXT): $(tls_pic_test_OBJECTS) $(tls_pic_test_DEPENDENCIES) @rm -f tls_pic_test$(EXEEXT) - $(CXXLINK) $(tls_pic_test_LDFLAGS) $(tls_pic_test_OBJECTS) $(tls_pic_test_LDADD) $(LIBS) + $(tls_pic_test_LINK) $(tls_pic_test_OBJECTS) $(tls_pic_test_LDADD) $(LIBS) +@GCC_FALSE@tls_pie_pic_test$(EXEEXT): $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f tls_pie_pic_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@tls_pie_pic_test$(EXEEXT): $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f tls_pie_pic_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_LDADD) $(LIBS) +@TLS_FALSE@tls_pie_pic_test$(EXEEXT): $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_DEPENDENCIES) +@TLS_FALSE@ @rm -f tls_pie_pic_test$(EXEEXT) +@TLS_FALSE@ $(LINK) $(tls_pie_pic_test_OBJECTS) $(tls_pie_pic_test_LDADD) $(LIBS) +@GCC_FALSE@tls_pie_test$(EXEEXT): $(tls_pie_test_OBJECTS) $(tls_pie_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f tls_pie_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(tls_pie_test_OBJECTS) $(tls_pie_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@tls_pie_test$(EXEEXT): $(tls_pie_test_OBJECTS) $(tls_pie_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f tls_pie_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(tls_pie_test_OBJECTS) $(tls_pie_test_LDADD) $(LIBS) +@TLS_FALSE@tls_pie_test$(EXEEXT): $(tls_pie_test_OBJECTS) $(tls_pie_test_DEPENDENCIES) +@TLS_FALSE@ @rm -f tls_pie_test$(EXEEXT) +@TLS_FALSE@ $(LINK) $(tls_pie_test_OBJECTS) $(tls_pie_test_LDADD) $(LIBS) tls_shared_gd_to_ie_test$(EXEEXT): $(tls_shared_gd_to_ie_test_OBJECTS) $(tls_shared_gd_to_ie_test_DEPENDENCIES) @rm -f tls_shared_gd_to_ie_test$(EXEEXT) - $(CXXLINK) $(tls_shared_gd_to_ie_test_LDFLAGS) $(tls_shared_gd_to_ie_test_OBJECTS) $(tls_shared_gd_to_ie_test_LDADD) $(LIBS) + $(tls_shared_gd_to_ie_test_LINK) $(tls_shared_gd_to_ie_test_OBJECTS) $(tls_shared_gd_to_ie_test_LDADD) $(LIBS) tls_shared_gnu2_gd_to_ie_test$(EXEEXT): $(tls_shared_gnu2_gd_to_ie_test_OBJECTS) $(tls_shared_gnu2_gd_to_ie_test_DEPENDENCIES) @rm -f tls_shared_gnu2_gd_to_ie_test$(EXEEXT) - $(CXXLINK) $(tls_shared_gnu2_gd_to_ie_test_LDFLAGS) $(tls_shared_gnu2_gd_to_ie_test_OBJECTS) $(tls_shared_gnu2_gd_to_ie_test_LDADD) $(LIBS) + $(tls_shared_gnu2_gd_to_ie_test_LINK) $(tls_shared_gnu2_gd_to_ie_test_OBJECTS) $(tls_shared_gnu2_gd_to_ie_test_LDADD) $(LIBS) tls_shared_gnu2_test$(EXEEXT): $(tls_shared_gnu2_test_OBJECTS) $(tls_shared_gnu2_test_DEPENDENCIES) @rm -f tls_shared_gnu2_test$(EXEEXT) - $(CXXLINK) $(tls_shared_gnu2_test_LDFLAGS) $(tls_shared_gnu2_test_OBJECTS) $(tls_shared_gnu2_test_LDADD) $(LIBS) + $(tls_shared_gnu2_test_LINK) $(tls_shared_gnu2_test_OBJECTS) $(tls_shared_gnu2_test_LDADD) $(LIBS) tls_shared_ie_test$(EXEEXT): $(tls_shared_ie_test_OBJECTS) $(tls_shared_ie_test_DEPENDENCIES) @rm -f tls_shared_ie_test$(EXEEXT) - $(CXXLINK) $(tls_shared_ie_test_LDFLAGS) $(tls_shared_ie_test_OBJECTS) $(tls_shared_ie_test_LDADD) $(LIBS) + $(tls_shared_ie_test_LINK) $(tls_shared_ie_test_OBJECTS) $(tls_shared_ie_test_LDADD) $(LIBS) tls_shared_nonpic_test$(EXEEXT): $(tls_shared_nonpic_test_OBJECTS) $(tls_shared_nonpic_test_DEPENDENCIES) @rm -f tls_shared_nonpic_test$(EXEEXT) - $(CXXLINK) $(tls_shared_nonpic_test_LDFLAGS) $(tls_shared_nonpic_test_OBJECTS) $(tls_shared_nonpic_test_LDADD) $(LIBS) + $(tls_shared_nonpic_test_LINK) $(tls_shared_nonpic_test_OBJECTS) $(tls_shared_nonpic_test_LDADD) $(LIBS) tls_shared_test$(EXEEXT): $(tls_shared_test_OBJECTS) $(tls_shared_test_DEPENDENCIES) @rm -f tls_shared_test$(EXEEXT) - $(CXXLINK) $(tls_shared_test_LDFLAGS) $(tls_shared_test_OBJECTS) $(tls_shared_test_LDADD) $(LIBS) + $(tls_shared_test_LINK) $(tls_shared_test_OBJECTS) $(tls_shared_test_LDADD) $(LIBS) tls_static_pic_test$(EXEEXT): $(tls_static_pic_test_OBJECTS) $(tls_static_pic_test_DEPENDENCIES) @rm -f tls_static_pic_test$(EXEEXT) - $(CXXLINK) $(tls_static_pic_test_LDFLAGS) $(tls_static_pic_test_OBJECTS) $(tls_static_pic_test_LDADD) $(LIBS) + $(tls_static_pic_test_LINK) $(tls_static_pic_test_OBJECTS) $(tls_static_pic_test_LDADD) $(LIBS) tls_static_test$(EXEEXT): $(tls_static_test_OBJECTS) $(tls_static_test_DEPENDENCIES) @rm -f tls_static_test$(EXEEXT) - $(CXXLINK) $(tls_static_test_LDFLAGS) $(tls_static_test_OBJECTS) $(tls_static_test_LDADD) $(LIBS) + $(tls_static_test_LINK) $(tls_static_test_OBJECTS) $(tls_static_test_LDADD) $(LIBS) tls_test$(EXEEXT): $(tls_test_OBJECTS) $(tls_test_DEPENDENCIES) @rm -f tls_test$(EXEEXT) - $(CXXLINK) $(tls_test_LDFLAGS) $(tls_test_OBJECTS) $(tls_test_LDADD) $(LIBS) + $(tls_test_LINK) $(tls_test_OBJECTS) $(tls_test_LDADD) $(LIBS) two_file_mixed_2_shared_test$(EXEEXT): $(two_file_mixed_2_shared_test_OBJECTS) $(two_file_mixed_2_shared_test_DEPENDENCIES) @rm -f two_file_mixed_2_shared_test$(EXEEXT) - $(CXXLINK) $(two_file_mixed_2_shared_test_LDFLAGS) $(two_file_mixed_2_shared_test_OBJECTS) $(two_file_mixed_2_shared_test_LDADD) $(LIBS) + $(two_file_mixed_2_shared_test_LINK) $(two_file_mixed_2_shared_test_OBJECTS) $(two_file_mixed_2_shared_test_LDADD) $(LIBS) two_file_mixed_shared_test$(EXEEXT): $(two_file_mixed_shared_test_OBJECTS) $(two_file_mixed_shared_test_DEPENDENCIES) @rm -f two_file_mixed_shared_test$(EXEEXT) - $(CXXLINK) $(two_file_mixed_shared_test_LDFLAGS) $(two_file_mixed_shared_test_OBJECTS) $(two_file_mixed_shared_test_LDADD) $(LIBS) + $(two_file_mixed_shared_test_LINK) $(two_file_mixed_shared_test_OBJECTS) $(two_file_mixed_shared_test_LDADD) $(LIBS) two_file_pic_test$(EXEEXT): $(two_file_pic_test_OBJECTS) $(two_file_pic_test_DEPENDENCIES) @rm -f two_file_pic_test$(EXEEXT) - $(CXXLINK) $(two_file_pic_test_LDFLAGS) $(two_file_pic_test_OBJECTS) $(two_file_pic_test_LDADD) $(LIBS) + $(two_file_pic_test_LINK) $(two_file_pic_test_OBJECTS) $(two_file_pic_test_LDADD) $(LIBS) +@GCC_FALSE@two_file_pie_test$(EXEEXT): $(two_file_pie_test_OBJECTS) $(two_file_pie_test_DEPENDENCIES) +@GCC_FALSE@ @rm -f two_file_pie_test$(EXEEXT) +@GCC_FALSE@ $(LINK) $(two_file_pie_test_OBJECTS) $(two_file_pie_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@two_file_pie_test$(EXEEXT): $(two_file_pie_test_OBJECTS) $(two_file_pie_test_DEPENDENCIES) +@NATIVE_LINKER_FALSE@ @rm -f two_file_pie_test$(EXEEXT) +@NATIVE_LINKER_FALSE@ $(LINK) $(two_file_pie_test_OBJECTS) $(two_file_pie_test_LDADD) $(LIBS) two_file_relocatable_test$(EXEEXT): $(two_file_relocatable_test_OBJECTS) $(two_file_relocatable_test_DEPENDENCIES) @rm -f two_file_relocatable_test$(EXEEXT) - $(CXXLINK) $(two_file_relocatable_test_LDFLAGS) $(two_file_relocatable_test_OBJECTS) $(two_file_relocatable_test_LDADD) $(LIBS) + $(two_file_relocatable_test_LINK) $(two_file_relocatable_test_OBJECTS) $(two_file_relocatable_test_LDADD) $(LIBS) two_file_same_shared_nonpic_test$(EXEEXT): $(two_file_same_shared_nonpic_test_OBJECTS) $(two_file_same_shared_nonpic_test_DEPENDENCIES) @rm -f two_file_same_shared_nonpic_test$(EXEEXT) - $(CXXLINK) $(two_file_same_shared_nonpic_test_LDFLAGS) $(two_file_same_shared_nonpic_test_OBJECTS) $(two_file_same_shared_nonpic_test_LDADD) $(LIBS) + $(two_file_same_shared_nonpic_test_LINK) $(two_file_same_shared_nonpic_test_OBJECTS) $(two_file_same_shared_nonpic_test_LDADD) $(LIBS) two_file_same_shared_strip_test$(EXEEXT): $(two_file_same_shared_strip_test_OBJECTS) $(two_file_same_shared_strip_test_DEPENDENCIES) @rm -f two_file_same_shared_strip_test$(EXEEXT) - $(CXXLINK) $(two_file_same_shared_strip_test_LDFLAGS) $(two_file_same_shared_strip_test_OBJECTS) $(two_file_same_shared_strip_test_LDADD) $(LIBS) + $(two_file_same_shared_strip_test_LINK) $(two_file_same_shared_strip_test_OBJECTS) $(two_file_same_shared_strip_test_LDADD) $(LIBS) two_file_same_shared_test$(EXEEXT): $(two_file_same_shared_test_OBJECTS) $(two_file_same_shared_test_DEPENDENCIES) @rm -f two_file_same_shared_test$(EXEEXT) - $(CXXLINK) $(two_file_same_shared_test_LDFLAGS) $(two_file_same_shared_test_OBJECTS) $(two_file_same_shared_test_LDADD) $(LIBS) + $(two_file_same_shared_test_LINK) $(two_file_same_shared_test_OBJECTS) $(two_file_same_shared_test_LDADD) $(LIBS) two_file_separate_shared_12_nonpic_test$(EXEEXT): $(two_file_separate_shared_12_nonpic_test_OBJECTS) $(two_file_separate_shared_12_nonpic_test_DEPENDENCIES) @rm -f two_file_separate_shared_12_nonpic_test$(EXEEXT) - $(CXXLINK) $(two_file_separate_shared_12_nonpic_test_LDFLAGS) $(two_file_separate_shared_12_nonpic_test_OBJECTS) $(two_file_separate_shared_12_nonpic_test_LDADD) $(LIBS) + $(two_file_separate_shared_12_nonpic_test_LINK) $(two_file_separate_shared_12_nonpic_test_OBJECTS) $(two_file_separate_shared_12_nonpic_test_LDADD) $(LIBS) two_file_separate_shared_12_test$(EXEEXT): $(two_file_separate_shared_12_test_OBJECTS) $(two_file_separate_shared_12_test_DEPENDENCIES) @rm -f two_file_separate_shared_12_test$(EXEEXT) - $(CXXLINK) $(two_file_separate_shared_12_test_LDFLAGS) $(two_file_separate_shared_12_test_OBJECTS) $(two_file_separate_shared_12_test_LDADD) $(LIBS) + $(two_file_separate_shared_12_test_LINK) $(two_file_separate_shared_12_test_OBJECTS) $(two_file_separate_shared_12_test_LDADD) $(LIBS) two_file_separate_shared_21_nonpic_test$(EXEEXT): $(two_file_separate_shared_21_nonpic_test_OBJECTS) $(two_file_separate_shared_21_nonpic_test_DEPENDENCIES) @rm -f two_file_separate_shared_21_nonpic_test$(EXEEXT) - $(CXXLINK) $(two_file_separate_shared_21_nonpic_test_LDFLAGS) $(two_file_separate_shared_21_nonpic_test_OBJECTS) $(two_file_separate_shared_21_nonpic_test_LDADD) $(LIBS) + $(two_file_separate_shared_21_nonpic_test_LINK) $(two_file_separate_shared_21_nonpic_test_OBJECTS) $(two_file_separate_shared_21_nonpic_test_LDADD) $(LIBS) two_file_separate_shared_21_test$(EXEEXT): $(two_file_separate_shared_21_test_OBJECTS) $(two_file_separate_shared_21_test_DEPENDENCIES) @rm -f two_file_separate_shared_21_test$(EXEEXT) - $(CXXLINK) $(two_file_separate_shared_21_test_LDFLAGS) $(two_file_separate_shared_21_test_OBJECTS) $(two_file_separate_shared_21_test_LDADD) $(LIBS) + $(two_file_separate_shared_21_test_LINK) $(two_file_separate_shared_21_test_OBJECTS) $(two_file_separate_shared_21_test_LDADD) $(LIBS) two_file_shared_1_nonpic_test$(EXEEXT): $(two_file_shared_1_nonpic_test_OBJECTS) $(two_file_shared_1_nonpic_test_DEPENDENCIES) @rm -f two_file_shared_1_nonpic_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_1_nonpic_test_LDFLAGS) $(two_file_shared_1_nonpic_test_OBJECTS) $(two_file_shared_1_nonpic_test_LDADD) $(LIBS) + $(two_file_shared_1_nonpic_test_LINK) $(two_file_shared_1_nonpic_test_OBJECTS) $(two_file_shared_1_nonpic_test_LDADD) $(LIBS) two_file_shared_1_pic_2_test$(EXEEXT): $(two_file_shared_1_pic_2_test_OBJECTS) $(two_file_shared_1_pic_2_test_DEPENDENCIES) @rm -f two_file_shared_1_pic_2_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_1_pic_2_test_LDFLAGS) $(two_file_shared_1_pic_2_test_OBJECTS) $(two_file_shared_1_pic_2_test_LDADD) $(LIBS) + $(two_file_shared_1_pic_2_test_LINK) $(two_file_shared_1_pic_2_test_OBJECTS) $(two_file_shared_1_pic_2_test_LDADD) $(LIBS) two_file_shared_1_test$(EXEEXT): $(two_file_shared_1_test_OBJECTS) $(two_file_shared_1_test_DEPENDENCIES) @rm -f two_file_shared_1_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_1_test_LDFLAGS) $(two_file_shared_1_test_OBJECTS) $(two_file_shared_1_test_LDADD) $(LIBS) + $(two_file_shared_1_test_LINK) $(two_file_shared_1_test_OBJECTS) $(two_file_shared_1_test_LDADD) $(LIBS) two_file_shared_2_nonpic_test$(EXEEXT): $(two_file_shared_2_nonpic_test_OBJECTS) $(two_file_shared_2_nonpic_test_DEPENDENCIES) @rm -f two_file_shared_2_nonpic_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_2_nonpic_test_LDFLAGS) $(two_file_shared_2_nonpic_test_OBJECTS) $(two_file_shared_2_nonpic_test_LDADD) $(LIBS) + $(two_file_shared_2_nonpic_test_LINK) $(two_file_shared_2_nonpic_test_OBJECTS) $(two_file_shared_2_nonpic_test_LDADD) $(LIBS) two_file_shared_2_pic_1_test$(EXEEXT): $(two_file_shared_2_pic_1_test_OBJECTS) $(two_file_shared_2_pic_1_test_DEPENDENCIES) @rm -f two_file_shared_2_pic_1_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_2_pic_1_test_LDFLAGS) $(two_file_shared_2_pic_1_test_OBJECTS) $(two_file_shared_2_pic_1_test_LDADD) $(LIBS) + $(two_file_shared_2_pic_1_test_LINK) $(two_file_shared_2_pic_1_test_OBJECTS) $(two_file_shared_2_pic_1_test_LDADD) $(LIBS) two_file_shared_2_test$(EXEEXT): $(two_file_shared_2_test_OBJECTS) $(two_file_shared_2_test_DEPENDENCIES) @rm -f two_file_shared_2_test$(EXEEXT) - $(CXXLINK) $(two_file_shared_2_test_LDFLAGS) $(two_file_shared_2_test_OBJECTS) $(two_file_shared_2_test_LDADD) $(LIBS) + $(two_file_shared_2_test_LINK) $(two_file_shared_2_test_OBJECTS) $(two_file_shared_2_test_LDADD) $(LIBS) two_file_static_test$(EXEEXT): $(two_file_static_test_OBJECTS) $(two_file_static_test_DEPENDENCIES) @rm -f two_file_static_test$(EXEEXT) - $(CXXLINK) $(two_file_static_test_LDFLAGS) $(two_file_static_test_OBJECTS) $(two_file_static_test_LDADD) $(LIBS) + $(two_file_static_test_LINK) $(two_file_static_test_OBJECTS) $(two_file_static_test_LDADD) $(LIBS) @GCC_FALSE@two_file_strip_test$(EXEEXT): $(two_file_strip_test_OBJECTS) $(two_file_strip_test_DEPENDENCIES) @GCC_FALSE@ @rm -f two_file_strip_test$(EXEEXT) -@GCC_FALSE@ $(LINK) $(two_file_strip_test_LDFLAGS) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@two_file_strip_test$(EXEEXT): $(two_file_strip_test_OBJECTS) $(two_file_strip_test_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f two_file_strip_test$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(two_file_strip_test_LDFLAGS) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(two_file_strip_test_OBJECTS) $(two_file_strip_test_LDADD) $(LIBS) two_file_test$(EXEEXT): $(two_file_test_OBJECTS) $(two_file_test_DEPENDENCIES) @rm -f two_file_test$(EXEEXT) - $(CXXLINK) $(two_file_test_LDFLAGS) $(two_file_test_OBJECTS) $(two_file_test_LDADD) $(LIBS) + $(two_file_test_LINK) $(two_file_test_OBJECTS) $(two_file_test_LDADD) $(LIBS) ver_test$(EXEEXT): $(ver_test_OBJECTS) $(ver_test_DEPENDENCIES) @rm -f ver_test$(EXEEXT) - $(CXXLINK) $(ver_test_LDFLAGS) $(ver_test_OBJECTS) $(ver_test_LDADD) $(LIBS) + $(ver_test_LINK) $(ver_test_OBJECTS) $(ver_test_LDADD) $(LIBS) +ver_test_11$(EXEEXT): $(ver_test_11_OBJECTS) $(ver_test_11_DEPENDENCIES) + @rm -f ver_test_11$(EXEEXT) + $(ver_test_11_LINK) $(ver_test_11_OBJECTS) $(ver_test_11_LDADD) $(LIBS) ver_test_2$(EXEEXT): $(ver_test_2_OBJECTS) $(ver_test_2_DEPENDENCIES) @rm -f ver_test_2$(EXEEXT) - $(CXXLINK) $(ver_test_2_LDFLAGS) $(ver_test_2_OBJECTS) $(ver_test_2_LDADD) $(LIBS) + $(ver_test_2_LINK) $(ver_test_2_OBJECTS) $(ver_test_2_LDADD) $(LIBS) ver_test_6$(EXEEXT): $(ver_test_6_OBJECTS) $(ver_test_6_DEPENDENCIES) @rm -f ver_test_6$(EXEEXT) - $(LINK) $(ver_test_6_LDFLAGS) $(ver_test_6_OBJECTS) $(ver_test_6_LDADD) $(LIBS) + $(ver_test_6_LINK) $(ver_test_6_OBJECTS) $(ver_test_6_LDADD) $(LIBS) ver_test_8$(EXEEXT): $(ver_test_8_OBJECTS) $(ver_test_8_DEPENDENCIES) @rm -f ver_test_8$(EXEEXT) - $(CXXLINK) $(ver_test_8_LDFLAGS) $(ver_test_8_OBJECTS) $(ver_test_8_LDADD) $(LIBS) + $(ver_test_8_LINK) $(ver_test_8_OBJECTS) $(ver_test_8_LDADD) $(LIBS) ver_test_9$(EXEEXT): $(ver_test_9_OBJECTS) $(ver_test_9_DEPENDENCIES) @rm -f ver_test_9$(EXEEXT) - $(CXXLINK) $(ver_test_9_LDFLAGS) $(ver_test_9_OBJECTS) $(ver_test_9_LDADD) $(LIBS) + $(ver_test_9_LINK) $(ver_test_9_OBJECTS) $(ver_test_9_LDADD) $(LIBS) weak_alias_test$(EXEEXT): $(weak_alias_test_OBJECTS) $(weak_alias_test_DEPENDENCIES) @rm -f weak_alias_test$(EXEEXT) - $(CXXLINK) $(weak_alias_test_LDFLAGS) $(weak_alias_test_OBJECTS) $(weak_alias_test_LDADD) $(LIBS) + $(weak_alias_test_LINK) $(weak_alias_test_OBJECTS) $(weak_alias_test_LDADD) $(LIBS) @GCC_FALSE@weak_plt$(EXEEXT): $(weak_plt_OBJECTS) $(weak_plt_DEPENDENCIES) @GCC_FALSE@ @rm -f weak_plt$(EXEEXT) -@GCC_FALSE@ $(LINK) $(weak_plt_LDFLAGS) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) +@GCC_FALSE@ $(LINK) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) @NATIVE_LINKER_FALSE@weak_plt$(EXEEXT): $(weak_plt_OBJECTS) $(weak_plt_DEPENDENCIES) @NATIVE_LINKER_FALSE@ @rm -f weak_plt$(EXEEXT) -@NATIVE_LINKER_FALSE@ $(LINK) $(weak_plt_LDFLAGS) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) +@NATIVE_LINKER_FALSE@ $(LINK) $(weak_plt_OBJECTS) $(weak_plt_LDADD) $(LIBS) weak_test$(EXEEXT): $(weak_test_OBJECTS) $(weak_test_DEPENDENCIES) @rm -f weak_test$(EXEEXT) - $(CXXLINK) $(weak_test_LDFLAGS) $(weak_test_OBJECTS) $(weak_test_LDADD) $(LIBS) + $(weak_test_LINK) $(weak_test_OBJECTS) $(weak_test_LDADD) $(LIBS) weak_undef_nonpic_test$(EXEEXT): $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_nonpic_test_DEPENDENCIES) @rm -f weak_undef_nonpic_test$(EXEEXT) - $(CXXLINK) $(weak_undef_nonpic_test_LDFLAGS) $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_nonpic_test_LDADD) $(LIBS) + $(weak_undef_nonpic_test_LINK) $(weak_undef_nonpic_test_OBJECTS) $(weak_undef_nonpic_test_LDADD) $(LIBS) weak_undef_test$(EXEEXT): $(weak_undef_test_OBJECTS) $(weak_undef_test_DEPENDENCIES) @rm -f weak_undef_test$(EXEEXT) - $(CXXLINK) $(weak_undef_test_LDFLAGS) $(weak_undef_test_OBJECTS) $(weak_undef_test_LDADD) $(LIBS) + $(weak_undef_test_LINK) $(weak_undef_test_OBJECTS) $(weak_undef_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1673,6 +2214,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_pic_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_pie_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_static_pic_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_static_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/basic_test.Po@am__quote@ @@ -1681,17 +2223,27 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/constructor_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copy_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/discard_locals_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exclude_libs_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_compress_debug_sections.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large-large.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_labels_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_r_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/permission_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test_1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test_2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test_3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test_4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_test_5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_3.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protected_main_2.Po@am__quote@ @@ -1702,12 +2254,17 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2a.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2b.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/searched_file_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testmain.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thin_archive_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_pie_pic_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_pie_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test_file2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls_test_main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_pie_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_strip_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/two_file_test_1b.Po@am__quote@ @@ -1722,78 +2279,95 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weak_undef_test.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 +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @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 +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @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) '$<'` +large-large.o: large.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.o -MD -MP -MF $(DEPDIR)/large-large.Tpo -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/large-large.Tpo $(DEPDIR)/large-large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='large.c' object='large-large.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -c -o large-large.o `test -f 'large.c' || echo '$(srcdir)/'`large.c + +large-large.obj: large.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -MT large-large.obj -MD -MP -MF $(DEPDIR)/large-large.Tpo -c -o large-large.obj `if test -f 'large.c'; then $(CYGPATH_W) 'large.c'; else $(CYGPATH_W) '$(srcdir)/large.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/large-large.Tpo $(DEPDIR)/large-large.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='large.c' object='large-large.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(large_CFLAGS) $(CFLAGS) -c -o large-large.obj `if test -f 'large.c'; then $(CYGPATH_W) 'large.c'; else $(CYGPATH_W) '$(srcdir)/large.c'; fi` + .cc.o: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -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; }'`; \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) - tags=; \ + set x; \ 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 \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ 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" \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique + $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags @@ -1801,7 +2375,8 @@ distclean-tags: check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ - list='$(TESTS)'; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ @@ -1810,49 +2385,63 @@ check-TESTS: $(TESTS) if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *" $$tst "*) \ + *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ - echo "XPASS: $$tst"; \ + col=$$red; res=XPASS; \ ;; \ *) \ - echo "PASS: $$tst"; \ + col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ - *" $$tst "*) \ + *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ - echo "XFAIL: $$tst"; \ + col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ - echo "FAIL: $$tst"; \ + col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ - echo "SKIP: $$tst"; \ + col=$$blu; res=SKIP; \ fi; \ + echo "$${col}$$res$${std}: $$tst"; \ done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ - banner="All $$all tests passed"; \ + banner="$$All$$all $$tests passed"; \ else \ - banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all tests failed"; \ + banner="$$failed of $$all $$tests failed"; \ else \ - banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ - skipped="($$skip tests were not run)"; \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ @@ -1863,38 +2452,45 @@ check-TESTS: $(TESTS) dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ - echo "$$dashes"; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ echo "$$banner"; \ test -z "$$skipped" || echo "$$skipped"; \ test -z "$$report" || echo "$$report"; \ - echo "$$dashes"; \ + echo "$$dashes$$std"; \ test "$$failed" -eq 0; \ else :; fi 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; \ + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ 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 \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @@ -1928,6 +2524,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -1950,18 +2547,38 @@ dvi-am: html: html-am +html-am: + info: info-am info-am: install-data-am: +install-dvi: install-dvi-am + +install-dvi-am: + install-exec-am: +install-html: install-html-am + +install-html-am: + install-info: install-info-am +install-info-am: + install-man: +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + installcheck-am: maintainer-clean: maintainer-clean-am @@ -1981,18 +2598,22 @@ ps: ps-am ps-am: -uninstall-am: uninstall-info-am +uninstall-am: + +.MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \ clean-checkLIBRARIES clean-checkPROGRAMS clean-generic ctags \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ - install-am install-data install-data-am install-exec \ - install-exec-am install-info install-info-am install-man \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-info-am + tags uninstall uninstall-am # --------------------------------------------------------------------- @@ -2019,6 +2640,62 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@flagstest_ndebug.o: constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test_1.o: incremental_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test_2.o: incremental_test_2.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test: incremental_test_1.o incremental_test_2.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,-incremental incremental_test_1.o incremental_test_2.o -Wl,-debug 2> incremental_test.cmdline +@GCC_TRUE@@NATIVE_LINKER_TRUE@incremental_test.stdout: incremental_test ../incremental-dump +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ../incremental-dump incremental_test > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_comdat_test_1.o: gc_comdat_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_comdat_test_2.o: gc_comdat_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_comdat_test: gc_comdat_test_1.o gc_comdat_test_2.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_comdat_test_1.o gc_comdat_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_comdat_test.stdout: gc_comdat_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C gc_comdat_test > gc_comdat_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_tls_test.o: gc_tls_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_tls_test:gc_tls_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_tls_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_tls_test.stdout: gc_tls_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C gc_tls_test > gc_tls_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test.o: gc_orphan_section_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test:gc_orphan_section_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_orphan_section_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test.stdout: gc_orphan_section_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) gc_orphan_section_test > gc_orphan_section_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test.o: icf_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test: icf_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test.stdout: icf_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C icf_test > icf_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test.o: icf_keep_unique_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test: icf_keep_unique_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all -Wl,--keep-unique,_Z11unique_funcv icf_keep_unique_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_keep_unique_test.stdout: icf_keep_unique_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C icf_keep_unique_test > icf_keep_unique_test.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test.o: icf_safe_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test: icf_safe_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test_1.stdout: icf_safe_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_test > icf_safe_test_1.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_test_2.stdout: icf_safe_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -h icf_safe_test > icf_safe_test_2.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test.o: icf_safe_so_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test: icf_safe_so_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=safe icf_safe_so_test.o -fPIC -shared +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test_1.stdout: icf_safe_so_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_so_test > icf_safe_so_test_1.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test_2.stdout: icf_safe_so_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test: basic_test.o gcctestdir/ld @@ -2032,6 +2709,10 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_pic_test.o @GCC_TRUE@@NATIVE_LINKER_TRUE@basic_static_pic_test: basic_pic_test.o gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -static basic_pic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_pie_test.o: basic_test.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_pie_test: basic_pie_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -pie basic_pie_test.o @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1_pic.o: two_file_test_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1b_pic.o: two_file_test_1b.cc @@ -2046,6 +2727,19 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1_pic.o two_file_test_1b_pic.o two_file_test_2_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_relocatable.o: gcctestdir/ld two_file_test_1.o two_file_test_1b.o two_file_test_2.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -r -o $@ two_file_test_1.o two_file_test_1b.o two_file_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1_pie.o: two_file_test_1.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_1b_pie.o: two_file_test_1b.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_2_pie.o: two_file_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_test_main_pie.o: two_file_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_pie_test: two_file_test_1_pie.o two_file_test_1b_pie.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_2_pie.o two_file_test_main_pie.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -pie two_file_test_1_pie.o two_file_test_1b_pie.o two_file_test_2_pie.o two_file_test_main_pie.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared.dbg: two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -w $< >$@ 2>/dev/null @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_1_nonpic.so: two_file_test_1.o gcctestdir/ld @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared two_file_test_1.o two_file_test_1b.o @FN_PTRS_IN_SO_WITHOUT_PIC_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_2_nonpic.so: two_file_test_2.o gcctestdir/ld @@ -2060,6 +2754,14 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_STRIP) -o two_file_strip_test two_file_test @GCC_TRUE@@NATIVE_LINKER_TRUE@two_file_shared_strip.so: two_file_shared.so @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_STRIP) -S -o two_file_shared_strip.so two_file_shared.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2_pic.o: common_test_2.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_2.so: common_test_2_pic.o common_test_3.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared common_test_2_pic.o common_test_3.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_3_pic.o: common_test_3.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@common_test_3.so: common_test_3_pic.o ver_test_2.script gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared common_test_3_pic.o -Wl,--version-script,$(srcdir)/ver_test_2.script @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_1_pic.o: exception_test_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@exception_test_2_pic.o: exception_test_2.cc @@ -2125,7 +2827,7 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c_pic.o: tls_test_c.c @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared.so: tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o gcctestdir/ld -@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o -Wl,-z,defs @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_shared2.so: tls_test_file2_pic.o gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared tls_test_file2_pic.o @@ -2140,6 +2842,22 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c.o: tls_test_c.c @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c $(TLS_TEST_C_CFLAGS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_main_pie.o: tls_test_main.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_pie.o: tls_test.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_file2_pie.o: tls_test_file2.cc tls_test.h +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpie -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_test_c_pie.o: tls_test_c.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(COMPILE) -c -fpic $(TLS_TEST_C_CFLAGS) -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pie_test: tls_test_main_pie.o tls_test_pie.o tls_test_file2_pie.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pie.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -pie tls_test_main_pie.o tls_test_pie.o tls_test_file2_pie.o tls_test_c_pie.o -lpthread + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@tls_pie_pic_test: tls_test_main_pie.o tls_test_pic.o tls_test_file2_pic.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ tls_test_c_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@ $(CXXLINK) -Bgcctestdir/ -pie tls_test_main_pie.o tls_test_pic.o tls_test_file2_pic.o tls_test_c_pic.o -lpthread + @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_gnu2.o: tls_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@ $(CXXCOMPILE) -c -fpic -mtls-dialect=gnu2 -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_GNU2_DIALECT_TRUE@@TLS_TRUE@tls_test_file2_gnu2.o: tls_test_file2.cc @@ -2247,6 +2965,8 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.o: ver_test_4.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_1.syms: ver_test_1.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_2.syms: ver_test_2 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.syms: ver_test_4.so @@ -2277,6 +2997,8 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -s $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_10.so: gcctestdir/ld ver_test_2.o ver_test_10.script @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,--version-script,$(srcdir)/ver_test_10.script ver_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_11.a: ver_test_1.o ver_test_2.o ver_test_4.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ @GCC_TRUE@@NATIVE_LINKER_TRUE@protected_1.so: gcctestdir/ld protected_1_pic.o protected_2_pic.o protected_3_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared protected_1_pic.o protected_2_pic.o protected_3_pic.o @@ -2286,6 +3008,15 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@protected_3_pic.o: protected_3.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_4_pic.o: protected_4.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@protected_3.err: protected_4_pic.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @echo $(CXXLINK) -Bgcctestdir/ -shared -o protected_4.so protected_4_pic.o "2>$@" +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @if $(CXXLINK) -Bgcctestdir/ -shared -o protected_4.so protected_4_pic.o 2>$@; then \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 1>&2 "Link of protected_4.so should have failed"; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ exit 1; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ fi @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test.so: gcctestdir/ld relro_test_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_pic.o: relro_test.cc @@ -2301,7 +3032,7 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@binary.txt: $(srcdir)/binary.in @GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LN_S) $< $@ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_def.so: ver_matching_def.cc gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_def.so: ver_matching_def.cc $(srcdir)/version_script.map gcctestdir/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map @GCC_TRUE@@NATIVE_LINKER_TRUE@ver_matching_test.stdout: ver_matching_def.so @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -T ver_matching_def.so | $(TEST_CXXFILT) > ver_matching_test.stdout @@ -2313,6 +3044,339 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_4.t @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_4.stdout: script_test_4 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_4 > script_test_4.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_5: script_test_5.o gcctestdir/ld $(srcdir)/script_test_5.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ script_test_5.o -T $(srcdir)/script_test_5.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_5.stdout: script_test_5 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SW script_test_5 > script_test_5.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_6: basic_test.o gcctestdir/ld $(srcdir)/script_test_6.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_6.t \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,-Ttext=0x10001000 -Wl,-Tdata=0x10200000 -Wl,-Tbss=0x10400000 +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_6.stdout: script_test_6 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_6 > script_test_6.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_7: basic_test.o gcctestdir/ld $(srcdir)/script_test_7.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_7.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_7.stdout: script_test_7 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_7 > script_test_7.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_8: basic_test.o gcctestdir/ld $(srcdir)/script_test_7.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o -T $(srcdir)/script_test_7.t \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,-Ttext=0x20001000 -Wl,-Tdata=0x20200000 -Wl,-Tbss=0x20400000 +@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_8.stdout: script_test_8 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -SlW script_test_8 > script_test_8.stdout +@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list: basic_test.o gcctestdir/ld $(srcdir)/dynamic_list.t +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list $(srcdir)/dynamic_list.t \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-data \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-cpp-new \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ -Wl,--dynamic-list-cpp-typeinfo +@GCC_TRUE@@NATIVE_LINKER_TRUE@dynamic_list.stdout: dynamic_list +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -W -Ds dynamic_list > dynamic_list.stdout + +@GCC_TRUE@@NATIVE_LINKER_TRUE@libthin1.a: thin_archive_test_1.o alt/thin_archive_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) crT $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/libthin2.a: thin_archive_test_3.o alt/thin_archive_test_4.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) crT $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@libthin3.a: thin_archive_test_1.o alt/thin_archive_test_4.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) crT $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/libthin4.a: alt/thin_archive_test_2.o thin_archive_test_3.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) crT $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@libthinall.a: libthin3.a alt/libthin4.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) crT $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/thin_archive_test_2.o: thin_archive_test_2.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/thin_archive_test_4.o: thin_archive_test_4.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_1: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_1.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_1.err: plugin_test_1 +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @touch plugin_test_1.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_2: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so gcctestdir/ld plugin_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,-R,.,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so 2>plugin_test_2.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_2.err: plugin_test_2 +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @touch plugin_test_2.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_3: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--export-dynamic -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_3.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_3.err: plugin_test_3 +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @touch plugin_test_3.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_4: two_file_test_main.o plugin_test_4.a gcctestdir/ld plugin_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o -Wl,--whole-archive,plugin_test_4.a,--no-whole-archive 2>plugin_test_4.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_4.err: plugin_test_4 +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @touch plugin_test_4.err + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_4.a: two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_AR) cr $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test_5: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms gcctestdir/ld plugin_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv",--gc-sections two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test.so: plugin_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(LINK) -Bgcctestdir/ -shared plugin_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_test.o: plugin_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -O0 -c -fpic -o $@ $< + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@two_file_test_main.syms: two_file_test_main.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@two_file_test_1.syms: two_file_test_1.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@two_file_test_1b.syms: two_file_test_1b.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@two_file_test_2.syms: two_file_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@empty.syms: +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @echo "" >$@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @echo "Symbol table" >>$@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.syms: unused.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @echo " 1: 00000000 4 FUNC GLOBAL DEFAULT 1 UNUSED" >>$@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.o: unused.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.c: +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @cp /dev/null $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test.syms: exclude_libs_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_1.a: exclude_libs_test_1.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_2.a: exclude_libs_test_2.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/libexclude_libs_test_3.a: exclude_libs_test_3.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +@GCC_TRUE@@NATIVE_LINKER_TRUE@local_labels_test.o: ver_test_6.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -g -c -Wa,-L -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@local_labels_test: local_labels_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ local_labels_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test.syms: discard_locals_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +# '-Wa,-L' is required to preserve the local label used for testing. +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_test.o: discard_locals_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -Wa,-L -o $@ $< + +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_relocatable_test1.syms: discard_locals_relocatable_test1.out +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_relocatable_test.o: discard_locals_relocatable_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -Wa,-L -fPIC -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_relocatable_test1.out: discard_locals_relocatable_test.o ../ld-new +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ../ld-new --discard-locals -relocatable -o $@ $< + +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_relocatable_test2.syms: discard_locals_relocatable_test2.out +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null +@GCC_TRUE@@NATIVE_LINKER_TRUE@discard_locals_relocatable_test2.out: discard_locals_relocatable_test.o ../ld-new +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ../ld-new --discard-all -relocatable -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@libhidden.so: hidden_test_1.c gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -Bgcctestdir/ -g -shared -fPIC -w -o $@ $(srcdir)/hidden_test_1.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@hidden_test: hidden_test_main.o libhidden.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,-R,. hidden_test_main.o libhidden.so 2>hidden_test.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@hidden_test.err: hidden_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ @touch hidden_test.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@retain_symbols_file_test.so: basic_pic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 'main' > retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo 't1' >> retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo '_ZN4t16bC1Ev' >> retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo '_ZNK4t20a3getEv' >> retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo '_Z3t18v' >> retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo '__tcf_0' >> retain_symbols_file_test.in +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-retain-symbols-file,retain_symbols_file_test.in basic_pic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@retain_symbols_file_test.stdout: retain_symbols_file_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C retain_symbols_file_test.so > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@permission_test: basic_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ umask 022; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ touch $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ chmod 600 $@; \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ basic_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@searched_file_test_lib.o: searched_file_test_lib.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@alt/searched_file_test_lib.a: searched_file_test_lib.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d alt || mkdir -p alt +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_AR) rc $@ $^ +# We invoke the linker directly since gcc may include additional objects that +# uses symbol versioning. +@GCC_TRUE@@NATIVE_LINKER_TRUE@libno_version_test.so: no_version_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -shared -o $@ no_version_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@no_version_test.o: no_version_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -o $@ -c -fPIC $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@no_version_test.stdout: libno_version_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_OBJDUMP) -h $< > $@ +@DEFAULT_TARGET_I386_TRUE@split_i386_1.o: split_i386_1.s +@DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_I386_TRUE@split_i386_2.o: split_i386_2.s +@DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_I386_TRUE@split_i386_3.o: split_i386_3.s +@DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_I386_TRUE@split_i386_4.o: split_i386_4.s +@DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_I386_TRUE@split_i386_n.o: split_i386_n.s +@DEFAULT_TARGET_I386_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_I386_TRUE@split_i386_1: split_i386_1.o split_i386_n.o ../ld-new +@DEFAULT_TARGET_I386_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_1.o split_i386_n.o +@DEFAULT_TARGET_I386_TRUE@split_i386_1.stdout: split_i386_1 +@DEFAULT_TARGET_I386_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_I386_TRUE@split_i386_2: split_i386_2.o split_i386_n.o ../ld-new +@DEFAULT_TARGET_I386_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_2.o split_i386_n.o +@DEFAULT_TARGET_I386_TRUE@split_i386_2.stdout: split_i386_2 +@DEFAULT_TARGET_I386_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_I386_TRUE@split_i386_3.stdout: split_i386_3.o split_i386_n.o ../ld-new +@DEFAULT_TARGET_I386_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o split_i386_3 split_i386_3.o split_i386_n.o > $@ 2>&1 || exit 0 +@DEFAULT_TARGET_I386_TRUE@split_i386_4: split_i386_4.o split_i386_n.o ../ld-new +@DEFAULT_TARGET_I386_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_i386_4.o split_i386_n.o +@DEFAULT_TARGET_I386_TRUE@split_i386_4.stdout: split_i386_4 +@DEFAULT_TARGET_I386_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_I386_TRUE@split_i386_r.stdout: split_i386_1.o split_i386_n.o ../ld-new +@DEFAULT_TARGET_I386_TRUE@ ../ld-new -r split_i386_1.o split_i386_n.o -o split_i386_r > $@ 2>&1 || exit 0 +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_1.o: split_x86_64_1.s +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_2.o: split_x86_64_2.s +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_3.o: split_x86_64_3.s +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_4.o: split_x86_64_4.s +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_n.o: split_x86_64_n.s +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_AS) -o $@ $< +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_1: split_x86_64_1.o split_x86_64_n.o ../ld-new +@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_1.o split_x86_64_n.o +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_1.stdout: split_x86_64_1 +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_2: split_x86_64_2.o split_x86_64_n.o ../ld-new +@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_2.o split_x86_64_n.o +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_2.stdout: split_x86_64_2 +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_3.stdout: split_x86_64_3.o split_x86_64_n.o ../ld-new +@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o split_x86_64_3 split_x86_64_3.o split_x86_64_n.o > $@ 2>&1 || exit 0 +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_4: split_x86_64_4.o split_x86_64_n.o ../ld-new +@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new $(SPLIT_DEFSYMS) -o $@ split_x86_64_4.o split_x86_64_n.o +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_4.stdout: split_x86_64_4 +@DEFAULT_TARGET_X86_64_TRUE@ $(TEST_OBJDUMP) -d $< > $@ +@DEFAULT_TARGET_X86_64_TRUE@split_x86_64_r.stdout: split_x86_64_1.o split_x86_64_n.o ../ld-new +@DEFAULT_TARGET_X86_64_TRUE@ ../ld-new -r split_x86_64_1.o split_x86_64_n.o -o split_x86_64_r > $@ 2>&1 || exit 0 +@DEFAULT_TARGET_ARM_TRUE@arm_abs_lib.o: arm_abs_lib.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -march=armv7-a -o $@ $< +@DEFAULT_TARGET_ARM_TRUE@libarm_abs.so: arm_abs_lib.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -shared -o $@ arm_abs_lib.o +@DEFAULT_TARGET_ARM_TRUE@arm_abs_global.o: arm_abs_global.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -march=armv7-a -o $@ $< +@DEFAULT_TARGET_ARM_TRUE@arm_abs_global: arm_abs_global.o libarm_abs.so ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ arm_abs_global.o -L. -larm_abs +@DEFAULT_TARGET_ARM_TRUE@arm_abs_global.stdout: arm_abs_global +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_READELF) -r $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_in_range.stdout: arm_bl_in_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_in_range: arm_bl_in_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/arm_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_in_range.o: arm_bl_in_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_out_of_range.stdout: arm_bl_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -S $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_out_of_range: arm_bl_out_of_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/arm_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_bl_out_of_range.o: arm_bl_out_of_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_in_range.stdout: thumb_bl_in_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_in_range: thumb_bl_in_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_in_range.o: thumb_bl_in_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv5te $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range.stdout: thumb_bl_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range: thumb_bl_out_of_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_bl_out_of_range.o: thumb_bl_out_of_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv5te $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_in_range.stdout: thumb2_bl_in_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_in_range: thumb2_bl_in_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_in_range.o: thumb_bl_in_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_out_of_range.stdout: thumb2_bl_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_out_of_range: thumb2_bl_out_of_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_bl_out_of_range.o: thumb_bl_out_of_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_in_range.stdout: thumb_blx_in_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_in_range: thumb_blx_in_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_in_range.o: thumb_blx_in_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv5te $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_out_of_range.stdout: thumb_blx_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_out_of_range: thumb_blx_out_of_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb_blx_out_of_range.o: thumb_blx_out_of_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv5te $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_in_range.stdout: thumb2_blx_in_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_in_range: thumb2_blx_in_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_in_range.o: thumb_blx_in_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_out_of_range.stdout: thumb2_blx_out_of_range +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_out_of_range: thumb2_blx_out_of_range.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -T $(srcdir)/thumb2_branch_range.t -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@thumb2_blx_out_of_range.o: thumb_blx_out_of_range.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ -march=armv7-a $< + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx.stdout: arm_fix_v4bx +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx: arm_fix_v4bx.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new --fix-v4bx -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx.o: arm_fix_v4bx.s +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_AS) -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx_interworking.stdout: arm_fix_v4bx_interworking +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_fix_v4bx_interworking: arm_fix_v4bx.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new --fix-v4bx-interworking -o $@ $< + +@DEFAULT_TARGET_ARM_TRUE@arm_no_fix_v4bx.stdout: arm_no_fix_v4bx +@DEFAULT_TARGET_ARM_TRUE@ $(TEST_OBJDUMP) -D -j.text $< > $@ + +@DEFAULT_TARGET_ARM_TRUE@arm_no_fix_v4bx: arm_fix_v4bx.o ../ld-new +@DEFAULT_TARGET_ARM_TRUE@ ../ld-new -o $@ $< + # 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/binutils-2.19/gold/testsuite/arm_abs_global.s b/binutils-2.19/gold/testsuite/arm_abs_global.s new file mode 100644 index 0000000..65cb309 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_abs_global.s @@ -0,0 +1,31 @@ + .syntax unified + + .text + .align 2 + + .global _start + .type _start, %function +_start: + bx lr + .size _start, .-_start + + .global _arm_test + .type _arm_test, %function +_arm_test: + movt r0, #:upper16:_movt_abs_global + movw r0, #:lower16:_movw_abs_global + bx lr + .size _arm_test, .-_arm_test + + .thumb + .global _thumb_test +_thumb_test: + movt r0, #:upper16:_thm_movt_abs_global + movw r0, #:lower16:_thm_movw_abs_global + bx lr + .size _thumb_test, .-_thumb_test + + .data +_data_test: + .word _abs32_global + .word _abs32_global_plt diff --git a/binutils-2.19/gold/testsuite/arm_abs_global.sh b/binutils-2.19/gold/testsuite/arm_abs_global.sh new file mode 100755 index 0000000..26abc24 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_abs_global.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# arm_abs_global.sh -- test ARM absolute relocations against global symbols. + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with the assembler source file arm_abs_global.s, +# that is assembled and linked with a shared object libarm_abs.so. We +# want to check that a MOV[TW] instruction referencing an external function +# causes a PLT to be created. + +check() +{ + file=$1 + sym=$2 + reloc=$3 + + found=`grep " $sym\$" $file` + if test -z "$found"; then + echo "Symbol $sym not found." + exit 1 + fi + + match_reloc=`grep " $sym\$" $file | grep " $reloc "` + if test -z "$match_reloc"; then + echo "Expected symbol $sym to have relocation $reloc but found" + echo "$found" + exit 1 + fi +} + +check "arm_abs_global.stdout" "_movt_abs_global" "R_ARM_JUMP_SLOT" +check "arm_abs_global.stdout" "_movw_abs_global" "R_ARM_JUMP_SLOT" +check "arm_abs_global.stdout" "_thm_movt_abs_global" "R_ARM_JUMP_SLOT" +check "arm_abs_global.stdout" "_thm_movw_abs_global" "R_ARM_JUMP_SLOT" +check "arm_abs_global.stdout" "_abs32_global_plt" "R_ARM_JUMP_SLOT" +check "arm_abs_global.stdout" "_abs32_global" "R_ARM_ABS32" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/arm_abs_lib.s b/binutils-2.19/gold/testsuite/arm_abs_lib.s new file mode 100644 index 0000000..a2d7207 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_abs_lib.s @@ -0,0 +1,37 @@ + .syntax unified + + .text + .align 2 + .global _movt_abs_global + .type _movt_abs_global, %function +_movt_abs_global: + bx lr + .size _movt_abs_global, .-_movt_abs_global + + .global _movw_abs_global + .type _movw_abs_global, %function +_movw_abs_global: + bx lr + .size _movw_abs_global, .-_movw_abs_global + + .thumb + .align 2 + .global _thm_movt_abs_global + .type _thm_movt_abs_global, %function +_thm_movt_abs_global: + bx lr + .size _thm_movt_abs_global, .-_thm_movt_abs_global + + .global _thm_movw_abs_global + .type _thm_movw_abs_global, %function +_thm_movw_abs_global: + bx lr + .size _thm_movw_abs_global, .-_thm_movw_abs_global + + .global _abs32_global_plt + .type _abs32_global_plt, %function +_abs32_global_plt: + bx lr + .size _abs32_global_plt, .-_abs32_global_plt + + .comm _abs32_global,4,4 diff --git a/binutils-2.19/gold/testsuite/arm_bl_in_range.s b/binutils-2.19/gold/testsuite/arm_bl_in_range.s new file mode 100644 index 0000000..23960f9 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_bl_in_range.s @@ -0,0 +1,45 @@ +# arm_bl_in_range.s +# Test ARM bl instructions just within branch range limits. + .syntax unified + .arch armv5te + + .section .text.pre,"x" + +# Add padding so that target is just within branch range. + .space 12 + + .align 2 + .global _backward_target +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + .align 2 + +# Define _start so that linker does not complain. + .global _start +_start: + bx lr + .size _start, .-_start + + .global _backward_test +_backward_test: + bl _backward_target + .size _backward_test, .-_backward_test + + .global _forward_test +_forward_test: + bl _forward_target + .size _forward_test, .-_forward_test + + .section .text.post,"x" + +# Add padding so that target is just within of branch range. + .space 12 + + .align 2 + .global _forward_target +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/arm_bl_out_of_range.s b/binutils-2.19/gold/testsuite/arm_bl_out_of_range.s new file mode 100644 index 0000000..786d9aa --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_bl_out_of_range.s @@ -0,0 +1,45 @@ +# arm_bl_out_of_range.s +# Test ARM bl instructions just out of the branch range limits. + .syntax unified + .arch armv5te + + .section .text.pre,"x" + +# Add padding so that target is just out of branch range. + .space 8 + + .align 2 + .global _backward_target +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + .align 2 + +# Define _start so that linker does not complain. + .global _start +_start: + bx lr + .size _start, .-_start + + .global _backward_test +_backward_test: + bl _backward_target + .size _backward_test, .-_backward_test + + .global _forward_test +_forward_test: + bl _forward_target + .size _forward_test, .-_forward_test + + .section .text.post,"x" + +# Add padding so that target is just out of branch range. + .space 16 + + .align 2 + .global _forward_target +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/arm_branch_in_range.sh b/binutils-2.19/gold/testsuite/arm_branch_in_range.sh new file mode 100755 index 0000000..43b50c6 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_branch_in_range.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +# arm_branch_in_range.sh -- test ARM/THUMB/THUMB branch instructions whose +# targets are just within the branch range limits. + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with the assembler source files arm_bl_in_range.s +# thumb_bl_in_range.s that are assembled and linked to check that branches +# whose target are just within the branch range limits are handle correctly. + +check() +{ + file=$1 + pattern=$2 + + found=`grep "$pattern" $file` + if test -z "$found"; then + echo "pattern \"$pattern\" not found in file $file." + exit 1 + fi +} + +# This is a bit crude. Also, there are tabs in the grep patterns. + +check arm_bl_in_range.stdout \ + " 4000004: eb800000 bl 200000c <_backward_target>" +check arm_bl_in_range.stdout \ + " 4000008: eb7fffff bl 600000c <_forward_target>" +check thumb_bl_in_range.stdout \ + " 800004: f400 f800 bl 400008 <_backward_target>" +check thumb_bl_in_range.stdout \ + " 800008: f3ff ffff bl c0000a <_forward_target>" +check thumb2_bl_in_range.stdout \ + " 2000004: f400 d000 bl 1000008 <_backward_target>" +check thumb2_bl_in_range.stdout \ + " 2000008: f3ff d7ff bl 300000a <_forward_target>" +check thumb_blx_in_range.stdout \ + " 800006: f400 e800 blx 400008 <_backward_target>" +check thumb_blx_in_range.stdout \ + " 80000c: f3ff effe blx c0000c <_forward_target>" +check thumb2_blx_in_range.stdout \ + " 2000006: f400 c000 blx 1000008 <_backward_target>" +check thumb2_blx_in_range.stdout \ + " 200000c: f3ff c7fe blx 300000c <_forward_target>" +exit 0 diff --git a/binutils-2.19/gold/testsuite/arm_branch_range.t b/binutils-2.19/gold/testsuite/arm_branch_range.t new file mode 100644 index 0000000..865e404 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_branch_range.t @@ -0,0 +1,36 @@ +/* arm_banch_range.t -- linker script to test ARM branch range. + + Copyright 2010 Free Software Foundation, Inc. + Written by Doug Kwan <dougkwan@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +SECTIONS +{ + . = 0x2000000; + + .text.pre : { *(.text.pre) } + . = ALIGN(0x2000000); + .text : { *(.text) } + . = ALIGN(0x2000000); + .text.post : { *(.text.post) } + . += 0x1000; + .data : { *(.data) } + .bss : { *(.bss) } + .ARM.attributes : { *(.ARM.attributes) } +} diff --git a/binutils-2.19/gold/testsuite/arm_fix_v4bx.s b/binutils-2.19/gold/testsuite/arm_fix_v4bx.s new file mode 100644 index 0000000..fc3aa2a --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_fix_v4bx.s @@ -0,0 +1,15 @@ + .syntax unified + .text + +# Align this to 256-byte boundary for easier address matching. + .align 8 + +# We do not want to run this file. We define _start here to avoid missing +# entry point. + + .global _start + .type _start, %function +_start: + bx r0 + bx r15 + .size _start, .-_start diff --git a/binutils-2.19/gold/testsuite/arm_fix_v4bx.sh b/binutils-2.19/gold/testsuite/arm_fix_v4bx.sh new file mode 100755 index 0000000..a331ff9 --- /dev/null +++ b/binutils-2.19/gold/testsuite/arm_fix_v4bx.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# arm_v4bx.sh -- a test case for --fix-v4bx and --fix-v4bx-interworking. + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with arm_v4bx.s, an ARM assembly source file constructed to +# have test the handling of R_ARM_V4BX relocation. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected instruction in $1:" + echo " $2" + echo "" + echo "Actual instructions below:" + cat "$1" + exit 1 + fi +} + +# Test --fix-v4bx +check arm_fix_v4bx.stdout ".*00: .* mov pc, r0" +check arm_fix_v4bx.stdout ".*04: .* mov pc, pc" + +# Test --fix-v4bx-interworking +check arm_fix_v4bx_interworking.stdout ".*00: .* b .*00 <.*>" +check arm_fix_v4bx_interworking.stdout ".*04: .* mov pc, pc" +check arm_fix_v4bx_interworking.stdout ".*00: .* tst r0, #1" +check arm_fix_v4bx_interworking.stdout ".*04: .* moveq pc, r0" +check arm_fix_v4bx_interworking.stdout ".*08: .* bx r0" + +# Test no fix. +check arm_no_fix_v4bx.stdout ".*00: .* bx r0" +check arm_no_fix_v4bx.stdout ".*04: .* bx pc" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/binary_unittest.cc b/binutils-2.19/gold/testsuite/binary_unittest.cc index 44db01e..b2e14df 100644 --- a/binutils-2.19/gold/testsuite/binary_unittest.cc +++ b/binutils-2.19/gold/testsuite/binary_unittest.cc @@ -44,8 +44,9 @@ using namespace gold; template<int size, bool big_endian> bool -Sized_binary_test(Target* target) +Sized_binary_test() { + parameters_clear_target(); // We need a pretend Task. const Task* task = reinterpret_cast<const Task*>(-1); @@ -67,13 +68,12 @@ Sized_binary_test(Target* target) binary.converted_size()); Object* object = make_elf_object("test.o", &input_file, 0, binary.converted_data(), - binary.converted_size()); + binary.converted_size(), NULL); CHECK(object != NULL); if (object == NULL) return false; CHECK(!object->is_dynamic()); - CHECK(object->target() == target); CHECK(object->shnum() == 5); CHECK(object->section_name(1) == ".data"); CHECK(object->section_flags(1) == (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE)); @@ -125,23 +125,27 @@ Binary_test(Test_report*) int fail = 0; #ifdef HAVE_TARGET_32_LITTLE - if (!Sized_binary_test<32, false>(target_test_pointer_32_little)) + if (!Sized_binary_test<32, false>()) ++fail; + CHECK(¶meters->target() == target_test_pointer_32_little); #endif #ifdef HAVE_TARGET_32_BIG - if (!Sized_binary_test<32, true>(target_test_pointer_32_big)) + if (!Sized_binary_test<32, true>()) ++fail; + CHECK(¶meters->target() == target_test_pointer_32_big); #endif #ifdef HAVE_TARGET_64_LITTLE - if (!Sized_binary_test<64, false>(target_test_pointer_64_little)) + if (!Sized_binary_test<64, false>()) ++fail; + CHECK(¶meters->target() == target_test_pointer_64_little); #endif #ifdef HAVE_TARGET_64_BIG - if (!Sized_binary_test<64, true>(target_test_pointer_64_big)) + if (!Sized_binary_test<64, true>()) ++fail; + CHECK(¶meters->target() == target_test_pointer_64_big); #endif return fail == 0; diff --git a/binutils-2.19/gold/testsuite/common_test_2.c b/binutils-2.19/gold/testsuite/common_test_2.c new file mode 100644 index 0000000..ef6d83d --- /dev/null +++ b/binutils-2.19/gold/testsuite/common_test_2.c @@ -0,0 +1,33 @@ +/* common_test_2.c -- test common symbol name conflicts + + Copyright 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor <iant@google.com> + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* Call a function. The function will come from a shared library. */ + +extern void c1 (void); + +void fn (void); + +void +fn (void) +{ + c1 (); +} diff --git a/binutils-2.19/gold/testsuite/common_test_3.c b/binutils-2.19/gold/testsuite/common_test_3.c new file mode 100644 index 0000000..ba8960c --- /dev/null +++ b/binutils-2.19/gold/testsuite/common_test_3.c @@ -0,0 +1,32 @@ +/* common_test_3.c -- test common symbol name conflicts + + Copyright 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor <iant@google.com> + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* Define a function with a default version whose name is the same as + a common symbol. This file will wind up in a shared library. */ + +void c1_v1 (void); + +void +c1_v1 (void) +{ +} +__asm__ (".symver c1_v1,c1@@VER1"); diff --git a/binutils-2.19/gold/testsuite/debug_msg.sh b/binutils-2.19/gold/testsuite/debug_msg.sh index 23da5a2..750261e 100755 --- a/binutils-2.19/gold/testsuite/debug_msg.sh +++ b/binutils-2.19/gold/testsuite/debug_msg.sh @@ -55,18 +55,21 @@ check_missing() # We don't know how the compiler might order these variables, so we # can't test for the actual offset from .data, hence the regexp. -check debug_msg.err "debug_msg.o: in function fn_array:debug_msg.cc(.data+0x[0-9a-fA-F]*): undefined reference to 'undef_fn1()'" -check debug_msg.err "debug_msg.o: in function fn_array:debug_msg.cc(.data+0x[0-9a-fA-F]*): undefined reference to 'undef_fn2()'" -check debug_msg.err "debug_msg.o: in function badref1:debug_msg.cc(.data+0x[0-9a-fA-F]*): undefined reference to 'undef_int'" +check debug_msg.err "debug_msg.o: in function fn_array:debug_msg.cc(.data+0x[0-9a-fA-F]*): error: undefined reference to 'undef_fn1()'" +check debug_msg.err "debug_msg.o: in function fn_array:debug_msg.cc(.data+0x[0-9a-fA-F]*): error: undefined reference to 'undef_fn2()'" +check debug_msg.err "debug_msg.o: in function badref1:debug_msg.cc(.data+0x[0-9a-fA-F]*): error: undefined reference to 'undef_int'" -check debug_msg.err "debug_msg.o: in function Base::virtfn():${srcdir}/debug_msg.cc:50: undefined reference to 'undef_fn1()'" -check debug_msg.err "debug_msg.o: in function Derived::virtfn():${srcdir}/debug_msg.cc:55: undefined reference to 'undef_fn2()'" -check debug_msg.err "debug_msg.o: in function int testfn<int>(int):${srcdir}/debug_msg.cc:43: undefined reference to 'undef_fn1()'" -check debug_msg.err "debug_msg.o: in function int testfn<int>(int):${srcdir}/debug_msg.cc:44: undefined reference to 'undef_fn2()'" -check debug_msg.err "debug_msg.o: in function int testfn<int>(int):${srcdir}/debug_msg.cc:45: undefined reference to 'undef_int'" -check debug_msg.err "debug_msg.o: in function int testfn<double>(double):${srcdir}/debug_msg.cc:43: undefined reference to 'undef_fn1()'" -check debug_msg.err "debug_msg.o: in function int testfn<double>(double):${srcdir}/debug_msg.cc:44: undefined reference to 'undef_fn2()'" -check debug_msg.err "debug_msg.o: in function int testfn<double>(double):${srcdir}/debug_msg.cc:45: undefined reference to 'undef_int'" +# These tests check only for the source file's file name (not the complete +# path) because use of -fdebug-prefix-map may change the path to the source +# file recorded in the objects. +check debug_msg.err "debug_msg.o: in function Base::virtfn():.*/debug_msg.cc:50: error: undefined reference to 'undef_fn1()'" +check debug_msg.err "debug_msg.o: in function Derived::virtfn():.*/debug_msg.cc:55: error: undefined reference to 'undef_fn2()'" +check debug_msg.err "debug_msg.o: in function int testfn<int>(int):.*/debug_msg.cc:43: error: undefined reference to 'undef_fn1()'" +check debug_msg.err "debug_msg.o: in function int testfn<int>(int):.*/debug_msg.cc:44: error: undefined reference to 'undef_fn2()'" +check debug_msg.err "debug_msg.o: in function int testfn<int>(int):.*/debug_msg.cc:.*: error: undefined reference to 'undef_int'" +check debug_msg.err "debug_msg.o: in function int testfn<double>(double):.*/debug_msg.cc:43: error: undefined reference to 'undef_fn1()'" +check debug_msg.err "debug_msg.o: in function int testfn<double>(double):.*/debug_msg.cc:44: error: undefined reference to 'undef_fn2()'" +check debug_msg.err "debug_msg.o: in function int testfn<double>(double):.*/debug_msg.cc:.*: error: undefined reference to 'undef_int'" # Check we detected the ODR (One Definition Rule) violation. check debug_msg.err ": symbol 'Ordering::operator()(int, int)' defined in multiple places (possible ODR violation):" @@ -75,17 +78,17 @@ check debug_msg.err "odr_violation2.cc:5" # When linking together .so's, we don't catch the line numbers, but we # still find all the undefined variables, and the ODR violation. -check debug_msg_so.err "debug_msg.so: undefined reference to 'undef_fn1()'" -check debug_msg_so.err "debug_msg.so: undefined reference to 'undef_fn2()'" -check debug_msg_so.err "debug_msg.so: undefined reference to 'undef_int'" +check debug_msg_so.err "debug_msg.so: error: undefined reference to 'undef_fn1()'" +check debug_msg_so.err "debug_msg.so: error: undefined reference to 'undef_fn2()'" +check debug_msg_so.err "debug_msg.so: error: undefined reference to 'undef_int'" check debug_msg_so.err ": symbol 'Ordering::operator()(int, int)' defined in multiple places (possible ODR violation):" check debug_msg_so.err "odr_violation1.cc:5" check debug_msg_so.err "odr_violation2.cc:5" # These messages shouldn't need any debug info to detect: -check debug_msg_ndebug.err "debug_msg_ndebug.so: undefined reference to 'undef_fn1()'" -check debug_msg_ndebug.err "debug_msg_ndebug.so: undefined reference to 'undef_fn2()'" -check debug_msg_ndebug.err "debug_msg_ndebug.so: undefined reference to 'undef_int'" +check debug_msg_ndebug.err "debug_msg_ndebug.so: error: undefined reference to 'undef_fn1()'" +check debug_msg_ndebug.err "debug_msg_ndebug.so: error: undefined reference to 'undef_fn2()'" +check debug_msg_ndebug.err "debug_msg_ndebug.so: error: undefined reference to 'undef_int'" # However, we shouldn't detect or declare any ODR violation check_missing debug_msg_ndebug.err "(possible ODR violation)" diff --git a/binutils-2.19/gold/testsuite/discard_locals_relocatable_test.c b/binutils-2.19/gold/testsuite/discard_locals_relocatable_test.c new file mode 100644 index 0000000..d46151e --- /dev/null +++ b/binutils-2.19/gold/testsuite/discard_locals_relocatable_test.c @@ -0,0 +1,43 @@ +/* discard_locals_relocatable_test.c -- test --discard-locals/--discard-all -r + + Copyright 2010 Free Software Foundation, Inc. + Viktor Kutuzov <vkutuzov@accesssoftek.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. + + This is a test of a common symbol in the main program and a + versioned symbol in a shared library. The common symbol in the + main program should override the shared library symbol. */ + +/* Note: use GCC -fPIC option to compile this test. */ + +/* Local symbol format for generic ELF target. + Use GCC -Wa,-L option to preserve this local symbol + in the output object file. */ +asm (".Lshould_be_discarded:"); + +extern void print_func (const char* s); + +extern int func (void); + +int +func (void) +{ + print_func ("local string"); + return 0; +} diff --git a/binutils-2.19/gold/testsuite/discard_locals_test.c b/binutils-2.19/gold/testsuite/discard_locals_test.c new file mode 100644 index 0000000..b722447 --- /dev/null +++ b/binutils-2.19/gold/testsuite/discard_locals_test.c @@ -0,0 +1,40 @@ +/* discard_locals_test.c -- test --discard-locals option. + + Copyright 2009 Free Software Foundation, Inc. + Doug Kwan <dougkwan@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. + + This is a test of a common symbol in the main program and a + versioned symbol in a shared library. The common symbol in the + main program should override the shared library symbol. */ + +/* Local symbol format for generic ELF target. */ +asm (".Lshould_be_discarded:"); + +#ifdef __i386__ +/* Additional local symbol format for the i386 target. */ +asm (".Xshould_be_discarded:"); +#endif + +int +main (void) +{ + return 0; +} + diff --git a/binutils-2.19/gold/testsuite/discard_locals_test.sh b/binutils-2.19/gold/testsuite/discard_locals_test.sh new file mode 100755 index 0000000..3fc679a --- /dev/null +++ b/binutils-2.19/gold/testsuite/discard_locals_test.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +# discard_locals_test.sh -- test that local symbols are discarded. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with exclude_libs_test.c, a C source file +# linked with option -Wl,--exclude-libs. We run readelf on +# the resulting executable and check that symbols from two test library +# archives are correctly hidden or left unmodified. + +check_discarded() +{ + file=$1 + sym=$2 + + found=`egrep $sym $file` + if test -n "$found"; then + echo "These local symbols are not discarded in $file:" + echo "$found" + exit 1 + fi +} + +check_non_discarded() +{ + file=$1 + sym=$2 + + found=`egrep $sym $file` + if test -z "$found"; then + echo "This local symbol is discarded in $file:" + echo "$2" + exit 1 + fi +} + +check_discarded "discard_locals_test.syms" "should_be_discarded" + +check_non_discarded "discard_locals_relocatable_test1.syms" ".LC0" +check_discarded "discard_locals_relocatable_test1.syms" "should_be_discarded" +check_non_discarded "discard_locals_relocatable_test2.syms" ".LC0" +check_discarded "discard_locals_relocatable_test2.syms" "should_be_discarded" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/dynamic_list.sh b/binutils-2.19/gold/testsuite/dynamic_list.sh new file mode 100755 index 0000000..dfd9f0f --- /dev/null +++ b/binutils-2.19/gold/testsuite/dynamic_list.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +# dynamic_list.sh -- test --dynamic-list and --dynamic-list-* + +# Copyright 2008 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with dynamic_list.t, which is a dynamic-list script. + +check() +{ + if ! grep -qw "$2" "$1" + then + echo "Did not find expected text in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check dynamic_list.stdout "main" # comes via --dynamic-list +check dynamic_list.stdout "_ZdlPv" # "operator delete(void*)" +check dynamic_list.stdout "_Z4t1_6v" # t1_6() +check dynamic_list.stdout "_ZN4t16aC2Ev" # t16a:t16a() +check dynamic_list.stdout "_ZN4t16aD1Ev" # t16a:~t16a() +check dynamic_list.stdout "_ZN4t16a1tEv" # t16a:t() +check dynamic_list.stdout "_ZTI4t16a" # typeinfo for t16a +check dynamic_list.stdout "_ZTI4t16b" # typeinfo for t16b +check dynamic_list.stdout "_ZTS4t16a" # typeinfo name for t16a +check dynamic_list.stdout "_ZTS4t16b" # typeinfo name for t16b +check dynamic_list.stdout "t20v" # comes via --dynamic-list-data diff --git a/binutils-2.19/gold/testsuite/dynamic_list.t b/binutils-2.19/gold/testsuite/dynamic_list.t new file mode 100644 index 0000000..6457173 --- /dev/null +++ b/binutils-2.19/gold/testsuite/dynamic_list.t @@ -0,0 +1,11 @@ +{ + main; + not_a_symbol; + global; + extern "C++" { t1_6* }; +}; +{ + extern "C++" { t16a* }; + local; + extern; +}; diff --git a/binutils-2.19/gold/testsuite/exclude_libs_test.c b/binutils-2.19/gold/testsuite/exclude_libs_test.c new file mode 100644 index 0000000..85441a0 --- /dev/null +++ b/binutils-2.19/gold/testsuite/exclude_libs_test.c @@ -0,0 +1,14 @@ +extern void lib1_default (void); +extern void lib2_default (void); +extern void lib3_default (void); + +int +main (int argc __attribute__ ((unused)), + char** argv __attribute__ ((unused))) +{ + lib1_default (); + lib2_default (); + lib3_default (); + return 0; +} + diff --git a/binutils-2.19/gold/testsuite/exclude_libs_test.sh b/binutils-2.19/gold/testsuite/exclude_libs_test.sh new file mode 100755 index 0000000..65ce03b --- /dev/null +++ b/binutils-2.19/gold/testsuite/exclude_libs_test.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +# exclude_libs_test.sh -- test that library symbols are not exported. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with exclude_libs_test.c, a C source file +# linked with option -Wl,--exclude-libs. We run readelf on +# the resulting executable and check that symbols from two test library +# archives are correctly hidden or left unmodified. + +check() +{ + file=$1 + sym=$2 + vis=$3 + + found=`grep " $sym\$" $file` + if test -z "$found"; then + echo "Symbol $sym not found." + exit 1 + fi + + match_vis=`grep " $sym\$" $file | grep " $vis "` + if test -z "$match_vis"; then + echo "Expected symbol $sym to have visibility $vis but found" + echo "$found" + exit 1 + fi +} + +check "exclude_libs_test.syms" "lib1_default" "HIDDEN" +check "exclude_libs_test.syms" "lib1_protected" "HIDDEN" +check "exclude_libs_test.syms" "lib1_internal" "INTERNAL" +check "exclude_libs_test.syms" "lib1_hidden" "HIDDEN" +check "exclude_libs_test.syms" "lib2_default" "DEFAULT" +check "exclude_libs_test.syms" "lib2_protected" "PROTECTED" +check "exclude_libs_test.syms" "lib2_internal" "INTERNAL" +check "exclude_libs_test.syms" "lib2_hidden" "HIDDEN" +check "exclude_libs_test.syms" "lib3_default" "HIDDEN" +check "exclude_libs_test.syms" "lib3_protected" "HIDDEN" +check "exclude_libs_test.syms" "lib3_internal" "INTERNAL" +check "exclude_libs_test.syms" "lib3_hidden" "HIDDEN" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/exclude_libs_test_1.c b/binutils-2.19/gold/testsuite/exclude_libs_test_1.c new file mode 100644 index 0000000..48b617b --- /dev/null +++ b/binutils-2.19/gold/testsuite/exclude_libs_test_1.c @@ -0,0 +1,32 @@ +void lib1_default (void); +void lib1_hidden (void); +void lib1_internal (void); +void lib1_protected (void); +void lib1_ref (void); +extern void lib2_default (void); + +void __attribute__((visibility ("default"))) +lib1_default (void) +{ +} + +void __attribute__((visibility ("hidden"))) +lib1_hidden (void) +{ +} + +void __attribute__((visibility ("internal"))) +lib1_internal (void) +{ +} + +void __attribute__((visibility ("protected"))) +lib1_protected (void) +{ +} + +void +lib1_ref (void) +{ + lib2_default (); +} diff --git a/binutils-2.19/gold/testsuite/exclude_libs_test_2.c b/binutils-2.19/gold/testsuite/exclude_libs_test_2.c new file mode 100644 index 0000000..a8952e7 --- /dev/null +++ b/binutils-2.19/gold/testsuite/exclude_libs_test_2.c @@ -0,0 +1,24 @@ +void lib2_default (void); +void lib2_hidden (void); +void lib2_internal (void); +void lib2_protected (void); + +void __attribute__((visibility ("default"))) +lib2_default (void) +{ +} + +void __attribute__((visibility ("hidden"))) +lib2_hidden (void) +{ +} + +void __attribute__((visibility ("internal"))) +lib2_internal (void) +{ +} + +void __attribute__((visibility ("protected"))) +lib2_protected (void) +{ +} diff --git a/binutils-2.19/gold/testsuite/exclude_libs_test_3.c b/binutils-2.19/gold/testsuite/exclude_libs_test_3.c new file mode 100644 index 0000000..b4e2635 --- /dev/null +++ b/binutils-2.19/gold/testsuite/exclude_libs_test_3.c @@ -0,0 +1,24 @@ +void lib3_default (void); +void lib3_hidden (void); +void lib3_internal (void); +void lib3_protected (void); + +void __attribute__((visibility ("default"))) +lib3_default (void) +{ +} + +void __attribute__((visibility ("hidden"))) +lib3_hidden (void) +{ +} + +void __attribute__((visibility ("internal"))) +lib3_internal (void) +{ +} + +void __attribute__((visibility ("protected"))) +lib3_protected (void) +{ +} diff --git a/binutils-2.19/gold/testsuite/gc_comdat_test.sh b/binutils-2.19/gold/testsuite/gc_comdat_test.sh new file mode 100755 index 0000000..baff98d --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_comdat_test.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +# gc_comdat_test.sh -- test --gc-sections + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if comdat's and garbage +# collection work together. Files gc_comdat_test_1.cc and +# gc_comdat_test_2.cc are used in this test. This program checks +# if the kept comdat section is garbage collected. + +check() +{ + if grep -q "$2" "$1" + then + echo "Garbage collection failed to collect :" + echo " $2" + exit 1 + fi +} + +check gc_comdat_test.stdout "foo()" +check gc_comdat_test.stdout "bar()" +check gc_comdat_test.stdout "int GetMax<int>(int, int)" diff --git a/binutils-2.19/gold/testsuite/gc_comdat_test_1.cc b/binutils-2.19/gold/testsuite/gc_comdat_test_1.cc new file mode 100644 index 0000000..0b4b286 --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_comdat_test_1.cc @@ -0,0 +1,42 @@ +// gc_comdat_test_1.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if comdat's and garbage +// collection work together. This file is compiled with -g. The +// comdat kept function for GetMax is garbage. + +int foo(); +template <class T> +T GetMax (T a, T b) +{ + return (a > b)?a:b; +} + +int bar () +{ + return GetMax <int> (4,5); +} + +int main() +{ + return 0; +} diff --git a/binutils-2.19/gold/testsuite/gc_comdat_test_2.cc b/binutils-2.19/gold/testsuite/gc_comdat_test_2.cc new file mode 100644 index 0000000..5841bdf --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_comdat_test_2.cc @@ -0,0 +1,35 @@ +// gc_comdat_test_2.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if comdat's and garbage +// collection work together. This file is compiled with -g. + +template <class T> +T GetMax (T a, T b) +{ + return (a > b)?a:b; +} + +int foo () +{ + return GetMax <int> (10,11); +} diff --git a/binutils-2.19/gold/testsuite/gc_orphan_section_test.cc b/binutils-2.19/gold/testsuite/gc_orphan_section_test.cc new file mode 100644 index 0000000..3443f8d --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_orphan_section_test.cc @@ -0,0 +1,36 @@ +// gc_orphan_section_test.cc -- a test case for gold + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if garbage collection does not +// discard orphan sections when references to them through __start_XXX +// and __stop_XXX are present. Here section _foo must not be gc'ed but +// _boo should be gc'ed. + +extern const int *__start__foo; +int foo __attribute__((__section__("_foo"))) = 1; +int boo __attribute__((__section__("_boo"))) = 1; + +int main() +{ + return *__start__foo; +} + diff --git a/binutils-2.19/gold/testsuite/gc_orphan_section_test.sh b/binutils-2.19/gold/testsuite/gc_orphan_section_test.sh new file mode 100755 index 0000000..6ce524d --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_orphan_section_test.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +# gc_orphan_section_test.sh -- test --gc-sections + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if gc-sections works as expected +# with orphan sections. +# File gc_orphan_sections_test.cc is in this test. This program checks if +# the orphan sections are retained when they are referenced through +# __start_XXX and __stop_XXX symbols. + +check() +{ + if grep -q " boo" "$1" + then + echo "Garbage collection failed to collect boo" + exit 1 + fi + grep_foo=`grep -q " foo" $1` + if [ $? != 0 ]; + then + echo "Garbage collection should not discard foo" + exit 1 + fi +} + +check gc_orphan_section_test.stdout diff --git a/binutils-2.19/gold/testsuite/gc_tls_test.cc b/binutils-2.19/gold/testsuite/gc_tls_test.cc new file mode 100644 index 0000000..1b10d98 --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_tls_test.cc @@ -0,0 +1,32 @@ +// gc_tls_test.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if tls sections are garbage +// collected with --gc-sections. + +__thread int number; + +int main() +{ + return 0; +} + diff --git a/binutils-2.19/gold/testsuite/gc_tls_test.sh b/binutils-2.19/gold/testsuite/gc_tls_test.sh new file mode 100755 index 0000000..c4635c9 --- /dev/null +++ b/binutils-2.19/gold/testsuite/gc_tls_test.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# gc_tls_test.sh -- test -- gc + tls + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if tls sections are garbage +# collected with --gc-sections. File gc_tls_test.cc is in this test. + +check() +{ + if grep -q "$2" "$1" + then + echo "Garbage collection failed to collect tls variable:" + echo " $2" + exit 1 + fi + +} + +check gc_tls_test.stdout "number" diff --git a/binutils-2.19/gold/testsuite/hidden_test.sh b/binutils-2.19/gold/testsuite/hidden_test.sh new file mode 100755 index 0000000..df51b37 --- /dev/null +++ b/binutils-2.19/gold/testsuite/hidden_test.sh @@ -0,0 +1,66 @@ +#!/bin/sh + +# hidden_test.sh -- a test case for hidden and internal symbols. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with hidden_test_main.c and hidden_test_1.c. +# The main program defines several symbols with each of the ELF +# visibilities, and the shared library attempts to reference the +# symbols. We try to link the program and check that the expected +# error messages are issued for the references to internal and +# hidden symbols. The errors will be found in hidden_test.err. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected error in $1:" + echo " $2" + echo "" + echo "Actual error output below:" + cat "$1" + exit 1 + fi +} + +check_missing() +{ + if grep -q "$2" "$1" + then + echo "Found unexpected error in $1:" + echo " $2" + echo "" + echo "Actual error output below:" + cat "$1" + exit 1 + fi +} + +# We should see errors for hidden and internal symbols. +check hidden_test.err "hidden symbol 'main_hidden' in hidden_test_main.o is referenced by DSO libhidden.so" +check hidden_test.err "internal symbol 'main_internal' in hidden_test_main.o is referenced by DSO libhidden.so" + +# We shouldn't see errors for the default and protected symbols. +check_missing hidden_test.err "main_default" +check_missing hidden_test.err "main_protected" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/hidden_test_1.c b/binutils-2.19/gold/testsuite/hidden_test_1.c new file mode 100644 index 0000000..f685cab --- /dev/null +++ b/binutils-2.19/gold/testsuite/hidden_test_1.c @@ -0,0 +1,41 @@ +/* hidden_test_1.c -- test hidden and internal symbols + + Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com> + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. + + This is a test of symbols of various visibilities in the main program + and attempts to reference those symbols from a shared library. + The linker should issue an error message for references to hidden + and internal symbols. */ + +extern void main_default (void); +extern void main_hidden (void); +extern void main_internal (void); +extern void main_protected (void); + +int +lib1 (void) +{ + main_default (); + main_hidden (); + main_internal (); + main_protected (); + return 0; +} diff --git a/binutils-2.19/gold/testsuite/hidden_test_main.c b/binutils-2.19/gold/testsuite/hidden_test_main.c new file mode 100644 index 0000000..c54864d --- /dev/null +++ b/binutils-2.19/gold/testsuite/hidden_test_main.c @@ -0,0 +1,61 @@ +/* hidden_test_main.c -- test hidden and internal symbols + + Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com> + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. + + This is a test of symbols of various visibilities in the main program + and attempts to reference those symbols from a shared library. + The linker should issue an error message for references to hidden + and internal symbols. */ + +extern void lib1 (void); + +void main_default (void); +void main_hidden (void); +void main_internal (void); +void main_protected (void); + +void __attribute__((visibility ("default"))) +main_default (void) +{ +} + +void __attribute__((visibility ("hidden"))) +main_hidden (void) +{ +} + +void __attribute__((visibility ("internal"))) +main_internal (void) +{ +} + +void __attribute__((visibility ("protected"))) +main_protected (void) +{ +} + +int +main (int argc __attribute__ ((unused)), + char** argv __attribute__ ((unused))) +{ + lib1 (); + return 0; +} diff --git a/binutils-2.19/gold/testsuite/icf_keep_unique_test.cc b/binutils-2.19/gold/testsuite/icf_keep_unique_test.cc new file mode 100644 index 0000000..37f6437 --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_keep_unique_test.cc @@ -0,0 +1,39 @@ +// icf_keep_unique_test.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if --keep-unique works +// as intended when used with --icf. + +int kept_func() +{ + return 0; +} + +int unique_func() +{ + return 0; +} + +int main() +{ + return 1; +} diff --git a/binutils-2.19/gold/testsuite/icf_keep_unique_test.sh b/binutils-2.19/gold/testsuite/icf_keep_unique_test.sh new file mode 100755 index 0000000..c267373 --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_keep_unique_test.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +# icf_keep_unique_test.sh -- test --icf --keep-unique + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --keep-unique works +# as intended when used with --icf. + +check() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 = $func_addr_2 ] + then + echo "Identical Code Folding with keep-unique failed to unfold" $2 + exit 1 + fi +} + +check icf_keep_unique_test.stdout "kept_func" "unique_func" diff --git a/binutils-2.19/gold/testsuite/icf_safe_so_test.cc b/binutils-2.19/gold/testsuite/icf_safe_so_test.cc new file mode 100644 index 0000000..5e4453b --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_safe_so_test.cc @@ -0,0 +1,73 @@ +// icf_safe_so_test.cc -- a test case for gold + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if identical code folding +// in safe mode correctly folds functions in a shared object. The +// foo_* functions below should not be folded. For x86-64, +// foo_glob and bar_glob should be folded as their function pointers +// are addresses of PLT entries in shared objects. + +int __attribute__ ((visibility ("protected"))) +foo_prot() +{ + return 1; +} + +int __attribute__ ((visibility ("hidden"))) +foo_hidden() +{ + return 1; +} + +int __attribute__ ((visibility ("internal"))) +foo_internal() +{ + return 1; +} + +static int +foo_static() +{ + return 1; +} + +int foo_glob() +{ + return 2; +} + +int bar_glob() +{ + return 2; +} + +int main() +{ + int (*p)() = foo_glob; + (void)p; + foo_static(); + foo_prot(); + foo_hidden(); + foo_internal(); + return 0; +} + diff --git a/binutils-2.19/gold/testsuite/icf_safe_so_test.sh b/binutils-2.19/gold/testsuite/icf_safe_so_test.sh new file mode 100755 index 0000000..db2e73e --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_safe_so_test.sh @@ -0,0 +1,69 @@ +# icf_safe_so_test.sh -- test --icf=safe + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --icf=safe works as expected. +# File icf_safe_so_test.cc is in this test. The goal of this script is +# to verify if identical code folding in safe mode correctly folds +# functions in a shared object. + +check_nofold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 = $func_addr_2 ]; + then + echo "Safe Identical Code Folding folded" $2 "and" $3 + exit 1 + fi +} + +check_fold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 != $func_addr_2 ]; + then + echo "Safe Identical Code Folding did not fold " $2 "and" $3 + exit 1 + fi +} + +arch_specific_safe_fold() +{ + grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2` + if [ $? == 0 ]; + then + check_fold $1 $3 $4 + else + check_nofold $1 $3 $4 + fi +} + +check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_hidden" +check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_internal" +check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_static" +check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_internal" +check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_static" +check_nofold icf_safe_so_test_1.stdout "foo_internal" "foo_static" +arch_specific_safe_fold icf_safe_so_test_1.stdout icf_safe_so_test_2.stdout \ + "foo_glob" "bar_glob" + diff --git a/binutils-2.19/gold/testsuite/icf_safe_test.cc b/binutils-2.19/gold/testsuite/icf_safe_test.cc new file mode 100644 index 0000000..3edb865 --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_safe_test.cc @@ -0,0 +1,63 @@ +// icf_safe_test.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if identical code folding +// in safe mode correctly folds only ctors and dtors. kept_func_1 must +// not be folded into kept_func_2 other than for X86-64 which can +// use relocation types to determine if function pointers are taken. +// kept_func_3 should never be folded as its pointer is taken. The ctor +// and dtor of class A must be folded. + +class A +{ + public: + A() + { + } + ~A() + { + } +}; + +A a; + +int kept_func_1() +{ + return 1; +} + +int kept_func_2() +{ + return 1; +} + +int kept_func_3() +{ + return 1; +} + +int main() +{ + int (*p)() = kept_func_3; + p(); + return 0; +} diff --git a/binutils-2.19/gold/testsuite/icf_safe_test.sh b/binutils-2.19/gold/testsuite/icf_safe_test.sh new file mode 100755 index 0000000..540dcc2 --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_safe_test.sh @@ -0,0 +1,65 @@ +# icf_safe_test.sh -- test --icf=safe + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --icf=safe works as expected. +# File icf_safe_test.cc is in this test. This program checks if only +# ctors and dtors are folded, except for x86-64, which uses relocation +# types to detect if function pointers are taken. + +check_nofold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 = $func_addr_2 ] + then + echo "Safe Identical Code Folding folded" $2 "and" $3 + exit 1 + fi +} + +check_fold() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 != $func_addr_2 ] + then + echo "Safe Identical Code Folding did not fold " $2 "and" $3 + exit 1 + fi +} + +arch_specific_safe_fold() +{ + grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2` + if [ $? == 0 ]; + then + check_fold $1 $3 $4 + else + check_nofold $1 $3 $4 + fi +} + +arch_specific_safe_fold icf_safe_test_1.stdout icf_safe_test_2.stdout \ + "kept_func_1" "kept_func_2" +check_fold icf_safe_test_1.stdout "_ZN1AD1Ev" "_ZN1AC1Ev" +check_nofold icf_safe_test_1.stdout "kept_func_3" "kept_func_1" +check_nofold icf_safe_test_1.stdout "kept_func_3" "kept_func_2" diff --git a/binutils-2.19/gold/testsuite/icf_test.cc b/binutils-2.19/gold/testsuite/icf_test.cc new file mode 100644 index 0000000..c7a5ea9 --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_test.cc @@ -0,0 +1,51 @@ +// icf_test.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if identical code folding +// correctly identifies and folds functions. folded_func must be +// folded into kept_func. + +int common() +{ + return 1; +} + +int kept_func() +{ + common(); + // Recursive call. + kept_func(); + return 1; +} + +int folded_func() +{ + common(); + // Recursive call. + folded_func(); + return 1; +} + +int main() +{ + return 0; +} diff --git a/binutils-2.19/gold/testsuite/icf_test.sh b/binutils-2.19/gold/testsuite/icf_test.sh new file mode 100755 index 0000000..5f1481c --- /dev/null +++ b/binutils-2.19/gold/testsuite/icf_test.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# icf_test.sh -- test --icf + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if icf works as expected. +# File icf_test.cc is in this test. This program checks if the +# identical sections are correctly folded. + +check() +{ + func_addr_1=`grep $2 $1 | awk '{print $1}'` + func_addr_2=`grep $3 $1 | awk '{print $1}'` + if [ $func_addr_1 != $func_addr_2 ] + then + echo "Identical Code Folding failed to fold" $2 "and" $3 + exit 1 + fi +} + +check icf_test.stdout "folded_func" "kept_func" diff --git a/binutils-2.19/gold/testsuite/incremental_test.sh b/binutils-2.19/gold/testsuite/incremental_test.sh new file mode 100755 index 0000000..8da60e0 --- /dev/null +++ b/binutils-2.19/gold/testsuite/incremental_test.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# incremental_test.sh -- test that incremental linking information is correct. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Rafael Avila de Espindola <espindola@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +set -e +cat incremental_test.cmdline | grep "gcctestdir/ld " | cut -d ' ' -f 2- > \ + actual + +cat incremental_test.stdout | grep "Link command line" | cut -d : -f 2- | \ + cut -d ' ' -f 3- | sed "s/'//g" > recorded + +diff actual recorded +rm actual recorded + +exit 0
\ No newline at end of file diff --git a/binutils-2.19/gold/testsuite/incremental_test_1.c b/binutils-2.19/gold/testsuite/incremental_test_1.c new file mode 100644 index 0000000..9783515 --- /dev/null +++ b/binutils-2.19/gold/testsuite/incremental_test_1.c @@ -0,0 +1,21 @@ +// Copyright 2009 Free Software Foundation, Inc. +// Written by Rafael Avila de Espindola <espindola@google.com> + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +int a; diff --git a/binutils-2.19/gold/testsuite/incremental_test_2.c b/binutils-2.19/gold/testsuite/incremental_test_2.c new file mode 100644 index 0000000..050986e --- /dev/null +++ b/binutils-2.19/gold/testsuite/incremental_test_2.c @@ -0,0 +1,25 @@ +// Copyright 2009 Free Software Foundation, Inc. +// Written by Rafael Avila de Espindola <espindola@google.com> + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +int b; + +int main(void) { + return 0; +} diff --git a/binutils-2.19/gold/testsuite/initpri1.c b/binutils-2.19/gold/testsuite/initpri1.c index 890df03..1c5252d 100644 --- a/binutils-2.19/gold/testsuite/initpri1.c +++ b/binutils-2.19/gold/testsuite/initpri1.c @@ -1,6 +1,6 @@ /* initpri1.c -- test constructor priorities. - Copyright 2007, 2008 Free Software Foundation, Inc. + Copyright 2007, 2008, 2009 Free Software Foundation, Inc. Copied from the gcc testsuite, where the test was contributed by Mark Mitchell <mark@codesourcery.com>. @@ -19,20 +19,22 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - MA 02110-1301, USA. + MA 02110-1301, USA. */ - This is a test of a common symbol in the main program and a - versioned symbol in a shared library. The common symbol in the - main program should override the shared library symbol. */ +/* This tests that the linker handles constructor and destructor + priorities correctly. */ #include <stdlib.h> +/* Constructor priorities in attributes were added in gcc 4.3. */ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) + int i; int j; -void c1() __attribute__((constructor (500))); -void c2() __attribute__((constructor (700))); -void c3() __attribute__((constructor (600))); +void c1(void) __attribute__((constructor (500))); +void c2(void) __attribute__((constructor (700))); +void c3(void) __attribute__((constructor (600))); void c1() { if (i++ != 0) @@ -49,9 +51,9 @@ void c3() { abort (); } -void d1() __attribute__((destructor (500))); -void d2() __attribute__((destructor (700))); -void d3() __attribute__((destructor (600))); +void d1(void) __attribute__((destructor (500))); +void d2(void) __attribute__((destructor (700))); +void d3(void) __attribute__((destructor (600))); void d1() { if (--i != 0) @@ -70,7 +72,7 @@ void d3() { abort (); } -void cd4() __attribute__((constructor (800), destructor (800))); +void cd4(void) __attribute__((constructor (800), destructor (800))); void cd4() { if (i != 3) @@ -78,7 +80,7 @@ void cd4() { ++j; } -void cd5() __attribute__((constructor, destructor)); +void cd5(void) __attribute__((constructor, destructor)); void cd5() { if (i != 3) @@ -86,10 +88,18 @@ void cd5() { ++j; } -int main () { +int main (void) { if (i != 3) return 1; if (j != 2) abort (); return 0; } + +#else /* !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) */ + +int main (void) { + exit (0); +} + +#endif /* !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) */ diff --git a/binutils-2.19/gold/testsuite/large.c b/binutils-2.19/gold/testsuite/large.c new file mode 100644 index 0000000..796242a --- /dev/null +++ b/binutils-2.19/gold/testsuite/large.c @@ -0,0 +1,59 @@ +/* large.c -- a test case for gold + + Copyright 2009 Free Software Foundation, Inc. + Written by Ian Lance Taylor <iant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include <assert.h> + +/* Test large sections in gold. */ + +int v1; +int v2 = 1; +int v3[0x10000]; +int v4[0x10000] = { 1 }; +const int v5[0x10000] = { 2 }; +int v6; +int v7 = 1; + +int +main (int argc __attribute__ ((unused)), char** argv __attribute ((unused))) +{ + assert (v1 == 0); + assert (v2 == 1); + assert (v3[0] == 0 && v3[0xffff] == 0); + assert (v4[0] == 1 && v4[0xffff] == 0); + assert (v5[0] == 2 && v5[0xffff] == 0); + assert (v6 == 0); + assert (v7 == 1); + + /* The large symbols must follow the small ones. */ + assert (&v1 < v3 && &v1 < v4 && &v1 < v5); + assert (&v2 < v3 && &v2 < v4 && &v2 < v5); + assert (&v6 < v3 && &v6 < v4 && &v6 < v5); + assert (&v7 < v3 && &v7 < v4 && &v7 < v5); + + /* Large symbols should be BSS followed by read-only followed by + read-write. */ + assert (v3 < v4); + assert (v3 < v5); + assert (v5 < v4); + + return 0; +} diff --git a/binutils-2.19/gold/testsuite/no_version_test.c b/binutils-2.19/gold/testsuite/no_version_test.c new file mode 100644 index 0000000..e42d04f --- /dev/null +++ b/binutils-2.19/gold/testsuite/no_version_test.c @@ -0,0 +1,32 @@ +// ver_no_default.c -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Doug Kwan <dougkwan@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// We should not create any .gnu.version sections if symbol versioning +// is not used. + +extern int the_answer(void); + +int +the_answer(void) +{ + return 42; +} diff --git a/binutils-2.19/gold/testsuite/no_version_test.sh b/binutils-2.19/gold/testsuite/no_version_test.sh new file mode 100755 index 0000000..f4ca9b1 --- /dev/null +++ b/binutils-2.19/gold/testsuite/no_version_test.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# no_version_test.sh -- test that .gnu.version* sections are not created +# in a shared object when symbol versioning is not used. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com> + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with no_version_test.c, a C source file +# linked with option -shared -nostdlib. We run objdump on +# the resulting executable and check that .gnu.version* sections +# are not created. + +check() +{ + file=$1 + + found=`egrep "\.gnu\.version.*" $file` + if test -n "$found"; then + echo "These section should not be in $file:" + echo "$found" + exit 1 + fi +} + +check "no_version_test.stdout" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/object_unittest.cc b/binutils-2.19/gold/testsuite/object_unittest.cc index 93d4636..0451add 100644 --- a/binutils-2.19/gold/testsuite/object_unittest.cc +++ b/binutils-2.19/gold/testsuite/object_unittest.cc @@ -36,17 +36,16 @@ using namespace gold; template<int size, bool big_endian> bool -Sized_object_test(const unsigned char* test_file, unsigned int test_file_size, - Target* target_test_pointer) +Sized_object_test(const unsigned char* test_file, unsigned int test_file_size) { + parameters_clear_target(); // We need a pretend Task. const Task* task = reinterpret_cast<const Task*>(-1); Input_file input_file(task, "test.o", test_file, test_file_size); Object* object = make_elf_object("test.o", &input_file, 0, - test_file, test_file_size); + test_file, test_file_size, NULL); CHECK(object->name() == "test.o"); CHECK(!object->is_dynamic()); - CHECK(object->target() == target_test_pointer); CHECK(object->is_locked()); object->unlock(task); CHECK(!object->is_locked()); @@ -67,30 +66,30 @@ Object_test(Test_report*) #ifdef HAVE_TARGET_32_LITTLE if (!Sized_object_test<32, false>(test_file_1_32_little, - test_file_1_size_32_little, - target_test_pointer_32_little)) + test_file_1_size_32_little)) ++fail; + CHECK(¶meters->target() == target_test_pointer_32_little); #endif #ifdef HAVE_TARGET_32_BIG if (!Sized_object_test<32, true>(test_file_1_32_big, - test_file_1_size_32_big, - target_test_pointer_32_big)) + test_file_1_size_32_big)) ++fail; + CHECK(¶meters->target() == target_test_pointer_32_big); #endif #ifdef HAVE_TARGET_64_LITTLE if (!Sized_object_test<64, false>(test_file_1_64_little, - test_file_1_size_64_little, - target_test_pointer_64_little)) + test_file_1_size_64_little)) ++fail; + CHECK(¶meters->target() == target_test_pointer_64_little); #endif #ifdef HAVE_TARGET_64_BIG if (!Sized_object_test<64, true>(test_file_1_64_big, - test_file_1_size_64_big, - target_test_pointer_64_big)) + test_file_1_size_64_big)) ++fail; + CHECK(¶meters->target() == target_test_pointer_64_big); #endif return fail == 0; diff --git a/binutils-2.19/gold/testsuite/plugin_test.c b/binutils-2.19/gold/testsuite/plugin_test.c new file mode 100644 index 0000000..9d095e8 --- /dev/null +++ b/binutils-2.19/gold/testsuite/plugin_test.c @@ -0,0 +1,533 @@ +/* test_plugin.c -- simple linker plugin test + + Copyright 2008, 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "plugin-api.h" + +struct claimed_file +{ + const char* name; + void* handle; + int nsyms; + struct ld_plugin_symbol* syms; + struct claimed_file* next; +}; + +struct sym_info +{ + int size; + char* type; + char* bind; + char* vis; + char* sect; + char* name; +}; + +static struct claimed_file* first_claimed_file = NULL; +static struct claimed_file* last_claimed_file = NULL; + +static ld_plugin_register_claim_file register_claim_file_hook = NULL; +static ld_plugin_register_all_symbols_read register_all_symbols_read_hook = NULL; +static ld_plugin_register_cleanup register_cleanup_hook = NULL; +static ld_plugin_add_symbols add_symbols = NULL; +static ld_plugin_get_symbols get_symbols = NULL; +static ld_plugin_add_input_file add_input_file = NULL; +static ld_plugin_message message = NULL; +static ld_plugin_get_input_file get_input_file = NULL; +static ld_plugin_release_input_file release_input_file = NULL; + +#define MAXOPTS 10 + +static const char *opts[MAXOPTS]; +static int nopts = 0; + +enum ld_plugin_status onload(struct ld_plugin_tv *tv); +enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file, + int *claimed); +enum ld_plugin_status all_symbols_read_hook(void); +enum ld_plugin_status cleanup_hook(void); + +static void parse_readelf_line(char*, struct sym_info*); + +enum ld_plugin_status +onload(struct ld_plugin_tv *tv) +{ + struct ld_plugin_tv *entry; + int api_version = 0; + int gold_version = 0; + int i; + + for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry) + { + switch (entry->tv_tag) + { + case LDPT_API_VERSION: + api_version = entry->tv_u.tv_val; + break; + case LDPT_GOLD_VERSION: + gold_version = entry->tv_u.tv_val; + break; + case LDPT_LINKER_OUTPUT: + break; + case LDPT_OPTION: + if (nopts < MAXOPTS) + opts[nopts++] = entry->tv_u.tv_string; + break; + case LDPT_REGISTER_CLAIM_FILE_HOOK: + register_claim_file_hook = entry->tv_u.tv_register_claim_file; + break; + case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: + register_all_symbols_read_hook = + entry->tv_u.tv_register_all_symbols_read; + break; + case LDPT_REGISTER_CLEANUP_HOOK: + register_cleanup_hook = entry->tv_u.tv_register_cleanup; + break; + case LDPT_ADD_SYMBOLS: + add_symbols = entry->tv_u.tv_add_symbols; + break; + case LDPT_GET_SYMBOLS: + get_symbols = entry->tv_u.tv_get_symbols; + break; + case LDPT_ADD_INPUT_FILE: + add_input_file = entry->tv_u.tv_add_input_file; + break; + case LDPT_MESSAGE: + message = entry->tv_u.tv_message; + break; + case LDPT_GET_INPUT_FILE: + get_input_file = entry->tv_u.tv_get_input_file; + break; + case LDPT_RELEASE_INPUT_FILE: + release_input_file = entry->tv_u.tv_release_input_file; + break; + default: + break; + } + } + + if (message == NULL) + { + fprintf(stderr, "tv_message interface missing\n"); + return LDPS_ERR; + } + + if (register_claim_file_hook == NULL) + { + fprintf(stderr, "tv_register_claim_file_hook interface missing\n"); + return LDPS_ERR; + } + + if (register_all_symbols_read_hook == NULL) + { + fprintf(stderr, "tv_register_all_symbols_read_hook interface missing\n"); + return LDPS_ERR; + } + + if (register_cleanup_hook == NULL) + { + fprintf(stderr, "tv_register_cleanup_hook interface missing\n"); + return LDPS_ERR; + } + + (*message)(LDPL_INFO, "API version: %d", api_version); + (*message)(LDPL_INFO, "gold version: %d", gold_version); + + for (i = 0; i < nopts; ++i) + (*message)(LDPL_INFO, "option: %s", opts[i]); + + if ((*register_claim_file_hook)(claim_file_hook) != LDPS_OK) + { + (*message)(LDPL_ERROR, "error registering claim file hook"); + return LDPS_ERR; + } + + if ((*register_all_symbols_read_hook)(all_symbols_read_hook) != LDPS_OK) + { + (*message)(LDPL_ERROR, "error registering all symbols read hook"); + return LDPS_ERR; + } + + if ((*register_cleanup_hook)(cleanup_hook) != LDPS_OK) + { + (*message)(LDPL_ERROR, "error registering cleanup hook"); + return LDPS_ERR; + } + + return LDPS_OK; +} + +enum ld_plugin_status +claim_file_hook (const struct ld_plugin_input_file* file, int* claimed) +{ + int len; + off_t end_offset; + char buf[160]; + struct claimed_file* claimed_file; + struct ld_plugin_symbol* syms; + int nsyms = 0; + int maxsyms = 0; + FILE* irfile; + struct sym_info info; + int weak; + int def; + int vis; + int is_comdat; + int i; + + (*message)(LDPL_INFO, + "%s: claim file hook called (offset = %ld, size = %ld)", + file->name, (long)file->offset, (long)file->filesize); + + /* Look for the beginning of output from readelf -s. */ + irfile = fdopen(file->fd, "r"); + (void)fseek(irfile, file->offset, SEEK_SET); + end_offset = file->offset + file->filesize; + len = fread(buf, 1, 13, irfile); + if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0) + return LDPS_OK; + + /* Skip the two header lines. */ + (void) fgets(buf, sizeof(buf), irfile); + (void) fgets(buf, sizeof(buf), irfile); + + if (add_symbols == NULL) + { + fprintf(stderr, "tv_add_symbols interface missing\n"); + return LDPS_ERR; + } + + /* Parse the output from readelf. The columns are: + Index Value Size Type Binding Visibility Section Name. */ + syms = (struct ld_plugin_symbol*)malloc(sizeof(struct ld_plugin_symbol) * 8); + if (syms == NULL) + return LDPS_ERR; + maxsyms = 8; + while (ftell(irfile) < end_offset + && fgets(buf, sizeof(buf), irfile) != NULL) + { + parse_readelf_line(buf, &info); + + /* Ignore local symbols. */ + if (strncmp(info.bind, "LOCAL", 5) == 0) + continue; + + weak = strncmp(info.bind, "WEAK", 4) == 0; + if (strncmp(info.sect, "UND", 3) == 0) + def = weak ? LDPK_WEAKUNDEF : LDPK_UNDEF; + else if (strncmp(info.sect, "COM", 3) == 0) + def = LDPK_COMMON; + else + def = weak ? LDPK_WEAKDEF : LDPK_DEF; + + if (strncmp(info.vis, "INTERNAL", 8) == 0) + vis = LDPV_INTERNAL; + else if (strncmp(info.vis, "HIDDEN", 6) == 0) + vis = LDPV_HIDDEN; + else if (strncmp(info.vis, "PROTECTED", 9) == 0) + vis = LDPV_PROTECTED; + else + vis = LDPV_DEFAULT; + + /* If the symbol is listed in the options list, special-case + it as a comdat symbol. */ + is_comdat = 0; + for (i = 0; i < nopts; ++i) + { + if (info.name != NULL && strcmp(info.name, opts[i]) == 0) + { + is_comdat = 1; + break; + } + } + + if (nsyms >= maxsyms) + { + syms = (struct ld_plugin_symbol*) + realloc(syms, sizeof(struct ld_plugin_symbol) * maxsyms * 2); + if (syms == NULL) + return LDPS_ERR; + maxsyms *= 2; + } + + if (info.name == NULL) + syms[nsyms].name = NULL; + else + { + len = strlen(info.name); + syms[nsyms].name = malloc(len + 1); + strncpy(syms[nsyms].name, info.name, len + 1); + } + syms[nsyms].version = NULL; + syms[nsyms].def = def; + syms[nsyms].visibility = vis; + syms[nsyms].size = info.size; + syms[nsyms].comdat_key = is_comdat ? syms[nsyms].name : NULL; + syms[nsyms].resolution = LDPR_UNKNOWN; + ++nsyms; + } + + claimed_file = (struct claimed_file*) malloc(sizeof(struct claimed_file)); + if (claimed_file == NULL) + return LDPS_ERR; + + claimed_file->name = file->name; + claimed_file->handle = file->handle; + claimed_file->nsyms = nsyms; + claimed_file->syms = syms; + claimed_file->next = NULL; + if (last_claimed_file == NULL) + first_claimed_file = claimed_file; + else + last_claimed_file->next = claimed_file; + last_claimed_file = claimed_file; + + (*message)(LDPL_INFO, "%s: claiming file, adding %d symbols", + file->name, nsyms); + + if (nsyms > 0) + (*add_symbols)(file->handle, nsyms, syms); + + *claimed = 1; + return LDPS_OK; +} + +enum ld_plugin_status +all_symbols_read_hook(void) +{ + int i; + const char* res; + struct claimed_file* claimed_file; + struct ld_plugin_input_file file; + FILE* irfile; + off_t end_offset; + struct sym_info info; + int len; + char buf[160]; + char* p; + const char* filename; + + (*message)(LDPL_INFO, "all symbols read hook called"); + + if (get_symbols == NULL) + { + fprintf(stderr, "tv_get_symbols interface missing\n"); + return LDPS_ERR; + } + + for (claimed_file = first_claimed_file; + claimed_file != NULL; + claimed_file = claimed_file->next) + { + (*get_symbols)(claimed_file->handle, claimed_file->nsyms, + claimed_file->syms); + + for (i = 0; i < claimed_file->nsyms; ++i) + { + switch (claimed_file->syms[i].resolution) + { + case LDPR_UNKNOWN: + res = "UNKNOWN"; + break; + case LDPR_UNDEF: + res = "UNDEF"; + break; + case LDPR_PREVAILING_DEF: + res = "PREVAILING_DEF_REG"; + break; + case LDPR_PREVAILING_DEF_IRONLY: + res = "PREVAILING_DEF_IRONLY"; + break; + case LDPR_PREEMPTED_REG: + res = "PREEMPTED_REG"; + break; + case LDPR_PREEMPTED_IR: + res = "PREEMPTED_IR"; + break; + case LDPR_RESOLVED_IR: + res = "RESOLVED_IR"; + break; + case LDPR_RESOLVED_EXEC: + res = "RESOLVED_EXEC"; + break; + case LDPR_RESOLVED_DYN: + res = "RESOLVED_DYN"; + break; + default: + res = "?"; + break; + } + (*message)(LDPL_INFO, "%s: %s: %s", claimed_file->name, + claimed_file->syms[i].name, res); + } + } + + if (add_input_file == NULL) + { + fprintf(stderr, "tv_add_input_file interface missing\n"); + return LDPS_ERR; + } + if (get_input_file == NULL) + { + fprintf(stderr, "tv_get_input_file interface missing\n"); + return LDPS_ERR; + } + if (release_input_file == NULL) + { + fprintf(stderr, "tv_release_input_file interface missing\n"); + return LDPS_ERR; + } + + for (claimed_file = first_claimed_file; + claimed_file != NULL; + claimed_file = claimed_file->next) + { + (*get_input_file) (claimed_file->handle, &file); + + /* Look for the beginning of output from readelf -s. */ + irfile = fdopen(file.fd, "r"); + (void)fseek(irfile, file.offset, SEEK_SET); + end_offset = file.offset + file.filesize; + len = fread(buf, 1, 13, irfile); + if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0) + { + fprintf(stderr, "%s: can't re-read original input file\n", + claimed_file->name); + return LDPS_ERR; + } + + /* Skip the two header lines. */ + (void) fgets(buf, sizeof(buf), irfile); + (void) fgets(buf, sizeof(buf), irfile); + + filename = NULL; + while (ftell(irfile) < end_offset + && fgets(buf, sizeof(buf), irfile) != NULL) + { + parse_readelf_line(buf, &info); + + /* Look for file name. */ + if (strncmp(info.type, "FILE", 4) == 0) + { + len = strlen(info.name); + p = malloc(len + 1); + strncpy(p, info.name, len + 1); + filename = p; + break; + } + } + + (*release_input_file) (claimed_file->handle); + + if (filename == NULL) + filename = claimed_file->name; + + if (claimed_file->nsyms == 0) + continue; + + if (strlen(filename) >= sizeof(buf)) + { + (*message)(LDPL_FATAL, "%s: filename too long", filename); + return LDPS_ERR; + } + strcpy(buf, filename); + p = strrchr(buf, '.'); + if (p == NULL + || (strcmp(p, ".syms") != 0 + && strcmp(p, ".c") != 0 + && strcmp(p, ".cc") != 0)) + { + (*message)(LDPL_FATAL, "%s: filename has unknown suffix", + filename); + return LDPS_ERR; + } + p[1] = 'o'; + p[2] = '\0'; + (*message)(LDPL_INFO, "%s: adding new input file", buf); + (*add_input_file)(buf); + } + + return LDPS_OK; +} + +enum ld_plugin_status +cleanup_hook(void) +{ + (*message)(LDPL_INFO, "cleanup hook called"); + return LDPS_OK; +} + +static void +parse_readelf_line(char* p, struct sym_info* info) +{ + int len; + + p += strspn(p, " "); + + /* Index field. */ + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Value field. */ + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Size field. */ + info->size = atoi(p); + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Type field. */ + info->type = p; + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Binding field. */ + info->bind = p; + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Visibility field. */ + info->vis = p; + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Section field. */ + info->sect = p; + p += strcspn(p, " "); + p += strspn(p, " "); + + /* Name field. */ + /* FIXME: Look for version. */ + len = strlen(p); + if (len == 0) + p = NULL; + else if (p[len-1] == '\n') + p[--len] = '\0'; + info->name = p; +} diff --git a/binutils-2.19/gold/testsuite/plugin_test_1.sh b/binutils-2.19/gold/testsuite/plugin_test_1.sh new file mode 100755 index 0000000..4d3ed41 --- /dev/null +++ b/binutils-2.19/gold/testsuite/plugin_test_1.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +# plugin_test_1.sh -- a test case for the plugin API. + +# Copyright 2008, 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with plugin_test_1.c, a simple plug-in library that +# exercises the basic interfaces and prints out version numbers and +# options passed to the plugin. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected output in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check plugin_test_1.err "API version:" +check plugin_test_1.err "gold version:" +check plugin_test_1.err "option: _Z4f13iv" +check plugin_test_1.err "two_file_test_main.o: claim file hook called" +check plugin_test_1.err "two_file_test_1.syms: claim file hook called" +check plugin_test_1.err "two_file_test_1b.syms: claim file hook called" +check plugin_test_1.err "two_file_test_2.syms: claim file hook called" +check plugin_test_1.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY" +check plugin_test_1.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG" +check plugin_test_1.err "two_file_test_1.syms: v2: RESOLVED_IR" +check plugin_test_1.err "two_file_test_1.syms: t17data: RESOLVED_IR" +check plugin_test_1.err "two_file_test_2.syms: _Z4f13iv: PREEMPTED_IR" +check plugin_test_1.err "two_file_test_1.o: adding new input file" +check plugin_test_1.err "two_file_test_1b.o: adding new input file" +check plugin_test_1.err "two_file_test_2.o: adding new input file" +check plugin_test_1.err "cleanup hook called" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/plugin_test_2.sh b/binutils-2.19/gold/testsuite/plugin_test_2.sh new file mode 100755 index 0000000..a47d22a --- /dev/null +++ b/binutils-2.19/gold/testsuite/plugin_test_2.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# plugin_test_2.sh -- a test case for the plugin API. + +# Copyright 2008, 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with plugin_test_1.c, a simple plug-in library that +# exercises the basic interfaces and prints out version numbers and +# options passed to the plugin. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected output in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check plugin_test_2.err "API version:" +check plugin_test_2.err "gold version:" +check plugin_test_2.err "two_file_test_main.o: claim file hook called" +check plugin_test_2.err "two_file_test_1.syms: claim file hook called" +check plugin_test_2.err "two_file_test_1b.syms: claim file hook called" +check plugin_test_2.err "two_file_shared_2.so: claim file hook called" +check plugin_test_2.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_REG" +check plugin_test_2.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG" +check plugin_test_2.err "two_file_test_1.syms: v2: RESOLVED_DYN" +check plugin_test_2.err "two_file_test_1.syms: t17data: RESOLVED_DYN" +check plugin_test_2.err "two_file_test_1.o: adding new input file" +check plugin_test_2.err "two_file_test_1b.o: adding new input file" +check plugin_test_2.err "cleanup hook called" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/plugin_test_3.sh b/binutils-2.19/gold/testsuite/plugin_test_3.sh new file mode 100755 index 0000000..961df15 --- /dev/null +++ b/binutils-2.19/gold/testsuite/plugin_test_3.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +# plugin_test_3.sh -- a test case for the plugin API. + +# Copyright 2008, 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with plugin_test.c, a simple plug-in library that +# exercises the basic interfaces and prints out version numbers and +# options passed to the plugin. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected output in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check plugin_test_3.err "API version:" +check plugin_test_3.err "gold version:" +check plugin_test_3.err "option: _Z4f13iv" +check plugin_test_3.err "two_file_test_main.o: claim file hook called" +check plugin_test_3.err "two_file_test_1.syms: claim file hook called" +check plugin_test_3.err "two_file_test_1b.syms: claim file hook called" +check plugin_test_3.err "two_file_test_2.syms: claim file hook called" +check plugin_test_3.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_REG" +check plugin_test_3.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG" +check plugin_test_3.err "two_file_test_1.syms: v2: RESOLVED_IR" +check plugin_test_3.err "two_file_test_1.syms: t17data: RESOLVED_IR" +check plugin_test_3.err "two_file_test_2.syms: _Z4f13iv: PREEMPTED_IR" +check plugin_test_3.err "two_file_test_1.o: adding new input file" +check plugin_test_3.err "two_file_test_1b.o: adding new input file" +check plugin_test_3.err "two_file_test_2.o: adding new input file" +check plugin_test_3.err "cleanup hook called" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/plugin_test_4.sh b/binutils-2.19/gold/testsuite/plugin_test_4.sh new file mode 100755 index 0000000..89df46c --- /dev/null +++ b/binutils-2.19/gold/testsuite/plugin_test_4.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +# plugin_test_4.sh -- a test case for the plugin API. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with plugin_test_4.c, a simple plug-in library that +# exercises the basic interfaces and prints out version numbers and +# options passed to the plugin. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected output in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check plugin_test_4.err "API version:" +check plugin_test_4.err "gold version:" +check plugin_test_4.err "option: _Z4f13iv" +check plugin_test_4.err "two_file_test_main.o: claim file hook called" +check plugin_test_4.err "plugin_test_4.a: claim file hook called" +check plugin_test_4.err "plugin_test_4.a: claiming file" +check plugin_test_4.err "plugin_test_4.a: _Z4f13iv: PREVAILING_DEF_IRONLY" +check plugin_test_4.err "plugin_test_4.a: _Z2t2v: PREVAILING_DEF_REG" +check plugin_test_4.err "plugin_test_4.a: v2: RESOLVED_IR" +check plugin_test_4.err "plugin_test_4.a: t17data: RESOLVED_IR" +check plugin_test_4.err "plugin_test_4.a: _Z4f13iv: PREEMPTED_IR" +check plugin_test_4.err "two_file_test_1.o: adding new input file" +check plugin_test_4.err "two_file_test_1b.o: adding new input file" +check plugin_test_4.err "two_file_test_2.o: adding new input file" +check plugin_test_4.err "cleanup hook called" + +exit 0 diff --git a/binutils-2.19/gold/testsuite/protected_4.cc b/binutils-2.19/gold/testsuite/protected_4.cc new file mode 100644 index 0000000..58e3e2b --- /dev/null +++ b/binutils-2.19/gold/testsuite/protected_4.cc @@ -0,0 +1,32 @@ +// protected_4.cc -- a test case for gold + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Ian Lance Taylor <iant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The function f1 is protected but not defined. + +int +f1() __attribute__ ((__visibility__ ("protected"))); + +int +f2() +{ + return f1(); +} diff --git a/binutils-2.19/gold/testsuite/relro_script_test.t b/binutils-2.19/gold/testsuite/relro_script_test.t index cacb84d..3a6e3e9 100644 --- a/binutils-2.19/gold/testsuite/relro_script_test.t +++ b/binutils-2.19/gold/testsuite/relro_script_test.t @@ -46,6 +46,8 @@ SECTIONS . = DATA_SEGMENT_RELRO_END(0, .); + .got.plt : { *(.got.plt) } + .data : { *(.data .data.* .gnu.linkonce.d.*) } . = DATA_SEGMENT_END (.); diff --git a/binutils-2.19/gold/testsuite/retain_symbols_file_test.sh b/binutils-2.19/gold/testsuite/retain_symbols_file_test.sh new file mode 100755 index 0000000..e0d3ffc --- /dev/null +++ b/binutils-2.19/gold/testsuite/retain_symbols_file_test.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# retain_symbols_file_test.sh -- a test case for -retain-symbols-file + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Craig Silverstein <csilvers@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The Makefile tries linking simple_test.o with -retain-symbols-file. +# It then runs nm over the results. We check that the output is right. + +check_present() +{ + if ! grep -q "$1" retain_symbols_file_test.stdout + then + echo "Did not find expected symbol $1 in retain_symbols_file_test.stdout" + exit 1 + fi +} + +check_absent() +{ + if grep -q "$1" retain_symbols_file_test.stdout + then + echo "Found unexpected symbol $1 in retain_symbols_file_test.stdout" + exit 1 + fi +} + +check_present 't1' +check_present 't16b::t16b()' +check_present 't20a::get()' +check_present 't18()' +check_absent 't10' +check_absent 't1()' +check_absent 't16b::t()' + +exit 0 diff --git a/binutils-2.19/gold/testsuite/script_test_5.cc b/binutils-2.19/gold/testsuite/script_test_5.cc new file mode 100644 index 0000000..b5aec29 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_5.cc @@ -0,0 +1,45 @@ +// script_test_5.cc -- a test case for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This program checks that the default renaming of ".text.xxx" +// sections does not take place in the presence of a linker script +// with a SECTIONS clause. + +bool +t1() __attribute__ ((section (".text.foo"))); + +bool +t1() +{ + return 1; +} + +// Main function. Initialize variables and call test functions. + +int +main() +{ + if (t1()) + return 0; + else + return 1; +} diff --git a/binutils-2.19/gold/testsuite/script_test_5.sh b/binutils-2.19/gold/testsuite/script_test_5.sh new file mode 100755 index 0000000..76e2e31 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_5.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# script_test_5.sh -- test linker script with uncovered sections + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Cary Coutant <ccoutant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with script_test_5.t, which is a linker script with +# a SECTIONS clause that does not explicitly mention one of the input +# sections in the test object file. We check to make sure that the +# correct output section is generated. + +check_count() +{ + if test "`grep -c "$2" "$1"`" != "$3" + then + echo "Did not find expected number ($3) of '$2' sections in $1" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check_count script_test_5.stdout " .text " 1 +check_count script_test_5.stdout " .text.foo " 1 diff --git a/binutils-2.19/gold/testsuite/script_test_5.t b/binutils-2.19/gold/testsuite/script_test_5.t new file mode 100644 index 0000000..b5e83aa --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_5.t @@ -0,0 +1,40 @@ +/* script_test_5.t -- linker script test 5 for gold + + Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* We won't try to run this program, just ensure that it links + as expected. */ + +SECTIONS +{ + . = 0x10000000; + + /* With luck this will be enough to get the program working. */ + .interp : { *(.interp) } + .text : { *(.text) } + . += 0x100000; + . = ALIGN(0x100); + .dynamic : { *(.dynamic) } + .data : { *(.data) } + . += 0x100000; + . = ALIGN(0x100); + .bss : { *(.bss) } +} diff --git a/binutils-2.19/gold/testsuite/script_test_6.sh b/binutils-2.19/gold/testsuite/script_test_6.sh new file mode 100755 index 0000000..bbc96d8 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_6.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# script_test_6.sh -- test for -Ttext, -Tdata and -Tbss with a script. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with script_test_4.t, which is a linker script which +# starts the program at an unaligned address. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected section in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check script_test_6.stdout "\\.text[ ]*PROGBITS[ ]*0*10001000" +check script_test_6.stdout "\\.data[ ]*PROGBITS[ ]*0*10200000" +check script_test_6.stdout "\\.bss[ ]*NOBITS[ ]*0*10400000" diff --git a/binutils-2.19/gold/testsuite/script_test_6.t b/binutils-2.19/gold/testsuite/script_test_6.t new file mode 100644 index 0000000..9676371 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_6.t @@ -0,0 +1,41 @@ +/* script_test_5.t -- linker script test 5 for gold + + Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* We won't try to run this program, just ensure that it links + as expected. */ + +SECTIONS +{ + . = 0x10000000; + + /* With luck this will be enough to get the program working. */ + .interp : { *(.interp) } + .text : { *(.text .text.*) } + .rodata : { *(.rodata .rodata.*) } + . += 0x100000; + . = ALIGN(0x100); + .dynamic : { *(.dynamic) } + .data : { *(.data) } + . += 0x100000; + . = ALIGN(0x100); + .bss : { *(.bss) } +} diff --git a/binutils-2.19/gold/testsuite/script_test_7.sh b/binutils-2.19/gold/testsuite/script_test_7.sh new file mode 100755 index 0000000..982a1c1 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_7.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# script_test_7.sh -- test for SEGMENT_START expressions. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with script_test_4.t, which is a linker script which +# starts the program at an unaligned address. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected section in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check script_test_7.stdout "\\.interp[ ]*PROGBITS[ ]*0*10000100" +check script_test_7.stdout "\\.data[ ]*PROGBITS[ ]*0*10200000" +check script_test_7.stdout "\\.bss[ ]*NOBITS[ ]*0*10400..." diff --git a/binutils-2.19/gold/testsuite/script_test_7.t b/binutils-2.19/gold/testsuite/script_test_7.t new file mode 100644 index 0000000..a4c4973 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_7.t @@ -0,0 +1,41 @@ +/* script_test_5.t -- linker script test 5 for gold + + Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* We won't try to run this program, just ensure that it links + as expected. */ + +SECTIONS +{ + . = SEGMENT_START(".text", 0x10000100); + + /* With luck this will be enough to get the program working. */ + .interp : { *(.interp) } + .text : { *(.text .text.*) } + .rodata : { *(.rodata .rodata.*) } + .dynamic : { *(.dynamic) } + + . = SEGMENT_START(".data", 0x10200000); + .data : { *(.data) } + + . = SEGMENT_START(".bss", 0x10400000); + .bss : { *(.bss) } +} diff --git a/binutils-2.19/gold/testsuite/script_test_8.sh b/binutils-2.19/gold/testsuite/script_test_8.sh new file mode 100755 index 0000000..83e8e72 --- /dev/null +++ b/binutils-2.19/gold/testsuite/script_test_8.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# script_test_8.sh -- test for SEGMENT_START expressions with +# -Ttext, -Tdata and -Tbss in a script. + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Doug Kwan <dougkwan@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# This file goes with script_test_4.t, which is a linker script which +# starts the program at an unaligned address. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected section in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check script_test_8.stdout "\\.interp[ ]*PROGBITS[ ]*0*20001000" +check script_test_8.stdout "\\.data[ ]*PROGBITS[ ]*0*20200000" +check script_test_8.stdout "\\.bss[ ]*NOBITS[ ]*0*2040...." diff --git a/binutils-2.19/gold/testsuite/searched_file_test.cc b/binutils-2.19/gold/testsuite/searched_file_test.cc new file mode 100644 index 0000000..aa99e24 --- /dev/null +++ b/binutils-2.19/gold/testsuite/searched_file_test.cc @@ -0,0 +1,36 @@ +// searched_file_test.cc -- test -l:foo.a for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Chris Demetriou <cgd@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The Linux kernel builds an object file using a linker script, and +// then links against that object file using the -R option. This is a +// test for that usage. + +#include <cstdlib> + +extern int zero_from_lib; + +int +main(int, char**) +{ + exit(zero_from_lib); +} + diff --git a/binutils-2.19/gold/testsuite/searched_file_test_lib.cc b/binutils-2.19/gold/testsuite/searched_file_test_lib.cc new file mode 100644 index 0000000..0686e52 --- /dev/null +++ b/binutils-2.19/gold/testsuite/searched_file_test_lib.cc @@ -0,0 +1,27 @@ +// searched_file_test_lib.cc -- test -l:foo.a for gold + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Chris Demetriou <cgd@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The Linux kernel builds an object file using a linker script, and +// then links against that object file using the -R option. This is a +// test for that usage. + +int zero_from_lib = 0; diff --git a/binutils-2.19/gold/testsuite/split_i386.sh b/binutils-2.19/gold/testsuite/split_i386.sh new file mode 100755 index 0000000..e94fea2 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# split_i386.sh -- test -fstack-split for i386 + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +match() +{ + if ! egrep "$1" "$2" >/dev/null 2>&1; then + echo 1>&2 "could not find '$1' in $2" + exit 1 + fi +} + +nomatch() +{ + if egrep "$1" "$2" >/dev/null 2>&1; then + echo 1>&2 "found unexpected '$1' in $2" + exit 1 + fi +} + +match 'cmp.*+%gs:[^,]*,%esp' split_i386_1.stdout +match 'call.*__morestack>?$' split_i386_1.stdout +match 'lea.*-0x200\(%esp\),' split_i386_1.stdout + +match 'stc' split_i386_2.stdout +match 'call.*__morestack_non_split>?$' split_i386_2.stdout +nomatch 'call.*__morestack>?$' split_i386_2.stdout +match 'lea.*-0x4200\(%esp\),' split_i386_2.stdout + +match 'failed to match' split_i386_3.stdout + +match 'call.*__morestack>?$' split_i386_4.stdout + +match 'cannot mix' split_i386_r.stdout diff --git a/binutils-2.19/gold/testsuite/split_i386_1.s b/binutils-2.19/gold/testsuite/split_i386_1.s new file mode 100644 index 0000000..9ac816e --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386_1.s @@ -0,0 +1,33 @@ +# split_i386_1.s: i386 specific test case for -fsplit-stack. + + .text + + .global fn1 + .type fn1,@function +fn1: + cmp %gs:0x30,%esp + jae 1f + call __morestack + ret +1: + call fn2 + ret + + .size fn1,. - fn1 + + .global fn2 + .type fn2,@function +fn2: + lea -0x200(%esp),%ecx + cmp %gs:0x30,%ecx + jae 1f + call __morestack + ret +1: + call fn1 + ret + + .size fn2,. - fn2 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_i386_2.s b/binutils-2.19/gold/testsuite/split_i386_2.s new file mode 100644 index 0000000..b4a2f14 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386_2.s @@ -0,0 +1,33 @@ +# split_i386_2.s: i386 specific, -fsplit-stack calling non-split + + .text + + .global fn1 + .type fn1,@function +fn1: + cmp %gs:0x30,%esp + jae 1f + call __morestack + ret +1: + call fn3 + ret + + .size fn1,. - fn1 + + .global fn2 + .type fn2,@function +fn2: + lea -0x200(%esp),%ecx + cmp %gs:0x30,%ecx + jae 1f + call __morestack + ret +1: + call fn3 + ret + + .size fn2,. - fn2 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_i386_3.s b/binutils-2.19/gold/testsuite/split_i386_3.s new file mode 100644 index 0000000..fdde7a9 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386_3.s @@ -0,0 +1,22 @@ +# split_i386_3.s: i386 specific, adjustment failure + + .text + + .global fn1 + .type fn1,@function +fn1: + push %ebp + mov %esp,%ebp + cmp %gs:0x30,%esp + jae 1f + call __morestack + ret +1: + call fn3 + leave + ret + + .size fn1,. - fn1 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_i386_4.s b/binutils-2.19/gold/testsuite/split_i386_4.s new file mode 100644 index 0000000..be774ae --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386_4.s @@ -0,0 +1,23 @@ +# split_i386_4.s: i386 specific, permitted adjustment failure + + .text + + .global fn1 + .type fn1,@function +fn1: + push %ebp + mov %esp,%ebp + cmp %gs:0x30,%esp + jae 1f + call __morestack + ret +1: + call fn3 + leave + ret + + .size fn1,. - fn1 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits + .section .note.GNU-no-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_i386_n.s b/binutils-2.19/gold/testsuite/split_i386_n.s new file mode 100644 index 0000000..4d4e6e8 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_i386_n.s @@ -0,0 +1,12 @@ +# split_i386_n.s: i386 specific, -fsplit-stack calling non-split + + .text + + .global fn3 + .type fn3,@function +fn3: + ret + + .size fn3,. - fn3 + + .section .note.GNU-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_x86_64.sh b/binutils-2.19/gold/testsuite/split_x86_64.sh new file mode 100755 index 0000000..61544b2 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +# split_x86_64.sh -- test -fstack-split for x86_64 + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +match() +{ + if ! egrep "$1" "$2" >/dev/null 2>&1; then + echo 1>&2 "could not find '$1' in $2" + exit 1 + fi +} + +nomatch() +{ + if egrep "$1" "$2" >/dev/null 2>&1; then + echo 1>&2 "found unexpected '$1' in $2" + exit 1 + fi +} + +match 'cmp.*+%fs:[^,]*,%rsp' split_x86_64_1.stdout +match 'callq.*__morestack>?$' split_x86_64_1.stdout +match 'lea.*-0x200\(%rsp\),' split_x86_64_1.stdout + +match 'stc' split_x86_64_2.stdout +match 'callq.*__morestack_non_split>?$' split_x86_64_2.stdout +nomatch 'callq.*__morestack>?$' split_x86_64_2.stdout +match 'lea.*-0x4200\(%rsp\),' split_x86_64_2.stdout + +match 'failed to match' split_x86_64_3.stdout + +match 'callq.*__morestack>?$' split_x86_64_4.stdout + +match 'cannot mix' split_x86_64_r.stdout diff --git a/binutils-2.19/gold/testsuite/split_x86_64_1.s b/binutils-2.19/gold/testsuite/split_x86_64_1.s new file mode 100644 index 0000000..e23ea7f --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64_1.s @@ -0,0 +1,33 @@ +# split_x86_64_1.s: x86_64 specific test case for -fsplit-stack. + + .text + + .global fn1 + .type fn1,@function +fn1: + cmp %fs:0x70,%rsp + jae 1f + callq __morestack + retq +1: + callq fn2 + retq + + .size fn1,. - fn1 + + .global fn2 + .type fn2,@function +fn2: + lea -0x200(%rsp),%r10 + cmp %fs:0x70,%r10 + jae 1f + callq __morestack + retq +1: + callq fn1 + retq + + .size fn2,. - fn2 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_x86_64_2.s b/binutils-2.19/gold/testsuite/split_x86_64_2.s new file mode 100644 index 0000000..0559bbc --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64_2.s @@ -0,0 +1,33 @@ +# split_x86_64_2.s: x86_64 specific, -fsplit-stack calling non-split + + .text + + .global fn1 + .type fn1,@function +fn1: + cmp %fs:0x70,%rsp + jae 1f + callq __morestack + retq +1: + callq fn3 + retq + + .size fn1,. - fn1 + + .global fn2 + .type fn2,@function +fn2: + lea -0x200(%rsp),%r10 + cmp %fs:0x70,%r10 + jae 1f + callq __morestack + retq +1: + callq fn3 + retq + + .size fn2,. - fn2 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_x86_64_3.s b/binutils-2.19/gold/testsuite/split_x86_64_3.s new file mode 100644 index 0000000..68ae6e3 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64_3.s @@ -0,0 +1,22 @@ +# split_x86_64_3.s: x86_64 specific, adjustment failure + + .text + + .global fn1 + .type fn1,@function +fn1: + push %rbp + mov %rsp,%rbp + cmp %fs:0x70,%rsp + jae 1f + callq __morestack + retq +1: + callq fn3 + leaveq + retq + + .size fn1,. - fn1 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_x86_64_4.s b/binutils-2.19/gold/testsuite/split_x86_64_4.s new file mode 100644 index 0000000..653b917 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64_4.s @@ -0,0 +1,23 @@ +# split_x86_64_4.s: x86_64 specific, permitted adjustment failure + + .text + + .global fn1 + .type fn1,@function +fn1: + push %rbp + mov %rsp,%rbp + cmp %fs:0x70,%rsp + jae 1f + callq __morestack + retq +1: + callq fn3 + leaveq + retq + + .size fn1,. - fn1 + + .section .note.GNU-stack,"",@progbits + .section .note.GNU-split-stack,"",@progbits + .section .note.GNU-no-split-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/split_x86_64_n.s b/binutils-2.19/gold/testsuite/split_x86_64_n.s new file mode 100644 index 0000000..10436b1 --- /dev/null +++ b/binutils-2.19/gold/testsuite/split_x86_64_n.s @@ -0,0 +1,12 @@ +# split_x86_64_n.s: x86_64 specific, -fsplit-stack calling non-split + + .text + + .global fn3 + .type fn3,@function +fn3: + retq + + .size fn3,. - fn3 + + .section .note.GNU-stack,"",@progbits diff --git a/binutils-2.19/gold/testsuite/testfile.cc b/binutils-2.19/gold/testsuite/testfile.cc index 4551c44..7f53792 100644 --- a/binutils-2.19/gold/testsuite/testfile.cc +++ b/binutils-2.19/gold/testsuite/testfile.cc @@ -1,6 +1,6 @@ // testfile.cc -- Dummy ELF objects for testing purposes. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -44,21 +44,26 @@ class Target_test : public Sized_target<size, big_endian> { } void - scan_relocs(const General_options&, Symbol_table*, Layout*, - Sized_relobj<size, big_endian>*, unsigned int, - unsigned int, const unsigned char*, size_t, Output_section*, - bool, size_t, const unsigned char*) + gc_process_relocs(Symbol_table*, Layout*, Sized_relobj<size, big_endian>*, + unsigned int, unsigned int, const unsigned char*, size_t, + Output_section*, bool, size_t, const unsigned char*) + { ERROR("call to Target_test::gc_process_relocs"); } + + void + scan_relocs(Symbol_table*, Layout*, Sized_relobj<size, big_endian>*, + unsigned int, unsigned int, const unsigned char*, size_t, + Output_section*, bool, size_t, const unsigned char*) { ERROR("call to Target_test::scan_relocs"); } void relocate_section(const Relocate_info<size, big_endian>*, unsigned int, const unsigned char*, size_t, Output_section*, bool, unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr, - section_size_type) + section_size_type, const Reloc_symbol_changes*) { ERROR("call to Target_test::relocate_section"); } void - scan_relocatable_relocs(const General_options&, Symbol_table*, Layout*, + scan_relocatable_relocs(Symbol_table*, Layout*, Sized_relobj<size, big_endian>*, unsigned int, unsigned int, const unsigned char*, size_t, Output_section*, bool, size_t, @@ -92,7 +97,13 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info = "/dummy", // dynamic_linker 0x08000000, // default_text_segment_address 0x1000, // abi_pagesize - 0x1000 // common_pagesize + 0x1000, // common_pagesize + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_UNDEF, // large_common_shndx + 0, // small_common_section_flags + 0, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; // The test targets. diff --git a/binutils-2.19/gold/testsuite/thin_archive_main.cc b/binutils-2.19/gold/testsuite/thin_archive_main.cc new file mode 100644 index 0000000..6c38715 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thin_archive_main.cc @@ -0,0 +1,39 @@ +// thin_archive_main.cc -- a test case for gold + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This is the main program for the thin archive tests. It calls a single +// routine, t1, defined in libthin1.a or libthin3.a, which then references +// other routines in the same and other libraries, to make sure that all +// archive members are linked properly. + +#include <cassert> + +extern int t1(); + +// Main function. Call the test function. + +int +main() +{ + assert(t1() == 0x4321); + return 0; +} diff --git a/binutils-2.19/gold/testsuite/thin_archive_test_1.cc b/binutils-2.19/gold/testsuite/thin_archive_test_1.cc new file mode 100644 index 0000000..db23937 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thin_archive_test_1.cc @@ -0,0 +1,37 @@ +// thin_archive_test_1.cc -- part of a test case for thin archives + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This tests references between files and archives. This is file 1 of 4. +// Each of the first three files contains a reference to the next. +// We test the archives as follows: + +// Files 1 and 2 in libthin1.a, files 3 and 4 in libthin2.a. +// Files 1 and 4 in libthin3.a, files 2 and 3 in libthin4.a, with +// libthin3.a and libthin4.a nested inside libthinall.a. + +extern int t2(); + +int +t1() +{ + return (t2() << 4) | 1; +} diff --git a/binutils-2.19/gold/testsuite/thin_archive_test_2.cc b/binutils-2.19/gold/testsuite/thin_archive_test_2.cc new file mode 100644 index 0000000..2c1ee31 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thin_archive_test_2.cc @@ -0,0 +1,37 @@ +// thin_archive_test_2.cc -- part of a test case for thin archives + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This tests references between files and archives. This is file 2 of 4. +// Each of the first three files contains a reference to the next. +// We test the archives as follows: + +// Files 1 and 2 in libthin1.a, files 3 and 4 in libthin2.a. +// Files 1 and 4 in libthin3.a, files 2 and 3 in libthin4.a, with +// libthin3.a and libthin4.a nested inside libthinall.a. + +extern int t3(); + +int +t2() +{ + return (t3() << 4) | 2; +} diff --git a/binutils-2.19/gold/testsuite/thin_archive_test_3.cc b/binutils-2.19/gold/testsuite/thin_archive_test_3.cc new file mode 100644 index 0000000..b58c59f --- /dev/null +++ b/binutils-2.19/gold/testsuite/thin_archive_test_3.cc @@ -0,0 +1,37 @@ +// thin_archive_test_3.cc -- part of a test case for thin archives + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This tests references between files and archives. This is file 3 of 4. +// Each of the first three files contains a reference to the next. +// We test the archives as follows: + +// Files 1 and 2 in libthin1.a, files 3 and 4 in libthin2.a. +// Files 1 and 4 in libthin3.a, files 2 and 3 in libthin4.a, with +// libthin3.a and libthin4.a nested inside libthinall.a. + +extern int t4(); + +int +t3() +{ + return (t4() << 4) | 3; +} diff --git a/binutils-2.19/gold/testsuite/thin_archive_test_4.cc b/binutils-2.19/gold/testsuite/thin_archive_test_4.cc new file mode 100644 index 0000000..1b67c94 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thin_archive_test_4.cc @@ -0,0 +1,35 @@ +// thin_archive_test_4.cc -- part of a test case for thin archives + +// Copyright 2008 Free Software Foundation, Inc. +// Written by Cary Coutant <ccoutant@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// This tests references between files and archives. This is file 4 of 4. +// Each of the first three files contains a reference to the next. +// We test the archives as follows: + +// Files 1 and 2 in libthin1.a, files 3 and 4 in libthin2.a. +// Files 1 and 4 in libthin3.a, files 2 and 3 in libthin4.a, with +// libthin3.a and libthin4.a nested inside libthinall.a. + +int +t4() +{ + return 4; +} diff --git a/binutils-2.19/gold/testsuite/thumb2_branch_range.t b/binutils-2.19/gold/testsuite/thumb2_branch_range.t new file mode 100644 index 0000000..8fdc783 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb2_branch_range.t @@ -0,0 +1,36 @@ +/* thumb2_banch_range.t -- linker script to test THUMB-2 branch range. + + Copyright 2010 Free Software Foundation, Inc. + Written by Doug Kwan <dougkwan@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +SECTIONS +{ + . = 0x1000000; + + .text.pre : { *(.text.pre) } + . = ALIGN(0x1000000); + .text : { *(.text) } + . = ALIGN(0x1000000); + .text.post : { *(.text.post) } + . += 0x1000; + .data : { *(.data) } + .bss : { *(.bss) } + .ARM.attributes : { *(.ARM.attributes) } +} diff --git a/binutils-2.19/gold/testsuite/thumb_bl_in_range.s b/binutils-2.19/gold/testsuite/thumb_bl_in_range.s new file mode 100644 index 0000000..4a40ae2 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb_bl_in_range.s @@ -0,0 +1,56 @@ +# thumb_bl_in_range.s +# Test THUMB/THUMB-2 bl instructions just within the branch range limits. + .syntax unified + + .section .text.pre,"x" + +# Add padding so that target is just in branch range. + .space 8 + + .global _backward_target + .code 16 + .thumb_func + .type _backword_target, %function +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + +# Define _start so that linker does not complain. + .global _start + .code 32 + .align 2 + .type _start, %function +_start: + bx lr + .size _start, .-_start + + .global _backward_test + .code 16 + .thumb_func + .type _backward_test, %function +_backward_test: + bl _backward_target + .size _backward_test, .-_backward_test + + .global _forward_test + .code 16 + .thumb_func + .type _forward_test, %function +_forward_test: + bl _forward_target + .size _forward_test, .-_forward_test + + .section .text.post,"x" + +# Add padding so that target is just in branch range. + .space 10 + + .global _forward_target + .code 16 + .thumb_func + .type _forward_target, %function +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/thumb_bl_out_of_range.s b/binutils-2.19/gold/testsuite/thumb_bl_out_of_range.s new file mode 100644 index 0000000..6629d74 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb_bl_out_of_range.s @@ -0,0 +1,56 @@ +# thumb_bl_out_of_range.s +# Test THUMB/THUMB-2 bl instructions just out of the branch range limits. + .syntax unified + + .section .text.pre,"x" + +# Add padding so that target is just output of branch range. + .space 6 + + .global _backward_target + .code 16 + .thumb_func + .type _backword_target, %function +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + +# Define _start so that linker does not complain. + .global _start + .code 32 + .align 2 + .type _start, %function +_start: + bx lr + .size _start, .-_start + + .global _backward_test + .code 16 + .thumb_func + .type _backward_test, %function +_backward_test: + bl _backward_target + .size _backward_test, .-_backward_test + + .global _forward_test + .code 16 + .thumb_func + .type _forward_test, %function +_forward_test: + bl _forward_target + .size _forward_test, .-_forward_test + + .section .text.post,"x" + +# Add padding so that target is just out of branch range. + .space 12 + + .global _forward_target + .code 16 + .thumb_func + .type _forward_target, %function +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/thumb_blx_in_range.s b/binutils-2.19/gold/testsuite/thumb_blx_in_range.s new file mode 100644 index 0000000..bd2d060 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb_blx_in_range.s @@ -0,0 +1,64 @@ +# thumb_blx_in_range.s +# +# Test THUMB/THUMB-2 blx instructions just within the branch range limits. +# Because bit 1 of the branch target comes from the branch instruction +# address, the branch range from PC (branch instruction address + 4) is +# acutally -((1<<22) + 2) to ((1<<22) - 4) for THUMB and -((1<<24) + 2) to +# ((1<<24) - 4) from THUMB2. + + .syntax unified + .section .text.pre,"x" + +# Add padding so that target is just in branch range. + .space 8 + + .align 2 + .global _backward_target + .code 32 + .type _backword_target, %function +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + +# Define _start so that linker does not complain. + .global _start + .code 32 + .align 2 + .type _start, %function +_start: + bx lr + .size _start, .-_start + + .global _backward_test + .code 16 + .thumb_func + .type _backward_test, %function +_backward_test: + nop.n + blx _backward_target + .size _backward_test, .-_backward_test + + .align 2 + .global _forward_test + .code 16 + .thumb_func + .type _forward_test, %function +_forward_test: + blx _forward_target + .size _forward_test, .-_forward_test + .code 32 + + .section .text.post,"x" + +# Add padding so that target is just in branch range. + .space 12 + + .align 2 + .global _forward_target + .code 32 + .type _forward_target, %function +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/thumb_blx_out_of_range.s b/binutils-2.19/gold/testsuite/thumb_blx_out_of_range.s new file mode 100644 index 0000000..fc5beb5 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb_blx_out_of_range.s @@ -0,0 +1,61 @@ +# thumb_blx_out_of_range.s +# Test THUMB/THUMB-2 blx instructions just out of the branch range limits. + .syntax unified + + .section .text.pre,"x" + +# Add padding so that target is just output of branch range. + .space 6 + + .global _forward_target + .global _backward_target + .type _backword_target, %function +_backward_target: + bx lr + .size _backward_target, .-_backward_target + + .text + +# Define _start so that linker does not complain. + .align 2 + .global _start + .code 32 + .type _start, %function +_start: + bx lr + .size _start, .-_start + + .global _backward_test + .code 16 + .thumb_func + .type _backward_test, %function +_backward_test: + bl _backward_target + .size _backward_test, .-_backward_test + + .align 2 + .global _forward_test + .code 16 + .thumb_func + .type _forward_test, %function +_forward_test: + # Bit 1 of the BLX target comes from bit 1 of branch base address, + # which is BLX instruction's address + 4. We intentionally put this + # forward BLX at an address n*4 + 2 so that the branch offset is + # bumped up by 2. + nop.n + bl _forward_target + .size _forward_test, .-_forward_test + .code 32 + + .section .text.post,"x" + +# Add padding so that target is just out of branch range. + .space 12 + .align 2 + .code 32 + .global _forward_target + .type _forward_target, %function +_forward_target: + bx lr + .size _forward_target, .-_forward_target diff --git a/binutils-2.19/gold/testsuite/thumb_branch_range.t b/binutils-2.19/gold/testsuite/thumb_branch_range.t new file mode 100644 index 0000000..fa858b5 --- /dev/null +++ b/binutils-2.19/gold/testsuite/thumb_branch_range.t @@ -0,0 +1,36 @@ +/* thumb_banch_range.t -- linker script to test ARM branch range. + + Copyright 2010 Free Software Foundation, Inc. + Written by Doug Kwan <dougkwan@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +SECTIONS +{ + . = 0x400000; + + .text.pre : { *(.text.pre) } + . = ALIGN(0x400000); + .text : { *(.text) } + . = ALIGN(0x400000); + .text.post : { *(.text.post) } + . += 0x1000; + .data : { *(.data) } + .bss : { *(.bss) } + .ARM.attributes : { *(.ARM.attributes) } +} diff --git a/binutils-2.19/gold/testsuite/tls_test_c.c b/binutils-2.19/gold/testsuite/tls_test_c.c index 1860969..730e46d 100644 --- a/binutils-2.19/gold/testsuite/tls_test_c.c +++ b/binutils-2.19/gold/testsuite/tls_test_c.c @@ -42,8 +42,11 @@ int v7; #pragma omp threadprivate (v7) #endif +int t11(void); +int t11_last(void); + int -t11() +t11(void) { #ifdef HAVE_OMP_SUPPORT CHECK_EQ_OR_RETURN(v7, 0); @@ -53,7 +56,7 @@ t11() } int -t11_last() +t11_last(void) { #ifdef HAVE_OMP_SUPPORT CHECK_EQ_OR_RETURN(v7, 70); diff --git a/binutils-2.19/gold/testsuite/two_file_shared.sh b/binutils-2.19/gold/testsuite/two_file_shared.sh new file mode 100755 index 0000000..6240311 --- /dev/null +++ b/binutils-2.19/gold/testsuite/two_file_shared.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# two_file_shared.sh -- check that debug info gets symbol addresses + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +addrs=`grep DW_OP_addr two_file_shared.dbg | fgrep '(DW_OP_addr: 0)'` +if test -n "$addrs"; then + echo "Found variables with address zero" + echo $addrs + exit 1 +fi diff --git a/binutils-2.19/gold/testsuite/undef_symbol.sh b/binutils-2.19/gold/testsuite/undef_symbol.sh index 03c1576..b689edc 100755 --- a/binutils-2.19/gold/testsuite/undef_symbol.sh +++ b/binutils-2.19/gold/testsuite/undef_symbol.sh @@ -40,6 +40,6 @@ check() fi } -check "undef_symbol.so: undefined reference to 'a'" +check "undef_symbol.so: error: undefined reference to 'a'" exit 0 diff --git a/binutils-2.19/gold/testsuite/ver_matching_test.sh b/binutils-2.19/gold/testsuite/ver_matching_test.sh index 7f42526..4880efa 100755 --- a/binutils-2.19/gold/testsuite/ver_matching_test.sh +++ b/binutils-2.19/gold/testsuite/ver_matching_test.sh @@ -2,7 +2,7 @@ # ver_matching_test.sh -- a test case for version script matching -# Copyright 2008 Free Software Foundation, Inc. +# Copyright 2008, 2010 Free Software Foundation, Inc. # Written by Ian Lance Taylor <iant@google.com>. # This file is part of gold. @@ -66,9 +66,9 @@ check ver_matching_test.stdout "V1 *myns::blah()$" check ver_matching_test.stdout "V1 *myns::bip()$" check ver_matching_test.stdout "V1 *myns::Stuff::Stuff()$" check ver_matching_test.stdout "Base *Biz::Biz()$" -check ver_matching_test.stdout "V1 *blaza1$" +check ver_matching_test.stdout "V2 *blaza1$" check ver_matching_test.stdout "V2 *blaza2$" -check ver_matching_test.stdout "V1 *blaza$" +check ver_matching_test.stdout "V2 *blaza$" check ver_matching_test.stdout "Base *bla$" check ver_matching_test.stdout "V2 *blaz$" check ver_matching_test.stdout "V2 *blazb$" diff --git a/binutils-2.19/gold/testsuite/ver_test_1.sh b/binutils-2.19/gold/testsuite/ver_test_1.sh new file mode 100755 index 0000000..edf7351 --- /dev/null +++ b/binutils-2.19/gold/testsuite/ver_test_1.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# ver_test_1.sh -- check that protected symbols are local + +# Copyright 2009 Free Software Foundation, Inc. +# Written by Ian Lance Taylor <iant@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +syms=`grep ' HIDDEN ' ver_test_1.syms | grep ' GLOBAL '` +if test -n "$syms"; then + echo "Found GLOBAL HIDDEN symbols" + echo $syms + exit 1 +fi diff --git a/binutils-2.19/gold/testsuite/ver_test_4.script b/binutils-2.19/gold/testsuite/ver_test_4.script index 9f7d350..e97c74e 100644 --- a/binutils-2.19/gold/testsuite/ver_test_4.script +++ b/binutils-2.19/gold/testsuite/ver_test_4.script @@ -30,7 +30,6 @@ VER1 { VER2 { global: t1_2; - t2_2; t4_2a; } VER1; diff --git a/binutils-2.19/gold/testsuite/ver_test_6.c b/binutils-2.19/gold/testsuite/ver_test_6.c index 4206354..44b483f 100644 --- a/binutils-2.19/gold/testsuite/ver_test_6.c +++ b/binutils-2.19/gold/testsuite/ver_test_6.c @@ -26,8 +26,10 @@ int t3_2; +/* Since we don't use any of the arguments to main, we give it a void + prototype, so as to quiet gcc -Wstrict-prototypes. */ int -main() +main(void) { return t3_2; } diff --git a/binutils-2.19/gold/testsuite/version_script.map b/binutils-2.19/gold/testsuite/version_script.map index 3b7d1b6..d3ba02e 100644 --- a/binutils-2.19/gold/testsuite/version_script.map +++ b/binutils-2.19/gold/testsuite/version_script.map @@ -29,7 +29,6 @@ V2 { otherns::stuff; }; blaz*; - foo; local: _[^A-Z]*; } V1; diff --git a/binutils-2.19/gold/timer.cc b/binutils-2.19/gold/timer.cc new file mode 100644 index 0000000..ec51bc9 --- /dev/null +++ b/binutils-2.19/gold/timer.cc @@ -0,0 +1,107 @@ +// timer.cc -- helper class for time accounting + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Rafael Avila de Espindola <espindola@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#include "gold.h" + +#include <sys/times.h> + +#include "libiberty.h" + +#include "timer.h" + +namespace gold +{ + +// Class Timer + +Timer::Timer() +{ + this->start_time_.wall = 0; + this->start_time_.user = 0; + this->start_time_.sys = 0; +} + +// Start couting the time. +void +Timer::start () +{ + this->get_time(&this->start_time_); +} + +#if HAVE_SYSCONF && defined _SC_CLK_TCK +# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */ +#else +# ifdef CLK_TCK +# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */ +# else +# ifdef HZ +# define TICKS_PER_SECOND HZ /* traditional UNIX */ +# else +# define TICKS_PER_SECOND 100 /* often the correct value */ +# endif +# endif +#endif + +// times returns statistics in clock_t units. This variable will hold the +// conversion factor to seconds. We use a variable that is initialize once +// because sysconf can be slow. +static long ticks_per_sec; +class Timer_init +{ + public: + Timer_init() + { + ticks_per_sec = TICKS_PER_SECOND; + } +}; +Timer_init timer_init; + +// Write the current time infortamion. +void +Timer::get_time (TimeStats *now) +{ +#ifdef HAVE_TIMES + tms t; + now->wall = (times(&t) * 1000) / ticks_per_sec; + now->user = (t.tms_utime * 1000) / ticks_per_sec; + now->sys = (t.tms_stime * 1000) / ticks_per_sec; +#else + now->wall = get_run_time() / 1000; + now->user = 0; + now->sys = 0; +#endif +} + +// Return the stats since start was called. +Timer::TimeStats +Timer::get_elapsed_time () +{ + TimeStats now; + this->get_time(&now); + TimeStats delta; + delta.wall = now.wall - this->start_time_.wall; + delta.user = now.user - this->start_time_.user; + delta.sys = now.sys - this->start_time_.sys; + return delta; +} + +} diff --git a/binutils-2.19/gold/timer.h b/binutils-2.19/gold/timer.h new file mode 100644 index 0000000..ea360c2 --- /dev/null +++ b/binutils-2.19/gold/timer.h @@ -0,0 +1,69 @@ +// timer.h -- helper class for time accounting -*- C++ -*- + +// Copyright 2009 Free Software Foundation, Inc. +// Written by Rafael Avila de Espindola <espindola@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +#ifndef GOLD_TIMER_H +#define GOLD_TIMER_H + +namespace gold +{ + +class Timer +{ + public: + // Used to report time statistics. All fields are in milliseconds. + struct TimeStats + { + /* User time in this process. */ + long user; + + /* System time in this process. */ + long sys; + + /* Wall clock time. */ + long wall; + }; + + Timer(); + + // Return the stats since start was called. + TimeStats + get_elapsed_time(); + + // Start couting the time. + void + start(); + + private: + // This class cannot be copied. + Timer(const Timer&); + Timer& operator=(const Timer&); + + // Write the current time infortamion. + static void + get_time(TimeStats *now); + + // The time of the last call to start. + TimeStats start_time_; +}; + +} +#endif diff --git a/binutils-2.19/gold/token.h b/binutils-2.19/gold/token.h index dcf00b6..5cf64a0 100644 --- a/binutils-2.19/gold/token.h +++ b/binutils-2.19/gold/token.h @@ -1,6 +1,6 @@ // token.h -- lock tokens for gold -*- C++ -*- -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -144,6 +144,15 @@ class Task_token this->writer_ = NULL; } + // Add some number of blockers to the token. + void + add_blockers(int c) + { + gold_assert(this->is_blocker_); + this->blockers_ += c; + this->writer_ = NULL; + } + // Remove a blocker from the token. Returns true if block count // drops to zero. bool diff --git a/binutils-2.19/gold/version.cc b/binutils-2.19/gold/version.cc index 0e938f7..caaa8a6 100644 --- a/binutils-2.19/gold/version.cc +++ b/binutils-2.19/gold/version.cc @@ -1,6 +1,7 @@ // version.c -- print gold version information -// Copyright 2006, 2007, 200 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 +// Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -23,6 +24,7 @@ #include "gold.h" #include <string> +#include <cstdio> #include "../bfd/bfdver.h" @@ -35,7 +37,7 @@ namespace gold // version number from configure.ac. But it's easier to just change // this file for now. -static const char* version_string = "1.7"; +static const char* version_string = "1.9"; // Report version information. @@ -61,7 +63,7 @@ print_version(bool print_short) if (!print_short) { // This output is intended to follow the GNU standards. - printf (_("Copyright 2008 Free Software Foundation, Inc.\n")); + printf (_("Copyright 2010 Free Software Foundation, Inc.\n")); printf (_("\ This program is free software; you may redistribute it under the terms of\n\ the GNU General Public License version 3 or (at your option) a later version.\n\ diff --git a/binutils-2.19/gold/workqueue.cc b/binutils-2.19/gold/workqueue.cc index 42182ea..6449bba 100644 --- a/binutils-2.19/gold/workqueue.cc +++ b/binutils-2.19/gold/workqueue.cc @@ -24,6 +24,7 @@ #include "debug.h" #include "options.h" +#include "timer.h" #include "workqueue.h" #include "workqueue-internal.h" @@ -311,10 +312,24 @@ Workqueue::find_and_run_task(int thread_number) gold_debug(DEBUG_TASK, "%3d running task %s", thread_number, t->name().c_str()); + Timer timer; + if (is_debugging_enabled(DEBUG_TASK)) + timer.start(); + t->run(this); - gold_debug(DEBUG_TASK, "%3d completed task %s", thread_number, - t->name().c_str()); + if (is_debugging_enabled(DEBUG_TASK)) + { + Timer::TimeStats elapsed = timer.get_elapsed_time(); + + gold_debug(DEBUG_TASK, + "%3d completed task %s " + "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)", + thread_number, t->name().c_str(), + elapsed.user / 1000, (elapsed.user % 1000) * 1000, + elapsed.sys / 1000, (elapsed.sys % 1000) * 1000, + elapsed.wall / 1000, (elapsed.wall % 1000) * 1000); + } Task* next; { @@ -494,4 +509,13 @@ Workqueue::set_thread_count(int threads) this->condvar_.broadcast(); } +// Add a new blocker to an existing Task_token. + +void +Workqueue::add_blocker(Task_token* token) +{ + Hold_lock hl(this->lock_); + token->add_blocker(); +} + } // End namespace gold. diff --git a/binutils-2.19/gold/workqueue.h b/binutils-2.19/gold/workqueue.h index 3b7a764..9121e10 100644 --- a/binutils-2.19/gold/workqueue.h +++ b/binutils-2.19/gold/workqueue.h @@ -152,7 +152,7 @@ class Task_function : public Task Task_function(Task_function_runner* runner, Task_token* blocker, const char* name) : runner_(runner), blocker_(blocker), name_(name) - { } + { gold_assert(blocker != NULL); } ~Task_function() { @@ -227,6 +227,12 @@ class Workqueue void set_thread_count(int); + // Add a new blocker to an existing Task_token. This must be done + // with the workqueue lock held. This should not be done routinely, + // only in special circumstances. + void + add_blocker(Task_token*); + private: // This class can not be copied. Workqueue(const Workqueue&); diff --git a/binutils-2.19/gold/x86_64.cc b/binutils-2.19/gold/x86_64.cc index 2daa9bf..e9dd5ae 100644 --- a/binutils-2.19/gold/x86_64.cc +++ b/binutils-2.19/gold/x86_64.cc @@ -1,6 +1,6 @@ // x86_64.cc -- x86_64 target support for gold. -// Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -37,6 +37,9 @@ #include "target-reloc.h" #include "target-select.h" #include "tls.h" +#include "freebsd.h" +#include "gc.h" +#include "icf.h" namespace { @@ -52,7 +55,7 @@ class Output_data_plt_x86_64; // http://people.redhat.com/drepper/tls.pdf // http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt -class Target_x86_64 : public Sized_target<64, false> +class Target_x86_64 : public Target_freebsd<64, false> { public: // In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures @@ -60,16 +63,44 @@ class Target_x86_64 : public Sized_target<64, false> typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section; Target_x86_64() - : Sized_target<64, false>(&x86_64_info), - got_(NULL), plt_(NULL), got_plt_(NULL), rela_dyn_(NULL), - copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL), - got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) + : Target_freebsd<64, false>(&x86_64_info), + got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL), + rela_dyn_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL), + got_mod_index_offset_(-1U), tlsdesc_reloc_info_(), + tls_base_symbol_defined_(false) { } + // This function should be defined in targets that can use relocation + // types to determine (implemented in local_reloc_may_be_function_pointer + // and global_reloc_may_be_function_pointer) + // if a function's pointer is taken. ICF uses this in safe mode to only + // fold those functions whose pointer is defintely not taken. For x86_64 + // pie binaries, safe ICF cannot be done by looking at relocation types. + inline bool + can_check_for_function_pointers() const + { return !parameters->options().pie(); } + + // Hook for a new output section. + void + do_new_output_section(Output_section*) const; + + // Scan the relocations to look for symbol adjustments. + void + gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols); + // Scan the relocations to look for symbol adjustments. void - scan_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<64, false>* object, unsigned int data_shndx, @@ -83,7 +114,7 @@ class Target_x86_64 : public Sized_target<64, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(Layout*, const Input_objects*, Symbol_table*); // Return the value to use for a dynamic which requires special // treatment. @@ -100,12 +131,12 @@ class Target_x86_64 : public Sized_target<64, false> bool needs_special_offset_handling, unsigned char* view, elfcpp::Elf_types<64>::Elf_Addr view_address, - section_size_type view_size); + section_size_type view_size, + const Reloc_symbol_changes*); // Scan the relocs during a relocatable link. void - scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, + scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<64, false>* object, unsigned int data_shndx, @@ -139,9 +170,30 @@ class Target_x86_64 : public Sized_target<64, false> // Return whether SYM is defined by the ABI. bool - do_is_defined_by_abi(Symbol* sym) const + do_is_defined_by_abi(const Symbol* sym) const { return strcmp(sym->name(), "__tls_get_addr") == 0; } + // Return the symbol index to use for a target specific relocation. + // The only target specific relocation is R_X86_64_TLSDESC for a + // local symbol, which is an absolute reloc. + unsigned int + do_reloc_symbol_index(void*, unsigned int r_type) const + { + gold_assert(r_type == elfcpp::R_X86_64_TLSDESC); + return 0; + } + + // Return the addend to use for a target specific relocation. + uint64_t + do_reloc_addend(void* arg, unsigned int r_type, uint64_t addend) const; + + // Adjust -fstack-split code which calls non-stack-split code. + void + do_calls_non_split(Relobj* object, unsigned int shndx, + section_offset_type fnoffset, section_size_type fnsize, + unsigned char* view, section_size_type view_size, + std::string* from, std::string* to) const; + // Return the size of the GOT section. section_size_type got_size() @@ -150,6 +202,14 @@ class Target_x86_64 : public Sized_target<64, false> return this->got_->data_size(); } + // Add a new reloc argument, returning the index in the vector. + size_t + add_tlsdesc_info(Sized_relobj<64, false>* object, unsigned int r_sym) + { + this->tlsdesc_reloc_info_.push_back(Tlsdesc_info(object, r_sym)); + return this->tlsdesc_reloc_info_.size() - 1; + } + private: // The class which scans relocations. class Scan @@ -160,8 +220,7 @@ class Target_x86_64 : public Sized_target<64, false> { } inline void - local(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_x86_64* target, + local(Symbol_table* symtab, Layout* layout, Target_x86_64* target, Sized_relobj<64, false>* object, unsigned int data_shndx, Output_section* output_section, @@ -169,14 +228,33 @@ class Target_x86_64 : public Sized_target<64, false> const elfcpp::Sym<64, false>& lsym); inline void - global(const General_options& options, Symbol_table* symtab, - Layout* layout, Target_x86_64* target, + global(Symbol_table* symtab, Layout* layout, Target_x86_64* target, Sized_relobj<64, false>* object, unsigned int data_shndx, Output_section* output_section, const elfcpp::Rela<64, false>& reloc, unsigned int r_type, Symbol* gsym); + inline bool + local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout, + Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, + unsigned int r_type, + const elfcpp::Sym<64, false>& lsym); + + inline bool + global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout, + Target_x86_64* target, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + Output_section* output_section, + const elfcpp::Rela<64, false>& reloc, + unsigned int r_type, + Symbol* gsym); + private: static void unsupported_reloc_local(Sized_relobj<64, false>*, unsigned int r_type); @@ -188,6 +266,9 @@ class Target_x86_64 : public Sized_target<64, false> void check_non_pic(Relobj*, unsigned int r_type); + inline bool + possible_function_pointer_reloc(unsigned int r_type); + // Whether we have issued an error about a non-PIC compilation. bool issued_non_pic_error_; }; @@ -212,8 +293,8 @@ class Target_x86_64 : public Sized_target<64, false> // Do a relocation. Return false if the caller should not issue // any warnings about this relocation. inline bool - relocate(const Relocate_info<64, false>*, Target_x86_64*, size_t relnum, - const elfcpp::Rela<64, false>&, + relocate(const Relocate_info<64, false>*, Target_x86_64*, Output_section*, + size_t relnum, const elfcpp::Rela<64, false>&, unsigned int r_type, const Sized_symbol<64>*, const Symbol_value<64>*, unsigned char*, elfcpp::Elf_types<64>::Elf_Addr, @@ -330,7 +411,7 @@ class Target_x86_64 : public Sized_target<64, false> void make_plt_entry(Symbol_table*, Layout*, Symbol*); - // Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. + // Define the _TLS_MODULE_BASE_ symbol in the TLS segment. void define_tls_base_symbol(Symbol_table*, Layout*); @@ -355,16 +436,9 @@ class Target_x86_64 : public Sized_target<64, false> Reloc_section* rela_dyn_section(Layout*); - // Return true if the symbol may need a COPY relocation. - // References from an executable object to non-function symbols - // defined in a dynamic object may need a COPY relocation. - bool - may_need_copy_reloc(Symbol* gsym) - { - return (!parameters->options().shared() - && gsym->is_from_dynobj() - && gsym->type() != elfcpp::STT_FUNC); - } + // Get the section to use for TLSDESC relocations. + Reloc_section* + rela_tlsdesc_section(Layout*) const; // Add a potential copy relocation. void @@ -391,12 +465,29 @@ class Target_x86_64 : public Sized_target<64, false> GOT_TYPE_TLS_DESC = 3 // GOT entry for TLS_DESC pair }; + // This type is used as the argument to the target specific + // relocation routines. The only target specific reloc is + // R_X86_64_TLSDESC against a local symbol. + struct Tlsdesc_info + { + Tlsdesc_info(Sized_relobj<64, false>* a_object, unsigned int a_r_sym) + : object(a_object), r_sym(a_r_sym) + { } + + // The object in which the local symbol is defined. + Sized_relobj<64, false>* object; + // The local symbol index in the object. + unsigned int r_sym; + }; + // The GOT section. Output_data_got<64, false>* got_; // The PLT section. Output_data_plt_x86_64* plt_; // The GOT PLT section. Output_data_space* got_plt_; + // The _GLOBAL_OFFSET_TABLE_ symbol. + Symbol* global_offset_table_; // The dynamic reloc section. Reloc_section* rela_dyn_; // Relocs saved to avoid a COPY reloc. @@ -405,6 +496,10 @@ class Target_x86_64 : public Sized_target<64, false> Output_data_space* dynbss_; // Offset of the GOT entry for the TLS module index. unsigned int got_mod_index_offset_; + // We handle R_X86_64_TLSDESC against a local symbol as a target + // specific relocation. Here we store the object and local symbol + // index for the relocation. + std::vector<Tlsdesc_info> tlsdesc_reloc_info_; // True if the _TLS_MODULE_BASE_ symbol has been defined. bool tls_base_symbol_defined_; }; @@ -422,9 +517,25 @@ const Target::Target_info Target_x86_64::x86_64_info = "/lib/ld64.so.1", // program interpreter 0x400000, // default_text_segment_address 0x1000, // abi_pagesize (overridable by -z max-page-size) - 0x1000 // common_pagesize (overridable by -z common-page-size) + 0x1000, // common_pagesize (overridable by -z common-page-size) + elfcpp::SHN_UNDEF, // small_common_shndx + elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx + 0, // small_common_section_flags + elfcpp::SHF_X86_64_LARGE, // large_common_section_flags + NULL, // attributes_section + NULL // attributes_vendor }; +// This is called when a new output section is created. This is where +// we handle the SHF_X86_64_LARGE. + +void +Target_x86_64::do_new_output_section(Output_section *os) const +{ + if ((os->flags() & elfcpp::SHF_X86_64_LARGE) != 0) + os->set_is_large_section(); +} + // Get the GOT section, creating it if necessary. Output_data_got<64, false>* @@ -440,30 +551,31 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_); - os->set_is_relro(); + this->got_, false, true, true, + false); - // The old GNU linker creates a .got.plt section. We just - // create another set of data in the .got section. Note that we - // always create a PLT if we create a GOT, although the PLT - // might be empty. this->got_plt_ = new Output_data_space(8, "** GOT PLT"); - os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, + os = layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_plt_); - os->set_is_relro(); + this->got_plt_, false, false, + false, true); // The first three entries are reserved. this->got_plt_->set_current_data_size(3 * 8); + // Those bytes can go into the relro segment. + layout->increase_relro(3 * 8); + // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT. - symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, - this->got_plt_, - 0, 0, elfcpp::STT_OBJECT, - elfcpp::STB_LOCAL, - elfcpp::STV_HIDDEN, 0, - false, false); + this->global_offset_table_ = + symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, + Symbol_table::PREDEFINED, + this->got_plt_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, + false, false); } return this->got_; @@ -479,7 +591,8 @@ Target_x86_64::rela_dyn_section(Layout* layout) gold_assert(layout != NULL); this->rela_dyn_ = new Reloc_section(parameters->options().combreloc()); layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rela_dyn_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true, + false, false, false); } return this->rela_dyn_; } @@ -518,11 +631,15 @@ class Output_data_plt_x86_64 : public Output_section_data get_tlsdesc_plt_offset() const { return (this->count_ + 1) * plt_entry_size; } - // Return the .rel.plt section data. + // Return the .rela.plt section data. const Reloc_section* - rel_plt() const + rela_plt() const { return this->rel_; } + // Return where the TLSDESC relocations should go. + Reloc_section* + rela_tlsdesc(Layout*); + protected: void do_adjust_output_section(Output_section* os); @@ -557,6 +674,9 @@ class Output_data_plt_x86_64 : public Output_section_data // The reloc section. Reloc_section* rel_; + // The TLSDESC relocs, if necessary. These must follow the regular + // PLT relocs. + Reloc_section* tlsdesc_rel_; // The .got section. Output_data_got<64, false>* got_; // The .got.plt section. @@ -574,20 +694,19 @@ class Output_data_plt_x86_64 : public Output_section_data Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got, Output_data_space* got_plt) - : Output_section_data(8), got_(got), got_plt_(got_plt), count_(0), - tlsdesc_got_offset_(-1U) + : Output_section_data(8), tlsdesc_rel_(NULL), got_(got), got_plt_(got_plt), + count_(0), tlsdesc_got_offset_(-1U) { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_); + elfcpp::SHF_ALLOC, this->rel_, true, + false, false, false); } void Output_data_plt_x86_64::do_adjust_output_section(Output_section* os) { - // UnixWare sets the entsize of .plt to 4, and so does the old GNU - // linker, and so do we. - os->set_entsize(4); + os->set_entsize(plt_entry_size); } // Add an entry to the PLT. @@ -620,6 +739,24 @@ Output_data_plt_x86_64::add_entry(Symbol* gsym) // appear in the relocations. } +// Return where the TLSDESC relocations should go, creating it if +// necessary. These follow the JUMP_SLOT relocations. + +Output_data_plt_x86_64::Reloc_section* +Output_data_plt_x86_64::rela_tlsdesc(Layout* layout) +{ + if (this->tlsdesc_rel_ == NULL) + { + this->tlsdesc_rel_ = new Reloc_section(false); + layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, + elfcpp::SHF_ALLOC, this->tlsdesc_rel_, + true, false, false, false); + gold_assert(this->tlsdesc_rel_->output_section() == + this->rel_->output_section()); + } + return this->tlsdesc_rel_; +} + // Set the final size. void Output_data_plt_x86_64::set_final_data_size() @@ -777,10 +914,18 @@ Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), - this->plt_); + this->plt_, false, false, false, false); } } +// Return the section for TLSDESC relocations. + +Target_x86_64::Reloc_section* +Target_x86_64::rela_tlsdesc_section(Layout* layout) const +{ + return this->plt_section()->rela_tlsdesc(layout); +} + // Create a PLT entry for a global symbol. void @@ -796,7 +941,7 @@ Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout, this->plt_->add_entry(gsym); } -// Define the _TLS_MODULE_BASE_ symbol at the end of the TLS segment. +// Define the _TLS_MODULE_BASE_ symbol in the TLS segment. void Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) @@ -807,12 +952,17 @@ Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout) Output_segment* tls_segment = layout->tls_segment(); if (tls_segment != NULL) { + bool is_exec = parameters->options().output_is_executable(); symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL, + Symbol_table::PREDEFINED, tls_segment, 0, 0, elfcpp::STT_TLS, elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN, 0, - Symbol::SEGMENT_END, true); + (is_exec + ? Symbol::SEGMENT_END + : Symbol::SEGMENT_START), + true); } this->tls_base_symbol_defined_ = true; } @@ -954,6 +1104,7 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type) // error per object file. if (this->issued_non_pic_error_) return; + gold_assert(parameters->options().output_is_position_independent()); object->error(_("requires unsupported dynamic reloc; " "recompile with -fPIC")); this->issued_non_pic_error_ = true; @@ -967,8 +1118,7 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type) // Scan a relocation for a local symbol. inline void -Target_x86_64::Scan::local(const General_options&, - Symbol_table* symtab, +Target_x86_64::Scan::local(Symbol_table* symtab, Layout* layout, Target_x86_64* target, Sized_relobj<64, false>* object, @@ -1162,18 +1312,21 @@ Target_x86_64::Scan::local(const General_options&, Output_data_got<64, false>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info()); - unsigned int shndx = lsym.get_st_shndx(); - bool is_ordinary; - shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary); - if (!is_ordinary) - object->error(_("local symbol %u has bad shndx %u"), - r_sym, shndx); - else - got->add_local_pair_with_rela(object, r_sym, - shndx, - GOT_TYPE_TLS_DESC, - target->rela_dyn_section(layout), - elfcpp::R_X86_64_TLSDESC, 0); + if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC)) + { + unsigned int got_offset = got->add_constant(0); + got->add_constant(0); + object->set_local_got_offset(r_sym, GOT_TYPE_TLS_DESC, + got_offset); + Reloc_section* rt = target->rela_tlsdesc_section(layout); + // We store the arguments we need in a vector, and + // use the index into the vector as the parameter + // to pass to the target specific routines. + uintptr_t intarg = target->add_tlsdesc_info(object, r_sym); + void* arg = reinterpret_cast<void*>(intarg); + rt->add_target_specific(elfcpp::R_X86_64_TLSDESC, arg, + got, got_offset, 0); + } } else if (optimized_type != tls::TLSOPT_TO_LE) unsupported_reloc_local(object, r_type); @@ -1245,11 +1398,80 @@ Target_x86_64::Scan::unsupported_reloc_global(Sized_relobj<64, false>* object, object->name().c_str(), r_type, gsym->demangled_name().c_str()); } +// Returns true if this relocation type could be that of a function pointer +// only if the target is not position-independent code. +inline bool +Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type) +{ + if (parameters->options().shared()) + return false; + + switch (r_type) + { + case elfcpp::R_X86_64_64: + case elfcpp::R_X86_64_32: + case elfcpp::R_X86_64_32S: + case elfcpp::R_X86_64_16: + case elfcpp::R_X86_64_8: + { + return true; + } + } + return false; +} + +// For safe ICF, scan a relocation for a local symbol to check if it +// corresponds to a function pointer being taken. In that case mark +// the function whose pointer was taken as not foldable. + +inline bool +Target_x86_64::Scan::local_reloc_may_be_function_pointer( + Symbol_table* , + Layout* , + Target_x86_64* , + Sized_relobj<64, false>* , + unsigned int , + Output_section* , + const elfcpp::Rela<64, false>& , + unsigned int r_type, + const elfcpp::Sym<64, false>&) +{ + // When building a shared library, do not fold any local symbols as it is + // not possible to distinguish pointer taken versus a call by looking at + // the relocation types. + return (parameters->options().shared() + || possible_function_pointer_reloc(r_type)); +} + +// For safe ICF, scan a relocation for a global symbol to check if it +// corresponds to a function pointer being taken. In that case mark +// the function whose pointer was taken as not foldable. + +inline bool +Target_x86_64::Scan::global_reloc_may_be_function_pointer( + Symbol_table*, + Layout* , + Target_x86_64* , + Sized_relobj<64, false>* , + unsigned int , + Output_section* , + const elfcpp::Rela<64, false>& , + unsigned int r_type, + Symbol* gsym) +{ + // When building a shared library, do not fold symbols whose visibility + // is hidden, internal or protected. + return ((parameters->options().shared() + && (gsym->visibility() == elfcpp::STV_INTERNAL + || gsym->visibility() == elfcpp::STV_PROTECTED + || gsym->visibility() == elfcpp::STV_HIDDEN)) + || possible_function_pointer_reloc(r_type)); +} + // Scan a relocation for a global symbol. inline void -Target_x86_64::Scan::global(const General_options&, - Symbol_table* symtab, +Target_x86_64::Scan::global(Symbol_table* symtab, Layout* layout, Target_x86_64* target, Sized_relobj<64, false>* object, @@ -1286,7 +1508,7 @@ Target_x86_64::Scan::global(const General_options&, // Make a dynamic relocation if necessary. if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -1322,11 +1544,11 @@ Target_x86_64::Scan::global(const General_options&, target->make_plt_entry(symtab, layout, gsym); // Make a dynamic relocation if necessary. int flags = Symbol::NON_PIC_REF; - if (gsym->type() == elfcpp::STT_FUNC) + if (gsym->is_func()) flags |= Symbol::FUNCTION_CALL; if (gsym->needs_dynamic_reloc(flags)) { - if (target->may_need_copy_reloc(gsym)) + if (gsym->may_need_copy_reloc()) { target->copy_reloc(symtab, layout, object, data_shndx, output_section, gsym, reloc); @@ -1469,8 +1691,8 @@ Target_x86_64::Scan::global(const General_options&, // Create a double GOT entry with an R_X86_64_TLSDESC reloc. Output_data_got<64, false>* got = target->got_section(symtab, layout); - got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, - target->rela_dyn_section(layout), + Reloc_section *rt = target->rela_tlsdesc_section(layout); + got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt, elfcpp::R_X86_64_TLSDESC, 0); } else if (optimized_type == tls::TLSOPT_TO_IE) @@ -1540,11 +1762,44 @@ Target_x86_64::Scan::global(const General_options&, } } +void +Target_x86_64::gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Sized_relobj<64, false>* object, + unsigned int data_shndx, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + size_t local_symbol_count, + const unsigned char* plocal_symbols) +{ + + if (sh_type == elfcpp::SHT_REL) + { + return; + } + + gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA, + Target_x86_64::Scan>( + symtab, + layout, + this, + object, + data_shndx, + prelocs, + reloc_count, + output_section, + needs_special_offset_handling, + local_symbol_count, + plocal_symbols); + +} // Scan relocations for a section. void -Target_x86_64::scan_relocs(const General_options& options, - Symbol_table* symtab, +Target_x86_64::scan_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<64, false>* object, unsigned int data_shndx, @@ -1565,7 +1820,6 @@ Target_x86_64::scan_relocs(const General_options& options, gold::scan_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA, Target_x86_64::Scan>( - options, symtab, layout, this, @@ -1582,47 +1836,32 @@ Target_x86_64::scan_relocs(const General_options& options, // Finalize the sections. void -Target_x86_64::do_finalize_sections(Layout* layout) +Target_x86_64::do_finalize_sections( + Layout* layout, + const Input_objects*, + Symbol_table* symtab) { + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rela_plt()); + layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt, + this->rela_dyn_, true, false); + // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); if (odyn != NULL) { - if (this->got_plt_ != NULL) - odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); - - if (this->plt_ != NULL) + if (this->plt_ != NULL + && this->plt_->output_section() != NULL + && this->plt_->has_tlsdesc_entry()) { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - if (this->plt_->has_tlsdesc_entry()) - { - unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); - unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); - this->got_->finalize_data_size(); - odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, - this->plt_, plt_offset); - odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, - this->got_, got_offset); - } - } - - if (this->rela_dyn_ != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<64>::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); + unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); + unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); + this->got_->finalize_data_size(); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, + this->plt_, plt_offset); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, + this->got_, got_offset); } } @@ -1630,6 +1869,15 @@ Target_x86_64::do_finalize_sections(Layout* layout) // relocs. if (this->copy_relocs_.any_saved_relocs()) this->copy_relocs_.emit(this->rela_dyn_section(layout)); + + // Set the size of the _GLOBAL_OFFSET_TABLE_ symbol to the size of + // the .got.plt section. + Symbol* sym = this->global_offset_table_; + if (sym != NULL) + { + uint64_t data_size = this->got_plt_->current_data_size(); + symtab->get_sized_symbol<64>(sym)->set_symsize(data_size); + } } // Perform a relocation. @@ -1637,6 +1885,7 @@ Target_x86_64::do_finalize_sections(Layout* layout) inline bool Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, Target_x86_64* target, + Output_section*, size_t relnum, const elfcpp::Rela<64, false>& rela, unsigned int r_type, @@ -1648,7 +1897,8 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, { if (this->skip_call_tls_get_addr_) { - if (r_type != elfcpp::R_X86_64_PLT32 + if ((r_type != elfcpp::R_X86_64_PLT32 + && r_type != elfcpp::R_X86_64_PC32) || gsym == NULL || strcmp(gsym->name(), "__tls_get_addr") != 0) { @@ -1907,7 +2157,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0); const bool is_final = (gsym == NULL - ? !parameters->options().output_is_position_independent() + ? !parameters->options().shared() : gsym->final_value_is_known()); const tls::Tls_optimization optimized_type = Target_x86_64::optimize_tls_reloc(is_final, r_type); @@ -2044,7 +2294,6 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, break; case elfcpp::R_X86_64_DTPOFF32: - gold_assert(tls_segment != NULL); if (optimized_type == tls::TLSOPT_TO_LE) { // This relocation type is used in debugging information. @@ -2052,18 +2301,23 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo, // haven't seen a TLSLD reloc, then we assume we should not // optimize this reloc. if (this->saw_tls_block_reloc_) - value -= tls_segment->memsz(); + { + gold_assert(tls_segment != NULL); + value -= tls_segment->memsz(); + } } Relocate_functions<64, false>::rela32(view, value, addend); break; case elfcpp::R_X86_64_DTPOFF64: - gold_assert(tls_segment != NULL); if (optimized_type == tls::TLSOPT_TO_LE) { // See R_X86_64_DTPOFF32, just above, for why we test this. if (this->saw_tls_block_reloc_) - value -= tls_segment->memsz(); + { + gold_assert(tls_segment != NULL); + value -= tls_segment->memsz(); + } } Relocate_functions<64, false>::rela64(view, value, addend); break; @@ -2349,15 +2603,17 @@ Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo, // Relocate section data. void -Target_x86_64::relocate_section(const Relocate_info<64, false>* relinfo, - unsigned int sh_type, - const unsigned char* prelocs, - size_t reloc_count, - Output_section* output_section, - bool needs_special_offset_handling, - unsigned char* view, - elfcpp::Elf_types<64>::Elf_Addr address, - section_size_type view_size) +Target_x86_64::relocate_section( + const Relocate_info<64, false>* relinfo, + unsigned int sh_type, + const unsigned char* prelocs, + size_t reloc_count, + Output_section* output_section, + bool needs_special_offset_handling, + unsigned char* view, + elfcpp::Elf_types<64>::Elf_Addr address, + section_size_type view_size, + const Reloc_symbol_changes* reloc_symbol_changes) { gold_assert(sh_type == elfcpp::SHT_RELA); @@ -2371,7 +2627,8 @@ Target_x86_64::relocate_section(const Relocate_info<64, false>* relinfo, needs_special_offset_handling, view, address, - view_size); + view_size, + reloc_symbol_changes); } // Return the size of a relocation while scanning during a relocatable @@ -2446,8 +2703,7 @@ Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc( // Scan the relocs during a relocatable link. void -Target_x86_64::scan_relocatable_relocs(const General_options& options, - Symbol_table* symtab, +Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab, Layout* layout, Sized_relobj<64, false>* object, unsigned int data_shndx, @@ -2467,7 +2723,6 @@ Target_x86_64::scan_relocatable_relocs(const General_options& options, gold::scan_relocatable_relocs<64, false, elfcpp::SHT_RELA, Scan_relocatable_relocs>( - options, symtab, layout, object, @@ -2545,40 +2800,40 @@ Target_x86_64::do_code_fill(section_size_type length) const // Nop sequences of various lengths. const char nop1[1] = { 0x90 }; // nop const char nop2[2] = { 0x66, 0x90 }; // xchg %ax %ax - const char nop3[3] = { 0x8d, 0x76, 0x00 }; // leal 0(%esi),%esi - const char nop4[4] = { 0x8d, 0x74, 0x26, 0x00}; // leal 0(%esi,1),%esi - const char nop5[5] = { 0x90, 0x8d, 0x74, 0x26, // nop - 0x00 }; // leal 0(%esi,1),%esi - const char nop6[6] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi + const char nop3[3] = { 0x0f, 0x1f, 0x00 }; // nop (%rax) + const char nop4[4] = { 0x0f, 0x1f, 0x40, 0x00}; // nop 0(%rax) + const char nop5[5] = { 0x0f, 0x1f, 0x44, 0x00, // nop 0(%rax,%rax,1) + 0x00 }; + const char nop6[6] = { 0x66, 0x0f, 0x1f, 0x44, // nopw 0(%rax,%rax,1) 0x00, 0x00 }; - const char nop7[7] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi + const char nop7[7] = { 0x0f, 0x1f, 0x80, 0x00, // nopl 0L(%rax) 0x00, 0x00, 0x00 }; - const char nop8[8] = { 0x90, 0x8d, 0xb4, 0x26, // nop - 0x00, 0x00, 0x00, 0x00 }; // leal 0L(%esi,1),%esi - const char nop9[9] = { 0x89, 0xf6, 0x8d, 0xbc, // movl %esi,%esi - 0x27, 0x00, 0x00, 0x00, // leal 0L(%edi,1),%edi + const char nop8[8] = { 0x0f, 0x1f, 0x84, 0x00, // nopl 0L(%rax,%rax,1) + 0x00, 0x00, 0x00, 0x00 }; + const char nop9[9] = { 0x66, 0x0f, 0x1f, 0x84, // nopw 0L(%rax,%rax,1) + 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char nop10[10] = { 0x8d, 0x76, 0x00, 0x8d, // leal 0(%esi),%esi - 0xbc, 0x27, 0x00, 0x00, // leal 0L(%edi,1),%edi + const char nop10[10] = { 0x66, 0x2e, 0x0f, 0x1f, // nopw %cs:0L(%rax,%rax,1) + 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char nop11[11] = { 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi - 0x8d, 0xbc, 0x27, 0x00, // leal 0L(%edi,1),%edi + const char nop11[11] = { 0x66, 0x66, 0x2e, 0x0f, // data16 + 0x1f, 0x84, 0x00, 0x00, // nopw %cs:0L(%rax,%rax,1) 0x00, 0x00, 0x00 }; - const char nop12[12] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi - 0x00, 0x00, 0x8d, 0xbf, // leal 0L(%edi),%edi + const char nop12[12] = { 0x66, 0x66, 0x66, 0x2e, // data16; data16 + 0x0f, 0x1f, 0x84, 0x00, // nopw %cs:0L(%rax,%rax,1) 0x00, 0x00, 0x00, 0x00 }; - const char nop13[13] = { 0x8d, 0xb6, 0x00, 0x00, // leal 0L(%esi),%esi - 0x00, 0x00, 0x8d, 0xbc, // leal 0L(%edi,1),%edi - 0x27, 0x00, 0x00, 0x00, + const char nop13[13] = { 0x66, 0x66, 0x66, 0x66, // data16; data16; data16 + 0x2e, 0x0f, 0x1f, 0x84, // nopw %cs:0L(%rax,%rax,1) + 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char nop14[14] = { 0x8d, 0xb4, 0x26, 0x00, // leal 0L(%esi,1),%esi - 0x00, 0x00, 0x00, 0x8d, // leal 0L(%edi,1),%edi - 0xbc, 0x27, 0x00, 0x00, + const char nop14[14] = { 0x66, 0x66, 0x66, 0x66, // data16; data16; data16 + 0x66, 0x2e, 0x0f, 0x1f, // data16 + 0x84, 0x00, 0x00, 0x00, // nopw %cs:0L(%rax,%rax,1) 0x00, 0x00 }; - const char nop15[15] = { 0xeb, 0x0d, 0x90, 0x90, // jmp .+15 - 0x90, 0x90, 0x90, 0x90, // nop,nop,nop,... - 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90 }; + const char nop15[15] = { 0x66, 0x66, 0x66, 0x66, // data16; data16; data16 + 0x66, 0x66, 0x2e, 0x0f, // data16; data16 + 0x1f, 0x84, 0x00, 0x00, // nopw %cs:0L(%rax,%rax,1) + 0x00, 0x00, 0x00 }; const char* nops[16] = { NULL, @@ -2589,18 +2844,100 @@ Target_x86_64::do_code_fill(section_size_type length) const return std::string(nops[length], length); } +// Return the addend to use for a target specific relocation. The +// only target specific relocation is R_X86_64_TLSDESC for a local +// symbol. We want to set the addend is the offset of the local +// symbol in the TLS segment. + +uint64_t +Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type, + uint64_t) const +{ + gold_assert(r_type == elfcpp::R_X86_64_TLSDESC); + uintptr_t intarg = reinterpret_cast<uintptr_t>(arg); + gold_assert(intarg < this->tlsdesc_reloc_info_.size()); + const Tlsdesc_info& ti(this->tlsdesc_reloc_info_[intarg]); + const Symbol_value<64>* psymval = ti.object->local_symbol(ti.r_sym); + gold_assert(psymval->is_tls_symbol()); + // The value of a TLS symbol is the offset in the TLS segment. + return psymval->value(ti.object, 0); +} + +// FNOFFSET in section SHNDX in OBJECT is the start of a function +// compiled with -fstack-split. The function calls non-stack-split +// code. We have to change the function so that it always ensures +// that it has enough stack space to run some random function. + +void +Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx, + section_offset_type fnoffset, + section_size_type fnsize, + unsigned char* view, + section_size_type view_size, + std::string* from, + std::string* to) const +{ + // The function starts with a comparison of the stack pointer and a + // field in the TCB. This is followed by a jump. + + // cmp %fs:NN,%rsp + if (this->match_view(view, view_size, fnoffset, "\x64\x48\x3b\x24\x25", 5) + && fnsize > 9) + { + // We will call __morestack if the carry flag is set after this + // comparison. We turn the comparison into an stc instruction + // and some nops. + view[fnoffset] = '\xf9'; + this->set_view_to_nop(view, view_size, fnoffset + 1, 8); + } + // lea NN(%rsp),%r10 + // lea NN(%rsp),%r11 + else if ((this->match_view(view, view_size, fnoffset, + "\x4c\x8d\x94\x24", 4) + || this->match_view(view, view_size, fnoffset, + "\x4c\x8d\x9c\x24", 4)) + && fnsize > 8) + { + // This is loading an offset from the stack pointer for a + // comparison. The offset is negative, so we decrease the + // offset by the amount of space we need for the stack. This + // means we will avoid calling __morestack if there happens to + // be plenty of space on the stack already. + unsigned char* pval = view + fnoffset + 4; + uint32_t val = elfcpp::Swap_unaligned<32, false>::readval(pval); + val -= parameters->options().split_stack_adjust_size(); + elfcpp::Swap_unaligned<32, false>::writeval(pval, val); + } + else + { + if (!object->has_no_split_stack()) + object->error(_("failed to match split-stack sequence at " + "section %u offset %0zx"), + shndx, static_cast<size_t>(fnoffset)); + return; + } + + // We have to change the function so that it calls + // __morestack_non_split instead of __morestack. The former will + // allocate additional stack space. + *from = "__morestack"; + *to = "__morestack_non_split"; +} + // The selector for x86_64 object files. -class Target_selector_x86_64 : public Target_selector +class Target_selector_x86_64 : public Target_selector_freebsd { public: Target_selector_x86_64() - : Target_selector(elfcpp::EM_X86_64, 64, false, "elf64-x86-64") + : Target_selector_freebsd(elfcpp::EM_X86_64, 64, false, "elf64-x86-64", + "elf64-x86-64-freebsd") { } Target* do_instantiate_target() { return new Target_x86_64(); } + }; Target_selector_x86_64 target_selector_x86_64; diff --git a/binutils-2.19/gold/yyscript.y b/binutils-2.19/gold/yyscript.y index 683273b..f762536 100644 --- a/binutils-2.19/gold/yyscript.y +++ b/binutils-2.19/gold/yyscript.y @@ -77,6 +77,7 @@ struct Version_dependency_list* deplist; struct Version_expression_list* versyms; struct Version_tree* versnode; + enum Script_section_type section_type; } /* Operators, including a precedence table for expressions. */ @@ -121,11 +122,13 @@ %token BYTE %token CONSTANT %token CONSTRUCTORS +%token COPY %token CREATE_OBJECT_SYMBOLS %token DATA_SEGMENT_ALIGN %token DATA_SEGMENT_END %token DATA_SEGMENT_RELRO_END %token DEFINED +%token DSECT %token ENTRY %token EXCLUDE_FILE %token EXTERN @@ -137,6 +140,7 @@ %token HLL %token INCLUDE %token INHIBIT_COMMON_ALLOCATION +%token INFO %token INPUT %token KEEP %token LENGTH /* LENGTH, l, len */ @@ -150,6 +154,7 @@ %token NEXT %token NOCROSSREFS %token NOFLOAT +%token NOLOAD %token ONLY_IF_RO %token ONLY_IF_RW %token ORIGIN /* ORIGIN, o, org */ @@ -193,12 +198,14 @@ %token PARSING_LINKER_SCRIPT %token PARSING_VERSION_SCRIPT %token PARSING_DEFSYM +%token PARSING_DYNAMIC_LIST /* Non-terminal types, where needed. */ -%type <expr> parse_exp exp opt_address_and_section_type +%type <expr> parse_exp exp %type <expr> opt_at opt_align opt_subalign opt_fill -%type <output_section_header> section_header +%type <output_section_header> section_header opt_address_and_section_type +%type <section_type> section_type %type <output_section_trailer> section_trailer %type <constraint> opt_constraint %type <string_list> opt_phdr @@ -222,6 +229,7 @@ top: PARSING_LINKER_SCRIPT linker_script | PARSING_VERSION_SCRIPT version_script | PARSING_DEFSYM defsym_expr + | PARSING_DYNAMIC_LIST dynamic_list_expr ; /* A file contains a list of commands. */ @@ -232,7 +240,8 @@ linker_script: /* A command which may appear at top level of a linker script. */ file_cmd: - FORCE_COMMON_ALLOCATION + EXTERN '(' extern_name_list ')' + | FORCE_COMMON_ALLOCATION { script_set_common_allocation(closure, 1); } | GROUP { script_start_group(closure); } @@ -240,8 +249,22 @@ file_cmd: { script_end_group(closure); } | INHIBIT_COMMON_ALLOCATION { script_set_common_allocation(closure, 0); } + | INPUT '(' input_list ')' | OPTION '(' string ')' { script_parse_option(closure, $3.value, $3.length); } + | OUTPUT_FORMAT '(' string ')' + { + if (!script_check_output_format(closure, $3.value, $3.length, + NULL, 0, NULL, 0)) + YYABORT; + } + | OUTPUT_FORMAT '(' string ',' string ',' string ')' + { + if (!script_check_output_format(closure, $3.value, $3.length, + $5.value, $5.length, + $7.value, $7.length)) + YYABORT; + } | PHDRS '{' phdrs_defs '}' | SEARCH_DIR '(' string ')' { script_add_search_dir(closure, $3.value, $3.length); } @@ -249,6 +272,8 @@ file_cmd: { script_start_sections(closure); } sections_block '}' { script_finish_sections(closure); } + | TARGET_K '(' string ')' + { script_set_target(closure, $3.value, $3.length); } | VERSIONK '{' { script_push_lex_into_version_mode(closure); } version_script '}' @@ -263,9 +288,26 @@ file_cmd: these is more-or-less OK since most scripts simply explicitly choose the default. */ ignore_cmd: - OUTPUT_FORMAT '(' string ')' - | OUTPUT_FORMAT '(' string ',' string ',' string ')' - | OUTPUT_ARCH '(' string ')' + OUTPUT_ARCH '(' string ')' + ; + +/* A list of external undefined symbols. We put the lexer into + expression mode so that commas separate names; this is what the GNU + linker does. */ + +extern_name_list: + { script_push_lex_into_expression_mode(closure); } + extern_name_list_body + { script_pop_lex_mode(closure); } + ; + +extern_name_list_body: + string + { script_add_extern(closure, $1.value, $1.length); } + | extern_name_list_body string + { script_add_extern(closure, $2.value, $2.length); } + | extern_name_list_body ',' string + { script_add_extern(closure, $3.value, $3.length); } ; /* A list of input file names. */ @@ -307,7 +349,8 @@ section_header: { script_pop_lex_mode(closure); } opt_constraint { - $$.address = $2; + $$.address = $2.address; + $$.section_type = $2.section_type; $$.load_address = $3; $$.align = $4; $$.subalign = $5; @@ -320,18 +363,61 @@ section_header: '(' in section_header. */ opt_address_and_section_type: - ':' - { $$ = NULL; } + ':' + { + $$.address = NULL; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | '(' ')' ':' - { $$ = NULL; } + { + $$.address = NULL; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | exp ':' - { $$ = $1; } + { + $$.address = $1; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } | exp '(' ')' ':' - { $$ = $1; } - | exp '(' string ')' ':' { - yyerror(closure, "section types are not supported"); - $$ = $1; + $$.address = $1; + $$.section_type = SCRIPT_SECTION_TYPE_NONE; + } + | '(' section_type ')' ':' + { + $$.address = NULL; + $$.section_type = $2; + } + | exp '(' section_type ')' ':' + { + $$.address = $1; + $$.section_type = $3; + } + ; + +/* We only support NOLOAD. */ +section_type: + NOLOAD + { $$ = SCRIPT_SECTION_TYPE_NOLOAD; } + | DSECT + { + yyerror(closure, "DSECT section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_DSECT; + } + | COPY + { + yyerror(closure, "COPY section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_COPY; + } + | INFO + { + yyerror(closure, "INFO section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_INFO; + } + | OVERLAY + { + yyerror(closure, "OVERLAY section type is unsupported"); + $$ = SCRIPT_SECTION_TYPE_OVERLAY; } ; @@ -825,6 +911,10 @@ exp: | SEGMENT_START '(' string ',' exp ')' { $$ = script_exp_function_segment_start($3.value, $3.length, $5); + /* We need to take note of any SEGMENT_START expressions + because they change the behaviour of -Ttext, -Tdata and + -Tbss options. */ + script_saw_segment_start_expression(closure); } | ASSERT_K '(' exp ',' string ')' { $$ = script_exp_function_assert($3, $5.value, $5.length); } @@ -836,6 +926,24 @@ defsym_expr: { script_set_symbol(closure, $1.value, $1.length, $3, 0, 0); } ; +/* Handle the --dynamic-list option. A dynamic list has the format + { sym1; sym2; extern "C++" { namespace::sym3 }; }; + We store the symbol we see in the "local" list; that is where + Command_line::in_dynamic_list() will look to do its check. + TODO(csilvers): More than one of these brace-lists can appear, and + should just be merged and treated as a single list. */ +dynamic_list_expr: dynamic_list_nodes ; + +dynamic_list_nodes: + dynamic_list_node + | dynamic_list_nodes dynamic_list_node + ; + +dynamic_list_node: + '{' vers_defns ';' '}' ';' + { script_new_vers_node (closure, NULL, $2); } + ; + /* A version script. */ version_script: vers_nodes diff --git a/binutils-2.19/include/libiberty.h b/binutils-2.19/include/libiberty.h index e3eca9d..d8707bc 100644 --- a/binutils-2.19/include/libiberty.h +++ b/binutils-2.19/include/libiberty.h @@ -311,6 +311,8 @@ extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC; extern double physmem_total (void); extern double physmem_available (void); +/* Compute the 32-bit CRC of a block of memory. */ +extern unsigned int xcrc32 (const unsigned char *, int, unsigned int); /* These macros provide a K&R/C89/C++-friendly way of allocating structures with nice encapsulation. The XDELETE*() macros are technically diff --git a/binutils-2.19/include/plugin-api.h b/binutils-2.19/include/plugin-api.h new file mode 100644 index 0000000..572621f --- /dev/null +++ b/binutils-2.19/include/plugin-api.h @@ -0,0 +1,298 @@ +/* plugin-api.h -- External linker plugin API. */ + +/* Copyright 2009 Free Software Foundation, Inc. + Written by Cary Coutant <ccoutant@google.com>. + + This file is part of binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* This file defines the interface for writing a linker plugin, which is + described at < http://gcc.gnu.org/wiki/whopr/driver >. */ + +#ifndef PLUGIN_API_H +#define PLUGIN_API_H + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#elif defined(HAVE_INTTYPES_H) +#include <inttypes.h> +#endif +#include <sys/types.h> +#if !defined(HAVE_STDINT_H) && !defined(HAVE_INTTYPES_H) && \ + !defined(UINT64_MAX) && !defined(uint64_t) +#error can not find uint64_t type +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Status code returned by most API routines. */ + +enum ld_plugin_status +{ + LDPS_OK = 0, + LDPS_NO_SYMS, /* Attempt to get symbols that haven't been added. */ + LDPS_BAD_HANDLE, /* No claimed object associated with given handle. */ + LDPS_ERR + /* Additional Error codes TBD. */ +}; + +/* The version of the API specification. */ + +enum ld_plugin_api_version +{ + LD_PLUGIN_API_VERSION = 1 +}; + +/* The type of output file being generated by the linker. */ + +enum ld_plugin_output_file_type +{ + LDPO_REL, + LDPO_EXEC, + LDPO_DYN +}; + +/* An input file managed by the plugin library. */ + +struct ld_plugin_input_file +{ + const char *name; + int fd; + off_t offset; + off_t filesize; + void *handle; +}; + +/* A symbol belonging to an input file managed by the plugin library. */ + +struct ld_plugin_symbol +{ + char *name; + char *version; + int def; + int visibility; + uint64_t size; + char *comdat_key; + int resolution; +}; + +/* Whether the symbol is a definition, reference, or common, weak or not. */ + +enum ld_plugin_symbol_kind +{ + LDPK_DEF, + LDPK_WEAKDEF, + LDPK_UNDEF, + LDPK_WEAKUNDEF, + LDPK_COMMON +}; + +/* The visibility of the symbol. */ + +enum ld_plugin_symbol_visibility +{ + LDPV_DEFAULT, + LDPV_PROTECTED, + LDPV_INTERNAL, + LDPV_HIDDEN +}; + +/* How a symbol is resolved. */ + +enum ld_plugin_symbol_resolution +{ + LDPR_UNKNOWN = 0, + + /* Symbol is still undefined at this point. */ + LDPR_UNDEF, + + /* This is the prevailing definition of the symbol, with references from + regular object code. */ + LDPR_PREVAILING_DEF, + + /* This is the prevailing definition of the symbol, with no + references from regular objects. It is only referenced from IR + code. */ + LDPR_PREVAILING_DEF_IRONLY, + + /* This definition was pre-empted by a definition in a regular + object file. */ + LDPR_PREEMPTED_REG, + + /* This definition was pre-empted by a definition in another IR file. */ + LDPR_PREEMPTED_IR, + + /* This symbol was resolved by a definition in another IR file. */ + LDPR_RESOLVED_IR, + + /* This symbol was resolved by a definition in a regular object + linked into the main executable. */ + LDPR_RESOLVED_EXEC, + + /* This symbol was resolved by a definition in a shared object. */ + LDPR_RESOLVED_DYN +}; + +/* The plugin library's "claim file" handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_claim_file_handler) ( + const struct ld_plugin_input_file *file, int *claimed); + +/* The plugin library's "all symbols read" handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_all_symbols_read_handler) (void); + +/* The plugin library's cleanup handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_cleanup_handler) (void); + +/* The linker's interface for registering the "claim file" handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_register_claim_file) (ld_plugin_claim_file_handler handler); + +/* The linker's interface for registering the "all symbols read" handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_register_all_symbols_read) ( + ld_plugin_all_symbols_read_handler handler); + +/* The linker's interface for registering the cleanup handler. */ + +typedef +enum ld_plugin_status +(*ld_plugin_register_cleanup) (ld_plugin_cleanup_handler handler); + +/* The linker's interface for adding symbols from a claimed input file. */ + +typedef +enum ld_plugin_status +(*ld_plugin_add_symbols) (void *handle, int nsyms, + const struct ld_plugin_symbol *syms); + +/* The linker's interface for getting the input file information with + an open (possibly re-opened) file descriptor. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_input_file) (const void *handle, + struct ld_plugin_input_file *file); + +/* The linker's interface for releasing the input file. */ + +typedef +enum ld_plugin_status +(*ld_plugin_release_input_file) (const void *handle); + +/* The linker's interface for retrieving symbol resolution information. */ + +typedef +enum ld_plugin_status +(*ld_plugin_get_symbols) (const void *handle, int nsyms, + struct ld_plugin_symbol *syms); + +/* The linker's interface for adding a compiled input file. */ + +typedef +enum ld_plugin_status +(*ld_plugin_add_input_file) (char *pathname); + +/* The linker's interface for adding a library that should be searched. */ + +typedef +enum ld_plugin_status +(*ld_plugin_add_input_library) (char *libname); + +/* The linker's interface for issuing a warning or error message. */ + +typedef +enum ld_plugin_status +(*ld_plugin_message) (int level, const char *format, ...); + +enum ld_plugin_level +{ + LDPL_INFO, + LDPL_WARNING, + LDPL_ERROR, + LDPL_FATAL +}; + +/* Values for the tv_tag field of the transfer vector. */ + +enum ld_plugin_tag +{ + LDPT_NULL = 0, + LDPT_API_VERSION, + LDPT_GOLD_VERSION, + LDPT_LINKER_OUTPUT, + LDPT_OPTION, + LDPT_REGISTER_CLAIM_FILE_HOOK, + LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK, + LDPT_REGISTER_CLEANUP_HOOK, + LDPT_ADD_SYMBOLS, + LDPT_GET_SYMBOLS, + LDPT_ADD_INPUT_FILE, + LDPT_MESSAGE, + LDPT_GET_INPUT_FILE, + LDPT_RELEASE_INPUT_FILE, + LDPT_ADD_INPUT_LIBRARY +}; + +/* The plugin transfer vector. */ + +struct ld_plugin_tv +{ + enum ld_plugin_tag tv_tag; + union + { + int tv_val; + const char *tv_string; + ld_plugin_register_claim_file tv_register_claim_file; + ld_plugin_register_all_symbols_read tv_register_all_symbols_read; + ld_plugin_register_cleanup tv_register_cleanup; + ld_plugin_add_symbols tv_add_symbols; + ld_plugin_get_symbols tv_get_symbols; + ld_plugin_add_input_file tv_add_input_file; + ld_plugin_message tv_message; + ld_plugin_get_input_file tv_get_input_file; + ld_plugin_release_input_file tv_release_input_file; + ld_plugin_add_input_library tv_add_input_library; + } tv_u; +}; + +/* The plugin library's "onload" entry point. */ + +typedef +enum ld_plugin_status +(*ld_plugin_onload) (struct ld_plugin_tv *tv); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(PLUGIN_API_H) */ diff --git a/binutils-2.19/ld/testsuite/ld-pe/secrel_64.d b/binutils-2.19/ld/testsuite/ld-pe/secrel_64.d index aba1bf1..4f1da93 100644 --- a/binutils-2.19/ld/testsuite/ld-pe/secrel_64.d +++ b/binutils-2.19/ld/testsuite/ld-pe/secrel_64.d @@ -1,28 +1,28 @@ -
-tmpdir/secrel\.x: +file format pei-.*
-
-Contents of section \.text:
- .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<<
- .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>><
- .*1020 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<<
- .*1030 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>><
- .*1040 ffffffff ffffffff 00000000 00000000 ................
- .*1050 ffffffff ffffffff 00000000 00000000 ................
-Contents of section \.data:
- .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<<
- .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>><
- .*2020 3e3e3e3e 04000000 110d0000 00111600 >>>>............
- .*2030 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<<
- .*2040 3e3e3e3e 04000000 110d0000 00111600 >>>>............
- .*2050 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<<
- .*2060 3e3e3e3e 04000000 110d0000 00111600 >>>>............
- .*2070 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<<
- .*2080 3e3e3e3e 24000000 112d0000 00113600 >>>>\$....-....6.
- .*2090 0000113f 00000011 3c3c3c3c 3c3c3c3c ...\?....<<<<<<<<
-Contents of section \.rdata:
- .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<<
- .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>><
- .*3020 3e3e3e3e 00000000 00000000 00000000 >>>>............
-Contents of section \.idata:
- .*4000 00000000 00000000 00000000 00000000 ................
- .*4010 00000000 ....
+ +tmpdir/secrel\.x: +file format pei-.* + +Contents of section \.text: + .*1000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<< + .*1010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>>< + .*1020 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<< + .*1030 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>>< + .*1040 ffffffff ffffffff 00000000 00000000 ................ + .*1050 ffffffff ffffffff 00000000 00000000 ................ +Contents of section \.data: + .*2000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<< + .*2010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>>< + .*2020 3e3e3e3e 04000000 110d0000 00111600 >>>>............ + .*2030 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<< + .*2040 3e3e3e3e 04000000 110d0000 00111600 >>>>............ + .*2050 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<< + .*2060 3e3e3e3e 04000000 110d0000 00111600 >>>>............ + .*2070 0000111f 00000011 3c3c3c3c 3c3c3c3c ........<<<<<<<< + .*2080 3e3e3e3e 24000000 112d0000 00113600 >>>>\$....-....6. + .*2090 0000113f 00000011 3c3c3c3c 3c3c3c3c ...\?....<<<<<<<< +Contents of section \.rdata: + .*3000 3e3e3e3e 3c3c3c3c 3e3e3e3e 3e3c3c3c >>>><<<<>>>>><<< + .*3010 3e3e3e3e 3e3e3c3c 3e3e3e3e 3e3e3e3c >>>>>><<>>>>>>>< + .*3020 3e3e3e3e 00000000 00000000 00000000 >>>>............ +Contents of section \.idata: + .*4000 00000000 00000000 00000000 00000000 ................ + .*4010 00000000 .... diff --git a/binutils-2.19/libiberty/Makefile.in b/binutils-2.19/libiberty/Makefile.in index e18aff7..c35e2a4 100644 --- a/binutils-2.19/libiberty/Makefile.in +++ b/binutils-2.19/libiberty/Makefile.in @@ -124,7 +124,7 @@ COMPILE.c = $(CC) -c @DEFS@ $(LIBCFLAGS) -I. -I$(INCDIR) $(HDEFINES) @ac_libiber CFILES = alloca.c argv.c asprintf.c atexit.c \ basename.c bcmp.c bcopy.c bsearch.c bzero.c \ calloc.c choose-temp.c clock.c concat.c cp-demangle.c \ - cp-demint.c cplus-dem.c \ + cp-demint.c cplus-dem.c crc32.c \ dyn-string.c \ fdmatch.c ffs.c fibheap.c filename_cmp.c floatformat.c \ fnmatch.c fopen_unlocked.c \ @@ -135,8 +135,8 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \ lbasename.c \ lrealpath.c \ make-relative-prefix.c \ - make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmove.c \ - mempcpy.c memset.c mkstemps.c \ + make-temp-file.c md5.c memchr.c memcmp.c memcpy.c memmem.c \ + memmove.c mempcpy.c memset.c mkstemps.c \ objalloc.c obstack.c \ partition.c pexecute.c \ pex-common.c pex-djgpp.c pex-msdos.c pex-one.c \ @@ -160,7 +160,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \ REQUIRED_OFILES = \ ./regex.o ./cplus-dem.o ./cp-demangle.o ./md5.o ./sha1.o \ ./alloca.o ./argv.o \ - ./choose-temp.o ./concat.o ./cp-demint.o \ + ./choose-temp.o ./concat.o ./cp-demint.o crc32.o \ ./dyn-string.o \ ./fdmatch.o ./fibheap.o ./filename_cmp.o ./floatformat.o \ ./fnmatch.o ./fopen_unlocked.o \ @@ -187,8 +187,8 @@ CONFIGURED_OFILES = ./asprintf.o ./atexit.o \ ./ffs.o \ ./getcwd.o ./getpagesize.o ./gettimeofday.o \ ./index.o ./insque.o \ - ./memchr.o ./memcmp.o ./memcpy.o ./memmove.o ./mempcpy.o \ - ./memset.o ./mkstemps.o \ + ./memchr.o ./memcmp.o ./memcpy.o ./memmem.o ./memmove.o \ + ./mempcpy.o ./memset.o ./mkstemps.o \ ./pex-djgpp.o ./pex-msdos.o \ ./pex-unix.o ./pex-win32.o \ ./putenv.o \ @@ -619,6 +619,12 @@ $(CONFIGURED_OFILES): stamp-picdir else true; fi $(COMPILE.c) $(srcdir)/cplus-dem.c $(OUTPUT_OPTION) +./crc32.o: $(srcdir)/crc32.c config.h $(INCDIR)/ansidecl.h $(INCDIR)/libiberty.h + if [ x"$(PICFLAG)" != x ]; then \ + $(COMPILE.c) $(PICFLAG) $(srcdir)/crc32.c -o pic/$@; \ + else true; fi + $(COMPILE.c) $(srcdir)/crc32.c $(OUTPUT_OPTION) + ./dyn-string.o: $(srcdir)/dyn-string.c config.h $(INCDIR)/ansidecl.h \ $(INCDIR)/dyn-string.h $(INCDIR)/libiberty.h if [ x"$(PICFLAG)" != x ]; then \ @@ -798,6 +804,12 @@ $(CONFIGURED_OFILES): stamp-picdir else true; fi $(COMPILE.c) $(srcdir)/memcpy.c $(OUTPUT_OPTION) +./memmem.o: $(srcdir)/memmem.c config.h + if [ x"$(PICFLAG)" != x ]; then \ + $(COMPILE.c) $(PICFLAG) $(srcdir)/memmem.c -o pic/$@; \ + else true; fi + $(COMPILE.c) $(srcdir)/memmem.c $(OUTPUT_OPTION) + ./memmove.o: $(srcdir)/memmove.c $(INCDIR)/ansidecl.h if [ x"$(PICFLAG)" != x ]; then \ $(COMPILE.c) $(PICFLAG) $(srcdir)/memmove.c -o pic/$@; \ diff --git a/binutils-2.19/libiberty/configure b/binutils-2.19/libiberty/configure index 50e9ba3..ddf1f5b 100755 --- a/binutils-2.19/libiberty/configure +++ b/binutils-2.19/libiberty/configure @@ -5055,6 +5055,7 @@ funcs="$funcs insque" funcs="$funcs memchr" funcs="$funcs memcmp" funcs="$funcs memcpy" +funcs="$funcs memmem" funcs="$funcs memmove" funcs="$funcs mempcpy" funcs="$funcs memset" @@ -5167,9 +5168,10 @@ if test "x" = "y"; then + for ac_func in asprintf atexit basename bcmp bcopy bsearch bzero calloc clock \ getcwd getpagesize gettimeofday index insque mkstemps memchr memcmp memcpy \ - memmove mempcpy memset putenv random rename rindex sigsetmask \ + memmem memmove mempcpy memset putenv random rename rindex sigsetmask \ strcasecmp setenv stpcpy stpncpy strchr strdup strncasecmp strndup strrchr strstr \ strtod strtol strtoul strverscmp tmpnam vasprintf vfprintf vprintf \ vsprintf waitpid getrusage on_exit psignal strerror strsignal \ diff --git a/binutils-2.19/libiberty/configure.ac b/binutils-2.19/libiberty/configure.ac index 419351b..238bf76 100644 --- a/binutils-2.19/libiberty/configure.ac +++ b/binutils-2.19/libiberty/configure.ac @@ -316,6 +316,7 @@ funcs="$funcs insque" funcs="$funcs memchr" funcs="$funcs memcmp" funcs="$funcs memcpy" +funcs="$funcs memmem" funcs="$funcs memmove" funcs="$funcs mempcpy" funcs="$funcs memset" @@ -361,7 +362,7 @@ checkfuncs="$checkfuncs getsysinfo table sysctl wait3 wait4 __fsetlocking" if test "x" = "y"; then AC_CHECK_FUNCS(asprintf atexit basename bcmp bcopy bsearch bzero calloc clock \ getcwd getpagesize gettimeofday index insque mkstemps memchr memcmp memcpy \ - memmove mempcpy memset putenv random rename rindex sigsetmask \ + memmem memmove mempcpy memset putenv random rename rindex sigsetmask \ strcasecmp setenv stpcpy stpncpy strchr strdup strncasecmp strndup strrchr strstr \ strtod strtol strtoul strverscmp tmpnam vasprintf vfprintf vprintf \ vsprintf waitpid getrusage on_exit psignal strerror strsignal \ diff --git a/binutils-2.19/libiberty/crc32.c b/binutils-2.19/libiberty/crc32.c new file mode 100644 index 0000000..c12916b --- /dev/null +++ b/binutils-2.19/libiberty/crc32.c @@ -0,0 +1,180 @@ +/* crc32.c + Copyright (C) 2009 Free Software Foundation, Inc. + + This file is part of the libiberty library. + + This file 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 of the License, or + (at your option) any later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file into combinations with other programs, + and to distribute those combinations without any restriction coming + from the use of this file. (The General Public License restrictions + do apply in other respects; for example, they cover modification of + the file, and distribution when not linked into a combined + executable.) + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "libiberty.h" + +/* This table was generated by the following program. This matches + what gdb does. + + #include <stdio.h> + + int + main () + { + int i, j; + unsigned int c; + int table[256]; + + for (i = 0; i < 256; i++) + { + for (c = i << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); + table[i] = c; + } + + printf ("static const unsigned int crc32_table[] =\n{\n"); + for (i = 0; i < 256; i += 4) + { + printf (" 0x%08x, 0x%08x, 0x%08x, 0x%08x", + table[i + 0], table[i + 1], table[i + 2], table[i + 3]); + if (i + 4 < 256) + putchar (','); + putchar ('\n'); + } + printf ("};\n"); + return 0; + } + + For more information on CRC, see, e.g., + http://www.ross.net/crc/download/crc_v3.txt. */ + +static const unsigned int crc32_table[] = +{ + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +/* + +@deftypefn Extension unsigned int crc32 (const unsigned char *@var{buf}, int @var{len}, unsigned int @var{init}) + +Compute the 32-bit CRC of @var{buf} which has length @var{len}. The +starting value is @var{init}; this may be used to compute the CRC of +data split across multiple buffers by passing the return value of each +call as the @var{init} parameter of the next. + +This is intended to match the CRC used by the @command{gdb} remote +protocol for the @samp{qCRC} command. In order to get the same +results as gdb for a block of data, you must pass the first CRC +parameter as @code{0xffffffff}. + +This CRC can be specified as: + + Width : 32 + Poly : 0x04c11db7 + Init : parameter, typically 0xffffffff + RefIn : false + RefOut : false + XorOut : 0 + +This differs from the "standard" CRC-32 algorithm in that the values +are not reflected, and there is no final XOR value. These differences +make it easy to compose the values of multiple blocks. + +@end deftypefn + +*/ + +unsigned int +xcrc32 (const unsigned char *buf, int len, unsigned int init) +{ + unsigned int crc = init; + while (len--) + { + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255]; + buf++; + } + return crc; +} diff --git a/binutils-2.19/libiberty/functions.texi b/binutils-2.19/libiberty/functions.texi index 34566d8..1ff0155 100644 --- a/binutils-2.19/libiberty/functions.texi +++ b/binutils-2.19/libiberty/functions.texi @@ -185,6 +185,34 @@ pointer encountered. Pointers to empty strings are ignored. @end deftypefn +@c crc32.c:141 +@deftypefn Extension unsigned int crc32 (const unsigned char *@var{buf}, int @var{len}, unsigned int @var{init}) + +Compute the 32-bit CRC of @var{buf} which has length @var{len}. The +starting value is @var{init}; this may be used to compute the CRC of +data split across multiple buffers by passing the return value of each +call as the @var{init} parameter of the next. + +This is intended to match the CRC used by the @command{gdb} remote +protocol for the @samp{qCRC} command. In order to get the same +results as gdb for a block of data, you must pass the first CRC +parameter as @code{0xffffffff}. + +This CRC can be specified as: + + Width : 32 + Poly : 0x04c11db7 + Init : parameter, typically 0xffffffff + RefIn : false + RefOut : false + XorOut : 0 + +This differs from the "standard" CRC-32 algorithm in that the values +are not reflected, and there is no final XOR value. These differences +make it easy to compose the values of multiple blocks. + +@end deftypefn + @c argv.c:52 @deftypefn Extension char** dupargv (char **@var{vector}) @@ -643,6 +671,15 @@ Copies @var{length} bytes from memory region @var{in} to region @end deftypefn +@c memmem.c:20 +@deftypefn Supplemental void* memmem (const void *@var{haystack}, size_t @var{haystack_len} const void *@var{needle}, size_t @var{needle_len}) + +Returns a pointer to the first occurrence of @var{needle} (length +@var{needle_len}) in @var{haystack} (length @var{haystack_len}). +Returns @code{NULL} if not found. + +@end deftypefn + @c memmove.c:6 @deftypefn Supplemental void* memmove (void *@var{from}, const void *@var{to}, size_t @var{count}) diff --git a/binutils-2.19/libiberty/memmem.c b/binutils-2.19/libiberty/memmem.c new file mode 100644 index 0000000..5d75599 --- /dev/null +++ b/binutils-2.19/libiberty/memmem.c @@ -0,0 +1,70 @@ +/* Copyright (C) 1991,92,93,94,96,97,98,2000,2004,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* + +@deftypefn Supplemental void* memmem (const void *@var{haystack}, size_t @var{haystack_len} const void *@var{needle}, size_t @var{needle_len}) + +Returns a pointer to the first occurrence of @var{needle} (length +@var{needle_len}) in @var{haystack} (length @var{haystack_len}). +Returns @code{NULL} if not found. + +@end deftypefn + +*/ + +#ifndef _LIBC +# include <config.h> +#endif + +#include <stddef.h> +#include <string.h> + +#ifndef _LIBC +# define __builtin_expect(expr, val) (expr) +#endif + +#undef memmem + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +void * +memmem (const void *haystack, size_t haystack_len, const void *needle, + size_t needle_len) +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} |