1 |
/* X86-64 specific support for 64-bit ELF |
/* X86-64 specific support for 64-bit ELF |
2 |
Copyright 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright 2000, 2001, 2002, 2003, 2004, 2005 |
3 |
|
Free Software Foundation, Inc. |
4 |
Contributed by Jan Hubicka <jh@suse.cz>. |
Contributed by Jan Hubicka <jh@suse.cz>. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
7 |
|
|
8 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
9 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
10 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
11 |
(at your option) any later version. |
(at your option) any later version. |
12 |
|
|
13 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
14 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 |
GNU General Public License for more details. |
GNU General Public License for more details. |
17 |
|
|
18 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
19 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
20 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
21 |
|
|
22 |
#include "bfd.h" |
#include "bfd.h" |
23 |
#include "sysdep.h" |
#include "sysdep.h" |
27 |
|
|
28 |
#include "elf/x86-64.h" |
#include "elf/x86-64.h" |
29 |
|
|
|
/* We use only the RELA entries. */ |
|
|
#define USE_RELA 1 |
|
|
|
|
30 |
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ |
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ |
31 |
#define MINUS_ONE (~ (bfd_vma) 0) |
#define MINUS_ONE (~ (bfd_vma) 0) |
32 |
|
|
35 |
special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset. */ |
special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset. */ |
36 |
static reloc_howto_type x86_64_elf_howto_table[] = |
static reloc_howto_type x86_64_elf_howto_table[] = |
37 |
{ |
{ |
38 |
HOWTO(R_X86_64_NONE, 0, 0, 0, false, 0, complain_overflow_dont, |
HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont, |
39 |
bfd_elf_generic_reloc, "R_X86_64_NONE", false, 0x00000000, 0x00000000, |
bfd_elf_generic_reloc, "R_X86_64_NONE", FALSE, 0x00000000, 0x00000000, |
40 |
false), |
FALSE), |
41 |
HOWTO(R_X86_64_64, 0, 4, 64, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
42 |
bfd_elf_generic_reloc, "R_X86_64_64", false, MINUS_ONE, MINUS_ONE, |
bfd_elf_generic_reloc, "R_X86_64_64", FALSE, MINUS_ONE, MINUS_ONE, |
43 |
false), |
FALSE), |
44 |
HOWTO(R_X86_64_PC32, 0, 4, 32, true, 0, complain_overflow_signed, |
HOWTO(R_X86_64_PC32, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
45 |
bfd_elf_generic_reloc, "R_X86_64_PC32", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_PC32", FALSE, 0xffffffff, 0xffffffff, |
46 |
true), |
TRUE), |
47 |
HOWTO(R_X86_64_GOT32, 0, 4, 32, false, 0, complain_overflow_signed, |
HOWTO(R_X86_64_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_signed, |
48 |
bfd_elf_generic_reloc, "R_X86_64_GOT32", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_GOT32", FALSE, 0xffffffff, 0xffffffff, |
49 |
false), |
FALSE), |
50 |
HOWTO(R_X86_64_PLT32, 0, 4, 32, true, 0, complain_overflow_signed, |
HOWTO(R_X86_64_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
51 |
bfd_elf_generic_reloc, "R_X86_64_PLT32", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_PLT32", FALSE, 0xffffffff, 0xffffffff, |
52 |
true), |
TRUE), |
53 |
HOWTO(R_X86_64_COPY, 0, 4, 32, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
54 |
bfd_elf_generic_reloc, "R_X86_64_COPY", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_COPY", FALSE, 0xffffffff, 0xffffffff, |
55 |
false), |
FALSE), |
56 |
HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_GLOB_DAT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
57 |
bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", false, MINUS_ONE, |
bfd_elf_generic_reloc, "R_X86_64_GLOB_DAT", FALSE, MINUS_ONE, |
58 |
MINUS_ONE, false), |
MINUS_ONE, FALSE), |
59 |
HOWTO(R_X86_64_JUMP_SLOT, 0, 4, 64, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_JUMP_SLOT, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
60 |
bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", false, MINUS_ONE, |
bfd_elf_generic_reloc, "R_X86_64_JUMP_SLOT", FALSE, MINUS_ONE, |
61 |
MINUS_ONE, false), |
MINUS_ONE, FALSE), |
62 |
HOWTO(R_X86_64_RELATIVE, 0, 4, 64, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_RELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
63 |
bfd_elf_generic_reloc, "R_X86_64_RELATIVE", false, MINUS_ONE, |
bfd_elf_generic_reloc, "R_X86_64_RELATIVE", FALSE, MINUS_ONE, |
64 |
MINUS_ONE, false), |
MINUS_ONE, FALSE), |
65 |
HOWTO(R_X86_64_GOTPCREL, 0, 4, 32, true,0 , complain_overflow_signed, |
HOWTO(R_X86_64_GOTPCREL, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
66 |
bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", false, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_GOTPCREL", FALSE, 0xffffffff, |
67 |
0xffffffff, true), |
0xffffffff, TRUE), |
68 |
HOWTO(R_X86_64_32, 0, 4, 32, false, 0, complain_overflow_unsigned, |
HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned, |
69 |
bfd_elf_generic_reloc, "R_X86_64_32", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff, |
70 |
false), |
FALSE), |
71 |
HOWTO(R_X86_64_32S, 0, 4, 32, false, 0, complain_overflow_signed, |
HOWTO(R_X86_64_32S, 0, 2, 32, FALSE, 0, complain_overflow_signed, |
72 |
bfd_elf_generic_reloc, "R_X86_64_32S", false, 0xffffffff, 0xffffffff, |
bfd_elf_generic_reloc, "R_X86_64_32S", FALSE, 0xffffffff, 0xffffffff, |
73 |
false), |
FALSE), |
74 |
HOWTO(R_X86_64_16, 0, 1, 16, false, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, |
75 |
bfd_elf_generic_reloc, "R_X86_64_16", false, 0xffff, 0xffff, false), |
bfd_elf_generic_reloc, "R_X86_64_16", FALSE, 0xffff, 0xffff, FALSE), |
76 |
HOWTO(R_X86_64_PC16,0, 1, 16, true, 0, complain_overflow_bitfield, |
HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_bitfield, |
77 |
bfd_elf_generic_reloc, "R_X86_64_PC16", false, 0xffff, 0xffff, true), |
bfd_elf_generic_reloc, "R_X86_64_PC16", FALSE, 0xffff, 0xffff, TRUE), |
78 |
HOWTO(R_X86_64_8, 0, 0, 8, false, 0, complain_overflow_signed, |
HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_signed, |
79 |
bfd_elf_generic_reloc, "R_X86_64_8", false, 0xff, 0xff, false), |
bfd_elf_generic_reloc, "R_X86_64_8", FALSE, 0xff, 0xff, FALSE), |
80 |
HOWTO(R_X86_64_PC8, 0, 0, 8, true, 0, complain_overflow_signed, |
HOWTO(R_X86_64_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, |
81 |
bfd_elf_generic_reloc, "R_X86_64_PC8", false, 0xff, 0xff, true), |
bfd_elf_generic_reloc, "R_X86_64_PC8", FALSE, 0xff, 0xff, TRUE), |
82 |
|
HOWTO(R_X86_64_DTPMOD64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
83 |
|
bfd_elf_generic_reloc, "R_X86_64_DTPMOD64", FALSE, MINUS_ONE, |
84 |
|
MINUS_ONE, FALSE), |
85 |
|
HOWTO(R_X86_64_DTPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
86 |
|
bfd_elf_generic_reloc, "R_X86_64_DTPOFF64", FALSE, MINUS_ONE, |
87 |
|
MINUS_ONE, FALSE), |
88 |
|
HOWTO(R_X86_64_TPOFF64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, |
89 |
|
bfd_elf_generic_reloc, "R_X86_64_TPOFF64", FALSE, MINUS_ONE, |
90 |
|
MINUS_ONE, FALSE), |
91 |
|
HOWTO(R_X86_64_TLSGD, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
92 |
|
bfd_elf_generic_reloc, "R_X86_64_TLSGD", FALSE, 0xffffffff, |
93 |
|
0xffffffff, TRUE), |
94 |
|
HOWTO(R_X86_64_TLSLD, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
95 |
|
bfd_elf_generic_reloc, "R_X86_64_TLSLD", FALSE, 0xffffffff, |
96 |
|
0xffffffff, TRUE), |
97 |
|
HOWTO(R_X86_64_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, |
98 |
|
bfd_elf_generic_reloc, "R_X86_64_DTPOFF32", FALSE, 0xffffffff, |
99 |
|
0xffffffff, FALSE), |
100 |
|
HOWTO(R_X86_64_GOTTPOFF, 0, 2, 32, TRUE, 0, complain_overflow_signed, |
101 |
|
bfd_elf_generic_reloc, "R_X86_64_GOTTPOFF", FALSE, 0xffffffff, |
102 |
|
0xffffffff, TRUE), |
103 |
|
HOWTO(R_X86_64_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed, |
104 |
|
bfd_elf_generic_reloc, "R_X86_64_TPOFF32", FALSE, 0xffffffff, |
105 |
|
0xffffffff, FALSE), |
106 |
|
|
107 |
/* GNU extension to record C++ vtable hierarchy. */ |
/* GNU extension to record C++ vtable hierarchy. */ |
108 |
HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, false, 0, complain_overflow_dont, |
HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, FALSE, 0, complain_overflow_dont, |
109 |
NULL, "R_X86_64_GNU_VTINHERIT", false, 0, 0, false), |
NULL, "R_X86_64_GNU_VTINHERIT", FALSE, 0, 0, FALSE), |
110 |
|
|
111 |
/* GNU extension to record C++ vtable member usage. */ |
/* GNU extension to record C++ vtable member usage. */ |
112 |
HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, false, 0, complain_overflow_dont, |
HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, FALSE, 0, complain_overflow_dont, |
113 |
_bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", false, 0, 0, |
_bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", FALSE, 0, 0, |
114 |
false) |
FALSE) |
115 |
}; |
}; |
116 |
|
|
117 |
/* Map BFD relocs to the x86_64 elf relocs. */ |
/* Map BFD relocs to the x86_64 elf relocs. */ |
139 |
{ BFD_RELOC_16_PCREL, R_X86_64_PC16, }, |
{ BFD_RELOC_16_PCREL, R_X86_64_PC16, }, |
140 |
{ BFD_RELOC_8, R_X86_64_8, }, |
{ BFD_RELOC_8, R_X86_64_8, }, |
141 |
{ BFD_RELOC_8_PCREL, R_X86_64_PC8, }, |
{ BFD_RELOC_8_PCREL, R_X86_64_PC8, }, |
142 |
|
{ BFD_RELOC_X86_64_DTPMOD64, R_X86_64_DTPMOD64, }, |
143 |
|
{ BFD_RELOC_X86_64_DTPOFF64, R_X86_64_DTPOFF64, }, |
144 |
|
{ BFD_RELOC_X86_64_TPOFF64, R_X86_64_TPOFF64, }, |
145 |
|
{ BFD_RELOC_X86_64_TLSGD, R_X86_64_TLSGD, }, |
146 |
|
{ BFD_RELOC_X86_64_TLSLD, R_X86_64_TLSLD, }, |
147 |
|
{ BFD_RELOC_X86_64_DTPOFF32, R_X86_64_DTPOFF32, }, |
148 |
|
{ BFD_RELOC_X86_64_GOTTPOFF, R_X86_64_GOTTPOFF, }, |
149 |
|
{ BFD_RELOC_X86_64_TPOFF32, R_X86_64_TPOFF32, }, |
150 |
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, |
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, |
151 |
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, |
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, |
152 |
}; |
}; |
153 |
|
|
|
static reloc_howto_type *elf64_x86_64_reloc_type_lookup |
|
|
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
|
|
static void elf64_x86_64_info_to_howto |
|
|
PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *)); |
|
|
static boolean elf64_x86_64_grok_prstatus |
|
|
PARAMS ((bfd *, Elf_Internal_Note *)); |
|
|
static boolean elf64_x86_64_grok_psinfo |
|
|
PARAMS ((bfd *, Elf_Internal_Note *)); |
|
|
static struct bfd_link_hash_table *elf64_x86_64_link_hash_table_create |
|
|
PARAMS ((bfd *)); |
|
|
static boolean elf64_x86_64_elf_object_p PARAMS ((bfd *abfd)); |
|
|
static boolean create_got_section |
|
|
PARAMS((bfd *, struct bfd_link_info *)); |
|
|
static boolean elf64_x86_64_create_dynamic_sections |
|
|
PARAMS((bfd *, struct bfd_link_info *)); |
|
|
static void elf64_x86_64_copy_indirect_symbol |
|
|
PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *)); |
|
|
static boolean elf64_x86_64_check_relocs |
|
|
PARAMS ((bfd *, struct bfd_link_info *, asection *sec, |
|
|
const Elf_Internal_Rela *)); |
|
|
static asection *elf64_x86_64_gc_mark_hook |
|
|
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
|
|
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
|
|
|
|
|
static boolean elf64_x86_64_gc_sweep_hook |
|
|
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
|
|
const Elf_Internal_Rela *)); |
|
|
|
|
|
static struct bfd_hash_entry *link_hash_newfunc |
|
|
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
|
|
static boolean elf64_x86_64_adjust_dynamic_symbol |
|
|
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); |
|
|
|
|
|
static boolean allocate_dynrelocs |
|
|
PARAMS ((struct elf_link_hash_entry *, PTR)); |
|
|
static boolean readonly_dynrelocs |
|
|
PARAMS ((struct elf_link_hash_entry *, PTR)); |
|
|
static boolean elf64_x86_64_size_dynamic_sections |
|
|
PARAMS ((bfd *, struct bfd_link_info *)); |
|
|
static boolean elf64_x86_64_relocate_section |
|
|
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
|
|
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
|
|
static boolean elf64_x86_64_finish_dynamic_symbol |
|
|
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, |
|
|
Elf_Internal_Sym *sym)); |
|
|
static boolean elf64_x86_64_finish_dynamic_sections |
|
|
PARAMS ((bfd *, struct bfd_link_info *)); |
|
|
static enum elf_reloc_type_class elf64_x86_64_reloc_type_class |
|
|
PARAMS ((const Elf_Internal_Rela *)); |
|
154 |
|
|
155 |
/* Given a BFD reloc type, return a HOWTO structure. */ |
/* Given a BFD reloc type, return a HOWTO structure. */ |
156 |
static reloc_howto_type * |
static reloc_howto_type * |
157 |
elf64_x86_64_reloc_type_lookup (abfd, code) |
elf64_x86_64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
158 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd_reloc_code_real_type code) |
|
bfd_reloc_code_real_type code; |
|
159 |
{ |
{ |
160 |
unsigned int i; |
unsigned int i; |
161 |
|
|
162 |
for (i = 0; i < sizeof (x86_64_reloc_map) / sizeof (struct elf_reloc_map); |
for (i = 0; i < sizeof (x86_64_reloc_map) / sizeof (struct elf_reloc_map); |
163 |
i++) |
i++) |
164 |
{ |
{ |
171 |
/* Given an x86_64 ELF reloc type, fill in an arelent structure. */ |
/* Given an x86_64 ELF reloc type, fill in an arelent structure. */ |
172 |
|
|
173 |
static void |
static void |
174 |
elf64_x86_64_info_to_howto (abfd, cache_ptr, dst) |
elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, |
175 |
bfd *abfd ATTRIBUTE_UNUSED; |
Elf_Internal_Rela *dst) |
|
arelent *cache_ptr; |
|
|
Elf64_Internal_Rela *dst; |
|
176 |
{ |
{ |
177 |
unsigned r_type, i; |
unsigned r_type, i; |
178 |
|
|
179 |
r_type = ELF64_R_TYPE (dst->r_info); |
r_type = ELF64_R_TYPE (dst->r_info); |
180 |
if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT) |
if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT) |
181 |
{ |
{ |
182 |
BFD_ASSERT (r_type <= (unsigned int) R_X86_64_PC8); |
BFD_ASSERT (r_type <= (unsigned int) R_X86_64_TPOFF32); |
183 |
i = r_type; |
i = r_type; |
184 |
} |
} |
185 |
else |
else |
186 |
{ |
{ |
187 |
BFD_ASSERT (r_type < (unsigned int) R_X86_64_max); |
BFD_ASSERT (r_type < (unsigned int) R_X86_64_max); |
188 |
i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_PC8 - 1); |
i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_TPOFF32 - 1); |
189 |
} |
} |
190 |
cache_ptr->howto = &x86_64_elf_howto_table[i]; |
cache_ptr->howto = &x86_64_elf_howto_table[i]; |
191 |
BFD_ASSERT (r_type == cache_ptr->howto->type); |
BFD_ASSERT (r_type == cache_ptr->howto->type); |
192 |
} |
} |
193 |
|
|
194 |
/* Support for core dump NOTE sections. */ |
/* Support for core dump NOTE sections. */ |
195 |
static boolean |
static bfd_boolean |
196 |
elf64_x86_64_grok_prstatus (abfd, note) |
elf64_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
|
bfd *abfd; |
|
|
Elf_Internal_Note *note; |
|
197 |
{ |
{ |
198 |
int offset; |
int offset; |
199 |
size_t raw_size; |
size_t size; |
200 |
|
|
201 |
switch (note->descsz) |
switch (note->descsz) |
202 |
{ |
{ |
203 |
default: |
default: |
204 |
return false; |
return FALSE; |
205 |
|
|
206 |
case 336: /* sizeof(istruct elf_prstatus) on Linux/x86_64 */ |
case 336: /* sizeof(istruct elf_prstatus) on Linux/x86_64 */ |
207 |
/* pr_cursig */ |
/* pr_cursig */ |
214 |
|
|
215 |
/* pr_reg */ |
/* pr_reg */ |
216 |
offset = 112; |
offset = 112; |
217 |
raw_size = 216; |
size = 216; |
218 |
|
|
219 |
break; |
break; |
220 |
} |
} |
221 |
|
|
222 |
/* Make a ".reg/999" section. */ |
/* Make a ".reg/999" section. */ |
223 |
return _bfd_elfcore_make_pseudosection (abfd, ".reg", |
return _bfd_elfcore_make_pseudosection (abfd, ".reg", |
224 |
raw_size, note->descpos + offset); |
size, note->descpos + offset); |
225 |
} |
} |
226 |
|
|
227 |
static boolean |
static bfd_boolean |
228 |
elf64_x86_64_grok_psinfo (abfd, note) |
elf64_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
|
bfd *abfd; |
|
|
Elf_Internal_Note *note; |
|
229 |
{ |
{ |
230 |
switch (note->descsz) |
switch (note->descsz) |
231 |
{ |
{ |
232 |
default: |
default: |
233 |
return false; |
return FALSE; |
234 |
|
|
235 |
case 136: /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */ |
case 136: /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */ |
236 |
elf_tdata (abfd)->core_program |
elf_tdata (abfd)->core_program |
251 |
command[n - 1] = '\0'; |
command[n - 1] = '\0'; |
252 |
} |
} |
253 |
|
|
254 |
return true; |
return TRUE; |
255 |
} |
} |
256 |
|
|
257 |
/* Functions for the x86-64 ELF linker. */ |
/* Functions for the x86-64 ELF linker. */ |
261 |
|
|
262 |
#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1" |
#define ELF_DYNAMIC_INTERPRETER "/lib/ld64.so.1" |
263 |
|
|
264 |
|
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid |
265 |
|
copying dynamic variables from a shared lib into an app's dynbss |
266 |
|
section, and instead use a dynamic relocation to point into the |
267 |
|
shared lib. */ |
268 |
|
#define ELIMINATE_COPY_RELOCS 1 |
269 |
|
|
270 |
/* The size in bytes of an entry in the global offset table. */ |
/* The size in bytes of an entry in the global offset table. */ |
271 |
|
|
272 |
#define GOT_ENTRY_SIZE 8 |
#define GOT_ENTRY_SIZE 8 |
326 |
|
|
327 |
/* Track dynamic relocs copied for this symbol. */ |
/* Track dynamic relocs copied for this symbol. */ |
328 |
struct elf64_x86_64_dyn_relocs *dyn_relocs; |
struct elf64_x86_64_dyn_relocs *dyn_relocs; |
329 |
|
|
330 |
|
#define GOT_UNKNOWN 0 |
331 |
|
#define GOT_NORMAL 1 |
332 |
|
#define GOT_TLS_GD 2 |
333 |
|
#define GOT_TLS_IE 3 |
334 |
|
unsigned char tls_type; |
335 |
|
}; |
336 |
|
|
337 |
|
#define elf64_x86_64_hash_entry(ent) \ |
338 |
|
((struct elf64_x86_64_link_hash_entry *)(ent)) |
339 |
|
|
340 |
|
struct elf64_x86_64_obj_tdata |
341 |
|
{ |
342 |
|
struct elf_obj_tdata root; |
343 |
|
|
344 |
|
/* tls_type for each local got entry. */ |
345 |
|
char *local_got_tls_type; |
346 |
}; |
}; |
347 |
|
|
348 |
|
#define elf64_x86_64_tdata(abfd) \ |
349 |
|
((struct elf64_x86_64_obj_tdata *) (abfd)->tdata.any) |
350 |
|
|
351 |
|
#define elf64_x86_64_local_got_tls_type(abfd) \ |
352 |
|
(elf64_x86_64_tdata (abfd)->local_got_tls_type) |
353 |
|
|
354 |
|
|
355 |
/* x86-64 ELF linker hash table. */ |
/* x86-64 ELF linker hash table. */ |
356 |
|
|
357 |
struct elf64_x86_64_link_hash_table |
struct elf64_x86_64_link_hash_table |
367 |
asection *sdynbss; |
asection *sdynbss; |
368 |
asection *srelbss; |
asection *srelbss; |
369 |
|
|
370 |
|
union { |
371 |
|
bfd_signed_vma refcount; |
372 |
|
bfd_vma offset; |
373 |
|
} tls_ld_got; |
374 |
|
|
375 |
/* Small local sym to section mapping cache. */ |
/* Small local sym to section mapping cache. */ |
376 |
struct sym_sec_cache sym_sec; |
struct sym_sec_cache sym_sec; |
377 |
}; |
}; |
384 |
/* Create an entry in an x86-64 ELF linker hash table. */ |
/* Create an entry in an x86-64 ELF linker hash table. */ |
385 |
|
|
386 |
static struct bfd_hash_entry * |
static struct bfd_hash_entry * |
387 |
link_hash_newfunc (entry, table, string) |
link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table, |
388 |
struct bfd_hash_entry *entry; |
const char *string) |
|
struct bfd_hash_table *table; |
|
|
const char *string; |
|
389 |
{ |
{ |
390 |
/* Allocate the structure if it has not already been allocated by a |
/* Allocate the structure if it has not already been allocated by a |
391 |
subclass. */ |
subclass. */ |
405 |
|
|
406 |
eh = (struct elf64_x86_64_link_hash_entry *) entry; |
eh = (struct elf64_x86_64_link_hash_entry *) entry; |
407 |
eh->dyn_relocs = NULL; |
eh->dyn_relocs = NULL; |
408 |
|
eh->tls_type = GOT_UNKNOWN; |
409 |
} |
} |
410 |
|
|
411 |
return entry; |
return entry; |
414 |
/* Create an X86-64 ELF linker hash table. */ |
/* Create an X86-64 ELF linker hash table. */ |
415 |
|
|
416 |
static struct bfd_link_hash_table * |
static struct bfd_link_hash_table * |
417 |
elf64_x86_64_link_hash_table_create (abfd) |
elf64_x86_64_link_hash_table_create (bfd *abfd) |
|
bfd *abfd; |
|
418 |
{ |
{ |
419 |
struct elf64_x86_64_link_hash_table *ret; |
struct elf64_x86_64_link_hash_table *ret; |
420 |
bfd_size_type amt = sizeof (struct elf64_x86_64_link_hash_table); |
bfd_size_type amt = sizeof (struct elf64_x86_64_link_hash_table); |
437 |
ret->sdynbss = NULL; |
ret->sdynbss = NULL; |
438 |
ret->srelbss = NULL; |
ret->srelbss = NULL; |
439 |
ret->sym_sec.abfd = NULL; |
ret->sym_sec.abfd = NULL; |
440 |
|
ret->tls_ld_got.refcount = 0; |
441 |
|
|
442 |
return &ret->elf.root; |
return &ret->elf.root; |
443 |
} |
} |
445 |
/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up |
/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up |
446 |
shortcuts to them in our hash table. */ |
shortcuts to them in our hash table. */ |
447 |
|
|
448 |
static boolean |
static bfd_boolean |
449 |
create_got_section (dynobj, info) |
create_got_section (bfd *dynobj, struct bfd_link_info *info) |
|
bfd *dynobj; |
|
|
struct bfd_link_info *info; |
|
450 |
{ |
{ |
451 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
452 |
|
|
453 |
if (! _bfd_elf_create_got_section (dynobj, info)) |
if (! _bfd_elf_create_got_section (dynobj, info)) |
454 |
return false; |
return FALSE; |
455 |
|
|
456 |
htab = elf64_x86_64_hash_table (info); |
htab = elf64_x86_64_hash_table (info); |
457 |
htab->sgot = bfd_get_section_by_name (dynobj, ".got"); |
htab->sgot = bfd_get_section_by_name (dynobj, ".got"); |
466 |
| SEC_IN_MEMORY | SEC_LINKER_CREATED |
| SEC_IN_MEMORY | SEC_LINKER_CREATED |
467 |
| SEC_READONLY)) |
| SEC_READONLY)) |
468 |
|| ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) |
|| ! bfd_set_section_alignment (dynobj, htab->srelgot, 3)) |
469 |
return false; |
return FALSE; |
470 |
return true; |
return TRUE; |
471 |
} |
} |
472 |
|
|
473 |
/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and |
/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and |
474 |
.rela.bss sections in DYNOBJ, and set up shortcuts to them in our |
.rela.bss sections in DYNOBJ, and set up shortcuts to them in our |
475 |
hash table. */ |
hash table. */ |
476 |
|
|
477 |
static boolean |
static bfd_boolean |
478 |
elf64_x86_64_create_dynamic_sections (dynobj, info) |
elf64_x86_64_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) |
|
bfd *dynobj; |
|
|
struct bfd_link_info *info; |
|
479 |
{ |
{ |
480 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
481 |
|
|
482 |
htab = elf64_x86_64_hash_table (info); |
htab = elf64_x86_64_hash_table (info); |
483 |
if (!htab->sgot && !create_got_section (dynobj, info)) |
if (!htab->sgot && !create_got_section (dynobj, info)) |
484 |
return false; |
return FALSE; |
485 |
|
|
486 |
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
if (!_bfd_elf_create_dynamic_sections (dynobj, info)) |
487 |
return false; |
return FALSE; |
488 |
|
|
489 |
htab->splt = bfd_get_section_by_name (dynobj, ".plt"); |
htab->splt = bfd_get_section_by_name (dynobj, ".plt"); |
490 |
htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); |
htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt"); |
496 |
|| (!info->shared && !htab->srelbss)) |
|| (!info->shared && !htab->srelbss)) |
497 |
abort (); |
abort (); |
498 |
|
|
499 |
return true; |
return TRUE; |
500 |
} |
} |
501 |
|
|
502 |
/* Copy the extra info we tack onto an elf_link_hash_entry. */ |
/* Copy the extra info we tack onto an elf_link_hash_entry. */ |
503 |
|
|
504 |
static void |
static void |
505 |
elf64_x86_64_copy_indirect_symbol (dir, ind) |
elf64_x86_64_copy_indirect_symbol (const struct elf_backend_data *bed, |
506 |
struct elf_link_hash_entry *dir, *ind; |
struct elf_link_hash_entry *dir, |
507 |
|
struct elf_link_hash_entry *ind) |
508 |
{ |
{ |
509 |
struct elf64_x86_64_link_hash_entry *edir, *eind; |
struct elf64_x86_64_link_hash_entry *edir, *eind; |
510 |
|
|
545 |
eind->dyn_relocs = NULL; |
eind->dyn_relocs = NULL; |
546 |
} |
} |
547 |
|
|
548 |
_bfd_elf_link_hash_copy_indirect (dir, ind); |
if (ind->root.type == bfd_link_hash_indirect |
549 |
|
&& dir->got.refcount <= 0) |
550 |
|
{ |
551 |
|
edir->tls_type = eind->tls_type; |
552 |
|
eind->tls_type = GOT_UNKNOWN; |
553 |
|
} |
554 |
|
|
555 |
|
if (ELIMINATE_COPY_RELOCS |
556 |
|
&& ind->root.type != bfd_link_hash_indirect |
557 |
|
&& dir->dynamic_adjusted) |
558 |
|
{ |
559 |
|
/* If called to transfer flags for a weakdef during processing |
560 |
|
of elf_adjust_dynamic_symbol, don't copy non_got_ref. |
561 |
|
We clear it ourselves for ELIMINATE_COPY_RELOCS. */ |
562 |
|
dir->ref_dynamic |= ind->ref_dynamic; |
563 |
|
dir->ref_regular |= ind->ref_regular; |
564 |
|
dir->ref_regular_nonweak |= ind->ref_regular_nonweak; |
565 |
|
dir->needs_plt |= ind->needs_plt; |
566 |
|
dir->pointer_equality_needed |= ind->pointer_equality_needed; |
567 |
|
} |
568 |
|
else |
569 |
|
_bfd_elf_link_hash_copy_indirect (bed, dir, ind); |
570 |
} |
} |
571 |
|
|
572 |
static boolean |
static bfd_boolean |
573 |
elf64_x86_64_elf_object_p (abfd) |
elf64_x86_64_mkobject (bfd *abfd) |
574 |
bfd *abfd; |
{ |
575 |
|
bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata); |
576 |
|
abfd->tdata.any = bfd_zalloc (abfd, amt); |
577 |
|
if (abfd->tdata.any == NULL) |
578 |
|
return FALSE; |
579 |
|
return TRUE; |
580 |
|
} |
581 |
|
|
582 |
|
static bfd_boolean |
583 |
|
elf64_x86_64_elf_object_p (bfd *abfd) |
584 |
{ |
{ |
585 |
/* Set the right machine number for an x86-64 elf64 file. */ |
/* Set the right machine number for an x86-64 elf64 file. */ |
586 |
bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); |
bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); |
587 |
return true; |
return TRUE; |
588 |
|
} |
589 |
|
|
590 |
|
static int |
591 |
|
elf64_x86_64_tls_transition (struct bfd_link_info *info, int r_type, int is_local) |
592 |
|
{ |
593 |
|
if (info->shared) |
594 |
|
return r_type; |
595 |
|
|
596 |
|
switch (r_type) |
597 |
|
{ |
598 |
|
case R_X86_64_TLSGD: |
599 |
|
case R_X86_64_GOTTPOFF: |
600 |
|
if (is_local) |
601 |
|
return R_X86_64_TPOFF32; |
602 |
|
return R_X86_64_GOTTPOFF; |
603 |
|
case R_X86_64_TLSLD: |
604 |
|
return R_X86_64_TPOFF32; |
605 |
|
} |
606 |
|
|
607 |
|
return r_type; |
608 |
} |
} |
609 |
|
|
610 |
/* Look through the relocs for a section during the first phase, and |
/* Look through the relocs for a section during the first phase, and |
611 |
calculate needed space in the global offset table, procedure |
calculate needed space in the global offset table, procedure |
612 |
linkage table, and dynamic reloc sections. */ |
linkage table, and dynamic reloc sections. */ |
613 |
|
|
614 |
static boolean |
static bfd_boolean |
615 |
elf64_x86_64_check_relocs (abfd, info, sec, relocs) |
elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, |
616 |
bfd *abfd; |
const Elf_Internal_Rela *relocs) |
|
struct bfd_link_info *info; |
|
|
asection *sec; |
|
|
const Elf_Internal_Rela *relocs; |
|
617 |
{ |
{ |
618 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
619 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
622 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
623 |
asection *sreloc; |
asection *sreloc; |
624 |
|
|
625 |
if (info->relocateable) |
if (info->relocatable) |
626 |
return true; |
return TRUE; |
627 |
|
|
628 |
htab = elf64_x86_64_hash_table (info); |
htab = elf64_x86_64_hash_table (info); |
629 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
634 |
rel_end = relocs + sec->reloc_count; |
rel_end = relocs + sec->reloc_count; |
635 |
for (rel = relocs; rel < rel_end; rel++) |
for (rel = relocs; rel < rel_end; rel++) |
636 |
{ |
{ |
637 |
|
unsigned int r_type; |
638 |
unsigned long r_symndx; |
unsigned long r_symndx; |
639 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
640 |
|
|
641 |
r_symndx = ELF64_R_SYM (rel->r_info); |
r_symndx = ELF64_R_SYM (rel->r_info); |
642 |
|
r_type = ELF64_R_TYPE (rel->r_info); |
643 |
|
|
644 |
if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) |
if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) |
645 |
{ |
{ |
646 |
(*_bfd_error_handler) (_("%s: bad symbol index: %d"), |
(*_bfd_error_handler) (_("%B: bad symbol index: %d"), |
647 |
bfd_archive_filename (abfd), |
abfd, r_symndx); |
648 |
r_symndx); |
return FALSE; |
|
return false; |
|
649 |
} |
} |
650 |
|
|
651 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
653 |
else |
else |
654 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
655 |
|
|
656 |
switch (ELF64_R_TYPE (rel->r_info)) |
r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL); |
657 |
|
switch (r_type) |
658 |
{ |
{ |
659 |
|
case R_X86_64_TLSLD: |
660 |
|
htab->tls_ld_got.refcount += 1; |
661 |
|
goto create_got; |
662 |
|
|
663 |
|
case R_X86_64_TPOFF32: |
664 |
|
if (info->shared) |
665 |
|
{ |
666 |
|
(*_bfd_error_handler) |
667 |
|
(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), |
668 |
|
abfd, |
669 |
|
x86_64_elf_howto_table[r_type].name, |
670 |
|
(h) ? h->root.root.string : "a local symbol"); |
671 |
|
bfd_set_error (bfd_error_bad_value); |
672 |
|
return FALSE; |
673 |
|
} |
674 |
|
break; |
675 |
|
|
676 |
|
case R_X86_64_GOTTPOFF: |
677 |
|
if (info->shared) |
678 |
|
info->flags |= DF_STATIC_TLS; |
679 |
|
/* Fall through */ |
680 |
|
|
681 |
case R_X86_64_GOT32: |
case R_X86_64_GOT32: |
682 |
case R_X86_64_GOTPCREL: |
case R_X86_64_GOTPCREL: |
683 |
|
case R_X86_64_TLSGD: |
684 |
/* This symbol requires a global offset table entry. */ |
/* This symbol requires a global offset table entry. */ |
685 |
if (h != NULL) |
{ |
686 |
{ |
int tls_type, old_tls_type; |
|
h->got.refcount += 1; |
|
|
} |
|
|
else |
|
|
{ |
|
|
bfd_signed_vma *local_got_refcounts; |
|
687 |
|
|
688 |
/* This is a global offset table entry for a local symbol. */ |
switch (r_type) |
689 |
local_got_refcounts = elf_local_got_refcounts (abfd); |
{ |
690 |
if (local_got_refcounts == NULL) |
default: tls_type = GOT_NORMAL; break; |
691 |
{ |
case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break; |
692 |
bfd_size_type size; |
case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break; |
693 |
|
} |
694 |
|
|
695 |
|
if (h != NULL) |
696 |
|
{ |
697 |
|
h->got.refcount += 1; |
698 |
|
old_tls_type = elf64_x86_64_hash_entry (h)->tls_type; |
699 |
|
} |
700 |
|
else |
701 |
|
{ |
702 |
|
bfd_signed_vma *local_got_refcounts; |
703 |
|
|
704 |
|
/* This is a global offset table entry for a local symbol. */ |
705 |
|
local_got_refcounts = elf_local_got_refcounts (abfd); |
706 |
|
if (local_got_refcounts == NULL) |
707 |
|
{ |
708 |
|
bfd_size_type size; |
709 |
|
|
710 |
size = symtab_hdr->sh_info; |
size = symtab_hdr->sh_info; |
711 |
size *= sizeof (bfd_signed_vma); |
size *= sizeof (bfd_signed_vma) + sizeof (char); |
712 |
local_got_refcounts = ((bfd_signed_vma *) |
local_got_refcounts = ((bfd_signed_vma *) |
713 |
bfd_zalloc (abfd, size)); |
bfd_zalloc (abfd, size)); |
714 |
if (local_got_refcounts == NULL) |
if (local_got_refcounts == NULL) |
715 |
return false; |
return FALSE; |
716 |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
717 |
} |
elf64_x86_64_local_got_tls_type (abfd) |
718 |
local_got_refcounts[r_symndx] += 1; |
= (char *) (local_got_refcounts + symtab_hdr->sh_info); |
719 |
} |
} |
720 |
|
local_got_refcounts[r_symndx] += 1; |
721 |
|
old_tls_type |
722 |
|
= elf64_x86_64_local_got_tls_type (abfd) [r_symndx]; |
723 |
|
} |
724 |
|
|
725 |
|
/* If a TLS symbol is accessed using IE at least once, |
726 |
|
there is no point to use dynamic model for it. */ |
727 |
|
if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN |
728 |
|
&& (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE)) |
729 |
|
{ |
730 |
|
if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD) |
731 |
|
tls_type = old_tls_type; |
732 |
|
else |
733 |
|
{ |
734 |
|
(*_bfd_error_handler) |
735 |
|
(_("%B: %s' accessed both as normal and thread local symbol"), |
736 |
|
abfd, h ? h->root.root.string : "<local>"); |
737 |
|
return FALSE; |
738 |
|
} |
739 |
|
} |
740 |
|
|
741 |
|
if (old_tls_type != tls_type) |
742 |
|
{ |
743 |
|
if (h != NULL) |
744 |
|
elf64_x86_64_hash_entry (h)->tls_type = tls_type; |
745 |
|
else |
746 |
|
elf64_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type; |
747 |
|
} |
748 |
|
} |
749 |
/* Fall through */ |
/* Fall through */ |
750 |
|
|
751 |
//case R_X86_64_GOTPCREL: |
//case R_X86_64_GOTPCREL: |
752 |
|
create_got: |
753 |
if (htab->sgot == NULL) |
if (htab->sgot == NULL) |
754 |
{ |
{ |
755 |
if (htab->elf.dynobj == NULL) |
if (htab->elf.dynobj == NULL) |
756 |
htab->elf.dynobj = abfd; |
htab->elf.dynobj = abfd; |
757 |
if (!create_got_section (htab->elf.dynobj, info)) |
if (!create_got_section (htab->elf.dynobj, info)) |
758 |
return false; |
return FALSE; |
759 |
} |
} |
760 |
break; |
break; |
761 |
|
|
772 |
if (h == NULL) |
if (h == NULL) |
773 |
continue; |
continue; |
774 |
|
|
775 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 1; |
776 |
h->plt.refcount += 1; |
h->plt.refcount += 1; |
777 |
break; |
break; |
778 |
|
|
789 |
&& (sec->flags & SEC_READONLY) != 0) |
&& (sec->flags & SEC_READONLY) != 0) |
790 |
{ |
{ |
791 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
792 |
(_("%s: relocation %s can not be used when making a shared object; recompile with -fPIC"), |
(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), |
793 |
bfd_archive_filename (abfd), |
abfd, |
794 |
x86_64_elf_howto_table[ELF64_R_TYPE (rel->r_info)].name); |
x86_64_elf_howto_table[r_type].name, |
795 |
|
(h) ? h->root.root.string : "a local symbol"); |
796 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
797 |
return false; |
return FALSE; |
798 |
} |
} |
799 |
/* Fall through. */ |
/* Fall through. */ |
800 |
|
|
810 |
sections have not yet been mapped to output sections. |
sections have not yet been mapped to output sections. |
811 |
Tentatively set the flag for now, and correct in |
Tentatively set the flag for now, and correct in |
812 |
adjust_dynamic_symbol. */ |
adjust_dynamic_symbol. */ |
813 |
h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; |
h->non_got_ref = 1; |
814 |
|
|
815 |
/* We may need a .plt entry if the function this reloc |
/* We may need a .plt entry if the function this reloc |
816 |
refers to is in a shared lib. */ |
refers to is in a shared lib. */ |
817 |
h->plt.refcount += 1; |
h->plt.refcount += 1; |
818 |
|
if (r_type != R_X86_64_PC32) |
819 |
|
h->pointer_equality_needed = 1; |
820 |
} |
} |
821 |
|
|
822 |
/* If we are creating a shared library, and this is a reloc |
/* If we are creating a shared library, and this is a reloc |
842 |
symbol. */ |
symbol. */ |
843 |
if ((info->shared |
if ((info->shared |
844 |
&& (sec->flags & SEC_ALLOC) != 0 |
&& (sec->flags & SEC_ALLOC) != 0 |
845 |
&& (((ELF64_R_TYPE (rel->r_info) != R_X86_64_PC8) |
&& (((r_type != R_X86_64_PC8) |
846 |
&& (ELF64_R_TYPE (rel->r_info) != R_X86_64_PC16) |
&& (r_type != R_X86_64_PC16) |
847 |
&& (ELF64_R_TYPE (rel->r_info) != R_X86_64_PC32)) |
&& (r_type != R_X86_64_PC32)) |
848 |
|| (h != NULL |
|| (h != NULL |
849 |
&& (! info->symbolic |
&& (! info->symbolic |
850 |
|| h->root.type == bfd_link_hash_defweak |
|| h->root.type == bfd_link_hash_defweak |
851 |
|| (h->elf_link_hash_flags |
|| !h->def_regular)))) |
852 |
& ELF_LINK_HASH_DEF_REGULAR) == 0)))) |
|| (ELIMINATE_COPY_RELOCS |
853 |
|| (!info->shared |
&& !info->shared |
854 |
&& (sec->flags & SEC_ALLOC) != 0 |
&& (sec->flags & SEC_ALLOC) != 0 |
855 |
&& h != NULL |
&& h != NULL |
856 |
&& (h->root.type == bfd_link_hash_defweak |
&& (h->root.type == bfd_link_hash_defweak |
857 |
|| (h->elf_link_hash_flags |
|| !h->def_regular))) |
|
& ELF_LINK_HASH_DEF_REGULAR) == 0))) |
|
858 |
{ |
{ |
859 |
struct elf64_x86_64_dyn_relocs *p; |
struct elf64_x86_64_dyn_relocs *p; |
860 |
struct elf64_x86_64_dyn_relocs **head; |
struct elf64_x86_64_dyn_relocs **head; |
872 |
elf_elfheader (abfd)->e_shstrndx, |
elf_elfheader (abfd)->e_shstrndx, |
873 |
elf_section_data (sec)->rel_hdr.sh_name)); |
elf_section_data (sec)->rel_hdr.sh_name)); |
874 |
if (name == NULL) |
if (name == NULL) |
875 |
return false; |
return FALSE; |
876 |
|
|
877 |
if (strncmp (name, ".rela", 5) != 0 |
if (strncmp (name, ".rela", 5) != 0 |
878 |
|| strcmp (bfd_get_section_name (abfd, sec), |
|| strcmp (bfd_get_section_name (abfd, sec), |
879 |
name + 5) != 0) |
name + 5) != 0) |
880 |
{ |
{ |
881 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
882 |
(_("%s: bad relocation section name `%s\'"), |
(_("%B: bad relocation section name `%s\'"), |
883 |
bfd_archive_filename (abfd), name); |
abfd, name); |
884 |
} |
} |
885 |
|
|
886 |
if (htab->elf.dynobj == NULL) |
if (htab->elf.dynobj == NULL) |
901 |
if (sreloc == NULL |
if (sreloc == NULL |
902 |
|| ! bfd_set_section_flags (dynobj, sreloc, flags) |
|| ! bfd_set_section_flags (dynobj, sreloc, flags) |
903 |
|| ! bfd_set_section_alignment (dynobj, sreloc, 3)) |
|| ! bfd_set_section_alignment (dynobj, sreloc, 3)) |
904 |
return false; |
return FALSE; |
905 |
} |
} |
906 |
elf_section_data (sec)->sreloc = sreloc; |
elf_section_data (sec)->sreloc = sreloc; |
907 |
} |
} |
922 |
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, |
s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, |
923 |
sec, r_symndx); |
sec, r_symndx); |
924 |
if (s == NULL) |
if (s == NULL) |
925 |
return false; |
return FALSE; |
926 |
|
|
927 |
head = ((struct elf64_x86_64_dyn_relocs **) |
head = ((struct elf64_x86_64_dyn_relocs **) |
928 |
&elf_section_data (s)->local_dynrel); |
&elf_section_data (s)->local_dynrel); |
935 |
p = ((struct elf64_x86_64_dyn_relocs *) |
p = ((struct elf64_x86_64_dyn_relocs *) |
936 |
bfd_alloc (htab->elf.dynobj, amt)); |
bfd_alloc (htab->elf.dynobj, amt)); |
937 |
if (p == NULL) |
if (p == NULL) |
938 |
return false; |
return FALSE; |
939 |
p->next = *head; |
p->next = *head; |
940 |
*head = p; |
*head = p; |
941 |
p->sec = sec; |
p->sec = sec; |
944 |
} |
} |
945 |
|
|
946 |
p->count += 1; |
p->count += 1; |
947 |
if (ELF64_R_TYPE (rel->r_info) == R_X86_64_PC8 |
if (r_type == R_X86_64_PC8 |
948 |
|| ELF64_R_TYPE (rel->r_info) == R_X86_64_PC16 |
|| r_type == R_X86_64_PC16 |
949 |
|| ELF64_R_TYPE (rel->r_info) == R_X86_64_PC32) |
|| r_type == R_X86_64_PC32) |
950 |
p->pc_count += 1; |
p->pc_count += 1; |
951 |
} |
} |
952 |
break; |
break; |
954 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
955 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
956 |
case R_X86_64_GNU_VTINHERIT: |
case R_X86_64_GNU_VTINHERIT: |
957 |
if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
958 |
return false; |
return FALSE; |
959 |
break; |
break; |
960 |
|
|
961 |
/* This relocation describes which C++ vtable entries are actually |
/* This relocation describes which C++ vtable entries are actually |
962 |
used. Record for later use during GC. */ |
used. Record for later use during GC. */ |
963 |
case R_X86_64_GNU_VTENTRY: |
case R_X86_64_GNU_VTENTRY: |
964 |
if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
965 |
return false; |
return FALSE; |
966 |
break; |
break; |
967 |
|
|
968 |
default: |
default: |
970 |
} |
} |
971 |
} |
} |
972 |
|
|
973 |
return true; |
return TRUE; |
974 |
} |
} |
975 |
|
|
976 |
/* Return the section that should be marked against GC for a given |
/* Return the section that should be marked against GC for a given |
977 |
relocation. */ |
relocation. */ |
978 |
|
|
979 |
static asection * |
static asection * |
980 |
elf64_x86_64_gc_mark_hook (sec, info, rel, h, sym) |
elf64_x86_64_gc_mark_hook (asection *sec, |
981 |
asection *sec; |
struct bfd_link_info *info ATTRIBUTE_UNUSED, |
982 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
Elf_Internal_Rela *rel, |
983 |
Elf_Internal_Rela *rel; |
struct elf_link_hash_entry *h, |
984 |
struct elf_link_hash_entry *h; |
Elf_Internal_Sym *sym) |
|
Elf_Internal_Sym *sym; |
|
985 |
{ |
{ |
986 |
if (h != NULL) |
if (h != NULL) |
987 |
{ |
{ |
1014 |
|
|
1015 |
/* Update the got entry reference counts for the section being removed. */ |
/* Update the got entry reference counts for the section being removed. */ |
1016 |
|
|
1017 |
static boolean |
static bfd_boolean |
1018 |
elf64_x86_64_gc_sweep_hook (abfd, info, sec, relocs) |
elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, |
1019 |
bfd *abfd; |
asection *sec, const Elf_Internal_Rela *relocs) |
|
struct bfd_link_info *info; |
|
|
asection *sec; |
|
|
const Elf_Internal_Rela *relocs; |
|
1020 |
{ |
{ |
1021 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
1022 |
struct elf_link_hash_entry **sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
1023 |
bfd_signed_vma *local_got_refcounts; |
bfd_signed_vma *local_got_refcounts; |
1024 |
const Elf_Internal_Rela *rel, *relend; |
const Elf_Internal_Rela *rel, *relend; |
|
unsigned long r_symndx; |
|
|
struct elf_link_hash_entry *h; |
|
1025 |
|
|
1026 |
elf_section_data (sec)->local_dynrel = NULL; |
elf_section_data (sec)->local_dynrel = NULL; |
1027 |
|
|
1031 |
|
|
1032 |
relend = relocs + sec->reloc_count; |
relend = relocs + sec->reloc_count; |
1033 |
for (rel = relocs; rel < relend; rel++) |
for (rel = relocs; rel < relend; rel++) |
1034 |
switch (ELF64_R_TYPE (rel->r_info)) |
{ |
1035 |
{ |
unsigned long r_symndx; |
1036 |
case R_X86_64_GOT32: |
unsigned int r_type; |
1037 |
case R_X86_64_GOTPCREL: |
struct elf_link_hash_entry *h = NULL; |
|
r_symndx = ELF64_R_SYM (rel->r_info); |
|
|
if (r_symndx >= symtab_hdr->sh_info) |
|
|
{ |
|
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
|
|
if (h->got.refcount > 0) |
|
|
h->got.refcount -= 1; |
|
|
} |
|
|
else if (local_got_refcounts != NULL) |
|
|
{ |
|
|
if (local_got_refcounts[r_symndx] > 0) |
|
|
local_got_refcounts[r_symndx] -= 1; |
|
|
} |
|
|
break; |
|
1038 |
|
|
1039 |
case R_X86_64_8: |
r_symndx = ELF64_R_SYM (rel->r_info); |
1040 |
case R_X86_64_16: |
if (r_symndx >= symtab_hdr->sh_info) |
1041 |
case R_X86_64_32: |
{ |
1042 |
case R_X86_64_64: |
struct elf64_x86_64_link_hash_entry *eh; |
1043 |
case R_X86_64_32S: |
struct elf64_x86_64_dyn_relocs **pp; |
1044 |
case R_X86_64_PC8: |
struct elf64_x86_64_dyn_relocs *p; |
|
case R_X86_64_PC16: |
|
|
case R_X86_64_PC32: |
|
|
r_symndx = ELF64_R_SYM (rel->r_info); |
|
|
if (r_symndx >= symtab_hdr->sh_info) |
|
|
{ |
|
|
struct elf64_x86_64_link_hash_entry *eh; |
|
|
struct elf64_x86_64_dyn_relocs **pp; |
|
|
struct elf64_x86_64_dyn_relocs *p; |
|
1045 |
|
|
1046 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
1047 |
|
while (h->root.type == bfd_link_hash_indirect |
1048 |
|
|| h->root.type == bfd_link_hash_warning) |
1049 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
1050 |
|
eh = (struct elf64_x86_64_link_hash_entry *) h; |
1051 |
|
|
1052 |
if (!info->shared && h->plt.refcount > 0) |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) |
1053 |
h->plt.refcount -= 1; |
if (p->sec == sec) |
1054 |
|
{ |
1055 |
|
/* Everything must go for SEC. */ |
1056 |
|
*pp = p->next; |
1057 |
|
break; |
1058 |
|
} |
1059 |
|
} |
1060 |
|
|
1061 |
eh = (struct elf64_x86_64_link_hash_entry *) h; |
r_type = ELF64_R_TYPE (rel->r_info); |
1062 |
|
r_type = elf64_x86_64_tls_transition (info, r_type, h != NULL); |
1063 |
|
switch (r_type) |
1064 |
|
{ |
1065 |
|
case R_X86_64_TLSLD: |
1066 |
|
if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0) |
1067 |
|
elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1; |
1068 |
|
break; |
1069 |
|
|
1070 |
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) |
case R_X86_64_TLSGD: |
1071 |
if (p->sec == sec) |
case R_X86_64_GOTTPOFF: |
1072 |
{ |
case R_X86_64_GOT32: |
1073 |
if (ELF64_R_TYPE (rel->r_info) == R_X86_64_PC8 |
case R_X86_64_GOTPCREL: |
1074 |
|| ELF64_R_TYPE (rel->r_info) == R_X86_64_PC16 |
if (h != NULL) |
1075 |
|| ELF64_R_TYPE (rel->r_info) == R_X86_64_PC32) |
{ |
1076 |
p->pc_count -= 1; |
if (h->got.refcount > 0) |
1077 |
p->count -= 1; |
h->got.refcount -= 1; |
1078 |
if (p->count == 0) |
} |
1079 |
*pp = p->next; |
else if (local_got_refcounts != NULL) |
1080 |
break; |
{ |
1081 |
} |
if (local_got_refcounts[r_symndx] > 0) |
1082 |
} |
local_got_refcounts[r_symndx] -= 1; |
1083 |
break; |
} |
1084 |
|
break; |
1085 |
|
|
1086 |
|
case R_X86_64_8: |
1087 |
|
case R_X86_64_16: |
1088 |
|
case R_X86_64_32: |
1089 |
|
case R_X86_64_64: |
1090 |
|
case R_X86_64_32S: |
1091 |
|
case R_X86_64_PC8: |
1092 |
|
case R_X86_64_PC16: |
1093 |
|
case R_X86_64_PC32: |
1094 |
|
if (info->shared) |
1095 |
|
break; |
1096 |
|
/* Fall thru */ |
1097 |
|
|
1098 |
case R_X86_64_PLT32: |
case R_X86_64_PLT32: |
1099 |
r_symndx = ELF64_R_SYM (rel->r_info); |
if (h != NULL) |
1100 |
if (r_symndx >= symtab_hdr->sh_info) |
{ |
1101 |
{ |
if (h->plt.refcount > 0) |
1102 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
h->plt.refcount -= 1; |
1103 |
if (h->plt.refcount > 0) |
} |
1104 |
h->plt.refcount -= 1; |
break; |
|
} |
|
|
break; |
|
1105 |
|
|
1106 |
default: |
default: |
1107 |
break; |
break; |
1108 |
} |
} |
1109 |
|
} |
1110 |
|
|
1111 |
return true; |
return TRUE; |
1112 |
} |
} |
1113 |
|
|
1114 |
/* Adjust a symbol defined by a dynamic object and referenced by a |
/* Adjust a symbol defined by a dynamic object and referenced by a |
1117 |
change the definition to something the rest of the link can |
change the definition to something the rest of the link can |
1118 |
understand. */ |
understand. */ |
1119 |
|
|
1120 |
static boolean |
static bfd_boolean |
1121 |
elf64_x86_64_adjust_dynamic_symbol (info, h) |
elf64_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, |
1122 |
struct bfd_link_info *info; |
struct elf_link_hash_entry *h) |
|
struct elf_link_hash_entry *h; |
|
1123 |
{ |
{ |
1124 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
|
struct elf64_x86_64_link_hash_entry * eh; |
|
|
struct elf64_x86_64_dyn_relocs *p; |
|
1125 |
asection *s; |
asection *s; |
1126 |
unsigned int power_of_two; |
unsigned int power_of_two; |
1127 |
|
|
1129 |
will fill in the contents of the procedure linkage table later, |
will fill in the contents of the procedure linkage table later, |
1130 |
when we know the address of the .got section. */ |
when we know the address of the .got section. */ |
1131 |
if (h->type == STT_FUNC |
if (h->type == STT_FUNC |
1132 |
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) |
|| h->needs_plt) |
1133 |
{ |
{ |
1134 |
if (h->plt.refcount <= 0 |
if (h->plt.refcount <= 0 |
1135 |
|| (! info->shared |
|| SYMBOL_CALLS_LOCAL (info, h) |
1136 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 |
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
1137 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 |
&& h->root.type == bfd_link_hash_undefweak)) |
|
&& h->root.type != bfd_link_hash_undefweak |
|
|
&& h->root.type != bfd_link_hash_undefined)) |
|
1138 |
{ |
{ |
1139 |
/* This case can occur if we saw a PLT32 reloc in an input |
/* This case can occur if we saw a PLT32 reloc in an input |
1140 |
file, but the symbol was never referred to by a dynamic |
file, but the symbol was never referred to by a dynamic |
1142 |
such a case, we don't actually need to build a procedure |
such a case, we don't actually need to build a procedure |
1143 |
linkage table, and we can just do a PC32 reloc instead. */ |
linkage table, and we can just do a PC32 reloc instead. */ |
1144 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
1145 |
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 0; |
1146 |
} |
} |
1147 |
|
|
1148 |
return true; |
return TRUE; |
1149 |
} |
} |
1150 |
else |
else |
1151 |
/* It's possible that we incorrectly decided a .plt reloc was |
/* It's possible that we incorrectly decided a .plt reloc was |
1158 |
/* If this is a weak symbol, and there is a real definition, the |
/* If this is a weak symbol, and there is a real definition, the |
1159 |
processor independent code will have arranged for us to see the |
processor independent code will have arranged for us to see the |
1160 |
real definition first, and we can just use the same value. */ |
real definition first, and we can just use the same value. */ |
1161 |
if (h->weakdef != NULL) |
if (h->u.weakdef != NULL) |
1162 |
{ |
{ |
1163 |
BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined |
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined |
1164 |
|| h->weakdef->root.type == bfd_link_hash_defweak); |
|| h->u.weakdef->root.type == bfd_link_hash_defweak); |
1165 |
h->root.u.def.section = h->weakdef->root.u.def.section; |
h->root.u.def.section = h->u.weakdef->root.u.def.section; |
1166 |
h->root.u.def.value = h->weakdef->root.u.def.value; |
h->root.u.def.value = h->u.weakdef->root.u.def.value; |
1167 |
return true; |
if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) |
1168 |
|
h->non_got_ref = h->u.weakdef->non_got_ref; |
1169 |
|
return TRUE; |
1170 |
} |
} |
1171 |
|
|
1172 |
/* This is a reference to a symbol defined by a dynamic object which |
/* This is a reference to a symbol defined by a dynamic object which |
1177 |
For such cases we need not do anything here; the relocations will |
For such cases we need not do anything here; the relocations will |
1178 |
be handled correctly by relocate_section. */ |
be handled correctly by relocate_section. */ |
1179 |
if (info->shared) |
if (info->shared) |
1180 |
return true; |
return TRUE; |
1181 |
|
|
1182 |
/* If there are no references to this symbol that do not use the |
/* If there are no references to this symbol that do not use the |
1183 |
GOT, we don't need to generate a copy reloc. */ |
GOT, we don't need to generate a copy reloc. */ |
1184 |
if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) |
if (!h->non_got_ref) |
1185 |
return true; |
return TRUE; |
1186 |
|
|
1187 |
/* If -z nocopyreloc was given, we won't generate them either. */ |
/* If -z nocopyreloc was given, we won't generate them either. */ |
1188 |
if (info->nocopyreloc) |
if (info->nocopyreloc) |
1189 |
{ |
{ |
1190 |
h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; |
h->non_got_ref = 0; |
1191 |
return true; |
return TRUE; |
1192 |
} |
} |
1193 |
|
|
1194 |
eh = (struct elf64_x86_64_link_hash_entry *) h; |
if (ELIMINATE_COPY_RELOCS) |
|
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
|
1195 |
{ |
{ |
1196 |
s = p->sec->output_section; |
struct elf64_x86_64_link_hash_entry * eh; |
1197 |
if (s != NULL && (s->flags & SEC_READONLY) != 0) |
struct elf64_x86_64_dyn_relocs *p; |
|
break; |
|
|
} |
|
1198 |
|
|
1199 |
/* If we didn't find any dynamic relocs in read-only sections, then |
eh = (struct elf64_x86_64_link_hash_entry *) h; |
1200 |
we'll be keeping the dynamic relocs and avoiding the copy reloc. */ |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
1201 |
if (p == NULL) |
{ |
1202 |
{ |
s = p->sec->output_section; |
1203 |
h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; |
if (s != NULL && (s->flags & SEC_READONLY) != 0) |
1204 |
return true; |
break; |
1205 |
|
} |
1206 |
|
|
1207 |
|
/* If we didn't find any dynamic relocs in read-only sections, then |
1208 |
|
we'll be keeping the dynamic relocs and avoiding the copy reloc. */ |
1209 |
|
if (p == NULL) |
1210 |
|
{ |
1211 |
|
h->non_got_ref = 0; |
1212 |
|
return TRUE; |
1213 |
|
} |
1214 |
} |
} |
1215 |
|
|
1216 |
/* We must allocate the symbol in our .dynbss section, which will |
/* We must allocate the symbol in our .dynbss section, which will |
1230 |
runtime process image. */ |
runtime process image. */ |
1231 |
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) |
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) |
1232 |
{ |
{ |
1233 |
htab->srelbss->_raw_size += sizeof (Elf64_External_Rela); |
htab->srelbss->size += sizeof (Elf64_External_Rela); |
1234 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; |
h->needs_copy = 1; |
1235 |
} |
} |
1236 |
|
|
1237 |
/* We need to figure out the alignment required for this symbol. I |
/* We need to figure out the alignment required for this symbol. I |
1245 |
|
|
1246 |
/* Apply the required alignment. */ |
/* Apply the required alignment. */ |
1247 |
s = htab->sdynbss; |
s = htab->sdynbss; |
1248 |
s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); |
s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); |
1249 |
if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) |
if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) |
1250 |
{ |
{ |
1251 |
if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) |
if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) |
1252 |
return false; |
return FALSE; |
1253 |
} |
} |
1254 |
|
|
1255 |
/* Define the symbol as being at this point in the section. */ |
/* Define the symbol as being at this point in the section. */ |
1256 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
1257 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = s->size; |
1258 |
|
|
1259 |
/* Increment the section size to make room for the symbol. */ |
/* Increment the section size to make room for the symbol. */ |
1260 |
s->_raw_size += h->size; |
s->size += h->size; |
1261 |
|
|
1262 |
return true; |
return TRUE; |
1263 |
} |
} |
1264 |
|
|
|
/* This is the condition under which elf64_x86_64_finish_dynamic_symbol |
|
|
will be called from elflink.h. If elflink.h doesn't call our |
|
|
finish_dynamic_symbol routine, we'll need to do something about |
|
|
initializing any .plt and .got entries in elf64_x86_64_relocate_section. */ |
|
|
#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ |
|
|
((DYN) \ |
|
|
&& ((INFO)->shared \ |
|
|
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ |
|
|
&& ((H)->dynindx != -1 \ |
|
|
|| ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) |
|
|
|
|
1265 |
/* Allocate space in .plt, .got and associated reloc sections for |
/* Allocate space in .plt, .got and associated reloc sections for |
1266 |
dynamic relocs. */ |
dynamic relocs. */ |
1267 |
|
|
1268 |
static boolean |
static bfd_boolean |
1269 |
allocate_dynrelocs (h, inf) |
allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) |
|
struct elf_link_hash_entry *h; |
|
|
PTR inf; |
|
1270 |
{ |
{ |
1271 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1272 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
1274 |
struct elf64_x86_64_dyn_relocs *p; |
struct elf64_x86_64_dyn_relocs *p; |
1275 |
|
|
1276 |
if (h->root.type == bfd_link_hash_indirect) |
if (h->root.type == bfd_link_hash_indirect) |
1277 |
return true; |
return TRUE; |
1278 |
|
|
1279 |
if (h->root.type == bfd_link_hash_warning) |
if (h->root.type == bfd_link_hash_warning) |
1280 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
1288 |
/* Make sure this symbol is output as a dynamic symbol. |
/* Make sure this symbol is output as a dynamic symbol. |
1289 |
Undefined weak syms won't yet be marked as dynamic. */ |
Undefined weak syms won't yet be marked as dynamic. */ |
1290 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
1291 |
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) |
&& !h->forced_local) |
1292 |
{ |
{ |
1293 |
if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
1294 |
return false; |
return FALSE; |
1295 |
} |
} |
1296 |
|
|
1297 |
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) |
if (info->shared |
1298 |
|
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
1299 |
{ |
{ |
1300 |
asection *s = htab->splt; |
asection *s = htab->splt; |
1301 |
|
|
1302 |
/* If this is the first .plt entry, make room for the special |
/* If this is the first .plt entry, make room for the special |
1303 |
first entry. */ |
first entry. */ |
1304 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1305 |
s->_raw_size += PLT_ENTRY_SIZE; |
s->size += PLT_ENTRY_SIZE; |
1306 |
|
|
1307 |
h->plt.offset = s->_raw_size; |
h->plt.offset = s->size; |
1308 |
|
|
1309 |
/* If this symbol is not defined in a regular file, and we are |
/* If this symbol is not defined in a regular file, and we are |
1310 |
not generating a shared library, then set the symbol to this |
not generating a shared library, then set the symbol to this |
1312 |
pointers compare as equal between the normal executable and |
pointers compare as equal between the normal executable and |
1313 |
the shared library. */ |
the shared library. */ |
1314 |
if (! info->shared |
if (! info->shared |
1315 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
&& !h->def_regular) |
1316 |
{ |
{ |
1317 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
1318 |
h->root.u.def.value = h->plt.offset; |
h->root.u.def.value = h->plt.offset; |
1319 |
} |
} |
1320 |
|
|
1321 |
/* Make room for this entry. */ |
/* Make room for this entry. */ |
1322 |
s->_raw_size += PLT_ENTRY_SIZE; |
s->size += PLT_ENTRY_SIZE; |
1323 |
|
|
1324 |
/* We also need to make an entry in the .got.plt section, which |
/* We also need to make an entry in the .got.plt section, which |
1325 |
will be placed in the .got section by the linker script. */ |
will be placed in the .got section by the linker script. */ |
1326 |
htab->sgotplt->_raw_size += GOT_ENTRY_SIZE; |
htab->sgotplt->size += GOT_ENTRY_SIZE; |
1327 |
|
|
1328 |
/* We also need to make an entry in the .rela.plt section. */ |
/* We also need to make an entry in the .rela.plt section. */ |
1329 |
htab->srelplt->_raw_size += sizeof (Elf64_External_Rela); |
htab->srelplt->size += sizeof (Elf64_External_Rela); |
1330 |
} |
} |
1331 |
else |
else |
1332 |
{ |
{ |
1333 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
1334 |
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 0; |
1335 |
} |
} |
1336 |
} |
} |
1337 |
else |
else |
1338 |
{ |
{ |
1339 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
1340 |
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 0; |
1341 |
} |
} |
1342 |
|
|
1343 |
if (h->got.refcount > 0) |
/* If R_X86_64_GOTTPOFF symbol is now local to the binary, |
1344 |
|
make it a R_X86_64_TPOFF32 requiring no GOT entry. */ |
1345 |
|
if (h->got.refcount > 0 |
1346 |
|
&& !info->shared |
1347 |
|
&& h->dynindx == -1 |
1348 |
|
&& elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE) |
1349 |
|
h->got.offset = (bfd_vma) -1; |
1350 |
|
else if (h->got.refcount > 0) |
1351 |
{ |
{ |
1352 |
asection *s; |
asection *s; |
1353 |
boolean dyn; |
bfd_boolean dyn; |
1354 |
|
int tls_type = elf64_x86_64_hash_entry (h)->tls_type; |
1355 |
|
|
1356 |
/* Make sure this symbol is output as a dynamic symbol. |
/* Make sure this symbol is output as a dynamic symbol. |
1357 |
Undefined weak syms won't yet be marked as dynamic. */ |
Undefined weak syms won't yet be marked as dynamic. */ |
1358 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
1359 |
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) |
&& !h->forced_local) |
1360 |
{ |
{ |
1361 |
if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
1362 |
return false; |
return FALSE; |
1363 |
} |
} |
1364 |
|
|
1365 |
s = htab->sgot; |
s = htab->sgot; |
1366 |
h->got.offset = s->_raw_size; |
h->got.offset = s->size; |
1367 |
s->_raw_size += GOT_ENTRY_SIZE; |
s->size += GOT_ENTRY_SIZE; |
1368 |
|
/* R_X86_64_TLSGD needs 2 consecutive GOT slots. */ |
1369 |
|
if (tls_type == GOT_TLS_GD) |
1370 |
|
s->size += GOT_ENTRY_SIZE; |
1371 |
dyn = htab->elf.dynamic_sections_created; |
dyn = htab->elf.dynamic_sections_created; |
1372 |
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) |
/* R_X86_64_TLSGD needs one dynamic relocation if local symbol |
1373 |
htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); |
and two if global. |
1374 |
|
R_X86_64_GOTTPOFF needs one dynamic relocation. */ |
1375 |
|
if ((tls_type == GOT_TLS_GD && h->dynindx == -1) |
1376 |
|
|| tls_type == GOT_TLS_IE) |
1377 |
|
htab->srelgot->size += sizeof (Elf64_External_Rela); |
1378 |
|
else if (tls_type == GOT_TLS_GD) |
1379 |
|
htab->srelgot->size += 2 * sizeof (Elf64_External_Rela); |
1380 |
|
else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
1381 |
|
|| h->root.type != bfd_link_hash_undefweak) |
1382 |
|
&& (info->shared |
1383 |
|
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) |
1384 |
|
htab->srelgot->size += sizeof (Elf64_External_Rela); |
1385 |
} |
} |
1386 |
else |
else |
1387 |
h->got.offset = (bfd_vma) -1; |
h->got.offset = (bfd_vma) -1; |
1388 |
|
|
1389 |
eh = (struct elf64_x86_64_link_hash_entry *) h; |
eh = (struct elf64_x86_64_link_hash_entry *) h; |
1390 |
if (eh->dyn_relocs == NULL) |
if (eh->dyn_relocs == NULL) |
1391 |
return true; |
return TRUE; |
1392 |
|
|
1393 |
/* In the shared -Bsymbolic case, discard space allocated for |
/* In the shared -Bsymbolic case, discard space allocated for |
1394 |
dynamic pc-relative relocs against symbols which turn out to be |
dynamic pc-relative relocs against symbols which turn out to be |
1398 |
|
|
1399 |
if (info->shared) |
if (info->shared) |
1400 |
{ |
{ |
1401 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 |
/* Relocs that use pc_count are those that appear on a call |
1402 |
&& ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 |
insn, or certain REL relocs that can generated via assembly. |
1403 |
|| info->symbolic)) |
We want calls to protected symbols to resolve directly to the |
1404 |
|
function rather than going via the plt. If people want |
1405 |
|
function pointer comparisons to work as expected then they |
1406 |
|
should avoid writing weird assembly. */ |
1407 |
|
if (SYMBOL_CALLS_LOCAL (info, h)) |
1408 |
{ |
{ |
1409 |
struct elf64_x86_64_dyn_relocs **pp; |
struct elf64_x86_64_dyn_relocs **pp; |
1410 |
|
|
1418 |
pp = &p->next; |
pp = &p->next; |
1419 |
} |
} |
1420 |
} |
} |
1421 |
|
|
1422 |
|
/* Also discard relocs on undefined weak syms with non-default |
1423 |
|
visibility. */ |
1424 |
|
if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
1425 |
|
&& h->root.type == bfd_link_hash_undefweak) |
1426 |
|
eh->dyn_relocs = NULL; |
1427 |
} |
} |
1428 |
else |
else if (ELIMINATE_COPY_RELOCS) |
1429 |
{ |
{ |
1430 |
/* For the non-shared case, discard space for relocs against |
/* For the non-shared case, discard space for relocs against |
1431 |
symbols which turn out to need copy relocs or are not |
symbols which turn out to need copy relocs or are not |
1432 |
dynamic. */ |
dynamic. */ |
1433 |
|
|
1434 |
if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 |
if (!h->non_got_ref |
1435 |
&& (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 |
&& ((h->def_dynamic |
1436 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
&& !h->def_regular) |
1437 |
|| (htab->elf.dynamic_sections_created |
|| (htab->elf.dynamic_sections_created |
1438 |
&& (h->root.type == bfd_link_hash_undefweak |
&& (h->root.type == bfd_link_hash_undefweak |
1439 |
|| h->root.type == bfd_link_hash_undefined)))) |
|| h->root.type == bfd_link_hash_undefined)))) |
1441 |
/* Make sure this symbol is output as a dynamic symbol. |
/* Make sure this symbol is output as a dynamic symbol. |
1442 |
Undefined weak syms won't yet be marked as dynamic. */ |
Undefined weak syms won't yet be marked as dynamic. */ |
1443 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
1444 |
&& (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) |
&& !h->forced_local) |
1445 |
{ |
{ |
1446 |
if (! bfd_elf64_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
1447 |
return false; |
return FALSE; |
1448 |
} |
} |
1449 |
|
|
1450 |
/* If that succeeded, we know we'll be keeping all the |
/* If that succeeded, we know we'll be keeping all the |
1462 |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
for (p = eh->dyn_relocs; p != NULL; p = p->next) |
1463 |
{ |
{ |
1464 |
asection *sreloc = elf_section_data (p->sec)->sreloc; |
asection *sreloc = elf_section_data (p->sec)->sreloc; |
1465 |
sreloc->_raw_size += p->count * sizeof (Elf64_External_Rela); |
sreloc->size += p->count * sizeof (Elf64_External_Rela); |
1466 |
} |
} |
1467 |
|
|
1468 |
return true; |
return TRUE; |
1469 |
} |
} |
1470 |
|
|
1471 |
/* Find any dynamic relocs that apply to read-only sections. */ |
/* Find any dynamic relocs that apply to read-only sections. */ |
1472 |
|
|
1473 |
static boolean |
static bfd_boolean |
1474 |
readonly_dynrelocs (h, inf) |
readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf) |
|
struct elf_link_hash_entry *h; |
|
|
PTR inf; |
|
1475 |
{ |
{ |
1476 |
struct elf64_x86_64_link_hash_entry *eh; |
struct elf64_x86_64_link_hash_entry *eh; |
1477 |
struct elf64_x86_64_dyn_relocs *p; |
struct elf64_x86_64_dyn_relocs *p; |
1491 |
info->flags |= DF_TEXTREL; |
info->flags |= DF_TEXTREL; |
1492 |
|
|
1493 |
/* Not an error, just cut short the traversal. */ |
/* Not an error, just cut short the traversal. */ |
1494 |
return false; |
return FALSE; |
1495 |
} |
} |
1496 |
} |
} |
1497 |
return true; |
return TRUE; |
1498 |
} |
} |
1499 |
|
|
1500 |
/* Set the sizes of the dynamic sections. */ |
/* Set the sizes of the dynamic sections. */ |
1501 |
|
|
1502 |
static boolean |
static bfd_boolean |
1503 |
elf64_x86_64_size_dynamic_sections (output_bfd, info) |
elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
1504 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
struct bfd_link_info *info) |
|
struct bfd_link_info *info; |
|
1505 |
{ |
{ |
1506 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
1507 |
bfd *dynobj; |
bfd *dynobj; |
1508 |
asection *s; |
asection *s; |
1509 |
boolean relocs; |
bfd_boolean relocs; |
1510 |
bfd *ibfd; |
bfd *ibfd; |
1511 |
|
|
1512 |
htab = elf64_x86_64_hash_table (info); |
htab = elf64_x86_64_hash_table (info); |
1517 |
if (htab->elf.dynamic_sections_created) |
if (htab->elf.dynamic_sections_created) |
1518 |
{ |
{ |
1519 |
/* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
1520 |
if (! info->shared) |
if (info->executable) |
1521 |
{ |
{ |
1522 |
s = bfd_get_section_by_name (dynobj, ".interp"); |
s = bfd_get_section_by_name (dynobj, ".interp"); |
1523 |
if (s == NULL) |
if (s == NULL) |
1524 |
abort (); |
abort (); |
1525 |
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; |
s->size = sizeof ELF_DYNAMIC_INTERPRETER; |
1526 |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
1527 |
} |
} |
1528 |
} |
} |
1533 |
{ |
{ |
1534 |
bfd_signed_vma *local_got; |
bfd_signed_vma *local_got; |
1535 |
bfd_signed_vma *end_local_got; |
bfd_signed_vma *end_local_got; |
1536 |
|
char *local_tls_type; |
1537 |
bfd_size_type locsymcount; |
bfd_size_type locsymcount; |
1538 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
1539 |
asection *srel; |
asection *srel; |
1561 |
else if (p->count != 0) |
else if (p->count != 0) |
1562 |
{ |
{ |
1563 |
srel = elf_section_data (p->sec)->sreloc; |
srel = elf_section_data (p->sec)->sreloc; |
1564 |
srel->_raw_size += p->count * sizeof (Elf64_External_Rela); |
srel->size += p->count * sizeof (Elf64_External_Rela); |
1565 |
if ((p->sec->output_section->flags & SEC_READONLY) != 0) |
if ((p->sec->output_section->flags & SEC_READONLY) != 0) |
1566 |
info->flags |= DF_TEXTREL; |
info->flags |= DF_TEXTREL; |
1567 |
|
|
1576 |
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; |
1577 |
locsymcount = symtab_hdr->sh_info; |
locsymcount = symtab_hdr->sh_info; |
1578 |
end_local_got = local_got + locsymcount; |
end_local_got = local_got + locsymcount; |
1579 |
|
local_tls_type = elf64_x86_64_local_got_tls_type (ibfd); |
1580 |
s = htab->sgot; |
s = htab->sgot; |
1581 |
srel = htab->srelgot; |
srel = htab->srelgot; |
1582 |
for (; local_got < end_local_got; ++local_got) |
for (; local_got < end_local_got; ++local_got, ++local_tls_type) |
1583 |
{ |
{ |
1584 |
if (*local_got > 0) |
if (*local_got > 0) |
1585 |
{ |
{ |
1586 |
*local_got = s->_raw_size; |
*local_got = s->size; |
1587 |
s->_raw_size += GOT_ENTRY_SIZE; |
s->size += GOT_ENTRY_SIZE; |
1588 |
if (info->shared) |
if (*local_tls_type == GOT_TLS_GD) |
1589 |
srel->_raw_size += sizeof (Elf64_External_Rela); |
s->size += GOT_ENTRY_SIZE; |
1590 |
|
if (info->shared |
1591 |
|
|| *local_tls_type == GOT_TLS_GD |
1592 |
|
|| *local_tls_type == GOT_TLS_IE) |
1593 |
|
srel->size += sizeof (Elf64_External_Rela); |
1594 |
} |
} |
1595 |
else |
else |
1596 |
*local_got = (bfd_vma) -1; |
*local_got = (bfd_vma) -1; |
1597 |
} |
} |
1598 |
} |
} |
1599 |
|
|
1600 |
|
if (htab->tls_ld_got.refcount > 0) |
1601 |
|
{ |
1602 |
|
/* Allocate 2 got entries and 1 dynamic reloc for R_X86_64_TLSLD |
1603 |
|
relocs. */ |
1604 |
|
htab->tls_ld_got.offset = htab->sgot->size; |
1605 |
|
htab->sgot->size += 2 * GOT_ENTRY_SIZE; |
1606 |
|
htab->srelgot->size += sizeof (Elf64_External_Rela); |
1607 |
|
} |
1608 |
|
else |
1609 |
|
htab->tls_ld_got.offset = -1; |
1610 |
|
|
1611 |
/* Allocate global sym .plt and .got entries, and space for global |
/* Allocate global sym .plt and .got entries, and space for global |
1612 |
sym dynamic relocs. */ |
sym dynamic relocs. */ |
1613 |
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); |
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); |
1614 |
|
|
1615 |
/* We now have determined the sizes of the various dynamic sections. |
/* We now have determined the sizes of the various dynamic sections. |
1616 |
Allocate memory for them. */ |
Allocate memory for them. */ |
1617 |
relocs = false; |
relocs = FALSE; |
1618 |
for (s = dynobj->sections; s != NULL; s = s->next) |
for (s = dynobj->sections; s != NULL; s = s->next) |
1619 |
{ |
{ |
1620 |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
1629 |
} |
} |
1630 |
else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) |
else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) |
1631 |
{ |
{ |
1632 |
if (s->_raw_size != 0 && s != htab->srelplt) |
if (s->size != 0 && s != htab->srelplt) |
1633 |
relocs = true; |
relocs = TRUE; |
1634 |
|
|
1635 |
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
1636 |
to copy relocs into the output file. */ |
to copy relocs into the output file. */ |
1642 |
continue; |
continue; |
1643 |
} |
} |
1644 |
|
|
1645 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1646 |
{ |
{ |
1647 |
/* If we don't need this section, strip it from the |
/* If we don't need this section, strip it from the |
1648 |
output file. This is mostly to handle .rela.bss and |
output file. This is mostly to handle .rela.bss and |
1663 |
section's contents are written out. This should not happen, |
section's contents are written out. This should not happen, |
1664 |
but this way if it does, we get a R_X86_64_NONE reloc instead |
but this way if it does, we get a R_X86_64_NONE reloc instead |
1665 |
of garbage. */ |
of garbage. */ |
1666 |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); |
1667 |
if (s->contents == NULL) |
if (s->contents == NULL) |
1668 |
return false; |
return FALSE; |
1669 |
} |
} |
1670 |
|
|
1671 |
if (htab->elf.dynamic_sections_created) |
if (htab->elf.dynamic_sections_created) |
1676 |
the .dynamic section. The DT_DEBUG entry is filled in by the |
the .dynamic section. The DT_DEBUG entry is filled in by the |
1677 |
dynamic linker and used by the debugger. */ |
dynamic linker and used by the debugger. */ |
1678 |
#define add_dynamic_entry(TAG, VAL) \ |
#define add_dynamic_entry(TAG, VAL) \ |
1679 |
bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) |
_bfd_elf_add_dynamic_entry (info, TAG, VAL) |
1680 |
|
|
1681 |
if (! info->shared) |
if (info->executable) |
1682 |
{ |
{ |
1683 |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
1684 |
return false; |
return FALSE; |
1685 |
} |
} |
1686 |
|
|
1687 |
if (htab->splt->_raw_size != 0) |
if (htab->splt->size != 0) |
1688 |
{ |
{ |
1689 |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
if (!add_dynamic_entry (DT_PLTGOT, 0) |
1690 |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
1691 |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
1692 |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
1693 |
return false; |
return FALSE; |
1694 |
} |
} |
1695 |
|
|
1696 |
if (relocs) |
if (relocs) |
1698 |
if (!add_dynamic_entry (DT_RELA, 0) |
if (!add_dynamic_entry (DT_RELA, 0) |
1699 |
|| !add_dynamic_entry (DT_RELASZ, 0) |
|| !add_dynamic_entry (DT_RELASZ, 0) |
1700 |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela))) |
1701 |
return false; |
return FALSE; |
1702 |
|
|
1703 |
/* If any dynamic relocs apply to a read-only section, |
/* If any dynamic relocs apply to a read-only section, |
1704 |
then we need a DT_TEXTREL entry. */ |
then we need a DT_TEXTREL entry. */ |
1709 |
if ((info->flags & DF_TEXTREL) != 0) |
if ((info->flags & DF_TEXTREL) != 0) |
1710 |
{ |
{ |
1711 |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
1712 |
return false; |
return FALSE; |
1713 |
} |
} |
1714 |
} |
} |
1715 |
} |
} |
1716 |
#undef add_dynamic_entry |
#undef add_dynamic_entry |
1717 |
|
|
1718 |
return true; |
return TRUE; |
1719 |
|
} |
1720 |
|
|
1721 |
|
/* Return the base VMA address which should be subtracted from real addresses |
1722 |
|
when resolving @dtpoff relocation. |
1723 |
|
This is PT_TLS segment p_vaddr. */ |
1724 |
|
|
1725 |
|
static bfd_vma |
1726 |
|
dtpoff_base (struct bfd_link_info *info) |
1727 |
|
{ |
1728 |
|
/* If tls_sec is NULL, we should have signalled an error already. */ |
1729 |
|
if (elf_hash_table (info)->tls_sec == NULL) |
1730 |
|
return 0; |
1731 |
|
return elf_hash_table (info)->tls_sec->vma; |
1732 |
|
} |
1733 |
|
|
1734 |
|
/* Return the relocation value for @tpoff relocation |
1735 |
|
if STT_TLS virtual address is ADDRESS. */ |
1736 |
|
|
1737 |
|
static bfd_vma |
1738 |
|
tpoff (struct bfd_link_info *info, bfd_vma address) |
1739 |
|
{ |
1740 |
|
struct elf_link_hash_table *htab = elf_hash_table (info); |
1741 |
|
|
1742 |
|
/* If tls_segment is NULL, we should have signalled an error already. */ |
1743 |
|
if (htab->tls_sec == NULL) |
1744 |
|
return 0; |
1745 |
|
return address - htab->tls_size - htab->tls_sec->vma; |
1746 |
|
} |
1747 |
|
|
1748 |
|
/* Is the instruction before OFFSET in CONTENTS a 32bit relative |
1749 |
|
branch? */ |
1750 |
|
|
1751 |
|
static bfd_boolean |
1752 |
|
is_32bit_relative_branch (bfd_byte *contents, bfd_vma offset) |
1753 |
|
{ |
1754 |
|
/* Opcode Instruction |
1755 |
|
0xe8 call |
1756 |
|
0xe9 jump |
1757 |
|
0x0f 0x8x conditional jump */ |
1758 |
|
return ((offset > 0 |
1759 |
|
&& (contents [offset - 1] == 0xe8 |
1760 |
|
|| contents [offset - 1] == 0xe9)) |
1761 |
|
|| (offset > 1 |
1762 |
|
&& contents [offset - 2] == 0x0f |
1763 |
|
&& (contents [offset - 1] & 0xf0) == 0x80)); |
1764 |
} |
} |
1765 |
|
|
1766 |
/* Relocate an x86_64 ELF section. */ |
/* Relocate an x86_64 ELF section. */ |
1767 |
|
|
1768 |
static boolean |
static bfd_boolean |
1769 |
elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, |
elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info, |
1770 |
contents, relocs, local_syms, local_sections) |
bfd *input_bfd, asection *input_section, |
1771 |
bfd *output_bfd; |
bfd_byte *contents, Elf_Internal_Rela *relocs, |
1772 |
struct bfd_link_info *info; |
Elf_Internal_Sym *local_syms, |
1773 |
bfd *input_bfd; |
asection **local_sections) |
|
asection *input_section; |
|
|
bfd_byte *contents; |
|
|
Elf_Internal_Rela *relocs; |
|
|
Elf_Internal_Sym *local_syms; |
|
|
asection **local_sections; |
|
1774 |
{ |
{ |
1775 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
1776 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
1779 |
Elf_Internal_Rela *rel; |
Elf_Internal_Rela *rel; |
1780 |
Elf_Internal_Rela *relend; |
Elf_Internal_Rela *relend; |
1781 |
|
|
1782 |
if (info->relocateable) |
if (info->relocatable) |
1783 |
return true; |
return TRUE; |
1784 |
|
|
1785 |
htab = elf64_x86_64_hash_table (info); |
htab = elf64_x86_64_hash_table (info); |
1786 |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
1791 |
relend = relocs + input_section->reloc_count; |
relend = relocs + input_section->reloc_count; |
1792 |
for (; rel < relend; rel++) |
for (; rel < relend; rel++) |
1793 |
{ |
{ |
1794 |
int r_type; |
unsigned int r_type; |
1795 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
1796 |
unsigned long r_symndx; |
unsigned long r_symndx; |
1797 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
1799 |
asection *sec; |
asection *sec; |
1800 |
bfd_vma off; |
bfd_vma off; |
1801 |
bfd_vma relocation; |
bfd_vma relocation; |
1802 |
boolean unresolved_reloc; |
bfd_boolean unresolved_reloc; |
1803 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
1804 |
|
int tls_type; |
1805 |
|
|
1806 |
r_type = ELF64_R_TYPE (rel->r_info); |
r_type = ELF64_R_TYPE (rel->r_info); |
1807 |
if (r_type == (int) R_X86_64_GNU_VTINHERIT |
if (r_type == (int) R_X86_64_GNU_VTINHERIT |
1808 |
|| r_type == (int) R_X86_64_GNU_VTENTRY) |
|| r_type == (int) R_X86_64_GNU_VTENTRY) |
1809 |
continue; |
continue; |
1810 |
|
|
1811 |
if (r_type < 0 || r_type >= R_X86_64_max) |
if (r_type >= R_X86_64_max) |
1812 |
{ |
{ |
1813 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
1814 |
return false; |
return FALSE; |
1815 |
} |
} |
1816 |
|
|
1817 |
howto = x86_64_elf_howto_table + r_type; |
howto = x86_64_elf_howto_table + r_type; |
1819 |
h = NULL; |
h = NULL; |
1820 |
sym = NULL; |
sym = NULL; |
1821 |
sec = NULL; |
sec = NULL; |
1822 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
1823 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
1824 |
{ |
{ |
1825 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
1826 |
sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
1827 |
|
|
1828 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
1829 |
} |
} |
1830 |
else |
else |
1831 |
{ |
{ |
1832 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
bfd_boolean warned; |
|
while (h->root.type == bfd_link_hash_indirect |
|
|
|| h->root.type == bfd_link_hash_warning) |
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
1833 |
|
|
1834 |
if (h->root.type == bfd_link_hash_defined |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
1835 |
|| h->root.type == bfd_link_hash_defweak) |
r_symndx, symtab_hdr, sym_hashes, |
1836 |
{ |
h, sec, relocation, |
1837 |
sec = h->root.u.def.section; |
unresolved_reloc, warned); |
|
if (sec->output_section == NULL) |
|
|
{ |
|
|
/* Set a flag that will be cleared later if we find a |
|
|
relocation value for this symbol. output_section |
|
|
is typically NULL for symbols satisfied by a shared |
|
|
library. */ |
|
|
unresolved_reloc = true; |
|
|
relocation = 0; |
|
|
} |
|
|
else |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
relocation = 0; |
|
|
else if (info->shared |
|
|
&& (!info->symbolic || info->allow_shlib_undefined) |
|
|
&& !info->no_undefined |
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
|
relocation = 0; |
|
|
else |
|
|
{ |
|
|
if (! ((*info->callbacks->undefined_symbol) |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, |
|
|
(!info->shared || info->no_undefined |
|
|
|| ELF_ST_VISIBILITY (h->other))))) |
|
|
return false; |
|
|
relocation = 0; |
|
|
} |
|
1838 |
} |
} |
1839 |
/* When generating a shared object, the relocations handled here are |
/* When generating a shared object, the relocations handled here are |
1840 |
copied into the output file to be resolved at run time. */ |
copied into the output file to be resolved at run time. */ |
1850 |
|
|
1851 |
if (h != NULL) |
if (h != NULL) |
1852 |
{ |
{ |
1853 |
boolean dyn; |
bfd_boolean dyn; |
1854 |
|
|
1855 |
off = h->got.offset; |
off = h->got.offset; |
1856 |
dyn = htab->elf.dynamic_sections_created; |
dyn = htab->elf.dynamic_sections_created; |
1857 |
|
|
1858 |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) |
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
1859 |
|| (info->shared |
|| (info->shared |
1860 |
&& (info->symbolic |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
1861 |
|| h->dynindx == -1 |
|| (ELF_ST_VISIBILITY (h->other) |
1862 |
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) |
&& h->root.type == bfd_link_hash_undefweak)) |
|
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) |
|
1863 |
{ |
{ |
1864 |
/* This is actually a static link, or it is a -Bsymbolic |
/* This is actually a static link, or it is a -Bsymbolic |
1865 |
link and the symbol is defined locally, or the symbol |
link and the symbol is defined locally, or the symbol |
1882 |
} |
} |
1883 |
} |
} |
1884 |
else |
else |
1885 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
1886 |
} |
} |
1887 |
else |
else |
1888 |
{ |
{ |
1903 |
|
|
1904 |
if (info->shared) |
if (info->shared) |
1905 |
{ |
{ |
1906 |
asection *srelgot; |
asection *s; |
1907 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
1908 |
Elf64_External_Rela *loc; |
bfd_byte *loc; |
1909 |
|
|
1910 |
/* We need to generate a R_X86_64_RELATIVE reloc |
/* We need to generate a R_X86_64_RELATIVE reloc |
1911 |
for the dynamic linker. */ |
for the dynamic linker. */ |
1912 |
srelgot = htab->srelgot; |
s = htab->srelgot; |
1913 |
if (srelgot == NULL) |
if (s == NULL) |
1914 |
abort (); |
abort (); |
1915 |
|
|
1916 |
outrel.r_offset = (htab->sgot->output_section->vma |
outrel.r_offset = (htab->sgot->output_section->vma |
1918 |
+ off); |
+ off); |
1919 |
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
1920 |
outrel.r_addend = relocation; |
outrel.r_addend = relocation; |
1921 |
loc = (Elf64_External_Rela *) srelgot->contents; |
loc = s->contents; |
1922 |
loc += srelgot->reloc_count++; |
loc += s->reloc_count++ * sizeof (Elf64_External_Rela); |
1923 |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
1924 |
} |
} |
1925 |
|
|
1930 |
if (off >= (bfd_vma) -2) |
if (off >= (bfd_vma) -2) |
1931 |
abort (); |
abort (); |
1932 |
|
|
1933 |
relocation = htab->sgot->output_offset + off; |
relocation = htab->sgot->output_section->vma |
1934 |
if (r_type == R_X86_64_GOTPCREL) |
+ htab->sgot->output_offset + off; |
1935 |
relocation += htab->sgot->output_section->vma; |
if (r_type != R_X86_64_GOTPCREL) |
1936 |
|
relocation -= htab->sgotplt->output_section->vma |
1937 |
|
- htab->sgotplt->output_offset; |
1938 |
|
|
1939 |
break; |
break; |
1940 |
|
|
1959 |
relocation = (htab->splt->output_section->vma |
relocation = (htab->splt->output_section->vma |
1960 |
+ htab->splt->output_offset |
+ htab->splt->output_offset |
1961 |
+ h->plt.offset); |
+ h->plt.offset); |
1962 |
unresolved_reloc = false; |
unresolved_reloc = FALSE; |
1963 |
break; |
break; |
1964 |
|
|
1965 |
case R_X86_64_PC8: |
case R_X86_64_PC8: |
1966 |
case R_X86_64_PC16: |
case R_X86_64_PC16: |
1967 |
case R_X86_64_PC32: |
case R_X86_64_PC32: |
1968 |
|
if (info->shared |
1969 |
|
&& !SYMBOL_REFERENCES_LOCAL (info, h) |
1970 |
|
&& (input_section->flags & SEC_ALLOC) != 0 |
1971 |
|
&& (input_section->flags & SEC_READONLY) != 0 |
1972 |
|
&& (!h->def_regular |
1973 |
|
|| r_type != R_X86_64_PC32 |
1974 |
|
|| h->type != STT_FUNC |
1975 |
|
|| ELF_ST_VISIBILITY (h->other) != STV_PROTECTED |
1976 |
|
|| !is_32bit_relative_branch (contents, |
1977 |
|
rel->r_offset))) |
1978 |
|
{ |
1979 |
|
if (h->def_regular |
1980 |
|
&& r_type == R_X86_64_PC32 |
1981 |
|
&& h->type == STT_FUNC |
1982 |
|
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) |
1983 |
|
(*_bfd_error_handler) |
1984 |
|
(_("%B: relocation R_X86_64_PC32 against protected function `%s' can not be used when making a shared object"), |
1985 |
|
input_bfd, h->root.root.string); |
1986 |
|
else |
1987 |
|
(*_bfd_error_handler) |
1988 |
|
(_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), |
1989 |
|
input_bfd, x86_64_elf_howto_table[r_type].name, |
1990 |
|
h->root.root.string); |
1991 |
|
bfd_set_error (bfd_error_bad_value); |
1992 |
|
return FALSE; |
1993 |
|
} |
1994 |
|
/* Fall through. */ |
1995 |
|
|
1996 |
case R_X86_64_8: |
case R_X86_64_8: |
1997 |
case R_X86_64_16: |
case R_X86_64_16: |
1998 |
case R_X86_64_32: |
case R_X86_64_32: |
2008 |
break; |
break; |
2009 |
|
|
2010 |
if ((info->shared |
if ((info->shared |
2011 |
|
&& (h == NULL |
2012 |
|
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
2013 |
|
|| h->root.type != bfd_link_hash_undefweak) |
2014 |
&& ((r_type != R_X86_64_PC8 |
&& ((r_type != R_X86_64_PC8 |
2015 |
&& r_type != R_X86_64_PC16 |
&& r_type != R_X86_64_PC16 |
2016 |
&& r_type != R_X86_64_PC32) |
&& r_type != R_X86_64_PC32) |
2017 |
|| (h != NULL |
|| !SYMBOL_CALLS_LOCAL (info, h))) |
2018 |
&& h->dynindx != -1 |
|| (ELIMINATE_COPY_RELOCS |
2019 |
&& (! info->symbolic |
&& !info->shared |
|
|| (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0)))) |
|
|
|| (!info->shared |
|
2020 |
&& h != NULL |
&& h != NULL |
2021 |
&& h->dynindx != -1 |
&& h->dynindx != -1 |
2022 |
&& (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 |
&& !h->non_got_ref |
2023 |
&& (((h->elf_link_hash_flags |
&& ((h->def_dynamic |
2024 |
& ELF_LINK_HASH_DEF_DYNAMIC) != 0 |
&& !h->def_regular) |
|
&& (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0) |
|
2025 |
|| h->root.type == bfd_link_hash_undefweak |
|| h->root.type == bfd_link_hash_undefweak |
2026 |
|| h->root.type == bfd_link_hash_undefined))) |
|| h->root.type == bfd_link_hash_undefined))) |
2027 |
{ |
{ |
2028 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
2029 |
boolean skip, relocate; |
bfd_byte *loc; |
2030 |
|
bfd_boolean skip, relocate; |
2031 |
asection *sreloc; |
asection *sreloc; |
|
Elf64_External_Rela *loc; |
|
2032 |
|
|
2033 |
/* When generating a shared object, these relocations |
/* When generating a shared object, these relocations |
2034 |
are copied into the output file to be resolved at run |
are copied into the output file to be resolved at run |
2035 |
time. */ |
time. */ |
2036 |
|
skip = FALSE; |
2037 |
skip = false; |
relocate = FALSE; |
|
relocate = false; |
|
2038 |
|
|
2039 |
outrel.r_offset = |
outrel.r_offset = |
2040 |
_bfd_elf_section_offset (output_bfd, info, input_section, |
_bfd_elf_section_offset (output_bfd, info, input_section, |
2041 |
rel->r_offset); |
rel->r_offset); |
2042 |
if (outrel.r_offset == (bfd_vma) -1) |
if (outrel.r_offset == (bfd_vma) -1) |
2043 |
skip = true; |
skip = TRUE; |
2044 |
else if (outrel.r_offset == (bfd_vma) -2) |
else if (outrel.r_offset == (bfd_vma) -2) |
2045 |
skip = true, relocate = true; |
skip = TRUE, relocate = TRUE; |
2046 |
|
|
2047 |
outrel.r_offset += (input_section->output_section->vma |
outrel.r_offset += (input_section->output_section->vma |
2048 |
+ input_section->output_offset); |
+ input_section->output_offset); |
2059 |
|| r_type == R_X86_64_PC32 |
|| r_type == R_X86_64_PC32 |
2060 |
|| !info->shared |
|| !info->shared |
2061 |
|| !info->symbolic |
|| !info->symbolic |
2062 |
|| (h->elf_link_hash_flags |
|| !h->def_regular)) |
|
& ELF_LINK_HASH_DEF_REGULAR) == 0)) |
|
2063 |
{ |
{ |
2064 |
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); |
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type); |
2065 |
outrel.r_addend = rel->r_addend; |
outrel.r_addend = rel->r_addend; |
2069 |
/* This symbol is local, or marked to become local. */ |
/* This symbol is local, or marked to become local. */ |
2070 |
if (r_type == R_X86_64_64) |
if (r_type == R_X86_64_64) |
2071 |
{ |
{ |
2072 |
relocate = true; |
relocate = TRUE; |
2073 |
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
2074 |
outrel.r_addend = relocation + rel->r_addend; |
outrel.r_addend = relocation + rel->r_addend; |
2075 |
} |
} |
2077 |
{ |
{ |
2078 |
long sindx; |
long sindx; |
2079 |
|
|
2080 |
if (h == NULL) |
if (bfd_is_abs_section (sec)) |
|
sec = local_sections[r_symndx]; |
|
|
else |
|
|
{ |
|
|
BFD_ASSERT (h->root.type == bfd_link_hash_defined |
|
|
|| (h->root.type |
|
|
== bfd_link_hash_defweak)); |
|
|
sec = h->root.u.def.section; |
|
|
} |
|
|
if (sec != NULL && bfd_is_abs_section (sec)) |
|
2081 |
sindx = 0; |
sindx = 0; |
2082 |
else if (sec == NULL || sec->owner == NULL) |
else if (sec == NULL || sec->owner == NULL) |
2083 |
{ |
{ |
2084 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2085 |
return false; |
return FALSE; |
2086 |
} |
} |
2087 |
else |
else |
2088 |
{ |
{ |
2102 |
if (sreloc == NULL) |
if (sreloc == NULL) |
2103 |
abort (); |
abort (); |
2104 |
|
|
2105 |
loc = (Elf64_External_Rela *) sreloc->contents; |
loc = sreloc->contents; |
2106 |
loc += sreloc->reloc_count++; |
loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); |
2107 |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
2108 |
|
|
2109 |
/* If this reloc is against an external symbol, we do |
/* If this reloc is against an external symbol, we do |
2116 |
|
|
2117 |
break; |
break; |
2118 |
|
|
2119 |
|
case R_X86_64_TLSGD: |
2120 |
|
case R_X86_64_GOTTPOFF: |
2121 |
|
r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL); |
2122 |
|
tls_type = GOT_UNKNOWN; |
2123 |
|
if (h == NULL && local_got_offsets) |
2124 |
|
tls_type = elf64_x86_64_local_got_tls_type (input_bfd) [r_symndx]; |
2125 |
|
else if (h != NULL) |
2126 |
|
{ |
2127 |
|
tls_type = elf64_x86_64_hash_entry (h)->tls_type; |
2128 |
|
if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE) |
2129 |
|
r_type = R_X86_64_TPOFF32; |
2130 |
|
} |
2131 |
|
if (r_type == R_X86_64_TLSGD) |
2132 |
|
{ |
2133 |
|
if (tls_type == GOT_TLS_IE) |
2134 |
|
r_type = R_X86_64_GOTTPOFF; |
2135 |
|
} |
2136 |
|
|
2137 |
|
if (r_type == R_X86_64_TPOFF32) |
2138 |
|
{ |
2139 |
|
BFD_ASSERT (! unresolved_reloc); |
2140 |
|
if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD) |
2141 |
|
{ |
2142 |
|
unsigned int i; |
2143 |
|
static unsigned char tlsgd[8] |
2144 |
|
= { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 }; |
2145 |
|
|
2146 |
|
/* GD->LE transition. |
2147 |
|
.byte 0x66; leaq foo@tlsgd(%rip), %rdi |
2148 |
|
.word 0x6666; rex64; call __tls_get_addr@plt |
2149 |
|
Change it into: |
2150 |
|
movq %fs:0, %rax |
2151 |
|
leaq foo@tpoff(%rax), %rax */ |
2152 |
|
BFD_ASSERT (rel->r_offset >= 4); |
2153 |
|
for (i = 0; i < 4; i++) |
2154 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, |
2155 |
|
contents + rel->r_offset - 4 + i) |
2156 |
|
== tlsgd[i]); |
2157 |
|
BFD_ASSERT (rel->r_offset + 12 <= input_section->size); |
2158 |
|
for (i = 0; i < 4; i++) |
2159 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, |
2160 |
|
contents + rel->r_offset + 4 + i) |
2161 |
|
== tlsgd[i+4]); |
2162 |
|
BFD_ASSERT (rel + 1 < relend); |
2163 |
|
BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32); |
2164 |
|
memcpy (contents + rel->r_offset - 4, |
2165 |
|
"\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", |
2166 |
|
16); |
2167 |
|
bfd_put_32 (output_bfd, tpoff (info, relocation), |
2168 |
|
contents + rel->r_offset + 8); |
2169 |
|
/* Skip R_X86_64_PLT32. */ |
2170 |
|
rel++; |
2171 |
|
continue; |
2172 |
|
} |
2173 |
|
else |
2174 |
|
{ |
2175 |
|
unsigned int val, type, reg; |
2176 |
|
|
2177 |
|
/* IE->LE transition: |
2178 |
|
Originally it can be one of: |
2179 |
|
movq foo@gottpoff(%rip), %reg |
2180 |
|
addq foo@gottpoff(%rip), %reg |
2181 |
|
We change it into: |
2182 |
|
movq $foo, %reg |
2183 |
|
leaq foo(%reg), %reg |
2184 |
|
addq $foo, %reg. */ |
2185 |
|
BFD_ASSERT (rel->r_offset >= 3); |
2186 |
|
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 3); |
2187 |
|
BFD_ASSERT (val == 0x48 || val == 0x4c); |
2188 |
|
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); |
2189 |
|
BFD_ASSERT (type == 0x8b || type == 0x03); |
2190 |
|
reg = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); |
2191 |
|
BFD_ASSERT ((reg & 0xc7) == 5); |
2192 |
|
reg >>= 3; |
2193 |
|
BFD_ASSERT (rel->r_offset + 4 <= input_section->size); |
2194 |
|
if (type == 0x8b) |
2195 |
|
{ |
2196 |
|
/* movq */ |
2197 |
|
if (val == 0x4c) |
2198 |
|
bfd_put_8 (output_bfd, 0x49, |
2199 |
|
contents + rel->r_offset - 3); |
2200 |
|
bfd_put_8 (output_bfd, 0xc7, |
2201 |
|
contents + rel->r_offset - 2); |
2202 |
|
bfd_put_8 (output_bfd, 0xc0 | reg, |
2203 |
|
contents + rel->r_offset - 1); |
2204 |
|
} |
2205 |
|
else if (reg == 4) |
2206 |
|
{ |
2207 |
|
/* addq -> addq - addressing with %rsp/%r12 is |
2208 |
|
special */ |
2209 |
|
if (val == 0x4c) |
2210 |
|
bfd_put_8 (output_bfd, 0x49, |
2211 |
|
contents + rel->r_offset - 3); |
2212 |
|
bfd_put_8 (output_bfd, 0x81, |
2213 |
|
contents + rel->r_offset - 2); |
2214 |
|
bfd_put_8 (output_bfd, 0xc0 | reg, |
2215 |
|
contents + rel->r_offset - 1); |
2216 |
|
} |
2217 |
|
else |
2218 |
|
{ |
2219 |
|
/* addq -> leaq */ |
2220 |
|
if (val == 0x4c) |
2221 |
|
bfd_put_8 (output_bfd, 0x4d, |
2222 |
|
contents + rel->r_offset - 3); |
2223 |
|
bfd_put_8 (output_bfd, 0x8d, |
2224 |
|
contents + rel->r_offset - 2); |
2225 |
|
bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3), |
2226 |
|
contents + rel->r_offset - 1); |
2227 |
|
} |
2228 |
|
bfd_put_32 (output_bfd, tpoff (info, relocation), |
2229 |
|
contents + rel->r_offset); |
2230 |
|
continue; |
2231 |
|
} |
2232 |
|
} |
2233 |
|
|
2234 |
|
if (htab->sgot == NULL) |
2235 |
|
abort (); |
2236 |
|
|
2237 |
|
if (h != NULL) |
2238 |
|
off = h->got.offset; |
2239 |
|
else |
2240 |
|
{ |
2241 |
|
if (local_got_offsets == NULL) |
2242 |
|
abort (); |
2243 |
|
|
2244 |
|
off = local_got_offsets[r_symndx]; |
2245 |
|
} |
2246 |
|
|
2247 |
|
if ((off & 1) != 0) |
2248 |
|
off &= ~1; |
2249 |
|
else |
2250 |
|
{ |
2251 |
|
Elf_Internal_Rela outrel; |
2252 |
|
bfd_byte *loc; |
2253 |
|
int dr_type, indx; |
2254 |
|
|
2255 |
|
if (htab->srelgot == NULL) |
2256 |
|
abort (); |
2257 |
|
|
2258 |
|
outrel.r_offset = (htab->sgot->output_section->vma |
2259 |
|
+ htab->sgot->output_offset + off); |
2260 |
|
|
2261 |
|
indx = h && h->dynindx != -1 ? h->dynindx : 0; |
2262 |
|
if (r_type == R_X86_64_TLSGD) |
2263 |
|
dr_type = R_X86_64_DTPMOD64; |
2264 |
|
else |
2265 |
|
dr_type = R_X86_64_TPOFF64; |
2266 |
|
|
2267 |
|
bfd_put_64 (output_bfd, 0, htab->sgot->contents + off); |
2268 |
|
outrel.r_addend = 0; |
2269 |
|
if (dr_type == R_X86_64_TPOFF64 && indx == 0) |
2270 |
|
outrel.r_addend = relocation - dtpoff_base (info); |
2271 |
|
outrel.r_info = ELF64_R_INFO (indx, dr_type); |
2272 |
|
|
2273 |
|
loc = htab->srelgot->contents; |
2274 |
|
loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); |
2275 |
|
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
2276 |
|
|
2277 |
|
if (r_type == R_X86_64_TLSGD) |
2278 |
|
{ |
2279 |
|
if (indx == 0) |
2280 |
|
{ |
2281 |
|
BFD_ASSERT (! unresolved_reloc); |
2282 |
|
bfd_put_64 (output_bfd, |
2283 |
|
relocation - dtpoff_base (info), |
2284 |
|
htab->sgot->contents + off + GOT_ENTRY_SIZE); |
2285 |
|
} |
2286 |
|
else |
2287 |
|
{ |
2288 |
|
bfd_put_64 (output_bfd, 0, |
2289 |
|
htab->sgot->contents + off + GOT_ENTRY_SIZE); |
2290 |
|
outrel.r_info = ELF64_R_INFO (indx, |
2291 |
|
R_X86_64_DTPOFF64); |
2292 |
|
outrel.r_offset += GOT_ENTRY_SIZE; |
2293 |
|
htab->srelgot->reloc_count++; |
2294 |
|
loc += sizeof (Elf64_External_Rela); |
2295 |
|
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
2296 |
|
} |
2297 |
|
} |
2298 |
|
|
2299 |
|
if (h != NULL) |
2300 |
|
h->got.offset |= 1; |
2301 |
|
else |
2302 |
|
local_got_offsets[r_symndx] |= 1; |
2303 |
|
} |
2304 |
|
|
2305 |
|
if (off >= (bfd_vma) -2) |
2306 |
|
abort (); |
2307 |
|
if (r_type == ELF64_R_TYPE (rel->r_info)) |
2308 |
|
{ |
2309 |
|
relocation = htab->sgot->output_section->vma |
2310 |
|
+ htab->sgot->output_offset + off; |
2311 |
|
unresolved_reloc = FALSE; |
2312 |
|
} |
2313 |
|
else |
2314 |
|
{ |
2315 |
|
unsigned int i; |
2316 |
|
static unsigned char tlsgd[8] |
2317 |
|
= { 0x66, 0x48, 0x8d, 0x3d, 0x66, 0x66, 0x48, 0xe8 }; |
2318 |
|
|
2319 |
|
/* GD->IE transition. |
2320 |
|
.byte 0x66; leaq foo@tlsgd(%rip), %rdi |
2321 |
|
.word 0x6666; rex64; call __tls_get_addr@plt |
2322 |
|
Change it into: |
2323 |
|
movq %fs:0, %rax |
2324 |
|
addq foo@gottpoff(%rip), %rax */ |
2325 |
|
BFD_ASSERT (rel->r_offset >= 4); |
2326 |
|
for (i = 0; i < 4; i++) |
2327 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, |
2328 |
|
contents + rel->r_offset - 4 + i) |
2329 |
|
== tlsgd[i]); |
2330 |
|
BFD_ASSERT (rel->r_offset + 12 <= input_section->size); |
2331 |
|
for (i = 0; i < 4; i++) |
2332 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, |
2333 |
|
contents + rel->r_offset + 4 + i) |
2334 |
|
== tlsgd[i+4]); |
2335 |
|
BFD_ASSERT (rel + 1 < relend); |
2336 |
|
BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32); |
2337 |
|
memcpy (contents + rel->r_offset - 4, |
2338 |
|
"\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", |
2339 |
|
16); |
2340 |
|
|
2341 |
|
relocation = (htab->sgot->output_section->vma |
2342 |
|
+ htab->sgot->output_offset + off |
2343 |
|
- rel->r_offset |
2344 |
|
- input_section->output_section->vma |
2345 |
|
- input_section->output_offset |
2346 |
|
- 12); |
2347 |
|
bfd_put_32 (output_bfd, relocation, |
2348 |
|
contents + rel->r_offset + 8); |
2349 |
|
/* Skip R_X86_64_PLT32. */ |
2350 |
|
rel++; |
2351 |
|
continue; |
2352 |
|
} |
2353 |
|
break; |
2354 |
|
|
2355 |
|
case R_X86_64_TLSLD: |
2356 |
|
if (! info->shared) |
2357 |
|
{ |
2358 |
|
/* LD->LE transition: |
2359 |
|
Ensure it is: |
2360 |
|
leaq foo@tlsld(%rip), %rdi; call __tls_get_addr@plt. |
2361 |
|
We change it into: |
2362 |
|
.word 0x6666; .byte 0x66; movl %fs:0, %rax. */ |
2363 |
|
BFD_ASSERT (rel->r_offset >= 3); |
2364 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 3) |
2365 |
|
== 0x48); |
2366 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 2) |
2367 |
|
== 0x8d); |
2368 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 1) |
2369 |
|
== 0x3d); |
2370 |
|
BFD_ASSERT (rel->r_offset + 9 <= input_section->size); |
2371 |
|
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4) |
2372 |
|
== 0xe8); |
2373 |
|
BFD_ASSERT (rel + 1 < relend); |
2374 |
|
BFD_ASSERT (ELF64_R_TYPE (rel[1].r_info) == R_X86_64_PLT32); |
2375 |
|
memcpy (contents + rel->r_offset - 3, |
2376 |
|
"\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); |
2377 |
|
/* Skip R_X86_64_PLT32. */ |
2378 |
|
rel++; |
2379 |
|
continue; |
2380 |
|
} |
2381 |
|
|
2382 |
|
if (htab->sgot == NULL) |
2383 |
|
abort (); |
2384 |
|
|
2385 |
|
off = htab->tls_ld_got.offset; |
2386 |
|
if (off & 1) |
2387 |
|
off &= ~1; |
2388 |
|
else |
2389 |
|
{ |
2390 |
|
Elf_Internal_Rela outrel; |
2391 |
|
bfd_byte *loc; |
2392 |
|
|
2393 |
|
if (htab->srelgot == NULL) |
2394 |
|
abort (); |
2395 |
|
|
2396 |
|
outrel.r_offset = (htab->sgot->output_section->vma |
2397 |
|
+ htab->sgot->output_offset + off); |
2398 |
|
|
2399 |
|
bfd_put_64 (output_bfd, 0, |
2400 |
|
htab->sgot->contents + off); |
2401 |
|
bfd_put_64 (output_bfd, 0, |
2402 |
|
htab->sgot->contents + off + GOT_ENTRY_SIZE); |
2403 |
|
outrel.r_info = ELF64_R_INFO (0, R_X86_64_DTPMOD64); |
2404 |
|
outrel.r_addend = 0; |
2405 |
|
loc = htab->srelgot->contents; |
2406 |
|
loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); |
2407 |
|
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); |
2408 |
|
htab->tls_ld_got.offset |= 1; |
2409 |
|
} |
2410 |
|
relocation = htab->sgot->output_section->vma |
2411 |
|
+ htab->sgot->output_offset + off; |
2412 |
|
unresolved_reloc = FALSE; |
2413 |
|
break; |
2414 |
|
|
2415 |
|
case R_X86_64_DTPOFF32: |
2416 |
|
if (info->shared || (input_section->flags & SEC_CODE) == 0) |
2417 |
|
relocation -= dtpoff_base (info); |
2418 |
|
else |
2419 |
|
relocation = tpoff (info, relocation); |
2420 |
|
break; |
2421 |
|
|
2422 |
|
case R_X86_64_TPOFF32: |
2423 |
|
BFD_ASSERT (! info->shared); |
2424 |
|
relocation = tpoff (info, relocation); |
2425 |
|
break; |
2426 |
|
|
2427 |
default: |
default: |
2428 |
break; |
break; |
2429 |
} |
} |
2433 |
not process them. */ |
not process them. */ |
2434 |
if (unresolved_reloc |
if (unresolved_reloc |
2435 |
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
2436 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) |
&& h->def_dynamic)) |
2437 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2438 |
(_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), |
(_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"), |
2439 |
bfd_archive_filename (input_bfd), |
input_bfd, |
2440 |
bfd_get_section_name (input_bfd, input_section), |
input_section, |
2441 |
(long) rel->r_offset, |
(long) rel->r_offset, |
2442 |
h->root.root.string); |
h->root.root.string); |
2443 |
|
|
2457 |
symtab_hdr->sh_link, |
symtab_hdr->sh_link, |
2458 |
sym->st_name); |
sym->st_name); |
2459 |
if (name == NULL) |
if (name == NULL) |
2460 |
return false; |
return FALSE; |
2461 |
if (*name == '\0') |
if (*name == '\0') |
2462 |
name = bfd_section_name (input_bfd, sec); |
name = bfd_section_name (input_bfd, sec); |
2463 |
} |
} |
2464 |
|
|
2465 |
if (r == bfd_reloc_overflow) |
if (r == bfd_reloc_overflow) |
2466 |
{ |
{ |
2467 |
|
if (h != NULL |
2468 |
|
&& h->root.type == bfd_link_hash_undefweak |
2469 |
|
&& howto->pc_relative) |
2470 |
|
/* Ignore reloc overflow on branches to undefweak syms. */ |
2471 |
|
continue; |
2472 |
|
|
2473 |
if (! ((*info->callbacks->reloc_overflow) |
if (! ((*info->callbacks->reloc_overflow) |
2474 |
(info, name, howto->name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, howto->name, |
2475 |
input_bfd, input_section, rel->r_offset))) |
(bfd_vma) 0, input_bfd, input_section, |
2476 |
return false; |
rel->r_offset))) |
2477 |
|
return FALSE; |
2478 |
} |
} |
2479 |
else |
else |
2480 |
{ |
{ |
2481 |
(*_bfd_error_handler) |
(*_bfd_error_handler) |
2482 |
(_("%s(%s+0x%lx): reloc against `%s': error %d"), |
(_("%B(%A+0x%lx): reloc against `%s': error %d"), |
2483 |
bfd_archive_filename (input_bfd), |
input_bfd, input_section, |
|
bfd_get_section_name (input_bfd, input_section), |
|
2484 |
(long) rel->r_offset, name, (int) r); |
(long) rel->r_offset, name, (int) r); |
2485 |
return false; |
return FALSE; |
2486 |
} |
} |
2487 |
} |
} |
2488 |
} |
} |
2489 |
|
|
2490 |
return true; |
return TRUE; |
2491 |
} |
} |
2492 |
|
|
2493 |
/* Finish up dynamic symbol handling. We set the contents of various |
/* Finish up dynamic symbol handling. We set the contents of various |
2494 |
dynamic sections here. */ |
dynamic sections here. */ |
2495 |
|
|
2496 |
static boolean |
static bfd_boolean |
2497 |
elf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym) |
elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd, |
2498 |
bfd *output_bfd; |
struct bfd_link_info *info, |
2499 |
struct bfd_link_info *info; |
struct elf_link_hash_entry *h, |
2500 |
struct elf_link_hash_entry *h; |
Elf_Internal_Sym *sym) |
|
Elf_Internal_Sym *sym; |
|
2501 |
{ |
{ |
2502 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
2503 |
|
|
2508 |
bfd_vma plt_index; |
bfd_vma plt_index; |
2509 |
bfd_vma got_offset; |
bfd_vma got_offset; |
2510 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2511 |
Elf64_External_Rela *loc; |
bfd_byte *loc; |
2512 |
|
|
2513 |
/* This symbol has an entry in the procedure linkage table. Set |
/* This symbol has an entry in the procedure linkage table. Set |
2514 |
it up. */ |
it up. */ |
|
|
|
2515 |
if (h->dynindx == -1 |
if (h->dynindx == -1 |
2516 |
|| htab->splt == NULL |
|| htab->splt == NULL |
2517 |
|| htab->sgotplt == NULL |
|| htab->sgotplt == NULL |
2567 |
+ got_offset); |
+ got_offset); |
2568 |
rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT); |
rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_JUMP_SLOT); |
2569 |
rela.r_addend = 0; |
rela.r_addend = 0; |
2570 |
loc = (Elf64_External_Rela *) htab->srelplt->contents + plt_index; |
loc = htab->srelplt->contents + plt_index * sizeof (Elf64_External_Rela); |
2571 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
2572 |
|
|
2573 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
if (!h->def_regular) |
2574 |
{ |
{ |
2575 |
/* Mark the symbol as undefined, rather than as defined in |
/* Mark the symbol as undefined, rather than as defined in |
2576 |
the .plt section. Leave the value alone. This is a clue |
the .plt section. Leave the value if there were any |
2577 |
|
relocations where pointer equality matters (this is a clue |
2578 |
for the dynamic linker, to make function pointer |
for the dynamic linker, to make function pointer |
2579 |
comparisons work between an application and shared |
comparisons work between an application and shared |
2580 |
library. */ |
library), otherwise set it to zero. If a function is only |
2581 |
|
called from a binary, there is no need to slow down |
2582 |
|
shared libraries because of that. */ |
2583 |
sym->st_shndx = SHN_UNDEF; |
sym->st_shndx = SHN_UNDEF; |
2584 |
|
if (!h->pointer_equality_needed) |
2585 |
|
sym->st_value = 0; |
2586 |
} |
} |
2587 |
} |
} |
2588 |
|
|
2589 |
if (h->got.offset != (bfd_vma) -1) |
if (h->got.offset != (bfd_vma) -1 |
2590 |
|
&& elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD |
2591 |
|
&& elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE) |
2592 |
{ |
{ |
2593 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2594 |
Elf64_External_Rela *loc; |
bfd_byte *loc; |
2595 |
|
|
2596 |
/* This symbol has an entry in the global offset table. Set it |
/* This symbol has an entry in the global offset table. Set it |
2597 |
up. */ |
up. */ |
|
|
|
2598 |
if (htab->sgot == NULL || htab->srelgot == NULL) |
if (htab->sgot == NULL || htab->srelgot == NULL) |
2599 |
abort (); |
abort (); |
2600 |
|
|
2608 |
The entry in the global offset table will already have been |
The entry in the global offset table will already have been |
2609 |
initialized in the relocate_section function. */ |
initialized in the relocate_section function. */ |
2610 |
if (info->shared |
if (info->shared |
2611 |
&& (info->symbolic |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
|
|| h->dynindx == -1 |
|
|
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) |
|
|
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) |
|
2612 |
{ |
{ |
2613 |
BFD_ASSERT((h->got.offset & 1) != 0); |
BFD_ASSERT((h->got.offset & 1) != 0); |
2614 |
rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
rela.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); |
2625 |
rela.r_addend = 0; |
rela.r_addend = 0; |
2626 |
} |
} |
2627 |
|
|
2628 |
loc = (Elf64_External_Rela *) htab->srelgot->contents; |
loc = htab->srelgot->contents; |
2629 |
loc += htab->srelgot->reloc_count++; |
loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); |
2630 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
2631 |
} |
} |
2632 |
|
|
2633 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) |
if (h->needs_copy) |
2634 |
{ |
{ |
2635 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
2636 |
Elf64_External_Rela *loc; |
bfd_byte *loc; |
2637 |
|
|
2638 |
/* This symbol needs a copy reloc. Set it up. */ |
/* This symbol needs a copy reloc. Set it up. */ |
2639 |
|
|
2648 |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
2649 |
rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY); |
rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_COPY); |
2650 |
rela.r_addend = 0; |
rela.r_addend = 0; |
2651 |
loc = (Elf64_External_Rela *) htab->srelbss->contents; |
loc = htab->srelbss->contents; |
2652 |
loc += htab->srelbss->reloc_count++; |
loc += htab->srelbss->reloc_count++ * sizeof (Elf64_External_Rela); |
2653 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); |
2654 |
} |
} |
2655 |
|
|
2658 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
2659 |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
2660 |
|
|
2661 |
return true; |
return TRUE; |
2662 |
} |
} |
2663 |
|
|
2664 |
/* Used to decide how to sort relocs in an optimal manner for the |
/* Used to decide how to sort relocs in an optimal manner for the |
2665 |
dynamic linker, before writing them out. */ |
dynamic linker, before writing them out. */ |
2666 |
|
|
2667 |
static enum elf_reloc_type_class |
static enum elf_reloc_type_class |
2668 |
elf64_x86_64_reloc_type_class (rela) |
elf64_x86_64_reloc_type_class (const Elf_Internal_Rela *rela) |
|
const Elf_Internal_Rela *rela; |
|
2669 |
{ |
{ |
2670 |
switch ((int) ELF64_R_TYPE (rela->r_info)) |
switch ((int) ELF64_R_TYPE (rela->r_info)) |
2671 |
{ |
{ |
2682 |
|
|
2683 |
/* Finish up the dynamic sections. */ |
/* Finish up the dynamic sections. */ |
2684 |
|
|
2685 |
static boolean |
static bfd_boolean |
2686 |
elf64_x86_64_finish_dynamic_sections (output_bfd, info) |
elf64_x86_64_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) |
|
bfd *output_bfd; |
|
|
struct bfd_link_info *info; |
|
2687 |
{ |
{ |
2688 |
struct elf64_x86_64_link_hash_table *htab; |
struct elf64_x86_64_link_hash_table *htab; |
2689 |
bfd *dynobj; |
bfd *dynobj; |
2701 |
abort (); |
abort (); |
2702 |
|
|
2703 |
dyncon = (Elf64_External_Dyn *) sdyn->contents; |
dyncon = (Elf64_External_Dyn *) sdyn->contents; |
2704 |
dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size); |
dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size); |
2705 |
for (; dyncon < dynconend; dyncon++) |
for (; dyncon < dynconend; dyncon++) |
2706 |
{ |
{ |
2707 |
Elf_Internal_Dyn dyn; |
Elf_Internal_Dyn dyn; |
2715 |
continue; |
continue; |
2716 |
|
|
2717 |
case DT_PLTGOT: |
case DT_PLTGOT: |
2718 |
dyn.d_un.d_ptr = htab->sgot->output_section->vma; |
s = htab->sgotplt; |
2719 |
|
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; |
2720 |
break; |
break; |
2721 |
|
|
2722 |
case DT_JMPREL: |
case DT_JMPREL: |
2725 |
|
|
2726 |
case DT_PLTRELSZ: |
case DT_PLTRELSZ: |
2727 |
s = htab->srelplt->output_section; |
s = htab->srelplt->output_section; |
2728 |
if (s->_cooked_size != 0) |
dyn.d_un.d_val = s->size; |
|
dyn.d_un.d_val = s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val = s->_raw_size; |
|
2729 |
break; |
break; |
2730 |
|
|
2731 |
case DT_RELASZ: |
case DT_RELASZ: |
2739 |
if (htab->srelplt != NULL) |
if (htab->srelplt != NULL) |
2740 |
{ |
{ |
2741 |
s = htab->srelplt->output_section; |
s = htab->srelplt->output_section; |
2742 |
if (s->_cooked_size != 0) |
dyn.d_un.d_val -= s->size; |
|
dyn.d_un.d_val -= s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val -= s->_raw_size; |
|
2743 |
} |
} |
2744 |
break; |
break; |
2745 |
} |
} |
2748 |
} |
} |
2749 |
|
|
2750 |
/* Fill in the special first entry in the procedure linkage table. */ |
/* Fill in the special first entry in the procedure linkage table. */ |
2751 |
if (htab->splt && htab->splt->_raw_size > 0) |
if (htab->splt && htab->splt->size > 0) |
2752 |
{ |
{ |
2753 |
/* Fill in the first entry in the procedure linkage table. */ |
/* Fill in the first entry in the procedure linkage table. */ |
2754 |
memcpy (htab->splt->contents, elf64_x86_64_plt0_entry, |
memcpy (htab->splt->contents, elf64_x86_64_plt0_entry, |
2782 |
if (htab->sgotplt) |
if (htab->sgotplt) |
2783 |
{ |
{ |
2784 |
/* Fill in the first three entries in the global offset table. */ |
/* Fill in the first three entries in the global offset table. */ |
2785 |
if (htab->sgotplt->_raw_size > 0) |
if (htab->sgotplt->size > 0) |
2786 |
{ |
{ |
2787 |
/* Set the first entry in the global offset table to the address of |
/* Set the first entry in the global offset table to the address of |
2788 |
the dynamic section. */ |
the dynamic section. */ |
2801 |
GOT_ENTRY_SIZE; |
GOT_ENTRY_SIZE; |
2802 |
} |
} |
2803 |
|
|
2804 |
return true; |
if (htab->sgot && htab->sgot->size > 0) |
2805 |
|
elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize |
2806 |
|
= GOT_ENTRY_SIZE; |
2807 |
|
|
2808 |
|
return TRUE; |
2809 |
} |
} |
2810 |
|
|
2811 |
|
/* Return address for Ith PLT stub in section PLT, for relocation REL |
2812 |
|
or (bfd_vma) -1 if it should not be included. */ |
2813 |
|
|
2814 |
|
static bfd_vma |
2815 |
|
elf64_x86_64_plt_sym_val (bfd_vma i, const asection *plt, |
2816 |
|
const arelent *rel ATTRIBUTE_UNUSED) |
2817 |
|
{ |
2818 |
|
return plt->vma + (i + 1) * PLT_ENTRY_SIZE; |
2819 |
|
} |
2820 |
|
|
2821 |
|
/* Handle an x86-64 specific section when reading an object file. This |
2822 |
|
is called when elfcode.h finds a section with an unknown type. */ |
2823 |
|
|
2824 |
|
static bfd_boolean |
2825 |
|
elf64_x86_64_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr, const char *name) |
2826 |
|
{ |
2827 |
|
if (hdr->sh_type != SHT_X86_64_UNWIND) |
2828 |
|
return FALSE; |
2829 |
|
|
2830 |
|
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name)) |
2831 |
|
return FALSE; |
2832 |
|
|
2833 |
|
return TRUE; |
2834 |
|
} |
2835 |
|
|
2836 |
#define TARGET_LITTLE_SYM bfd_elf64_x86_64_vec |
#define TARGET_LITTLE_SYM bfd_elf64_x86_64_vec |
2837 |
#define TARGET_LITTLE_NAME "elf64-x86-64" |
#define TARGET_LITTLE_NAME "elf64-x86-64" |
2845 |
#define elf_backend_plt_readonly 1 |
#define elf_backend_plt_readonly 1 |
2846 |
#define elf_backend_want_plt_sym 0 |
#define elf_backend_want_plt_sym 0 |
2847 |
#define elf_backend_got_header_size (GOT_ENTRY_SIZE*3) |
#define elf_backend_got_header_size (GOT_ENTRY_SIZE*3) |
|
#define elf_backend_plt_header_size PLT_ENTRY_SIZE |
|
2848 |
#define elf_backend_rela_normal 1 |
#define elf_backend_rela_normal 1 |
2849 |
|
|
2850 |
#define elf_info_to_howto elf64_x86_64_info_to_howto |
#define elf_info_to_howto elf64_x86_64_info_to_howto |
2866 |
#define elf_backend_reloc_type_class elf64_x86_64_reloc_type_class |
#define elf_backend_reloc_type_class elf64_x86_64_reloc_type_class |
2867 |
#define elf_backend_relocate_section elf64_x86_64_relocate_section |
#define elf_backend_relocate_section elf64_x86_64_relocate_section |
2868 |
#define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections |
#define elf_backend_size_dynamic_sections elf64_x86_64_size_dynamic_sections |
2869 |
|
#define elf_backend_plt_sym_val elf64_x86_64_plt_sym_val |
2870 |
#define elf_backend_object_p elf64_x86_64_elf_object_p |
#define elf_backend_object_p elf64_x86_64_elf_object_p |
2871 |
|
#define bfd_elf64_mkobject elf64_x86_64_mkobject |
2872 |
|
|
2873 |
|
#define elf_backend_section_from_shdr \ |
2874 |
|
elf64_x86_64_section_from_shdr |
2875 |
|
|
2876 |
#include "elf64-target.h" |
#include "elf64-target.h" |