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