| 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 |