OLD | NEW |
1 /* | 1 /* |
2 * ELF object format helpers - x86:amd64 | 2 * ELF object format helpers - x86:amd64 |
3 * | 3 * |
4 * Copyright (C) 2004-2007 Michael Urman | 4 * Copyright (C) 2004-2007 Michael Urman |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' | 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. | 25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include <util.h> | 28 #include <util.h> |
29 /*@unused@*/ RCSID("$Id: elf-x86-amd64.c 2126 2008-10-03 08:13:00Z peter $"); | 29 /*@unused@*/ RCSID("$Id: elf-x86-amd64.c 2210 2009-07-22 05:51:35Z peter $"); |
30 | 30 |
31 #include <libyasm.h> | 31 #include <libyasm.h> |
32 #define YASM_OBJFMT_ELF_INTERNAL | 32 #define YASM_OBJFMT_ELF_INTERNAL |
33 #include "elf.h" | 33 #include "elf.h" |
34 #include "elf-machine.h" | 34 #include "elf-machine.h" |
35 | 35 |
36 static elf_machine_ssym elf_x86_amd64_ssyms[] = { | 36 static elf_machine_ssym elf_x86_amd64_ssyms[] = { |
| 37 {"pltoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLTOFF64, 64}, |
37 {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32}, | 38 {"plt", ELF_SSYM_SYM_RELATIVE, R_X86_64_PLT32, 32}, |
| 39 {"gotplt", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPLT64, 64}, |
| 40 {"gotoff", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTOFF64, 64}, |
38 {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32}, | 41 {"gotpcrel", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOTPCREL, 32}, |
39 {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, | 42 {"tlsgd", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
40 R_X86_64_TLSGD, 32}, | 43 R_X86_64_TLSGD, 32}, |
41 {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, | 44 {"tlsld", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
42 R_X86_64_TLSLD, 32}, | 45 R_X86_64_TLSLD, 32}, |
43 {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, | 46 {"gottpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
44 R_X86_64_GOTTPOFF, 32}, | 47 R_X86_64_GOTTPOFF, 32}, |
45 {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, | 48 {"tpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
46 R_X86_64_TPOFF32, 32}, | 49 R_X86_64_TPOFF32, 32}, |
47 {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, | 50 {"dtpoff", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
48 R_X86_64_DTPOFF32, 32}, | 51 R_X86_64_DTPOFF32, 32}, |
49 {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32} | 52 {"got", ELF_SSYM_SYM_RELATIVE, R_X86_64_GOT32, 32}, |
| 53 {"tlsdesc", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
| 54 R_X86_64_GOTPC32_TLSDESC, 32}, |
| 55 {"tlscall", ELF_SSYM_SYM_RELATIVE|ELF_SSYM_THREAD_LOCAL, |
| 56 R_X86_64_TLSDESC_CALL, 32} |
50 }; | 57 }; |
51 | 58 |
52 static int | 59 static int |
53 elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt, yasm_symrec **ssyms) | 60 elf_x86_amd64_accepts_reloc(size_t val, yasm_symrec *wrt) |
54 { | 61 { |
55 if (wrt) { | 62 if (wrt) { |
56 size_t i; | 63 const elf_machine_ssym *ssym = (elf_machine_ssym *) |
57 for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) { | 64 yasm_symrec_get_data(wrt, &elf_ssym_symrec_data); |
58 if (wrt == ssyms[i] && val == elf_x86_amd64_ssyms[i].size) | 65 if (!ssym || val != ssym->size) |
59 return 1; | 66 return 0; |
60 } | 67 return 1; |
61 return 0; | |
62 } | 68 } |
63 return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0); | 69 return (val&(val-1)) ? 0 : ((val & (8|16|32|64)) != 0); |
64 } | 70 } |
65 | 71 |
66 static void | 72 static void |
67 elf_x86_amd64_write_symtab_entry(unsigned char *bufp, | 73 elf_x86_amd64_write_symtab_entry(unsigned char *bufp, |
68 elf_symtab_entry *entry, | 74 elf_symtab_entry *entry, |
69 yasm_intnum *value_intn, | 75 yasm_intnum *value_intn, |
70 yasm_intnum *size_intn) | 76 yasm_intnum *size_intn) |
71 { | 77 { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 yasm_intnum_destroy(nreloc); | 130 yasm_intnum_destroy(nreloc); |
125 yasm_intnum_destroy(relocsize); | 131 yasm_intnum_destroy(relocsize); |
126 | 132 |
127 YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ | 133 YASM_WRITE_32_L(bufp, symtab_idx); /* link: symtab index */ |
128 YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ | 134 YASM_WRITE_32_L(bufp, shead->index); /* info: relocated's index */ |
129 YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */ | 135 YASM_WRITE_64Z_L(bufp, RELOC64_ALIGN); /* align */ |
130 YASM_WRITE_64Z_L(bufp, RELOC64A_SIZE); /* entity size */ | 136 YASM_WRITE_64Z_L(bufp, RELOC64A_SIZE); /* entity size */ |
131 } | 137 } |
132 | 138 |
133 static void | 139 static void |
134 elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn, elf_reloc_entry *reloc) | 140 elf_x86_amd64_handle_reloc_addend(yasm_intnum *intn, |
| 141 elf_reloc_entry *reloc, |
| 142 unsigned long offset) |
135 { | 143 { |
136 /* .rela: copy value out as addend, replace original with 0 */ | 144 /* .rela: copy value out as addend, replace original with 0 */ |
137 reloc->addend = yasm_intnum_copy(intn); | 145 reloc->addend = yasm_intnum_copy(intn); |
138 yasm_intnum_zero(intn); | 146 yasm_intnum_zero(intn); |
139 } | 147 } |
140 | 148 |
141 static unsigned int | 149 static unsigned int |
142 elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc, | 150 elf_x86_amd64_map_reloc_info_to_type(elf_reloc_entry *reloc) |
143 yasm_symrec **ssyms) | |
144 { | 151 { |
145 if (reloc->wrt) { | 152 if (reloc->wrt) { |
146 size_t i; | 153 const elf_machine_ssym *ssym = (elf_machine_ssym *) |
147 for (i=0; i<NELEMS(elf_x86_amd64_ssyms); i++) { | 154 yasm_symrec_get_data(reloc->wrt, &elf_ssym_symrec_data); |
148 if (reloc->wrt == ssyms[i] && | 155 if (!ssym || reloc->valsize != ssym->size) |
149 reloc->valsize == elf_x86_amd64_ssyms[i].size) { | 156 yasm_internal_error(N_("Unsupported WRT")); |
150 /* Force TLS type; this is required by the linker. */ | |
151 if (elf_x86_amd64_ssyms[i].sym_rel & ELF_SSYM_THREAD_LOCAL) { | |
152 elf_symtab_entry *esym; | |
153 | 157 |
154 esym = yasm_symrec_get_data(reloc->reloc.sym, | 158 /* Force TLS type; this is required by the linker. */ |
155 &elf_symrec_data); | 159 if (ssym->sym_rel & ELF_SSYM_THREAD_LOCAL) { |
156 if (esym) | 160 elf_symtab_entry *esym; |
157 esym->type = STT_TLS; | 161 |
158 } | 162 esym = yasm_symrec_get_data(reloc->reloc.sym, &elf_symrec_data); |
159 /* Map PC-relative GOT to appropriate relocation */ | 163 if (esym) |
160 if (reloc->rtype_rel && | 164 esym->type = STT_TLS; |
161 elf_x86_amd64_ssyms[i].reloc == R_X86_64_GOT32) | |
162 return (unsigned char) R_X86_64_GOTPCREL; | |
163 return (unsigned char) elf_x86_amd64_ssyms[i].reloc; | |
164 } | |
165 } | 165 } |
166 yasm_internal_error(N_("Unsupported WRT")); | 166 /* Map PC-relative GOT to appropriate relocation */ |
| 167 if (reloc->rtype_rel && ssym->reloc == R_X86_64_GOT32) |
| 168 return (unsigned char) R_X86_64_GOTPCREL; |
| 169 return (unsigned char) ssym->reloc; |
| 170 } else if (reloc->is_GOT_sym && reloc->valsize == 32) { |
| 171 return (unsigned char) R_X86_64_GOTPC32; |
| 172 } else if (reloc->is_GOT_sym && reloc->valsize == 64) { |
| 173 return (unsigned char) R_X86_64_GOTPC64; |
167 } else if (reloc->rtype_rel) { | 174 } else if (reloc->rtype_rel) { |
168 switch (reloc->valsize) { | 175 switch (reloc->valsize) { |
169 case 8: return (unsigned char) R_X86_64_PC8; | 176 case 8: return (unsigned char) R_X86_64_PC8; |
170 case 16: return (unsigned char) R_X86_64_PC16; | 177 case 16: return (unsigned char) R_X86_64_PC16; |
171 case 32: return (unsigned char) R_X86_64_PC32; | 178 case 32: return (unsigned char) R_X86_64_PC32; |
| 179 case 64: return (unsigned char) R_X86_64_PC64; |
172 default: yasm_internal_error(N_("Unsupported relocation size")); | 180 default: yasm_internal_error(N_("Unsupported relocation size")); |
173 } | 181 } |
174 } else { | 182 } else { |
175 switch (reloc->valsize) { | 183 switch (reloc->valsize) { |
176 case 8: return (unsigned char) R_X86_64_8; | 184 case 8: return (unsigned char) R_X86_64_8; |
177 case 16: return (unsigned char) R_X86_64_16; | 185 case 16: return (unsigned char) R_X86_64_16; |
178 case 32: return (unsigned char) R_X86_64_32; | 186 case 32: return (unsigned char) R_X86_64_32; |
179 case 64: return (unsigned char) R_X86_64_64; | 187 case 64: return (unsigned char) R_X86_64_64; |
180 default: yasm_internal_error(N_("Unsupported relocation size")); | 188 default: yasm_internal_error(N_("Unsupported relocation size")); |
181 } | 189 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 elf_x86_amd64_write_secthead, | 248 elf_x86_amd64_write_secthead, |
241 elf_x86_amd64_write_secthead_rel, | 249 elf_x86_amd64_write_secthead_rel, |
242 elf_x86_amd64_handle_reloc_addend, | 250 elf_x86_amd64_handle_reloc_addend, |
243 elf_x86_amd64_map_reloc_info_to_type, | 251 elf_x86_amd64_map_reloc_info_to_type, |
244 elf_x86_amd64_write_reloc, | 252 elf_x86_amd64_write_reloc, |
245 elf_x86_amd64_write_proghead, | 253 elf_x86_amd64_write_proghead, |
246 elf_x86_amd64_ssyms, | 254 elf_x86_amd64_ssyms, |
247 sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0]), | 255 sizeof(elf_x86_amd64_ssyms)/sizeof(elf_x86_amd64_ssyms[0]), |
248 64 | 256 64 |
249 }; | 257 }; |
OLD | NEW |