| 1 | /* X86-64 specific support for 64-bit ELF
 | 
|---|
| 2 |    Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 | 
|---|
| 3 |    Contributed by Jan Hubicka <jh@suse.cz>.
 | 
|---|
| 4 | 
 | 
|---|
| 5 |    This file is part of BFD, the Binary File Descriptor library.
 | 
|---|
| 6 | 
 | 
|---|
| 7 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 8 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 9 |    the Free Software Foundation; either version 2 of the License, or
 | 
|---|
| 10 |    (at your option) any later version.
 | 
|---|
| 11 | 
 | 
|---|
| 12 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 13 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 14 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 15 |    GNU General Public License for more details.
 | 
|---|
| 16 | 
 | 
|---|
| 17 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 18 |    along with this program; if not, write to the Free Software
 | 
|---|
| 19 |    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include "bfd.h"
 | 
|---|
| 22 | #include "sysdep.h"
 | 
|---|
| 23 | #include "bfdlink.h"
 | 
|---|
| 24 | #include "libbfd.h"
 | 
|---|
| 25 | #include "elf-bfd.h"
 | 
|---|
| 26 | 
 | 
|---|
| 27 | #include "elf/x86-64.h"
 | 
|---|
| 28 | 
 | 
|---|
| 29 | /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
 | 
|---|
| 30 | #define MINUS_ONE (~ (bfd_vma) 0)
 | 
|---|
| 31 | 
 | 
|---|
| 32 | /* The relocation "howto" table.  Order of fields:
 | 
|---|
| 33 |    type, size, bitsize, pc_relative, complain_on_overflow,
 | 
|---|
| 34 |    special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset.  */
 | 
|---|
| 35 | static reloc_howto_type x86_64_elf_howto_table[] =
 | 
|---|
| 36 | {
 | 
|---|
| 37 |   HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
 | 
|---|
| 38 |         bfd_elf_generic_reloc, "R_X86_64_NONE", FALSE, 0x00000000, 0x00000000,
 | 
|---|
| 39 |         FALSE),
 | 
|---|
| 40 |   HOWTO(R_X86_64_64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 41 |         bfd_elf_generic_reloc, "R_X86_64_64", FALSE, MINUS_ONE, MINUS_ONE,
 | 
|---|
| 42 |         FALSE),
 | 
|---|
| 43 |   HOWTO(R_X86_64_PC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 44 |         bfd_elf_generic_reloc, "R_X86_64_PC32", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 45 |         TRUE),
 | 
|---|
| 46 |   HOWTO(R_X86_64_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_signed,
 | 
|---|
| 47 |         bfd_elf_generic_reloc, "R_X86_64_GOT32", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 48 |         FALSE),
 | 
|---|
| 49 |   HOWTO(R_X86_64_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 50 |         bfd_elf_generic_reloc, "R_X86_64_PLT32", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 51 |         TRUE),
 | 
|---|
| 52 |   HOWTO(R_X86_64_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 53 |         bfd_elf_generic_reloc, "R_X86_64_COPY", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 54 |         FALSE),
 | 
|---|
| 55 |   HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 56 |         bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", FALSE, MINUS_ONE,
 | 
|---|
| 57 |         MINUS_ONE, FALSE),
 | 
|---|
| 58 |   HOWTO(R_X86_64_JUMP_SLOT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 59 |         bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", FALSE, MINUS_ONE,
 | 
|---|
| 60 |         MINUS_ONE, FALSE),
 | 
|---|
| 61 |   HOWTO(R_X86_64_RELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 62 |         bfd_elf_generic_reloc, "R_X86_64_RELATIVE", FALSE, MINUS_ONE,
 | 
|---|
| 63 |         MINUS_ONE, FALSE),
 | 
|---|
| 64 |   HOWTO(R_X86_64_GOTPCREL, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 65 |         bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", FALSE, 0xffffffff,
 | 
|---|
| 66 |         0xffffffff, TRUE),
 | 
|---|
| 67 |   HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
 | 
|---|
| 68 |         bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 69 |         FALSE),
 | 
|---|
| 70 |   HOWTO(R_X86_64_32S, 0, 2, 32, FALSE, 0, complain_overflow_signed,
 | 
|---|
| 71 |         bfd_elf_generic_reloc, "R_X86_64_32S", FALSE, 0xffffffff, 0xffffffff,
 | 
|---|
| 72 |         FALSE),
 | 
|---|
| 73 |   HOWTO(R_X86_64_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 74 |         bfd_elf_generic_reloc, "R_X86_64_16", FALSE, 0xffff, 0xffff, FALSE),
 | 
|---|
| 75 |   HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_bitfield,
 | 
|---|
| 76 |         bfd_elf_generic_reloc, "R_X86_64_PC16", FALSE, 0xffff, 0xffff, TRUE),
 | 
|---|
| 77 |   HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_signed,
 | 
|---|
| 78 |         bfd_elf_generic_reloc, "R_X86_64_8", FALSE, 0xff, 0xff, FALSE),
 | 
|---|
| 79 |   HOWTO(R_X86_64_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 80 |         bfd_elf_generic_reloc, "R_X86_64_PC8", FALSE, 0xff, 0xff, TRUE),
 | 
|---|
| 81 |   HOWTO(R_X86_64_DTPMOD64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 82 |         bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", FALSE, MINUS_ONE,
 | 
|---|
| 83 |         MINUS_ONE, FALSE),
 | 
|---|
| 84 |   HOWTO(R_X86_64_DTPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 85 |         bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", FALSE, MINUS_ONE,
 | 
|---|
| 86 |         MINUS_ONE, FALSE),
 | 
|---|
| 87 |   HOWTO(R_X86_64_TPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 88 |         bfd_elf_generic_reloc, "R_X86_64_TPOFF64", FALSE, MINUS_ONE,
 | 
|---|
| 89 |         MINUS_ONE, FALSE),
 | 
|---|
| 90 |   HOWTO(R_X86_64_TLSGD, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 91 |         bfd_elf_generic_reloc, "R_X86_64_TLSGD", FALSE, 0xffffffff,
 | 
|---|
| 92 |         0xffffffff, TRUE),
 | 
|---|
| 93 |   HOWTO(R_X86_64_TLSLD, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 94 |         bfd_elf_generic_reloc, "R_X86_64_TLSLD", FALSE, 0xffffffff,
 | 
|---|
| 95 |         0xffffffff, TRUE),
 | 
|---|
| 96 |   HOWTO(R_X86_64_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
 | 
|---|
| 97 |         bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", FALSE, 0xffffffff,
 | 
|---|
| 98 |         0xffffffff, FALSE),
 | 
|---|
| 99 |   HOWTO(R_X86_64_GOTTPOFF, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 | 
|---|
| 100 |         bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", FALSE, 0xffffffff,
 | 
|---|
| 101 |         0xffffffff, TRUE),
 | 
|---|
| 102 |   HOWTO(R_X86_64_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed,
 | 
|---|
| 103 |         bfd_elf_generic_reloc, "R_X86_64_TPOFF32", FALSE, 0xffffffff,
 | 
|---|
| 104 |         0xffffffff, FALSE),
 | 
|---|
| 105 | 
 | 
|---|
| 106 | /* GNU extension to record C++ vtable hierarchy.  */
 | 
|---|
| 107 |   HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, FALSE, 0, complain_overflow_dont,
 | 
|---|
| 108 |          NULL, "R_X86_64_GNU_VTINHERIT", FALSE, 0, 0, FALSE),
 | 
|---|
| 109 | 
 | 
|---|
| 110 | /* GNU extension to record C++ vtable member usage.  */
 | 
|---|
| 111 |   HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, FALSE, 0, complain_overflow_dont,
 | 
|---|
| 112 |          _bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", FALSE, 0, 0,
 | 
|---|
| 113 |          FALSE)
 | 
|---|
| 114 | };
 | 
|---|
| 115 | 
 | 
|---|
| 116 | /* Map BFD relocs to the x86_64 elf relocs.  */
 | 
|---|
| 117 | struct elf_reloc_map
 | 
|---|
| 118 | {
 | 
|---|
| 119 |   bfd_reloc_code_real_type bfd_reloc_val;
 | 
|---|
| 120 |   unsigned char elf_reloc_val;
 | 
|---|
| 121 | };
 | 
|---|
| 122 | 
 | 
|---|
| 123 | static const struct elf_reloc_map x86_64_reloc_map[] =
 | 
|---|
| 124 | {
 | 
|---|
| 125 |   { BFD_RELOC_NONE,             R_X86_64_NONE, },
 | 
|---|
| 126 |   { BFD_RELOC_64,               R_X86_64_64,   },
 | 
|---|
| 127 |   { BFD_RELOC_32_PCREL,         R_X86_64_PC32, },
 | 
|---|
| 128 |   { BFD_RELOC_X86_64_GOT32,     R_X86_64_GOT32,},
 | 
|---|
| 129 |   { BFD_RELOC_X86_64_PLT32,     R_X86_64_PLT32,},
 | 
|---|
| 130 |   { BFD_RELOC_X86_64_COPY,      R_X86_64_COPY, },
 | 
|---|
| 131 |   { BFD_RELOC_X86_64_GLOB_DAT,  R_X86_64_GLOB_DAT, },
 | 
|---|
| 132 |   { BFD_RELOC_X86_64_JUMP_SLOT, R_X86_64_JUMP_SLOT, },
 | 
|---|
| 133 |   { BFD_RELOC_X86_64_RELATIVE,  R_X86_64_RELATIVE, },
 | 
|---|
| 134 |   { BFD_RELOC_X86_64_GOTPCREL,  R_X86_64_GOTPCREL, },
 | 
|---|
| 135 |   { BFD_RELOC_32,               R_X86_64_32, },
 | 
|---|
| 136 |   { BFD_RELOC_X86_64_32S,       R_X86_64_32S, },
 | 
|---|
| 137 |   { BFD_RELOC_16,               R_X86_64_16, },
 | 
|---|
| 138 |   { BFD_RELOC_16_PCREL,         R_X86_64_PC16, },
 | 
|---|
| 139 |   { BFD_RELOC_8,                R_X86_64_8, },
 | 
|---|
| 140 |   { BFD_RELOC_8_PCREL,          R_X86_64_PC8, },
 | 
|---|
| 141 |   { BFD_RELOC_X86_64_DTPMOD64,  R_X86_64_DTPMOD64, },
 | 
|---|
| 142 |   { BFD_RELOC_X86_64_DTPOFF64,  R_X86_64_DTPOFF64, },
 | 
|---|
| 143 |   { BFD_RELOC_X86_64_TPOFF64,   R_X86_64_TPOFF64, },
 | 
|---|
| 144 |   { BFD_RELOC_X86_64_TLSGD,     R_X86_64_TLSGD, },
 | 
|---|
| 145 |   { BFD_RELOC_X86_64_TLSLD,     R_X86_64_TLSLD, },
 | 
|---|
| 146 |   { BFD_RELOC_X86_64_DTPOFF32,  R_X86_64_DTPOFF32, },
 | 
|---|
| 147 |   { BFD_RELOC_X86_64_GOTTPOFF,  R_X86_64_GOTTPOFF, },
 | 
|---|
| 148 |   { BFD_RELOC_X86_64_TPOFF32,   R_X86_64_TPOFF32, },
 | 
|---|
| 149 |   { BFD_RELOC_VTABLE_INHERIT,   R_X86_64_GNU_VTINHERIT, },
 | 
|---|
| 150 |   { BFD_RELOC_VTABLE_ENTRY,     R_X86_64_GNU_VTENTRY, },
 | 
|---|
| 151 | };
 | 
|---|
| 152 | 
 | 
|---|
| 153 | static reloc_howto_type *elf64_x86_64_reloc_type_lookup
 | 
|---|
| 154 |   PARAMS ((bfd *, bfd_reloc_code_real_type));
 | 
|---|
| 155 | static void elf64_x86_64_info_to_howto
 | 
|---|
| 156 |   PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
 | 
|---|
| 157 | static bfd_boolean elf64_x86_64_grok_prstatus
 | 
|---|
| 158 |   PARAMS ((bfd *, Elf_Internal_Note *));
 | 
|---|
| 159 | static bfd_boolean elf64_x86_64_grok_psinfo
 | 
|---|
| 160 |   PARAMS ((bfd *, Elf_Internal_Note *));
 | 
|---|
| 161 | static struct bfd_link_hash_table *elf64_x86_64_link_hash_table_create
 | 
|---|
| 162 |   PARAMS ((bfd *));
 | 
|---|
| 163 | static int elf64_x86_64_tls_transition
 | 
|---|
| 164 |   PARAMS ((struct bfd_link_info *, int, int));
 | 
|---|
| 165 | static bfd_boolean elf64_x86_64_mkobject
 | 
|---|
| 166 |   PARAMS((bfd *));
 | 
|---|
| 167 | static bfd_boolean elf64_x86_64_elf_object_p PARAMS ((bfd *abfd));
 | 
|---|
| 168 | static bfd_boolean create_got_section
 | 
|---|
| 169 |   PARAMS((bfd *, struct bfd_link_info *));
 | 
|---|
| 170 | static bfd_boolean elf64_x86_64_create_dynamic_sections
 | 
|---|
| 171 |   PARAMS((bfd *, struct bfd_link_info *));
 | 
|---|
| 172 | static void elf64_x86_64_copy_indirect_symbol
 | 
|---|
| 173 |   PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
 | 
|---|
| 174 |            struct elf_link_hash_entry *));
 | 
|---|
| 175 | static bfd_boolean elf64_x86_64_check_relocs
 | 
|---|
| 176 |   PARAMS ((bfd *, struct bfd_link_info *, asection *sec,
 | 
|---|
| 177 |            const Elf_Internal_Rela *));
 | 
|---|
| 178 | static asection *elf64_x86_64_gc_mark_hook
 | 
|---|
| 179 |   PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
 | 
|---|
| 180 |            struct elf_link_hash_entry *, Elf_Internal_Sym *));
 | 
|---|
| 181 | 
 | 
|---|
| 182 | static bfd_boolean elf64_x86_64_gc_sweep_hook
 | 
|---|
| 183 |   PARAMS ((bfd *, struct bfd_link_info *, asection *,
 | 
|---|
| 184 |            const Elf_Internal_Rela *));
 | 
|---|
| 185 | 
 | 
|---|
| 186 | static struct bfd_hash_entry *link_hash_newfunc
 | 
|---|
| 187 |   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 | 
|---|
| 188 | static bfd_boolean elf64_x86_64_adjust_dynamic_symbol
 | 
|---|
| 189 |   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
 | 
|---|
| 190 | 
 | 
|---|
| 191 | static bfd_boolean allocate_dynrelocs
 | 
|---|
| 192 |   PARAMS ((struct elf_link_hash_entry *, PTR));
 | 
|---|
| 193 | static bfd_boolean readonly_dynrelocs
 | 
|---|
| 194 |   PARAMS ((struct elf_link_hash_entry *, PTR));
 | 
|---|
| 195 | static bfd_boolean elf64_x86_64_size_dynamic_sections
 | 
|---|
| 196 |   PARAMS ((bfd *, struct bfd_link_info *));
 | 
|---|
| 197 | static bfd_vma dtpoff_base
 | 
|---|
| 198 |   PARAMS ((struct bfd_link_info *));
 | 
|---|
| 199 | static bfd_vma tpoff
 | 
|---|
| 200 |   PARAMS ((struct bfd_link_info *, bfd_vma));
 | 
|---|
| 201 | static bfd_boolean elf64_x86_64_relocate_section
 | 
|---|
| 202 |   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
 | 
|---|
| 203 |          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
 | 
|---|
| 204 | static bfd_boolean elf64_x86_64_finish_dynamic_symbol
 | 
|---|
| 205 |   PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
 | 
|---|
| 206 |            Elf_Internal_Sym *sym));
 | 
|---|
| 207 | static bfd_boolean elf64_x86_64_finish_dynamic_sections
 | 
|---|
| 208 |   PARAMS ((bfd *, struct bfd_link_info *));
 | 
|---|
| 209 | static enum elf_reloc_type_class elf64_x86_64_reloc_type_class
 | 
|---|
| 210 |   PARAMS ((const Elf_Internal_Rela *));
 | 
|---|
| 211 | 
 | 
|---|
| 212 | /* Given a BFD reloc type, return a HOWTO structure.  */
 | 
|---|
| 213 | static reloc_howto_type *
 | 
|---|
| 214 | elf64_x86_64_reloc_type_lookup (abfd, code)
 | 
|---|
| 215 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 216 |      bfd_reloc_code_real_type code;
 | 
|---|
| 217 | {
 | 
|---|
| 218 |   unsigned int i;
 | 
|---|
| 219 |   for (i = 0; i < sizeof (x86_64_reloc_map) / sizeof (struct elf_reloc_map);
 | 
|---|
| 220 |        i++)
 | 
|---|
| 221 |     {
 | 
|---|
| 222 |       if (x86_64_reloc_map[i].bfd_reloc_val == code)
 | 
|---|
| 223 |         return &x86_64_elf_howto_table[i];
 | 
|---|
| 224 |     }
 | 
|---|
| 225 |   return 0;
 | 
|---|
| 226 | }
 | 
|---|
| 227 | 
 | 
|---|
| 228 | /* Given an x86_64 ELF reloc type, fill in an arelent structure.  */
 | 
|---|
| 229 | 
 | 
|---|
| 230 | static void
 | 
|---|
| 231 | elf64_x86_64_info_to_howto (abfd, cache_ptr, dst)
 | 
|---|
| 232 |      bfd *abfd ATTRIBUTE_UNUSED;
 | 
|---|
| 233 |      arelent *cache_ptr;
 | 
|---|
| 234 |      Elf_Internal_Rela *dst;
 | 
|---|
| 235 | {
 | 
|---|
| 236 |   unsigned r_type, i;
 | 
|---|
| 237 | 
 | 
|---|
| 238 |   r_type = ELF64_R_TYPE (dst->r_info);
 | 
|---|
| 239 |   if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT)
 | 
|---|
| 240 |     {
 | 
|---|
| 241 |       BFD_ASSERT (r_type <= (unsigned int) R_X86_64_TPOFF32);
 | 
|---|
| 242 |       i = r_type;
 | 
|---|
| 243 |     }
 | 
|---|
| 244 |   else
 | 
|---|
| 245 |     {
 | 
|---|
| 246 |       BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);
 | 
|---|
| 247 |       i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_TPOFF32 - 1);
 | 
|---|
| 248 |     }
 | 
|---|
| 249 |   cache_ptr->howto = &x86_64_elf_howto_table[i];
 | 
|---|
| 250 |   BFD_ASSERT (r_type == cache_ptr->howto->type);
 | 
|---|
| 251 | }
 | 
|---|
| 252 |  | 
|---|
| 253 | 
 | 
|---|
| 254 | /* Support for core dump NOTE sections.  */
 | 
|---|
| 255 | static bfd_boolean
 | 
|---|
| 256 | elf64_x86_64_grok_prstatus (abfd, note)
 | 
|---|
| 257 |      bfd *abfd;
 | 
|---|
| 258 |      Elf_Internal_Note *note;
 | 
|---|
| 259 | {
 | 
|---|
| 260 |   int offset;
 | 
|---|
| 261 |   size_t raw_size;
 | 
|---|
| 262 | 
 | 
|---|
| 263 |   switch (note->descsz)
 | 
|---|
| 264 |     {
 | 
|---|
| 265 |       default:
 | 
|---|
| 266 |         return FALSE;
 | 
|---|
| 267 | 
 | 
|---|
| 268 |       case 336:         /* sizeof(istruct elf_prstatus) on Linux/x86_64 */
 | 
|---|
| 269 |         /* pr_cursig */
 | 
|---|
| 270 |         elf_tdata (abfd)->core_signal
 | 
|---|
| 271 |           = bfd_get_16 (abfd, note->descdata + 12);
 | 
|---|
| 272 | 
 | 
|---|
| 273 |         /* pr_pid */
 | 
|---|
| 274 |         elf_tdata (abfd)->core_pid
 | 
|---|
| 275 |           = bfd_get_32 (abfd, note->descdata + 32);
 | 
|---|
| 276 | 
 | 
|---|
| 277 |         /* pr_reg */
 | 
|---|
| 278 |         offset = 112;
 | 
|---|
| 279 |         raw_size = 216;
 | 
|---|
| 280 | 
 | 
|---|
| 281 |         break;
 | 
|---|
| 282 |     }
 | 
|---|
| 283 | 
 | 
|---|
| 284 |   /* Make a ".reg/999" section.  */
 | 
|---|
| 285 |   return _bfd_elfcore_make_pseudosection (abfd, ".reg",
 | 
|---|
| 286 |                                           raw_size, note->descpos + offset);
 | 
|---|
| 287 | }
 | 
|---|
| 288 | 
 | 
|---|
| 289 | static bfd_boolean
 | 
|---|
| 290 | elf64_x86_64_grok_psinfo (abfd, note)
 | 
|---|
| 291 |      bfd *abfd;
 | 
|---|
| 292 |      Elf_Internal_Note *note;
 | 
|---|
| 293 | {
 | 
|---|
| 294 |   switch (note->descsz)
 | 
|---|
| 295 |     {
 | 
|---|
| 296 |       default:
 | 
|---|
| 297 |         return FALSE;
 | 
|---|
| 298 | 
 | 
|---|
| 299 |       case 136:         /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */
 | 
|---|
| 300 |         elf_tdata (abfd)->core_program
 | 
|---|
| 301 |          = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
 | 
|---|
| 302 |         elf_tdata (abfd)->core_command
 | 
|---|
| 303 |          = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
 | 
|---|
| 304 |     }
 | 
|---|
| 305 | 
 | 
|---|
| 306 |   /* Note that for some reason, a spurious space is tacked
 | 
|---|
| 307 |      onto the end of the args in some (at least one anyway)
 | 
|---|
| 308 |      implementations, so strip it off if it exists.  */
 | 
|---|
| 309 | 
 | 
|---|
| 310 |   {
 | 
|---|
| 311 |     char *command = elf_tdata (abfd)->core_command;
 | 
|---|
| 312 |     int n = strlen (command);
 | 
|---|
| 313 | 
 | 
|---|
| 314 |     if (0 < n && command[n - 1] == ' ')
 | 
|---|
| 315 |       command[n - 1] = '\0';
 | 
|---|
| 316 |   }
 | 
|---|
| 317 | 
 | 
|---|
| 318 |   return TRUE;
 | 
|---|
| 319 | }
 | 
|---|
| 320 |  | 
|---|
| 321 | 
 | 
|---|
| 322 | /* Functions for the x86-64 ELF linker.  */
 | 
|---|
| 323 | 
 | 
|---|
| 324 | /* The name of the dynamic interpreter.  This is put in the .interp
 | 
|---|
| 325 |    section.  */
 | 
|---|
| 326 | 
 | 
|---|
| 327 | #define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
 | 
|---|
| 328 | 
 | 
|---|
| 329 | /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
 | 
|---|
| 330 |    copying dynamic variables from a shared lib into an app's dynbss
 | 
|---|
| 331 |    section, and instead use a dynamic relocation to point into the
 | 
|---|
| 332 |    shared lib.  */
 | 
|---|
| 333 | #define ELIMINATE_COPY_RELOCS 1
 | 
|---|
| 334 | 
 | 
|---|
| 335 | /* The size in bytes of an entry in the global offset table.  */
 | 
|---|
| 336 | 
 | 
|---|
| 337 | #define GOT_ENTRY_SIZE 8
 | 
|---|
| 338 | 
 | 
|---|
| 339 | /* The size in bytes of an entry in the procedure linkage table.  */
 | 
|---|
| 340 | 
 | 
|---|
| 341 | #define PLT_ENTRY_SIZE 16
 | 
|---|
| 342 | 
 | 
|---|
| 343 | /* The first entry in a procedure linkage table looks like this.  See the
 | 
|---|
| 344 |    SVR4 ABI i386 supplement and the x86-64 ABI to see how this works.  */
 | 
|---|
| 345 | 
 | 
|---|
| 346 | static const bfd_byte elf64_x86_64_plt0_entry[PLT_ENTRY_SIZE] =
 | 
|---|
| 347 | {
 | 
|---|
| 348 |   0xff, 0x35, 8, 0, 0, 0,       /* pushq GOT+8(%rip)  */
 | 
|---|
| 349 |   0xff, 0x25, 16, 0, 0, 0,      /* jmpq *GOT+16(%rip) */
 | 
|---|
| 350 |   0x90, 0x90, 0x90, 0x90        /* pad out to 16 bytes with nops.  */
 | 
|---|
| 351 | };
 | 
|---|
| 352 | 
 | 
|---|
| 353 | /* Subsequent entries in a procedure linkage table look like this.  */
 | 
|---|
| 354 | 
 | 
|---|
| 355 | static const bfd_byte elf64_x86_64_plt_entry[PLT_ENTRY_SIZE] =
 | 
|---|
| 356 | {
 | 
|---|
| 357 |   0xff, 0x25,   /* jmpq *name@GOTPC(%rip) */
 | 
|---|
| 358 |   0, 0, 0, 0,   /* replaced with offset to this symbol in .got.  */
 | 
|---|
| 359 |   0x68,         /* pushq immediate */
 | 
|---|
| 360 |   0, 0, 0, 0,   /* replaced with index into relocation table.  */
 | 
|---|
| 361 |   0xe9,         /* jmp relative */
 | 
|---|
| 362 |   0, 0, 0, 0    /* replaced with offset to start of .plt0.  */
 | 
|---|
| 363 | };
 | 
|---|
| 364 | 
 | 
|---|
| 365 | /* The x86-64 linker needs to keep track of the number of relocs that
 | 
|---|
| 366 |    it decides to copy as dynamic relocs in check_relocs for each symbol.
 | 
|---|
| 367 |    This is so that it can later discard them if they are found to be
 | 
|---|
| 368 |    unnecessary.  We store the information in a field extending the
 | 
|---|
| 369 |    regular ELF linker hash table.  */
 | 
|---|
| 370 | 
 | 
|---|
| 371 | struct elf64_x86_64_dyn_relocs
 | 
|---|
| 372 | {
 | 
|---|
| 373 |   /* Next section.  */
 | 
|---|
| 374 |   struct elf64_x86_64_dyn_relocs *next;
 | 
|---|
| 375 | 
 | 
|---|
| 376 |   /* The input section of the reloc.  */
 | 
|---|
| 377 |   asection *sec;
 | 
|---|
| 378 | 
 | 
|---|
| 379 |   /* Total number of relocs copied for the input section.  */
 | 
|---|
| 380 |   bfd_size_type count;
 | 
|---|
| 381 | 
 | 
|---|
| 382 |   /* Number of pc-relative relocs copied for the input section.  */
 | 
|---|
| 383 |   bfd_size_type pc_count;
 | 
|---|
| 384 | };
 | 
|---|
| 385 | 
 | 
|---|
| 386 | /* x86-64 ELF linker hash entry.  */
 | 
|---|
| 387 | 
 | 
|---|
| 388 | struct elf64_x86_64_link_hash_entry
 | 
|---|
| 389 | {
 | 
|---|
| 390 |   struct elf_link_hash_entry elf;
 | 
|---|
| 391 | 
 | 
|---|
| 392 |   /* Track dynamic relocs copied for this symbol.  */
 | 
|---|
| 393 |   struct elf64_x86_64_dyn_relocs *dyn_relocs;
 | 
|---|
| 394 | 
 | 
|---|
| 395 | #define GOT_UNKNOWN     0
 | 
|---|
| 396 | #define GOT_NORMAL      1
 | 
|---|
| 397 | #define GOT_TLS_GD      2
 | 
|---|
| 398 | #define GOT_TLS_IE      3
 | 
|---|
| 399 |   unsigned char tls_type;
 | 
|---|
| 400 | };
 | 
|---|
| 401 | 
 | 
|---|
| 402 | #define elf64_x86_64_hash_entry(ent) \
 | 
|---|
| 403 |   ((struct elf64_x86_64_link_hash_entry *)(ent))
 | 
|---|
| 404 | 
 | 
|---|
| 405 | struct elf64_x86_64_obj_tdata
 | 
|---|
| 406 | {
 | 
|---|
| 407 |   struct elf_obj_tdata root;
 | 
|---|
| 408 | 
 | 
|---|
| 409 |   /* tls_type for each local got entry.  */
 | 
|---|
| 410 |   char *local_got_tls_type;
 | 
|---|
| 411 | };
 | 
|---|
| 412 | 
 | 
|---|
| 413 | #define elf64_x86_64_tdata(abfd) \
 | 
|---|
| 414 |   ((struct elf64_x86_64_obj_tdata *) (abfd)->tdata.any)
 | 
|---|
| 415 | 
 | 
|---|
| 416 | #define elf64_x86_64_local_got_tls_type(abfd) \
 | 
|---|
| 417 |   (elf64_x86_64_tdata (abfd)->local_got_tls_type)
 | 
|---|
| 418 | 
 | 
|---|
| 419 | 
 | 
|---|
| 420 | /* x86-64 ELF linker hash table.  */
 | 
|---|
| 421 | 
 | 
|---|
| 422 | struct elf64_x86_64_link_hash_table
 | 
|---|
| 423 | {
 | 
|---|
| 424 |   struct elf_link_hash_table elf;
 | 
|---|
| 425 | 
 | 
|---|
| 426 |   /* Short-cuts to get to dynamic linker sections.  */
 | 
|---|
| 427 |   asection *sgot;
 | 
|---|
| 428 |   asection *sgotplt;
 | 
|---|
| 429 |   asection *srelgot;
 | 
|---|
| 430 |   asection *splt;
 | 
|---|
| 431 |   asection *srelplt;
 | 
|---|
| 432 |   asection *sdynbss;
 | 
|---|
| 433 |   asection *srelbss;
 | 
|---|
| 434 | 
 | 
|---|
| 435 |   union {
 | 
|---|
| 436 |     bfd_signed_vma refcount;
 | 
|---|
| 437 |     bfd_vma offset;
 | 
|---|
| 438 |   } tls_ld_got;
 | 
|---|
| 439 | 
 | 
|---|
| 440 |   /* Small local sym to section mapping cache.  */
 | 
|---|
| 441 |   struct sym_sec_cache sym_sec;
 | 
|---|
| 442 | };
 | 
|---|
| 443 | 
 | 
|---|
| 444 | /* Get the x86-64 ELF linker hash table from a link_info structure.  */
 | 
|---|
| 445 | 
 | 
|---|
| 446 | #define elf64_x86_64_hash_table(p) \
 | 
|---|
| 447 |   ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
 | 
|---|
| 448 | 
 | 
|---|
| 449 | /* Create an entry in an x86-64 ELF linker hash table.  */
 | 
|---|
| 450 | 
 | 
|---|
| 451 | static struct bfd_hash_entry *
 | 
|---|
| 452 | link_hash_newfunc (entry, table, string)
 | 
|---|
| 453 |      struct bfd_hash_entry *entry;
 | 
|---|
| 454 |      struct bfd_hash_table *table;
 | 
|---|
| 455 |      const char *string;
 | 
|---|
| 456 | {
 | 
|---|
| 457 |   /* Allocate the structure if it has not already been allocated by a
 | 
|---|
| 458 |      subclass.  */
 | 
|---|
| 459 |   if (entry == NULL)
 | 
|---|
| 460 |     {
 | 
|---|
| 461 |       entry = bfd_hash_allocate (table,
 | 
|---|
| 462 |                                  sizeof (struct elf64_x86_64_link_hash_entry));
 | 
|---|
| 463 |       if (entry == NULL)
 | 
|---|
| 464 |         return entry;
 | 
|---|
| 465 |     }
 | 
|---|
| 466 | 
 | 
|---|
| 467 |   /* Call the allocation method of the superclass.  */
 | 
|---|
| 468 |   entry = _bfd_elf_link_hash_newfunc (entry, table, string);
 | 
|---|
| 469 |   if (entry != NULL)
 | 
|---|
| 470 |     {
 | 
|---|
| 471 |       struct elf64_x86_64_link_hash_entry *eh;
 | 
|---|
| 472 | 
 | 
|---|
| 473 |       eh = (struct elf64_x86_64_link_hash_entry *) entry;
 | 
|---|
| 474 |       eh->dyn_relocs = NULL;
 | 
|---|
| 475 |       eh->tls_type = GOT_UNKNOWN;
 | 
|---|
| 476 |     }
 | 
|---|
| 477 | 
 | 
|---|
| 478 |   return entry;
 | 
|---|
| 479 | }
 | 
|---|
| 480 | 
 | 
|---|
| 481 | /* Create an X86-64 ELF linker hash table.  */
 | 
|---|
| 482 | 
 | 
|---|
| 483 | static struct bfd_link_hash_table *
 | 
|---|
| 484 | elf64_x86_64_link_hash_table_create (abfd)
 | 
|---|
| 485 |      bfd *abfd;
 | 
|---|
| 486 | {
 | 
|---|
| 487 |   struct elf64_x86_64_link_hash_table *ret;
 | 
|---|
| 488 |   bfd_size_type amt = sizeof (struct elf64_x86_64_link_hash_table);
 | 
|---|
| 489 | 
 | 
|---|
| 490 |   ret = (struct elf64_x86_64_link_hash_table *) bfd_malloc (amt);
 | 
|---|
| 491 |   if (ret == NULL)
 | 
|---|
| 492 |     return NULL;
 | 
|---|
| 493 | 
 | 
|---|
| 494 |   if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
 | 
|---|
| 495 |     {
 | 
|---|
| 496 |       free (ret);
 | 
|---|
| 497 |       return NULL;
 | 
|---|
| 498 |     }
 | 
|---|
| 499 | 
 | 
|---|
| 500 |   ret->sgot = NULL;
 | 
|---|
| 501 |   ret->sgotplt = NULL;
 | 
|---|
| 502 |   ret->srelgot = NULL;
 | 
|---|
| 503 |   ret->splt = NULL;
 | 
|---|
| 504 |   ret->srelplt = NULL;
 | 
|---|
| 505 |   ret->sdynbss = NULL;
 | 
|---|
| 506 |   ret->srelbss = NULL;
 | 
|---|
| 507 |   ret->sym_sec.abfd = NULL;
 | 
|---|
| 508 |   ret->tls_ld_got.refcount = 0;
 | 
|---|
| 509 | 
 | 
|---|
| 510 |   return &ret->elf.root;
 | 
|---|
| 511 | }
 | 
|---|
| 512 | 
 | 
|---|
| 513 | /* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
 | 
|---|
| 514 |    shortcuts to them in our hash table.  */
 | 
|---|
| 515 | 
 | 
|---|
| 516 | static bfd_boolean
 | 
|---|
| 517 | create_got_section (dynobj, info)
 | 
|---|
| 518 |      bfd *dynobj;
 | 
|---|
| 519 |      struct bfd_link_info *info;
 | 
|---|
| 520 | {
 | 
|---|
| 521 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 522 | 
 | 
|---|
| 523 |   if (! _bfd_elf_create_got_section (dynobj, info))
 | 
|---|
| 524 |     return FALSE;
 | 
|---|
| 525 | 
 | 
|---|
| 526 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 527 |   htab->sgot = bfd_get_section_by_name (dynobj, ".got");
 | 
|---|
| 528 |   htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
 | 
|---|
| 529 |   if (!htab->sgot || !htab->sgotplt)
 | 
|---|
| 530 |     abort ();
 | 
|---|
| 531 | 
 | 
|---|
| 532 |   htab->srelgot = bfd_make_section (dynobj, ".rela.got");
 | 
|---|
| 533 |   if (htab->srelgot == NULL
 | 
|---|
| 534 |       || ! bfd_set_section_flags (dynobj, htab->srelgot,
 | 
|---|
| 535 |                                   (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
 | 
|---|
| 536 |                                    | SEC_IN_MEMORY | SEC_LINKER_CREATED
 | 
|---|
| 537 |                                    | SEC_READONLY))
 | 
|---|
| 538 |       || ! bfd_set_section_alignment (dynobj, htab->srelgot, 3))
 | 
|---|
| 539 |     return FALSE;
 | 
|---|
| 540 |   return TRUE;
 | 
|---|
| 541 | }
 | 
|---|
| 542 | 
 | 
|---|
| 543 | /* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
 | 
|---|
| 544 |    .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
 | 
|---|
| 545 |    hash table.  */
 | 
|---|
| 546 | 
 | 
|---|
| 547 | static bfd_boolean
 | 
|---|
| 548 | elf64_x86_64_create_dynamic_sections (dynobj, info)
 | 
|---|
| 549 |      bfd *dynobj;
 | 
|---|
| 550 |      struct bfd_link_info *info;
 | 
|---|
| 551 | {
 | 
|---|
| 552 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 553 | 
 | 
|---|
| 554 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 555 |   if (!htab->sgot && !create_got_section (dynobj, info))
 | 
|---|
| 556 |     return FALSE;
 | 
|---|
| 557 | 
 | 
|---|
| 558 |   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
 | 
|---|
| 559 |     return FALSE;
 | 
|---|
| 560 | 
 | 
|---|
| 561 |   htab->splt = bfd_get_section_by_name (dynobj, ".plt");
 | 
|---|
| 562 |   htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
 | 
|---|
| 563 |   htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
 | 
|---|
| 564 |   if (!info->shared)
 | 
|---|
| 565 |     htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
 | 
|---|
| 566 | 
 | 
|---|
| 567 |   if (!htab->splt || !htab->srelplt || !htab->sdynbss
 | 
|---|
| 568 |       || (!info->shared && !htab->srelbss))
 | 
|---|
| 569 |     abort ();
 | 
|---|
| 570 | 
 | 
|---|
| 571 |   return TRUE;
 | 
|---|
| 572 | }
 | 
|---|
| 573 | 
 | 
|---|
| 574 | /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 | 
|---|
| 575 | 
 | 
|---|
| 576 | static void
 | 
|---|
| 577 | elf64_x86_64_copy_indirect_symbol (bed, dir, ind)
 | 
|---|
| 578 |      struct elf_backend_data *bed;
 | 
|---|
| 579 |      struct elf_link_hash_entry *dir, *ind;
 | 
|---|
| 580 | {
 | 
|---|
| 581 |   struct elf64_x86_64_link_hash_entry *edir, *eind;
 | 
|---|
| 582 | 
 | 
|---|
| 583 |   edir = (struct elf64_x86_64_link_hash_entry *) dir;
 | 
|---|
| 584 |   eind = (struct elf64_x86_64_link_hash_entry *) ind;
 | 
|---|
| 585 | 
 | 
|---|
| 586 |   if (eind->dyn_relocs != NULL)
 | 
|---|
| 587 |     {
 | 
|---|
| 588 |       if (edir->dyn_relocs != NULL)
 | 
|---|
| 589 |         {
 | 
|---|
| 590 |           struct elf64_x86_64_dyn_relocs **pp;
 | 
|---|
| 591 |           struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 592 | 
 | 
|---|
| 593 |           if (ind->root.type == bfd_link_hash_indirect)
 | 
|---|
| 594 |             abort ();
 | 
|---|
| 595 | 
 | 
|---|
| 596 |           /* Add reloc counts against the weak sym to the strong sym
 | 
|---|
| 597 |              list.  Merge any entries against the same section.  */
 | 
|---|
| 598 |           for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
 | 
|---|
| 599 |             {
 | 
|---|
| 600 |               struct elf64_x86_64_dyn_relocs *q;
 | 
|---|
| 601 | 
 | 
|---|
| 602 |               for (q = edir->dyn_relocs; q != NULL; q = q->next)
 | 
|---|
| 603 |                 if (q->sec == p->sec)
 | 
|---|
| 604 |                   {
 | 
|---|
| 605 |                     q->pc_count += p->pc_count;
 | 
|---|
| 606 |                     q->count += p->count;
 | 
|---|
| 607 |                     *pp = p->next;
 | 
|---|
| 608 |                     break;
 | 
|---|
| 609 |                   }
 | 
|---|
| 610 |               if (q == NULL)
 | 
|---|
| 611 |                 pp = &p->next;
 | 
|---|
| 612 |             }
 | 
|---|
| 613 |           *pp = edir->dyn_relocs;
 | 
|---|
| 614 |         }
 | 
|---|
| 615 | 
 | 
|---|
| 616 |       edir->dyn_relocs = eind->dyn_relocs;
 | 
|---|
| 617 |       eind->dyn_relocs = NULL;
 | 
|---|
| 618 |     }
 | 
|---|
| 619 | 
 | 
|---|
| 620 |   if (ind->root.type == bfd_link_hash_indirect
 | 
|---|
| 621 |       && dir->got.refcount <= 0)
 | 
|---|
| 622 |     {
 | 
|---|
| 623 |       edir->tls_type = eind->tls_type;
 | 
|---|
| 624 |       eind->tls_type = GOT_UNKNOWN;
 | 
|---|
| 625 |     }
 | 
|---|
| 626 | 
 | 
|---|
| 627 |   if (ELIMINATE_COPY_RELOCS
 | 
|---|
| 628 |       && ind->root.type != bfd_link_hash_indirect
 | 
|---|
| 629 |       && (dir->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
 | 
|---|
| 630 |     /* If called to transfer flags for a weakdef during processing
 | 
|---|
| 631 |        of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF.
 | 
|---|
| 632 |        We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
 | 
|---|
| 633 |     dir->elf_link_hash_flags |=
 | 
|---|
| 634 |       (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC
 | 
|---|
| 635 |                                    | ELF_LINK_HASH_REF_REGULAR
 | 
|---|
| 636 |                                    | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
 | 
|---|
| 637 |   else
 | 
|---|
| 638 |     _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 | 
|---|
| 639 | }
 | 
|---|
| 640 | 
 | 
|---|
| 641 | static bfd_boolean
 | 
|---|
| 642 | elf64_x86_64_mkobject (abfd)
 | 
|---|
| 643 |      bfd *abfd;
 | 
|---|
| 644 | {
 | 
|---|
| 645 |   bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
 | 
|---|
| 646 |   abfd->tdata.any = bfd_zalloc (abfd, amt);
 | 
|---|
| 647 |   if (abfd->tdata.any == NULL)
 | 
|---|
| 648 |     return FALSE;
 | 
|---|
| 649 |   return TRUE;
 | 
|---|
| 650 | }
 | 
|---|
| 651 | 
 | 
|---|
| 652 | static bfd_boolean
 | 
|---|
| 653 | elf64_x86_64_elf_object_p (abfd)
 | 
|---|
| 654 |   bfd *abfd;
 | 
|---|
| 655 | {
 | 
|---|
| 656 |   /* Allocate our special target data.  */
 | 
|---|
| 657 |   struct elf64_x86_64_obj_tdata *new_tdata;
 | 
|---|
| 658 |   bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
 | 
|---|
| 659 |   new_tdata = bfd_zalloc (abfd, amt);
 | 
|---|
| 660 |   if (new_tdata == NULL)
 | 
|---|
| 661 |     return FALSE;
 | 
|---|
| 662 |   new_tdata->root = *abfd->tdata.elf_obj_data;
 | 
|---|
| 663 |   abfd->tdata.any = new_tdata;
 | 
|---|
| 664 |   /* Set the right machine number for an x86-64 elf64 file.  */
 | 
|---|
| 665 |   bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
 | 
|---|
| 666 |   return TRUE;
 | 
|---|
| 667 | }
 | 
|---|
| 668 | 
 | 
|---|
| 669 | static int
 | 
|---|
| 670 | elf64_x86_64_tls_transition (info, r_type, is_local)
 | 
|---|
| 671 |      struct bfd_link_info *info;
 | 
|---|
| 672 |      int r_type;
 | 
|---|
| 673 |      int is_local;
 | 
|---|
| 674 | {
 | 
|---|
| 675 |   if (info->shared)
 | 
|---|
| 676 |     return r_type;
 | 
|---|
| 677 | 
 | 
|---|
| 678 |   switch (r_type)
 | 
|---|
| 679 |     {
 | 
|---|
| 680 |     case R_X86_64_TLSGD:
 | 
|---|
| 681 |     case R_X86_64_GOTTPOFF:
 | 
|---|
| 682 |       if (is_local)
 | 
|---|
| 683 |         return R_X86_64_TPOFF32;
 | 
|---|
| 684 |       return R_X86_64_GOTTPOFF;
 | 
|---|
| 685 |     case R_X86_64_TLSLD:
 | 
|---|
| 686 |       return R_X86_64_TPOFF32;
 | 
|---|
| 687 |     }
 | 
|---|
| 688 | 
 | 
|---|
| 689 |    return r_type;
 | 
|---|
| 690 | }
 | 
|---|
| 691 | 
 | 
|---|
| 692 | /* Look through the relocs for a section during the first phase, and
 | 
|---|
| 693 |    calculate needed space in the global offset table, procedure
 | 
|---|
| 694 |    linkage table, and dynamic reloc sections.  */
 | 
|---|
| 695 | 
 | 
|---|
| 696 | static bfd_boolean
 | 
|---|
| 697 | elf64_x86_64_check_relocs (abfd, info, sec, relocs)
 | 
|---|
| 698 |      bfd *abfd;
 | 
|---|
| 699 |      struct bfd_link_info *info;
 | 
|---|
| 700 |      asection *sec;
 | 
|---|
| 701 |      const Elf_Internal_Rela *relocs;
 | 
|---|
| 702 | {
 | 
|---|
| 703 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 704 |   Elf_Internal_Shdr *symtab_hdr;
 | 
|---|
| 705 |   struct elf_link_hash_entry **sym_hashes;
 | 
|---|
| 706 |   const Elf_Internal_Rela *rel;
 | 
|---|
| 707 |   const Elf_Internal_Rela *rel_end;
 | 
|---|
| 708 |   asection *sreloc;
 | 
|---|
| 709 | 
 | 
|---|
| 710 |   if (info->relocateable)
 | 
|---|
| 711 |     return TRUE;
 | 
|---|
| 712 | 
 | 
|---|
| 713 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 714 |   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 | 
|---|
| 715 |   sym_hashes = elf_sym_hashes (abfd);
 | 
|---|
| 716 | 
 | 
|---|
| 717 |   sreloc = NULL;
 | 
|---|
| 718 | 
 | 
|---|
| 719 |   rel_end = relocs + sec->reloc_count;
 | 
|---|
| 720 |   for (rel = relocs; rel < rel_end; rel++)
 | 
|---|
| 721 |     {
 | 
|---|
| 722 |       unsigned int r_type;
 | 
|---|
| 723 |       unsigned long r_symndx;
 | 
|---|
| 724 |       struct elf_link_hash_entry *h;
 | 
|---|
| 725 | 
 | 
|---|
| 726 |       r_symndx = ELF64_R_SYM (rel->r_info);
 | 
|---|
| 727 |       r_type = ELF64_R_TYPE (rel->r_info);
 | 
|---|
| 728 | 
 | 
|---|
| 729 |       if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
 | 
|---|
| 730 |         {
 | 
|---|
| 731 |           (*_bfd_error_handler) (_("%s: bad symbol index: %d"),
 | 
|---|
| 732 |                                  bfd_archive_filename (abfd),
 | 
|---|
| 733 |                                  r_symndx);
 | 
|---|
| 734 |           return FALSE;
 | 
|---|
| 735 |         }
 | 
|---|
| 736 | 
 | 
|---|
| 737 |       if (r_symndx < symtab_hdr->sh_info)
 | 
|---|
| 738 |         h = NULL;
 | 
|---|
| 739 |       else
 | 
|---|
| 740 |         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 | 
|---|
| 741 | 
 | 
|---|
| 742 |       r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 | 
|---|
| 743 |       switch (r_type)
 | 
|---|
| 744 |         {
 | 
|---|
| 745 |         case R_X86_64_TLSLD:
 | 
|---|
| 746 |           htab->tls_ld_got.refcount += 1;
 | 
|---|
| 747 |           goto create_got;
 | 
|---|
| 748 | 
 | 
|---|
| 749 |         case R_X86_64_TPOFF32:
 | 
|---|
| 750 |           if (info->shared)
 | 
|---|
| 751 |             {
 | 
|---|
| 752 |               (*_bfd_error_handler)
 | 
|---|
| 753 |                 (_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"),
 | 
|---|
| 754 |                  bfd_archive_filename (abfd),
 | 
|---|
| 755 |                  x86_64_elf_howto_table[r_type].name);
 | 
|---|
| 756 |               bfd_set_error (bfd_error_bad_value);
 | 
|---|
| 757 |               return FALSE;
 | 
|---|
| 758 |             }
 | 
|---|
| 759 |           break;
 | 
|---|
| 760 | 
 | 
|---|
| 761 |         case R_X86_64_GOTTPOFF:
 | 
|---|
| 762 |           if (info->shared)
 | 
|---|
| 763 |             info->flags |= DF_STATIC_TLS;
 | 
|---|
| 764 |           /* Fall through */
 | 
|---|
| 765 | 
 | 
|---|
| 766 |         case R_X86_64_GOT32:
 | 
|---|
| 767 |         case R_X86_64_GOTPCREL:
 | 
|---|
| 768 |         case R_X86_64_TLSGD:
 | 
|---|
| 769 |           /* This symbol requires a global offset table entry.  */
 | 
|---|
| 770 |           {
 | 
|---|
| 771 |             int tls_type, old_tls_type;
 | 
|---|
| 772 | 
 | 
|---|
| 773 |             switch (r_type)
 | 
|---|
| 774 |               {
 | 
|---|
| 775 |               default: tls_type = GOT_NORMAL; break;
 | 
|---|
| 776 |               case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
 | 
|---|
| 777 |               case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
 | 
|---|
| 778 |               }
 | 
|---|
| 779 | 
 | 
|---|
| 780 |             if (h != NULL)
 | 
|---|
| 781 |               {
 | 
|---|
| 782 |                 h->got.refcount += 1;
 | 
|---|
| 783 |                 old_tls_type = elf64_x86_64_hash_entry (h)->tls_type;
 | 
|---|
| 784 |               }
 | 
|---|
| 785 |             else
 | 
|---|
| 786 |               {
 | 
|---|
| 787 |                 bfd_signed_vma *local_got_refcounts;
 | 
|---|
| 788 | 
 | 
|---|
| 789 |                 /* This is a global offset table entry for a local symbol.  */
 | 
|---|
| 790 |                 local_got_refcounts = elf_local_got_refcounts (abfd);
 | 
|---|
| 791 |                 if (local_got_refcounts == NULL)
 | 
|---|
| 792 |                   {
 | 
|---|
| 793 |                     bfd_size_type size;
 | 
|---|
| 794 | 
 | 
|---|
| 795 |                     size = symtab_hdr->sh_info;
 | 
|---|
| 796 |                     size *= sizeof (bfd_signed_vma) + sizeof (char);
 | 
|---|
| 797 |                     local_got_refcounts = ((bfd_signed_vma *)
 | 
|---|
| 798 |                                            bfd_zalloc (abfd, size));
 | 
|---|
| 799 |                     if (local_got_refcounts == NULL)
 | 
|---|
| 800 |                       return FALSE;
 | 
|---|
| 801 |                     elf_local_got_refcounts (abfd) = local_got_refcounts;
 | 
|---|
| 802 |                     elf64_x86_64_local_got_tls_type (abfd)
 | 
|---|
| 803 |                       = (char *) (local_got_refcounts + symtab_hdr->sh_info);
 | 
|---|
| 804 |                   }
 | 
|---|
| 805 |                 local_got_refcounts[r_symndx] += 1;
 | 
|---|
| 806 |                 old_tls_type
 | 
|---|
| 807 |                   = elf64_x86_64_local_got_tls_type (abfd) [r_symndx];
 | 
|---|
| 808 |               }
 | 
|---|
| 809 | 
 | 
|---|
| 810 |             /* If a TLS symbol is accessed using IE at least once,
 | 
|---|
| 811 |                there is no point to use dynamic model for it.  */
 | 
|---|
| 812 |             if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
 | 
|---|
| 813 |                 && (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE))
 | 
|---|
| 814 |               {
 | 
|---|
| 815 |                 if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
 | 
|---|
| 816 |                   tls_type = old_tls_type;
 | 
|---|
| 817 |                 else
 | 
|---|
| 818 |                   {
 | 
|---|
| 819 |                     (*_bfd_error_handler)
 | 
|---|
| 820 |                       (_("%s: %s' accessed both as normal and thread local symbol"),
 | 
|---|
| 821 |                        bfd_archive_filename (abfd),
 | 
|---|
| 822 |                        h ? h->root.root.string : "<local>");
 | 
|---|
| 823 |                     return FALSE;
 | 
|---|
| 824 |                   }
 | 
|---|
| 825 |               }
 | 
|---|
| 826 | 
 | 
|---|
| 827 |             if (old_tls_type != tls_type)
 | 
|---|
| 828 |               {
 | 
|---|
| 829 |                 if (h != NULL)
 | 
|---|
| 830 |                   elf64_x86_64_hash_entry (h)->tls_type = tls_type;
 | 
|---|
| 831 |                 else
 | 
|---|
| 832 |                   elf64_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type;
 | 
|---|
| 833 |               }
 | 
|---|
| 834 |           }
 | 
|---|
| 835 |           /* Fall through */
 | 
|---|
| 836 | 
 | 
|---|
| 837 |           //case R_X86_64_GOTPCREL:
 | 
|---|
| 838 |         create_got:
 | 
|---|
| 839 |           if (htab->sgot == NULL)
 | 
|---|
| 840 |             {
 | 
|---|
| 841 |               if (htab->elf.dynobj == NULL)
 | 
|---|
| 842 |                 htab->elf.dynobj = abfd;
 | 
|---|
| 843 |               if (!create_got_section (htab->elf.dynobj, info))
 | 
|---|
| 844 |                 return FALSE;
 | 
|---|
| 845 |             }
 | 
|---|
| 846 |           break;
 | 
|---|
| 847 | 
 | 
|---|
| 848 |         case R_X86_64_PLT32:
 | 
|---|
| 849 |           /* This symbol requires a procedure linkage table entry.  We
 | 
|---|
| 850 |              actually build the entry in adjust_dynamic_symbol,
 | 
|---|
| 851 |              because this might be a case of linking PIC code which is
 | 
|---|
| 852 |              never referenced by a dynamic object, in which case we
 | 
|---|
| 853 |              don't need to generate a procedure linkage table entry
 | 
|---|
| 854 |              after all.  */
 | 
|---|
| 855 | 
 | 
|---|
| 856 |           /* If this is a local symbol, we resolve it directly without
 | 
|---|
| 857 |              creating a procedure linkage table entry.  */
 | 
|---|
| 858 |           if (h == NULL)
 | 
|---|
| 859 |             continue;
 | 
|---|
| 860 | 
 | 
|---|
| 861 |           h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
 | 
|---|
| 862 |           h->plt.refcount += 1;
 | 
|---|
| 863 |           break;
 | 
|---|
| 864 | 
 | 
|---|
| 865 |         case R_X86_64_8:
 | 
|---|
| 866 |         case R_X86_64_16:
 | 
|---|
| 867 |         case R_X86_64_32:
 | 
|---|
| 868 |         case R_X86_64_32S:
 | 
|---|
| 869 |           /* Let's help debug shared library creation.  These relocs
 | 
|---|
| 870 |              cannot be used in shared libs.  Don't error out for
 | 
|---|
| 871 |              sections we don't care about, such as debug sections or
 | 
|---|
| 872 |              non-constant sections.  */
 | 
|---|
| 873 |           if (info->shared
 | 
|---|
| 874 |               && (sec->flags & SEC_ALLOC) != 0
 | 
|---|
| 875 |               && (sec->flags & SEC_READONLY) != 0)
 | 
|---|
| 876 |             {
 | 
|---|
| 877 |               (*_bfd_error_handler)
 | 
|---|
| 878 |                 (_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"),
 | 
|---|
| 879 |                  bfd_archive_filename (abfd),
 | 
|---|
| 880 |                  x86_64_elf_howto_table[r_type].name);
 | 
|---|
| 881 |               bfd_set_error (bfd_error_bad_value);
 | 
|---|
| 882 |               return FALSE;
 | 
|---|
| 883 |             }
 | 
|---|
| 884 |           /* Fall through.  */
 | 
|---|
| 885 | 
 | 
|---|
| 886 |         case R_X86_64_PC8:
 | 
|---|
| 887 |         case R_X86_64_PC16:
 | 
|---|
| 888 |         case R_X86_64_PC32:
 | 
|---|
| 889 |         case R_X86_64_64:
 | 
|---|
| 890 |           if (h != NULL && !info->shared)
 | 
|---|
| 891 |             {
 | 
|---|
| 892 |               /* If this reloc is in a read-only section, we might
 | 
|---|
| 893 |                  need a copy reloc.  We can't check reliably at this
 | 
|---|
| 894 |                  stage whether the section is read-only, as input
 | 
|---|
| 895 |                  sections have not yet been mapped to output sections.
 | 
|---|
| 896 |                  Tentatively set the flag for now, and correct in
 | 
|---|
| 897 |                  adjust_dynamic_symbol.  */
 | 
|---|
| 898 |               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
 | 
|---|
| 899 | 
 | 
|---|
| 900 |               /* We may need a .plt entry if the function this reloc
 | 
|---|
| 901 |                  refers to is in a shared lib.  */
 | 
|---|
| 902 |               h->plt.refcount += 1;
 | 
|---|
| 903 |             }
 | 
|---|
| 904 | 
 | 
|---|
| 905 |           /* If we are creating a shared library, and this is a reloc
 | 
|---|
| 906 |              against a global symbol, or a non PC relative reloc
 | 
|---|
| 907 |              against a local symbol, then we need to copy the reloc
 | 
|---|
| 908 |              into the shared library.  However, if we are linking with
 | 
|---|
| 909 |              -Bsymbolic, we do not need to copy a reloc against a
 | 
|---|
| 910 |              global symbol which is defined in an object we are
 | 
|---|
| 911 |              including in the link (i.e., DEF_REGULAR is set).  At
 | 
|---|
| 912 |              this point we have not seen all the input files, so it is
 | 
|---|
| 913 |              possible that DEF_REGULAR is not set now but will be set
 | 
|---|
| 914 |              later (it is never cleared).  In case of a weak definition,
 | 
|---|
| 915 |              DEF_REGULAR may be cleared later by a strong definition in
 | 
|---|
| 916 |              a shared library.  We account for that possibility below by
 | 
|---|
| 917 |              storing information in the relocs_copied field of the hash
 | 
|---|
| 918 |              table entry.  A similar situation occurs when creating
 | 
|---|
| 919 |              shared libraries and symbol visibility changes render the
 | 
|---|
| 920 |              symbol local.
 | 
|---|
| 921 | 
 | 
|---|
| 922 |              If on the other hand, we are creating an executable, we
 | 
|---|
| 923 |              may need to keep relocations for symbols satisfied by a
 | 
|---|
| 924 |              dynamic library if we manage to avoid copy relocs for the
 | 
|---|
| 925 |              symbol.  */
 | 
|---|
| 926 |           if ((info->shared
 | 
|---|
| 927 |                && (sec->flags & SEC_ALLOC) != 0
 | 
|---|
| 928 |                && (((r_type != R_X86_64_PC8)
 | 
|---|
| 929 |                     && (r_type != R_X86_64_PC16)
 | 
|---|
| 930 |                     && (r_type != R_X86_64_PC32))
 | 
|---|
| 931 |                    || (h != NULL
 | 
|---|
| 932 |                        && (! info->symbolic
 | 
|---|
| 933 |                            || h->root.type == bfd_link_hash_defweak
 | 
|---|
| 934 |                            || (h->elf_link_hash_flags
 | 
|---|
| 935 |                                & ELF_LINK_HASH_DEF_REGULAR) == 0))))
 | 
|---|
| 936 |               || (ELIMINATE_COPY_RELOCS
 | 
|---|
| 937 |                   && !info->shared
 | 
|---|
| 938 |                   && (sec->flags & SEC_ALLOC) != 0
 | 
|---|
| 939 |                   && h != NULL
 | 
|---|
| 940 |                   && (h->root.type == bfd_link_hash_defweak
 | 
|---|
| 941 |                       || (h->elf_link_hash_flags
 | 
|---|
| 942 |                           & ELF_LINK_HASH_DEF_REGULAR) == 0)))
 | 
|---|
| 943 |             {
 | 
|---|
| 944 |               struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 945 |               struct elf64_x86_64_dyn_relocs **head;
 | 
|---|
| 946 | 
 | 
|---|
| 947 |               /* We must copy these reloc types into the output file.
 | 
|---|
| 948 |                  Create a reloc section in dynobj and make room for
 | 
|---|
| 949 |                  this reloc.  */
 | 
|---|
| 950 |               if (sreloc == NULL)
 | 
|---|
| 951 |                 {
 | 
|---|
| 952 |                   const char *name;
 | 
|---|
| 953 |                   bfd *dynobj;
 | 
|---|
| 954 | 
 | 
|---|
| 955 |                   name = (bfd_elf_string_from_elf_section
 | 
|---|
| 956 |                           (abfd,
 | 
|---|
| 957 |                            elf_elfheader (abfd)->e_shstrndx,
 | 
|---|
| 958 |                            elf_section_data (sec)->rel_hdr.sh_name));
 | 
|---|
| 959 |                   if (name == NULL)
 | 
|---|
| 960 |                     return FALSE;
 | 
|---|
| 961 | 
 | 
|---|
| 962 |                   if (strncmp (name, ".rela", 5) != 0
 | 
|---|
| 963 |                       || strcmp (bfd_get_section_name (abfd, sec),
 | 
|---|
| 964 |                                  name + 5) != 0)
 | 
|---|
| 965 |                     {
 | 
|---|
| 966 |                       (*_bfd_error_handler)
 | 
|---|
| 967 |                         (_("%s: bad relocation section name `%s\'"),
 | 
|---|
| 968 |                          bfd_archive_filename (abfd), name);
 | 
|---|
| 969 |                     }
 | 
|---|
| 970 | 
 | 
|---|
| 971 |                   if (htab->elf.dynobj == NULL)
 | 
|---|
| 972 |                     htab->elf.dynobj = abfd;
 | 
|---|
| 973 | 
 | 
|---|
| 974 |                   dynobj = htab->elf.dynobj;
 | 
|---|
| 975 | 
 | 
|---|
| 976 |                   sreloc = bfd_get_section_by_name (dynobj, name);
 | 
|---|
| 977 |                   if (sreloc == NULL)
 | 
|---|
| 978 |                     {
 | 
|---|
| 979 |                       flagword flags;
 | 
|---|
| 980 | 
 | 
|---|
| 981 |                       sreloc = bfd_make_section (dynobj, name);
 | 
|---|
| 982 |                       flags = (SEC_HAS_CONTENTS | SEC_READONLY
 | 
|---|
| 983 |                                | SEC_IN_MEMORY | SEC_LINKER_CREATED);
 | 
|---|
| 984 |                       if ((sec->flags & SEC_ALLOC) != 0)
 | 
|---|
| 985 |                         flags |= SEC_ALLOC | SEC_LOAD;
 | 
|---|
| 986 |                       if (sreloc == NULL
 | 
|---|
| 987 |                           || ! bfd_set_section_flags (dynobj, sreloc, flags)
 | 
|---|
| 988 |                           || ! bfd_set_section_alignment (dynobj, sreloc, 3))
 | 
|---|
| 989 |                         return FALSE;
 | 
|---|
| 990 |                     }
 | 
|---|
| 991 |                   elf_section_data (sec)->sreloc = sreloc;
 | 
|---|
| 992 |                 }
 | 
|---|
| 993 | 
 | 
|---|
| 994 |               /* If this is a global symbol, we count the number of
 | 
|---|
| 995 |                  relocations we need for this symbol.  */
 | 
|---|
| 996 |               if (h != NULL)
 | 
|---|
| 997 |                 {
 | 
|---|
| 998 |                   head = &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs;
 | 
|---|
| 999 |                 }
 | 
|---|
| 1000 |               else
 | 
|---|
| 1001 |                 {
 | 
|---|
| 1002 |                   /* Track dynamic relocs needed for local syms too.
 | 
|---|
| 1003 |                      We really need local syms available to do this
 | 
|---|
| 1004 |                      easily.  Oh well.  */
 | 
|---|
| 1005 | 
 | 
|---|
| 1006 |                   asection *s;
 | 
|---|
| 1007 |                   s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
 | 
|---|
| 1008 |                                                  sec, r_symndx);
 | 
|---|
| 1009 |                   if (s == NULL)
 | 
|---|
| 1010 |                     return FALSE;
 | 
|---|
| 1011 | 
 | 
|---|
| 1012 |                   head = ((struct elf64_x86_64_dyn_relocs **)
 | 
|---|
| 1013 |                           &elf_section_data (s)->local_dynrel);
 | 
|---|
| 1014 |                 }
 | 
|---|
| 1015 | 
 | 
|---|
| 1016 |               p = *head;
 | 
|---|
| 1017 |               if (p == NULL || p->sec != sec)
 | 
|---|
| 1018 |                 {
 | 
|---|
| 1019 |                   bfd_size_type amt = sizeof *p;
 | 
|---|
| 1020 |                   p = ((struct elf64_x86_64_dyn_relocs *)
 | 
|---|
| 1021 |                        bfd_alloc (htab->elf.dynobj, amt));
 | 
|---|
| 1022 |                   if (p == NULL)
 | 
|---|
| 1023 |                     return FALSE;
 | 
|---|
| 1024 |                   p->next = *head;
 | 
|---|
| 1025 |                   *head = p;
 | 
|---|
| 1026 |                   p->sec = sec;
 | 
|---|
| 1027 |                   p->count = 0;
 | 
|---|
| 1028 |                   p->pc_count = 0;
 | 
|---|
| 1029 |                 }
 | 
|---|
| 1030 | 
 | 
|---|
| 1031 |               p->count += 1;
 | 
|---|
| 1032 |               if (r_type == R_X86_64_PC8
 | 
|---|
| 1033 |                   || r_type == R_X86_64_PC16
 | 
|---|
| 1034 |                   || r_type == R_X86_64_PC32)
 | 
|---|
| 1035 |                 p->pc_count += 1;
 | 
|---|
| 1036 |             }
 | 
|---|
| 1037 |           break;
 | 
|---|
| 1038 | 
 | 
|---|
| 1039 |           /* This relocation describes the C++ object vtable hierarchy.
 | 
|---|
| 1040 |              Reconstruct it for later use during GC.  */
 | 
|---|
| 1041 |         case R_X86_64_GNU_VTINHERIT:
 | 
|---|
| 1042 |           if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
 | 
|---|
| 1043 |             return FALSE;
 | 
|---|
| 1044 |           break;
 | 
|---|
| 1045 | 
 | 
|---|
| 1046 |           /* This relocation describes which C++ vtable entries are actually
 | 
|---|
| 1047 |              used.  Record for later use during GC.  */
 | 
|---|
| 1048 |         case R_X86_64_GNU_VTENTRY:
 | 
|---|
| 1049 |           if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend))
 | 
|---|
| 1050 |             return FALSE;
 | 
|---|
| 1051 |           break;
 | 
|---|
| 1052 | 
 | 
|---|
| 1053 |         default:
 | 
|---|
| 1054 |           break;
 | 
|---|
| 1055 |         }
 | 
|---|
| 1056 |     }
 | 
|---|
| 1057 | 
 | 
|---|
| 1058 |   return TRUE;
 | 
|---|
| 1059 | }
 | 
|---|
| 1060 | 
 | 
|---|
| 1061 | /* Return the section that should be marked against GC for a given
 | 
|---|
| 1062 |    relocation.  */
 | 
|---|
| 1063 | 
 | 
|---|
| 1064 | static asection *
 | 
|---|
| 1065 | elf64_x86_64_gc_mark_hook (sec, info, rel, h, sym)
 | 
|---|
| 1066 |      asection *sec;
 | 
|---|
| 1067 |      struct bfd_link_info *info ATTRIBUTE_UNUSED;
 | 
|---|
| 1068 |      Elf_Internal_Rela *rel;
 | 
|---|
| 1069 |      struct elf_link_hash_entry *h;
 | 
|---|
| 1070 |      Elf_Internal_Sym *sym;
 | 
|---|
| 1071 | {
 | 
|---|
| 1072 |   if (h != NULL)
 | 
|---|
| 1073 |     {
 | 
|---|
| 1074 |       switch (ELF64_R_TYPE (rel->r_info))
 | 
|---|
| 1075 |         {
 | 
|---|
| 1076 |         case R_X86_64_GNU_VTINHERIT:
 | 
|---|
| 1077 |         case R_X86_64_GNU_VTENTRY:
 | 
|---|
| 1078 |           break;
 | 
|---|
| 1079 | 
 | 
|---|
| 1080 |         default:
 | 
|---|
| 1081 |           switch (h->root.type)
 | 
|---|
| 1082 |             {
 | 
|---|
| 1083 |             case bfd_link_hash_defined:
 | 
|---|
| 1084 |             case bfd_link_hash_defweak:
 | 
|---|
| 1085 |               return h->root.u.def.section;
 | 
|---|
| 1086 | 
 | 
|---|
| 1087 |             case bfd_link_hash_common:
 | 
|---|
| 1088 |               return h->root.u.c.p->section;
 | 
|---|
| 1089 | 
 | 
|---|
| 1090 |             default:
 | 
|---|
| 1091 |               break;
 | 
|---|
| 1092 |             }
 | 
|---|
| 1093 |         }
 | 
|---|
| 1094 |     }
 | 
|---|
| 1095 |   else
 | 
|---|
| 1096 |     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
 | 
|---|
| 1097 | 
 | 
|---|
| 1098 |   return NULL;
 | 
|---|
| 1099 | }
 | 
|---|
| 1100 | 
 | 
|---|
| 1101 | /* Update the got entry reference counts for the section being removed.  */
 | 
|---|
| 1102 | 
 | 
|---|
| 1103 | static bfd_boolean
 | 
|---|
| 1104 | elf64_x86_64_gc_sweep_hook (abfd, info, sec, relocs)
 | 
|---|
| 1105 |      bfd *abfd;
 | 
|---|
| 1106 |      struct bfd_link_info *info;
 | 
|---|
| 1107 |      asection *sec;
 | 
|---|
| 1108 |      const Elf_Internal_Rela *relocs;
 | 
|---|
| 1109 | {
 | 
|---|
| 1110 |   Elf_Internal_Shdr *symtab_hdr;
 | 
|---|
| 1111 |   struct elf_link_hash_entry **sym_hashes;
 | 
|---|
| 1112 |   bfd_signed_vma *local_got_refcounts;
 | 
|---|
| 1113 |   const Elf_Internal_Rela *rel, *relend;
 | 
|---|
| 1114 | 
 | 
|---|
| 1115 |   elf_section_data (sec)->local_dynrel = NULL;
 | 
|---|
| 1116 | 
 | 
|---|
| 1117 |   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 | 
|---|
| 1118 |   sym_hashes = elf_sym_hashes (abfd);
 | 
|---|
| 1119 |   local_got_refcounts = elf_local_got_refcounts (abfd);
 | 
|---|
| 1120 | 
 | 
|---|
| 1121 |   relend = relocs + sec->reloc_count;
 | 
|---|
| 1122 |   for (rel = relocs; rel < relend; rel++)
 | 
|---|
| 1123 |     {
 | 
|---|
| 1124 |       unsigned long r_symndx;
 | 
|---|
| 1125 |       unsigned int r_type;
 | 
|---|
| 1126 |       struct elf_link_hash_entry *h = NULL;
 | 
|---|
| 1127 | 
 | 
|---|
| 1128 |       r_symndx = ELF64_R_SYM (rel->r_info);
 | 
|---|
| 1129 |       if (r_symndx >= symtab_hdr->sh_info)
 | 
|---|
| 1130 |         {
 | 
|---|
| 1131 |           struct elf64_x86_64_link_hash_entry *eh;
 | 
|---|
| 1132 |           struct elf64_x86_64_dyn_relocs **pp;
 | 
|---|
| 1133 |           struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 1134 | 
 | 
|---|
| 1135 |           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 | 
|---|
| 1136 |           eh = (struct elf64_x86_64_link_hash_entry *) h;
 | 
|---|
| 1137 | 
 | 
|---|
| 1138 |           for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
 | 
|---|
| 1139 |             if (p->sec == sec)
 | 
|---|
| 1140 |               {
 | 
|---|
| 1141 |                 /* Everything must go for SEC.  */
 | 
|---|
| 1142 |                 *pp = p->next;
 | 
|---|
| 1143 |                 break;
 | 
|---|
| 1144 |               }
 | 
|---|
| 1145 |         }
 | 
|---|
| 1146 | 
 | 
|---|
| 1147 |       r_type = ELF64_R_TYPE (rel->r_info);
 | 
|---|
| 1148 |       r_type = elf64_x86_64_tls_transition (info, r_type, h != NULL);
 | 
|---|
| 1149 |       switch (r_type)
 | 
|---|
| 1150 |         {
 | 
|---|
| 1151 |         case R_X86_64_TLSLD:
 | 
|---|
| 1152 |           if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0)
 | 
|---|
| 1153 |             elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1;
 | 
|---|
| 1154 |           break;
 | 
|---|
| 1155 | 
 | 
|---|
| 1156 |         case R_X86_64_TLSGD:
 | 
|---|
| 1157 |         case R_X86_64_GOTTPOFF:
 | 
|---|
| 1158 |         case R_X86_64_GOT32:
 | 
|---|
| 1159 |         case R_X86_64_GOTPCREL:
 | 
|---|
| 1160 |           if (h != NULL)
 | 
|---|
| 1161 |             {
 | 
|---|
| 1162 |               if (h->got.refcount > 0)
 | 
|---|
| 1163 |                 h->got.refcount -= 1;
 | 
|---|
| 1164 |             }
 | 
|---|
| 1165 |           else if (local_got_refcounts != NULL)
 | 
|---|
| 1166 |             {
 | 
|---|
| 1167 |               if (local_got_refcounts[r_symndx] > 0)
 | 
|---|
| 1168 |                 local_got_refcounts[r_symndx] -= 1;
 | 
|---|
| 1169 |             }
 | 
|---|
| 1170 |           break;
 | 
|---|
| 1171 | 
 | 
|---|
| 1172 |         case R_X86_64_8:
 | 
|---|
| 1173 |         case R_X86_64_16:
 | 
|---|
| 1174 |         case R_X86_64_32:
 | 
|---|
| 1175 |         case R_X86_64_64:
 | 
|---|
| 1176 |         case R_X86_64_32S:
 | 
|---|
| 1177 |         case R_X86_64_PC8:
 | 
|---|
| 1178 |         case R_X86_64_PC16:
 | 
|---|
| 1179 |         case R_X86_64_PC32:
 | 
|---|
| 1180 |           if (info->shared)
 | 
|---|
| 1181 |             break;
 | 
|---|
| 1182 |           /* Fall thru */
 | 
|---|
| 1183 | 
 | 
|---|
| 1184 |         case R_X86_64_PLT32:
 | 
|---|
| 1185 |           if (h != NULL)
 | 
|---|
| 1186 |             {
 | 
|---|
| 1187 |               if (h->plt.refcount > 0)
 | 
|---|
| 1188 |                 h->plt.refcount -= 1;
 | 
|---|
| 1189 |             }
 | 
|---|
| 1190 |           break;
 | 
|---|
| 1191 | 
 | 
|---|
| 1192 |         default:
 | 
|---|
| 1193 |           break;
 | 
|---|
| 1194 |         }
 | 
|---|
| 1195 |     }
 | 
|---|
| 1196 | 
 | 
|---|
| 1197 |   return TRUE;
 | 
|---|
| 1198 | }
 | 
|---|
| 1199 | 
 | 
|---|
| 1200 | /* Adjust a symbol defined by a dynamic object and referenced by a
 | 
|---|
| 1201 |    regular object.  The current definition is in some section of the
 | 
|---|
| 1202 |    dynamic object, but we're not including those sections.  We have to
 | 
|---|
| 1203 |    change the definition to something the rest of the link can
 | 
|---|
| 1204 |    understand.  */
 | 
|---|
| 1205 | 
 | 
|---|
| 1206 | static bfd_boolean
 | 
|---|
| 1207 | elf64_x86_64_adjust_dynamic_symbol (info, h)
 | 
|---|
| 1208 |      struct bfd_link_info *info;
 | 
|---|
| 1209 |      struct elf_link_hash_entry *h;
 | 
|---|
| 1210 | {
 | 
|---|
| 1211 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 1212 |   asection *s;
 | 
|---|
| 1213 |   unsigned int power_of_two;
 | 
|---|
| 1214 | 
 | 
|---|
| 1215 |   /* If this is a function, put it in the procedure linkage table.  We
 | 
|---|
| 1216 |      will fill in the contents of the procedure linkage table later,
 | 
|---|
| 1217 |      when we know the address of the .got section.  */
 | 
|---|
| 1218 |   if (h->type == STT_FUNC
 | 
|---|
| 1219 |       || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
 | 
|---|
| 1220 |     {
 | 
|---|
| 1221 |       if (h->plt.refcount <= 0
 | 
|---|
| 1222 |           || (! info->shared
 | 
|---|
| 1223 |               && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
 | 
|---|
| 1224 |               && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
 | 
|---|
| 1225 |               && h->root.type != bfd_link_hash_undefweak
 | 
|---|
| 1226 |               && h->root.type != bfd_link_hash_undefined))
 | 
|---|
| 1227 |         {
 | 
|---|
| 1228 |           /* This case can occur if we saw a PLT32 reloc in an input
 | 
|---|
| 1229 |              file, but the symbol was never referred to by a dynamic
 | 
|---|
| 1230 |              object, or if all references were garbage collected.  In
 | 
|---|
| 1231 |              such a case, we don't actually need to build a procedure
 | 
|---|
| 1232 |              linkage table, and we can just do a PC32 reloc instead.  */
 | 
|---|
| 1233 |           h->plt.offset = (bfd_vma) -1;
 | 
|---|
| 1234 |           h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
 | 
|---|
| 1235 |         }
 | 
|---|
| 1236 | 
 | 
|---|
| 1237 |       return TRUE;
 | 
|---|
| 1238 |     }
 | 
|---|
| 1239 |   else
 | 
|---|
| 1240 |     /* It's possible that we incorrectly decided a .plt reloc was
 | 
|---|
| 1241 |        needed for an R_X86_64_PC32 reloc to a non-function sym in
 | 
|---|
| 1242 |        check_relocs.  We can't decide accurately between function and
 | 
|---|
| 1243 |        non-function syms in check-relocs;  Objects loaded later in
 | 
|---|
| 1244 |        the link may change h->type.  So fix it now.  */
 | 
|---|
| 1245 |     h->plt.offset = (bfd_vma) -1;
 | 
|---|
| 1246 | 
 | 
|---|
| 1247 |   /* If this is a weak symbol, and there is a real definition, the
 | 
|---|
| 1248 |      processor independent code will have arranged for us to see the
 | 
|---|
| 1249 |      real definition first, and we can just use the same value.  */
 | 
|---|
| 1250 |   if (h->weakdef != NULL)
 | 
|---|
| 1251 |     {
 | 
|---|
| 1252 |       BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
 | 
|---|
| 1253 |                   || h->weakdef->root.type == bfd_link_hash_defweak);
 | 
|---|
| 1254 |       h->root.u.def.section = h->weakdef->root.u.def.section;
 | 
|---|
| 1255 |       h->root.u.def.value = h->weakdef->root.u.def.value;
 | 
|---|
| 1256 |       if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
 | 
|---|
| 1257 |         h->elf_link_hash_flags
 | 
|---|
| 1258 |           = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF)
 | 
|---|
| 1259 |              | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF));
 | 
|---|
| 1260 |       return TRUE;
 | 
|---|
| 1261 |     }
 | 
|---|
| 1262 | 
 | 
|---|
| 1263 |   /* This is a reference to a symbol defined by a dynamic object which
 | 
|---|
| 1264 |      is not a function.  */
 | 
|---|
| 1265 | 
 | 
|---|
| 1266 |   /* If we are creating a shared library, we must presume that the
 | 
|---|
| 1267 |      only references to the symbol are via the global offset table.
 | 
|---|
| 1268 |      For such cases we need not do anything here; the relocations will
 | 
|---|
| 1269 |      be handled correctly by relocate_section.  */
 | 
|---|
| 1270 |   if (info->shared)
 | 
|---|
| 1271 |     return TRUE;
 | 
|---|
| 1272 | 
 | 
|---|
| 1273 |   /* If there are no references to this symbol that do not use the
 | 
|---|
| 1274 |      GOT, we don't need to generate a copy reloc.  */
 | 
|---|
| 1275 |   if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
 | 
|---|
| 1276 |     return TRUE;
 | 
|---|
| 1277 | 
 | 
|---|
| 1278 |   /* If -z nocopyreloc was given, we won't generate them either.  */
 | 
|---|
| 1279 |   if (info->nocopyreloc)
 | 
|---|
| 1280 |     {
 | 
|---|
| 1281 |       h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
 | 
|---|
| 1282 |       return TRUE;
 | 
|---|
| 1283 |     }
 | 
|---|
| 1284 | 
 | 
|---|
| 1285 |   if (ELIMINATE_COPY_RELOCS)
 | 
|---|
| 1286 |     {
 | 
|---|
| 1287 |       struct elf64_x86_64_link_hash_entry * eh;
 | 
|---|
| 1288 |       struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 1289 | 
 | 
|---|
| 1290 |       eh = (struct elf64_x86_64_link_hash_entry *) h;
 | 
|---|
| 1291 |       for (p = eh->dyn_relocs; p != NULL; p = p->next)
 | 
|---|
| 1292 |         {
 | 
|---|
| 1293 |           s = p->sec->output_section;
 | 
|---|
| 1294 |           if (s != NULL && (s->flags & SEC_READONLY) != 0)
 | 
|---|
| 1295 |             break;
 | 
|---|
| 1296 |         }
 | 
|---|
| 1297 | 
 | 
|---|
| 1298 |       /* If we didn't find any dynamic relocs in read-only sections, then
 | 
|---|
| 1299 |          we'll be keeping the dynamic relocs and avoiding the copy reloc.  */
 | 
|---|
| 1300 |       if (p == NULL)
 | 
|---|
| 1301 |         {
 | 
|---|
| 1302 |           h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
 | 
|---|
| 1303 |           return TRUE;
 | 
|---|
| 1304 |         }
 | 
|---|
| 1305 |     }
 | 
|---|
| 1306 | 
 | 
|---|
| 1307 |   /* We must allocate the symbol in our .dynbss section, which will
 | 
|---|
| 1308 |      become part of the .bss section of the executable.  There will be
 | 
|---|
| 1309 |      an entry for this symbol in the .dynsym section.  The dynamic
 | 
|---|
| 1310 |      object will contain position independent code, so all references
 | 
|---|
| 1311 |      from the dynamic object to this symbol will go through the global
 | 
|---|
| 1312 |      offset table.  The dynamic linker will use the .dynsym entry to
 | 
|---|
| 1313 |      determine the address it must put in the global offset table, so
 | 
|---|
| 1314 |      both the dynamic object and the regular object will refer to the
 | 
|---|
| 1315 |      same memory location for the variable.  */
 | 
|---|
| 1316 | 
 | 
|---|
| 1317 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 1318 | 
 | 
|---|
| 1319 |   /* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
 | 
|---|
| 1320 |      to copy the initial value out of the dynamic object and into the
 | 
|---|
| 1321 |      runtime process image.  */
 | 
|---|
| 1322 |   if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
 | 
|---|
| 1323 |     {
 | 
|---|
| 1324 |       htab->srelbss->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1325 |       h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
 | 
|---|
| 1326 |     }
 | 
|---|
| 1327 | 
 | 
|---|
| 1328 |   /* We need to figure out the alignment required for this symbol.  I
 | 
|---|
| 1329 |      have no idea how ELF linkers handle this.  16-bytes is the size
 | 
|---|
| 1330 |      of the largest type that requires hard alignment -- long double.  */
 | 
|---|
| 1331 |   /* FIXME: This is VERY ugly. Should be fixed for all architectures using
 | 
|---|
| 1332 |      this construct.  */
 | 
|---|
| 1333 |   power_of_two = bfd_log2 (h->size);
 | 
|---|
| 1334 |   if (power_of_two > 4)
 | 
|---|
| 1335 |     power_of_two = 4;
 | 
|---|
| 1336 | 
 | 
|---|
| 1337 |   /* Apply the required alignment.  */
 | 
|---|
| 1338 |   s = htab->sdynbss;
 | 
|---|
| 1339 |   s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two));
 | 
|---|
| 1340 |   if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s))
 | 
|---|
| 1341 |     {
 | 
|---|
| 1342 |       if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two))
 | 
|---|
| 1343 |         return FALSE;
 | 
|---|
| 1344 |     }
 | 
|---|
| 1345 | 
 | 
|---|
| 1346 |   /* Define the symbol as being at this point in the section.  */
 | 
|---|
| 1347 |   h->root.u.def.section = s;
 | 
|---|
| 1348 |   h->root.u.def.value = s->_raw_size;
 | 
|---|
| 1349 | 
 | 
|---|
| 1350 |   /* Increment the section size to make room for the symbol.  */
 | 
|---|
| 1351 |   s->_raw_size += h->size;
 | 
|---|
| 1352 | 
 | 
|---|
| 1353 |   return TRUE;
 | 
|---|
| 1354 | }
 | 
|---|
| 1355 | 
 | 
|---|
| 1356 | /* This is the condition under which elf64_x86_64_finish_dynamic_symbol
 | 
|---|
| 1357 |    will be called from elflink.h.  If elflink.h doesn't call our
 | 
|---|
| 1358 |    finish_dynamic_symbol routine, we'll need to do something about
 | 
|---|
| 1359 |    initializing any .plt and .got entries in elf64_x86_64_relocate_section.  */
 | 
|---|
| 1360 | #define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
 | 
|---|
| 1361 |   ((DYN)                                                                \
 | 
|---|
| 1362 |    && ((INFO)->shared                                                   \
 | 
|---|
| 1363 |        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)      \
 | 
|---|
| 1364 |    && ((H)->dynindx != -1                                               \
 | 
|---|
| 1365 |        || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
 | 
|---|
| 1366 | 
 | 
|---|
| 1367 | /* Allocate space in .plt, .got and associated reloc sections for
 | 
|---|
| 1368 |    dynamic relocs.  */
 | 
|---|
| 1369 | 
 | 
|---|
| 1370 | static bfd_boolean
 | 
|---|
| 1371 | allocate_dynrelocs (h, inf)
 | 
|---|
| 1372 |      struct elf_link_hash_entry *h;
 | 
|---|
| 1373 |      PTR inf;
 | 
|---|
| 1374 | {
 | 
|---|
| 1375 |   struct bfd_link_info *info;
 | 
|---|
| 1376 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 1377 |   struct elf64_x86_64_link_hash_entry *eh;
 | 
|---|
| 1378 |   struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 1379 | 
 | 
|---|
| 1380 |   if (h->root.type == bfd_link_hash_indirect)
 | 
|---|
| 1381 |     return TRUE;
 | 
|---|
| 1382 | 
 | 
|---|
| 1383 |   if (h->root.type == bfd_link_hash_warning)
 | 
|---|
| 1384 |     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 | 
|---|
| 1385 | 
 | 
|---|
| 1386 |   info = (struct bfd_link_info *) inf;
 | 
|---|
| 1387 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 1388 | 
 | 
|---|
| 1389 |   if (htab->elf.dynamic_sections_created
 | 
|---|
| 1390 |       && h->plt.refcount > 0)
 | 
|---|
| 1391 |     {
 | 
|---|
| 1392 |       /* Make sure this symbol is output as a dynamic symbol.
 | 
|---|
| 1393 |          Undefined weak syms won't yet be marked as dynamic.  */
 | 
|---|
| 1394 |       if (h->dynindx == -1
 | 
|---|
| 1395 |           && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 | 
|---|
| 1396 |         {
 | 
|---|
| 1397 |           if (! bfd_elf64_link_record_dynamic_symbol (info, h))
 | 
|---|
| 1398 |             return FALSE;
 | 
|---|
| 1399 |         }
 | 
|---|
| 1400 | 
 | 
|---|
| 1401 |       if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
 | 
|---|
| 1402 |         {
 | 
|---|
| 1403 |           asection *s = htab->splt;
 | 
|---|
| 1404 | 
 | 
|---|
| 1405 |           /* If this is the first .plt entry, make room for the special
 | 
|---|
| 1406 |              first entry.  */
 | 
|---|
| 1407 |           if (s->_raw_size == 0)
 | 
|---|
| 1408 |             s->_raw_size += PLT_ENTRY_SIZE;
 | 
|---|
| 1409 | 
 | 
|---|
| 1410 |           h->plt.offset = s->_raw_size;
 | 
|---|
| 1411 | 
 | 
|---|
| 1412 |           /* If this symbol is not defined in a regular file, and we are
 | 
|---|
| 1413 |              not generating a shared library, then set the symbol to this
 | 
|---|
| 1414 |              location in the .plt.  This is required to make function
 | 
|---|
| 1415 |              pointers compare as equal between the normal executable and
 | 
|---|
| 1416 |              the shared library.  */
 | 
|---|
| 1417 |           if (! info->shared
 | 
|---|
| 1418 |               && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
 | 
|---|
| 1419 |             {
 | 
|---|
| 1420 |               h->root.u.def.section = s;
 | 
|---|
| 1421 |               h->root.u.def.value = h->plt.offset;
 | 
|---|
| 1422 |             }
 | 
|---|
| 1423 | 
 | 
|---|
| 1424 |           /* Make room for this entry.  */
 | 
|---|
| 1425 |           s->_raw_size += PLT_ENTRY_SIZE;
 | 
|---|
| 1426 | 
 | 
|---|
| 1427 |           /* We also need to make an entry in the .got.plt section, which
 | 
|---|
| 1428 |              will be placed in the .got section by the linker script.  */
 | 
|---|
| 1429 |           htab->sgotplt->_raw_size += GOT_ENTRY_SIZE;
 | 
|---|
| 1430 | 
 | 
|---|
| 1431 |           /* We also need to make an entry in the .rela.plt section.  */
 | 
|---|
| 1432 |           htab->srelplt->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1433 |         }
 | 
|---|
| 1434 |       else
 | 
|---|
| 1435 |         {
 | 
|---|
| 1436 |           h->plt.offset = (bfd_vma) -1;
 | 
|---|
| 1437 |           h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
 | 
|---|
| 1438 |         }
 | 
|---|
| 1439 |     }
 | 
|---|
| 1440 |   else
 | 
|---|
| 1441 |     {
 | 
|---|
| 1442 |       h->plt.offset = (bfd_vma) -1;
 | 
|---|
| 1443 |       h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
 | 
|---|
| 1444 |     }
 | 
|---|
| 1445 | 
 | 
|---|
| 1446 |   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
 | 
|---|
| 1447 |      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
 | 
|---|
| 1448 |   if (h->got.refcount > 0
 | 
|---|
| 1449 |       && !info->shared
 | 
|---|
| 1450 |       && h->dynindx == -1
 | 
|---|
| 1451 |       && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
 | 
|---|
| 1452 |     h->got.offset = (bfd_vma) -1;
 | 
|---|
| 1453 |   else if (h->got.refcount > 0)
 | 
|---|
| 1454 |     {
 | 
|---|
| 1455 |       asection *s;
 | 
|---|
| 1456 |       bfd_boolean dyn;
 | 
|---|
| 1457 |       int tls_type = elf64_x86_64_hash_entry (h)->tls_type;
 | 
|---|
| 1458 | 
 | 
|---|
| 1459 |       /* Make sure this symbol is output as a dynamic symbol.
 | 
|---|
| 1460 |          Undefined weak syms won't yet be marked as dynamic.  */
 | 
|---|
| 1461 |       if (h->dynindx == -1
 | 
|---|
| 1462 |           && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 | 
|---|
| 1463 |         {
 | 
|---|
| 1464 |           if (! bfd_elf64_link_record_dynamic_symbol (info, h))
 | 
|---|
| 1465 |             return FALSE;
 | 
|---|
| 1466 |         }
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 |       s = htab->sgot;
 | 
|---|
| 1469 |       h->got.offset = s->_raw_size;
 | 
|---|
| 1470 |       s->_raw_size += GOT_ENTRY_SIZE;
 | 
|---|
| 1471 |       /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
 | 
|---|
| 1472 |       if (tls_type == GOT_TLS_GD)
 | 
|---|
| 1473 |         s->_raw_size += GOT_ENTRY_SIZE;
 | 
|---|
| 1474 |       dyn = htab->elf.dynamic_sections_created;
 | 
|---|
| 1475 |       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
 | 
|---|
| 1476 |          and two if global.
 | 
|---|
| 1477 |          R_X86_64_GOTTPOFF needs one dynamic relocation.  */
 | 
|---|
| 1478 |       if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
 | 
|---|
| 1479 |           || tls_type == GOT_TLS_IE)
 | 
|---|
| 1480 |         htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1481 |       else if (tls_type == GOT_TLS_GD)
 | 
|---|
| 1482 |         htab->srelgot->_raw_size += 2 * sizeof (Elf64_External_Rela);
 | 
|---|
| 1483 |       else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
 | 
|---|
| 1484 |         htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1485 |     }
 | 
|---|
| 1486 |   else
 | 
|---|
| 1487 |     h->got.offset = (bfd_vma) -1;
 | 
|---|
| 1488 | 
 | 
|---|
| 1489 |   eh = (struct elf64_x86_64_link_hash_entry *) h;
 | 
|---|
| 1490 |   if (eh->dyn_relocs == NULL)
 | 
|---|
| 1491 |     return TRUE;
 | 
|---|
| 1492 | 
 | 
|---|
| 1493 |   /* In the shared -Bsymbolic case, discard space allocated for
 | 
|---|
| 1494 |      dynamic pc-relative relocs against symbols which turn out to be
 | 
|---|
| 1495 |      defined in regular objects.  For the normal shared case, discard
 | 
|---|
| 1496 |      space for pc-relative relocs that have become local due to symbol
 | 
|---|
| 1497 |      visibility changes.  */
 | 
|---|
| 1498 | 
 | 
|---|
| 1499 |   if (info->shared)
 | 
|---|
| 1500 |     {
 | 
|---|
| 1501 |       if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
 | 
|---|
| 1502 |           && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
 | 
|---|
| 1503 |               || info->symbolic))
 | 
|---|
| 1504 |         {
 | 
|---|
| 1505 |           struct elf64_x86_64_dyn_relocs **pp;
 | 
|---|
| 1506 | 
 | 
|---|
| 1507 |           for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
 | 
|---|
| 1508 |             {
 | 
|---|
| 1509 |               p->count -= p->pc_count;
 | 
|---|
| 1510 |               p->pc_count = 0;
 | 
|---|
| 1511 |               if (p->count == 0)
 | 
|---|
| 1512 |                 *pp = p->next;
 | 
|---|
| 1513 |               else
 | 
|---|
| 1514 |                 pp = &p->next;
 | 
|---|
| 1515 |             }
 | 
|---|
| 1516 |         }
 | 
|---|
| 1517 |     }
 | 
|---|
| 1518 |   else if (ELIMINATE_COPY_RELOCS)
 | 
|---|
| 1519 |     {
 | 
|---|
| 1520 |       /* For the non-shared case, discard space for relocs against
 | 
|---|
| 1521 |          symbols which turn out to need copy relocs or are not
 | 
|---|
| 1522 |          dynamic.  */
 | 
|---|
| 1523 | 
 | 
|---|
| 1524 |       if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
 | 
|---|
| 1525 |           && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
 | 
|---|
| 1526 |                && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
 | 
|---|
| 1527 |               || (htab->elf.dynamic_sections_created
 | 
|---|
| 1528 |                   && (h->root.type == bfd_link_hash_undefweak
 | 
|---|
| 1529 |                       || h->root.type == bfd_link_hash_undefined))))
 | 
|---|
| 1530 |         {
 | 
|---|
| 1531 |           /* Make sure this symbol is output as a dynamic symbol.
 | 
|---|
| 1532 |              Undefined weak syms won't yet be marked as dynamic.  */
 | 
|---|
| 1533 |           if (h->dynindx == -1
 | 
|---|
| 1534 |               && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
 | 
|---|
| 1535 |             {
 | 
|---|
| 1536 |               if (! bfd_elf64_link_record_dynamic_symbol (info, h))
 | 
|---|
| 1537 |                 return FALSE;
 | 
|---|
| 1538 |             }
 | 
|---|
| 1539 | 
 | 
|---|
| 1540 |           /* If that succeeded, we know we'll be keeping all the
 | 
|---|
| 1541 |              relocs.  */
 | 
|---|
| 1542 |           if (h->dynindx != -1)
 | 
|---|
| 1543 |             goto keep;
 | 
|---|
| 1544 |         }
 | 
|---|
| 1545 | 
 | 
|---|
| 1546 |       eh->dyn_relocs = NULL;
 | 
|---|
| 1547 | 
 | 
|---|
| 1548 |     keep: ;
 | 
|---|
| 1549 |     }
 | 
|---|
| 1550 | 
 | 
|---|
| 1551 |   /* Finally, allocate space.  */
 | 
|---|
| 1552 |   for (p = eh->dyn_relocs; p != NULL; p = p->next)
 | 
|---|
| 1553 |     {
 | 
|---|
| 1554 |       asection *sreloc = elf_section_data (p->sec)->sreloc;
 | 
|---|
| 1555 |       sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela);
 | 
|---|
| 1556 |     }
 | 
|---|
| 1557 | 
 | 
|---|
| 1558 |   return TRUE;
 | 
|---|
| 1559 | }
 | 
|---|
| 1560 | 
 | 
|---|
| 1561 | /* Find any dynamic relocs that apply to read-only sections.  */
 | 
|---|
| 1562 | 
 | 
|---|
| 1563 | static bfd_boolean
 | 
|---|
| 1564 | readonly_dynrelocs (h, inf)
 | 
|---|
| 1565 |      struct elf_link_hash_entry *h;
 | 
|---|
| 1566 |      PTR inf;
 | 
|---|
| 1567 | {
 | 
|---|
| 1568 |   struct elf64_x86_64_link_hash_entry *eh;
 | 
|---|
| 1569 |   struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 1570 | 
 | 
|---|
| 1571 |   if (h->root.type == bfd_link_hash_warning)
 | 
|---|
| 1572 |     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 | 
|---|
| 1573 | 
 | 
|---|
| 1574 |   eh = (struct elf64_x86_64_link_hash_entry *) h;
 | 
|---|
| 1575 |   for (p = eh->dyn_relocs; p != NULL; p = p->next)
 | 
|---|
| 1576 |     {
 | 
|---|
| 1577 |       asection *s = p->sec->output_section;
 | 
|---|
| 1578 | 
 | 
|---|
| 1579 |       if (s != NULL && (s->flags & SEC_READONLY) != 0)
 | 
|---|
| 1580 |         {
 | 
|---|
| 1581 |           struct bfd_link_info *info = (struct bfd_link_info *) inf;
 | 
|---|
| 1582 | 
 | 
|---|
| 1583 |           info->flags |= DF_TEXTREL;
 | 
|---|
| 1584 | 
 | 
|---|
| 1585 |           /* Not an error, just cut short the traversal.  */
 | 
|---|
| 1586 |           return FALSE;
 | 
|---|
| 1587 |         }
 | 
|---|
| 1588 |     }
 | 
|---|
| 1589 |   return TRUE;
 | 
|---|
| 1590 | }
 | 
|---|
| 1591 | 
 | 
|---|
| 1592 | /* Set the sizes of the dynamic sections.  */
 | 
|---|
| 1593 | 
 | 
|---|
| 1594 | static bfd_boolean
 | 
|---|
| 1595 | elf64_x86_64_size_dynamic_sections (output_bfd, info)
 | 
|---|
| 1596 |      bfd *output_bfd ATTRIBUTE_UNUSED;
 | 
|---|
| 1597 |      struct bfd_link_info *info;
 | 
|---|
| 1598 | {
 | 
|---|
| 1599 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 1600 |   bfd *dynobj;
 | 
|---|
| 1601 |   asection *s;
 | 
|---|
| 1602 |   bfd_boolean relocs;
 | 
|---|
| 1603 |   bfd *ibfd;
 | 
|---|
| 1604 | 
 | 
|---|
| 1605 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 1606 |   dynobj = htab->elf.dynobj;
 | 
|---|
| 1607 |   if (dynobj == NULL)
 | 
|---|
| 1608 |     abort ();
 | 
|---|
| 1609 | 
 | 
|---|
| 1610 |   if (htab->elf.dynamic_sections_created)
 | 
|---|
| 1611 |     {
 | 
|---|
| 1612 |       /* Set the contents of the .interp section to the interpreter.  */
 | 
|---|
| 1613 |       if (! info->shared)
 | 
|---|
| 1614 |         {
 | 
|---|
| 1615 |           s = bfd_get_section_by_name (dynobj, ".interp");
 | 
|---|
| 1616 |           if (s == NULL)
 | 
|---|
| 1617 |             abort ();
 | 
|---|
| 1618 |           s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
 | 
|---|
| 1619 |           s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
 | 
|---|
| 1620 |         }
 | 
|---|
| 1621 |     }
 | 
|---|
| 1622 | 
 | 
|---|
| 1623 |   /* Set up .got offsets for local syms, and space for local dynamic
 | 
|---|
| 1624 |      relocs.  */
 | 
|---|
| 1625 |   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
 | 
|---|
| 1626 |     {
 | 
|---|
| 1627 |       bfd_signed_vma *local_got;
 | 
|---|
| 1628 |       bfd_signed_vma *end_local_got;
 | 
|---|
| 1629 |       char *local_tls_type;
 | 
|---|
| 1630 |       bfd_size_type locsymcount;
 | 
|---|
| 1631 |       Elf_Internal_Shdr *symtab_hdr;
 | 
|---|
| 1632 |       asection *srel;
 | 
|---|
| 1633 | 
 | 
|---|
| 1634 |       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
 | 
|---|
| 1635 |         continue;
 | 
|---|
| 1636 | 
 | 
|---|
| 1637 |       for (s = ibfd->sections; s != NULL; s = s->next)
 | 
|---|
| 1638 |         {
 | 
|---|
| 1639 |           struct elf64_x86_64_dyn_relocs *p;
 | 
|---|
| 1640 | 
 | 
|---|
| 1641 |           for (p = *((struct elf64_x86_64_dyn_relocs **)
 | 
|---|
| 1642 |                      &elf_section_data (s)->local_dynrel);
 | 
|---|
| 1643 |                p != NULL;
 | 
|---|
| 1644 |                p = p->next)
 | 
|---|
| 1645 |             {
 | 
|---|
| 1646 |               if (!bfd_is_abs_section (p->sec)
 | 
|---|
| 1647 |                   && bfd_is_abs_section (p->sec->output_section))
 | 
|---|
| 1648 |                 {
 | 
|---|
| 1649 |                   /* Input section has been discarded, either because
 | 
|---|
| 1650 |                      it is a copy of a linkonce section or due to
 | 
|---|
| 1651 |                      linker script /DISCARD/, so we'll be discarding
 | 
|---|
| 1652 |                      the relocs too.  */
 | 
|---|
| 1653 |                 }
 | 
|---|
| 1654 |               else if (p->count != 0)
 | 
|---|
| 1655 |                 {
 | 
|---|
| 1656 |                   srel = elf_section_data (p->sec)->sreloc;
 | 
|---|
| 1657 |                   srel->_raw_size += p->count * sizeof (Elf64_External_Rela);
 | 
|---|
| 1658 |                   if ((p->sec->output_section->flags & SEC_READONLY) != 0)
 | 
|---|
| 1659 |                     info->flags |= DF_TEXTREL;
 | 
|---|
| 1660 | 
 | 
|---|
| 1661 |                 }
 | 
|---|
| 1662 |             }
 | 
|---|
| 1663 |         }
 | 
|---|
| 1664 | 
 | 
|---|
| 1665 |       local_got = elf_local_got_refcounts (ibfd);
 | 
|---|
| 1666 |       if (!local_got)
 | 
|---|
| 1667 |         continue;
 | 
|---|
| 1668 | 
 | 
|---|
| 1669 |       symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
 | 
|---|
| 1670 |       locsymcount = symtab_hdr->sh_info;
 | 
|---|
| 1671 |       end_local_got = local_got + locsymcount;
 | 
|---|
| 1672 |       local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
 | 
|---|
| 1673 |       s = htab->sgot;
 | 
|---|
| 1674 |       srel = htab->srelgot;
 | 
|---|
| 1675 |       for (; local_got < end_local_got; ++local_got, ++local_tls_type)
 | 
|---|
| 1676 |         {
 | 
|---|
| 1677 |           if (*local_got > 0)
 | 
|---|
| 1678 |             {
 | 
|---|
| 1679 |               *local_got = s->_raw_size;
 | 
|---|
| 1680 |               s->_raw_size += GOT_ENTRY_SIZE;
 | 
|---|
| 1681 |               if (*local_tls_type == GOT_TLS_GD)
 | 
|---|
| 1682 |                 s->_raw_size += GOT_ENTRY_SIZE;
 | 
|---|
| 1683 |               if (info->shared
 | 
|---|
| 1684 |                   || *local_tls_type == GOT_TLS_GD
 | 
|---|
| 1685 |                   || *local_tls_type == GOT_TLS_IE)
 | 
|---|
| 1686 |                 srel->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1687 |             }
 | 
|---|
| 1688 |           else
 | 
|---|
| 1689 |             *local_got = (bfd_vma) -1;
 | 
|---|
| 1690 |         }
 | 
|---|
| 1691 |     }
 | 
|---|
| 1692 | 
 | 
|---|
| 1693 |   if (htab->tls_ld_got.refcount > 0)
 | 
|---|
| 1694 |     {
 | 
|---|
| 1695 |       /* Allocate 2 got entries and 1 dynamic reloc for R_X86_64_TLSLD
 | 
|---|
| 1696 |          relocs.  */
 | 
|---|
| 1697 |       htab->tls_ld_got.offset = htab->sgot->_raw_size;
 | 
|---|
| 1698 |       htab->sgot->_raw_size += 2 * GOT_ENTRY_SIZE;
 | 
|---|
| 1699 |       htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
 | 
|---|
| 1700 |     }
 | 
|---|
| 1701 |   else
 | 
|---|
| 1702 |     htab->tls_ld_got.offset = -1;
 | 
|---|
| 1703 | 
 | 
|---|
| 1704 |   /* Allocate global sym .plt and .got entries, and space for global
 | 
|---|
| 1705 |      sym dynamic relocs.  */
 | 
|---|
| 1706 |   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 | 
|---|
| 1707 | 
 | 
|---|
| 1708 |   /* We now have determined the sizes of the various dynamic sections.
 | 
|---|
| 1709 |      Allocate memory for them.  */
 | 
|---|
| 1710 |   relocs = FALSE;
 | 
|---|
| 1711 |   for (s = dynobj->sections; s != NULL; s = s->next)
 | 
|---|
| 1712 |     {
 | 
|---|
| 1713 |       if ((s->flags & SEC_LINKER_CREATED) == 0)
 | 
|---|
| 1714 |         continue;
 | 
|---|
| 1715 | 
 | 
|---|
| 1716 |       if (s == htab->splt
 | 
|---|
| 1717 |           || s == htab->sgot
 | 
|---|
| 1718 |           || s == htab->sgotplt)
 | 
|---|
| 1719 |         {
 | 
|---|
| 1720 |           /* Strip this section if we don't need it; see the
 | 
|---|
| 1721 |              comment below.  */
 | 
|---|
| 1722 |         }
 | 
|---|
| 1723 |       else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
 | 
|---|
| 1724 |         {
 | 
|---|
| 1725 |           if (s->_raw_size != 0 && s != htab->srelplt)
 | 
|---|
| 1726 |             relocs = TRUE;
 | 
|---|
| 1727 | 
 | 
|---|
| 1728 |           /* We use the reloc_count field as a counter if we need
 | 
|---|
| 1729 |              to copy relocs into the output file.  */
 | 
|---|
| 1730 |           s->reloc_count = 0;
 | 
|---|
| 1731 |         }
 | 
|---|
| 1732 |       else
 | 
|---|
| 1733 |         {
 | 
|---|
| 1734 |           /* It's not one of our sections, so don't allocate space.  */
 | 
|---|
| 1735 |           continue;
 | 
|---|
| 1736 |         }
 | 
|---|
| 1737 | 
 | 
|---|
| 1738 |       if (s->_raw_size == 0)
 | 
|---|
| 1739 |         {
 | 
|---|
| 1740 |           /* If we don't need this section, strip it from the
 | 
|---|
| 1741 |              output file.  This is mostly to handle .rela.bss and
 | 
|---|
| 1742 |              .rela.plt.  We must create both sections in
 | 
|---|
| 1743 |              create_dynamic_sections, because they must be created
 | 
|---|
| 1744 |              before the linker maps input sections to output
 | 
|---|
| 1745 |              sections.  The linker does that before
 | 
|---|
| 1746 |              adjust_dynamic_symbol is called, and it is that
 | 
|---|
| 1747 |              function which decides whether anything needs to go
 | 
|---|
| 1748 |              into these sections.  */
 | 
|---|
| 1749 | 
 | 
|---|
| 1750 |           _bfd_strip_section_from_output (info, s);
 | 
|---|
| 1751 |           continue;
 | 
|---|
| 1752 |         }
 | 
|---|
| 1753 | 
 | 
|---|
| 1754 |       /* Allocate memory for the section contents.  We use bfd_zalloc
 | 
|---|
| 1755 |          here in case unused entries are not reclaimed before the
 | 
|---|
| 1756 |          section's contents are written out.  This should not happen,
 | 
|---|
| 1757 |          but this way if it does, we get a R_X86_64_NONE reloc instead
 | 
|---|
| 1758 |          of garbage.  */
 | 
|---|
| 1759 |       s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
 | 
|---|
| 1760 |       if (s->contents == NULL)
 | 
|---|
| 1761 |         return FALSE;
 | 
|---|
| 1762 |     }
 | 
|---|
| 1763 | 
 | 
|---|
| 1764 |   if (htab->elf.dynamic_sections_created)
 | 
|---|
| 1765 |     {
 | 
|---|
| 1766 |       /* Add some entries to the .dynamic section.  We fill in the
 | 
|---|
| 1767 |          values later, in elf64_x86_64_finish_dynamic_sections, but we
 | 
|---|
| 1768 |          must add the entries now so that we get the correct size for
 | 
|---|
| 1769 |          the .dynamic section.  The DT_DEBUG entry is filled in by the
 | 
|---|
| 1770 |          dynamic linker and used by the debugger.  */
 | 
|---|
| 1771 | #define add_dynamic_entry(TAG, VAL) \
 | 
|---|
| 1772 |   bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
 | 
|---|
| 1773 | 
 | 
|---|
| 1774 |       if (! info->shared)
 | 
|---|
| 1775 |         {
 | 
|---|
| 1776 |           if (!add_dynamic_entry (DT_DEBUG, 0))
 | 
|---|
| 1777 |             return FALSE;
 | 
|---|
| 1778 |         }
 | 
|---|
| 1779 | 
 | 
|---|
| 1780 |       if (htab->splt->_raw_size != 0)
 | 
|---|
| 1781 |         {
 | 
|---|
| 1782 |           if (!add_dynamic_entry (DT_PLTGOT, 0)
 | 
|---|
| 1783 |               || !add_dynamic_entry (DT_PLTRELSZ, 0)
 | 
|---|
| 1784 |               || !add_dynamic_entry (DT_PLTREL, DT_RELA)
 | 
|---|
| 1785 |               || !add_dynamic_entry (DT_JMPREL, 0))
 | 
|---|
| 1786 |             return FALSE;
 | 
|---|
| 1787 |         }
 | 
|---|
| 1788 | 
 | 
|---|
| 1789 |       if (relocs)
 | 
|---|
| 1790 |         {
 | 
|---|
| 1791 |           if (!add_dynamic_entry (DT_RELA, 0)
 | 
|---|
| 1792 |               || !add_dynamic_entry (DT_RELASZ, 0)
 | 
|---|
| 1793 |               || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
 | 
|---|
| 1794 |             return FALSE;
 | 
|---|
| 1795 | 
 | 
|---|
| 1796 |           /* If any dynamic relocs apply to a read-only section,
 | 
|---|
| 1797 |              then we need a DT_TEXTREL entry.  */
 | 
|---|
| 1798 |           if ((info->flags & DF_TEXTREL) == 0)
 | 
|---|
| 1799 |             elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
 | 
|---|
| 1800 |                                     (PTR) info);
 | 
|---|
| 1801 | 
 | 
|---|
| 1802 |           if ((info->flags & DF_TEXTREL) != 0)
 | 
|---|
| 1803 |             {
 | 
|---|
| 1804 |               if (!add_dynamic_entry (DT_TEXTREL, 0))
 | 
|---|
| 1805 |                 return FALSE;
 | 
|---|
| 1806 |             }
 | 
|---|
| 1807 |         }
 | 
|---|
| 1808 |     }
 | 
|---|
| 1809 | #undef add_dynamic_entry
 | 
|---|
| 1810 | 
 | 
|---|
| 1811 |   return TRUE;
 | 
|---|
| 1812 | }
 | 
|---|
| 1813 | 
 | 
|---|
| 1814 | /* Return the base VMA address which should be subtracted from real addresses
 | 
|---|
| 1815 |    when resolving @dtpoff relocation.
 | 
|---|
| 1816 |    This is PT_TLS segment p_vaddr.  */
 | 
|---|
| 1817 | 
 | 
|---|
| 1818 | static bfd_vma
 | 
|---|
| 1819 | dtpoff_base (info)
 | 
|---|
| 1820 |      struct bfd_link_info *info;
 | 
|---|
| 1821 | {
 | 
|---|
| 1822 |   /* If tls_segment is NULL, we should have signalled an error already.  */
 | 
|---|
| 1823 |   if (elf_hash_table (info)->tls_segment == NULL)
 | 
|---|
| 1824 |     return 0;
 | 
|---|
| 1825 |   return elf_hash_table (info)->tls_segment->start;
 | 
|---|
| 1826 | }
 | 
|---|
| 1827 | 
 | 
|---|
| 1828 | /* Return the relocation value for @tpoff relocation
 | 
|---|
| 1829 |    if STT_TLS virtual address is ADDRESS.  */
 | 
|---|
| 1830 | 
 | 
|---|
| 1831 | static bfd_vma
 | 
|---|
| 1832 | tpoff (info, address)
 | 
|---|
| 1833 |      struct bfd_link_info *info;
 | 
|---|
| 1834 |      bfd_vma address;
 | 
|---|
| 1835 | {
 | 
|---|
| 1836 |   struct elf_link_tls_segment *tls_segment
 | 
|---|
| 1837 |     = elf_hash_table (info)->tls_segment;
 | 
|---|
| 1838 | 
 | 
|---|
| 1839 |   /* If tls_segment is NULL, we should have signalled an error already.  */
 | 
|---|
| 1840 |   if (tls_segment == NULL)
 | 
|---|
| 1841 |     return 0;
 | 
|---|
| 1842 |   return address - align_power (tls_segment->size, tls_segment->align)
 | 
|---|
| 1843 |          - tls_segment->start;
 | 
|---|
| 1844 | }
 | 
|---|
| 1845 | 
 | 
|---|
| 1846 | /* Relocate an x86_64 ELF section.  */
 | 
|---|
| 1847 | 
 | 
|---|
| 1848 | static bfd_boolean
 | 
|---|
| 1849 | elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section,
 | 
|---|
| 1850 |                                contents, relocs, local_syms, local_sections)
 | 
|---|
| 1851 |      bfd *output_bfd;
 | 
|---|
| 1852 |      struct bfd_link_info *info;
 | 
|---|
| 1853 |      bfd *input_bfd;
 | 
|---|
| 1854 |      asection *input_section;
 | 
|---|
| 1855 |      bfd_byte *contents;
 | 
|---|
| 1856 |      Elf_Internal_Rela *relocs;
 | 
|---|
| 1857 |      Elf_Internal_Sym *local_syms;
 | 
|---|
| 1858 |      asection **local_sections;
 | 
|---|
| 1859 | {
 | 
|---|
| 1860 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 1861 |   Elf_Internal_Shdr *symtab_hdr;
 | 
|---|
| 1862 |   struct elf_link_hash_entry **sym_hashes;
 | 
|---|
| 1863 |   bfd_vma *local_got_offsets;
 | 
|---|
| 1864 |   Elf_Internal_Rela *rel;
 | 
|---|
| 1865 |   Elf_Internal_Rela *relend;
 | 
|---|
| 1866 | 
 | 
|---|
| 1867 |   if (info->relocateable)
 | 
|---|
| 1868 |     return TRUE;
 | 
|---|
| 1869 | 
 | 
|---|
| 1870 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 1871 |   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
 | 
|---|
| 1872 |   sym_hashes = elf_sym_hashes (input_bfd);
 | 
|---|
| 1873 |   local_got_offsets = elf_local_got_offsets (input_bfd);
 | 
|---|
| 1874 | 
 | 
|---|
| 1875 |   rel = relocs;
 | 
|---|
| 1876 |   relend = relocs + input_section->reloc_count;
 | 
|---|
| 1877 |   for (; rel < relend; rel++)
 | 
|---|
| 1878 |     {
 | 
|---|
| 1879 |       unsigned int r_type;
 | 
|---|
| 1880 |       reloc_howto_type *howto;
 | 
|---|
| 1881 |       unsigned long r_symndx;
 | 
|---|
| 1882 |       struct elf_link_hash_entry *h;
 | 
|---|
| 1883 |       Elf_Internal_Sym *sym;
 | 
|---|
| 1884 |       asection *sec;
 | 
|---|
| 1885 |       bfd_vma off;
 | 
|---|
| 1886 |       bfd_vma relocation;
 | 
|---|
| 1887 |       bfd_boolean unresolved_reloc;
 | 
|---|
| 1888 |       bfd_reloc_status_type r;
 | 
|---|
| 1889 |       int tls_type;
 | 
|---|
| 1890 | 
 | 
|---|
| 1891 |       r_type = ELF64_R_TYPE (rel->r_info);
 | 
|---|
| 1892 |       if (r_type == (int) R_X86_64_GNU_VTINHERIT
 | 
|---|
| 1893 |           || r_type == (int) R_X86_64_GNU_VTENTRY)
 | 
|---|
| 1894 |         continue;
 | 
|---|
| 1895 | 
 | 
|---|
| 1896 |       if (r_type >= R_X86_64_max)
 | 
|---|
| 1897 |         {
 | 
|---|
| 1898 |           bfd_set_error (bfd_error_bad_value);
 | 
|---|
| 1899 |           return FALSE;
 | 
|---|
| 1900 |         }
 | 
|---|
| 1901 | 
 | 
|---|
| 1902 |       howto = x86_64_elf_howto_table + r_type;
 | 
|---|
| 1903 |       r_symndx = ELF64_R_SYM (rel->r_info);
 | 
|---|
| 1904 |       h = NULL;
 | 
|---|
| 1905 |       sym = NULL;
 | 
|---|
| 1906 |       sec = NULL;
 | 
|---|
| 1907 |       unresolved_reloc = FALSE;
 | 
|---|
| 1908 |       if (r_symndx < symtab_hdr->sh_info)
 | 
|---|
| 1909 |         {
 | 
|---|
| 1910 |           sym = local_syms + r_symndx;
 | 
|---|
| 1911 |           sec = local_sections[r_symndx];
 | 
|---|
| 1912 | 
 | 
|---|
| 1913 |           relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
 | 
|---|
| 1914 |         }
 | 
|---|
| 1915 |       else
 | 
|---|
| 1916 |         {
 | 
|---|
| 1917 |           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 | 
|---|
| 1918 |           while (h->root.type == bfd_link_hash_indirect
 | 
|---|
| 1919 |                  || h->root.type == bfd_link_hash_warning)
 | 
|---|
| 1920 |             h = (struct elf_link_hash_entry *) h->root.u.i.link;
 | 
|---|
| 1921 | 
 | 
|---|
| 1922 |           if (h->root.type == bfd_link_hash_defined
 | 
|---|
| 1923 |               || h->root.type == bfd_link_hash_defweak)
 | 
|---|
| 1924 |             {
 | 
|---|
| 1925 |               sec = h->root.u.def.section;
 | 
|---|
| 1926 |               if (sec->output_section == NULL)
 | 
|---|
| 1927 |                 {
 | 
|---|
| 1928 |                   /* Set a flag that will be cleared later if we find a
 | 
|---|
| 1929 |                      relocation value for this symbol.  output_section
 | 
|---|
| 1930 |                      is typically NULL for symbols satisfied by a shared
 | 
|---|
| 1931 |                      library.  */
 | 
|---|
| 1932 |                   unresolved_reloc = TRUE;
 | 
|---|
| 1933 |                   relocation = 0;
 | 
|---|
| 1934 |                 }
 | 
|---|
| 1935 |               else
 | 
|---|
| 1936 |                 relocation = (h->root.u.def.value
 | 
|---|
| 1937 |                               + sec->output_section->vma
 | 
|---|
| 1938 |                               + sec->output_offset);
 | 
|---|
| 1939 |             }
 | 
|---|
| 1940 |           else if (h->root.type == bfd_link_hash_undefweak)
 | 
|---|
| 1941 |             relocation = 0;
 | 
|---|
| 1942 |           else if (info->shared
 | 
|---|
| 1943 |                    && !info->no_undefined
 | 
|---|
| 1944 |                    && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
 | 
|---|
| 1945 |             relocation = 0;
 | 
|---|
| 1946 |           else
 | 
|---|
| 1947 |             {
 | 
|---|
| 1948 |               if (! ((*info->callbacks->undefined_symbol)
 | 
|---|
| 1949 |                      (info, h->root.root.string, input_bfd,
 | 
|---|
| 1950 |                       input_section, rel->r_offset,
 | 
|---|
| 1951 |                       (!info->shared || info->no_undefined
 | 
|---|
| 1952 |                        || ELF_ST_VISIBILITY (h->other)))))
 | 
|---|
| 1953 |                 return FALSE;
 | 
|---|
| 1954 |               relocation = 0;
 | 
|---|
| 1955 |             }
 | 
|---|
| 1956 |         }
 | 
|---|
| 1957 |       /* When generating a shared object, the relocations handled here are
 | 
|---|
| 1958 |          copied into the output file to be resolved at run time.  */
 | 
|---|
| 1959 |       switch (r_type)
 | 
|---|
| 1960 |         {
 | 
|---|
| 1961 |         case R_X86_64_GOT32:
 | 
|---|
| 1962 |           /* Relocation is to the entry for this symbol in the global
 | 
|---|
| 1963 |              offset table.  */
 | 
|---|
| 1964 |         case R_X86_64_GOTPCREL:
 | 
|---|
| 1965 |           /* Use global offset table as symbol value.  */
 | 
|---|
| 1966 |           if (htab->sgot == NULL)
 | 
|---|
| 1967 |             abort ();
 | 
|---|
| 1968 | 
 | 
|---|
| 1969 |           if (h != NULL)
 | 
|---|
| 1970 |             {
 | 
|---|
| 1971 |               bfd_boolean dyn;
 | 
|---|
| 1972 | 
 | 
|---|
| 1973 |               off = h->got.offset;
 | 
|---|
| 1974 |               dyn = htab->elf.dynamic_sections_created;
 | 
|---|
| 1975 | 
 | 
|---|
| 1976 |               if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
 | 
|---|
| 1977 |                   || (info->shared
 | 
|---|
| 1978 |                       && (info->symbolic
 | 
|---|
| 1979 |                           || h->dynindx == -1
 | 
|---|
| 1980 |                           || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
 | 
|---|
| 1981 |                       && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
 | 
|---|
| 1982 |                 {
 | 
|---|
| 1983 |                   /* This is actually a static link, or it is a -Bsymbolic
 | 
|---|
| 1984 |                      link and the symbol is defined locally, or the symbol
 | 
|---|
| 1985 |                      was forced to be local because of a version file.  We
 | 
|---|
| 1986 |                      must initialize this entry in the global offset table.
 | 
|---|
| 1987 |                      Since the offset must always be a multiple of 8, we
 | 
|---|
| 1988 |                      use the least significant bit to record whether we
 | 
|---|
| 1989 |                      have initialized it already.
 | 
|---|
| 1990 | 
 | 
|---|
| 1991 |                      When doing a dynamic link, we create a .rela.got
 | 
|---|
| 1992 |                      relocation entry to initialize the value.  This is
 | 
|---|
| 1993 |                      done in the finish_dynamic_symbol routine.  */
 | 
|---|
| 1994 |                   if ((off & 1) != 0)
 | 
|---|
| 1995 |                     off &= ~1;
 | 
|---|
| 1996 |                   else
 | 
|---|
| 1997 |                     {
 | 
|---|
| 1998 |                       bfd_put_64 (output_bfd, relocation,
 | 
|---|
| 1999 |                                   htab->sgot->contents + off);
 | 
|---|
| 2000 |                       h->got.offset |= 1;
 | 
|---|
| 2001 |                     }
 | 
|---|
| 2002 |                 }
 | 
|---|
| 2003 |               else
 | 
|---|
| 2004 |                 unresolved_reloc = FALSE;
 | 
|---|
| 2005 |             }
 | 
|---|
| 2006 |           else
 | 
|---|
| 2007 |             {
 | 
|---|
| 2008 |               if (local_got_offsets == NULL)
 | 
|---|
| 2009 |                 abort ();
 | 
|---|
| 2010 | 
 | 
|---|
| 2011 |               off = local_got_offsets[r_symndx];
 | 
|---|
| 2012 | 
 | 
|---|
| 2013 |               /* The offset must always be a multiple of 8.  We use
 | 
|---|
| 2014 |                  the least significant bit to record whether we have
 | 
|---|
| 2015 |                  already generated the necessary reloc.  */
 | 
|---|
| 2016 |               if ((off & 1) != 0)
 | 
|---|
| 2017 |                 off &= ~1;
 | 
|---|
| 2018 |               else
 | 
|---|
| 2019 |                 {
 | 
|---|
| 2020 |                   bfd_put_64 (output_bfd, relocation,
 | 
|---|
| 2021 |                               htab->sgot->contents + off);
 | 
|---|
| 2022 | 
 | 
|---|
| 2023 |                   if (info->shared)
 | 
|---|
| 2024 |                     {
 | 
|---|
| 2025 |                       asection *s;
 | 
|---|
| 2026 |                       Elf_Internal_Rela outrel;
 | 
|---|
| 2027 |                       bfd_byte *loc;
 | 
|---|
| 2028 | 
 | 
|---|
| 2029 |                       /* We need to generate a R_X86_64_RELATIVE reloc
 | 
|---|
| 2030 |                          for the dynamic linker.  */
 | 
|---|
| 2031 |                       s = htab->srelgot;
 | 
|---|
| 2032 |                       if (s == NULL)
 | 
|---|
| 2033 |                         abort ();
 | 
|---|
| 2034 | 
 | 
|---|
| 2035 |                       outrel.r_offset = (htab->sgot->output_section->vma
 | 
|---|
| 2036 |                                          + htab->sgot->output_offset
 | 
|---|
| 2037 |                                          + off);
 | 
|---|
| 2038 |                       outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
 | 
|---|
| 2039 |                       outrel.r_addend = relocation;
 | 
|---|
| 2040 |                       loc = s->contents;
 | 
|---|
| 2041 |                       loc += s->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2042 |                       bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 | 
|---|
| 2043 |                     }
 | 
|---|
| 2044 | 
 | 
|---|
| 2045 |                   local_got_offsets[r_symndx] |= 1;
 | 
|---|
| 2046 |                 }
 | 
|---|
| 2047 |             }
 | 
|---|
| 2048 | 
 | 
|---|
| 2049 |           if (off >= (bfd_vma) -2)
 | 
|---|
| 2050 |             abort ();
 | 
|---|
| 2051 | 
 | 
|---|
| 2052 |           relocation = htab->sgot->output_offset + off;
 | 
|---|
| 2053 |           if (r_type == R_X86_64_GOTPCREL)
 | 
|---|
| 2054 |             relocation += htab->sgot->output_section->vma;
 | 
|---|
| 2055 | 
 | 
|---|
| 2056 |           break;
 | 
|---|
| 2057 | 
 | 
|---|
| 2058 |         case R_X86_64_PLT32:
 | 
|---|
| 2059 |           /* Relocation is to the entry for this symbol in the
 | 
|---|
| 2060 |              procedure linkage table.  */
 | 
|---|
| 2061 | 
 | 
|---|
| 2062 |           /* Resolve a PLT32 reloc against a local symbol directly,
 | 
|---|
| 2063 |              without using the procedure linkage table.  */
 | 
|---|
| 2064 |           if (h == NULL)
 | 
|---|
| 2065 |             break;
 | 
|---|
| 2066 | 
 | 
|---|
| 2067 |           if (h->plt.offset == (bfd_vma) -1
 | 
|---|
| 2068 |               || htab->splt == NULL)
 | 
|---|
| 2069 |             {
 | 
|---|
| 2070 |               /* We didn't make a PLT entry for this symbol.  This
 | 
|---|
| 2071 |                  happens when statically linking PIC code, or when
 | 
|---|
| 2072 |                  using -Bsymbolic.  */
 | 
|---|
| 2073 |               break;
 | 
|---|
| 2074 |             }
 | 
|---|
| 2075 | 
 | 
|---|
| 2076 |           relocation = (htab->splt->output_section->vma
 | 
|---|
| 2077 |                         + htab->splt->output_offset
 | 
|---|
| 2078 |                         + h->plt.offset);
 | 
|---|
| 2079 |           unresolved_reloc = FALSE;
 | 
|---|
| 2080 |           break;
 | 
|---|
| 2081 | 
 | 
|---|
| 2082 |         case R_X86_64_PC8:
 | 
|---|
| 2083 |         case R_X86_64_PC16:
 | 
|---|
| 2084 |         case R_X86_64_PC32:
 | 
|---|
| 2085 |         case R_X86_64_8:
 | 
|---|
| 2086 |         case R_X86_64_16:
 | 
|---|
| 2087 |         case R_X86_64_32:
 | 
|---|
| 2088 |         case R_X86_64_64:
 | 
|---|
| 2089 |           /* FIXME: The ABI says the linker should make sure the value is
 | 
|---|
| 2090 |              the same when it's zeroextended to 64 bit.  */
 | 
|---|
| 2091 | 
 | 
|---|
| 2092 |           /* r_symndx will be zero only for relocs against symbols
 | 
|---|
| 2093 |              from removed linkonce sections, or sections discarded by
 | 
|---|
| 2094 |              a linker script.  */
 | 
|---|
| 2095 |           if (r_symndx == 0
 | 
|---|
| 2096 |               || (input_section->flags & SEC_ALLOC) == 0)
 | 
|---|
| 2097 |             break;
 | 
|---|
| 2098 | 
 | 
|---|
| 2099 |           if ((info->shared
 | 
|---|
| 2100 |                && ((r_type != R_X86_64_PC8
 | 
|---|
| 2101 |                     && r_type != R_X86_64_PC16
 | 
|---|
| 2102 |                     && r_type != R_X86_64_PC32)
 | 
|---|
| 2103 |                    || (h != NULL
 | 
|---|
| 2104 |                        && h->dynindx != -1
 | 
|---|
| 2105 |                        && (! info->symbolic
 | 
|---|
| 2106 |                            || (h->elf_link_hash_flags
 | 
|---|
| 2107 |                                & ELF_LINK_HASH_DEF_REGULAR) == 0))))
 | 
|---|
| 2108 |               || (ELIMINATE_COPY_RELOCS
 | 
|---|
| 2109 |                   && !info->shared
 | 
|---|
| 2110 |                   && h != NULL
 | 
|---|
| 2111 |                   && h->dynindx != -1
 | 
|---|
| 2112 |                   && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0
 | 
|---|
| 2113 |                   && (((h->elf_link_hash_flags
 | 
|---|
| 2114 |                         & ELF_LINK_HASH_DEF_DYNAMIC) != 0
 | 
|---|
| 2115 |                        && (h->elf_link_hash_flags
 | 
|---|
| 2116 |                            & ELF_LINK_HASH_DEF_REGULAR) == 0)
 | 
|---|
| 2117 |                       || h->root.type == bfd_link_hash_undefweak
 | 
|---|
| 2118 |                       || h->root.type == bfd_link_hash_undefined)))
 | 
|---|
| 2119 |             {
 | 
|---|
| 2120 |               Elf_Internal_Rela outrel;
 | 
|---|
| 2121 |               bfd_byte *loc;
 | 
|---|
| 2122 |               bfd_boolean skip, relocate;
 | 
|---|
| 2123 |               asection *sreloc;
 | 
|---|
| 2124 | 
 | 
|---|
| 2125 |               /* When generating a shared object, these relocations
 | 
|---|
| 2126 |                  are copied into the output file to be resolved at run
 | 
|---|
| 2127 |                  time.  */
 | 
|---|
| 2128 |               skip = FALSE;
 | 
|---|
| 2129 |               relocate = FALSE;
 | 
|---|
| 2130 | 
 | 
|---|
| 2131 |               outrel.r_offset =
 | 
|---|
| 2132 |                 _bfd_elf_section_offset (output_bfd, info, input_section,
 | 
|---|
| 2133 |                                          rel->r_offset);
 | 
|---|
| 2134 |               if (outrel.r_offset == (bfd_vma) -1)
 | 
|---|
| 2135 |                 skip = TRUE;
 | 
|---|
| 2136 |               else if (outrel.r_offset == (bfd_vma) -2)
 | 
|---|
| 2137 |                 skip = TRUE, relocate = TRUE;
 | 
|---|
| 2138 | 
 | 
|---|
| 2139 |               outrel.r_offset += (input_section->output_section->vma
 | 
|---|
| 2140 |                                   + input_section->output_offset);
 | 
|---|
| 2141 | 
 | 
|---|
| 2142 |               if (skip)
 | 
|---|
| 2143 |                 memset (&outrel, 0, sizeof outrel);
 | 
|---|
| 2144 | 
 | 
|---|
| 2145 |               /* h->dynindx may be -1 if this symbol was marked to
 | 
|---|
| 2146 |                  become local.  */
 | 
|---|
| 2147 |               else if (h != NULL
 | 
|---|
| 2148 |                        && h->dynindx != -1
 | 
|---|
| 2149 |                        && (r_type == R_X86_64_PC8
 | 
|---|
| 2150 |                            || r_type == R_X86_64_PC16
 | 
|---|
| 2151 |                            || r_type == R_X86_64_PC32
 | 
|---|
| 2152 |                            || !info->shared
 | 
|---|
| 2153 |                            || !info->symbolic
 | 
|---|
| 2154 |                            || (h->elf_link_hash_flags
 | 
|---|
| 2155 |                                & ELF_LINK_HASH_DEF_REGULAR) == 0))
 | 
|---|
| 2156 |                 {
 | 
|---|
| 2157 |                   outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
 | 
|---|
| 2158 |                   outrel.r_addend = rel->r_addend;
 | 
|---|
| 2159 |                 }
 | 
|---|
| 2160 |               else
 | 
|---|
| 2161 |                 {
 | 
|---|
| 2162 |                   /* This symbol is local, or marked to become local.  */
 | 
|---|
| 2163 |                   if (r_type == R_X86_64_64)
 | 
|---|
| 2164 |                     {
 | 
|---|
| 2165 |                       relocate = TRUE;
 | 
|---|
| 2166 |                       outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
 | 
|---|
| 2167 |                       outrel.r_addend = relocation + rel->r_addend;
 | 
|---|
| 2168 |                     }
 | 
|---|
| 2169 |                   else
 | 
|---|
| 2170 |                     {
 | 
|---|
| 2171 |                       long sindx;
 | 
|---|
| 2172 | 
 | 
|---|
| 2173 |                       if (h == NULL)
 | 
|---|
| 2174 |                         sec = local_sections[r_symndx];
 | 
|---|
| 2175 |                       else
 | 
|---|
| 2176 |                         {
 | 
|---|
| 2177 |                           BFD_ASSERT (h->root.type == bfd_link_hash_defined
 | 
|---|
| 2178 |                                       || (h->root.type
 | 
|---|
| 2179 |                                           == bfd_link_hash_defweak));
 | 
|---|
| 2180 |                           sec = h->root.u.def.section;
 | 
|---|
| 2181 |                         }
 | 
|---|
| 2182 |                       if (sec != NULL && bfd_is_abs_section (sec))
 | 
|---|
| 2183 |                         sindx = 0;
 | 
|---|
| 2184 |                       else if (sec == NULL || sec->owner == NULL)
 | 
|---|
| 2185 |                         {
 | 
|---|
| 2186 |                           bfd_set_error (bfd_error_bad_value);
 | 
|---|
| 2187 |                           return FALSE;
 | 
|---|
| 2188 |                         }
 | 
|---|
| 2189 |                       else
 | 
|---|
| 2190 |                         {
 | 
|---|
| 2191 |                           asection *osec;
 | 
|---|
| 2192 | 
 | 
|---|
| 2193 |                           osec = sec->output_section;
 | 
|---|
| 2194 |                           sindx = elf_section_data (osec)->dynindx;
 | 
|---|
| 2195 |                           BFD_ASSERT (sindx > 0);
 | 
|---|
| 2196 |                         }
 | 
|---|
| 2197 | 
 | 
|---|
| 2198 |                       outrel.r_info = ELF64_R_INFO (sindx, r_type);
 | 
|---|
| 2199 |                       outrel.r_addend = relocation + rel->r_addend;
 | 
|---|
| 2200 |                     }
 | 
|---|
| 2201 |                 }
 | 
|---|
| 2202 | 
 | 
|---|
| 2203 |               sreloc = elf_section_data (input_section)->sreloc;
 | 
|---|
| 2204 |               if (sreloc == NULL)
 | 
|---|
| 2205 |                 abort ();
 | 
|---|
| 2206 | 
 | 
|---|
| 2207 |               loc = sreloc->contents;
 | 
|---|
| 2208 |               loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2209 |               bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 | 
|---|
| 2210 | 
 | 
|---|
| 2211 |               /* If this reloc is against an external symbol, we do
 | 
|---|
| 2212 |                  not want to fiddle with the addend.  Otherwise, we
 | 
|---|
| 2213 |                  need to include the symbol value so that it becomes
 | 
|---|
| 2214 |                  an addend for the dynamic reloc.  */
 | 
|---|
| 2215 |               if (! relocate)
 | 
|---|
| 2216 |                 continue;
 | 
|---|
| 2217 |             }
 | 
|---|
| 2218 | 
 | 
|---|
| 2219 |           break;
 | 
|---|
| 2220 | 
 | 
|---|
| 2221 |         case R_X86_64_TLSGD:
 | 
|---|
| 2222 |         case R_X86_64_GOTTPOFF:
 | 
|---|
| 2223 |           r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 | 
|---|
| 2224 |           tls_type = GOT_UNKNOWN;
 | 
|---|
| 2225 |           if (h == NULL && local_got_offsets)
 | 
|---|
| 2226 |             tls_type = elf64_x86_64_local_got_tls_type (input_bfd) [r_symndx];
 | 
|---|
| 2227 |           else if (h != NULL)
 | 
|---|
| 2228 |             {
 | 
|---|
| 2229 |               tls_type = elf64_x86_64_hash_entry (h)->tls_type;
 | 
|---|
| 2230 |               if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
 | 
|---|
| 2231 |                 r_type = R_X86_64_TPOFF32;
 | 
|---|
| 2232 |             }
 | 
|---|
| 2233 |           if (r_type == R_X86_64_TLSGD)
 | 
|---|
| 2234 |             {
 | 
|---|
| 2235 |               if (tls_type == GOT_TLS_IE)
 | 
|---|
| 2236 |                 r_type = R_X86_64_GOTTPOFF;
 | 
|---|
| 2237 |             }
 | 
|---|
| 2238 | 
 | 
|---|
| 2239 |           if (r_type == R_X86_64_TPOFF32)
 | 
|---|
| 2240 |             {
 | 
|---|
| 2241 |               BFD_ASSERT (! unresolved_reloc);
 | 
|---|
| 2242 |               if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
 | 
|---|
| 2243 |                 {
 | 
|---|
| 2244 |                   unsigned int i;
 | 
|---|
| 2245 |                   static unsigned char tlsgd[8]
 | 
|---|
| 2246 |                     = { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 };
 | 
|---|
| 2247 | 
 | 
|---|
| 2248 |                   /* GD->LE transition.
 | 
|---|
| 2249 |                      .byte 0x66; leaq foo@tlsgd(%rip), %rdi
 | 
|---|
| 2250 |                      .word 0x6666; rex64; call __tls_get_addr@plt
 | 
|---|
| 2251 |                      Change it into:
 | 
|---|
| 2252 |                      movq %fs:0, %rax
 | 
|---|
| 2253 |                      leaq foo@tpoff(%rax), %rax */
 | 
|---|
| 2254 |                   BFD_ASSERT (rel->r_offset >= 4);
 | 
|---|
| 2255 |                   for (i = 0; i < 4; i++)
 | 
|---|
| 2256 |                     BFD_ASSERT (bfd_get_8 (input_bfd,
 | 
|---|
| 2257 |                                            contents + rel->r_offset - 4 + i)
 | 
|---|
| 2258 |                                 == tlsgd[i]);
 | 
|---|
| 2259 |                   BFD_ASSERT (rel->r_offset + 12 <= input_section->_raw_size);
 | 
|---|
| 2260 |                   for (i = 0; i < 4; i++)
 | 
|---|
| 2261 |                     BFD_ASSERT (bfd_get_8 (input_bfd,
 | 
|---|
| 2262 |                                            contents + rel->r_offset + 4 + i)
 | 
|---|
| 2263 |                                 == tlsgd[i+4]);
 | 
|---|
| 2264 |                   BFD_ASSERT (rel + 1 < relend);
 | 
|---|
| 2265 |                   BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
 | 
|---|
| 2266 |                   memcpy (contents + rel->r_offset - 4,
 | 
|---|
| 2267 |                           "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0",
 | 
|---|
| 2268 |                           16);
 | 
|---|
| 2269 |                   bfd_put_32 (output_bfd, tpoff (info, relocation),
 | 
|---|
| 2270 |                               contents + rel->r_offset + 8);
 | 
|---|
| 2271 |                   /* Skip R_X86_64_PLT32.  */
 | 
|---|
| 2272 |                   rel++;
 | 
|---|
| 2273 |                   continue;
 | 
|---|
| 2274 |                 }
 | 
|---|
| 2275 |               else
 | 
|---|
| 2276 |                 {
 | 
|---|
| 2277 |                   unsigned int val, type, reg;
 | 
|---|
| 2278 | 
 | 
|---|
| 2279 |                   /* IE->LE transition:
 | 
|---|
| 2280 |                      Originally it can be one of:
 | 
|---|
| 2281 |                      movq foo@gottpoff(%rip), %reg
 | 
|---|
| 2282 |                      addq foo@gottpoff(%rip), %reg
 | 
|---|
| 2283 |                      We change it into:
 | 
|---|
| 2284 |                      movq $foo, %reg
 | 
|---|
| 2285 |                      leaq foo(%reg), %reg
 | 
|---|
| 2286 |                      addq $foo, %reg.  */
 | 
|---|
| 2287 |                   BFD_ASSERT (rel->r_offset >= 3);
 | 
|---|
| 2288 |                   val = bfd_get_8 (input_bfd, contents + rel->r_offset - 3);
 | 
|---|
| 2289 |                   BFD_ASSERT (val == 0x48 || val == 0x4c);
 | 
|---|
| 2290 |                   type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
 | 
|---|
| 2291 |                   BFD_ASSERT (type == 0x8b || type == 0x03);
 | 
|---|
| 2292 |                   reg = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
 | 
|---|
| 2293 |                   BFD_ASSERT ((reg & 0xc7) == 5);
 | 
|---|
| 2294 |                   reg >>= 3;
 | 
|---|
| 2295 |                   BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size);
 | 
|---|
| 2296 |                   if (type == 0x8b)
 | 
|---|
| 2297 |                     {
 | 
|---|
| 2298 |                       /* movq */
 | 
|---|
| 2299 |                       if (val == 0x4c)
 | 
|---|
| 2300 |                         bfd_put_8 (output_bfd, 0x49,
 | 
|---|
| 2301 |                                    contents + rel->r_offset - 3);
 | 
|---|
| 2302 |                       bfd_put_8 (output_bfd, 0xc7,
 | 
|---|
| 2303 |                                  contents + rel->r_offset - 2);
 | 
|---|
| 2304 |                       bfd_put_8 (output_bfd, 0xc0 | reg,
 | 
|---|
| 2305 |                                  contents + rel->r_offset - 1);
 | 
|---|
| 2306 |                     }
 | 
|---|
| 2307 |                   else if (reg == 4)
 | 
|---|
| 2308 |                     {
 | 
|---|
| 2309 |                       /* addq -> addq - addressing with %rsp/%r12 is
 | 
|---|
| 2310 |                          special  */
 | 
|---|
| 2311 |                       if (val == 0x4c)
 | 
|---|
| 2312 |                         bfd_put_8 (output_bfd, 0x49,
 | 
|---|
| 2313 |                                    contents + rel->r_offset - 3);
 | 
|---|
| 2314 |                       bfd_put_8 (output_bfd, 0x81,
 | 
|---|
| 2315 |                                  contents + rel->r_offset - 2);
 | 
|---|
| 2316 |                       bfd_put_8 (output_bfd, 0xc0 | reg,
 | 
|---|
| 2317 |                                  contents + rel->r_offset - 1);
 | 
|---|
| 2318 |                     }
 | 
|---|
| 2319 |                   else
 | 
|---|
| 2320 |                     {
 | 
|---|
| 2321 |                       /* addq -> leaq */
 | 
|---|
| 2322 |                       if (val == 0x4c)
 | 
|---|
| 2323 |                         bfd_put_8 (output_bfd, 0x4d,
 | 
|---|
| 2324 |                                    contents + rel->r_offset - 3);
 | 
|---|
| 2325 |                       bfd_put_8 (output_bfd, 0x8d,
 | 
|---|
| 2326 |                                  contents + rel->r_offset - 2);
 | 
|---|
| 2327 |                       bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3),
 | 
|---|
| 2328 |                                  contents + rel->r_offset - 1);
 | 
|---|
| 2329 |                     }
 | 
|---|
| 2330 |                   bfd_put_32 (output_bfd, tpoff (info, relocation),
 | 
|---|
| 2331 |                               contents + rel->r_offset);
 | 
|---|
| 2332 |                   continue;
 | 
|---|
| 2333 |                 }
 | 
|---|
| 2334 |             }
 | 
|---|
| 2335 | 
 | 
|---|
| 2336 |           if (htab->sgot == NULL)
 | 
|---|
| 2337 |             abort ();
 | 
|---|
| 2338 | 
 | 
|---|
| 2339 |           if (h != NULL)
 | 
|---|
| 2340 |             off = h->got.offset;
 | 
|---|
| 2341 |           else
 | 
|---|
| 2342 |             {
 | 
|---|
| 2343 |               if (local_got_offsets == NULL)
 | 
|---|
| 2344 |                 abort ();
 | 
|---|
| 2345 | 
 | 
|---|
| 2346 |               off = local_got_offsets[r_symndx];
 | 
|---|
| 2347 |             }
 | 
|---|
| 2348 | 
 | 
|---|
| 2349 |           if ((off & 1) != 0)
 | 
|---|
| 2350 |             off &= ~1;
 | 
|---|
| 2351 |           else
 | 
|---|
| 2352 |             {
 | 
|---|
| 2353 |               Elf_Internal_Rela outrel;
 | 
|---|
| 2354 |               bfd_byte *loc;
 | 
|---|
| 2355 |               int dr_type, indx;
 | 
|---|
| 2356 | 
 | 
|---|
| 2357 |               if (htab->srelgot == NULL)
 | 
|---|
| 2358 |                 abort ();
 | 
|---|
| 2359 | 
 | 
|---|
| 2360 |               outrel.r_offset = (htab->sgot->output_section->vma
 | 
|---|
| 2361 |                                  + htab->sgot->output_offset + off);
 | 
|---|
| 2362 | 
 | 
|---|
| 2363 |               indx = h && h->dynindx != -1 ? h->dynindx : 0;
 | 
|---|
| 2364 |               if (r_type == R_X86_64_TLSGD)
 | 
|---|
| 2365 |                 dr_type = R_X86_64_DTPMOD64;
 | 
|---|
| 2366 |               else
 | 
|---|
| 2367 |                 dr_type = R_X86_64_TPOFF64;
 | 
|---|
| 2368 | 
 | 
|---|
| 2369 |               bfd_put_64 (output_bfd, 0, htab->sgot->contents + off);
 | 
|---|
| 2370 |               outrel.r_addend = 0;
 | 
|---|
| 2371 |               if (dr_type == R_X86_64_TPOFF64 && indx == 0)
 | 
|---|
| 2372 |                 outrel.r_addend = relocation - dtpoff_base (info);
 | 
|---|
| 2373 |               outrel.r_info = ELF64_R_INFO (indx, dr_type);
 | 
|---|
| 2374 | 
 | 
|---|
| 2375 |               loc = htab->srelgot->contents;
 | 
|---|
| 2376 |               loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2377 |               bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 | 
|---|
| 2378 | 
 | 
|---|
| 2379 |               if (r_type == R_X86_64_TLSGD)
 | 
|---|
| 2380 |                 {
 | 
|---|
| 2381 |                   if (indx == 0)
 | 
|---|
| 2382 |                     {
 | 
|---|
| 2383 |                       BFD_ASSERT (! unresolved_reloc);
 | 
|---|
| 2384 |                       bfd_put_64 (output_bfd,
 | 
|---|
| 2385 |                                   relocation - dtpoff_base (info),
 | 
|---|
| 2386 |                                   htab->sgot->contents + off + GOT_ENTRY_SIZE);
 | 
|---|
| 2387 |                     }
 | 
|---|
| 2388 |                   else
 | 
|---|
| 2389 |                     {
 | 
|---|
| 2390 |                       bfd_put_64 (output_bfd, 0,
 | 
|---|
| 2391 |                                   htab->sgot->contents + off + GOT_ENTRY_SIZE);
 | 
|---|
| 2392 |                       outrel.r_info = ELF64_R_INFO (indx,
 | 
|---|
| 2393 |                                                     R_X86_64_DTPOFF64);
 | 
|---|
| 2394 |                       outrel.r_offset += GOT_ENTRY_SIZE;
 | 
|---|
| 2395 |                       htab->srelgot->reloc_count++;
 | 
|---|
| 2396 |                       loc += sizeof (Elf64_External_Rela);
 | 
|---|
| 2397 |                       bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 | 
|---|
| 2398 |                     }
 | 
|---|
| 2399 |                 }
 | 
|---|
| 2400 | 
 | 
|---|
| 2401 |               if (h != NULL)
 | 
|---|
| 2402 |                 h->got.offset |= 1;
 | 
|---|
| 2403 |               else
 | 
|---|
| 2404 |                 local_got_offsets[r_symndx] |= 1;
 | 
|---|
| 2405 |             }
 | 
|---|
| 2406 | 
 | 
|---|
| 2407 |           if (off >= (bfd_vma) -2)
 | 
|---|
| 2408 |             abort ();
 | 
|---|
| 2409 |           if (r_type == ELF64_R_TYPE (rel->r_info))
 | 
|---|
| 2410 |             {
 | 
|---|
| 2411 |               relocation = htab->sgot->output_section->vma
 | 
|---|
| 2412 |                            + htab->sgot->output_offset + off;
 | 
|---|
| 2413 |               unresolved_reloc = FALSE;
 | 
|---|
| 2414 |             }
 | 
|---|
| 2415 |           else
 | 
|---|
| 2416 |             {
 | 
|---|
| 2417 |               unsigned int i;
 | 
|---|
| 2418 |               static unsigned char tlsgd[8]
 | 
|---|
| 2419 |                 = { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 };
 | 
|---|
| 2420 | 
 | 
|---|
| 2421 |               /* GD->IE transition.
 | 
|---|
| 2422 |                  .byte 0x66; leaq foo@tlsgd(%rip), %rdi
 | 
|---|
| 2423 |                  .word 0x6666; rex64; call __tls_get_addr@plt
 | 
|---|
| 2424 |                  Change it into:
 | 
|---|
| 2425 |                  movq %fs:0, %rax
 | 
|---|
| 2426 |                  addq foo@gottpoff(%rip), %rax */
 | 
|---|
| 2427 |               BFD_ASSERT (rel->r_offset >= 4);
 | 
|---|
| 2428 |               for (i = 0; i < 4; i++)
 | 
|---|
| 2429 |                 BFD_ASSERT (bfd_get_8 (input_bfd,
 | 
|---|
| 2430 |                                        contents + rel->r_offset - 4 + i)
 | 
|---|
| 2431 |                             == tlsgd[i]);
 | 
|---|
| 2432 |               BFD_ASSERT (rel->r_offset + 12 <= input_section->_raw_size);
 | 
|---|
| 2433 |               for (i = 0; i < 4; i++)
 | 
|---|
| 2434 |                 BFD_ASSERT (bfd_get_8 (input_bfd,
 | 
|---|
| 2435 |                                        contents + rel->r_offset + 4 + i)
 | 
|---|
| 2436 |                             == tlsgd[i+4]);
 | 
|---|
| 2437 |               BFD_ASSERT (rel + 1 < relend);
 | 
|---|
| 2438 |               BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
 | 
|---|
| 2439 |               memcpy (contents + rel->r_offset - 4,
 | 
|---|
| 2440 |                       "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0",
 | 
|---|
| 2441 |                       16);
 | 
|---|
| 2442 | 
 | 
|---|
| 2443 |               relocation = (htab->sgot->output_section->vma
 | 
|---|
| 2444 |                             + htab->sgot->output_offset + off
 | 
|---|
| 2445 |                             - rel->r_offset
 | 
|---|
| 2446 |                             - input_section->output_section->vma
 | 
|---|
| 2447 |                             - input_section->output_offset
 | 
|---|
| 2448 |                             - 12);
 | 
|---|
| 2449 |               bfd_put_32 (output_bfd, relocation,
 | 
|---|
| 2450 |                           contents + rel->r_offset + 8);
 | 
|---|
| 2451 |               /* Skip R_X86_64_PLT32.  */
 | 
|---|
| 2452 |               rel++;
 | 
|---|
| 2453 |               continue;
 | 
|---|
| 2454 |             }
 | 
|---|
| 2455 |           break;
 | 
|---|
| 2456 | 
 | 
|---|
| 2457 |         case R_X86_64_TLSLD:
 | 
|---|
| 2458 |           if (! info->shared)
 | 
|---|
| 2459 |             {
 | 
|---|
| 2460 |               /* LD->LE transition:
 | 
|---|
| 2461 |                  Ensure it is:
 | 
|---|
| 2462 |                  leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt.
 | 
|---|
| 2463 |                  We change it into:
 | 
|---|
| 2464 |                  .word 0x6666; .byte 0x66; movl %fs:0, %rax.  */
 | 
|---|
| 2465 |               BFD_ASSERT (rel->r_offset >= 3);
 | 
|---|
| 2466 |               BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 3)
 | 
|---|
| 2467 |                           == 0x48);
 | 
|---|
| 2468 |               BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 2)
 | 
|---|
| 2469 |                           == 0x8d);
 | 
|---|
| 2470 |               BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 1)
 | 
|---|
| 2471 |                           == 0x3d);
 | 
|---|
| 2472 |               BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
 | 
|---|
| 2473 |               BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
 | 
|---|
| 2474 |                           == 0xe8);
 | 
|---|
| 2475 |               BFD_ASSERT (rel + 1 < relend);
 | 
|---|
| 2476 |               BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32);
 | 
|---|
| 2477 |               memcpy (contents + rel->r_offset - 3,
 | 
|---|
| 2478 |                       "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12);
 | 
|---|
| 2479 |               /* Skip R_X86_64_PLT32.  */
 | 
|---|
| 2480 |               rel++;
 | 
|---|
| 2481 |               continue;
 | 
|---|
| 2482 |             }
 | 
|---|
| 2483 | 
 | 
|---|
| 2484 |           if (htab->sgot == NULL)
 | 
|---|
| 2485 |             abort ();
 | 
|---|
| 2486 | 
 | 
|---|
| 2487 |           off = htab->tls_ld_got.offset;
 | 
|---|
| 2488 |           if (off & 1)
 | 
|---|
| 2489 |             off &= ~1;
 | 
|---|
| 2490 |           else
 | 
|---|
| 2491 |             {
 | 
|---|
| 2492 |               Elf_Internal_Rela outrel;
 | 
|---|
| 2493 |               bfd_byte *loc;
 | 
|---|
| 2494 | 
 | 
|---|
| 2495 |               if (htab->srelgot == NULL)
 | 
|---|
| 2496 |                 abort ();
 | 
|---|
| 2497 | 
 | 
|---|
| 2498 |               outrel.r_offset = (htab->sgot->output_section->vma
 | 
|---|
| 2499 |                                  + htab->sgot->output_offset + off);
 | 
|---|
| 2500 | 
 | 
|---|
| 2501 |               bfd_put_64 (output_bfd, 0,
 | 
|---|
| 2502 |                           htab->sgot->contents + off);
 | 
|---|
| 2503 |               bfd_put_64 (output_bfd, 0,
 | 
|---|
| 2504 |                           htab->sgot->contents + off + GOT_ENTRY_SIZE);
 | 
|---|
| 2505 |               outrel.r_info = ELF64_R_INFO (0, R_X86_64_DTPMOD64);
 | 
|---|
| 2506 |               outrel.r_addend = 0;
 | 
|---|
| 2507 |               loc = htab->srelgot->contents;
 | 
|---|
| 2508 |               loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2509 |               bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 | 
|---|
| 2510 |               htab->tls_ld_got.offset |= 1;
 | 
|---|
| 2511 |             }
 | 
|---|
| 2512 |           relocation = htab->sgot->output_section->vma
 | 
|---|
| 2513 |                        + htab->sgot->output_offset + off;
 | 
|---|
| 2514 |           unresolved_reloc = FALSE;
 | 
|---|
| 2515 |           break;
 | 
|---|
| 2516 | 
 | 
|---|
| 2517 |         case R_X86_64_DTPOFF32:
 | 
|---|
| 2518 |           if (info->shared || (input_section->flags & SEC_CODE) == 0)
 | 
|---|
| 2519 |             relocation -= dtpoff_base (info);
 | 
|---|
| 2520 |           else
 | 
|---|
| 2521 |             relocation = tpoff (info, relocation);
 | 
|---|
| 2522 |           break;
 | 
|---|
| 2523 | 
 | 
|---|
| 2524 |         case R_X86_64_TPOFF32:
 | 
|---|
| 2525 |           BFD_ASSERT (! info->shared);
 | 
|---|
| 2526 |           relocation = tpoff (info, relocation);
 | 
|---|
| 2527 |           break;
 | 
|---|
| 2528 | 
 | 
|---|
| 2529 |         default:
 | 
|---|
| 2530 |           break;
 | 
|---|
| 2531 |         }
 | 
|---|
| 2532 | 
 | 
|---|
| 2533 |       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
 | 
|---|
| 2534 |          because such sections are not SEC_ALLOC and thus ld.so will
 | 
|---|
| 2535 |          not process them.  */
 | 
|---|
| 2536 |       if (unresolved_reloc
 | 
|---|
| 2537 |           && !((input_section->flags & SEC_DEBUGGING) != 0
 | 
|---|
| 2538 |                && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
 | 
|---|
| 2539 |         (*_bfd_error_handler)
 | 
|---|
| 2540 |           (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
 | 
|---|
| 2541 |            bfd_archive_filename (input_bfd),
 | 
|---|
| 2542 |            bfd_get_section_name (input_bfd, input_section),
 | 
|---|
| 2543 |            (long) rel->r_offset,
 | 
|---|
| 2544 |            h->root.root.string);
 | 
|---|
| 2545 | 
 | 
|---|
| 2546 |       r = _bfd_final_link_relocate (howto, input_bfd, input_section,
 | 
|---|
| 2547 |                                     contents, rel->r_offset,
 | 
|---|
| 2548 |                                     relocation, rel->r_addend);
 | 
|---|
| 2549 | 
 | 
|---|
| 2550 |       if (r != bfd_reloc_ok)
 | 
|---|
| 2551 |         {
 | 
|---|
| 2552 |           const char *name;
 | 
|---|
| 2553 | 
 | 
|---|
| 2554 |           if (h != NULL)
 | 
|---|
| 2555 |             name = h->root.root.string;
 | 
|---|
| 2556 |           else
 | 
|---|
| 2557 |             {
 | 
|---|
| 2558 |               name = bfd_elf_string_from_elf_section (input_bfd,
 | 
|---|
| 2559 |                                                       symtab_hdr->sh_link,
 | 
|---|
| 2560 |                                                       sym->st_name);
 | 
|---|
| 2561 |               if (name == NULL)
 | 
|---|
| 2562 |                 return FALSE;
 | 
|---|
| 2563 |               if (*name == '\0')
 | 
|---|
| 2564 |                 name = bfd_section_name (input_bfd, sec);
 | 
|---|
| 2565 |             }
 | 
|---|
| 2566 | 
 | 
|---|
| 2567 |           if (r == bfd_reloc_overflow)
 | 
|---|
| 2568 |             {
 | 
|---|
| 2569 | 
 | 
|---|
| 2570 |               if (! ((*info->callbacks->reloc_overflow)
 | 
|---|
| 2571 |                      (info, name, howto->name, (bfd_vma) 0,
 | 
|---|
| 2572 |                       input_bfd, input_section, rel->r_offset)))
 | 
|---|
| 2573 |                 return FALSE;
 | 
|---|
| 2574 |             }
 | 
|---|
| 2575 |           else
 | 
|---|
| 2576 |             {
 | 
|---|
| 2577 |               (*_bfd_error_handler)
 | 
|---|
| 2578 |                 (_("%s(%s+0x%lx): reloc against `%s': error %d"),
 | 
|---|
| 2579 |                  bfd_archive_filename (input_bfd),
 | 
|---|
| 2580 |                  bfd_get_section_name (input_bfd, input_section),
 | 
|---|
| 2581 |                  (long) rel->r_offset, name, (int) r);
 | 
|---|
| 2582 |               return FALSE;
 | 
|---|
| 2583 |             }
 | 
|---|
| 2584 |         }
 | 
|---|
| 2585 |     }
 | 
|---|
| 2586 | 
 | 
|---|
| 2587 |   return TRUE;
 | 
|---|
| 2588 | }
 | 
|---|
| 2589 | 
 | 
|---|
| 2590 | /* Finish up dynamic symbol handling.  We set the contents of various
 | 
|---|
| 2591 |    dynamic sections here.  */
 | 
|---|
| 2592 | 
 | 
|---|
| 2593 | static bfd_boolean
 | 
|---|
| 2594 | elf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym)
 | 
|---|
| 2595 |      bfd *output_bfd;
 | 
|---|
| 2596 |      struct bfd_link_info *info;
 | 
|---|
| 2597 |      struct elf_link_hash_entry *h;
 | 
|---|
| 2598 |      Elf_Internal_Sym *sym;
 | 
|---|
| 2599 | {
 | 
|---|
| 2600 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 2601 | 
 | 
|---|
| 2602 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 2603 | 
 | 
|---|
| 2604 |   if (h->plt.offset != (bfd_vma) -1)
 | 
|---|
| 2605 |     {
 | 
|---|
| 2606 |       bfd_vma plt_index;
 | 
|---|
| 2607 |       bfd_vma got_offset;
 | 
|---|
| 2608 |       Elf_Internal_Rela rela;
 | 
|---|
| 2609 |       bfd_byte *loc;
 | 
|---|
| 2610 | 
 | 
|---|
| 2611 |       /* This symbol has an entry in the procedure linkage table.  Set
 | 
|---|
| 2612 |          it up.  */
 | 
|---|
| 2613 |       if (h->dynindx == -1
 | 
|---|
| 2614 |           || htab->splt == NULL
 | 
|---|
| 2615 |           || htab->sgotplt == NULL
 | 
|---|
| 2616 |           || htab->srelplt == NULL)
 | 
|---|
| 2617 |         abort ();
 | 
|---|
| 2618 | 
 | 
|---|
| 2619 |       /* Get the index in the procedure linkage table which
 | 
|---|
| 2620 |          corresponds to this symbol.  This is the index of this symbol
 | 
|---|
| 2621 |          in all the symbols for which we are making plt entries.  The
 | 
|---|
| 2622 |          first entry in the procedure linkage table is reserved.  */
 | 
|---|
| 2623 |       plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
 | 
|---|
| 2624 | 
 | 
|---|
| 2625 |       /* Get the offset into the .got table of the entry that
 | 
|---|
| 2626 |          corresponds to this function.  Each .got entry is GOT_ENTRY_SIZE
 | 
|---|
| 2627 |          bytes. The first three are reserved for the dynamic linker.  */
 | 
|---|
| 2628 |       got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
 | 
|---|
| 2629 | 
 | 
|---|
| 2630 |       /* Fill in the entry in the procedure linkage table.  */
 | 
|---|
| 2631 |       memcpy (htab->splt->contents + h->plt.offset, elf64_x86_64_plt_entry,
 | 
|---|
| 2632 |               PLT_ENTRY_SIZE);
 | 
|---|
| 2633 | 
 | 
|---|
| 2634 |       /* Insert the relocation positions of the plt section.  The magic
 | 
|---|
| 2635 |          numbers at the end of the statements are the positions of the
 | 
|---|
| 2636 |          relocations in the plt section.  */
 | 
|---|
| 2637 |       /* Put offset for jmp *name@GOTPCREL(%rip), since the
 | 
|---|
| 2638 |          instruction uses 6 bytes, subtract this value.  */
 | 
|---|
| 2639 |       bfd_put_32 (output_bfd,
 | 
|---|
| 2640 |                       (htab->sgotplt->output_section->vma
 | 
|---|
| 2641 |                        + htab->sgotplt->output_offset
 | 
|---|
| 2642 |                        + got_offset
 | 
|---|
| 2643 |                        - htab->splt->output_section->vma
 | 
|---|
| 2644 |                        - htab->splt->output_offset
 | 
|---|
| 2645 |                        - h->plt.offset
 | 
|---|
| 2646 |                        - 6),
 | 
|---|
| 2647 |                   htab->splt->contents + h->plt.offset + 2);
 | 
|---|
| 2648 |       /* Put relocation index.  */
 | 
|---|
| 2649 |       bfd_put_32 (output_bfd, plt_index,
 | 
|---|
| 2650 |                   htab->splt->contents + h->plt.offset + 7);
 | 
|---|
| 2651 |       /* Put offset for jmp .PLT0.  */
 | 
|---|
| 2652 |       bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
 | 
|---|
| 2653 |                   htab->splt->contents + h->plt.offset + 12);
 | 
|---|
| 2654 | 
 | 
|---|
| 2655 |       /* Fill in the entry in the global offset table, initially this
 | 
|---|
| 2656 |          points to the pushq instruction in the PLT which is at offset 6.  */
 | 
|---|
| 2657 |       bfd_put_64 (output_bfd, (htab->splt->output_section->vma
 | 
|---|
| 2658 |                                + htab->splt->output_offset
 | 
|---|
| 2659 |                                + h->plt.offset + 6),
 | 
|---|
| 2660 |                   htab->sgotplt->contents + got_offset);
 | 
|---|
| 2661 | 
 | 
|---|
| 2662 |       /* Fill in the entry in the .rela.plt section.  */
 | 
|---|
| 2663 |       rela.r_offset = (htab->sgotplt->output_section->vma
 | 
|---|
| 2664 |                        + htab->sgotplt->output_offset
 | 
|---|
| 2665 |                        + got_offset);
 | 
|---|
| 2666 |       rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT);
 | 
|---|
| 2667 |       rela.r_addend = 0;
 | 
|---|
| 2668 |       loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela);
 | 
|---|
| 2669 |       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
 | 
|---|
| 2670 | 
 | 
|---|
| 2671 |       if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
 | 
|---|
| 2672 |         {
 | 
|---|
| 2673 |           /* Mark the symbol as undefined, rather than as defined in
 | 
|---|
| 2674 |              the .plt section.  Leave the value alone.  This is a clue
 | 
|---|
| 2675 |              for the dynamic linker, to make function pointer
 | 
|---|
| 2676 |              comparisons work between an application and shared
 | 
|---|
| 2677 |              library.  */
 | 
|---|
| 2678 |           sym->st_shndx = SHN_UNDEF;
 | 
|---|
| 2679 |         }
 | 
|---|
| 2680 |     }
 | 
|---|
| 2681 | 
 | 
|---|
| 2682 |   if (h->got.offset != (bfd_vma) -1
 | 
|---|
| 2683 |       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
 | 
|---|
| 2684 |       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
 | 
|---|
| 2685 |     {
 | 
|---|
| 2686 |       Elf_Internal_Rela rela;
 | 
|---|
| 2687 |       bfd_byte *loc;
 | 
|---|
| 2688 | 
 | 
|---|
| 2689 |       /* This symbol has an entry in the global offset table.  Set it
 | 
|---|
| 2690 |          up.  */
 | 
|---|
| 2691 |       if (htab->sgot == NULL || htab->srelgot == NULL)
 | 
|---|
| 2692 |         abort ();
 | 
|---|
| 2693 | 
 | 
|---|
| 2694 |       rela.r_offset = (htab->sgot->output_section->vma
 | 
|---|
| 2695 |                        + htab->sgot->output_offset
 | 
|---|
| 2696 |                        + (h->got.offset &~ (bfd_vma) 1));
 | 
|---|
| 2697 | 
 | 
|---|
| 2698 |       /* If this is a static link, or it is a -Bsymbolic link and the
 | 
|---|
| 2699 |          symbol is defined locally or was forced to be local because
 | 
|---|
| 2700 |          of a version file, we just want to emit a RELATIVE reloc.
 | 
|---|
| 2701 |          The entry in the global offset table will already have been
 | 
|---|
| 2702 |          initialized in the relocate_section function.  */
 | 
|---|
| 2703 |       if (info->shared
 | 
|---|
| 2704 |           && (info->symbolic
 | 
|---|
| 2705 |               || h->dynindx == -1
 | 
|---|
| 2706 |               || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
 | 
|---|
| 2707 |           && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
 | 
|---|
| 2708 |         {
 | 
|---|
| 2709 |           BFD_ASSERT((h->got.offset & 1) != 0);
 | 
|---|
| 2710 |           rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
 | 
|---|
| 2711 |           rela.r_addend = (h->root.u.def.value
 | 
|---|
| 2712 |                            + h->root.u.def.section->output_section->vma
 | 
|---|
| 2713 |                            + h->root.u.def.section->output_offset);
 | 
|---|
| 2714 |         }
 | 
|---|
| 2715 |       else
 | 
|---|
| 2716 |         {
 | 
|---|
| 2717 |           BFD_ASSERT((h->got.offset & 1) == 0);
 | 
|---|
| 2718 |           bfd_put_64 (output_bfd, (bfd_vma) 0,
 | 
|---|
| 2719 |                       htab->sgot->contents + h->got.offset);
 | 
|---|
| 2720 |           rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT);
 | 
|---|
| 2721 |           rela.r_addend = 0;
 | 
|---|
| 2722 |         }
 | 
|---|
| 2723 | 
 | 
|---|
| 2724 |       loc = htab->srelgot->contents;
 | 
|---|
| 2725 |       loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2726 |       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
 | 
|---|
| 2727 |     }
 | 
|---|
| 2728 | 
 | 
|---|
| 2729 |   if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
 | 
|---|
| 2730 |     {
 | 
|---|
| 2731 |       Elf_Internal_Rela rela;
 | 
|---|
| 2732 |       bfd_byte *loc;
 | 
|---|
| 2733 | 
 | 
|---|
| 2734 |       /* This symbol needs a copy reloc.  Set it up.  */
 | 
|---|
| 2735 | 
 | 
|---|
| 2736 |       if (h->dynindx == -1
 | 
|---|
| 2737 |           || (h->root.type != bfd_link_hash_defined
 | 
|---|
| 2738 |               && h->root.type != bfd_link_hash_defweak)
 | 
|---|
| 2739 |           || htab->srelbss == NULL)
 | 
|---|
| 2740 |         abort ();
 | 
|---|
| 2741 | 
 | 
|---|
| 2742 |       rela.r_offset = (h->root.u.def.value
 | 
|---|
| 2743 |                        + h->root.u.def.section->output_section->vma
 | 
|---|
| 2744 |                        + h->root.u.def.section->output_offset);
 | 
|---|
| 2745 |       rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY);
 | 
|---|
| 2746 |       rela.r_addend = 0;
 | 
|---|
| 2747 |       loc = htab->srelbss->contents;
 | 
|---|
| 2748 |       loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
 | 
|---|
| 2749 |       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
 | 
|---|
| 2750 |     }
 | 
|---|
| 2751 | 
 | 
|---|
| 2752 |   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
 | 
|---|
| 2753 |   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
 | 
|---|
| 2754 |       || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
 | 
|---|
| 2755 |     sym->st_shndx = SHN_ABS;
 | 
|---|
| 2756 | 
 | 
|---|
| 2757 |   return TRUE;
 | 
|---|
| 2758 | }
 | 
|---|
| 2759 | 
 | 
|---|
| 2760 | /* Used to decide how to sort relocs in an optimal manner for the
 | 
|---|
| 2761 |    dynamic linker, before writing them out.  */
 | 
|---|
| 2762 | 
 | 
|---|
| 2763 | static enum elf_reloc_type_class
 | 
|---|
| 2764 | elf64_x86_64_reloc_type_class (rela)
 | 
|---|
| 2765 |      const Elf_Internal_Rela *rela;
 | 
|---|
| 2766 | {
 | 
|---|
| 2767 |   switch ((int) ELF64_R_TYPE (rela->r_info))
 | 
|---|
| 2768 |     {
 | 
|---|
| 2769 |     case R_X86_64_RELATIVE:
 | 
|---|
| 2770 |       return reloc_class_relative;
 | 
|---|
| 2771 |     case R_X86_64_JUMP_SLOT:
 | 
|---|
| 2772 |       return reloc_class_plt;
 | 
|---|
| 2773 |     case R_X86_64_COPY:
 | 
|---|
| 2774 |       return reloc_class_copy;
 | 
|---|
| 2775 |     default:
 | 
|---|
| 2776 |       return reloc_class_normal;
 | 
|---|
| 2777 |     }
 | 
|---|
| 2778 | }
 | 
|---|
| 2779 | 
 | 
|---|
| 2780 | /* Finish up the dynamic sections.  */
 | 
|---|
| 2781 | 
 | 
|---|
| 2782 | static bfd_boolean
 | 
|---|
| 2783 | elf64_x86_64_finish_dynamic_sections (output_bfd, info)
 | 
|---|
| 2784 |      bfd *output_bfd;
 | 
|---|
| 2785 |      struct bfd_link_info *info;
 | 
|---|
| 2786 | {
 | 
|---|
| 2787 |   struct elf64_x86_64_link_hash_table *htab;
 | 
|---|
| 2788 |   bfd *dynobj;
 | 
|---|
| 2789 |   asection *sdyn;
 | 
|---|
| 2790 | 
 | 
|---|
| 2791 |   htab = elf64_x86_64_hash_table (info);
 | 
|---|
| 2792 |   dynobj = htab->elf.dynobj;
 | 
|---|
| 2793 |   sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
 | 
|---|
| 2794 | 
 | 
|---|
| 2795 |   if (htab->elf.dynamic_sections_created)
 | 
|---|
| 2796 |     {
 | 
|---|
| 2797 |       Elf64_External_Dyn *dyncon, *dynconend;
 | 
|---|
| 2798 | 
 | 
|---|
| 2799 |       if (sdyn == NULL || htab->sgot == NULL)
 | 
|---|
| 2800 |         abort ();
 | 
|---|
| 2801 | 
 | 
|---|
| 2802 |       dyncon = (Elf64_External_Dyn *) sdyn->contents;
 | 
|---|
| 2803 |       dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
 | 
|---|
| 2804 |       for (; dyncon < dynconend; dyncon++)
 | 
|---|
| 2805 |         {
 | 
|---|
| 2806 |           Elf_Internal_Dyn dyn;
 | 
|---|
| 2807 |           asection *s;
 | 
|---|
| 2808 | 
 | 
|---|
| 2809 |           bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
 | 
|---|
| 2810 | 
 | 
|---|
| 2811 |           switch (dyn.d_tag)
 | 
|---|
| 2812 |             {
 | 
|---|
| 2813 |             default:
 | 
|---|
| 2814 |               continue;
 | 
|---|
| 2815 | 
 | 
|---|
| 2816 |             case DT_PLTGOT:
 | 
|---|
| 2817 |               dyn.d_un.d_ptr = htab->sgot->output_section->vma;
 | 
|---|
| 2818 |               break;
 | 
|---|
| 2819 | 
 | 
|---|
| 2820 |             case DT_JMPREL:
 | 
|---|
| 2821 |               dyn.d_un.d_ptr = htab->srelplt->output_section->vma;
 | 
|---|
| 2822 |               break;
 | 
|---|
| 2823 | 
 | 
|---|
| 2824 |             case DT_PLTRELSZ:
 | 
|---|
| 2825 |               s = htab->srelplt->output_section;
 | 
|---|
| 2826 |               if (s->_cooked_size != 0)
 | 
|---|
| 2827 |                 dyn.d_un.d_val = s->_cooked_size;
 | 
|---|
| 2828 |               else
 | 
|---|
| 2829 |                 dyn.d_un.d_val = s->_raw_size;
 | 
|---|
| 2830 |               break;
 | 
|---|
| 2831 | 
 | 
|---|
| 2832 |             case DT_RELASZ:
 | 
|---|
| 2833 |               /* The procedure linkage table relocs (DT_JMPREL) should
 | 
|---|
| 2834 |                  not be included in the overall relocs (DT_RELA).
 | 
|---|
| 2835 |                  Therefore, we override the DT_RELASZ entry here to
 | 
|---|
| 2836 |                  make it not include the JMPREL relocs.  Since the
 | 
|---|
| 2837 |                  linker script arranges for .rela.plt to follow all
 | 
|---|
| 2838 |                  other relocation sections, we don't have to worry
 | 
|---|
| 2839 |                  about changing the DT_RELA entry.  */
 | 
|---|
| 2840 |               if (htab->srelplt != NULL)
 | 
|---|
| 2841 |                 {
 | 
|---|
| 2842 |                   s = htab->srelplt->output_section;
 | 
|---|
| 2843 |                   if (s->_cooked_size != 0)
 | 
|---|
| 2844 |                     dyn.d_un.d_val -= s->_cooked_size;
 | 
|---|
| 2845 |                   else
 | 
|---|
| 2846 |                     dyn.d_un.d_val -= s->_raw_size;
 | 
|---|
| 2847 |                 }
 | 
|---|
| 2848 |               break;
 | 
|---|
| 2849 |             }
 | 
|---|
| 2850 | 
 | 
|---|
| 2851 |           bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
 | 
|---|
| 2852 |         }
 | 
|---|
| 2853 | 
 | 
|---|
| 2854 |       /* Fill in the special first entry in the procedure linkage table.  */
 | 
|---|
| 2855 |       if (htab->splt && htab->splt->_raw_size > 0)
 | 
|---|
| 2856 |         {
 | 
|---|
| 2857 |           /* Fill in the first entry in the procedure linkage table.  */
 | 
|---|
| 2858 |           memcpy (htab->splt->contents, elf64_x86_64_plt0_entry,
 | 
|---|
| 2859 |                   PLT_ENTRY_SIZE);
 | 
|---|
| 2860 |           /* Add offset for pushq GOT+8(%rip), since the instruction
 | 
|---|
| 2861 |              uses 6 bytes subtract this value.  */
 | 
|---|
| 2862 |           bfd_put_32 (output_bfd,
 | 
|---|
| 2863 |                       (htab->sgotplt->output_section->vma
 | 
|---|
| 2864 |                        + htab->sgotplt->output_offset
 | 
|---|
| 2865 |                        + 8
 | 
|---|
| 2866 |                        - htab->splt->output_section->vma
 | 
|---|
| 2867 |                        - htab->splt->output_offset
 | 
|---|
| 2868 |                        - 6),
 | 
|---|
| 2869 |                       htab->splt->contents + 2);
 | 
|---|
| 2870 |           /* Add offset for jmp *GOT+16(%rip). The 12 is the offset to
 | 
|---|
| 2871 |              the end of the instruction.  */
 | 
|---|
| 2872 |           bfd_put_32 (output_bfd,
 | 
|---|
| 2873 |                       (htab->sgotplt->output_section->vma
 | 
|---|
| 2874 |                        + htab->sgotplt->output_offset
 | 
|---|
| 2875 |                        + 16
 | 
|---|
| 2876 |                        - htab->splt->output_section->vma
 | 
|---|
| 2877 |                        - htab->splt->output_offset
 | 
|---|
| 2878 |                        - 12),
 | 
|---|
| 2879 |                       htab->splt->contents + 8);
 | 
|---|
| 2880 | 
 | 
|---|
| 2881 |           elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize =
 | 
|---|
| 2882 |             PLT_ENTRY_SIZE;
 | 
|---|
| 2883 |         }
 | 
|---|
| 2884 |     }
 | 
|---|
| 2885 | 
 | 
|---|
| 2886 |   if (htab->sgotplt)
 | 
|---|
| 2887 |     {
 | 
|---|
| 2888 |       /* Fill in the first three entries in the global offset table.  */
 | 
|---|
| 2889 |       if (htab->sgotplt->_raw_size > 0)
 | 
|---|
| 2890 |         {
 | 
|---|
| 2891 |           /* Set the first entry in the global offset table to the address of
 | 
|---|
| 2892 |              the dynamic section.  */
 | 
|---|
| 2893 |           if (sdyn == NULL)
 | 
|---|
| 2894 |             bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents);
 | 
|---|
| 2895 |           else
 | 
|---|
| 2896 |             bfd_put_64 (output_bfd,
 | 
|---|
| 2897 |                         sdyn->output_section->vma + sdyn->output_offset,
 | 
|---|
| 2898 |                         htab->sgotplt->contents);
 | 
|---|
| 2899 |           /* Write GOT[1] and GOT[2], needed for the dynamic linker.  */
 | 
|---|
| 2900 |           bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + GOT_ENTRY_SIZE);
 | 
|---|
| 2901 |           bfd_put_64 (output_bfd, (bfd_vma) 0, htab->sgotplt->contents + GOT_ENTRY_SIZE*2);
 | 
|---|
| 2902 |         }
 | 
|---|
| 2903 | 
 | 
|---|
| 2904 |       elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize =
 | 
|---|
| 2905 |         GOT_ENTRY_SIZE;
 | 
|---|
| 2906 |     }
 | 
|---|
| 2907 | 
 | 
|---|
| 2908 |   return TRUE;
 | 
|---|
| 2909 | }
 | 
|---|
| 2910 | 
 | 
|---|
| 2911 | 
 | 
|---|
| 2912 | #define TARGET_LITTLE_SYM                   bfd_elf64_x86_64_vec
 | 
|---|
| 2913 | #define TARGET_LITTLE_NAME                  "elf64-x86-64"
 | 
|---|
| 2914 | #define ELF_ARCH                            bfd_arch_i386
 | 
|---|
| 2915 | #define ELF_MACHINE_CODE                    EM_X86_64
 | 
|---|
| 2916 | #define ELF_MAXPAGESIZE                     0x100000
 | 
|---|
| 2917 | 
 | 
|---|
| 2918 | #define elf_backend_can_gc_sections         1
 | 
|---|
| 2919 | #define elf_backend_can_refcount            1
 | 
|---|
| 2920 | #define elf_backend_want_got_plt            1
 | 
|---|
| 2921 | #define elf_backend_plt_readonly            1
 | 
|---|
| 2922 | #define elf_backend_want_plt_sym            0
 | 
|---|
| 2923 | #define elf_backend_got_header_size         (GOT_ENTRY_SIZE*3)
 | 
|---|
| 2924 | #define elf_backend_plt_header_size         PLT_ENTRY_SIZE
 | 
|---|
| 2925 | #define elf_backend_rela_normal             1
 | 
|---|
| 2926 | 
 | 
|---|
| 2927 | #define elf_info_to_howto                   elf64_x86_64_info_to_howto
 | 
|---|
| 2928 | 
 | 
|---|
| 2929 | #define bfd_elf64_bfd_link_hash_table_create \
 | 
|---|
| 2930 |   elf64_x86_64_link_hash_table_create
 | 
|---|
| 2931 | #define bfd_elf64_bfd_reloc_type_lookup     elf64_x86_64_reloc_type_lookup
 | 
|---|
| 2932 | 
 | 
|---|
| 2933 | #define elf_backend_adjust_dynamic_symbol   elf64_x86_64_adjust_dynamic_symbol
 | 
|---|
| 2934 | #define elf_backend_check_relocs            elf64_x86_64_check_relocs
 | 
|---|
| 2935 | #define elf_backend_copy_indirect_symbol    elf64_x86_64_copy_indirect_symbol
 | 
|---|
| 2936 | #define elf_backend_create_dynamic_sections elf64_x86_64_create_dynamic_sections
 | 
|---|
| 2937 | #define elf_backend_finish_dynamic_sections elf64_x86_64_finish_dynamic_sections
 | 
|---|
| 2938 | #define elf_backend_finish_dynamic_symbol   elf64_x86_64_finish_dynamic_symbol
 | 
|---|
| 2939 | #define elf_backend_gc_mark_hook            elf64_x86_64_gc_mark_hook
 | 
|---|
| 2940 | #define elf_backend_gc_sweep_hook           elf64_x86_64_gc_sweep_hook
 | 
|---|
| 2941 | #define elf_backend_grok_prstatus           elf64_x86_64_grok_prstatus
 | 
|---|
| 2942 | #define elf_backend_grok_psinfo             elf64_x86_64_grok_psinfo
 | 
|---|
| 2943 | #define elf_backend_reloc_type_class        elf64_x86_64_reloc_type_class
 | 
|---|
| 2944 | #define elf_backend_relocate_section        elf64_x86_64_relocate_section
 | 
|---|
| 2945 | #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
 | 
|---|
| 2946 | #define elf_backend_object_p                elf64_x86_64_elf_object_p
 | 
|---|
| 2947 | #define bfd_elf64_mkobject                  elf64_x86_64_mkobject
 | 
|---|
| 2948 | 
 | 
|---|
| 2949 | #include "elf64-target.h"
 | 
|---|