1 /* IA-64 support for 64-bit ELF 2 Copyright (C) 1998-2014 Free Software Foundation, Inc. 3 Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com> 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 3 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., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "bfd.h" 24 #include "libbfd.h" 25 #include "elf-bfd.h" 26 #include "opcode/ia64.h" 27 #include "elf/ia64.h" 28 #include "objalloc.h" 29 #include "hashtab.h" 30 #include "bfd_stdint.h" 31 #include "elfxx-ia64.h" 32 33 /* THE RULES for all the stuff the linker creates -- 34 35 GOT Entries created in response to LTOFF or LTOFF_FPTR 36 relocations. Dynamic relocs created for dynamic 37 symbols in an application; REL relocs for locals 38 in a shared library. 39 40 FPTR The canonical function descriptor. Created for local 41 symbols in applications. Descriptors for dynamic symbols 42 and local symbols in shared libraries are created by 43 ld.so. Thus there are no dynamic relocs against these 44 objects. The FPTR relocs for such _are_ passed through 45 to the dynamic relocation tables. 46 47 FULL_PLT Created for a PCREL21B relocation against a dynamic symbol. 48 Requires the creation of a PLTOFF entry. This does not 49 require any dynamic relocations. 50 51 PLTOFF Created by PLTOFF relocations. For local symbols, this 52 is an alternate function descriptor, and in shared libraries 53 requires two REL relocations. Note that this cannot be 54 transformed into an FPTR relocation, since it must be in 55 range of the GP. For dynamic symbols, this is a function 56 descriptor for a MIN_PLT entry, and requires one IPLT reloc. 57 58 MIN_PLT Created by PLTOFF entries against dynamic symbols. This 59 does not require dynamic relocations. */ 60 61 /* ia64-specific relocation. */ 62 63 #define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0]))) 64 65 /* Perform a relocation. Not much to do here as all the hard work is 66 done in elfNN_ia64_final_link_relocate. */ 67 static bfd_reloc_status_type 68 ia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, 69 asymbol *sym ATTRIBUTE_UNUSED, 70 PTR data ATTRIBUTE_UNUSED, asection *input_section, 71 bfd *output_bfd, char **error_message) 72 { 73 if (output_bfd) 74 { 75 reloc->address += input_section->output_offset; 76 return bfd_reloc_ok; 77 } 78 79 if (input_section->flags & SEC_DEBUGGING) 80 return bfd_reloc_continue; 81 82 *error_message = "Unsupported call to ia64_elf_reloc"; 83 return bfd_reloc_notsupported; 84 } 85 86 #define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \ 87 HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \ 88 ia64_elf_reloc, NAME, FALSE, 0, -1, IN) 89 90 /* This table has to be sorted according to increasing number of the 91 TYPE field. */ 92 static reloc_howto_type ia64_howto_table[] = 93 { 94 IA64_HOWTO (R_IA64_NONE, "NONE", 0, FALSE, TRUE), 95 96 IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE), 97 IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE), 98 IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE), 99 IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE), 100 IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE), 101 IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE), 102 IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE), 103 104 IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE), 105 IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE), 106 IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE), 107 IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE), 108 IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE), 109 IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE), 110 111 IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE), 112 IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE), 113 114 IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE), 115 IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE), 116 IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE), 117 IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE), 118 119 IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE), 120 IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE), 121 IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE), 122 IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE), 123 IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE), 124 125 IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE), 126 IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE), 127 IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE), 128 IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE), 129 IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE), 130 IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE), 131 IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE), 132 IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE), 133 134 IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE), 135 IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE), 136 IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE), 137 IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE), 138 IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE), 139 IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE), 140 141 IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE), 142 IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE), 143 IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE), 144 IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE), 145 146 IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE), 147 IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE), 148 IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE), 149 IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE), 150 151 IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE), 152 IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE), 153 IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE), 154 IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE), 155 156 IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE), 157 IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE), 158 IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE), 159 IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE), 160 161 IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE), 162 IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE), 163 IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE), 164 165 IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE), 166 IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE), 167 IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE), 168 IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE), 169 IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE), 170 171 IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE), 172 IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE), 173 IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE), 174 IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE), 175 IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE), 176 IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE), 177 178 IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE), 179 IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE), 180 IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE), 181 182 IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE), 183 IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE), 184 IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE), 185 IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE), 186 IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE), 187 IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE), 188 IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE), 189 IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE), 190 }; 191 192 static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1]; 193 194 /* Given a BFD reloc type, return the matching HOWTO structure. */ 195 196 reloc_howto_type * 197 ia64_elf_lookup_howto (unsigned int rtype) 198 { 199 static int inited = 0; 200 int i; 201 202 if (!inited) 203 { 204 inited = 1; 205 206 memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index)); 207 for (i = 0; i < NELEMS (ia64_howto_table); ++i) 208 elf_code_to_howto_index[ia64_howto_table[i].type] = i; 209 } 210 211 if (rtype > R_IA64_MAX_RELOC_CODE) 212 return 0; 213 i = elf_code_to_howto_index[rtype]; 214 if (i >= NELEMS (ia64_howto_table)) 215 return 0; 216 return ia64_howto_table + i; 217 } 218 219 reloc_howto_type* 220 ia64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 221 bfd_reloc_code_real_type bfd_code) 222 { 223 unsigned int rtype; 224 225 switch (bfd_code) 226 { 227 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break; 228 229 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break; 230 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break; 231 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break; 232 233 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break; 234 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break; 235 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break; 236 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break; 237 238 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break; 239 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break; 240 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break; 241 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break; 242 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break; 243 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break; 244 245 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break; 246 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break; 247 248 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break; 249 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break; 250 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break; 251 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break; 252 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break; 253 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break; 254 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break; 255 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break; 256 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break; 257 258 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break; 259 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break; 260 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break; 261 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break; 262 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break; 263 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break; 264 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break; 265 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break; 266 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break; 267 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break; 268 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break; 269 270 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break; 271 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break; 272 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break; 273 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break; 274 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break; 275 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break; 276 277 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break; 278 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break; 279 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break; 280 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break; 281 282 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break; 283 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break; 284 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break; 285 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break; 286 287 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break; 288 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break; 289 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break; 290 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break; 291 292 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break; 293 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break; 294 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break; 295 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break; 296 297 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break; 298 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break; 299 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break; 300 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break; 301 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break; 302 303 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break; 304 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break; 305 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break; 306 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break; 307 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break; 308 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break; 309 310 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break; 311 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break; 312 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break; 313 314 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break; 315 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break; 316 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break; 317 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break; 318 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break; 319 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break; 320 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break; 321 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break; 322 323 default: return 0; 324 } 325 return ia64_elf_lookup_howto (rtype); 326 } 327 328 reloc_howto_type * 329 ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 330 const char *r_name) 331 { 332 unsigned int i; 333 334 for (i = 0; 335 i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]); 336 i++) 337 if (ia64_howto_table[i].name != NULL 338 && strcasecmp (ia64_howto_table[i].name, r_name) == 0) 339 return &ia64_howto_table[i]; 340 341 return NULL; 342 } 343 344 #define BTYPE_SHIFT 6 345 #define Y_SHIFT 26 346 #define X6_SHIFT 27 347 #define X4_SHIFT 27 348 #define X3_SHIFT 33 349 #define X2_SHIFT 31 350 #define X_SHIFT 33 351 #define OPCODE_SHIFT 37 352 353 #define OPCODE_BITS (0xfLL << OPCODE_SHIFT) 354 #define X6_BITS (0x3fLL << X6_SHIFT) 355 #define X4_BITS (0xfLL << X4_SHIFT) 356 #define X3_BITS (0x7LL << X3_SHIFT) 357 #define X2_BITS (0x3LL << X2_SHIFT) 358 #define X_BITS (0x1LL << X_SHIFT) 359 #define Y_BITS (0x1LL << Y_SHIFT) 360 #define BTYPE_BITS (0x7LL << BTYPE_SHIFT) 361 #define PREDICATE_BITS (0x3fLL) 362 363 #define IS_NOP_B(i) \ 364 (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT)) 365 #define IS_NOP_F(i) \ 366 (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \ 367 == (0x1LL << X6_SHIFT)) 368 #define IS_NOP_I(i) \ 369 (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \ 370 == (0x1LL << X6_SHIFT)) 371 #define IS_NOP_M(i) \ 372 (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \ 373 == (0x1LL << X4_SHIFT)) 374 #define IS_BR_COND(i) \ 375 (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT)) 376 #define IS_BR_CALL(i) \ 377 (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT)) 378 379 bfd_boolean 380 ia64_elf_relax_br (bfd_byte *contents, bfd_vma off) 381 { 382 unsigned int template_val, mlx; 383 bfd_vma t0, t1, s0, s1, s2, br_code; 384 long br_slot; 385 bfd_byte *hit_addr; 386 387 hit_addr = (bfd_byte *) (contents + off); 388 br_slot = (intptr_t) hit_addr & 0x3; 389 hit_addr -= br_slot; 390 t0 = bfd_getl64 (hit_addr + 0); 391 t1 = bfd_getl64 (hit_addr + 8); 392 393 /* Check if we can turn br into brl. A label is always at the start 394 of the bundle. Even if there are predicates on NOPs, we still 395 perform this optimization. */ 396 template_val = t0 & 0x1e; 397 s0 = (t0 >> 5) & 0x1ffffffffffLL; 398 s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL; 399 s2 = (t1 >> 23) & 0x1ffffffffffLL; 400 switch (br_slot) 401 { 402 case 0: 403 /* Check if slot 1 and slot 2 are NOPs. Possible template is 404 BBB. We only need to check nop.b. */ 405 if (!(IS_NOP_B (s1) && IS_NOP_B (s2))) 406 return FALSE; 407 br_code = s0; 408 break; 409 case 1: 410 /* Check if slot 2 is NOP. Possible templates are MBB and BBB. 411 For BBB, slot 0 also has to be nop.b. */ 412 if (!((template_val == 0x12 /* MBB */ 413 && IS_NOP_B (s2)) 414 || (template_val == 0x16 /* BBB */ 415 && IS_NOP_B (s0) 416 && IS_NOP_B (s2)))) 417 return FALSE; 418 br_code = s1; 419 break; 420 case 2: 421 /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB, 422 MMB and MFB. For BBB, slot 0 also has to be nop.b. */ 423 if (!((template_val == 0x10 /* MIB */ 424 && IS_NOP_I (s1)) 425 || (template_val == 0x12 /* MBB */ 426 && IS_NOP_B (s1)) 427 || (template_val == 0x16 /* BBB */ 428 && IS_NOP_B (s0) 429 && IS_NOP_B (s1)) 430 || (template_val == 0x18 /* MMB */ 431 && IS_NOP_M (s1)) 432 || (template_val == 0x1c /* MFB */ 433 && IS_NOP_F (s1)))) 434 return FALSE; 435 br_code = s2; 436 break; 437 default: 438 /* It should never happen. */ 439 abort (); 440 } 441 442 /* We can turn br.cond/br.call into brl.cond/brl.call. */ 443 if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code))) 444 return FALSE; 445 446 /* Turn br into brl by setting bit 40. */ 447 br_code |= 0x1LL << 40; 448 449 /* Turn the old bundle into a MLX bundle with the same stop-bit 450 variety. */ 451 if (t0 & 0x1) 452 mlx = 0x5; 453 else 454 mlx = 0x4; 455 456 if (template_val == 0x16) 457 { 458 /* For BBB, we need to put nop.m in slot 0. We keep the original 459 predicate only if slot 0 isn't br. */ 460 if (br_slot == 0) 461 t0 = 0LL; 462 else 463 t0 &= PREDICATE_BITS << 5; 464 t0 |= 0x1LL << (X4_SHIFT + 5); 465 } 466 else 467 { 468 /* Keep the original instruction in slot 0. */ 469 t0 &= 0x1ffffffffffLL << 5; 470 } 471 472 t0 |= mlx; 473 474 /* Put brl in slot 1. */ 475 t1 = br_code << 23; 476 477 bfd_putl64 (t0, hit_addr); 478 bfd_putl64 (t1, hit_addr + 8); 479 return TRUE; 480 } 481 482 void 483 ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off) 484 { 485 int template_val; 486 bfd_byte *hit_addr; 487 bfd_vma t0, t1, i0, i1, i2; 488 489 hit_addr = (bfd_byte *) (contents + off); 490 hit_addr -= (intptr_t) hit_addr & 0x3; 491 t0 = bfd_getl64 (hit_addr); 492 t1 = bfd_getl64 (hit_addr + 8); 493 494 /* Keep the instruction in slot 0. */ 495 i0 = (t0 >> 5) & 0x1ffffffffffLL; 496 /* Use nop.b for slot 1. */ 497 i1 = 0x4000000000LL; 498 /* For slot 2, turn brl into br by masking out bit 40. */ 499 i2 = (t1 >> 23) & 0x0ffffffffffLL; 500 501 /* Turn a MLX bundle into a MBB bundle with the same stop-bit 502 variety. */ 503 if (t0 & 0x1) 504 template_val = 0x13; 505 else 506 template_val = 0x12; 507 t0 = (i1 << 46) | (i0 << 5) | template_val; 508 t1 = (i2 << 23) | (i1 >> 18); 509 510 bfd_putl64 (t0, hit_addr); 511 bfd_putl64 (t1, hit_addr + 8); 512 } 513 514 void 515 ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off) 516 { 517 int shift, r1, r3; 518 bfd_vma dword, insn; 519 520 switch ((int)off & 0x3) 521 { 522 case 0: shift = 5; break; 523 case 1: shift = 14; off += 3; break; 524 case 2: shift = 23; off += 6; break; 525 default: 526 abort (); 527 } 528 529 dword = bfd_getl64 (contents + off); 530 insn = (dword >> shift) & 0x1ffffffffffLL; 531 532 r1 = (insn >> 6) & 127; 533 r3 = (insn >> 20) & 127; 534 if (r1 == r3) 535 insn = 0x8000000; /* nop */ 536 else 537 insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */ 538 539 dword &= ~(0x1ffffffffffLL << shift); 540 dword |= (insn << shift); 541 bfd_putl64 (dword, contents + off); 542 } 543 544 bfd_reloc_status_type 546 ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type) 547 { 548 const struct ia64_operand *op; 549 int bigendian = 0, shift = 0; 550 bfd_vma t0, t1, dword; 551 ia64_insn insn; 552 enum ia64_opnd opnd; 553 const char *err; 554 size_t size = 8; 555 #ifdef BFD_HOST_U_64_BIT 556 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v; 557 #else 558 bfd_vma val = v; 559 #endif 560 561 opnd = IA64_OPND_NIL; 562 switch (r_type) 563 { 564 case R_IA64_NONE: 565 case R_IA64_LDXMOV: 566 return bfd_reloc_ok; 567 568 /* Instruction relocations. */ 569 570 case R_IA64_IMM14: 571 case R_IA64_TPREL14: 572 case R_IA64_DTPREL14: 573 opnd = IA64_OPND_IMM14; 574 break; 575 576 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break; 577 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break; 578 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break; 579 case R_IA64_PCREL21B: 580 case R_IA64_PCREL21BI: 581 opnd = IA64_OPND_TGT25c; 582 break; 583 584 case R_IA64_IMM22: 585 case R_IA64_GPREL22: 586 case R_IA64_LTOFF22: 587 case R_IA64_LTOFF22X: 588 case R_IA64_PLTOFF22: 589 case R_IA64_PCREL22: 590 case R_IA64_LTOFF_FPTR22: 591 case R_IA64_TPREL22: 592 case R_IA64_DTPREL22: 593 case R_IA64_LTOFF_TPREL22: 594 case R_IA64_LTOFF_DTPMOD22: 595 case R_IA64_LTOFF_DTPREL22: 596 opnd = IA64_OPND_IMM22; 597 break; 598 599 case R_IA64_IMM64: 600 case R_IA64_GPREL64I: 601 case R_IA64_LTOFF64I: 602 case R_IA64_PLTOFF64I: 603 case R_IA64_PCREL64I: 604 case R_IA64_FPTR64I: 605 case R_IA64_LTOFF_FPTR64I: 606 case R_IA64_TPREL64I: 607 case R_IA64_DTPREL64I: 608 opnd = IA64_OPND_IMMU64; 609 break; 610 611 /* Data relocations. */ 612 613 case R_IA64_DIR32MSB: 614 case R_IA64_GPREL32MSB: 615 case R_IA64_FPTR32MSB: 616 case R_IA64_PCREL32MSB: 617 case R_IA64_LTOFF_FPTR32MSB: 618 case R_IA64_SEGREL32MSB: 619 case R_IA64_SECREL32MSB: 620 case R_IA64_LTV32MSB: 621 case R_IA64_DTPREL32MSB: 622 size = 4; bigendian = 1; 623 break; 624 625 case R_IA64_DIR32LSB: 626 case R_IA64_GPREL32LSB: 627 case R_IA64_FPTR32LSB: 628 case R_IA64_PCREL32LSB: 629 case R_IA64_LTOFF_FPTR32LSB: 630 case R_IA64_SEGREL32LSB: 631 case R_IA64_SECREL32LSB: 632 case R_IA64_LTV32LSB: 633 case R_IA64_DTPREL32LSB: 634 size = 4; bigendian = 0; 635 break; 636 637 case R_IA64_DIR64MSB: 638 case R_IA64_GPREL64MSB: 639 case R_IA64_PLTOFF64MSB: 640 case R_IA64_FPTR64MSB: 641 case R_IA64_PCREL64MSB: 642 case R_IA64_LTOFF_FPTR64MSB: 643 case R_IA64_SEGREL64MSB: 644 case R_IA64_SECREL64MSB: 645 case R_IA64_LTV64MSB: 646 case R_IA64_TPREL64MSB: 647 case R_IA64_DTPMOD64MSB: 648 case R_IA64_DTPREL64MSB: 649 size = 8; bigendian = 1; 650 break; 651 652 case R_IA64_DIR64LSB: 653 case R_IA64_GPREL64LSB: 654 case R_IA64_PLTOFF64LSB: 655 case R_IA64_FPTR64LSB: 656 case R_IA64_PCREL64LSB: 657 case R_IA64_LTOFF_FPTR64LSB: 658 case R_IA64_SEGREL64LSB: 659 case R_IA64_SECREL64LSB: 660 case R_IA64_LTV64LSB: 661 case R_IA64_TPREL64LSB: 662 case R_IA64_DTPMOD64LSB: 663 case R_IA64_DTPREL64LSB: 664 size = 8; bigendian = 0; 665 break; 666 667 /* Unsupported / Dynamic relocations. */ 668 default: 669 return bfd_reloc_notsupported; 670 } 671 672 switch (opnd) 673 { 674 case IA64_OPND_IMMU64: 675 hit_addr -= (intptr_t) hit_addr & 0x3; 676 t0 = bfd_getl64 (hit_addr); 677 t1 = bfd_getl64 (hit_addr + 8); 678 679 /* tmpl/s: bits 0.. 5 in t0 680 slot 0: bits 5..45 in t0 681 slot 1: bits 46..63 in t0, bits 0..22 in t1 682 slot 2: bits 23..63 in t1 */ 683 684 /* First, clear the bits that form the 64 bit constant. */ 685 t0 &= ~(0x3ffffLL << 46); 686 t1 &= ~(0x7fffffLL 687 | (( (0x07fLL << 13) | (0x1ffLL << 27) 688 | (0x01fLL << 22) | (0x001LL << 21) 689 | (0x001LL << 36)) << 23)); 690 691 t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */ 692 t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */ 693 t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */ 694 | (((val >> 7) & 0x1ff) << 27) /* imm9d */ 695 | (((val >> 16) & 0x01f) << 22) /* imm5c */ 696 | (((val >> 21) & 0x001) << 21) /* ic */ 697 | (((val >> 63) & 0x001) << 36)) << 23; /* i */ 698 699 bfd_putl64 (t0, hit_addr); 700 bfd_putl64 (t1, hit_addr + 8); 701 break; 702 703 case IA64_OPND_TGT64: 704 hit_addr -= (intptr_t) hit_addr & 0x3; 705 t0 = bfd_getl64 (hit_addr); 706 t1 = bfd_getl64 (hit_addr + 8); 707 708 /* tmpl/s: bits 0.. 5 in t0 709 slot 0: bits 5..45 in t0 710 slot 1: bits 46..63 in t0, bits 0..22 in t1 711 slot 2: bits 23..63 in t1 */ 712 713 /* First, clear the bits that form the 64 bit constant. */ 714 t0 &= ~(0x3ffffLL << 46); 715 t1 &= ~(0x7fffffLL 716 | ((1LL << 36 | 0xfffffLL << 13) << 23)); 717 718 val >>= 4; 719 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */ 720 t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */ 721 t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */ 722 | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */ 723 724 bfd_putl64 (t0, hit_addr); 725 bfd_putl64 (t1, hit_addr + 8); 726 break; 727 728 default: 729 switch ((intptr_t) hit_addr & 0x3) 730 { 731 case 0: shift = 5; break; 732 case 1: shift = 14; hit_addr += 3; break; 733 case 2: shift = 23; hit_addr += 6; break; 734 case 3: return bfd_reloc_notsupported; /* shouldn't happen... */ 735 } 736 dword = bfd_getl64 (hit_addr); 737 insn = (dword >> shift) & 0x1ffffffffffLL; 738 739 op = elf64_ia64_operands + opnd; 740 err = (*op->insert) (op, val, &insn); 741 if (err) 742 return bfd_reloc_overflow; 743 744 dword &= ~(0x1ffffffffffLL << shift); 745 dword |= (insn << shift); 746 bfd_putl64 (dword, hit_addr); 747 break; 748 749 case IA64_OPND_NIL: 750 /* A data relocation. */ 751 if (bigendian) 752 if (size == 4) 753 bfd_putb32 (val, hit_addr); 754 else 755 bfd_putb64 (val, hit_addr); 756 else 757 if (size == 4) 758 bfd_putl32 (val, hit_addr); 759 else 760 bfd_putl64 (val, hit_addr); 761 break; 762 } 763 764 return bfd_reloc_ok; 765 } 766