111979Srdurbin/* IA-64 support for 64-bit ELF 212970Scjplummer Copyright (C) 1998-2020 Free Software Foundation, Inc. 311979Srdurbin Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 411979Srdurbin 511979Srdurbin This file is part of BFD, the Binary File Descriptor library. 611979Srdurbin 711979Srdurbin This program is free software; you can redistribute it and/or modify 811979Srdurbin it under the terms of the GNU General Public License as published by 911979Srdurbin the Free Software Foundation; either version 3 of the License, or 1011979Srdurbin (at your option) any later version. 1111979Srdurbin 1211979Srdurbin This program is distributed in the hope that it will be useful, 1311979Srdurbin but WITHOUT ANY WARRANTY; without even the implied warranty of 1411979Srdurbin MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1511979Srdurbin GNU General Public License for more details. 1611979Srdurbin 1711979Srdurbin You should have received a copy of the GNU General Public License 1811979Srdurbin along with this program; if not, write to the Free Software 1911979Srdurbin Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 2011979Srdurbin MA 02110-1301, USA. */ 2111979Srdurbin 2211979Srdurbin#include "sysdep.h" 2311979Srdurbin#include "bfd.h" 2411979Srdurbin#include "libbfd.h" 2511979Srdurbin#include "elf-bfd.h" 2611979Srdurbin#include "opcode/ia64.h" 2711979Srdurbin#include "elf/ia64.h" 2811979Srdurbin#include "objalloc.h" 2911979Srdurbin#include "hashtab.h" 3011979Srdurbin#include "elfxx-ia64.h" 3111979Srdurbin 3211979Srdurbin/* THE RULES for all the stuff the linker creates -- 3311979Srdurbin 3411979Srdurbin GOT Entries created in response to LTOFF or LTOFF_FPTR 3511979Srdurbin relocations. Dynamic relocs created for dynamic 3611979Srdurbin symbols in an application; REL relocs for locals 3711979Srdurbin in a shared library. 3811979Srdurbin 3911979Srdurbin FPTR The canonical function descriptor. Created for local 4011979Srdurbin symbols in applications. Descriptors for dynamic symbols 4111979Srdurbin and local symbols in shared libraries are created by 4211979Srdurbin ld.so. Thus there are no dynamic relocs against these 4311979Srdurbin objects. The FPTR relocs for such _are_ passed through 4411979Srdurbin to the dynamic relocation tables. 4511979Srdurbin 4611979Srdurbin FULL_PLT Created for a PCREL21B relocation against a dynamic symbol. 4711979Srdurbin Requires the creation of a PLTOFF entry. This does not 4811979Srdurbin require any dynamic relocations. 4911979Srdurbin 5011979Srdurbin PLTOFF Created by PLTOFF relocations. For local symbols, this 5111979Srdurbin is an alternate function descriptor, and in shared libraries 5211979Srdurbin requires two REL relocations. Note that this cannot be 5311979Srdurbin transformed into an FPTR relocation, since it must be in 5411979Srdurbin range of the GP. For dynamic symbols, this is a function 5511979Srdurbin descriptor for a MIN_PLT entry, and requires one IPLT reloc. 5611979Srdurbin 5711979Srdurbin MIN_PLT Created by PLTOFF entries against dynamic symbols. This 5811979Srdurbin does not require dynamic relocations. */ 5911979Srdurbin 6011979Srdurbin/* ia64-specific relocation. */ 6111979Srdurbin 6211979Srdurbin#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0]))) 6311979Srdurbin 6411979Srdurbin/* Perform a relocation. Not much to do here as all the hard work is 6511979Srdurbin done in elfNN_ia64_final_link_relocate. */ 6611979Srdurbinstatic bfd_reloc_status_type 6711979Srdurbinia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc, 6811979Srdurbin asymbol *sym ATTRIBUTE_UNUSED, 6911979Srdurbin PTR data ATTRIBUTE_UNUSED, asection *input_section, 7011979Srdurbin bfd *output_bfd, char **error_message) 7111979Srdurbin{ 7211979Srdurbin if (output_bfd) 7311979Srdurbin { 7411979Srdurbin reloc->address += input_section->output_offset; 7511979Srdurbin return bfd_reloc_ok; 7611979Srdurbin } 7711979Srdurbin 7811979Srdurbin if (input_section->flags & SEC_DEBUGGING) 7911979Srdurbin return bfd_reloc_continue; 8011979Srdurbin 8111979Srdurbin *error_message = "Unsupported call to ia64_elf_reloc"; 8211979Srdurbin return bfd_reloc_notsupported; 8311979Srdurbin} 8411979Srdurbin 8511979Srdurbin#define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN) \ 8611979Srdurbin HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed, \ 8711979Srdurbin ia64_elf_reloc, NAME, FALSE, 0, -1, IN) 8811979Srdurbin 8911979Srdurbin/* This table has to be sorted according to increasing number of the 9011979Srdurbin TYPE field. */ 9111979Srdurbinstatic reloc_howto_type ia64_howto_table[] = 9211979Srdurbin { 9311979Srdurbin IA64_HOWTO (R_IA64_NONE, "NONE", 3, FALSE, TRUE), 9411979Srdurbin 9511979Srdurbin IA64_HOWTO (R_IA64_IMM14, "IMM14", 0, FALSE, TRUE), 9611979Srdurbin IA64_HOWTO (R_IA64_IMM22, "IMM22", 0, FALSE, TRUE), 9711979Srdurbin IA64_HOWTO (R_IA64_IMM64, "IMM64", 0, FALSE, TRUE), 9811979Srdurbin IA64_HOWTO (R_IA64_DIR32MSB, "DIR32MSB", 2, FALSE, TRUE), 9911979Srdurbin IA64_HOWTO (R_IA64_DIR32LSB, "DIR32LSB", 2, FALSE, TRUE), 10011979Srdurbin IA64_HOWTO (R_IA64_DIR64MSB, "DIR64MSB", 4, FALSE, TRUE), 10111979Srdurbin IA64_HOWTO (R_IA64_DIR64LSB, "DIR64LSB", 4, FALSE, TRUE), 10211979Srdurbin 10311979Srdurbin IA64_HOWTO (R_IA64_GPREL22, "GPREL22", 0, FALSE, TRUE), 10411979Srdurbin IA64_HOWTO (R_IA64_GPREL64I, "GPREL64I", 0, FALSE, TRUE), 10511979Srdurbin IA64_HOWTO (R_IA64_GPREL32MSB, "GPREL32MSB", 2, FALSE, TRUE), 10611979Srdurbin IA64_HOWTO (R_IA64_GPREL32LSB, "GPREL32LSB", 2, FALSE, TRUE), 10711979Srdurbin IA64_HOWTO (R_IA64_GPREL64MSB, "GPREL64MSB", 4, FALSE, TRUE), 10811979Srdurbin IA64_HOWTO (R_IA64_GPREL64LSB, "GPREL64LSB", 4, FALSE, TRUE), 10911979Srdurbin 11011979Srdurbin IA64_HOWTO (R_IA64_LTOFF22, "LTOFF22", 0, FALSE, TRUE), 11111979Srdurbin IA64_HOWTO (R_IA64_LTOFF64I, "LTOFF64I", 0, FALSE, TRUE), 11211979Srdurbin 11311979Srdurbin IA64_HOWTO (R_IA64_PLTOFF22, "PLTOFF22", 0, FALSE, TRUE), 11411979Srdurbin IA64_HOWTO (R_IA64_PLTOFF64I, "PLTOFF64I", 0, FALSE, TRUE), 11511979Srdurbin IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE), 11611979Srdurbin IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE), 11711979Srdurbin 11811979Srdurbin IA64_HOWTO (R_IA64_FPTR64I, "FPTR64I", 0, FALSE, TRUE), 11911979Srdurbin IA64_HOWTO (R_IA64_FPTR32MSB, "FPTR32MSB", 2, FALSE, TRUE), 12011979Srdurbin IA64_HOWTO (R_IA64_FPTR32LSB, "FPTR32LSB", 2, FALSE, TRUE), 12111979Srdurbin IA64_HOWTO (R_IA64_FPTR64MSB, "FPTR64MSB", 4, FALSE, TRUE), 12211979Srdurbin IA64_HOWTO (R_IA64_FPTR64LSB, "FPTR64LSB", 4, FALSE, TRUE), 12311979Srdurbin 12411979Srdurbin IA64_HOWTO (R_IA64_PCREL60B, "PCREL60B", 0, TRUE, TRUE), 12511979Srdurbin IA64_HOWTO (R_IA64_PCREL21B, "PCREL21B", 0, TRUE, TRUE), 12611979Srdurbin IA64_HOWTO (R_IA64_PCREL21M, "PCREL21M", 0, TRUE, TRUE), 12711979Srdurbin IA64_HOWTO (R_IA64_PCREL21F, "PCREL21F", 0, TRUE, TRUE), 12811979Srdurbin IA64_HOWTO (R_IA64_PCREL32MSB, "PCREL32MSB", 2, TRUE, TRUE), 12911979Srdurbin IA64_HOWTO (R_IA64_PCREL32LSB, "PCREL32LSB", 2, TRUE, TRUE), 13011979Srdurbin IA64_HOWTO (R_IA64_PCREL64MSB, "PCREL64MSB", 4, TRUE, TRUE), 13111979Srdurbin IA64_HOWTO (R_IA64_PCREL64LSB, "PCREL64LSB", 4, TRUE, TRUE), 13211979Srdurbin 13311979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE), 13411979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE), 13511979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE), 13611979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE), 13711979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE), 13811979Srdurbin IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE), 13911979Srdurbin 14011979Srdurbin IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE), 14111979Srdurbin IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE), 14211979Srdurbin IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE), 14311979Srdurbin IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE), 14411979Srdurbin 14511979Srdurbin IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE), 14611979Srdurbin IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE), 14711979Srdurbin IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE), 14811979Srdurbin IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE), 14911979Srdurbin 15011979Srdurbin IA64_HOWTO (R_IA64_REL32MSB, "REL32MSB", 2, FALSE, TRUE), 15111979Srdurbin IA64_HOWTO (R_IA64_REL32LSB, "REL32LSB", 2, FALSE, TRUE), 15211979Srdurbin IA64_HOWTO (R_IA64_REL64MSB, "REL64MSB", 4, FALSE, TRUE), 15311979Srdurbin IA64_HOWTO (R_IA64_REL64LSB, "REL64LSB", 4, FALSE, TRUE), 15411979Srdurbin 15511979Srdurbin IA64_HOWTO (R_IA64_LTV32MSB, "LTV32MSB", 2, FALSE, TRUE), 15611979Srdurbin IA64_HOWTO (R_IA64_LTV32LSB, "LTV32LSB", 2, FALSE, TRUE), 15711979Srdurbin IA64_HOWTO (R_IA64_LTV64MSB, "LTV64MSB", 4, FALSE, TRUE), 15811979Srdurbin IA64_HOWTO (R_IA64_LTV64LSB, "LTV64LSB", 4, FALSE, TRUE), 15911979Srdurbin 16011979Srdurbin IA64_HOWTO (R_IA64_PCREL21BI, "PCREL21BI", 0, TRUE, TRUE), 16111979Srdurbin IA64_HOWTO (R_IA64_PCREL22, "PCREL22", 0, TRUE, TRUE), 16211979Srdurbin IA64_HOWTO (R_IA64_PCREL64I, "PCREL64I", 0, TRUE, TRUE), 16311979Srdurbin 16411979Srdurbin IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, FALSE, TRUE), 16511979Srdurbin IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, FALSE, TRUE), 16611979Srdurbin IA64_HOWTO (R_IA64_COPY, "COPY", 4, FALSE, TRUE), 16711979Srdurbin IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, FALSE, TRUE), 16811979Srdurbin IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, FALSE, TRUE), 16911979Srdurbin 17011979Srdurbin IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE), 17111979Srdurbin IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE), 17211979Srdurbin IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE), 17312975Scjplummer IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE), 17411979Srdurbin IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE), 17511979Srdurbin IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE), 17611979Srdurbin 17712975Scjplummer IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE), 17811979Srdurbin IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE), 17911979Srdurbin IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE), 18011979Srdurbin 18111979Srdurbin IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE), 18211979Srdurbin IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE), 18311979Srdurbin IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE), 18411979Srdurbin IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE), 18512970Scjplummer IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE), 18612970Scjplummer IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE), 18712970Scjplummer IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE), 18812970Scjplummer IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE), 18912970Scjplummer }; 19011979Srdurbin 19111979Srdurbinstatic unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1]; 19211979Srdurbin 19312975Scjplummer/* Given a BFD reloc type, return the matching HOWTO structure. */ 19411979Srdurbin 19512970Scjplummerreloc_howto_type * 19611979Srdurbinia64_elf_lookup_howto (unsigned int rtype) 19711979Srdurbin{ 19811979Srdurbin static bfd_boolean inited = FALSE; 19911979Srdurbin int i; 20011979Srdurbin 20112975Scjplummer if (!inited) 20211979Srdurbin { 20312970Scjplummer inited = TRUE; 20411979Srdurbin 20511979Srdurbin memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index)); 206 for (i = 0; i < NELEMS (ia64_howto_table); ++i) 207 elf_code_to_howto_index[ia64_howto_table[i].type] = i; 208 } 209 210 if (rtype > R_IA64_MAX_RELOC_CODE) 211 return NULL; 212 i = elf_code_to_howto_index[rtype]; 213 if (i >= NELEMS (ia64_howto_table)) 214 return NULL; 215 return ia64_howto_table + i; 216} 217 218reloc_howto_type * 219ia64_elf_reloc_type_lookup (bfd *abfd, 220 bfd_reloc_code_real_type bfd_code) 221{ 222 unsigned int rtype; 223 224 switch (bfd_code) 225 { 226 case BFD_RELOC_NONE: rtype = R_IA64_NONE; break; 227 228 case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break; 229 case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break; 230 case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break; 231 232 case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break; 233 case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break; 234 case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break; 235 case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break; 236 237 case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break; 238 case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break; 239 case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break; 240 case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break; 241 case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break; 242 case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break; 243 244 case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break; 245 case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break; 246 247 case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break; 248 case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break; 249 case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break; 250 case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break; 251 case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break; 252 case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break; 253 case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break; 254 case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break; 255 case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break; 256 257 case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break; 258 case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break; 259 case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break; 260 case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break; 261 case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break; 262 case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break; 263 case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break; 264 case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break; 265 case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break; 266 case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break; 267 case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break; 268 269 case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break; 270 case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break; 271 case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break; 272 case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break; 273 case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break; 274 case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break; 275 276 case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break; 277 case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break; 278 case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break; 279 case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break; 280 281 case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break; 282 case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break; 283 case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break; 284 case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break; 285 286 case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break; 287 case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break; 288 case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break; 289 case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break; 290 291 case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break; 292 case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break; 293 case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break; 294 case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break; 295 296 case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break; 297 case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break; 298 case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break; 299 case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break; 300 case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break; 301 302 case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break; 303 case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break; 304 case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break; 305 case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break; 306 case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break; 307 case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break; 308 309 case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break; 310 case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break; 311 case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break; 312 313 case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break; 314 case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break; 315 case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break; 316 case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break; 317 case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break; 318 case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break; 319 case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break; 320 case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break; 321 322 default: 323 /* xgettext:c-format */ 324 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 325 abfd, (int) bfd_code); 326 bfd_set_error (bfd_error_bad_value); 327 return NULL; 328 } 329 return ia64_elf_lookup_howto (rtype); 330} 331 332reloc_howto_type * 333ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 334 const char *r_name) 335{ 336 unsigned int i; 337 338 for (i = 0; 339 i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]); 340 i++) 341 if (ia64_howto_table[i].name != NULL 342 && strcasecmp (ia64_howto_table[i].name, r_name) == 0) 343 return &ia64_howto_table[i]; 344 345 return NULL; 346} 347 348#define BTYPE_SHIFT 6 349#define Y_SHIFT 26 350#define X6_SHIFT 27 351#define X4_SHIFT 27 352#define X3_SHIFT 33 353#define X2_SHIFT 31 354#define X_SHIFT 33 355#define OPCODE_SHIFT 37 356 357#define OPCODE_BITS (0xfLL << OPCODE_SHIFT) 358#define X6_BITS (0x3fLL << X6_SHIFT) 359#define X4_BITS (0xfLL << X4_SHIFT) 360#define X3_BITS (0x7LL << X3_SHIFT) 361#define X2_BITS (0x3LL << X2_SHIFT) 362#define X_BITS (0x1LL << X_SHIFT) 363#define Y_BITS (0x1LL << Y_SHIFT) 364#define BTYPE_BITS (0x7LL << BTYPE_SHIFT) 365#define PREDICATE_BITS (0x3fLL) 366 367#define IS_NOP_B(i) \ 368 (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT)) 369#define IS_NOP_F(i) \ 370 (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \ 371 == (0x1LL << X6_SHIFT)) 372#define IS_NOP_I(i) \ 373 (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \ 374 == (0x1LL << X6_SHIFT)) 375#define IS_NOP_M(i) \ 376 (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \ 377 == (0x1LL << X4_SHIFT)) 378#define IS_BR_COND(i) \ 379 (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT)) 380#define IS_BR_CALL(i) \ 381 (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT)) 382 383bfd_boolean 384ia64_elf_relax_br (bfd_byte *contents, bfd_vma off) 385{ 386 unsigned int template_val, mlx; 387 bfd_vma t0, t1, s0, s1, s2, br_code; 388 long br_slot; 389 bfd_byte *hit_addr; 390 391 hit_addr = (bfd_byte *) (contents + off); 392 br_slot = (intptr_t) hit_addr & 0x3; 393 hit_addr -= br_slot; 394 t0 = bfd_getl64 (hit_addr + 0); 395 t1 = bfd_getl64 (hit_addr + 8); 396 397 /* Check if we can turn br into brl. A label is always at the start 398 of the bundle. Even if there are predicates on NOPs, we still 399 perform this optimization. */ 400 template_val = t0 & 0x1e; 401 s0 = (t0 >> 5) & 0x1ffffffffffLL; 402 s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL; 403 s2 = (t1 >> 23) & 0x1ffffffffffLL; 404 switch (br_slot) 405 { 406 case 0: 407 /* Check if slot 1 and slot 2 are NOPs. Possible template is 408 BBB. We only need to check nop.b. */ 409 if (!(IS_NOP_B (s1) && IS_NOP_B (s2))) 410 return FALSE; 411 br_code = s0; 412 break; 413 case 1: 414 /* Check if slot 2 is NOP. Possible templates are MBB and BBB. 415 For BBB, slot 0 also has to be nop.b. */ 416 if (!((template_val == 0x12 /* MBB */ 417 && IS_NOP_B (s2)) 418 || (template_val == 0x16 /* BBB */ 419 && IS_NOP_B (s0) 420 && IS_NOP_B (s2)))) 421 return FALSE; 422 br_code = s1; 423 break; 424 case 2: 425 /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB, 426 MMB and MFB. For BBB, slot 0 also has to be nop.b. */ 427 if (!((template_val == 0x10 /* MIB */ 428 && IS_NOP_I (s1)) 429 || (template_val == 0x12 /* MBB */ 430 && IS_NOP_B (s1)) 431 || (template_val == 0x16 /* BBB */ 432 && IS_NOP_B (s0) 433 && IS_NOP_B (s1)) 434 || (template_val == 0x18 /* MMB */ 435 && IS_NOP_M (s1)) 436 || (template_val == 0x1c /* MFB */ 437 && IS_NOP_F (s1)))) 438 return FALSE; 439 br_code = s2; 440 break; 441 default: 442 /* It should never happen. */ 443 abort (); 444 } 445 446 /* We can turn br.cond/br.call into brl.cond/brl.call. */ 447 if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code))) 448 return FALSE; 449 450 /* Turn br into brl by setting bit 40. */ 451 br_code |= 0x1LL << 40; 452 453 /* Turn the old bundle into a MLX bundle with the same stop-bit 454 variety. */ 455 if (t0 & 0x1) 456 mlx = 0x5; 457 else 458 mlx = 0x4; 459 460 if (template_val == 0x16) 461 { 462 /* For BBB, we need to put nop.m in slot 0. We keep the original 463 predicate only if slot 0 isn't br. */ 464 if (br_slot == 0) 465 t0 = 0LL; 466 else 467 t0 &= PREDICATE_BITS << 5; 468 t0 |= 0x1LL << (X4_SHIFT + 5); 469 } 470 else 471 { 472 /* Keep the original instruction in slot 0. */ 473 t0 &= 0x1ffffffffffLL << 5; 474 } 475 476 t0 |= mlx; 477 478 /* Put brl in slot 1. */ 479 t1 = br_code << 23; 480 481 bfd_putl64 (t0, hit_addr); 482 bfd_putl64 (t1, hit_addr + 8); 483 return TRUE; 484} 485 486void 487ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off) 488{ 489 int template_val; 490 bfd_byte *hit_addr; 491 bfd_vma t0, t1, i0, i1, i2; 492 493 hit_addr = (bfd_byte *) (contents + off); 494 hit_addr -= (intptr_t) hit_addr & 0x3; 495 t0 = bfd_getl64 (hit_addr); 496 t1 = bfd_getl64 (hit_addr + 8); 497 498 /* Keep the instruction in slot 0. */ 499 i0 = (t0 >> 5) & 0x1ffffffffffLL; 500 /* Use nop.b for slot 1. */ 501 i1 = 0x4000000000LL; 502 /* For slot 2, turn brl into br by masking out bit 40. */ 503 i2 = (t1 >> 23) & 0x0ffffffffffLL; 504 505 /* Turn a MLX bundle into a MBB bundle with the same stop-bit 506 variety. */ 507 if (t0 & 0x1) 508 template_val = 0x13; 509 else 510 template_val = 0x12; 511 t0 = (i1 << 46) | (i0 << 5) | template_val; 512 t1 = (i2 << 23) | (i1 >> 18); 513 514 bfd_putl64 (t0, hit_addr); 515 bfd_putl64 (t1, hit_addr + 8); 516} 517 518void 519ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off) 520{ 521 int shift, r1, r3; 522 bfd_vma dword, insn; 523 524 switch ((int)off & 0x3) 525 { 526 case 0: shift = 5; break; 527 case 1: shift = 14; off += 3; break; 528 case 2: shift = 23; off += 6; break; 529 default: 530 abort (); 531 } 532 533 dword = bfd_getl64 (contents + off); 534 insn = (dword >> shift) & 0x1ffffffffffLL; 535 536 r1 = (insn >> 6) & 127; 537 r3 = (insn >> 20) & 127; 538 if (r1 == r3) 539 insn = 0x8000000; /* nop */ 540 else 541 insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */ 542 543 dword &= ~(0x1ffffffffffLL << shift); 544 dword |= (insn << shift); 545 bfd_putl64 (dword, contents + off); 546} 547 548bfd_reloc_status_type 549ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type) 550{ 551 const struct ia64_operand *op; 552 int bigendian = 0, shift = 0; 553 bfd_vma t0, t1, dword; 554 ia64_insn insn; 555 enum ia64_opnd opnd; 556 const char *err; 557 size_t size = 8; 558#ifdef BFD_HOST_U_64_BIT 559 BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v; 560#else 561 bfd_vma val = v; 562#endif 563 564 opnd = IA64_OPND_NIL; 565 switch (r_type) 566 { 567 case R_IA64_NONE: 568 case R_IA64_LDXMOV: 569 return bfd_reloc_ok; 570 571 /* Instruction relocations. */ 572 573 case R_IA64_IMM14: 574 case R_IA64_TPREL14: 575 case R_IA64_DTPREL14: 576 opnd = IA64_OPND_IMM14; 577 break; 578 579 case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break; 580 case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break; 581 case R_IA64_PCREL60B: opnd = IA64_OPND_TGT64; break; 582 case R_IA64_PCREL21B: 583 case R_IA64_PCREL21BI: 584 opnd = IA64_OPND_TGT25c; 585 break; 586 587 case R_IA64_IMM22: 588 case R_IA64_GPREL22: 589 case R_IA64_LTOFF22: 590 case R_IA64_LTOFF22X: 591 case R_IA64_PLTOFF22: 592 case R_IA64_PCREL22: 593 case R_IA64_LTOFF_FPTR22: 594 case R_IA64_TPREL22: 595 case R_IA64_DTPREL22: 596 case R_IA64_LTOFF_TPREL22: 597 case R_IA64_LTOFF_DTPMOD22: 598 case R_IA64_LTOFF_DTPREL22: 599 opnd = IA64_OPND_IMM22; 600 break; 601 602 case R_IA64_IMM64: 603 case R_IA64_GPREL64I: 604 case R_IA64_LTOFF64I: 605 case R_IA64_PLTOFF64I: 606 case R_IA64_PCREL64I: 607 case R_IA64_FPTR64I: 608 case R_IA64_LTOFF_FPTR64I: 609 case R_IA64_TPREL64I: 610 case R_IA64_DTPREL64I: 611 opnd = IA64_OPND_IMMU64; 612 break; 613 614 /* Data relocations. */ 615 616 case R_IA64_DIR32MSB: 617 case R_IA64_GPREL32MSB: 618 case R_IA64_FPTR32MSB: 619 case R_IA64_PCREL32MSB: 620 case R_IA64_LTOFF_FPTR32MSB: 621 case R_IA64_SEGREL32MSB: 622 case R_IA64_SECREL32MSB: 623 case R_IA64_LTV32MSB: 624 case R_IA64_DTPREL32MSB: 625 size = 4; bigendian = 1; 626 break; 627 628 case R_IA64_DIR32LSB: 629 case R_IA64_GPREL32LSB: 630 case R_IA64_FPTR32LSB: 631 case R_IA64_PCREL32LSB: 632 case R_IA64_LTOFF_FPTR32LSB: 633 case R_IA64_SEGREL32LSB: 634 case R_IA64_SECREL32LSB: 635 case R_IA64_LTV32LSB: 636 case R_IA64_DTPREL32LSB: 637 size = 4; bigendian = 0; 638 break; 639 640 case R_IA64_DIR64MSB: 641 case R_IA64_GPREL64MSB: 642 case R_IA64_PLTOFF64MSB: 643 case R_IA64_FPTR64MSB: 644 case R_IA64_PCREL64MSB: 645 case R_IA64_LTOFF_FPTR64MSB: 646 case R_IA64_SEGREL64MSB: 647 case R_IA64_SECREL64MSB: 648 case R_IA64_LTV64MSB: 649 case R_IA64_TPREL64MSB: 650 case R_IA64_DTPMOD64MSB: 651 case R_IA64_DTPREL64MSB: 652 size = 8; bigendian = 1; 653 break; 654 655 case R_IA64_DIR64LSB: 656 case R_IA64_GPREL64LSB: 657 case R_IA64_PLTOFF64LSB: 658 case R_IA64_FPTR64LSB: 659 case R_IA64_PCREL64LSB: 660 case R_IA64_LTOFF_FPTR64LSB: 661 case R_IA64_SEGREL64LSB: 662 case R_IA64_SECREL64LSB: 663 case R_IA64_LTV64LSB: 664 case R_IA64_TPREL64LSB: 665 case R_IA64_DTPMOD64LSB: 666 case R_IA64_DTPREL64LSB: 667 size = 8; bigendian = 0; 668 break; 669 670 /* Unsupported / Dynamic relocations. */ 671 default: 672 return bfd_reloc_notsupported; 673 } 674 675 switch (opnd) 676 { 677 case IA64_OPND_IMMU64: 678 hit_addr -= (intptr_t) hit_addr & 0x3; 679 t0 = bfd_getl64 (hit_addr); 680 t1 = bfd_getl64 (hit_addr + 8); 681 682 /* tmpl/s: bits 0.. 5 in t0 683 slot 0: bits 5..45 in t0 684 slot 1: bits 46..63 in t0, bits 0..22 in t1 685 slot 2: bits 23..63 in t1 */ 686 687 /* First, clear the bits that form the 64 bit constant. */ 688 t0 &= ~(0x3ffffULL << 46); 689 t1 &= ~(0x7fffffLL 690 | (( (0x07fLL << 13) | (0x1ffLL << 27) 691 | (0x01fLL << 22) | (0x001LL << 21) 692 | (0x001LL << 36)) << 23)); 693 694 t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */ 695 t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */ 696 t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */ 697 | (((val >> 7) & 0x1ff) << 27) /* imm9d */ 698 | (((val >> 16) & 0x01f) << 22) /* imm5c */ 699 | (((val >> 21) & 0x001) << 21) /* ic */ 700 | (((val >> 63) & 0x001) << 36)) << 23; /* i */ 701 702 bfd_putl64 (t0, hit_addr); 703 bfd_putl64 (t1, hit_addr + 8); 704 break; 705 706 case IA64_OPND_TGT64: 707 hit_addr -= (intptr_t) hit_addr & 0x3; 708 t0 = bfd_getl64 (hit_addr); 709 t1 = bfd_getl64 (hit_addr + 8); 710 711 /* tmpl/s: bits 0.. 5 in t0 712 slot 0: bits 5..45 in t0 713 slot 1: bits 46..63 in t0, bits 0..22 in t1 714 slot 2: bits 23..63 in t1 */ 715 716 /* First, clear the bits that form the 64 bit constant. */ 717 t0 &= ~(0x3ffffULL << 46); 718 t1 &= ~(0x7fffffLL 719 | ((1LL << 36 | 0xfffffLL << 13) << 23)); 720 721 val >>= 4; 722 t0 |= ((val >> 20) & 0xffffLL) << 2 << 46; /* 16 lsbs of imm39 */ 723 t1 |= ((val >> 36) & 0x7fffffLL) << 0; /* 23 msbs of imm39 */ 724 t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */ 725 | (((val >> 59) & 0x1LL) << 36)) << 23; /* i */ 726 727 bfd_putl64 (t0, hit_addr); 728 bfd_putl64 (t1, hit_addr + 8); 729 break; 730 731 default: 732 switch ((intptr_t) hit_addr & 0x3) 733 { 734 case 0: shift = 5; break; 735 case 1: shift = 14; hit_addr += 3; break; 736 case 2: shift = 23; hit_addr += 6; break; 737 case 3: return bfd_reloc_notsupported; /* shouldn't happen... */ 738 } 739 dword = bfd_getl64 (hit_addr); 740 insn = (dword >> shift) & 0x1ffffffffffLL; 741 742 op = elf64_ia64_operands + opnd; 743 err = (*op->insert) (op, val, &insn); 744 if (err) 745 return bfd_reloc_overflow; 746 747 dword &= ~(0x1ffffffffffULL << shift); 748 dword |= (insn << shift); 749 bfd_putl64 (dword, hit_addr); 750 break; 751 752 case IA64_OPND_NIL: 753 /* A data relocation. */ 754 if (bigendian) 755 if (size == 4) 756 bfd_putb32 (val, hit_addr); 757 else 758 bfd_putb64 (val, hit_addr); 759 else 760 if (size == 4) 761 bfd_putl32 (val, hit_addr); 762 else 763 bfd_putl64 (val, hit_addr); 764 break; 765 } 766 767 return bfd_reloc_ok; 768} 769