1214082Sdim/* 32-bit ELF support for ARM 2214634Sdim Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 3214082Sdim Free Software Foundation, Inc. 4214082Sdim 5214082Sdim This file is part of BFD, the Binary File Descriptor library. 6214082Sdim 7214082Sdim This program is free software; you can redistribute it and/or modify 8214082Sdim it under the terms of the GNU General Public License as published by 9214082Sdim the Free Software Foundation; either version 2 of the License, or 10214082Sdim (at your option) any later version. 11214082Sdim 12214082Sdim This program is distributed in the hope that it will be useful, 13214082Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 14214082Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15214082Sdim GNU General Public License for more details. 16214082Sdim 17214082Sdim You should have received a copy of the GNU General Public License 18214082Sdim along with this program; if not, write to the Free Software 19214082Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20214082Sdim 21214634Sdim#include "sysdep.h" 22214082Sdim#include "bfd.h" 23214082Sdim#include "libiberty.h" 24214082Sdim#include "libbfd.h" 25214082Sdim#include "elf-bfd.h" 26214082Sdim#include "elf-vxworks.h" 27214082Sdim#include "elf/arm.h" 28214082Sdim 29214082Sdim#ifndef NUM_ELEM 30214082Sdim#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0])) 31214082Sdim#endif 32214082Sdim 33214082Sdim/* Return the relocation section associated with NAME. HTAB is the 34214082Sdim bfd's elf32_arm_link_hash_entry. */ 35214082Sdim#define RELOC_SECTION(HTAB, NAME) \ 36214082Sdim ((HTAB)->use_rel ? ".rel" NAME : ".rela" NAME) 37214082Sdim 38214082Sdim/* Return size of a relocation entry. HTAB is the bfd's 39214082Sdim elf32_arm_link_hash_entry. */ 40214082Sdim#define RELOC_SIZE(HTAB) \ 41214082Sdim ((HTAB)->use_rel \ 42214082Sdim ? sizeof (Elf32_External_Rel) \ 43214082Sdim : sizeof (Elf32_External_Rela)) 44214082Sdim 45214082Sdim/* Return function to swap relocations in. HTAB is the bfd's 46214082Sdim elf32_arm_link_hash_entry. */ 47214082Sdim#define SWAP_RELOC_IN(HTAB) \ 48214082Sdim ((HTAB)->use_rel \ 49214082Sdim ? bfd_elf32_swap_reloc_in \ 50214082Sdim : bfd_elf32_swap_reloca_in) 51214082Sdim 52214082Sdim/* Return function to swap relocations out. HTAB is the bfd's 53214082Sdim elf32_arm_link_hash_entry. */ 54214082Sdim#define SWAP_RELOC_OUT(HTAB) \ 55214082Sdim ((HTAB)->use_rel \ 56214082Sdim ? bfd_elf32_swap_reloc_out \ 57214082Sdim : bfd_elf32_swap_reloca_out) 58214082Sdim 59214082Sdim#define elf_info_to_howto 0 60214082Sdim#define elf_info_to_howto_rel elf32_arm_info_to_howto 61214082Sdim 62214082Sdim#define ARM_ELF_ABI_VERSION 0 63214157Sdim#ifdef __FreeBSD__ 64214157Sdim#define ARM_ELF_OS_ABI_VERSION ELFOSABI_FREEBSD 65214157Sdim#else 66214082Sdim#define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM 67214157Sdim#endif 68214082Sdim 69214634Sdimstatic struct elf_backend_data elf32_arm_vxworks_bed; 70214082Sdim 71214082Sdim/* Note: code such as elf32_arm_reloc_type_lookup expect to use e.g. 72214082Sdim R_ARM_PC24 as an index into this, and find the R_ARM_PC24 HOWTO 73214082Sdim in that slot. */ 74214082Sdim 75214082Sdimstatic reloc_howto_type elf32_arm_howto_table_1[] = 76214082Sdim{ 77214082Sdim /* No relocation */ 78214082Sdim HOWTO (R_ARM_NONE, /* type */ 79214082Sdim 0, /* rightshift */ 80214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 81214082Sdim 0, /* bitsize */ 82214082Sdim FALSE, /* pc_relative */ 83214082Sdim 0, /* bitpos */ 84214082Sdim complain_overflow_dont,/* complain_on_overflow */ 85214082Sdim bfd_elf_generic_reloc, /* special_function */ 86214082Sdim "R_ARM_NONE", /* name */ 87214082Sdim FALSE, /* partial_inplace */ 88214082Sdim 0, /* src_mask */ 89214082Sdim 0, /* dst_mask */ 90214082Sdim FALSE), /* pcrel_offset */ 91214082Sdim 92214082Sdim HOWTO (R_ARM_PC24, /* type */ 93214082Sdim 2, /* rightshift */ 94214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 95214082Sdim 24, /* bitsize */ 96214082Sdim TRUE, /* pc_relative */ 97214082Sdim 0, /* bitpos */ 98214082Sdim complain_overflow_signed,/* complain_on_overflow */ 99214082Sdim bfd_elf_generic_reloc, /* special_function */ 100214082Sdim "R_ARM_PC24", /* name */ 101214082Sdim FALSE, /* partial_inplace */ 102214082Sdim 0x00ffffff, /* src_mask */ 103214082Sdim 0x00ffffff, /* dst_mask */ 104214082Sdim TRUE), /* pcrel_offset */ 105214082Sdim 106214082Sdim /* 32 bit absolute */ 107214082Sdim HOWTO (R_ARM_ABS32, /* type */ 108214082Sdim 0, /* rightshift */ 109214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 110214082Sdim 32, /* bitsize */ 111214082Sdim FALSE, /* pc_relative */ 112214082Sdim 0, /* bitpos */ 113214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 114214082Sdim bfd_elf_generic_reloc, /* special_function */ 115214082Sdim "R_ARM_ABS32", /* name */ 116214082Sdim FALSE, /* partial_inplace */ 117214082Sdim 0xffffffff, /* src_mask */ 118214082Sdim 0xffffffff, /* dst_mask */ 119214082Sdim FALSE), /* pcrel_offset */ 120214082Sdim 121214082Sdim /* standard 32bit pc-relative reloc */ 122214082Sdim HOWTO (R_ARM_REL32, /* type */ 123214082Sdim 0, /* rightshift */ 124214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 125214082Sdim 32, /* bitsize */ 126214082Sdim TRUE, /* pc_relative */ 127214082Sdim 0, /* bitpos */ 128214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 129214082Sdim bfd_elf_generic_reloc, /* special_function */ 130214082Sdim "R_ARM_REL32", /* name */ 131214082Sdim FALSE, /* partial_inplace */ 132214082Sdim 0xffffffff, /* src_mask */ 133214082Sdim 0xffffffff, /* dst_mask */ 134214082Sdim TRUE), /* pcrel_offset */ 135214082Sdim 136214082Sdim /* 8 bit absolute - R_ARM_LDR_PC_G0 in AAELF */ 137214634Sdim HOWTO (R_ARM_LDR_PC_G0, /* type */ 138214082Sdim 0, /* rightshift */ 139214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 140214634Sdim 32, /* bitsize */ 141214634Sdim TRUE, /* pc_relative */ 142214082Sdim 0, /* bitpos */ 143214634Sdim complain_overflow_dont,/* complain_on_overflow */ 144214082Sdim bfd_elf_generic_reloc, /* special_function */ 145214634Sdim "R_ARM_LDR_PC_G0", /* name */ 146214082Sdim FALSE, /* partial_inplace */ 147214634Sdim 0xffffffff, /* src_mask */ 148214634Sdim 0xffffffff, /* dst_mask */ 149214634Sdim TRUE), /* pcrel_offset */ 150214082Sdim 151214082Sdim /* 16 bit absolute */ 152214082Sdim HOWTO (R_ARM_ABS16, /* type */ 153214082Sdim 0, /* rightshift */ 154214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 155214082Sdim 16, /* bitsize */ 156214082Sdim FALSE, /* pc_relative */ 157214082Sdim 0, /* bitpos */ 158214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 159214082Sdim bfd_elf_generic_reloc, /* special_function */ 160214082Sdim "R_ARM_ABS16", /* name */ 161214082Sdim FALSE, /* partial_inplace */ 162214082Sdim 0x0000ffff, /* src_mask */ 163214082Sdim 0x0000ffff, /* dst_mask */ 164214082Sdim FALSE), /* pcrel_offset */ 165214082Sdim 166214082Sdim /* 12 bit absolute */ 167214082Sdim HOWTO (R_ARM_ABS12, /* type */ 168214082Sdim 0, /* rightshift */ 169214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 170214082Sdim 12, /* bitsize */ 171214082Sdim FALSE, /* pc_relative */ 172214082Sdim 0, /* bitpos */ 173214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 174214082Sdim bfd_elf_generic_reloc, /* special_function */ 175214082Sdim "R_ARM_ABS12", /* name */ 176214082Sdim FALSE, /* partial_inplace */ 177214082Sdim 0x00000fff, /* src_mask */ 178214082Sdim 0x00000fff, /* dst_mask */ 179214082Sdim FALSE), /* pcrel_offset */ 180214082Sdim 181214082Sdim HOWTO (R_ARM_THM_ABS5, /* type */ 182214082Sdim 6, /* rightshift */ 183214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 184214082Sdim 5, /* bitsize */ 185214082Sdim FALSE, /* pc_relative */ 186214082Sdim 0, /* bitpos */ 187214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 188214082Sdim bfd_elf_generic_reloc, /* special_function */ 189214082Sdim "R_ARM_THM_ABS5", /* name */ 190214082Sdim FALSE, /* partial_inplace */ 191214082Sdim 0x000007e0, /* src_mask */ 192214082Sdim 0x000007e0, /* dst_mask */ 193214082Sdim FALSE), /* pcrel_offset */ 194214082Sdim 195214082Sdim /* 8 bit absolute */ 196214082Sdim HOWTO (R_ARM_ABS8, /* type */ 197214082Sdim 0, /* rightshift */ 198214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 199214082Sdim 8, /* bitsize */ 200214082Sdim FALSE, /* pc_relative */ 201214082Sdim 0, /* bitpos */ 202214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 203214082Sdim bfd_elf_generic_reloc, /* special_function */ 204214082Sdim "R_ARM_ABS8", /* name */ 205214082Sdim FALSE, /* partial_inplace */ 206214082Sdim 0x000000ff, /* src_mask */ 207214082Sdim 0x000000ff, /* dst_mask */ 208214082Sdim FALSE), /* pcrel_offset */ 209214082Sdim 210214082Sdim HOWTO (R_ARM_SBREL32, /* type */ 211214082Sdim 0, /* rightshift */ 212214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 213214082Sdim 32, /* bitsize */ 214214082Sdim FALSE, /* pc_relative */ 215214082Sdim 0, /* bitpos */ 216214082Sdim complain_overflow_dont,/* complain_on_overflow */ 217214082Sdim bfd_elf_generic_reloc, /* special_function */ 218214082Sdim "R_ARM_SBREL32", /* name */ 219214082Sdim FALSE, /* partial_inplace */ 220214082Sdim 0xffffffff, /* src_mask */ 221214082Sdim 0xffffffff, /* dst_mask */ 222214082Sdim FALSE), /* pcrel_offset */ 223214082Sdim 224214082Sdim HOWTO (R_ARM_THM_CALL, /* type */ 225214082Sdim 1, /* rightshift */ 226214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 227214634Sdim 25, /* bitsize */ 228214082Sdim TRUE, /* pc_relative */ 229214082Sdim 0, /* bitpos */ 230214082Sdim complain_overflow_signed,/* complain_on_overflow */ 231214082Sdim bfd_elf_generic_reloc, /* special_function */ 232214082Sdim "R_ARM_THM_CALL", /* name */ 233214082Sdim FALSE, /* partial_inplace */ 234214082Sdim 0x07ff07ff, /* src_mask */ 235214082Sdim 0x07ff07ff, /* dst_mask */ 236214082Sdim TRUE), /* pcrel_offset */ 237214082Sdim 238214082Sdim HOWTO (R_ARM_THM_PC8, /* type */ 239214082Sdim 1, /* rightshift */ 240214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 241214082Sdim 8, /* bitsize */ 242214082Sdim TRUE, /* pc_relative */ 243214082Sdim 0, /* bitpos */ 244214082Sdim complain_overflow_signed,/* complain_on_overflow */ 245214082Sdim bfd_elf_generic_reloc, /* special_function */ 246214082Sdim "R_ARM_THM_PC8", /* name */ 247214082Sdim FALSE, /* partial_inplace */ 248214082Sdim 0x000000ff, /* src_mask */ 249214082Sdim 0x000000ff, /* dst_mask */ 250214082Sdim TRUE), /* pcrel_offset */ 251214082Sdim 252214082Sdim HOWTO (R_ARM_BREL_ADJ, /* type */ 253214082Sdim 1, /* rightshift */ 254214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 255214082Sdim 32, /* bitsize */ 256214082Sdim FALSE, /* pc_relative */ 257214082Sdim 0, /* bitpos */ 258214082Sdim complain_overflow_signed,/* complain_on_overflow */ 259214082Sdim bfd_elf_generic_reloc, /* special_function */ 260214082Sdim "R_ARM_BREL_ADJ", /* name */ 261214082Sdim FALSE, /* partial_inplace */ 262214082Sdim 0xffffffff, /* src_mask */ 263214082Sdim 0xffffffff, /* dst_mask */ 264214082Sdim FALSE), /* pcrel_offset */ 265214082Sdim 266214082Sdim HOWTO (R_ARM_SWI24, /* type */ 267214082Sdim 0, /* rightshift */ 268214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 269214082Sdim 0, /* bitsize */ 270214082Sdim FALSE, /* pc_relative */ 271214082Sdim 0, /* bitpos */ 272214082Sdim complain_overflow_signed,/* complain_on_overflow */ 273214082Sdim bfd_elf_generic_reloc, /* special_function */ 274214082Sdim "R_ARM_SWI24", /* name */ 275214082Sdim FALSE, /* partial_inplace */ 276214082Sdim 0x00000000, /* src_mask */ 277214082Sdim 0x00000000, /* dst_mask */ 278214082Sdim FALSE), /* pcrel_offset */ 279214082Sdim 280214082Sdim HOWTO (R_ARM_THM_SWI8, /* type */ 281214082Sdim 0, /* rightshift */ 282214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 283214082Sdim 0, /* bitsize */ 284214082Sdim FALSE, /* pc_relative */ 285214082Sdim 0, /* bitpos */ 286214082Sdim complain_overflow_signed,/* complain_on_overflow */ 287214082Sdim bfd_elf_generic_reloc, /* special_function */ 288214082Sdim "R_ARM_SWI8", /* name */ 289214082Sdim FALSE, /* partial_inplace */ 290214082Sdim 0x00000000, /* src_mask */ 291214082Sdim 0x00000000, /* dst_mask */ 292214082Sdim FALSE), /* pcrel_offset */ 293214082Sdim 294214082Sdim /* BLX instruction for the ARM. */ 295214082Sdim HOWTO (R_ARM_XPC25, /* type */ 296214082Sdim 2, /* rightshift */ 297214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 298214082Sdim 25, /* bitsize */ 299214082Sdim TRUE, /* pc_relative */ 300214082Sdim 0, /* bitpos */ 301214082Sdim complain_overflow_signed,/* complain_on_overflow */ 302214082Sdim bfd_elf_generic_reloc, /* special_function */ 303214082Sdim "R_ARM_XPC25", /* name */ 304214082Sdim FALSE, /* partial_inplace */ 305214082Sdim 0x00ffffff, /* src_mask */ 306214082Sdim 0x00ffffff, /* dst_mask */ 307214082Sdim TRUE), /* pcrel_offset */ 308214082Sdim 309214082Sdim /* BLX instruction for the Thumb. */ 310214082Sdim HOWTO (R_ARM_THM_XPC22, /* type */ 311214082Sdim 2, /* rightshift */ 312214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 313214082Sdim 22, /* bitsize */ 314214082Sdim TRUE, /* pc_relative */ 315214082Sdim 0, /* bitpos */ 316214082Sdim complain_overflow_signed,/* complain_on_overflow */ 317214082Sdim bfd_elf_generic_reloc, /* special_function */ 318214082Sdim "R_ARM_THM_XPC22", /* name */ 319214082Sdim FALSE, /* partial_inplace */ 320214082Sdim 0x07ff07ff, /* src_mask */ 321214082Sdim 0x07ff07ff, /* dst_mask */ 322214082Sdim TRUE), /* pcrel_offset */ 323214082Sdim 324214082Sdim /* Dynamic TLS relocations. */ 325214082Sdim 326214082Sdim HOWTO (R_ARM_TLS_DTPMOD32, /* type */ 327214082Sdim 0, /* rightshift */ 328214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 329214082Sdim 32, /* bitsize */ 330214082Sdim FALSE, /* pc_relative */ 331214082Sdim 0, /* bitpos */ 332214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 333214082Sdim bfd_elf_generic_reloc, /* special_function */ 334214082Sdim "R_ARM_TLS_DTPMOD32", /* name */ 335214082Sdim TRUE, /* partial_inplace */ 336214082Sdim 0xffffffff, /* src_mask */ 337214082Sdim 0xffffffff, /* dst_mask */ 338214082Sdim FALSE), /* pcrel_offset */ 339214082Sdim 340214082Sdim HOWTO (R_ARM_TLS_DTPOFF32, /* type */ 341214082Sdim 0, /* rightshift */ 342214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 343214082Sdim 32, /* bitsize */ 344214082Sdim FALSE, /* pc_relative */ 345214082Sdim 0, /* bitpos */ 346214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 347214082Sdim bfd_elf_generic_reloc, /* special_function */ 348214082Sdim "R_ARM_TLS_DTPOFF32", /* name */ 349214082Sdim TRUE, /* partial_inplace */ 350214082Sdim 0xffffffff, /* src_mask */ 351214082Sdim 0xffffffff, /* dst_mask */ 352214082Sdim FALSE), /* pcrel_offset */ 353214082Sdim 354214082Sdim HOWTO (R_ARM_TLS_TPOFF32, /* type */ 355214082Sdim 0, /* rightshift */ 356214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 357214082Sdim 32, /* bitsize */ 358214082Sdim FALSE, /* pc_relative */ 359214082Sdim 0, /* bitpos */ 360214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 361214082Sdim bfd_elf_generic_reloc, /* special_function */ 362214082Sdim "R_ARM_TLS_TPOFF32", /* name */ 363214082Sdim TRUE, /* partial_inplace */ 364214082Sdim 0xffffffff, /* src_mask */ 365214082Sdim 0xffffffff, /* dst_mask */ 366214082Sdim FALSE), /* pcrel_offset */ 367214082Sdim 368214082Sdim /* Relocs used in ARM Linux */ 369214082Sdim 370214082Sdim HOWTO (R_ARM_COPY, /* type */ 371214082Sdim 0, /* rightshift */ 372214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 373214082Sdim 32, /* bitsize */ 374214082Sdim FALSE, /* pc_relative */ 375214082Sdim 0, /* bitpos */ 376214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 377214082Sdim bfd_elf_generic_reloc, /* special_function */ 378214082Sdim "R_ARM_COPY", /* name */ 379214082Sdim TRUE, /* partial_inplace */ 380214082Sdim 0xffffffff, /* src_mask */ 381214082Sdim 0xffffffff, /* dst_mask */ 382214082Sdim FALSE), /* pcrel_offset */ 383214082Sdim 384214082Sdim HOWTO (R_ARM_GLOB_DAT, /* type */ 385214082Sdim 0, /* rightshift */ 386214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 387214082Sdim 32, /* bitsize */ 388214082Sdim FALSE, /* pc_relative */ 389214082Sdim 0, /* bitpos */ 390214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 391214082Sdim bfd_elf_generic_reloc, /* special_function */ 392214082Sdim "R_ARM_GLOB_DAT", /* name */ 393214082Sdim TRUE, /* partial_inplace */ 394214082Sdim 0xffffffff, /* src_mask */ 395214082Sdim 0xffffffff, /* dst_mask */ 396214082Sdim FALSE), /* pcrel_offset */ 397214082Sdim 398214082Sdim HOWTO (R_ARM_JUMP_SLOT, /* type */ 399214082Sdim 0, /* rightshift */ 400214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 401214082Sdim 32, /* bitsize */ 402214082Sdim FALSE, /* pc_relative */ 403214082Sdim 0, /* bitpos */ 404214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 405214082Sdim bfd_elf_generic_reloc, /* special_function */ 406214082Sdim "R_ARM_JUMP_SLOT", /* name */ 407214082Sdim TRUE, /* partial_inplace */ 408214082Sdim 0xffffffff, /* src_mask */ 409214082Sdim 0xffffffff, /* dst_mask */ 410214082Sdim FALSE), /* pcrel_offset */ 411214082Sdim 412214082Sdim HOWTO (R_ARM_RELATIVE, /* type */ 413214082Sdim 0, /* rightshift */ 414214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 415214082Sdim 32, /* bitsize */ 416214082Sdim FALSE, /* pc_relative */ 417214082Sdim 0, /* bitpos */ 418214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 419214082Sdim bfd_elf_generic_reloc, /* special_function */ 420214082Sdim "R_ARM_RELATIVE", /* name */ 421214082Sdim TRUE, /* partial_inplace */ 422214082Sdim 0xffffffff, /* src_mask */ 423214082Sdim 0xffffffff, /* dst_mask */ 424214082Sdim FALSE), /* pcrel_offset */ 425214082Sdim 426214082Sdim HOWTO (R_ARM_GOTOFF32, /* type */ 427214082Sdim 0, /* rightshift */ 428214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 429214082Sdim 32, /* bitsize */ 430214082Sdim FALSE, /* pc_relative */ 431214082Sdim 0, /* bitpos */ 432214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 433214082Sdim bfd_elf_generic_reloc, /* special_function */ 434214082Sdim "R_ARM_GOTOFF32", /* name */ 435214082Sdim TRUE, /* partial_inplace */ 436214082Sdim 0xffffffff, /* src_mask */ 437214082Sdim 0xffffffff, /* dst_mask */ 438214082Sdim FALSE), /* pcrel_offset */ 439214082Sdim 440214082Sdim HOWTO (R_ARM_GOTPC, /* type */ 441214082Sdim 0, /* rightshift */ 442214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 443214082Sdim 32, /* bitsize */ 444214082Sdim TRUE, /* pc_relative */ 445214082Sdim 0, /* bitpos */ 446214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 447214082Sdim bfd_elf_generic_reloc, /* special_function */ 448214082Sdim "R_ARM_GOTPC", /* name */ 449214082Sdim TRUE, /* partial_inplace */ 450214082Sdim 0xffffffff, /* src_mask */ 451214082Sdim 0xffffffff, /* dst_mask */ 452214082Sdim TRUE), /* pcrel_offset */ 453214082Sdim 454214082Sdim HOWTO (R_ARM_GOT32, /* type */ 455214082Sdim 0, /* rightshift */ 456214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 457214082Sdim 32, /* bitsize */ 458214082Sdim FALSE, /* pc_relative */ 459214082Sdim 0, /* bitpos */ 460214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 461214082Sdim bfd_elf_generic_reloc, /* special_function */ 462214082Sdim "R_ARM_GOT32", /* name */ 463214082Sdim TRUE, /* partial_inplace */ 464214082Sdim 0xffffffff, /* src_mask */ 465214082Sdim 0xffffffff, /* dst_mask */ 466214082Sdim FALSE), /* pcrel_offset */ 467214082Sdim 468214082Sdim HOWTO (R_ARM_PLT32, /* type */ 469214082Sdim 2, /* rightshift */ 470214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 471214082Sdim 24, /* bitsize */ 472214082Sdim TRUE, /* pc_relative */ 473214082Sdim 0, /* bitpos */ 474214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 475214082Sdim bfd_elf_generic_reloc, /* special_function */ 476214082Sdim "R_ARM_PLT32", /* name */ 477214082Sdim FALSE, /* partial_inplace */ 478214082Sdim 0x00ffffff, /* src_mask */ 479214082Sdim 0x00ffffff, /* dst_mask */ 480214082Sdim TRUE), /* pcrel_offset */ 481214082Sdim 482214082Sdim HOWTO (R_ARM_CALL, /* type */ 483214082Sdim 2, /* rightshift */ 484214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 485214082Sdim 24, /* bitsize */ 486214082Sdim TRUE, /* pc_relative */ 487214082Sdim 0, /* bitpos */ 488214082Sdim complain_overflow_signed,/* complain_on_overflow */ 489214082Sdim bfd_elf_generic_reloc, /* special_function */ 490214082Sdim "R_ARM_CALL", /* name */ 491214082Sdim FALSE, /* partial_inplace */ 492214082Sdim 0x00ffffff, /* src_mask */ 493214082Sdim 0x00ffffff, /* dst_mask */ 494214082Sdim TRUE), /* pcrel_offset */ 495214082Sdim 496214082Sdim HOWTO (R_ARM_JUMP24, /* type */ 497214082Sdim 2, /* rightshift */ 498214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 499214082Sdim 24, /* bitsize */ 500214082Sdim TRUE, /* pc_relative */ 501214082Sdim 0, /* bitpos */ 502214082Sdim complain_overflow_signed,/* complain_on_overflow */ 503214082Sdim bfd_elf_generic_reloc, /* special_function */ 504214082Sdim "R_ARM_JUMP24", /* name */ 505214082Sdim FALSE, /* partial_inplace */ 506214082Sdim 0x00ffffff, /* src_mask */ 507214082Sdim 0x00ffffff, /* dst_mask */ 508214082Sdim TRUE), /* pcrel_offset */ 509214082Sdim 510214082Sdim HOWTO (R_ARM_THM_JUMP24, /* type */ 511214082Sdim 1, /* rightshift */ 512214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 513214082Sdim 24, /* bitsize */ 514214082Sdim TRUE, /* pc_relative */ 515214082Sdim 0, /* bitpos */ 516214082Sdim complain_overflow_signed,/* complain_on_overflow */ 517214082Sdim bfd_elf_generic_reloc, /* special_function */ 518214082Sdim "R_ARM_THM_JUMP24", /* name */ 519214082Sdim FALSE, /* partial_inplace */ 520214082Sdim 0x07ff2fff, /* src_mask */ 521214082Sdim 0x07ff2fff, /* dst_mask */ 522214082Sdim TRUE), /* pcrel_offset */ 523214082Sdim 524214082Sdim HOWTO (R_ARM_BASE_ABS, /* type */ 525214082Sdim 0, /* rightshift */ 526214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 527214082Sdim 32, /* bitsize */ 528214082Sdim FALSE, /* pc_relative */ 529214082Sdim 0, /* bitpos */ 530214082Sdim complain_overflow_dont,/* complain_on_overflow */ 531214082Sdim bfd_elf_generic_reloc, /* special_function */ 532214082Sdim "R_ARM_BASE_ABS", /* name */ 533214082Sdim FALSE, /* partial_inplace */ 534214082Sdim 0xffffffff, /* src_mask */ 535214082Sdim 0xffffffff, /* dst_mask */ 536214082Sdim FALSE), /* pcrel_offset */ 537214082Sdim 538214082Sdim HOWTO (R_ARM_ALU_PCREL7_0, /* type */ 539214082Sdim 0, /* rightshift */ 540214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 541214082Sdim 12, /* bitsize */ 542214082Sdim TRUE, /* pc_relative */ 543214082Sdim 0, /* bitpos */ 544214082Sdim complain_overflow_dont,/* complain_on_overflow */ 545214082Sdim bfd_elf_generic_reloc, /* special_function */ 546214082Sdim "R_ARM_ALU_PCREL_7_0", /* name */ 547214082Sdim FALSE, /* partial_inplace */ 548214082Sdim 0x00000fff, /* src_mask */ 549214082Sdim 0x00000fff, /* dst_mask */ 550214082Sdim TRUE), /* pcrel_offset */ 551214082Sdim 552214082Sdim HOWTO (R_ARM_ALU_PCREL15_8, /* type */ 553214082Sdim 0, /* rightshift */ 554214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 555214082Sdim 12, /* bitsize */ 556214082Sdim TRUE, /* pc_relative */ 557214082Sdim 8, /* bitpos */ 558214082Sdim complain_overflow_dont,/* complain_on_overflow */ 559214082Sdim bfd_elf_generic_reloc, /* special_function */ 560214082Sdim "R_ARM_ALU_PCREL_15_8",/* name */ 561214082Sdim FALSE, /* partial_inplace */ 562214082Sdim 0x00000fff, /* src_mask */ 563214082Sdim 0x00000fff, /* dst_mask */ 564214082Sdim TRUE), /* pcrel_offset */ 565214082Sdim 566214082Sdim HOWTO (R_ARM_ALU_PCREL23_15, /* type */ 567214082Sdim 0, /* rightshift */ 568214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 569214082Sdim 12, /* bitsize */ 570214082Sdim TRUE, /* pc_relative */ 571214082Sdim 16, /* bitpos */ 572214082Sdim complain_overflow_dont,/* complain_on_overflow */ 573214082Sdim bfd_elf_generic_reloc, /* special_function */ 574214082Sdim "R_ARM_ALU_PCREL_23_15",/* name */ 575214082Sdim FALSE, /* partial_inplace */ 576214082Sdim 0x00000fff, /* src_mask */ 577214082Sdim 0x00000fff, /* dst_mask */ 578214082Sdim TRUE), /* pcrel_offset */ 579214082Sdim 580214082Sdim HOWTO (R_ARM_LDR_SBREL_11_0, /* type */ 581214082Sdim 0, /* rightshift */ 582214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 583214082Sdim 12, /* bitsize */ 584214082Sdim FALSE, /* pc_relative */ 585214082Sdim 0, /* bitpos */ 586214082Sdim complain_overflow_dont,/* complain_on_overflow */ 587214082Sdim bfd_elf_generic_reloc, /* special_function */ 588214082Sdim "R_ARM_LDR_SBREL_11_0",/* name */ 589214082Sdim FALSE, /* partial_inplace */ 590214082Sdim 0x00000fff, /* src_mask */ 591214082Sdim 0x00000fff, /* dst_mask */ 592214082Sdim FALSE), /* pcrel_offset */ 593214082Sdim 594214082Sdim HOWTO (R_ARM_ALU_SBREL_19_12, /* type */ 595214082Sdim 0, /* rightshift */ 596214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 597214082Sdim 8, /* bitsize */ 598214082Sdim FALSE, /* pc_relative */ 599214082Sdim 12, /* bitpos */ 600214082Sdim complain_overflow_dont,/* complain_on_overflow */ 601214082Sdim bfd_elf_generic_reloc, /* special_function */ 602214082Sdim "R_ARM_ALU_SBREL_19_12",/* name */ 603214082Sdim FALSE, /* partial_inplace */ 604214082Sdim 0x000ff000, /* src_mask */ 605214082Sdim 0x000ff000, /* dst_mask */ 606214082Sdim FALSE), /* pcrel_offset */ 607214082Sdim 608214082Sdim HOWTO (R_ARM_ALU_SBREL_27_20, /* type */ 609214082Sdim 0, /* rightshift */ 610214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 611214082Sdim 8, /* bitsize */ 612214082Sdim FALSE, /* pc_relative */ 613214082Sdim 20, /* bitpos */ 614214082Sdim complain_overflow_dont,/* complain_on_overflow */ 615214082Sdim bfd_elf_generic_reloc, /* special_function */ 616214082Sdim "R_ARM_ALU_SBREL_27_20",/* name */ 617214082Sdim FALSE, /* partial_inplace */ 618214082Sdim 0x0ff00000, /* src_mask */ 619214082Sdim 0x0ff00000, /* dst_mask */ 620214082Sdim FALSE), /* pcrel_offset */ 621214082Sdim 622214082Sdim HOWTO (R_ARM_TARGET1, /* type */ 623214082Sdim 0, /* rightshift */ 624214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 625214082Sdim 32, /* bitsize */ 626214082Sdim FALSE, /* pc_relative */ 627214082Sdim 0, /* bitpos */ 628214082Sdim complain_overflow_dont,/* complain_on_overflow */ 629214082Sdim bfd_elf_generic_reloc, /* special_function */ 630214082Sdim "R_ARM_TARGET1", /* name */ 631214082Sdim FALSE, /* partial_inplace */ 632214082Sdim 0xffffffff, /* src_mask */ 633214082Sdim 0xffffffff, /* dst_mask */ 634214082Sdim FALSE), /* pcrel_offset */ 635214082Sdim 636214082Sdim HOWTO (R_ARM_ROSEGREL32, /* type */ 637214082Sdim 0, /* rightshift */ 638214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 639214082Sdim 32, /* bitsize */ 640214082Sdim FALSE, /* pc_relative */ 641214082Sdim 0, /* bitpos */ 642214082Sdim complain_overflow_dont,/* complain_on_overflow */ 643214082Sdim bfd_elf_generic_reloc, /* special_function */ 644214082Sdim "R_ARM_ROSEGREL32", /* name */ 645214082Sdim FALSE, /* partial_inplace */ 646214082Sdim 0xffffffff, /* src_mask */ 647214082Sdim 0xffffffff, /* dst_mask */ 648214082Sdim FALSE), /* pcrel_offset */ 649214082Sdim 650214082Sdim HOWTO (R_ARM_V4BX, /* type */ 651214082Sdim 0, /* rightshift */ 652214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 653214082Sdim 32, /* bitsize */ 654214082Sdim FALSE, /* pc_relative */ 655214082Sdim 0, /* bitpos */ 656214082Sdim complain_overflow_dont,/* complain_on_overflow */ 657214082Sdim bfd_elf_generic_reloc, /* special_function */ 658214082Sdim "R_ARM_V4BX", /* name */ 659214082Sdim FALSE, /* partial_inplace */ 660214082Sdim 0xffffffff, /* src_mask */ 661214082Sdim 0xffffffff, /* dst_mask */ 662214082Sdim FALSE), /* pcrel_offset */ 663214082Sdim 664214082Sdim HOWTO (R_ARM_TARGET2, /* type */ 665214082Sdim 0, /* rightshift */ 666214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 667214082Sdim 32, /* bitsize */ 668214082Sdim FALSE, /* pc_relative */ 669214082Sdim 0, /* bitpos */ 670214082Sdim complain_overflow_signed,/* complain_on_overflow */ 671214082Sdim bfd_elf_generic_reloc, /* special_function */ 672214082Sdim "R_ARM_TARGET2", /* name */ 673214082Sdim FALSE, /* partial_inplace */ 674214082Sdim 0xffffffff, /* src_mask */ 675214082Sdim 0xffffffff, /* dst_mask */ 676214082Sdim TRUE), /* pcrel_offset */ 677214082Sdim 678214082Sdim HOWTO (R_ARM_PREL31, /* type */ 679214082Sdim 0, /* rightshift */ 680214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 681214082Sdim 31, /* bitsize */ 682214082Sdim TRUE, /* pc_relative */ 683214082Sdim 0, /* bitpos */ 684214082Sdim complain_overflow_signed,/* complain_on_overflow */ 685214082Sdim bfd_elf_generic_reloc, /* special_function */ 686214082Sdim "R_ARM_PREL31", /* name */ 687214082Sdim FALSE, /* partial_inplace */ 688214082Sdim 0x7fffffff, /* src_mask */ 689214082Sdim 0x7fffffff, /* dst_mask */ 690214082Sdim TRUE), /* pcrel_offset */ 691214082Sdim 692214082Sdim HOWTO (R_ARM_MOVW_ABS_NC, /* type */ 693214082Sdim 0, /* rightshift */ 694214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 695214082Sdim 16, /* bitsize */ 696214082Sdim FALSE, /* pc_relative */ 697214082Sdim 0, /* bitpos */ 698214082Sdim complain_overflow_dont,/* complain_on_overflow */ 699214082Sdim bfd_elf_generic_reloc, /* special_function */ 700214082Sdim "R_ARM_MOVW_ABS_NC", /* name */ 701214082Sdim FALSE, /* partial_inplace */ 702214082Sdim 0x0000ffff, /* src_mask */ 703214082Sdim 0x0000ffff, /* dst_mask */ 704214082Sdim FALSE), /* pcrel_offset */ 705214082Sdim 706214082Sdim HOWTO (R_ARM_MOVT_ABS, /* type */ 707214082Sdim 0, /* rightshift */ 708214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 709214082Sdim 16, /* bitsize */ 710214082Sdim FALSE, /* pc_relative */ 711214082Sdim 0, /* bitpos */ 712214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 713214082Sdim bfd_elf_generic_reloc, /* special_function */ 714214082Sdim "R_ARM_MOVT_ABS", /* name */ 715214082Sdim FALSE, /* partial_inplace */ 716214082Sdim 0x0000ffff, /* src_mask */ 717214082Sdim 0x0000ffff, /* dst_mask */ 718214082Sdim FALSE), /* pcrel_offset */ 719214082Sdim 720214082Sdim HOWTO (R_ARM_MOVW_PREL_NC, /* type */ 721214082Sdim 0, /* rightshift */ 722214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 723214082Sdim 16, /* bitsize */ 724214082Sdim TRUE, /* pc_relative */ 725214082Sdim 0, /* bitpos */ 726214082Sdim complain_overflow_dont,/* complain_on_overflow */ 727214082Sdim bfd_elf_generic_reloc, /* special_function */ 728214082Sdim "R_ARM_MOVW_PREL_NC", /* name */ 729214082Sdim FALSE, /* partial_inplace */ 730214082Sdim 0x0000ffff, /* src_mask */ 731214082Sdim 0x0000ffff, /* dst_mask */ 732214082Sdim TRUE), /* pcrel_offset */ 733214082Sdim 734214082Sdim HOWTO (R_ARM_MOVT_PREL, /* type */ 735214082Sdim 0, /* rightshift */ 736214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 737214082Sdim 16, /* bitsize */ 738214082Sdim TRUE, /* pc_relative */ 739214082Sdim 0, /* bitpos */ 740214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 741214082Sdim bfd_elf_generic_reloc, /* special_function */ 742214082Sdim "R_ARM_MOVT_PREL", /* name */ 743214082Sdim FALSE, /* partial_inplace */ 744214082Sdim 0x0000ffff, /* src_mask */ 745214082Sdim 0x0000ffff, /* dst_mask */ 746214082Sdim TRUE), /* pcrel_offset */ 747214082Sdim 748214082Sdim HOWTO (R_ARM_THM_MOVW_ABS_NC, /* type */ 749214082Sdim 0, /* rightshift */ 750214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 751214082Sdim 16, /* bitsize */ 752214082Sdim FALSE, /* pc_relative */ 753214082Sdim 0, /* bitpos */ 754214082Sdim complain_overflow_dont,/* complain_on_overflow */ 755214082Sdim bfd_elf_generic_reloc, /* special_function */ 756214082Sdim "R_ARM_THM_MOVW_ABS_NC",/* name */ 757214082Sdim FALSE, /* partial_inplace */ 758214082Sdim 0x040f70ff, /* src_mask */ 759214082Sdim 0x040f70ff, /* dst_mask */ 760214082Sdim FALSE), /* pcrel_offset */ 761214082Sdim 762214082Sdim HOWTO (R_ARM_THM_MOVT_ABS, /* type */ 763214082Sdim 0, /* rightshift */ 764214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 765214082Sdim 16, /* bitsize */ 766214082Sdim FALSE, /* pc_relative */ 767214082Sdim 0, /* bitpos */ 768214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 769214082Sdim bfd_elf_generic_reloc, /* special_function */ 770214082Sdim "R_ARM_THM_MOVT_ABS", /* name */ 771214082Sdim FALSE, /* partial_inplace */ 772214082Sdim 0x040f70ff, /* src_mask */ 773214082Sdim 0x040f70ff, /* dst_mask */ 774214082Sdim FALSE), /* pcrel_offset */ 775214082Sdim 776214082Sdim HOWTO (R_ARM_THM_MOVW_PREL_NC,/* type */ 777214082Sdim 0, /* rightshift */ 778214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 779214082Sdim 16, /* bitsize */ 780214082Sdim TRUE, /* pc_relative */ 781214082Sdim 0, /* bitpos */ 782214082Sdim complain_overflow_dont,/* complain_on_overflow */ 783214082Sdim bfd_elf_generic_reloc, /* special_function */ 784214082Sdim "R_ARM_THM_MOVW_PREL_NC",/* name */ 785214082Sdim FALSE, /* partial_inplace */ 786214082Sdim 0x040f70ff, /* src_mask */ 787214082Sdim 0x040f70ff, /* dst_mask */ 788214082Sdim TRUE), /* pcrel_offset */ 789214082Sdim 790214082Sdim HOWTO (R_ARM_THM_MOVT_PREL, /* type */ 791214082Sdim 0, /* rightshift */ 792214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 793214082Sdim 16, /* bitsize */ 794214082Sdim TRUE, /* pc_relative */ 795214082Sdim 0, /* bitpos */ 796214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 797214082Sdim bfd_elf_generic_reloc, /* special_function */ 798214082Sdim "R_ARM_THM_MOVT_PREL", /* name */ 799214082Sdim FALSE, /* partial_inplace */ 800214082Sdim 0x040f70ff, /* src_mask */ 801214082Sdim 0x040f70ff, /* dst_mask */ 802214082Sdim TRUE), /* pcrel_offset */ 803214082Sdim 804214082Sdim HOWTO (R_ARM_THM_JUMP19, /* type */ 805214082Sdim 1, /* rightshift */ 806214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 807214082Sdim 19, /* bitsize */ 808214082Sdim TRUE, /* pc_relative */ 809214082Sdim 0, /* bitpos */ 810214082Sdim complain_overflow_signed,/* complain_on_overflow */ 811214082Sdim bfd_elf_generic_reloc, /* special_function */ 812214082Sdim "R_ARM_THM_JUMP19", /* name */ 813214082Sdim FALSE, /* partial_inplace */ 814214082Sdim 0x043f2fff, /* src_mask */ 815214082Sdim 0x043f2fff, /* dst_mask */ 816214082Sdim TRUE), /* pcrel_offset */ 817214082Sdim 818214082Sdim HOWTO (R_ARM_THM_JUMP6, /* type */ 819214082Sdim 1, /* rightshift */ 820214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 821214082Sdim 6, /* bitsize */ 822214082Sdim TRUE, /* pc_relative */ 823214082Sdim 0, /* bitpos */ 824214082Sdim complain_overflow_unsigned,/* complain_on_overflow */ 825214082Sdim bfd_elf_generic_reloc, /* special_function */ 826214082Sdim "R_ARM_THM_JUMP6", /* name */ 827214082Sdim FALSE, /* partial_inplace */ 828214082Sdim 0x02f8, /* src_mask */ 829214082Sdim 0x02f8, /* dst_mask */ 830214082Sdim TRUE), /* pcrel_offset */ 831214082Sdim 832214082Sdim /* These are declared as 13-bit signed relocations because we can 833214082Sdim address -4095 .. 4095(base) by altering ADDW to SUBW or vice 834214082Sdim versa. */ 835214082Sdim HOWTO (R_ARM_THM_ALU_PREL_11_0,/* type */ 836214082Sdim 0, /* rightshift */ 837214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 838214082Sdim 13, /* bitsize */ 839214082Sdim TRUE, /* pc_relative */ 840214082Sdim 0, /* bitpos */ 841214634Sdim complain_overflow_dont,/* complain_on_overflow */ 842214082Sdim bfd_elf_generic_reloc, /* special_function */ 843214082Sdim "R_ARM_THM_ALU_PREL_11_0",/* name */ 844214082Sdim FALSE, /* partial_inplace */ 845214634Sdim 0xffffffff, /* src_mask */ 846214634Sdim 0xffffffff, /* dst_mask */ 847214082Sdim TRUE), /* pcrel_offset */ 848214082Sdim 849214082Sdim HOWTO (R_ARM_THM_PC12, /* type */ 850214082Sdim 0, /* rightshift */ 851214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 852214082Sdim 13, /* bitsize */ 853214082Sdim TRUE, /* pc_relative */ 854214082Sdim 0, /* bitpos */ 855214634Sdim complain_overflow_dont,/* complain_on_overflow */ 856214082Sdim bfd_elf_generic_reloc, /* special_function */ 857214082Sdim "R_ARM_THM_PC12", /* name */ 858214082Sdim FALSE, /* partial_inplace */ 859214634Sdim 0xffffffff, /* src_mask */ 860214634Sdim 0xffffffff, /* dst_mask */ 861214082Sdim TRUE), /* pcrel_offset */ 862214082Sdim 863214082Sdim HOWTO (R_ARM_ABS32_NOI, /* type */ 864214082Sdim 0, /* rightshift */ 865214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 866214082Sdim 32, /* bitsize */ 867214082Sdim FALSE, /* pc_relative */ 868214082Sdim 0, /* bitpos */ 869214082Sdim complain_overflow_dont,/* complain_on_overflow */ 870214082Sdim bfd_elf_generic_reloc, /* special_function */ 871214082Sdim "R_ARM_ABS32_NOI", /* name */ 872214082Sdim FALSE, /* partial_inplace */ 873214082Sdim 0xffffffff, /* src_mask */ 874214082Sdim 0xffffffff, /* dst_mask */ 875214082Sdim FALSE), /* pcrel_offset */ 876214082Sdim 877214082Sdim HOWTO (R_ARM_REL32_NOI, /* type */ 878214082Sdim 0, /* rightshift */ 879214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 880214082Sdim 32, /* bitsize */ 881214082Sdim TRUE, /* pc_relative */ 882214082Sdim 0, /* bitpos */ 883214082Sdim complain_overflow_dont,/* complain_on_overflow */ 884214082Sdim bfd_elf_generic_reloc, /* special_function */ 885214082Sdim "R_ARM_REL32_NOI", /* name */ 886214082Sdim FALSE, /* partial_inplace */ 887214082Sdim 0xffffffff, /* src_mask */ 888214082Sdim 0xffffffff, /* dst_mask */ 889214082Sdim FALSE), /* pcrel_offset */ 890214082Sdim 891214634Sdim /* Group relocations. */ 892214082Sdim 893214634Sdim HOWTO (R_ARM_ALU_PC_G0_NC, /* type */ 894214634Sdim 0, /* rightshift */ 895214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 896214634Sdim 32, /* bitsize */ 897214634Sdim TRUE, /* pc_relative */ 898214634Sdim 0, /* bitpos */ 899214634Sdim complain_overflow_dont,/* complain_on_overflow */ 900214634Sdim bfd_elf_generic_reloc, /* special_function */ 901214634Sdim "R_ARM_ALU_PC_G0_NC", /* name */ 902214634Sdim FALSE, /* partial_inplace */ 903214634Sdim 0xffffffff, /* src_mask */ 904214634Sdim 0xffffffff, /* dst_mask */ 905214634Sdim TRUE), /* pcrel_offset */ 906214634Sdim 907214634Sdim HOWTO (R_ARM_ALU_PC_G0, /* type */ 908214634Sdim 0, /* rightshift */ 909214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 910214634Sdim 32, /* bitsize */ 911214634Sdim TRUE, /* pc_relative */ 912214634Sdim 0, /* bitpos */ 913214634Sdim complain_overflow_dont,/* complain_on_overflow */ 914214634Sdim bfd_elf_generic_reloc, /* special_function */ 915214634Sdim "R_ARM_ALU_PC_G0", /* name */ 916214634Sdim FALSE, /* partial_inplace */ 917214634Sdim 0xffffffff, /* src_mask */ 918214634Sdim 0xffffffff, /* dst_mask */ 919214634Sdim TRUE), /* pcrel_offset */ 920214634Sdim 921214634Sdim HOWTO (R_ARM_ALU_PC_G1_NC, /* type */ 922214634Sdim 0, /* rightshift */ 923214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 924214634Sdim 32, /* bitsize */ 925214634Sdim TRUE, /* pc_relative */ 926214634Sdim 0, /* bitpos */ 927214634Sdim complain_overflow_dont,/* complain_on_overflow */ 928214634Sdim bfd_elf_generic_reloc, /* special_function */ 929214634Sdim "R_ARM_ALU_PC_G1_NC", /* name */ 930214634Sdim FALSE, /* partial_inplace */ 931214634Sdim 0xffffffff, /* src_mask */ 932214634Sdim 0xffffffff, /* dst_mask */ 933214634Sdim TRUE), /* pcrel_offset */ 934214634Sdim 935214634Sdim HOWTO (R_ARM_ALU_PC_G1, /* type */ 936214634Sdim 0, /* rightshift */ 937214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 938214634Sdim 32, /* bitsize */ 939214634Sdim TRUE, /* pc_relative */ 940214634Sdim 0, /* bitpos */ 941214634Sdim complain_overflow_dont,/* complain_on_overflow */ 942214634Sdim bfd_elf_generic_reloc, /* special_function */ 943214634Sdim "R_ARM_ALU_PC_G1", /* name */ 944214634Sdim FALSE, /* partial_inplace */ 945214634Sdim 0xffffffff, /* src_mask */ 946214634Sdim 0xffffffff, /* dst_mask */ 947214634Sdim TRUE), /* pcrel_offset */ 948214634Sdim 949214634Sdim HOWTO (R_ARM_ALU_PC_G2, /* type */ 950214634Sdim 0, /* rightshift */ 951214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 952214634Sdim 32, /* bitsize */ 953214634Sdim TRUE, /* pc_relative */ 954214634Sdim 0, /* bitpos */ 955214634Sdim complain_overflow_dont,/* complain_on_overflow */ 956214634Sdim bfd_elf_generic_reloc, /* special_function */ 957214634Sdim "R_ARM_ALU_PC_G2", /* name */ 958214634Sdim FALSE, /* partial_inplace */ 959214634Sdim 0xffffffff, /* src_mask */ 960214634Sdim 0xffffffff, /* dst_mask */ 961214634Sdim TRUE), /* pcrel_offset */ 962214634Sdim 963214634Sdim HOWTO (R_ARM_LDR_PC_G1, /* type */ 964214634Sdim 0, /* rightshift */ 965214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 966214634Sdim 32, /* bitsize */ 967214634Sdim TRUE, /* pc_relative */ 968214634Sdim 0, /* bitpos */ 969214634Sdim complain_overflow_dont,/* complain_on_overflow */ 970214634Sdim bfd_elf_generic_reloc, /* special_function */ 971214634Sdim "R_ARM_LDR_PC_G1", /* name */ 972214634Sdim FALSE, /* partial_inplace */ 973214634Sdim 0xffffffff, /* src_mask */ 974214634Sdim 0xffffffff, /* dst_mask */ 975214634Sdim TRUE), /* pcrel_offset */ 976214634Sdim 977214634Sdim HOWTO (R_ARM_LDR_PC_G2, /* type */ 978214634Sdim 0, /* rightshift */ 979214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 980214634Sdim 32, /* bitsize */ 981214634Sdim TRUE, /* pc_relative */ 982214634Sdim 0, /* bitpos */ 983214634Sdim complain_overflow_dont,/* complain_on_overflow */ 984214634Sdim bfd_elf_generic_reloc, /* special_function */ 985214634Sdim "R_ARM_LDR_PC_G2", /* name */ 986214634Sdim FALSE, /* partial_inplace */ 987214634Sdim 0xffffffff, /* src_mask */ 988214634Sdim 0xffffffff, /* dst_mask */ 989214634Sdim TRUE), /* pcrel_offset */ 990214634Sdim 991214634Sdim HOWTO (R_ARM_LDRS_PC_G0, /* type */ 992214634Sdim 0, /* rightshift */ 993214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 994214634Sdim 32, /* bitsize */ 995214634Sdim TRUE, /* pc_relative */ 996214634Sdim 0, /* bitpos */ 997214634Sdim complain_overflow_dont,/* complain_on_overflow */ 998214634Sdim bfd_elf_generic_reloc, /* special_function */ 999214634Sdim "R_ARM_LDRS_PC_G0", /* name */ 1000214634Sdim FALSE, /* partial_inplace */ 1001214634Sdim 0xffffffff, /* src_mask */ 1002214634Sdim 0xffffffff, /* dst_mask */ 1003214634Sdim TRUE), /* pcrel_offset */ 1004214634Sdim 1005214634Sdim HOWTO (R_ARM_LDRS_PC_G1, /* type */ 1006214634Sdim 0, /* rightshift */ 1007214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1008214634Sdim 32, /* bitsize */ 1009214634Sdim TRUE, /* pc_relative */ 1010214634Sdim 0, /* bitpos */ 1011214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1012214634Sdim bfd_elf_generic_reloc, /* special_function */ 1013214634Sdim "R_ARM_LDRS_PC_G1", /* name */ 1014214634Sdim FALSE, /* partial_inplace */ 1015214634Sdim 0xffffffff, /* src_mask */ 1016214634Sdim 0xffffffff, /* dst_mask */ 1017214634Sdim TRUE), /* pcrel_offset */ 1018214634Sdim 1019214634Sdim HOWTO (R_ARM_LDRS_PC_G2, /* type */ 1020214634Sdim 0, /* rightshift */ 1021214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1022214634Sdim 32, /* bitsize */ 1023214634Sdim TRUE, /* pc_relative */ 1024214634Sdim 0, /* bitpos */ 1025214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1026214634Sdim bfd_elf_generic_reloc, /* special_function */ 1027214634Sdim "R_ARM_LDRS_PC_G2", /* name */ 1028214634Sdim FALSE, /* partial_inplace */ 1029214634Sdim 0xffffffff, /* src_mask */ 1030214634Sdim 0xffffffff, /* dst_mask */ 1031214634Sdim TRUE), /* pcrel_offset */ 1032214634Sdim 1033214634Sdim HOWTO (R_ARM_LDC_PC_G0, /* type */ 1034214634Sdim 0, /* rightshift */ 1035214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1036214634Sdim 32, /* bitsize */ 1037214634Sdim TRUE, /* pc_relative */ 1038214634Sdim 0, /* bitpos */ 1039214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1040214634Sdim bfd_elf_generic_reloc, /* special_function */ 1041214634Sdim "R_ARM_LDC_PC_G0", /* name */ 1042214634Sdim FALSE, /* partial_inplace */ 1043214634Sdim 0xffffffff, /* src_mask */ 1044214634Sdim 0xffffffff, /* dst_mask */ 1045214634Sdim TRUE), /* pcrel_offset */ 1046214634Sdim 1047214634Sdim HOWTO (R_ARM_LDC_PC_G1, /* type */ 1048214634Sdim 0, /* rightshift */ 1049214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1050214634Sdim 32, /* bitsize */ 1051214634Sdim TRUE, /* pc_relative */ 1052214634Sdim 0, /* bitpos */ 1053214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1054214634Sdim bfd_elf_generic_reloc, /* special_function */ 1055214634Sdim "R_ARM_LDC_PC_G1", /* name */ 1056214634Sdim FALSE, /* partial_inplace */ 1057214634Sdim 0xffffffff, /* src_mask */ 1058214634Sdim 0xffffffff, /* dst_mask */ 1059214634Sdim TRUE), /* pcrel_offset */ 1060214634Sdim 1061214634Sdim HOWTO (R_ARM_LDC_PC_G2, /* type */ 1062214634Sdim 0, /* rightshift */ 1063214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1064214634Sdim 32, /* bitsize */ 1065214634Sdim TRUE, /* pc_relative */ 1066214634Sdim 0, /* bitpos */ 1067214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1068214634Sdim bfd_elf_generic_reloc, /* special_function */ 1069214634Sdim "R_ARM_LDC_PC_G2", /* name */ 1070214634Sdim FALSE, /* partial_inplace */ 1071214634Sdim 0xffffffff, /* src_mask */ 1072214634Sdim 0xffffffff, /* dst_mask */ 1073214634Sdim TRUE), /* pcrel_offset */ 1074214634Sdim 1075214634Sdim HOWTO (R_ARM_ALU_SB_G0_NC, /* type */ 1076214634Sdim 0, /* rightshift */ 1077214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1078214634Sdim 32, /* bitsize */ 1079214634Sdim TRUE, /* pc_relative */ 1080214634Sdim 0, /* bitpos */ 1081214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1082214634Sdim bfd_elf_generic_reloc, /* special_function */ 1083214634Sdim "R_ARM_ALU_SB_G0_NC", /* name */ 1084214634Sdim FALSE, /* partial_inplace */ 1085214634Sdim 0xffffffff, /* src_mask */ 1086214634Sdim 0xffffffff, /* dst_mask */ 1087214634Sdim TRUE), /* pcrel_offset */ 1088214634Sdim 1089214634Sdim HOWTO (R_ARM_ALU_SB_G0, /* type */ 1090214634Sdim 0, /* rightshift */ 1091214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1092214634Sdim 32, /* bitsize */ 1093214634Sdim TRUE, /* pc_relative */ 1094214634Sdim 0, /* bitpos */ 1095214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1096214634Sdim bfd_elf_generic_reloc, /* special_function */ 1097214634Sdim "R_ARM_ALU_SB_G0", /* name */ 1098214634Sdim FALSE, /* partial_inplace */ 1099214634Sdim 0xffffffff, /* src_mask */ 1100214634Sdim 0xffffffff, /* dst_mask */ 1101214634Sdim TRUE), /* pcrel_offset */ 1102214634Sdim 1103214634Sdim HOWTO (R_ARM_ALU_SB_G1_NC, /* type */ 1104214634Sdim 0, /* rightshift */ 1105214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1106214634Sdim 32, /* bitsize */ 1107214634Sdim TRUE, /* pc_relative */ 1108214634Sdim 0, /* bitpos */ 1109214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1110214634Sdim bfd_elf_generic_reloc, /* special_function */ 1111214634Sdim "R_ARM_ALU_SB_G1_NC", /* name */ 1112214634Sdim FALSE, /* partial_inplace */ 1113214634Sdim 0xffffffff, /* src_mask */ 1114214634Sdim 0xffffffff, /* dst_mask */ 1115214634Sdim TRUE), /* pcrel_offset */ 1116214634Sdim 1117214634Sdim HOWTO (R_ARM_ALU_SB_G1, /* type */ 1118214634Sdim 0, /* rightshift */ 1119214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1120214634Sdim 32, /* bitsize */ 1121214634Sdim TRUE, /* pc_relative */ 1122214634Sdim 0, /* bitpos */ 1123214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1124214634Sdim bfd_elf_generic_reloc, /* special_function */ 1125214634Sdim "R_ARM_ALU_SB_G1", /* name */ 1126214634Sdim FALSE, /* partial_inplace */ 1127214634Sdim 0xffffffff, /* src_mask */ 1128214634Sdim 0xffffffff, /* dst_mask */ 1129214634Sdim TRUE), /* pcrel_offset */ 1130214634Sdim 1131214634Sdim HOWTO (R_ARM_ALU_SB_G2, /* type */ 1132214634Sdim 0, /* rightshift */ 1133214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1134214634Sdim 32, /* bitsize */ 1135214634Sdim TRUE, /* pc_relative */ 1136214634Sdim 0, /* bitpos */ 1137214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1138214634Sdim bfd_elf_generic_reloc, /* special_function */ 1139214634Sdim "R_ARM_ALU_SB_G2", /* name */ 1140214634Sdim FALSE, /* partial_inplace */ 1141214634Sdim 0xffffffff, /* src_mask */ 1142214634Sdim 0xffffffff, /* dst_mask */ 1143214634Sdim TRUE), /* pcrel_offset */ 1144214634Sdim 1145214634Sdim HOWTO (R_ARM_LDR_SB_G0, /* type */ 1146214634Sdim 0, /* rightshift */ 1147214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1148214634Sdim 32, /* bitsize */ 1149214634Sdim TRUE, /* pc_relative */ 1150214634Sdim 0, /* bitpos */ 1151214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1152214634Sdim bfd_elf_generic_reloc, /* special_function */ 1153214634Sdim "R_ARM_LDR_SB_G0", /* name */ 1154214634Sdim FALSE, /* partial_inplace */ 1155214634Sdim 0xffffffff, /* src_mask */ 1156214634Sdim 0xffffffff, /* dst_mask */ 1157214634Sdim TRUE), /* pcrel_offset */ 1158214634Sdim 1159214634Sdim HOWTO (R_ARM_LDR_SB_G1, /* type */ 1160214634Sdim 0, /* rightshift */ 1161214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1162214634Sdim 32, /* bitsize */ 1163214634Sdim TRUE, /* pc_relative */ 1164214634Sdim 0, /* bitpos */ 1165214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1166214634Sdim bfd_elf_generic_reloc, /* special_function */ 1167214634Sdim "R_ARM_LDR_SB_G1", /* name */ 1168214634Sdim FALSE, /* partial_inplace */ 1169214634Sdim 0xffffffff, /* src_mask */ 1170214634Sdim 0xffffffff, /* dst_mask */ 1171214634Sdim TRUE), /* pcrel_offset */ 1172214634Sdim 1173214634Sdim HOWTO (R_ARM_LDR_SB_G2, /* type */ 1174214634Sdim 0, /* rightshift */ 1175214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1176214634Sdim 32, /* bitsize */ 1177214634Sdim TRUE, /* pc_relative */ 1178214634Sdim 0, /* bitpos */ 1179214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1180214634Sdim bfd_elf_generic_reloc, /* special_function */ 1181214634Sdim "R_ARM_LDR_SB_G2", /* name */ 1182214634Sdim FALSE, /* partial_inplace */ 1183214634Sdim 0xffffffff, /* src_mask */ 1184214634Sdim 0xffffffff, /* dst_mask */ 1185214634Sdim TRUE), /* pcrel_offset */ 1186214634Sdim 1187214634Sdim HOWTO (R_ARM_LDRS_SB_G0, /* type */ 1188214634Sdim 0, /* rightshift */ 1189214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1190214634Sdim 32, /* bitsize */ 1191214634Sdim TRUE, /* pc_relative */ 1192214634Sdim 0, /* bitpos */ 1193214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1194214634Sdim bfd_elf_generic_reloc, /* special_function */ 1195214634Sdim "R_ARM_LDRS_SB_G0", /* name */ 1196214634Sdim FALSE, /* partial_inplace */ 1197214634Sdim 0xffffffff, /* src_mask */ 1198214634Sdim 0xffffffff, /* dst_mask */ 1199214634Sdim TRUE), /* pcrel_offset */ 1200214634Sdim 1201214634Sdim HOWTO (R_ARM_LDRS_SB_G1, /* type */ 1202214634Sdim 0, /* rightshift */ 1203214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1204214634Sdim 32, /* bitsize */ 1205214634Sdim TRUE, /* pc_relative */ 1206214634Sdim 0, /* bitpos */ 1207214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1208214634Sdim bfd_elf_generic_reloc, /* special_function */ 1209214634Sdim "R_ARM_LDRS_SB_G1", /* name */ 1210214634Sdim FALSE, /* partial_inplace */ 1211214634Sdim 0xffffffff, /* src_mask */ 1212214634Sdim 0xffffffff, /* dst_mask */ 1213214634Sdim TRUE), /* pcrel_offset */ 1214214634Sdim 1215214634Sdim HOWTO (R_ARM_LDRS_SB_G2, /* type */ 1216214634Sdim 0, /* rightshift */ 1217214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1218214634Sdim 32, /* bitsize */ 1219214634Sdim TRUE, /* pc_relative */ 1220214634Sdim 0, /* bitpos */ 1221214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1222214634Sdim bfd_elf_generic_reloc, /* special_function */ 1223214634Sdim "R_ARM_LDRS_SB_G2", /* name */ 1224214634Sdim FALSE, /* partial_inplace */ 1225214634Sdim 0xffffffff, /* src_mask */ 1226214634Sdim 0xffffffff, /* dst_mask */ 1227214634Sdim TRUE), /* pcrel_offset */ 1228214634Sdim 1229214634Sdim HOWTO (R_ARM_LDC_SB_G0, /* type */ 1230214634Sdim 0, /* rightshift */ 1231214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1232214634Sdim 32, /* bitsize */ 1233214634Sdim TRUE, /* pc_relative */ 1234214634Sdim 0, /* bitpos */ 1235214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1236214634Sdim bfd_elf_generic_reloc, /* special_function */ 1237214634Sdim "R_ARM_LDC_SB_G0", /* name */ 1238214634Sdim FALSE, /* partial_inplace */ 1239214634Sdim 0xffffffff, /* src_mask */ 1240214634Sdim 0xffffffff, /* dst_mask */ 1241214634Sdim TRUE), /* pcrel_offset */ 1242214634Sdim 1243214634Sdim HOWTO (R_ARM_LDC_SB_G1, /* type */ 1244214634Sdim 0, /* rightshift */ 1245214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1246214634Sdim 32, /* bitsize */ 1247214634Sdim TRUE, /* pc_relative */ 1248214634Sdim 0, /* bitpos */ 1249214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1250214634Sdim bfd_elf_generic_reloc, /* special_function */ 1251214634Sdim "R_ARM_LDC_SB_G1", /* name */ 1252214634Sdim FALSE, /* partial_inplace */ 1253214634Sdim 0xffffffff, /* src_mask */ 1254214634Sdim 0xffffffff, /* dst_mask */ 1255214634Sdim TRUE), /* pcrel_offset */ 1256214634Sdim 1257214634Sdim HOWTO (R_ARM_LDC_SB_G2, /* type */ 1258214634Sdim 0, /* rightshift */ 1259214634Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1260214634Sdim 32, /* bitsize */ 1261214634Sdim TRUE, /* pc_relative */ 1262214634Sdim 0, /* bitpos */ 1263214634Sdim complain_overflow_dont,/* complain_on_overflow */ 1264214634Sdim bfd_elf_generic_reloc, /* special_function */ 1265214634Sdim "R_ARM_LDC_SB_G2", /* name */ 1266214634Sdim FALSE, /* partial_inplace */ 1267214634Sdim 0xffffffff, /* src_mask */ 1268214634Sdim 0xffffffff, /* dst_mask */ 1269214634Sdim TRUE), /* pcrel_offset */ 1270214634Sdim 1271214634Sdim /* End of group relocations. */ 1272214634Sdim 1273214082Sdim HOWTO (R_ARM_MOVW_BREL_NC, /* type */ 1274214082Sdim 0, /* rightshift */ 1275214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1276214082Sdim 16, /* bitsize */ 1277214082Sdim FALSE, /* pc_relative */ 1278214082Sdim 0, /* bitpos */ 1279214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1280214082Sdim bfd_elf_generic_reloc, /* special_function */ 1281214082Sdim "R_ARM_MOVW_BREL_NC", /* name */ 1282214082Sdim FALSE, /* partial_inplace */ 1283214082Sdim 0x0000ffff, /* src_mask */ 1284214082Sdim 0x0000ffff, /* dst_mask */ 1285214082Sdim FALSE), /* pcrel_offset */ 1286214082Sdim 1287214082Sdim HOWTO (R_ARM_MOVT_BREL, /* type */ 1288214082Sdim 0, /* rightshift */ 1289214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1290214082Sdim 16, /* bitsize */ 1291214082Sdim FALSE, /* pc_relative */ 1292214082Sdim 0, /* bitpos */ 1293214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1294214082Sdim bfd_elf_generic_reloc, /* special_function */ 1295214082Sdim "R_ARM_MOVT_BREL", /* name */ 1296214082Sdim FALSE, /* partial_inplace */ 1297214082Sdim 0x0000ffff, /* src_mask */ 1298214082Sdim 0x0000ffff, /* dst_mask */ 1299214082Sdim FALSE), /* pcrel_offset */ 1300214082Sdim 1301214082Sdim HOWTO (R_ARM_MOVW_BREL, /* type */ 1302214082Sdim 0, /* rightshift */ 1303214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1304214082Sdim 16, /* bitsize */ 1305214082Sdim FALSE, /* pc_relative */ 1306214082Sdim 0, /* bitpos */ 1307214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1308214082Sdim bfd_elf_generic_reloc, /* special_function */ 1309214082Sdim "R_ARM_MOVW_BREL", /* name */ 1310214082Sdim FALSE, /* partial_inplace */ 1311214082Sdim 0x0000ffff, /* src_mask */ 1312214082Sdim 0x0000ffff, /* dst_mask */ 1313214082Sdim FALSE), /* pcrel_offset */ 1314214082Sdim 1315214082Sdim HOWTO (R_ARM_THM_MOVW_BREL_NC,/* type */ 1316214082Sdim 0, /* rightshift */ 1317214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1318214082Sdim 16, /* bitsize */ 1319214082Sdim FALSE, /* pc_relative */ 1320214082Sdim 0, /* bitpos */ 1321214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1322214082Sdim bfd_elf_generic_reloc, /* special_function */ 1323214082Sdim "R_ARM_THM_MOVW_BREL_NC",/* name */ 1324214082Sdim FALSE, /* partial_inplace */ 1325214082Sdim 0x040f70ff, /* src_mask */ 1326214082Sdim 0x040f70ff, /* dst_mask */ 1327214082Sdim FALSE), /* pcrel_offset */ 1328214082Sdim 1329214082Sdim HOWTO (R_ARM_THM_MOVT_BREL, /* type */ 1330214082Sdim 0, /* rightshift */ 1331214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1332214082Sdim 16, /* bitsize */ 1333214082Sdim FALSE, /* pc_relative */ 1334214082Sdim 0, /* bitpos */ 1335214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1336214082Sdim bfd_elf_generic_reloc, /* special_function */ 1337214082Sdim "R_ARM_THM_MOVT_BREL", /* name */ 1338214082Sdim FALSE, /* partial_inplace */ 1339214082Sdim 0x040f70ff, /* src_mask */ 1340214082Sdim 0x040f70ff, /* dst_mask */ 1341214082Sdim FALSE), /* pcrel_offset */ 1342214082Sdim 1343214082Sdim HOWTO (R_ARM_THM_MOVW_BREL, /* type */ 1344214082Sdim 0, /* rightshift */ 1345214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1346214082Sdim 16, /* bitsize */ 1347214082Sdim FALSE, /* pc_relative */ 1348214082Sdim 0, /* bitpos */ 1349214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1350214082Sdim bfd_elf_generic_reloc, /* special_function */ 1351214082Sdim "R_ARM_THM_MOVW_BREL", /* name */ 1352214082Sdim FALSE, /* partial_inplace */ 1353214082Sdim 0x040f70ff, /* src_mask */ 1354214082Sdim 0x040f70ff, /* dst_mask */ 1355214082Sdim FALSE), /* pcrel_offset */ 1356214082Sdim 1357214082Sdim EMPTY_HOWTO (90), /* unallocated */ 1358214082Sdim EMPTY_HOWTO (91), 1359214082Sdim EMPTY_HOWTO (92), 1360214082Sdim EMPTY_HOWTO (93), 1361214082Sdim 1362214082Sdim HOWTO (R_ARM_PLT32_ABS, /* type */ 1363214082Sdim 0, /* rightshift */ 1364214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1365214082Sdim 32, /* bitsize */ 1366214082Sdim FALSE, /* pc_relative */ 1367214082Sdim 0, /* bitpos */ 1368214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1369214082Sdim bfd_elf_generic_reloc, /* special_function */ 1370214082Sdim "R_ARM_PLT32_ABS", /* name */ 1371214082Sdim FALSE, /* partial_inplace */ 1372214082Sdim 0xffffffff, /* src_mask */ 1373214082Sdim 0xffffffff, /* dst_mask */ 1374214082Sdim FALSE), /* pcrel_offset */ 1375214082Sdim 1376214082Sdim HOWTO (R_ARM_GOT_ABS, /* type */ 1377214082Sdim 0, /* rightshift */ 1378214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1379214082Sdim 32, /* bitsize */ 1380214082Sdim FALSE, /* pc_relative */ 1381214082Sdim 0, /* bitpos */ 1382214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1383214082Sdim bfd_elf_generic_reloc, /* special_function */ 1384214082Sdim "R_ARM_GOT_ABS", /* name */ 1385214082Sdim FALSE, /* partial_inplace */ 1386214082Sdim 0xffffffff, /* src_mask */ 1387214082Sdim 0xffffffff, /* dst_mask */ 1388214082Sdim FALSE), /* pcrel_offset */ 1389214082Sdim 1390214082Sdim HOWTO (R_ARM_GOT_PREL, /* type */ 1391214082Sdim 0, /* rightshift */ 1392214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1393214082Sdim 32, /* bitsize */ 1394214082Sdim TRUE, /* pc_relative */ 1395214082Sdim 0, /* bitpos */ 1396214082Sdim complain_overflow_dont, /* complain_on_overflow */ 1397214082Sdim bfd_elf_generic_reloc, /* special_function */ 1398214082Sdim "R_ARM_GOT_PREL", /* name */ 1399214082Sdim FALSE, /* partial_inplace */ 1400214082Sdim 0xffffffff, /* src_mask */ 1401214082Sdim 0xffffffff, /* dst_mask */ 1402214082Sdim TRUE), /* pcrel_offset */ 1403214082Sdim 1404214082Sdim HOWTO (R_ARM_GOT_BREL12, /* type */ 1405214082Sdim 0, /* rightshift */ 1406214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1407214082Sdim 12, /* bitsize */ 1408214082Sdim FALSE, /* pc_relative */ 1409214082Sdim 0, /* bitpos */ 1410214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1411214082Sdim bfd_elf_generic_reloc, /* special_function */ 1412214082Sdim "R_ARM_GOT_BREL12", /* name */ 1413214082Sdim FALSE, /* partial_inplace */ 1414214082Sdim 0x00000fff, /* src_mask */ 1415214082Sdim 0x00000fff, /* dst_mask */ 1416214082Sdim FALSE), /* pcrel_offset */ 1417214082Sdim 1418214082Sdim HOWTO (R_ARM_GOTOFF12, /* type */ 1419214082Sdim 0, /* rightshift */ 1420214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1421214082Sdim 12, /* bitsize */ 1422214082Sdim FALSE, /* pc_relative */ 1423214082Sdim 0, /* bitpos */ 1424214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1425214082Sdim bfd_elf_generic_reloc, /* special_function */ 1426214082Sdim "R_ARM_GOTOFF12", /* name */ 1427214082Sdim FALSE, /* partial_inplace */ 1428214082Sdim 0x00000fff, /* src_mask */ 1429214082Sdim 0x00000fff, /* dst_mask */ 1430214082Sdim FALSE), /* pcrel_offset */ 1431214082Sdim 1432214082Sdim EMPTY_HOWTO (R_ARM_GOTRELAX), /* reserved for future GOT-load optimizations */ 1433214082Sdim 1434214082Sdim /* GNU extension to record C++ vtable member usage */ 1435214082Sdim HOWTO (R_ARM_GNU_VTENTRY, /* type */ 1436214082Sdim 0, /* rightshift */ 1437214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1438214082Sdim 0, /* bitsize */ 1439214082Sdim FALSE, /* pc_relative */ 1440214082Sdim 0, /* bitpos */ 1441214082Sdim complain_overflow_dont, /* complain_on_overflow */ 1442214082Sdim _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 1443214082Sdim "R_ARM_GNU_VTENTRY", /* name */ 1444214082Sdim FALSE, /* partial_inplace */ 1445214082Sdim 0, /* src_mask */ 1446214082Sdim 0, /* dst_mask */ 1447214082Sdim FALSE), /* pcrel_offset */ 1448214082Sdim 1449214082Sdim /* GNU extension to record C++ vtable hierarchy */ 1450214082Sdim HOWTO (R_ARM_GNU_VTINHERIT, /* type */ 1451214082Sdim 0, /* rightshift */ 1452214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1453214082Sdim 0, /* bitsize */ 1454214082Sdim FALSE, /* pc_relative */ 1455214082Sdim 0, /* bitpos */ 1456214082Sdim complain_overflow_dont, /* complain_on_overflow */ 1457214082Sdim NULL, /* special_function */ 1458214082Sdim "R_ARM_GNU_VTINHERIT", /* name */ 1459214082Sdim FALSE, /* partial_inplace */ 1460214082Sdim 0, /* src_mask */ 1461214082Sdim 0, /* dst_mask */ 1462214082Sdim FALSE), /* pcrel_offset */ 1463214082Sdim 1464214082Sdim HOWTO (R_ARM_THM_JUMP11, /* type */ 1465214082Sdim 1, /* rightshift */ 1466214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 1467214082Sdim 11, /* bitsize */ 1468214082Sdim TRUE, /* pc_relative */ 1469214082Sdim 0, /* bitpos */ 1470214082Sdim complain_overflow_signed, /* complain_on_overflow */ 1471214082Sdim bfd_elf_generic_reloc, /* special_function */ 1472214082Sdim "R_ARM_THM_JUMP11", /* name */ 1473214082Sdim FALSE, /* partial_inplace */ 1474214082Sdim 0x000007ff, /* src_mask */ 1475214082Sdim 0x000007ff, /* dst_mask */ 1476214082Sdim TRUE), /* pcrel_offset */ 1477214082Sdim 1478214082Sdim HOWTO (R_ARM_THM_JUMP8, /* type */ 1479214082Sdim 1, /* rightshift */ 1480214082Sdim 1, /* size (0 = byte, 1 = short, 2 = long) */ 1481214082Sdim 8, /* bitsize */ 1482214082Sdim TRUE, /* pc_relative */ 1483214082Sdim 0, /* bitpos */ 1484214082Sdim complain_overflow_signed, /* complain_on_overflow */ 1485214082Sdim bfd_elf_generic_reloc, /* special_function */ 1486214082Sdim "R_ARM_THM_JUMP8", /* name */ 1487214082Sdim FALSE, /* partial_inplace */ 1488214082Sdim 0x000000ff, /* src_mask */ 1489214082Sdim 0x000000ff, /* dst_mask */ 1490214082Sdim TRUE), /* pcrel_offset */ 1491214082Sdim 1492214082Sdim /* TLS relocations */ 1493214082Sdim HOWTO (R_ARM_TLS_GD32, /* type */ 1494214082Sdim 0, /* rightshift */ 1495214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1496214082Sdim 32, /* bitsize */ 1497214082Sdim FALSE, /* pc_relative */ 1498214082Sdim 0, /* bitpos */ 1499214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1500214082Sdim NULL, /* special_function */ 1501214082Sdim "R_ARM_TLS_GD32", /* name */ 1502214082Sdim TRUE, /* partial_inplace */ 1503214082Sdim 0xffffffff, /* src_mask */ 1504214082Sdim 0xffffffff, /* dst_mask */ 1505214082Sdim FALSE), /* pcrel_offset */ 1506214082Sdim 1507214082Sdim HOWTO (R_ARM_TLS_LDM32, /* type */ 1508214082Sdim 0, /* rightshift */ 1509214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1510214082Sdim 32, /* bitsize */ 1511214082Sdim FALSE, /* pc_relative */ 1512214082Sdim 0, /* bitpos */ 1513214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1514214082Sdim bfd_elf_generic_reloc, /* special_function */ 1515214082Sdim "R_ARM_TLS_LDM32", /* name */ 1516214082Sdim TRUE, /* partial_inplace */ 1517214082Sdim 0xffffffff, /* src_mask */ 1518214082Sdim 0xffffffff, /* dst_mask */ 1519214082Sdim FALSE), /* pcrel_offset */ 1520214082Sdim 1521214082Sdim HOWTO (R_ARM_TLS_LDO32, /* type */ 1522214082Sdim 0, /* rightshift */ 1523214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1524214082Sdim 32, /* bitsize */ 1525214082Sdim FALSE, /* pc_relative */ 1526214082Sdim 0, /* bitpos */ 1527214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1528214082Sdim bfd_elf_generic_reloc, /* special_function */ 1529214082Sdim "R_ARM_TLS_LDO32", /* name */ 1530214082Sdim TRUE, /* partial_inplace */ 1531214082Sdim 0xffffffff, /* src_mask */ 1532214082Sdim 0xffffffff, /* dst_mask */ 1533214082Sdim FALSE), /* pcrel_offset */ 1534214082Sdim 1535214082Sdim HOWTO (R_ARM_TLS_IE32, /* type */ 1536214082Sdim 0, /* rightshift */ 1537214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1538214082Sdim 32, /* bitsize */ 1539214082Sdim FALSE, /* pc_relative */ 1540214082Sdim 0, /* bitpos */ 1541214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1542214082Sdim NULL, /* special_function */ 1543214082Sdim "R_ARM_TLS_IE32", /* name */ 1544214082Sdim TRUE, /* partial_inplace */ 1545214082Sdim 0xffffffff, /* src_mask */ 1546214082Sdim 0xffffffff, /* dst_mask */ 1547214082Sdim FALSE), /* pcrel_offset */ 1548214082Sdim 1549214082Sdim HOWTO (R_ARM_TLS_LE32, /* type */ 1550214082Sdim 0, /* rightshift */ 1551214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1552214082Sdim 32, /* bitsize */ 1553214082Sdim FALSE, /* pc_relative */ 1554214082Sdim 0, /* bitpos */ 1555214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1556214082Sdim bfd_elf_generic_reloc, /* special_function */ 1557214082Sdim "R_ARM_TLS_LE32", /* name */ 1558214082Sdim TRUE, /* partial_inplace */ 1559214082Sdim 0xffffffff, /* src_mask */ 1560214082Sdim 0xffffffff, /* dst_mask */ 1561214082Sdim FALSE), /* pcrel_offset */ 1562214082Sdim 1563214082Sdim HOWTO (R_ARM_TLS_LDO12, /* type */ 1564214082Sdim 0, /* rightshift */ 1565214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1566214082Sdim 12, /* bitsize */ 1567214082Sdim FALSE, /* pc_relative */ 1568214082Sdim 0, /* bitpos */ 1569214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1570214082Sdim bfd_elf_generic_reloc, /* special_function */ 1571214082Sdim "R_ARM_TLS_LDO12", /* name */ 1572214082Sdim FALSE, /* partial_inplace */ 1573214082Sdim 0x00000fff, /* src_mask */ 1574214082Sdim 0x00000fff, /* dst_mask */ 1575214082Sdim FALSE), /* pcrel_offset */ 1576214082Sdim 1577214082Sdim HOWTO (R_ARM_TLS_LE12, /* type */ 1578214082Sdim 0, /* rightshift */ 1579214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1580214082Sdim 12, /* bitsize */ 1581214082Sdim FALSE, /* pc_relative */ 1582214082Sdim 0, /* bitpos */ 1583214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1584214082Sdim bfd_elf_generic_reloc, /* special_function */ 1585214082Sdim "R_ARM_TLS_LE12", /* name */ 1586214082Sdim FALSE, /* partial_inplace */ 1587214082Sdim 0x00000fff, /* src_mask */ 1588214082Sdim 0x00000fff, /* dst_mask */ 1589214082Sdim FALSE), /* pcrel_offset */ 1590214082Sdim 1591214082Sdim HOWTO (R_ARM_TLS_IE12GP, /* type */ 1592214082Sdim 0, /* rightshift */ 1593214082Sdim 2, /* size (0 = byte, 1 = short, 2 = long) */ 1594214082Sdim 12, /* bitsize */ 1595214082Sdim FALSE, /* pc_relative */ 1596214082Sdim 0, /* bitpos */ 1597214082Sdim complain_overflow_bitfield,/* complain_on_overflow */ 1598214082Sdim bfd_elf_generic_reloc, /* special_function */ 1599214082Sdim "R_ARM_TLS_IE12GP", /* name */ 1600214082Sdim FALSE, /* partial_inplace */ 1601214082Sdim 0x00000fff, /* src_mask */ 1602214082Sdim 0x00000fff, /* dst_mask */ 1603214082Sdim FALSE), /* pcrel_offset */ 1604214082Sdim}; 1605214082Sdim 1606214082Sdim/* 112-127 private relocations 1607214082Sdim 128 R_ARM_ME_TOO, obsolete 1608214082Sdim 129-255 unallocated in AAELF. 1609214082Sdim 1610214082Sdim 249-255 extended, currently unused, relocations: */ 1611214082Sdim 1612214634Sdimstatic reloc_howto_type elf32_arm_howto_table_2[4] = 1613214082Sdim{ 1614214082Sdim HOWTO (R_ARM_RREL32, /* type */ 1615214082Sdim 0, /* rightshift */ 1616214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 1617214082Sdim 0, /* bitsize */ 1618214082Sdim FALSE, /* pc_relative */ 1619214082Sdim 0, /* bitpos */ 1620214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1621214082Sdim bfd_elf_generic_reloc, /* special_function */ 1622214082Sdim "R_ARM_RREL32", /* name */ 1623214082Sdim FALSE, /* partial_inplace */ 1624214082Sdim 0, /* src_mask */ 1625214082Sdim 0, /* dst_mask */ 1626214082Sdim FALSE), /* pcrel_offset */ 1627214082Sdim 1628214082Sdim HOWTO (R_ARM_RABS32, /* type */ 1629214082Sdim 0, /* rightshift */ 1630214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 1631214082Sdim 0, /* bitsize */ 1632214082Sdim FALSE, /* pc_relative */ 1633214082Sdim 0, /* bitpos */ 1634214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1635214082Sdim bfd_elf_generic_reloc, /* special_function */ 1636214082Sdim "R_ARM_RABS32", /* name */ 1637214082Sdim FALSE, /* partial_inplace */ 1638214082Sdim 0, /* src_mask */ 1639214082Sdim 0, /* dst_mask */ 1640214082Sdim FALSE), /* pcrel_offset */ 1641214082Sdim 1642214082Sdim HOWTO (R_ARM_RPC24, /* type */ 1643214082Sdim 0, /* rightshift */ 1644214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 1645214082Sdim 0, /* bitsize */ 1646214082Sdim FALSE, /* pc_relative */ 1647214082Sdim 0, /* bitpos */ 1648214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1649214082Sdim bfd_elf_generic_reloc, /* special_function */ 1650214082Sdim "R_ARM_RPC24", /* name */ 1651214082Sdim FALSE, /* partial_inplace */ 1652214082Sdim 0, /* src_mask */ 1653214082Sdim 0, /* dst_mask */ 1654214082Sdim FALSE), /* pcrel_offset */ 1655214082Sdim 1656214082Sdim HOWTO (R_ARM_RBASE, /* type */ 1657214082Sdim 0, /* rightshift */ 1658214082Sdim 0, /* size (0 = byte, 1 = short, 2 = long) */ 1659214082Sdim 0, /* bitsize */ 1660214082Sdim FALSE, /* pc_relative */ 1661214082Sdim 0, /* bitpos */ 1662214082Sdim complain_overflow_dont,/* complain_on_overflow */ 1663214082Sdim bfd_elf_generic_reloc, /* special_function */ 1664214082Sdim "R_ARM_RBASE", /* name */ 1665214082Sdim FALSE, /* partial_inplace */ 1666214082Sdim 0, /* src_mask */ 1667214082Sdim 0, /* dst_mask */ 1668214082Sdim FALSE) /* pcrel_offset */ 1669214082Sdim}; 1670214082Sdim 1671214082Sdimstatic reloc_howto_type * 1672214082Sdimelf32_arm_howto_from_type (unsigned int r_type) 1673214082Sdim{ 1674214082Sdim if (r_type < NUM_ELEM (elf32_arm_howto_table_1)) 1675214082Sdim return &elf32_arm_howto_table_1[r_type]; 1676214082Sdim 1677214082Sdim if (r_type >= R_ARM_RREL32 1678214082Sdim && r_type < R_ARM_RREL32 + NUM_ELEM (elf32_arm_howto_table_2)) 1679214634Sdim return &elf32_arm_howto_table_2[r_type - R_ARM_RREL32]; 1680214082Sdim 1681214082Sdim return NULL; 1682214082Sdim} 1683214082Sdim 1684214082Sdimstatic void 1685214082Sdimelf32_arm_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc, 1686214082Sdim Elf_Internal_Rela * elf_reloc) 1687214082Sdim{ 1688214082Sdim unsigned int r_type; 1689214082Sdim 1690214082Sdim r_type = ELF32_R_TYPE (elf_reloc->r_info); 1691214082Sdim bfd_reloc->howto = elf32_arm_howto_from_type (r_type); 1692214082Sdim} 1693214082Sdim 1694214082Sdimstruct elf32_arm_reloc_map 1695214082Sdim { 1696214082Sdim bfd_reloc_code_real_type bfd_reloc_val; 1697214082Sdim unsigned char elf_reloc_val; 1698214082Sdim }; 1699214082Sdim 1700214082Sdim/* All entries in this list must also be present in elf32_arm_howto_table. */ 1701214082Sdimstatic const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = 1702214082Sdim { 1703214082Sdim {BFD_RELOC_NONE, R_ARM_NONE}, 1704214082Sdim {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24}, 1705214082Sdim {BFD_RELOC_ARM_PCREL_CALL, R_ARM_CALL}, 1706214082Sdim {BFD_RELOC_ARM_PCREL_JUMP, R_ARM_JUMP24}, 1707214082Sdim {BFD_RELOC_ARM_PCREL_BLX, R_ARM_XPC25}, 1708214082Sdim {BFD_RELOC_THUMB_PCREL_BLX, R_ARM_THM_XPC22}, 1709214082Sdim {BFD_RELOC_32, R_ARM_ABS32}, 1710214082Sdim {BFD_RELOC_32_PCREL, R_ARM_REL32}, 1711214082Sdim {BFD_RELOC_8, R_ARM_ABS8}, 1712214082Sdim {BFD_RELOC_16, R_ARM_ABS16}, 1713214082Sdim {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12}, 1714214082Sdim {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5}, 1715214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH25, R_ARM_THM_JUMP24}, 1716214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_CALL}, 1717214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_JUMP11}, 1718214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH20, R_ARM_THM_JUMP19}, 1719214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_JUMP8}, 1720214082Sdim {BFD_RELOC_THUMB_PCREL_BRANCH7, R_ARM_THM_JUMP6}, 1721214082Sdim {BFD_RELOC_ARM_GLOB_DAT, R_ARM_GLOB_DAT}, 1722214082Sdim {BFD_RELOC_ARM_JUMP_SLOT, R_ARM_JUMP_SLOT}, 1723214082Sdim {BFD_RELOC_ARM_RELATIVE, R_ARM_RELATIVE}, 1724214082Sdim {BFD_RELOC_ARM_GOTOFF, R_ARM_GOTOFF32}, 1725214082Sdim {BFD_RELOC_ARM_GOTPC, R_ARM_GOTPC}, 1726214082Sdim {BFD_RELOC_ARM_GOT32, R_ARM_GOT32}, 1727214082Sdim {BFD_RELOC_ARM_PLT32, R_ARM_PLT32}, 1728214082Sdim {BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1}, 1729214082Sdim {BFD_RELOC_ARM_ROSEGREL32, R_ARM_ROSEGREL32}, 1730214082Sdim {BFD_RELOC_ARM_SBREL32, R_ARM_SBREL32}, 1731214082Sdim {BFD_RELOC_ARM_PREL31, R_ARM_PREL31}, 1732214082Sdim {BFD_RELOC_ARM_TARGET2, R_ARM_TARGET2}, 1733214082Sdim {BFD_RELOC_ARM_PLT32, R_ARM_PLT32}, 1734214082Sdim {BFD_RELOC_ARM_TLS_GD32, R_ARM_TLS_GD32}, 1735214082Sdim {BFD_RELOC_ARM_TLS_LDO32, R_ARM_TLS_LDO32}, 1736214082Sdim {BFD_RELOC_ARM_TLS_LDM32, R_ARM_TLS_LDM32}, 1737214082Sdim {BFD_RELOC_ARM_TLS_DTPMOD32, R_ARM_TLS_DTPMOD32}, 1738214082Sdim {BFD_RELOC_ARM_TLS_DTPOFF32, R_ARM_TLS_DTPOFF32}, 1739214082Sdim {BFD_RELOC_ARM_TLS_TPOFF32, R_ARM_TLS_TPOFF32}, 1740214082Sdim {BFD_RELOC_ARM_TLS_IE32, R_ARM_TLS_IE32}, 1741214082Sdim {BFD_RELOC_ARM_TLS_LE32, R_ARM_TLS_LE32}, 1742214082Sdim {BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT}, 1743214082Sdim {BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY}, 1744214634Sdim {BFD_RELOC_ARM_MOVW, R_ARM_MOVW_ABS_NC}, 1745214634Sdim {BFD_RELOC_ARM_MOVT, R_ARM_MOVT_ABS}, 1746214634Sdim {BFD_RELOC_ARM_MOVW_PCREL, R_ARM_MOVW_PREL_NC}, 1747214634Sdim {BFD_RELOC_ARM_MOVT_PCREL, R_ARM_MOVT_PREL}, 1748214634Sdim {BFD_RELOC_ARM_THUMB_MOVW, R_ARM_THM_MOVW_ABS_NC}, 1749214634Sdim {BFD_RELOC_ARM_THUMB_MOVT, R_ARM_THM_MOVT_ABS}, 1750214634Sdim {BFD_RELOC_ARM_THUMB_MOVW_PCREL, R_ARM_THM_MOVW_PREL_NC}, 1751214634Sdim {BFD_RELOC_ARM_THUMB_MOVT_PCREL, R_ARM_THM_MOVT_PREL}, 1752214634Sdim {BFD_RELOC_ARM_ALU_PC_G0_NC, R_ARM_ALU_PC_G0_NC}, 1753214634Sdim {BFD_RELOC_ARM_ALU_PC_G0, R_ARM_ALU_PC_G0}, 1754214634Sdim {BFD_RELOC_ARM_ALU_PC_G1_NC, R_ARM_ALU_PC_G1_NC}, 1755214634Sdim {BFD_RELOC_ARM_ALU_PC_G1, R_ARM_ALU_PC_G1}, 1756214634Sdim {BFD_RELOC_ARM_ALU_PC_G2, R_ARM_ALU_PC_G2}, 1757214634Sdim {BFD_RELOC_ARM_LDR_PC_G0, R_ARM_LDR_PC_G0}, 1758214634Sdim {BFD_RELOC_ARM_LDR_PC_G1, R_ARM_LDR_PC_G1}, 1759214634Sdim {BFD_RELOC_ARM_LDR_PC_G2, R_ARM_LDR_PC_G2}, 1760214634Sdim {BFD_RELOC_ARM_LDRS_PC_G0, R_ARM_LDRS_PC_G0}, 1761214634Sdim {BFD_RELOC_ARM_LDRS_PC_G1, R_ARM_LDRS_PC_G1}, 1762214634Sdim {BFD_RELOC_ARM_LDRS_PC_G2, R_ARM_LDRS_PC_G2}, 1763214634Sdim {BFD_RELOC_ARM_LDC_PC_G0, R_ARM_LDC_PC_G0}, 1764214634Sdim {BFD_RELOC_ARM_LDC_PC_G1, R_ARM_LDC_PC_G1}, 1765214634Sdim {BFD_RELOC_ARM_LDC_PC_G2, R_ARM_LDC_PC_G2}, 1766214634Sdim {BFD_RELOC_ARM_ALU_SB_G0_NC, R_ARM_ALU_SB_G0_NC}, 1767214634Sdim {BFD_RELOC_ARM_ALU_SB_G0, R_ARM_ALU_SB_G0}, 1768214634Sdim {BFD_RELOC_ARM_ALU_SB_G1_NC, R_ARM_ALU_SB_G1_NC}, 1769214634Sdim {BFD_RELOC_ARM_ALU_SB_G1, R_ARM_ALU_SB_G1}, 1770214634Sdim {BFD_RELOC_ARM_ALU_SB_G2, R_ARM_ALU_SB_G2}, 1771214634Sdim {BFD_RELOC_ARM_LDR_SB_G0, R_ARM_LDR_SB_G0}, 1772214634Sdim {BFD_RELOC_ARM_LDR_SB_G1, R_ARM_LDR_SB_G1}, 1773214634Sdim {BFD_RELOC_ARM_LDR_SB_G2, R_ARM_LDR_SB_G2}, 1774214634Sdim {BFD_RELOC_ARM_LDRS_SB_G0, R_ARM_LDRS_SB_G0}, 1775214634Sdim {BFD_RELOC_ARM_LDRS_SB_G1, R_ARM_LDRS_SB_G1}, 1776214634Sdim {BFD_RELOC_ARM_LDRS_SB_G2, R_ARM_LDRS_SB_G2}, 1777214634Sdim {BFD_RELOC_ARM_LDC_SB_G0, R_ARM_LDC_SB_G0}, 1778214634Sdim {BFD_RELOC_ARM_LDC_SB_G1, R_ARM_LDC_SB_G1}, 1779214634Sdim {BFD_RELOC_ARM_LDC_SB_G2, R_ARM_LDC_SB_G2} 1780214082Sdim }; 1781214082Sdim 1782214082Sdimstatic reloc_howto_type * 1783214082Sdimelf32_arm_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1784214082Sdim bfd_reloc_code_real_type code) 1785214082Sdim{ 1786214082Sdim unsigned int i; 1787214082Sdim for (i = 0; i < NUM_ELEM (elf32_arm_reloc_map); i ++) 1788214082Sdim if (elf32_arm_reloc_map[i].bfd_reloc_val == code) 1789214082Sdim return elf32_arm_howto_from_type (elf32_arm_reloc_map[i].elf_reloc_val); 1790214082Sdim 1791214082Sdim return NULL; 1792214082Sdim} 1793214082Sdim 1794214634Sdimstatic reloc_howto_type * 1795214634Sdimelf32_arm_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1796214634Sdim const char *r_name) 1797214634Sdim{ 1798214634Sdim unsigned int i; 1799214634Sdim 1800214634Sdim for (i = 0; 1801214634Sdim i < (sizeof (elf32_arm_howto_table_1) 1802214634Sdim / sizeof (elf32_arm_howto_table_1[0])); 1803214634Sdim i++) 1804214634Sdim if (elf32_arm_howto_table_1[i].name != NULL 1805214634Sdim && strcasecmp (elf32_arm_howto_table_1[i].name, r_name) == 0) 1806214634Sdim return &elf32_arm_howto_table_1[i]; 1807214634Sdim 1808214634Sdim for (i = 0; 1809214634Sdim i < (sizeof (elf32_arm_howto_table_2) 1810214634Sdim / sizeof (elf32_arm_howto_table_2[0])); 1811214634Sdim i++) 1812214634Sdim if (elf32_arm_howto_table_2[i].name != NULL 1813214634Sdim && strcasecmp (elf32_arm_howto_table_2[i].name, r_name) == 0) 1814214634Sdim return &elf32_arm_howto_table_2[i]; 1815214634Sdim 1816214634Sdim return NULL; 1817214634Sdim} 1818214634Sdim 1819214082Sdim/* Support for core dump NOTE sections */ 1820214082Sdimstatic bfd_boolean 1821214082Sdimelf32_arm_nabi_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 1822214082Sdim{ 1823214082Sdim int offset; 1824214082Sdim size_t size; 1825214082Sdim 1826214082Sdim switch (note->descsz) 1827214082Sdim { 1828214082Sdim default: 1829214082Sdim return FALSE; 1830214082Sdim 1831214082Sdim case 148: /* Linux/ARM 32-bit*/ 1832214082Sdim /* pr_cursig */ 1833214082Sdim elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 1834214082Sdim 1835214082Sdim /* pr_pid */ 1836214082Sdim elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 1837214082Sdim 1838214082Sdim /* pr_reg */ 1839214082Sdim offset = 72; 1840214082Sdim size = 72; 1841214082Sdim 1842214082Sdim break; 1843214157Sdim 1844214157Sdim case 96: /* FreeBSD/ARM */ 1845214157Sdim /* pr_cursig */ 1846214157Sdim if (elf_tdata(abfd)->core_signal == 0) 1847214157Sdim elf_tdata (abfd)->core_signal = ((int *)(note->descdata))[5]; 1848214157Sdim 1849214157Sdim /* pr_pid */ 1850214157Sdim elf_tdata (abfd)->core_pid = ((int *)(note->descdata))[6]; 1851214157Sdim 1852214157Sdim /* pr_reg */ 1853214157Sdim offset = 28; 1854214157Sdim size = 68; 1855214157Sdim break; 1856214082Sdim } 1857214082Sdim 1858214082Sdim /* Make a ".reg/999" section. */ 1859214082Sdim return _bfd_elfcore_make_pseudosection (abfd, ".reg", 1860214082Sdim size, note->descpos + offset); 1861214082Sdim} 1862214082Sdim 1863214082Sdimstatic bfd_boolean 1864214082Sdimelf32_arm_nabi_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 1865214082Sdim{ 1866214082Sdim switch (note->descsz) 1867214082Sdim { 1868214082Sdim default: 1869214082Sdim return FALSE; 1870214082Sdim 1871214082Sdim case 124: /* Linux/ARM elf_prpsinfo */ 1872214082Sdim elf_tdata (abfd)->core_program 1873214082Sdim = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); 1874214082Sdim elf_tdata (abfd)->core_command 1875214082Sdim = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); 1876214082Sdim } 1877214082Sdim 1878214082Sdim /* Note that for some reason, a spurious space is tacked 1879214082Sdim onto the end of the args in some (at least one anyway) 1880214082Sdim implementations, so strip it off if it exists. */ 1881214082Sdim 1882214082Sdim { 1883214082Sdim char *command = elf_tdata (abfd)->core_command; 1884214082Sdim int n = strlen (command); 1885214082Sdim 1886214082Sdim if (0 < n && command[n - 1] == ' ') 1887214082Sdim command[n - 1] = '\0'; 1888214082Sdim } 1889214082Sdim 1890214082Sdim return TRUE; 1891214082Sdim} 1892214082Sdim 1893214082Sdim#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec 1894214082Sdim#define TARGET_LITTLE_NAME "elf32-littlearm" 1895214082Sdim#define TARGET_BIG_SYM bfd_elf32_bigarm_vec 1896214082Sdim#define TARGET_BIG_NAME "elf32-bigarm" 1897214082Sdim 1898214082Sdim#define elf_backend_grok_prstatus elf32_arm_nabi_grok_prstatus 1899214082Sdim#define elf_backend_grok_psinfo elf32_arm_nabi_grok_psinfo 1900214082Sdim 1901214082Sdimtypedef unsigned long int insn32; 1902214082Sdimtypedef unsigned short int insn16; 1903214082Sdim 1904214082Sdim/* In lieu of proper flags, assume all EABIv4 or later objects are 1905214082Sdim interworkable. */ 1906214082Sdim#define INTERWORK_FLAG(abfd) \ 1907214082Sdim (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) >= EF_ARM_EABI_VER4 \ 1908214082Sdim || (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK)) 1909214082Sdim 1910214082Sdim/* The linker script knows the section names for placement. 1911214082Sdim The entry_names are used to do simple name mangling on the stubs. 1912214082Sdim Given a function name, and its type, the stub can be found. The 1913214082Sdim name can be changed. The only requirement is the %s be present. */ 1914214082Sdim#define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t" 1915214082Sdim#define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb" 1916214082Sdim 1917214082Sdim#define ARM2THUMB_GLUE_SECTION_NAME ".glue_7" 1918214082Sdim#define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm" 1919214082Sdim 1920214634Sdim#define VFP11_ERRATUM_VENEER_SECTION_NAME ".vfp11_veneer" 1921214634Sdim#define VFP11_ERRATUM_VENEER_ENTRY_NAME "__vfp11_veneer_%x" 1922214634Sdim 1923214082Sdim/* The name of the dynamic interpreter. This is put in the .interp 1924214082Sdim section. */ 1925214082Sdim#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" 1926214082Sdim 1927214082Sdim#ifdef FOUR_WORD_PLT 1928214082Sdim 1929214082Sdim/* The first entry in a procedure linkage table looks like 1930214082Sdim this. It is set up so that any shared library function that is 1931214082Sdim called before the relocation has been set up calls the dynamic 1932214082Sdim linker first. */ 1933214082Sdimstatic const bfd_vma elf32_arm_plt0_entry [] = 1934214082Sdim { 1935214082Sdim 0xe52de004, /* str lr, [sp, #-4]! */ 1936214082Sdim 0xe59fe010, /* ldr lr, [pc, #16] */ 1937214082Sdim 0xe08fe00e, /* add lr, pc, lr */ 1938214082Sdim 0xe5bef008, /* ldr pc, [lr, #8]! */ 1939214082Sdim }; 1940214082Sdim 1941214082Sdim/* Subsequent entries in a procedure linkage table look like 1942214082Sdim this. */ 1943214082Sdimstatic const bfd_vma elf32_arm_plt_entry [] = 1944214082Sdim { 1945214082Sdim 0xe28fc600, /* add ip, pc, #NN */ 1946214082Sdim 0xe28cca00, /* add ip, ip, #NN */ 1947214082Sdim 0xe5bcf000, /* ldr pc, [ip, #NN]! */ 1948214082Sdim 0x00000000, /* unused */ 1949214082Sdim }; 1950214082Sdim 1951214082Sdim#else 1952214082Sdim 1953214082Sdim/* The first entry in a procedure linkage table looks like 1954214082Sdim this. It is set up so that any shared library function that is 1955214082Sdim called before the relocation has been set up calls the dynamic 1956214082Sdim linker first. */ 1957214082Sdimstatic const bfd_vma elf32_arm_plt0_entry [] = 1958214082Sdim { 1959214082Sdim 0xe52de004, /* str lr, [sp, #-4]! */ 1960214082Sdim 0xe59fe004, /* ldr lr, [pc, #4] */ 1961214082Sdim 0xe08fe00e, /* add lr, pc, lr */ 1962214082Sdim 0xe5bef008, /* ldr pc, [lr, #8]! */ 1963214082Sdim 0x00000000, /* &GOT[0] - . */ 1964214082Sdim }; 1965214082Sdim 1966214082Sdim/* Subsequent entries in a procedure linkage table look like 1967214082Sdim this. */ 1968214082Sdimstatic const bfd_vma elf32_arm_plt_entry [] = 1969214082Sdim { 1970214082Sdim 0xe28fc600, /* add ip, pc, #0xNN00000 */ 1971214082Sdim 0xe28cca00, /* add ip, ip, #0xNN000 */ 1972214082Sdim 0xe5bcf000, /* ldr pc, [ip, #0xNNN]! */ 1973214082Sdim }; 1974214082Sdim 1975214082Sdim#endif 1976214082Sdim 1977214082Sdim/* The format of the first entry in the procedure linkage table 1978214082Sdim for a VxWorks executable. */ 1979214082Sdimstatic const bfd_vma elf32_arm_vxworks_exec_plt0_entry[] = 1980214082Sdim { 1981214082Sdim 0xe52dc008, /* str ip,[sp,#-8]! */ 1982214082Sdim 0xe59fc000, /* ldr ip,[pc] */ 1983214082Sdim 0xe59cf008, /* ldr pc,[ip,#8] */ 1984214082Sdim 0x00000000, /* .long _GLOBAL_OFFSET_TABLE_ */ 1985214082Sdim }; 1986214082Sdim 1987214082Sdim/* The format of subsequent entries in a VxWorks executable. */ 1988214082Sdimstatic const bfd_vma elf32_arm_vxworks_exec_plt_entry[] = 1989214082Sdim { 1990214082Sdim 0xe59fc000, /* ldr ip,[pc] */ 1991214082Sdim 0xe59cf000, /* ldr pc,[ip] */ 1992214082Sdim 0x00000000, /* .long @got */ 1993214082Sdim 0xe59fc000, /* ldr ip,[pc] */ 1994214082Sdim 0xea000000, /* b _PLT */ 1995214082Sdim 0x00000000, /* .long @pltindex*sizeof(Elf32_Rela) */ 1996214082Sdim }; 1997214082Sdim 1998214082Sdim/* The format of entries in a VxWorks shared library. */ 1999214082Sdimstatic const bfd_vma elf32_arm_vxworks_shared_plt_entry[] = 2000214082Sdim { 2001214082Sdim 0xe59fc000, /* ldr ip,[pc] */ 2002214082Sdim 0xe79cf009, /* ldr pc,[ip,r9] */ 2003214082Sdim 0x00000000, /* .long @got */ 2004214082Sdim 0xe59fc000, /* ldr ip,[pc] */ 2005214082Sdim 0xe599f008, /* ldr pc,[r9,#8] */ 2006214082Sdim 0x00000000, /* .long @pltindex*sizeof(Elf32_Rela) */ 2007214082Sdim }; 2008214082Sdim 2009214082Sdim/* An initial stub used if the PLT entry is referenced from Thumb code. */ 2010214082Sdim#define PLT_THUMB_STUB_SIZE 4 2011214082Sdimstatic const bfd_vma elf32_arm_plt_thumb_stub [] = 2012214082Sdim { 2013214082Sdim 0x4778, /* bx pc */ 2014214082Sdim 0x46c0 /* nop */ 2015214082Sdim }; 2016214082Sdim 2017214082Sdim/* The entries in a PLT when using a DLL-based target with multiple 2018214082Sdim address spaces. */ 2019214082Sdimstatic const bfd_vma elf32_arm_symbian_plt_entry [] = 2020214082Sdim { 2021214082Sdim 0xe51ff004, /* ldr pc, [pc, #-4] */ 2022214082Sdim 0x00000000, /* dcd R_ARM_GLOB_DAT(X) */ 2023214082Sdim }; 2024214082Sdim 2025214082Sdim/* Used to build a map of a section. This is required for mixed-endian 2026214082Sdim code/data. */ 2027214082Sdim 2028214082Sdimtypedef struct elf32_elf_section_map 2029214082Sdim{ 2030214082Sdim bfd_vma vma; 2031214082Sdim char type; 2032214082Sdim} 2033214082Sdimelf32_arm_section_map; 2034214082Sdim 2035214634Sdim/* Information about a VFP11 erratum veneer, or a branch to such a veneer. */ 2036214634Sdim 2037214634Sdimtypedef enum 2038214634Sdim{ 2039214634Sdim VFP11_ERRATUM_BRANCH_TO_ARM_VENEER, 2040214634Sdim VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER, 2041214634Sdim VFP11_ERRATUM_ARM_VENEER, 2042214634Sdim VFP11_ERRATUM_THUMB_VENEER 2043214634Sdim} 2044214634Sdimelf32_vfp11_erratum_type; 2045214634Sdim 2046214634Sdimtypedef struct elf32_vfp11_erratum_list 2047214634Sdim{ 2048214634Sdim struct elf32_vfp11_erratum_list *next; 2049214634Sdim bfd_vma vma; 2050214634Sdim union 2051214634Sdim { 2052214634Sdim struct 2053214634Sdim { 2054214634Sdim struct elf32_vfp11_erratum_list *veneer; 2055214634Sdim unsigned int vfp_insn; 2056214634Sdim } b; 2057214634Sdim struct 2058214634Sdim { 2059214634Sdim struct elf32_vfp11_erratum_list *branch; 2060214634Sdim unsigned int id; 2061214634Sdim } v; 2062214634Sdim } u; 2063214634Sdim elf32_vfp11_erratum_type type; 2064214634Sdim} 2065214634Sdimelf32_vfp11_erratum_list; 2066214634Sdim 2067214082Sdimtypedef struct _arm_elf_section_data 2068214082Sdim{ 2069214082Sdim struct bfd_elf_section_data elf; 2070214082Sdim unsigned int mapcount; 2071214634Sdim unsigned int mapsize; 2072214082Sdim elf32_arm_section_map *map; 2073214634Sdim unsigned int erratumcount; 2074214634Sdim elf32_vfp11_erratum_list *erratumlist; 2075214082Sdim} 2076214082Sdim_arm_elf_section_data; 2077214082Sdim 2078214082Sdim#define elf32_arm_section_data(sec) \ 2079214082Sdim ((_arm_elf_section_data *) elf_section_data (sec)) 2080214082Sdim 2081214082Sdim/* The size of the thread control block. */ 2082214082Sdim#define TCB_SIZE 8 2083214082Sdim 2084214082Sdimstruct elf32_arm_obj_tdata 2085214082Sdim{ 2086214082Sdim struct elf_obj_tdata root; 2087214082Sdim 2088214082Sdim /* tls_type for each local got entry. */ 2089214082Sdim char *local_got_tls_type; 2090214082Sdim 2091214634Sdim /* Zero to warn when linking objects with incompatible enum sizes. */ 2092214634Sdim int no_enum_size_warning; 2093214082Sdim}; 2094214082Sdim 2095214082Sdim#define elf32_arm_tdata(abfd) \ 2096214082Sdim ((struct elf32_arm_obj_tdata *) (abfd)->tdata.any) 2097214082Sdim 2098214082Sdim#define elf32_arm_local_got_tls_type(abfd) \ 2099214082Sdim (elf32_arm_tdata (abfd)->local_got_tls_type) 2100214082Sdim 2101214082Sdimstatic bfd_boolean 2102214082Sdimelf32_arm_mkobject (bfd *abfd) 2103214082Sdim{ 2104214082Sdim if (abfd->tdata.any == NULL) 2105214634Sdim { 2106214634Sdim bfd_size_type amt = sizeof (struct elf32_arm_obj_tdata); 2107214634Sdim abfd->tdata.any = bfd_zalloc (abfd, amt); 2108214634Sdim if (abfd->tdata.any == NULL) 2109214634Sdim return FALSE; 2110214634Sdim } 2111214634Sdim return bfd_elf_mkobject (abfd); 2112214082Sdim} 2113214082Sdim 2114214082Sdim/* The ARM linker needs to keep track of the number of relocs that it 2115214082Sdim decides to copy in check_relocs for each symbol. This is so that 2116214082Sdim it can discard PC relative relocs if it doesn't need them when 2117214082Sdim linking with -Bsymbolic. We store the information in a field 2118214082Sdim extending the regular ELF linker hash table. */ 2119214082Sdim 2120214082Sdim/* This structure keeps track of the number of relocs we have copied 2121214082Sdim for a given symbol. */ 2122214082Sdimstruct elf32_arm_relocs_copied 2123214082Sdim { 2124214082Sdim /* Next section. */ 2125214082Sdim struct elf32_arm_relocs_copied * next; 2126214082Sdim /* A section in dynobj. */ 2127214082Sdim asection * section; 2128214082Sdim /* Number of relocs copied in this section. */ 2129214082Sdim bfd_size_type count; 2130214082Sdim /* Number of PC-relative relocs copied in this section. */ 2131214082Sdim bfd_size_type pc_count; 2132214082Sdim }; 2133214082Sdim 2134214082Sdim#define elf32_arm_hash_entry(ent) ((struct elf32_arm_link_hash_entry *)(ent)) 2135214082Sdim 2136214082Sdim/* Arm ELF linker hash entry. */ 2137214082Sdimstruct elf32_arm_link_hash_entry 2138214082Sdim { 2139214082Sdim struct elf_link_hash_entry root; 2140214082Sdim 2141214082Sdim /* Number of PC relative relocs copied for this symbol. */ 2142214082Sdim struct elf32_arm_relocs_copied * relocs_copied; 2143214082Sdim 2144214082Sdim /* We reference count Thumb references to a PLT entry separately, 2145214082Sdim so that we can emit the Thumb trampoline only if needed. */ 2146214082Sdim bfd_signed_vma plt_thumb_refcount; 2147214082Sdim 2148214082Sdim /* Since PLT entries have variable size if the Thumb prologue is 2149214082Sdim used, we need to record the index into .got.plt instead of 2150214082Sdim recomputing it from the PLT offset. */ 2151214082Sdim bfd_signed_vma plt_got_offset; 2152214082Sdim 2153214082Sdim#define GOT_UNKNOWN 0 2154214082Sdim#define GOT_NORMAL 1 2155214082Sdim#define GOT_TLS_GD 2 2156214082Sdim#define GOT_TLS_IE 4 2157214082Sdim unsigned char tls_type; 2158214634Sdim 2159214634Sdim /* The symbol marking the real symbol location for exported thumb 2160214634Sdim symbols with Arm stubs. */ 2161214634Sdim struct elf_link_hash_entry *export_glue; 2162214082Sdim }; 2163214082Sdim 2164214082Sdim/* Traverse an arm ELF linker hash table. */ 2165214082Sdim#define elf32_arm_link_hash_traverse(table, func, info) \ 2166214082Sdim (elf_link_hash_traverse \ 2167214082Sdim (&(table)->root, \ 2168214082Sdim (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \ 2169214082Sdim (info))) 2170214082Sdim 2171214082Sdim/* Get the ARM elf linker hash table from a link_info structure. */ 2172214082Sdim#define elf32_arm_hash_table(info) \ 2173214082Sdim ((struct elf32_arm_link_hash_table *) ((info)->hash)) 2174214082Sdim 2175214082Sdim/* ARM ELF linker hash table. */ 2176214082Sdimstruct elf32_arm_link_hash_table 2177214082Sdim { 2178214082Sdim /* The main hash table. */ 2179214082Sdim struct elf_link_hash_table root; 2180214082Sdim 2181214082Sdim /* The size in bytes of the section containing the Thumb-to-ARM glue. */ 2182214082Sdim bfd_size_type thumb_glue_size; 2183214082Sdim 2184214082Sdim /* The size in bytes of the section containing the ARM-to-Thumb glue. */ 2185214082Sdim bfd_size_type arm_glue_size; 2186214082Sdim 2187214634Sdim /* The size in bytes of the section containing glue for VFP11 erratum 2188214634Sdim veneers. */ 2189214634Sdim bfd_size_type vfp11_erratum_glue_size; 2190214634Sdim 2191214082Sdim /* An arbitrary input BFD chosen to hold the glue sections. */ 2192214082Sdim bfd * bfd_of_glue_owner; 2193214082Sdim 2194214082Sdim /* Nonzero to output a BE8 image. */ 2195214082Sdim int byteswap_code; 2196214082Sdim 2197214082Sdim /* Zero if R_ARM_TARGET1 means R_ARM_ABS32. 2198214634Sdim Nonzero if R_ARM_TARGET1 means R_ARM_REL32. */ 2199214082Sdim int target1_is_rel; 2200214082Sdim 2201214082Sdim /* The relocation to use for R_ARM_TARGET2 relocations. */ 2202214082Sdim int target2_reloc; 2203214082Sdim 2204214082Sdim /* Nonzero to fix BX instructions for ARMv4 targets. */ 2205214082Sdim int fix_v4bx; 2206214082Sdim 2207214082Sdim /* Nonzero if the ARM/Thumb BLX instructions are available for use. */ 2208214082Sdim int use_blx; 2209214082Sdim 2210214634Sdim /* What sort of code sequences we should look for which may trigger the 2211214634Sdim VFP11 denorm erratum. */ 2212214634Sdim bfd_arm_vfp11_fix vfp11_fix; 2213214634Sdim 2214214634Sdim /* Global counter for the number of fixes we have emitted. */ 2215214634Sdim int num_vfp11_fixes; 2216214634Sdim 2217214634Sdim /* Nonzero to force PIC branch veneers. */ 2218214634Sdim int pic_veneer; 2219214634Sdim 2220214082Sdim /* The number of bytes in the initial entry in the PLT. */ 2221214082Sdim bfd_size_type plt_header_size; 2222214082Sdim 2223214082Sdim /* The number of bytes in the subsequent PLT etries. */ 2224214082Sdim bfd_size_type plt_entry_size; 2225214082Sdim 2226214082Sdim /* True if the target system is VxWorks. */ 2227214082Sdim int vxworks_p; 2228214082Sdim 2229214082Sdim /* True if the target system is Symbian OS. */ 2230214082Sdim int symbian_p; 2231214082Sdim 2232214082Sdim /* True if the target uses REL relocations. */ 2233214082Sdim int use_rel; 2234214082Sdim 2235214082Sdim /* Short-cuts to get to dynamic linker sections. */ 2236214082Sdim asection *sgot; 2237214082Sdim asection *sgotplt; 2238214082Sdim asection *srelgot; 2239214082Sdim asection *splt; 2240214082Sdim asection *srelplt; 2241214082Sdim asection *sdynbss; 2242214082Sdim asection *srelbss; 2243214082Sdim 2244214082Sdim /* The (unloaded but important) VxWorks .rela.plt.unloaded section. */ 2245214082Sdim asection *srelplt2; 2246214082Sdim 2247214082Sdim /* Data for R_ARM_TLS_LDM32 relocations. */ 2248214082Sdim union { 2249214082Sdim bfd_signed_vma refcount; 2250214082Sdim bfd_vma offset; 2251214082Sdim } tls_ldm_got; 2252214082Sdim 2253214082Sdim /* Small local sym to section mapping cache. */ 2254214082Sdim struct sym_sec_cache sym_sec; 2255214082Sdim 2256214082Sdim /* For convenience in allocate_dynrelocs. */ 2257214082Sdim bfd * obfd; 2258214082Sdim }; 2259214082Sdim 2260214082Sdim/* Create an entry in an ARM ELF linker hash table. */ 2261214082Sdim 2262214082Sdimstatic struct bfd_hash_entry * 2263214082Sdimelf32_arm_link_hash_newfunc (struct bfd_hash_entry * entry, 2264214082Sdim struct bfd_hash_table * table, 2265214082Sdim const char * string) 2266214082Sdim{ 2267214082Sdim struct elf32_arm_link_hash_entry * ret = 2268214082Sdim (struct elf32_arm_link_hash_entry *) entry; 2269214082Sdim 2270214082Sdim /* Allocate the structure if it has not already been allocated by a 2271214082Sdim subclass. */ 2272214082Sdim if (ret == (struct elf32_arm_link_hash_entry *) NULL) 2273214082Sdim ret = bfd_hash_allocate (table, sizeof (struct elf32_arm_link_hash_entry)); 2274214082Sdim if (ret == NULL) 2275214082Sdim return (struct bfd_hash_entry *) ret; 2276214082Sdim 2277214082Sdim /* Call the allocation method of the superclass. */ 2278214082Sdim ret = ((struct elf32_arm_link_hash_entry *) 2279214082Sdim _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, 2280214082Sdim table, string)); 2281214082Sdim if (ret != NULL) 2282214082Sdim { 2283214082Sdim ret->relocs_copied = NULL; 2284214082Sdim ret->tls_type = GOT_UNKNOWN; 2285214082Sdim ret->plt_thumb_refcount = 0; 2286214082Sdim ret->plt_got_offset = -1; 2287214634Sdim ret->export_glue = NULL; 2288214082Sdim } 2289214082Sdim 2290214082Sdim return (struct bfd_hash_entry *) ret; 2291214082Sdim} 2292214082Sdim 2293214082Sdim/* Return true if NAME is the name of the relocation section associated 2294214082Sdim with S. */ 2295214082Sdim 2296214082Sdimstatic bfd_boolean 2297214082Sdimreloc_section_p (struct elf32_arm_link_hash_table *htab, 2298214082Sdim const char *name, asection *s) 2299214082Sdim{ 2300214082Sdim if (htab->use_rel) 2301214634Sdim return CONST_STRNEQ (name, ".rel") && strcmp (s->name, name + 4) == 0; 2302214082Sdim else 2303214634Sdim return CONST_STRNEQ (name, ".rela") && strcmp (s->name, name + 5) == 0; 2304214082Sdim} 2305214082Sdim 2306214082Sdim/* Create .got, .gotplt, and .rel(a).got sections in DYNOBJ, and set up 2307214082Sdim shortcuts to them in our hash table. */ 2308214082Sdim 2309214082Sdimstatic bfd_boolean 2310214082Sdimcreate_got_section (bfd *dynobj, struct bfd_link_info *info) 2311214082Sdim{ 2312214082Sdim struct elf32_arm_link_hash_table *htab; 2313214082Sdim 2314214082Sdim htab = elf32_arm_hash_table (info); 2315214082Sdim /* BPABI objects never have a GOT, or associated sections. */ 2316214082Sdim if (htab->symbian_p) 2317214082Sdim return TRUE; 2318214082Sdim 2319214082Sdim if (! _bfd_elf_create_got_section (dynobj, info)) 2320214082Sdim return FALSE; 2321214082Sdim 2322214082Sdim htab->sgot = bfd_get_section_by_name (dynobj, ".got"); 2323214082Sdim htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); 2324214082Sdim if (!htab->sgot || !htab->sgotplt) 2325214082Sdim abort (); 2326214082Sdim 2327214082Sdim htab->srelgot = bfd_make_section_with_flags (dynobj, 2328214082Sdim RELOC_SECTION (htab, ".got"), 2329214082Sdim (SEC_ALLOC | SEC_LOAD 2330214082Sdim | SEC_HAS_CONTENTS 2331214082Sdim | SEC_IN_MEMORY 2332214082Sdim | SEC_LINKER_CREATED 2333214082Sdim | SEC_READONLY)); 2334214082Sdim if (htab->srelgot == NULL 2335214082Sdim || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) 2336214082Sdim return FALSE; 2337214082Sdim return TRUE; 2338214082Sdim} 2339214082Sdim 2340214082Sdim/* Create .plt, .rel(a).plt, .got, .got.plt, .rel(a).got, .dynbss, and 2341214082Sdim .rel(a).bss sections in DYNOBJ, and set up shortcuts to them in our 2342214082Sdim hash table. */ 2343214082Sdim 2344214082Sdimstatic bfd_boolean 2345214082Sdimelf32_arm_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) 2346214082Sdim{ 2347214082Sdim struct elf32_arm_link_hash_table *htab; 2348214082Sdim 2349214082Sdim htab = elf32_arm_hash_table (info); 2350214082Sdim if (!htab->sgot && !create_got_section (dynobj, info)) 2351214082Sdim return FALSE; 2352214082Sdim 2353214082Sdim if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 2354214082Sdim return FALSE; 2355214082Sdim 2356214082Sdim htab->splt = bfd_get_section_by_name (dynobj, ".plt"); 2357214082Sdim htab->srelplt = bfd_get_section_by_name (dynobj, 2358214082Sdim RELOC_SECTION (htab, ".plt")); 2359214082Sdim htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 2360214082Sdim if (!info->shared) 2361214082Sdim htab->srelbss = bfd_get_section_by_name (dynobj, 2362214082Sdim RELOC_SECTION (htab, ".bss")); 2363214082Sdim 2364214082Sdim if (htab->vxworks_p) 2365214082Sdim { 2366214082Sdim if (!elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) 2367214082Sdim return FALSE; 2368214082Sdim 2369214082Sdim if (info->shared) 2370214082Sdim { 2371214082Sdim htab->plt_header_size = 0; 2372214082Sdim htab->plt_entry_size 2373214082Sdim = 4 * ARRAY_SIZE (elf32_arm_vxworks_shared_plt_entry); 2374214082Sdim } 2375214082Sdim else 2376214082Sdim { 2377214082Sdim htab->plt_header_size 2378214082Sdim = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt0_entry); 2379214082Sdim htab->plt_entry_size 2380214082Sdim = 4 * ARRAY_SIZE (elf32_arm_vxworks_exec_plt_entry); 2381214082Sdim } 2382214082Sdim } 2383214082Sdim 2384214082Sdim if (!htab->splt 2385214082Sdim || !htab->srelplt 2386214082Sdim || !htab->sdynbss 2387214082Sdim || (!info->shared && !htab->srelbss)) 2388214082Sdim abort (); 2389214082Sdim 2390214082Sdim return TRUE; 2391214082Sdim} 2392214082Sdim 2393214082Sdim/* Copy the extra info we tack onto an elf_link_hash_entry. */ 2394214082Sdim 2395214082Sdimstatic void 2396214082Sdimelf32_arm_copy_indirect_symbol (struct bfd_link_info *info, 2397214082Sdim struct elf_link_hash_entry *dir, 2398214082Sdim struct elf_link_hash_entry *ind) 2399214082Sdim{ 2400214082Sdim struct elf32_arm_link_hash_entry *edir, *eind; 2401214082Sdim 2402214082Sdim edir = (struct elf32_arm_link_hash_entry *) dir; 2403214082Sdim eind = (struct elf32_arm_link_hash_entry *) ind; 2404214082Sdim 2405214082Sdim if (eind->relocs_copied != NULL) 2406214082Sdim { 2407214082Sdim if (edir->relocs_copied != NULL) 2408214082Sdim { 2409214082Sdim struct elf32_arm_relocs_copied **pp; 2410214082Sdim struct elf32_arm_relocs_copied *p; 2411214082Sdim 2412214082Sdim /* Add reloc counts against the indirect sym to the direct sym 2413214082Sdim list. Merge any entries against the same section. */ 2414214082Sdim for (pp = &eind->relocs_copied; (p = *pp) != NULL; ) 2415214082Sdim { 2416214082Sdim struct elf32_arm_relocs_copied *q; 2417214082Sdim 2418214082Sdim for (q = edir->relocs_copied; q != NULL; q = q->next) 2419214082Sdim if (q->section == p->section) 2420214082Sdim { 2421214082Sdim q->pc_count += p->pc_count; 2422214082Sdim q->count += p->count; 2423214082Sdim *pp = p->next; 2424214082Sdim break; 2425214082Sdim } 2426214082Sdim if (q == NULL) 2427214082Sdim pp = &p->next; 2428214082Sdim } 2429214082Sdim *pp = edir->relocs_copied; 2430214082Sdim } 2431214082Sdim 2432214082Sdim edir->relocs_copied = eind->relocs_copied; 2433214082Sdim eind->relocs_copied = NULL; 2434214082Sdim } 2435214082Sdim 2436214634Sdim if (ind->root.type == bfd_link_hash_indirect) 2437214634Sdim { 2438214634Sdim /* Copy over PLT info. */ 2439214634Sdim edir->plt_thumb_refcount += eind->plt_thumb_refcount; 2440214634Sdim eind->plt_thumb_refcount = 0; 2441214082Sdim 2442214634Sdim if (dir->got.refcount <= 0) 2443214634Sdim { 2444214634Sdim edir->tls_type = eind->tls_type; 2445214634Sdim eind->tls_type = GOT_UNKNOWN; 2446214634Sdim } 2447214082Sdim } 2448214082Sdim 2449214082Sdim _bfd_elf_link_hash_copy_indirect (info, dir, ind); 2450214082Sdim} 2451214082Sdim 2452214082Sdim/* Create an ARM elf linker hash table. */ 2453214082Sdim 2454214082Sdimstatic struct bfd_link_hash_table * 2455214082Sdimelf32_arm_link_hash_table_create (bfd *abfd) 2456214082Sdim{ 2457214082Sdim struct elf32_arm_link_hash_table *ret; 2458214082Sdim bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table); 2459214082Sdim 2460214082Sdim ret = bfd_malloc (amt); 2461214082Sdim if (ret == NULL) 2462214082Sdim return NULL; 2463214082Sdim 2464214082Sdim if (!_bfd_elf_link_hash_table_init (& ret->root, abfd, 2465214082Sdim elf32_arm_link_hash_newfunc, 2466214082Sdim sizeof (struct elf32_arm_link_hash_entry))) 2467214082Sdim { 2468214082Sdim free (ret); 2469214082Sdim return NULL; 2470214082Sdim } 2471214082Sdim 2472214082Sdim ret->sgot = NULL; 2473214082Sdim ret->sgotplt = NULL; 2474214082Sdim ret->srelgot = NULL; 2475214082Sdim ret->splt = NULL; 2476214082Sdim ret->srelplt = NULL; 2477214082Sdim ret->sdynbss = NULL; 2478214082Sdim ret->srelbss = NULL; 2479214082Sdim ret->srelplt2 = NULL; 2480214082Sdim ret->thumb_glue_size = 0; 2481214082Sdim ret->arm_glue_size = 0; 2482214634Sdim ret->vfp11_fix = BFD_ARM_VFP11_FIX_NONE; 2483214634Sdim ret->vfp11_erratum_glue_size = 0; 2484214634Sdim ret->num_vfp11_fixes = 0; 2485214082Sdim ret->bfd_of_glue_owner = NULL; 2486214082Sdim ret->byteswap_code = 0; 2487214082Sdim ret->target1_is_rel = 0; 2488214082Sdim ret->target2_reloc = R_ARM_NONE; 2489214082Sdim#ifdef FOUR_WORD_PLT 2490214082Sdim ret->plt_header_size = 16; 2491214082Sdim ret->plt_entry_size = 16; 2492214082Sdim#else 2493214082Sdim ret->plt_header_size = 20; 2494214082Sdim ret->plt_entry_size = 12; 2495214082Sdim#endif 2496214082Sdim ret->fix_v4bx = 0; 2497214082Sdim ret->use_blx = 0; 2498214082Sdim ret->vxworks_p = 0; 2499214082Sdim ret->symbian_p = 0; 2500214082Sdim ret->use_rel = 1; 2501214082Sdim ret->sym_sec.abfd = NULL; 2502214082Sdim ret->obfd = abfd; 2503214082Sdim ret->tls_ldm_got.refcount = 0; 2504214082Sdim 2505214082Sdim return &ret->root.root; 2506214082Sdim} 2507214082Sdim 2508214082Sdim/* Locate the Thumb encoded calling stub for NAME. */ 2509214082Sdim 2510214082Sdimstatic struct elf_link_hash_entry * 2511214082Sdimfind_thumb_glue (struct bfd_link_info *link_info, 2512214082Sdim const char *name, 2513214634Sdim char **error_message) 2514214082Sdim{ 2515214082Sdim char *tmp_name; 2516214082Sdim struct elf_link_hash_entry *hash; 2517214082Sdim struct elf32_arm_link_hash_table *hash_table; 2518214082Sdim 2519214082Sdim /* We need a pointer to the armelf specific hash table. */ 2520214082Sdim hash_table = elf32_arm_hash_table (link_info); 2521214082Sdim 2522214082Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen (name) 2523214082Sdim + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1); 2524214082Sdim 2525214082Sdim BFD_ASSERT (tmp_name); 2526214082Sdim 2527214082Sdim sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name); 2528214082Sdim 2529214082Sdim hash = elf_link_hash_lookup 2530214082Sdim (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE); 2531214082Sdim 2532214082Sdim if (hash == NULL) 2533214634Sdim asprintf (error_message, _("unable to find THUMB glue '%s' for '%s'"), 2534214634Sdim tmp_name, name); 2535214082Sdim 2536214082Sdim free (tmp_name); 2537214082Sdim 2538214082Sdim return hash; 2539214082Sdim} 2540214082Sdim 2541214082Sdim/* Locate the ARM encoded calling stub for NAME. */ 2542214082Sdim 2543214082Sdimstatic struct elf_link_hash_entry * 2544214082Sdimfind_arm_glue (struct bfd_link_info *link_info, 2545214082Sdim const char *name, 2546214634Sdim char **error_message) 2547214082Sdim{ 2548214082Sdim char *tmp_name; 2549214082Sdim struct elf_link_hash_entry *myh; 2550214082Sdim struct elf32_arm_link_hash_table *hash_table; 2551214082Sdim 2552214082Sdim /* We need a pointer to the elfarm specific hash table. */ 2553214082Sdim hash_table = elf32_arm_hash_table (link_info); 2554214082Sdim 2555214082Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen (name) 2556214082Sdim + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1); 2557214082Sdim 2558214082Sdim BFD_ASSERT (tmp_name); 2559214082Sdim 2560214082Sdim sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name); 2561214082Sdim 2562214082Sdim myh = elf_link_hash_lookup 2563214082Sdim (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE); 2564214082Sdim 2565214082Sdim if (myh == NULL) 2566214634Sdim asprintf (error_message, _("unable to find ARM glue '%s' for '%s'"), 2567214634Sdim tmp_name, name); 2568214082Sdim 2569214082Sdim free (tmp_name); 2570214082Sdim 2571214082Sdim return myh; 2572214082Sdim} 2573214082Sdim 2574214082Sdim/* ARM->Thumb glue (static images): 2575214082Sdim 2576214082Sdim .arm 2577214082Sdim __func_from_arm: 2578214082Sdim ldr r12, __func_addr 2579214082Sdim bx r12 2580214082Sdim __func_addr: 2581214082Sdim .word func @ behave as if you saw a ARM_32 reloc. 2582214082Sdim 2583214634Sdim (v5t static images) 2584214634Sdim .arm 2585214634Sdim __func_from_arm: 2586214634Sdim ldr pc, __func_addr 2587214634Sdim __func_addr: 2588214634Sdim .word func @ behave as if you saw a ARM_32 reloc. 2589214634Sdim 2590214082Sdim (relocatable images) 2591214082Sdim .arm 2592214082Sdim __func_from_arm: 2593214082Sdim ldr r12, __func_offset 2594214082Sdim add r12, r12, pc 2595214082Sdim bx r12 2596214082Sdim __func_offset: 2597214082Sdim .word func - . 2598214082Sdim */ 2599214082Sdim 2600214082Sdim#define ARM2THUMB_STATIC_GLUE_SIZE 12 2601214082Sdimstatic const insn32 a2t1_ldr_insn = 0xe59fc000; 2602214082Sdimstatic const insn32 a2t2_bx_r12_insn = 0xe12fff1c; 2603214082Sdimstatic const insn32 a2t3_func_addr_insn = 0x00000001; 2604214082Sdim 2605214634Sdim#define ARM2THUMB_V5_STATIC_GLUE_SIZE 8 2606214634Sdimstatic const insn32 a2t1v5_ldr_insn = 0xe51ff004; 2607214634Sdimstatic const insn32 a2t2v5_func_addr_insn = 0x00000001; 2608214634Sdim 2609214082Sdim#define ARM2THUMB_PIC_GLUE_SIZE 16 2610214082Sdimstatic const insn32 a2t1p_ldr_insn = 0xe59fc004; 2611214082Sdimstatic const insn32 a2t2p_add_pc_insn = 0xe08cc00f; 2612214082Sdimstatic const insn32 a2t3p_bx_r12_insn = 0xe12fff1c; 2613214082Sdim 2614214082Sdim/* Thumb->ARM: Thumb->(non-interworking aware) ARM 2615214082Sdim 2616214082Sdim .thumb .thumb 2617214082Sdim .align 2 .align 2 2618214082Sdim __func_from_thumb: __func_from_thumb: 2619214082Sdim bx pc push {r6, lr} 2620214082Sdim nop ldr r6, __func_addr 2621214082Sdim .arm mov lr, pc 2622214082Sdim __func_change_to_arm: bx r6 2623214082Sdim b func .arm 2624214082Sdim __func_back_to_thumb: 2625214082Sdim ldmia r13! {r6, lr} 2626214082Sdim bx lr 2627214082Sdim __func_addr: 2628214082Sdim .word func */ 2629214082Sdim 2630214082Sdim#define THUMB2ARM_GLUE_SIZE 8 2631214082Sdimstatic const insn16 t2a1_bx_pc_insn = 0x4778; 2632214082Sdimstatic const insn16 t2a2_noop_insn = 0x46c0; 2633214082Sdimstatic const insn32 t2a3_b_insn = 0xea000000; 2634214082Sdim 2635214634Sdim#define VFP11_ERRATUM_VENEER_SIZE 8 2636214634Sdim 2637214082Sdim#ifndef ELFARM_NABI_C_INCLUDED 2638214082Sdimbfd_boolean 2639214082Sdimbfd_elf32_arm_allocate_interworking_sections (struct bfd_link_info * info) 2640214082Sdim{ 2641214082Sdim asection * s; 2642214082Sdim bfd_byte * foo; 2643214082Sdim struct elf32_arm_link_hash_table * globals; 2644214082Sdim 2645214082Sdim globals = elf32_arm_hash_table (info); 2646214082Sdim 2647214082Sdim BFD_ASSERT (globals != NULL); 2648214082Sdim 2649214082Sdim if (globals->arm_glue_size != 0) 2650214082Sdim { 2651214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 2652214082Sdim 2653214082Sdim s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 2654214082Sdim ARM2THUMB_GLUE_SECTION_NAME); 2655214082Sdim 2656214082Sdim BFD_ASSERT (s != NULL); 2657214082Sdim 2658214082Sdim foo = bfd_alloc (globals->bfd_of_glue_owner, globals->arm_glue_size); 2659214082Sdim 2660214634Sdim BFD_ASSERT (s->size == globals->arm_glue_size); 2661214082Sdim s->contents = foo; 2662214082Sdim } 2663214082Sdim 2664214082Sdim if (globals->thumb_glue_size != 0) 2665214082Sdim { 2666214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 2667214082Sdim 2668214082Sdim s = bfd_get_section_by_name 2669214082Sdim (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME); 2670214082Sdim 2671214082Sdim BFD_ASSERT (s != NULL); 2672214082Sdim 2673214082Sdim foo = bfd_alloc (globals->bfd_of_glue_owner, globals->thumb_glue_size); 2674214082Sdim 2675214634Sdim BFD_ASSERT (s->size == globals->thumb_glue_size); 2676214082Sdim s->contents = foo; 2677214082Sdim } 2678214634Sdim 2679214634Sdim if (globals->vfp11_erratum_glue_size != 0) 2680214634Sdim { 2681214634Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 2682214634Sdim 2683214634Sdim s = bfd_get_section_by_name 2684214634Sdim (globals->bfd_of_glue_owner, VFP11_ERRATUM_VENEER_SECTION_NAME); 2685214634Sdim 2686214634Sdim BFD_ASSERT (s != NULL); 2687214634Sdim 2688214634Sdim foo = bfd_alloc (globals->bfd_of_glue_owner, 2689214634Sdim globals->vfp11_erratum_glue_size); 2690214634Sdim 2691214634Sdim BFD_ASSERT (s->size == globals->vfp11_erratum_glue_size); 2692214634Sdim s->contents = foo; 2693214634Sdim } 2694214082Sdim 2695214082Sdim return TRUE; 2696214082Sdim} 2697214082Sdim 2698214634Sdim/* Allocate space and symbols for calling a Thumb function from Arm mode. 2699214634Sdim returns the symbol identifying teh stub. */ 2700214634Sdimstatic struct elf_link_hash_entry * 2701214082Sdimrecord_arm_to_thumb_glue (struct bfd_link_info * link_info, 2702214082Sdim struct elf_link_hash_entry * h) 2703214082Sdim{ 2704214082Sdim const char * name = h->root.root.string; 2705214082Sdim asection * s; 2706214082Sdim char * tmp_name; 2707214082Sdim struct elf_link_hash_entry * myh; 2708214082Sdim struct bfd_link_hash_entry * bh; 2709214082Sdim struct elf32_arm_link_hash_table * globals; 2710214082Sdim bfd_vma val; 2711214634Sdim bfd_size_type size; 2712214082Sdim 2713214082Sdim globals = elf32_arm_hash_table (link_info); 2714214082Sdim 2715214082Sdim BFD_ASSERT (globals != NULL); 2716214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 2717214082Sdim 2718214082Sdim s = bfd_get_section_by_name 2719214082Sdim (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME); 2720214082Sdim 2721214082Sdim BFD_ASSERT (s != NULL); 2722214082Sdim 2723214082Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1); 2724214082Sdim 2725214082Sdim BFD_ASSERT (tmp_name); 2726214082Sdim 2727214082Sdim sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name); 2728214082Sdim 2729214082Sdim myh = elf_link_hash_lookup 2730214082Sdim (&(globals)->root, tmp_name, FALSE, FALSE, TRUE); 2731214082Sdim 2732214082Sdim if (myh != NULL) 2733214082Sdim { 2734214082Sdim /* We've already seen this guy. */ 2735214082Sdim free (tmp_name); 2736214634Sdim return myh; 2737214082Sdim } 2738214082Sdim 2739214082Sdim /* The only trick here is using hash_table->arm_glue_size as the value. 2740214082Sdim Even though the section isn't allocated yet, this is where we will be 2741214082Sdim putting it. */ 2742214082Sdim bh = NULL; 2743214082Sdim val = globals->arm_glue_size + 1; 2744214082Sdim _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner, 2745214082Sdim tmp_name, BSF_GLOBAL, s, val, 2746214082Sdim NULL, TRUE, FALSE, &bh); 2747214082Sdim 2748214082Sdim myh = (struct elf_link_hash_entry *) bh; 2749214082Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC); 2750214082Sdim myh->forced_local = 1; 2751214082Sdim 2752214082Sdim free (tmp_name); 2753214082Sdim 2754214634Sdim if (link_info->shared || globals->root.is_relocatable_executable 2755214634Sdim || globals->pic_veneer) 2756214634Sdim size = ARM2THUMB_PIC_GLUE_SIZE; 2757214634Sdim else if (globals->use_blx) 2758214634Sdim size = ARM2THUMB_V5_STATIC_GLUE_SIZE; 2759214082Sdim else 2760214634Sdim size = ARM2THUMB_STATIC_GLUE_SIZE; 2761214082Sdim 2762214634Sdim s->size += size; 2763214634Sdim globals->arm_glue_size += size; 2764214634Sdim 2765214634Sdim return myh; 2766214082Sdim} 2767214082Sdim 2768214082Sdimstatic void 2769214082Sdimrecord_thumb_to_arm_glue (struct bfd_link_info *link_info, 2770214082Sdim struct elf_link_hash_entry *h) 2771214082Sdim{ 2772214082Sdim const char *name = h->root.root.string; 2773214082Sdim asection *s; 2774214082Sdim char *tmp_name; 2775214082Sdim struct elf_link_hash_entry *myh; 2776214082Sdim struct bfd_link_hash_entry *bh; 2777214082Sdim struct elf32_arm_link_hash_table *hash_table; 2778214082Sdim bfd_vma val; 2779214082Sdim 2780214082Sdim hash_table = elf32_arm_hash_table (link_info); 2781214082Sdim 2782214082Sdim BFD_ASSERT (hash_table != NULL); 2783214082Sdim BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL); 2784214082Sdim 2785214082Sdim s = bfd_get_section_by_name 2786214082Sdim (hash_table->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME); 2787214082Sdim 2788214082Sdim BFD_ASSERT (s != NULL); 2789214082Sdim 2790214082Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen (name) 2791214082Sdim + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1); 2792214082Sdim 2793214082Sdim BFD_ASSERT (tmp_name); 2794214082Sdim 2795214082Sdim sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name); 2796214082Sdim 2797214082Sdim myh = elf_link_hash_lookup 2798214082Sdim (&(hash_table)->root, tmp_name, FALSE, FALSE, TRUE); 2799214082Sdim 2800214082Sdim if (myh != NULL) 2801214082Sdim { 2802214082Sdim /* We've already seen this guy. */ 2803214082Sdim free (tmp_name); 2804214082Sdim return; 2805214082Sdim } 2806214082Sdim 2807214082Sdim bh = NULL; 2808214082Sdim val = hash_table->thumb_glue_size + 1; 2809214082Sdim _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, 2810214082Sdim tmp_name, BSF_GLOBAL, s, val, 2811214082Sdim NULL, TRUE, FALSE, &bh); 2812214082Sdim 2813214082Sdim /* If we mark it 'Thumb', the disassembler will do a better job. */ 2814214082Sdim myh = (struct elf_link_hash_entry *) bh; 2815214082Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC); 2816214082Sdim myh->forced_local = 1; 2817214082Sdim 2818214082Sdim free (tmp_name); 2819214082Sdim 2820214082Sdim#define CHANGE_TO_ARM "__%s_change_to_arm" 2821214082Sdim#define BACK_FROM_ARM "__%s_back_from_arm" 2822214082Sdim 2823214082Sdim /* Allocate another symbol to mark where we switch to Arm mode. */ 2824214082Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen (name) 2825214082Sdim + strlen (CHANGE_TO_ARM) + 1); 2826214082Sdim 2827214082Sdim BFD_ASSERT (tmp_name); 2828214082Sdim 2829214082Sdim sprintf (tmp_name, CHANGE_TO_ARM, name); 2830214082Sdim 2831214082Sdim bh = NULL; 2832214082Sdim val = hash_table->thumb_glue_size + 4, 2833214082Sdim _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, 2834214082Sdim tmp_name, BSF_LOCAL, s, val, 2835214082Sdim NULL, TRUE, FALSE, &bh); 2836214082Sdim 2837214082Sdim free (tmp_name); 2838214082Sdim 2839214634Sdim s->size += THUMB2ARM_GLUE_SIZE; 2840214082Sdim hash_table->thumb_glue_size += THUMB2ARM_GLUE_SIZE; 2841214082Sdim 2842214082Sdim return; 2843214082Sdim} 2844214082Sdim 2845214634Sdim 2846214634Sdim/* Add an entry to the code/data map for section SEC. */ 2847214634Sdim 2848214634Sdimstatic void 2849214634Sdimelf32_arm_section_map_add (asection *sec, char type, bfd_vma vma) 2850214634Sdim{ 2851214634Sdim struct _arm_elf_section_data *sec_data = elf32_arm_section_data (sec); 2852214634Sdim unsigned int newidx; 2853214634Sdim 2854214634Sdim if (sec_data->map == NULL) 2855214634Sdim { 2856214634Sdim sec_data->map = bfd_malloc (sizeof (elf32_arm_section_map)); 2857214634Sdim sec_data->mapcount = 0; 2858214634Sdim sec_data->mapsize = 1; 2859214634Sdim } 2860214634Sdim 2861214634Sdim newidx = sec_data->mapcount++; 2862214634Sdim 2863214634Sdim if (sec_data->mapcount > sec_data->mapsize) 2864214634Sdim { 2865214634Sdim sec_data->mapsize *= 2; 2866214634Sdim sec_data->map = bfd_realloc (sec_data->map, sec_data->mapsize 2867214634Sdim * sizeof (elf32_arm_section_map)); 2868214634Sdim } 2869214634Sdim 2870214634Sdim sec_data->map[newidx].vma = vma; 2871214634Sdim sec_data->map[newidx].type = type; 2872214634Sdim} 2873214634Sdim 2874214634Sdim 2875214634Sdim/* Record information about a VFP11 denorm-erratum veneer. Only ARM-mode 2876214634Sdim veneers are handled for now. */ 2877214634Sdim 2878214634Sdimstatic bfd_vma 2879214634Sdimrecord_vfp11_erratum_veneer (struct bfd_link_info *link_info, 2880214634Sdim elf32_vfp11_erratum_list *branch, 2881214634Sdim bfd *branch_bfd, 2882214634Sdim asection *branch_sec, 2883214634Sdim unsigned int offset) 2884214634Sdim{ 2885214634Sdim asection *s; 2886214634Sdim struct elf32_arm_link_hash_table *hash_table; 2887214634Sdim char *tmp_name; 2888214634Sdim struct elf_link_hash_entry *myh; 2889214634Sdim struct bfd_link_hash_entry *bh; 2890214634Sdim bfd_vma val; 2891214634Sdim struct _arm_elf_section_data *sec_data; 2892214634Sdim int errcount; 2893214634Sdim elf32_vfp11_erratum_list *newerr; 2894214634Sdim 2895214634Sdim hash_table = elf32_arm_hash_table (link_info); 2896214634Sdim 2897214634Sdim BFD_ASSERT (hash_table != NULL); 2898214634Sdim BFD_ASSERT (hash_table->bfd_of_glue_owner != NULL); 2899214634Sdim 2900214634Sdim s = bfd_get_section_by_name 2901214634Sdim (hash_table->bfd_of_glue_owner, VFP11_ERRATUM_VENEER_SECTION_NAME); 2902214634Sdim 2903214634Sdim sec_data = elf32_arm_section_data (s); 2904214634Sdim 2905214634Sdim BFD_ASSERT (s != NULL); 2906214634Sdim 2907214634Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen 2908214634Sdim (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10); 2909214634Sdim 2910214634Sdim BFD_ASSERT (tmp_name); 2911214634Sdim 2912214634Sdim sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME, 2913214634Sdim hash_table->num_vfp11_fixes); 2914214634Sdim 2915214634Sdim myh = elf_link_hash_lookup 2916214634Sdim (&(hash_table)->root, tmp_name, FALSE, FALSE, FALSE); 2917214634Sdim 2918214634Sdim BFD_ASSERT (myh == NULL); 2919214634Sdim 2920214634Sdim bh = NULL; 2921214634Sdim val = hash_table->vfp11_erratum_glue_size; 2922214634Sdim _bfd_generic_link_add_one_symbol (link_info, hash_table->bfd_of_glue_owner, 2923214634Sdim tmp_name, BSF_FUNCTION | BSF_LOCAL, s, val, 2924214634Sdim NULL, TRUE, FALSE, &bh); 2925214634Sdim 2926214634Sdim myh = (struct elf_link_hash_entry *) bh; 2927214634Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC); 2928214634Sdim myh->forced_local = 1; 2929214634Sdim 2930214634Sdim /* Link veneer back to calling location. */ 2931214634Sdim errcount = ++(sec_data->erratumcount); 2932214634Sdim newerr = bfd_zmalloc (sizeof (elf32_vfp11_erratum_list)); 2933214634Sdim 2934214634Sdim newerr->type = VFP11_ERRATUM_ARM_VENEER; 2935214634Sdim newerr->vma = -1; 2936214634Sdim newerr->u.v.branch = branch; 2937214634Sdim newerr->u.v.id = hash_table->num_vfp11_fixes; 2938214634Sdim branch->u.b.veneer = newerr; 2939214634Sdim 2940214634Sdim newerr->next = sec_data->erratumlist; 2941214634Sdim sec_data->erratumlist = newerr; 2942214634Sdim 2943214634Sdim /* A symbol for the return from the veneer. */ 2944214634Sdim sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME "_r", 2945214634Sdim hash_table->num_vfp11_fixes); 2946214634Sdim 2947214634Sdim myh = elf_link_hash_lookup 2948214634Sdim (&(hash_table)->root, tmp_name, FALSE, FALSE, FALSE); 2949214634Sdim 2950214634Sdim if (myh != NULL) 2951214634Sdim abort (); 2952214634Sdim 2953214634Sdim bh = NULL; 2954214634Sdim val = offset + 4; 2955214634Sdim _bfd_generic_link_add_one_symbol (link_info, branch_bfd, tmp_name, BSF_LOCAL, 2956214634Sdim branch_sec, val, NULL, TRUE, FALSE, &bh); 2957214634Sdim 2958214634Sdim myh = (struct elf_link_hash_entry *) bh; 2959214634Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC); 2960214634Sdim myh->forced_local = 1; 2961214634Sdim 2962214634Sdim free (tmp_name); 2963214634Sdim 2964214634Sdim /* Generate a mapping symbol for the veneer section, and explicitly add an 2965214634Sdim entry for that symbol to the code/data map for the section. */ 2966214634Sdim if (hash_table->vfp11_erratum_glue_size == 0) 2967214634Sdim { 2968214634Sdim bh = NULL; 2969214634Sdim /* FIXME: Creates an ARM symbol. Thumb mode will need attention if it 2970214634Sdim ever requires this erratum fix. */ 2971214634Sdim _bfd_generic_link_add_one_symbol (link_info, 2972214634Sdim hash_table->bfd_of_glue_owner, "$a", 2973214634Sdim BSF_LOCAL, s, 0, NULL, 2974214634Sdim TRUE, FALSE, &bh); 2975214634Sdim 2976214634Sdim myh = (struct elf_link_hash_entry *) bh; 2977214634Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); 2978214634Sdim myh->forced_local = 1; 2979214634Sdim 2980214634Sdim /* The elf32_arm_init_maps function only cares about symbols from input 2981214634Sdim BFDs. We must make a note of this generated mapping symbol 2982214634Sdim ourselves so that code byteswapping works properly in 2983214634Sdim elf32_arm_write_section. */ 2984214634Sdim elf32_arm_section_map_add (s, 'a', 0); 2985214634Sdim } 2986214634Sdim 2987214634Sdim s->size += VFP11_ERRATUM_VENEER_SIZE; 2988214634Sdim hash_table->vfp11_erratum_glue_size += VFP11_ERRATUM_VENEER_SIZE; 2989214634Sdim hash_table->num_vfp11_fixes++; 2990214634Sdim 2991214634Sdim /* The offset of the veneer. */ 2992214634Sdim return val; 2993214634Sdim} 2994214634Sdim 2995214082Sdim/* Add the glue sections to ABFD. This function is called from the 2996214082Sdim linker scripts in ld/emultempl/{armelf}.em. */ 2997214082Sdim 2998214082Sdimbfd_boolean 2999214082Sdimbfd_elf32_arm_add_glue_sections_to_bfd (bfd *abfd, 3000214082Sdim struct bfd_link_info *info) 3001214082Sdim{ 3002214082Sdim flagword flags; 3003214082Sdim asection *sec; 3004214082Sdim 3005214082Sdim /* If we are only performing a partial 3006214082Sdim link do not bother adding the glue. */ 3007214082Sdim if (info->relocatable) 3008214082Sdim return TRUE; 3009214082Sdim 3010214082Sdim sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME); 3011214082Sdim 3012214082Sdim if (sec == NULL) 3013214082Sdim { 3014214082Sdim /* Note: we do not include the flag SEC_LINKER_CREATED, as this 3015214082Sdim will prevent elf_link_input_bfd() from processing the contents 3016214082Sdim of this section. */ 3017214634Sdim flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 3018214634Sdim | SEC_CODE | SEC_READONLY); 3019214082Sdim 3020214082Sdim sec = bfd_make_section_with_flags (abfd, 3021214082Sdim ARM2THUMB_GLUE_SECTION_NAME, 3022214082Sdim flags); 3023214082Sdim 3024214082Sdim if (sec == NULL 3025214082Sdim || !bfd_set_section_alignment (abfd, sec, 2)) 3026214082Sdim return FALSE; 3027214082Sdim 3028214082Sdim /* Set the gc mark to prevent the section from being removed by garbage 3029214082Sdim collection, despite the fact that no relocs refer to this section. */ 3030214082Sdim sec->gc_mark = 1; 3031214082Sdim } 3032214082Sdim 3033214082Sdim sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME); 3034214082Sdim 3035214082Sdim if (sec == NULL) 3036214082Sdim { 3037214634Sdim flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 3038214634Sdim | SEC_CODE | SEC_READONLY); 3039214082Sdim 3040214082Sdim sec = bfd_make_section_with_flags (abfd, 3041214082Sdim THUMB2ARM_GLUE_SECTION_NAME, 3042214082Sdim flags); 3043214082Sdim 3044214082Sdim if (sec == NULL 3045214082Sdim || !bfd_set_section_alignment (abfd, sec, 2)) 3046214082Sdim return FALSE; 3047214082Sdim 3048214082Sdim sec->gc_mark = 1; 3049214082Sdim } 3050214082Sdim 3051214634Sdim sec = bfd_get_section_by_name (abfd, VFP11_ERRATUM_VENEER_SECTION_NAME); 3052214634Sdim 3053214634Sdim if (sec == NULL) 3054214634Sdim { 3055214634Sdim flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY 3056214634Sdim | SEC_CODE | SEC_READONLY); 3057214634Sdim 3058214634Sdim sec = bfd_make_section_with_flags (abfd, 3059214634Sdim VFP11_ERRATUM_VENEER_SECTION_NAME, 3060214634Sdim flags); 3061214634Sdim 3062214634Sdim if (sec == NULL 3063214634Sdim || !bfd_set_section_alignment (abfd, sec, 2)) 3064214634Sdim return FALSE; 3065214634Sdim 3066214634Sdim sec->gc_mark = 1; 3067214634Sdim } 3068214634Sdim 3069214082Sdim return TRUE; 3070214082Sdim} 3071214082Sdim 3072214082Sdim/* Select a BFD to be used to hold the sections used by the glue code. 3073214082Sdim This function is called from the linker scripts in ld/emultempl/ 3074214082Sdim {armelf/pe}.em */ 3075214082Sdim 3076214082Sdimbfd_boolean 3077214082Sdimbfd_elf32_arm_get_bfd_for_interworking (bfd *abfd, struct bfd_link_info *info) 3078214082Sdim{ 3079214082Sdim struct elf32_arm_link_hash_table *globals; 3080214082Sdim 3081214082Sdim /* If we are only performing a partial link 3082214082Sdim do not bother getting a bfd to hold the glue. */ 3083214082Sdim if (info->relocatable) 3084214082Sdim return TRUE; 3085214082Sdim 3086214082Sdim /* Make sure we don't attach the glue sections to a dynamic object. */ 3087214082Sdim BFD_ASSERT (!(abfd->flags & DYNAMIC)); 3088214082Sdim 3089214082Sdim globals = elf32_arm_hash_table (info); 3090214082Sdim 3091214082Sdim BFD_ASSERT (globals != NULL); 3092214082Sdim 3093214082Sdim if (globals->bfd_of_glue_owner != NULL) 3094214082Sdim return TRUE; 3095214082Sdim 3096214082Sdim /* Save the bfd for later use. */ 3097214082Sdim globals->bfd_of_glue_owner = abfd; 3098214082Sdim 3099214082Sdim return TRUE; 3100214082Sdim} 3101214082Sdim 3102214082Sdimstatic void check_use_blx(struct elf32_arm_link_hash_table *globals) 3103214082Sdim{ 3104214634Sdim if (bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, 3105214634Sdim Tag_CPU_arch) > 2) 3106214082Sdim globals->use_blx = 1; 3107214082Sdim} 3108214082Sdim 3109214082Sdimbfd_boolean 3110214082Sdimbfd_elf32_arm_process_before_allocation (bfd *abfd, 3111214634Sdim struct bfd_link_info *link_info) 3112214082Sdim{ 3113214082Sdim Elf_Internal_Shdr *symtab_hdr; 3114214082Sdim Elf_Internal_Rela *internal_relocs = NULL; 3115214082Sdim Elf_Internal_Rela *irel, *irelend; 3116214082Sdim bfd_byte *contents = NULL; 3117214082Sdim 3118214082Sdim asection *sec; 3119214082Sdim struct elf32_arm_link_hash_table *globals; 3120214082Sdim 3121214082Sdim /* If we are only performing a partial link do not bother 3122214082Sdim to construct any glue. */ 3123214082Sdim if (link_info->relocatable) 3124214082Sdim return TRUE; 3125214082Sdim 3126214082Sdim /* Here we have a bfd that is to be included on the link. We have a hook 3127214082Sdim to do reloc rummaging, before section sizes are nailed down. */ 3128214082Sdim globals = elf32_arm_hash_table (link_info); 3129214082Sdim check_use_blx (globals); 3130214082Sdim 3131214082Sdim BFD_ASSERT (globals != NULL); 3132214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 3133214082Sdim 3134214634Sdim if (globals->byteswap_code && !bfd_big_endian (abfd)) 3135214082Sdim { 3136214082Sdim _bfd_error_handler (_("%B: BE8 images only valid in big-endian mode."), 3137214082Sdim abfd); 3138214082Sdim return FALSE; 3139214082Sdim } 3140214082Sdim 3141214082Sdim /* Rummage around all the relocs and map the glue vectors. */ 3142214082Sdim sec = abfd->sections; 3143214082Sdim 3144214082Sdim if (sec == NULL) 3145214082Sdim return TRUE; 3146214082Sdim 3147214082Sdim for (; sec != NULL; sec = sec->next) 3148214082Sdim { 3149214082Sdim if (sec->reloc_count == 0) 3150214082Sdim continue; 3151214082Sdim 3152214634Sdim if ((sec->flags & SEC_EXCLUDE) != 0) 3153214634Sdim continue; 3154214634Sdim 3155214082Sdim symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 3156214082Sdim 3157214082Sdim /* Load the relocs. */ 3158214082Sdim internal_relocs 3159214082Sdim = _bfd_elf_link_read_relocs (abfd, sec, (void *) NULL, 3160214082Sdim (Elf_Internal_Rela *) NULL, FALSE); 3161214082Sdim 3162214082Sdim if (internal_relocs == NULL) 3163214082Sdim goto error_return; 3164214082Sdim 3165214082Sdim irelend = internal_relocs + sec->reloc_count; 3166214082Sdim for (irel = internal_relocs; irel < irelend; irel++) 3167214082Sdim { 3168214082Sdim long r_type; 3169214082Sdim unsigned long r_index; 3170214082Sdim 3171214082Sdim struct elf_link_hash_entry *h; 3172214082Sdim 3173214082Sdim r_type = ELF32_R_TYPE (irel->r_info); 3174214082Sdim r_index = ELF32_R_SYM (irel->r_info); 3175214082Sdim 3176214082Sdim /* These are the only relocation types we care about. */ 3177214082Sdim if ( r_type != R_ARM_PC24 3178214082Sdim && r_type != R_ARM_PLT32 3179214082Sdim && r_type != R_ARM_CALL 3180214082Sdim && r_type != R_ARM_JUMP24 3181214082Sdim && r_type != R_ARM_THM_CALL) 3182214082Sdim continue; 3183214082Sdim 3184214082Sdim /* Get the section contents if we haven't done so already. */ 3185214082Sdim if (contents == NULL) 3186214082Sdim { 3187214082Sdim /* Get cached copy if it exists. */ 3188214082Sdim if (elf_section_data (sec)->this_hdr.contents != NULL) 3189214082Sdim contents = elf_section_data (sec)->this_hdr.contents; 3190214082Sdim else 3191214082Sdim { 3192214082Sdim /* Go get them off disk. */ 3193214082Sdim if (! bfd_malloc_and_get_section (abfd, sec, &contents)) 3194214082Sdim goto error_return; 3195214082Sdim } 3196214082Sdim } 3197214082Sdim 3198214082Sdim /* If the relocation is not against a symbol it cannot concern us. */ 3199214082Sdim h = NULL; 3200214082Sdim 3201214082Sdim /* We don't care about local symbols. */ 3202214082Sdim if (r_index < symtab_hdr->sh_info) 3203214082Sdim continue; 3204214082Sdim 3205214082Sdim /* This is an external symbol. */ 3206214082Sdim r_index -= symtab_hdr->sh_info; 3207214082Sdim h = (struct elf_link_hash_entry *) 3208214082Sdim elf_sym_hashes (abfd)[r_index]; 3209214082Sdim 3210214082Sdim /* If the relocation is against a static symbol it must be within 3211214082Sdim the current section and so cannot be a cross ARM/Thumb relocation. */ 3212214082Sdim if (h == NULL) 3213214082Sdim continue; 3214214082Sdim 3215214082Sdim /* If the call will go through a PLT entry then we do not need 3216214082Sdim glue. */ 3217214082Sdim if (globals->splt != NULL && h->plt.offset != (bfd_vma) -1) 3218214082Sdim continue; 3219214082Sdim 3220214082Sdim switch (r_type) 3221214082Sdim { 3222214082Sdim case R_ARM_PC24: 3223214082Sdim case R_ARM_PLT32: 3224214082Sdim case R_ARM_CALL: 3225214082Sdim case R_ARM_JUMP24: 3226214082Sdim /* This one is a call from arm code. We need to look up 3227214082Sdim the target of the call. If it is a thumb target, we 3228214082Sdim insert glue. */ 3229214082Sdim if (ELF_ST_TYPE(h->type) == STT_ARM_TFUNC 3230214082Sdim && !(r_type == R_ARM_CALL && globals->use_blx)) 3231214082Sdim record_arm_to_thumb_glue (link_info, h); 3232214082Sdim break; 3233214082Sdim 3234214082Sdim case R_ARM_THM_CALL: 3235214082Sdim /* This one is a call from thumb code. We look 3236214082Sdim up the target of the call. If it is not a thumb 3237214082Sdim target, we insert glue. */ 3238214634Sdim if (ELF_ST_TYPE (h->type) != STT_ARM_TFUNC && !globals->use_blx 3239214634Sdim && h->root.type != bfd_link_hash_undefweak) 3240214082Sdim record_thumb_to_arm_glue (link_info, h); 3241214082Sdim break; 3242214082Sdim 3243214082Sdim default: 3244214082Sdim abort (); 3245214082Sdim } 3246214082Sdim } 3247214082Sdim 3248214082Sdim if (contents != NULL 3249214082Sdim && elf_section_data (sec)->this_hdr.contents != contents) 3250214082Sdim free (contents); 3251214082Sdim contents = NULL; 3252214082Sdim 3253214082Sdim if (internal_relocs != NULL 3254214082Sdim && elf_section_data (sec)->relocs != internal_relocs) 3255214082Sdim free (internal_relocs); 3256214082Sdim internal_relocs = NULL; 3257214082Sdim } 3258214082Sdim 3259214082Sdim return TRUE; 3260214082Sdim 3261214082Sdimerror_return: 3262214082Sdim if (contents != NULL 3263214082Sdim && elf_section_data (sec)->this_hdr.contents != contents) 3264214082Sdim free (contents); 3265214082Sdim if (internal_relocs != NULL 3266214082Sdim && elf_section_data (sec)->relocs != internal_relocs) 3267214082Sdim free (internal_relocs); 3268214082Sdim 3269214082Sdim return FALSE; 3270214082Sdim} 3271214082Sdim#endif 3272214082Sdim 3273214082Sdim 3274214634Sdim/* Initialise maps of ARM/Thumb/data for input BFDs. */ 3275214634Sdim 3276214634Sdimvoid 3277214634Sdimbfd_elf32_arm_init_maps (bfd *abfd) 3278214634Sdim{ 3279214634Sdim Elf_Internal_Sym *isymbuf; 3280214634Sdim Elf_Internal_Shdr *hdr; 3281214634Sdim unsigned int i, localsyms; 3282214634Sdim 3283214751Sdim if (bfd_get_flavour (abfd) != bfd_target_elf_flavour || elf_tdata (abfd) == NULL) 3284214751Sdim return; 3285214751Sdim 3286214634Sdim if ((abfd->flags & DYNAMIC) != 0) 3287214634Sdim return; 3288214634Sdim 3289214634Sdim hdr = &elf_tdata (abfd)->symtab_hdr; 3290214634Sdim localsyms = hdr->sh_info; 3291214634Sdim 3292214634Sdim /* Obtain a buffer full of symbols for this BFD. The hdr->sh_info field 3293214634Sdim should contain the number of local symbols, which should come before any 3294214634Sdim global symbols. Mapping symbols are always local. */ 3295214634Sdim isymbuf = bfd_elf_get_elf_syms (abfd, hdr, localsyms, 0, NULL, NULL, 3296214634Sdim NULL); 3297214634Sdim 3298214634Sdim /* No internal symbols read? Skip this BFD. */ 3299214634Sdim if (isymbuf == NULL) 3300214634Sdim return; 3301214634Sdim 3302214634Sdim for (i = 0; i < localsyms; i++) 3303214634Sdim { 3304214634Sdim Elf_Internal_Sym *isym = &isymbuf[i]; 3305214634Sdim asection *sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 3306214634Sdim const char *name; 3307214634Sdim 3308214634Sdim if (sec != NULL 3309214634Sdim && ELF_ST_BIND (isym->st_info) == STB_LOCAL) 3310214634Sdim { 3311214634Sdim name = bfd_elf_string_from_elf_section (abfd, 3312214634Sdim hdr->sh_link, isym->st_name); 3313214634Sdim 3314214634Sdim if (bfd_is_arm_special_symbol_name (name, 3315214634Sdim BFD_ARM_SPECIAL_SYM_TYPE_MAP)) 3316214634Sdim elf32_arm_section_map_add (sec, name[1], isym->st_value); 3317214634Sdim } 3318214634Sdim } 3319214634Sdim} 3320214634Sdim 3321214634Sdim 3322214634Sdimvoid 3323214634Sdimbfd_elf32_arm_set_vfp11_fix (bfd *obfd, struct bfd_link_info *link_info) 3324214634Sdim{ 3325214634Sdim struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info); 3326214634Sdim obj_attribute *out_attr = elf_known_obj_attributes_proc (obfd); 3327214634Sdim 3328214634Sdim /* We assume that ARMv7+ does not need the VFP11 denorm erratum fix. */ 3329214634Sdim if (out_attr[Tag_CPU_arch].i >= TAG_CPU_ARCH_V7) 3330214634Sdim { 3331214634Sdim switch (globals->vfp11_fix) 3332214634Sdim { 3333214634Sdim case BFD_ARM_VFP11_FIX_DEFAULT: 3334214634Sdim case BFD_ARM_VFP11_FIX_NONE: 3335214634Sdim globals->vfp11_fix = BFD_ARM_VFP11_FIX_NONE; 3336214634Sdim break; 3337214634Sdim 3338214634Sdim default: 3339214634Sdim /* Give a warning, but do as the user requests anyway. */ 3340214634Sdim (*_bfd_error_handler) (_("%B: warning: selected VFP11 erratum " 3341214634Sdim "workaround is not necessary for target architecture"), obfd); 3342214634Sdim } 3343214634Sdim } 3344214634Sdim else if (globals->vfp11_fix == BFD_ARM_VFP11_FIX_DEFAULT) 3345214634Sdim /* For earlier architectures, we might need the workaround, but do not 3346214634Sdim enable it by default. If users is running with broken hardware, they 3347214634Sdim must enable the erratum fix explicitly. */ 3348214634Sdim globals->vfp11_fix = BFD_ARM_VFP11_FIX_NONE; 3349214634Sdim} 3350214634Sdim 3351214634Sdim 3352214634Sdimenum bfd_arm_vfp11_pipe { 3353214634Sdim VFP11_FMAC, 3354214634Sdim VFP11_LS, 3355214634Sdim VFP11_DS, 3356214634Sdim VFP11_BAD 3357214634Sdim}; 3358214634Sdim 3359214634Sdim/* Return a VFP register number. This is encoded as RX:X for single-precision 3360214634Sdim registers, or X:RX for double-precision registers, where RX is the group of 3361214634Sdim four bits in the instruction encoding and X is the single extension bit. 3362214634Sdim RX and X fields are specified using their lowest (starting) bit. The return 3363214634Sdim value is: 3364214634Sdim 3365214634Sdim 0...31: single-precision registers s0...s31 3366214634Sdim 32...63: double-precision registers d0...d31. 3367214634Sdim 3368214634Sdim Although X should be zero for VFP11 (encoding d0...d15 only), we might 3369214634Sdim encounter VFP3 instructions, so we allow the full range for DP registers. */ 3370214634Sdim 3371214634Sdimstatic unsigned int 3372214634Sdimbfd_arm_vfp11_regno (unsigned int insn, bfd_boolean is_double, unsigned int rx, 3373214634Sdim unsigned int x) 3374214634Sdim{ 3375214634Sdim if (is_double) 3376214634Sdim return (((insn >> rx) & 0xf) | (((insn >> x) & 1) << 4)) + 32; 3377214634Sdim else 3378214634Sdim return (((insn >> rx) & 0xf) << 1) | ((insn >> x) & 1); 3379214634Sdim} 3380214634Sdim 3381214634Sdim/* Set bits in *WMASK according to a register number REG as encoded by 3382214634Sdim bfd_arm_vfp11_regno(). Ignore d16-d31. */ 3383214634Sdim 3384214634Sdimstatic void 3385214634Sdimbfd_arm_vfp11_write_mask (unsigned int *wmask, unsigned int reg) 3386214634Sdim{ 3387214634Sdim if (reg < 32) 3388214634Sdim *wmask |= 1 << reg; 3389214634Sdim else if (reg < 48) 3390214634Sdim *wmask |= 3 << ((reg - 32) * 2); 3391214634Sdim} 3392214634Sdim 3393214634Sdim/* Return TRUE if WMASK overwrites anything in REGS. */ 3394214634Sdim 3395214634Sdimstatic bfd_boolean 3396214634Sdimbfd_arm_vfp11_antidependency (unsigned int wmask, int *regs, int numregs) 3397214634Sdim{ 3398214634Sdim int i; 3399214634Sdim 3400214634Sdim for (i = 0; i < numregs; i++) 3401214634Sdim { 3402214634Sdim unsigned int reg = regs[i]; 3403214634Sdim 3404214634Sdim if (reg < 32 && (wmask & (1 << reg)) != 0) 3405214634Sdim return TRUE; 3406214634Sdim 3407214634Sdim reg -= 32; 3408214634Sdim 3409214634Sdim if (reg >= 16) 3410214634Sdim continue; 3411214634Sdim 3412214634Sdim if ((wmask & (3 << (reg * 2))) != 0) 3413214634Sdim return TRUE; 3414214634Sdim } 3415214634Sdim 3416214634Sdim return FALSE; 3417214634Sdim} 3418214634Sdim 3419214634Sdim/* In this function, we're interested in two things: finding input registers 3420214634Sdim for VFP data-processing instructions, and finding the set of registers which 3421214634Sdim arbitrary VFP instructions may write to. We use a 32-bit unsigned int to 3422214634Sdim hold the written set, so FLDM etc. are easy to deal with (we're only 3423214634Sdim interested in 32 SP registers or 16 dp registers, due to the VFP version 3424214634Sdim implemented by the chip in question). DP registers are marked by setting 3425214634Sdim both SP registers in the write mask). */ 3426214634Sdim 3427214634Sdimstatic enum bfd_arm_vfp11_pipe 3428214634Sdimbfd_arm_vfp11_insn_decode (unsigned int insn, unsigned int *destmask, int *regs, 3429214634Sdim int *numregs) 3430214634Sdim{ 3431214634Sdim enum bfd_arm_vfp11_pipe pipe = VFP11_BAD; 3432214634Sdim bfd_boolean is_double = ((insn & 0xf00) == 0xb00) ? 1 : 0; 3433214634Sdim 3434214634Sdim if ((insn & 0x0f000e10) == 0x0e000a00) /* A data-processing insn. */ 3435214634Sdim { 3436214634Sdim unsigned int pqrs; 3437214634Sdim unsigned int fd = bfd_arm_vfp11_regno (insn, is_double, 12, 22); 3438214634Sdim unsigned int fm = bfd_arm_vfp11_regno (insn, is_double, 0, 5); 3439214634Sdim 3440214634Sdim pqrs = ((insn & 0x00800000) >> 20) 3441214634Sdim | ((insn & 0x00300000) >> 19) 3442214634Sdim | ((insn & 0x00000040) >> 6); 3443214634Sdim 3444214634Sdim switch (pqrs) 3445214634Sdim { 3446214634Sdim case 0: /* fmac[sd]. */ 3447214634Sdim case 1: /* fnmac[sd]. */ 3448214634Sdim case 2: /* fmsc[sd]. */ 3449214634Sdim case 3: /* fnmsc[sd]. */ 3450214634Sdim pipe = VFP11_FMAC; 3451214634Sdim bfd_arm_vfp11_write_mask (destmask, fd); 3452214634Sdim regs[0] = fd; 3453214634Sdim regs[1] = bfd_arm_vfp11_regno (insn, is_double, 16, 7); /* Fn. */ 3454214634Sdim regs[2] = fm; 3455214634Sdim *numregs = 3; 3456214634Sdim break; 3457214634Sdim 3458214634Sdim case 4: /* fmul[sd]. */ 3459214634Sdim case 5: /* fnmul[sd]. */ 3460214634Sdim case 6: /* fadd[sd]. */ 3461214634Sdim case 7: /* fsub[sd]. */ 3462214634Sdim pipe = VFP11_FMAC; 3463214634Sdim goto vfp_binop; 3464214634Sdim 3465214634Sdim case 8: /* fdiv[sd]. */ 3466214634Sdim pipe = VFP11_DS; 3467214634Sdim vfp_binop: 3468214634Sdim bfd_arm_vfp11_write_mask (destmask, fd); 3469214634Sdim regs[0] = bfd_arm_vfp11_regno (insn, is_double, 16, 7); /* Fn. */ 3470214634Sdim regs[1] = fm; 3471214634Sdim *numregs = 2; 3472214634Sdim break; 3473214634Sdim 3474214634Sdim case 15: /* extended opcode. */ 3475214634Sdim { 3476214634Sdim unsigned int extn = ((insn >> 15) & 0x1e) 3477214634Sdim | ((insn >> 7) & 1); 3478214634Sdim 3479214634Sdim switch (extn) 3480214634Sdim { 3481214634Sdim case 0: /* fcpy[sd]. */ 3482214634Sdim case 1: /* fabs[sd]. */ 3483214634Sdim case 2: /* fneg[sd]. */ 3484214634Sdim case 8: /* fcmp[sd]. */ 3485214634Sdim case 9: /* fcmpe[sd]. */ 3486214634Sdim case 10: /* fcmpz[sd]. */ 3487214634Sdim case 11: /* fcmpez[sd]. */ 3488214634Sdim case 16: /* fuito[sd]. */ 3489214634Sdim case 17: /* fsito[sd]. */ 3490214634Sdim case 24: /* ftoui[sd]. */ 3491214634Sdim case 25: /* ftouiz[sd]. */ 3492214634Sdim case 26: /* ftosi[sd]. */ 3493214634Sdim case 27: /* ftosiz[sd]. */ 3494214634Sdim /* These instructions will not bounce due to underflow. */ 3495214634Sdim *numregs = 0; 3496214634Sdim pipe = VFP11_FMAC; 3497214634Sdim break; 3498214634Sdim 3499214634Sdim case 3: /* fsqrt[sd]. */ 3500214634Sdim /* fsqrt cannot underflow, but it can (perhaps) overwrite 3501214634Sdim registers to cause the erratum in previous instructions. */ 3502214634Sdim bfd_arm_vfp11_write_mask (destmask, fd); 3503214634Sdim pipe = VFP11_DS; 3504214634Sdim break; 3505214634Sdim 3506214634Sdim case 15: /* fcvt{ds,sd}. */ 3507214634Sdim { 3508214634Sdim int rnum = 0; 3509214634Sdim 3510214634Sdim bfd_arm_vfp11_write_mask (destmask, fd); 3511214634Sdim 3512214634Sdim /* Only FCVTSD can underflow. */ 3513214634Sdim if ((insn & 0x100) != 0) 3514214634Sdim regs[rnum++] = fm; 3515214634Sdim 3516214634Sdim *numregs = rnum; 3517214634Sdim 3518214634Sdim pipe = VFP11_FMAC; 3519214634Sdim } 3520214634Sdim break; 3521214634Sdim 3522214634Sdim default: 3523214634Sdim return VFP11_BAD; 3524214634Sdim } 3525214634Sdim } 3526214634Sdim break; 3527214634Sdim 3528214634Sdim default: 3529214634Sdim return VFP11_BAD; 3530214634Sdim } 3531214634Sdim } 3532214634Sdim /* Two-register transfer. */ 3533214634Sdim else if ((insn & 0x0fe00ed0) == 0x0c400a10) 3534214634Sdim { 3535214634Sdim unsigned int fm = bfd_arm_vfp11_regno (insn, is_double, 0, 5); 3536214634Sdim 3537214634Sdim if ((insn & 0x100000) == 0) 3538214634Sdim { 3539214634Sdim if (is_double) 3540214634Sdim bfd_arm_vfp11_write_mask (destmask, fm); 3541214634Sdim else 3542214634Sdim { 3543214634Sdim bfd_arm_vfp11_write_mask (destmask, fm); 3544214634Sdim bfd_arm_vfp11_write_mask (destmask, fm + 1); 3545214634Sdim } 3546214634Sdim } 3547214634Sdim 3548214634Sdim pipe = VFP11_LS; 3549214634Sdim } 3550214634Sdim else if ((insn & 0x0e100e00) == 0x0c100a00) /* A load insn. */ 3551214634Sdim { 3552214634Sdim int fd = bfd_arm_vfp11_regno (insn, is_double, 12, 22); 3553214634Sdim unsigned int puw = ((insn >> 21) & 0x1) | (((insn >> 23) & 3) << 1); 3554214634Sdim 3555214634Sdim switch (puw) 3556214634Sdim { 3557214634Sdim case 0: /* Two-reg transfer. We should catch these above. */ 3558214634Sdim abort (); 3559214634Sdim 3560214634Sdim case 2: /* fldm[sdx]. */ 3561214634Sdim case 3: 3562214634Sdim case 5: 3563214634Sdim { 3564214634Sdim unsigned int i, offset = insn & 0xff; 3565214634Sdim 3566214634Sdim if (is_double) 3567214634Sdim offset >>= 1; 3568214634Sdim 3569214634Sdim for (i = fd; i < fd + offset; i++) 3570214634Sdim bfd_arm_vfp11_write_mask (destmask, i); 3571214634Sdim } 3572214634Sdim break; 3573214634Sdim 3574214634Sdim case 4: /* fld[sd]. */ 3575214634Sdim case 6: 3576214634Sdim bfd_arm_vfp11_write_mask (destmask, fd); 3577214634Sdim break; 3578214634Sdim 3579214634Sdim default: 3580214634Sdim return VFP11_BAD; 3581214634Sdim } 3582214634Sdim 3583214634Sdim pipe = VFP11_LS; 3584214634Sdim } 3585214634Sdim /* Single-register transfer. Note L==0. */ 3586214634Sdim else if ((insn & 0x0f100e10) == 0x0e000a10) 3587214634Sdim { 3588214634Sdim unsigned int opcode = (insn >> 21) & 7; 3589214634Sdim unsigned int fn = bfd_arm_vfp11_regno (insn, is_double, 16, 7); 3590214634Sdim 3591214634Sdim switch (opcode) 3592214634Sdim { 3593214634Sdim case 0: /* fmsr/fmdlr. */ 3594214634Sdim case 1: /* fmdhr. */ 3595214634Sdim /* Mark fmdhr and fmdlr as writing to the whole of the DP 3596214634Sdim destination register. I don't know if this is exactly right, 3597214634Sdim but it is the conservative choice. */ 3598214634Sdim bfd_arm_vfp11_write_mask (destmask, fn); 3599214634Sdim break; 3600214634Sdim 3601214634Sdim case 7: /* fmxr. */ 3602214634Sdim break; 3603214634Sdim } 3604214634Sdim 3605214634Sdim pipe = VFP11_LS; 3606214634Sdim } 3607214634Sdim 3608214634Sdim return pipe; 3609214634Sdim} 3610214634Sdim 3611214634Sdim 3612214634Sdimstatic int elf32_arm_compare_mapping (const void * a, const void * b); 3613214634Sdim 3614214634Sdim 3615214634Sdim/* Look for potentially-troublesome code sequences which might trigger the 3616214634Sdim VFP11 denormal/antidependency erratum. See, e.g., the ARM1136 errata sheet 3617214634Sdim (available from ARM) for details of the erratum. A short version is 3618214634Sdim described in ld.texinfo. */ 3619214634Sdim 3620214634Sdimbfd_boolean 3621214634Sdimbfd_elf32_arm_vfp11_erratum_scan (bfd *abfd, struct bfd_link_info *link_info) 3622214634Sdim{ 3623214634Sdim asection *sec; 3624214634Sdim bfd_byte *contents = NULL; 3625214634Sdim int state = 0; 3626214634Sdim int regs[3], numregs = 0; 3627214634Sdim struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info); 3628214634Sdim int use_vector = (globals->vfp11_fix == BFD_ARM_VFP11_FIX_VECTOR); 3629214634Sdim 3630214634Sdim /* We use a simple FSM to match troublesome VFP11 instruction sequences. 3631214634Sdim The states transition as follows: 3632214634Sdim 3633214634Sdim 0 -> 1 (vector) or 0 -> 2 (scalar) 3634214634Sdim A VFP FMAC-pipeline instruction has been seen. Fill 3635214634Sdim regs[0]..regs[numregs-1] with its input operands. Remember this 3636214634Sdim instruction in 'first_fmac'. 3637214634Sdim 3638214634Sdim 1 -> 2 3639214634Sdim Any instruction, except for a VFP instruction which overwrites 3640214634Sdim regs[*]. 3641214634Sdim 3642214634Sdim 1 -> 3 [ -> 0 ] or 3643214634Sdim 2 -> 3 [ -> 0 ] 3644214634Sdim A VFP instruction has been seen which overwrites any of regs[*]. 3645214634Sdim We must make a veneer! Reset state to 0 before examining next 3646214634Sdim instruction. 3647214634Sdim 3648214634Sdim 2 -> 0 3649214634Sdim If we fail to match anything in state 2, reset to state 0 and reset 3650214634Sdim the instruction pointer to the instruction after 'first_fmac'. 3651214634Sdim 3652214634Sdim If the VFP11 vector mode is in use, there must be at least two unrelated 3653214634Sdim instructions between anti-dependent VFP11 instructions to properly avoid 3654214634Sdim triggering the erratum, hence the use of the extra state 1. 3655214634Sdim */ 3656214634Sdim 3657214634Sdim /* If we are only performing a partial link do not bother 3658214634Sdim to construct any glue. */ 3659214634Sdim if (link_info->relocatable) 3660214634Sdim return TRUE; 3661214634Sdim 3662214634Sdim /* We should have chosen a fix type by the time we get here. */ 3663214634Sdim BFD_ASSERT (globals->vfp11_fix != BFD_ARM_VFP11_FIX_DEFAULT); 3664214634Sdim 3665214634Sdim if (globals->vfp11_fix == BFD_ARM_VFP11_FIX_NONE) 3666214634Sdim return TRUE; 3667214634Sdim 3668214634Sdim /* Skip if this bfd does not correspond to an ELF image. */ 3669214634Sdim if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) 3670214634Sdim return TRUE; 3671214634Sdim 3672214634Sdim for (sec = abfd->sections; sec != NULL; sec = sec->next) 3673214634Sdim { 3674214634Sdim unsigned int i, span, first_fmac = 0, veneer_of_insn = 0; 3675214634Sdim struct _arm_elf_section_data *sec_data; 3676214634Sdim 3677214634Sdim /* If we don't have executable progbits, we're not interested in this 3678214634Sdim section. Also skip if section is to be excluded. */ 3679214634Sdim if (elf_section_type (sec) != SHT_PROGBITS 3680214634Sdim || (elf_section_flags (sec) & SHF_EXECINSTR) == 0 3681214634Sdim || (sec->flags & SEC_EXCLUDE) != 0 3682214634Sdim || strcmp (sec->name, VFP11_ERRATUM_VENEER_SECTION_NAME) == 0) 3683214634Sdim continue; 3684214634Sdim 3685214634Sdim sec_data = elf32_arm_section_data (sec); 3686214634Sdim 3687214634Sdim if (sec_data->mapcount == 0) 3688214634Sdim continue; 3689214634Sdim 3690214634Sdim if (elf_section_data (sec)->this_hdr.contents != NULL) 3691214634Sdim contents = elf_section_data (sec)->this_hdr.contents; 3692214634Sdim else if (! bfd_malloc_and_get_section (abfd, sec, &contents)) 3693214634Sdim goto error_return; 3694214634Sdim 3695214634Sdim qsort (sec_data->map, sec_data->mapcount, sizeof (elf32_arm_section_map), 3696214634Sdim elf32_arm_compare_mapping); 3697214634Sdim 3698214634Sdim for (span = 0; span < sec_data->mapcount; span++) 3699214634Sdim { 3700214634Sdim unsigned int span_start = sec_data->map[span].vma; 3701214634Sdim unsigned int span_end = (span == sec_data->mapcount - 1) 3702214634Sdim ? sec->size : sec_data->map[span + 1].vma; 3703214634Sdim char span_type = sec_data->map[span].type; 3704214634Sdim 3705214634Sdim /* FIXME: Only ARM mode is supported at present. We may need to 3706214634Sdim support Thumb-2 mode also at some point. */ 3707214634Sdim if (span_type != 'a') 3708214634Sdim continue; 3709214634Sdim 3710214634Sdim for (i = span_start; i < span_end;) 3711214634Sdim { 3712214634Sdim unsigned int next_i = i + 4; 3713214634Sdim unsigned int insn = bfd_big_endian (abfd) 3714214634Sdim ? (contents[i] << 24) 3715214634Sdim | (contents[i + 1] << 16) 3716214634Sdim | (contents[i + 2] << 8) 3717214634Sdim | contents[i + 3] 3718214634Sdim : (contents[i + 3] << 24) 3719214634Sdim | (contents[i + 2] << 16) 3720214634Sdim | (contents[i + 1] << 8) 3721214634Sdim | contents[i]; 3722214634Sdim unsigned int writemask = 0; 3723214634Sdim enum bfd_arm_vfp11_pipe pipe; 3724214634Sdim 3725214634Sdim switch (state) 3726214634Sdim { 3727214634Sdim case 0: 3728214634Sdim pipe = bfd_arm_vfp11_insn_decode (insn, &writemask, regs, 3729214634Sdim &numregs); 3730214634Sdim /* I'm assuming the VFP11 erratum can trigger with denorm 3731214634Sdim operands on either the FMAC or the DS pipeline. This might 3732214634Sdim lead to slightly overenthusiastic veneer insertion. */ 3733214634Sdim if (pipe == VFP11_FMAC || pipe == VFP11_DS) 3734214634Sdim { 3735214634Sdim state = use_vector ? 1 : 2; 3736214634Sdim first_fmac = i; 3737214634Sdim veneer_of_insn = insn; 3738214634Sdim } 3739214634Sdim break; 3740214634Sdim 3741214634Sdim case 1: 3742214634Sdim { 3743214634Sdim int other_regs[3], other_numregs; 3744214634Sdim pipe = bfd_arm_vfp11_insn_decode (insn, &writemask, 3745214634Sdim other_regs, 3746214634Sdim &other_numregs); 3747214634Sdim if (pipe != VFP11_BAD 3748214634Sdim && bfd_arm_vfp11_antidependency (writemask, regs, 3749214634Sdim numregs)) 3750214634Sdim state = 3; 3751214634Sdim else 3752214634Sdim state = 2; 3753214634Sdim } 3754214634Sdim break; 3755214634Sdim 3756214634Sdim case 2: 3757214634Sdim { 3758214634Sdim int other_regs[3], other_numregs; 3759214634Sdim pipe = bfd_arm_vfp11_insn_decode (insn, &writemask, 3760214634Sdim other_regs, 3761214634Sdim &other_numregs); 3762214634Sdim if (pipe != VFP11_BAD 3763214634Sdim && bfd_arm_vfp11_antidependency (writemask, regs, 3764214634Sdim numregs)) 3765214634Sdim state = 3; 3766214634Sdim else 3767214634Sdim { 3768214634Sdim state = 0; 3769214634Sdim next_i = first_fmac + 4; 3770214634Sdim } 3771214634Sdim } 3772214634Sdim break; 3773214634Sdim 3774214634Sdim case 3: 3775214634Sdim abort (); /* Should be unreachable. */ 3776214634Sdim } 3777214634Sdim 3778214634Sdim if (state == 3) 3779214634Sdim { 3780214634Sdim elf32_vfp11_erratum_list *newerr 3781214634Sdim = bfd_zmalloc (sizeof (elf32_vfp11_erratum_list)); 3782214634Sdim int errcount; 3783214634Sdim 3784214634Sdim errcount = ++(elf32_arm_section_data (sec)->erratumcount); 3785214634Sdim 3786214634Sdim newerr->u.b.vfp_insn = veneer_of_insn; 3787214634Sdim 3788214634Sdim switch (span_type) 3789214634Sdim { 3790214634Sdim case 'a': 3791214634Sdim newerr->type = VFP11_ERRATUM_BRANCH_TO_ARM_VENEER; 3792214634Sdim break; 3793214634Sdim 3794214634Sdim default: 3795214634Sdim abort (); 3796214634Sdim } 3797214634Sdim 3798214634Sdim record_vfp11_erratum_veneer (link_info, newerr, abfd, sec, 3799214634Sdim first_fmac); 3800214634Sdim 3801214634Sdim newerr->vma = -1; 3802214634Sdim 3803214634Sdim newerr->next = sec_data->erratumlist; 3804214634Sdim sec_data->erratumlist = newerr; 3805214634Sdim 3806214634Sdim state = 0; 3807214634Sdim } 3808214634Sdim 3809214634Sdim i = next_i; 3810214634Sdim } 3811214634Sdim } 3812214634Sdim 3813214634Sdim if (contents != NULL 3814214634Sdim && elf_section_data (sec)->this_hdr.contents != contents) 3815214634Sdim free (contents); 3816214634Sdim contents = NULL; 3817214634Sdim } 3818214634Sdim 3819214634Sdim return TRUE; 3820214634Sdim 3821214634Sdimerror_return: 3822214634Sdim if (contents != NULL 3823214634Sdim && elf_section_data (sec)->this_hdr.contents != contents) 3824214634Sdim free (contents); 3825214634Sdim 3826214634Sdim return FALSE; 3827214634Sdim} 3828214634Sdim 3829214634Sdim/* Find virtual-memory addresses for VFP11 erratum veneers and return locations 3830214634Sdim after sections have been laid out, using specially-named symbols. */ 3831214634Sdim 3832214634Sdimvoid 3833214634Sdimbfd_elf32_arm_vfp11_fix_veneer_locations (bfd *abfd, 3834214634Sdim struct bfd_link_info *link_info) 3835214634Sdim{ 3836214634Sdim asection *sec; 3837214634Sdim struct elf32_arm_link_hash_table *globals; 3838214634Sdim char *tmp_name; 3839214634Sdim 3840214634Sdim if (link_info->relocatable) 3841214634Sdim return; 3842214634Sdim 3843214634Sdim /* Skip if this bfd does not correspond to an ELF image. */ 3844214634Sdim if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) 3845214634Sdim return; 3846214634Sdim 3847214634Sdim globals = elf32_arm_hash_table (link_info); 3848214634Sdim 3849214634Sdim tmp_name = bfd_malloc ((bfd_size_type) strlen 3850214634Sdim (VFP11_ERRATUM_VENEER_ENTRY_NAME) + 10); 3851214634Sdim 3852214634Sdim for (sec = abfd->sections; sec != NULL; sec = sec->next) 3853214634Sdim { 3854214634Sdim struct _arm_elf_section_data *sec_data = elf32_arm_section_data (sec); 3855214634Sdim elf32_vfp11_erratum_list *errnode = sec_data->erratumlist; 3856214634Sdim 3857214634Sdim for (; errnode != NULL; errnode = errnode->next) 3858214634Sdim { 3859214634Sdim struct elf_link_hash_entry *myh; 3860214634Sdim bfd_vma vma; 3861214634Sdim 3862214634Sdim switch (errnode->type) 3863214634Sdim { 3864214634Sdim case VFP11_ERRATUM_BRANCH_TO_ARM_VENEER: 3865214634Sdim case VFP11_ERRATUM_BRANCH_TO_THUMB_VENEER: 3866214634Sdim /* Find veneer symbol. */ 3867214634Sdim sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME, 3868214634Sdim errnode->u.b.veneer->u.v.id); 3869214634Sdim 3870214634Sdim myh = elf_link_hash_lookup 3871214634Sdim (&(globals)->root, tmp_name, FALSE, FALSE, TRUE); 3872214634Sdim 3873214634Sdim if (myh == NULL) 3874214634Sdim (*_bfd_error_handler) (_("%B: unable to find VFP11 veneer " 3875214634Sdim "`%s'"), abfd, tmp_name); 3876214634Sdim 3877214634Sdim vma = myh->root.u.def.section->output_section->vma 3878214634Sdim + myh->root.u.def.section->output_offset 3879214634Sdim + myh->root.u.def.value; 3880214634Sdim 3881214634Sdim errnode->u.b.veneer->vma = vma; 3882214634Sdim break; 3883214634Sdim 3884214634Sdim case VFP11_ERRATUM_ARM_VENEER: 3885214634Sdim case VFP11_ERRATUM_THUMB_VENEER: 3886214634Sdim /* Find return location. */ 3887214634Sdim sprintf (tmp_name, VFP11_ERRATUM_VENEER_ENTRY_NAME "_r", 3888214634Sdim errnode->u.v.id); 3889214634Sdim 3890214634Sdim myh = elf_link_hash_lookup 3891214634Sdim (&(globals)->root, tmp_name, FALSE, FALSE, TRUE); 3892214634Sdim 3893214634Sdim if (myh == NULL) 3894214634Sdim (*_bfd_error_handler) (_("%B: unable to find VFP11 veneer " 3895214634Sdim "`%s'"), abfd, tmp_name); 3896214634Sdim 3897214634Sdim vma = myh->root.u.def.section->output_section->vma 3898214634Sdim + myh->root.u.def.section->output_offset 3899214634Sdim + myh->root.u.def.value; 3900214634Sdim 3901214634Sdim errnode->u.v.branch->vma = vma; 3902214634Sdim break; 3903214634Sdim 3904214634Sdim default: 3905214634Sdim abort (); 3906214634Sdim } 3907214634Sdim } 3908214634Sdim } 3909214634Sdim 3910214634Sdim free (tmp_name); 3911214634Sdim} 3912214634Sdim 3913214634Sdim 3914214082Sdim/* Set target relocation values needed during linking. */ 3915214082Sdim 3916214082Sdimvoid 3917214634Sdimbfd_elf32_arm_set_target_relocs (struct bfd *output_bfd, 3918214634Sdim struct bfd_link_info *link_info, 3919214082Sdim int target1_is_rel, 3920214082Sdim char * target2_type, 3921214082Sdim int fix_v4bx, 3922214634Sdim int use_blx, 3923214634Sdim bfd_arm_vfp11_fix vfp11_fix, 3924214634Sdim int no_enum_warn, int pic_veneer) 3925214082Sdim{ 3926214082Sdim struct elf32_arm_link_hash_table *globals; 3927214082Sdim 3928214082Sdim globals = elf32_arm_hash_table (link_info); 3929214082Sdim 3930214082Sdim globals->target1_is_rel = target1_is_rel; 3931214082Sdim if (strcmp (target2_type, "rel") == 0) 3932214082Sdim globals->target2_reloc = R_ARM_REL32; 3933214082Sdim else if (strcmp (target2_type, "abs") == 0) 3934214082Sdim globals->target2_reloc = R_ARM_ABS32; 3935214082Sdim else if (strcmp (target2_type, "got-rel") == 0) 3936214082Sdim globals->target2_reloc = R_ARM_GOT_PREL; 3937214082Sdim else 3938214082Sdim { 3939214082Sdim _bfd_error_handler (_("Invalid TARGET2 relocation type '%s'."), 3940214082Sdim target2_type); 3941214082Sdim } 3942214082Sdim globals->fix_v4bx = fix_v4bx; 3943214082Sdim globals->use_blx |= use_blx; 3944214634Sdim globals->vfp11_fix = vfp11_fix; 3945214634Sdim globals->pic_veneer = pic_veneer; 3946214634Sdim 3947214634Sdim elf32_arm_tdata (output_bfd)->no_enum_size_warning = no_enum_warn; 3948214082Sdim} 3949214082Sdim 3950214082Sdim/* The thumb form of a long branch is a bit finicky, because the offset 3951214082Sdim encoding is split over two fields, each in it's own instruction. They 3952214082Sdim can occur in any order. So given a thumb form of long branch, and an 3953214082Sdim offset, insert the offset into the thumb branch and return finished 3954214082Sdim instruction. 3955214082Sdim 3956214082Sdim It takes two thumb instructions to encode the target address. Each has 3957214082Sdim 11 bits to invest. The upper 11 bits are stored in one (identified by 3958214082Sdim H-0.. see below), the lower 11 bits are stored in the other (identified 3959214082Sdim by H-1). 3960214082Sdim 3961214082Sdim Combine together and shifted left by 1 (it's a half word address) and 3962214082Sdim there you have it. 3963214082Sdim 3964214082Sdim Op: 1111 = F, 3965214082Sdim H-0, upper address-0 = 000 3966214082Sdim Op: 1111 = F, 3967214082Sdim H-1, lower address-0 = 800 3968214082Sdim 3969214082Sdim They can be ordered either way, but the arm tools I've seen always put 3970214082Sdim the lower one first. It probably doesn't matter. krk@cygnus.com 3971214082Sdim 3972214082Sdim XXX: Actually the order does matter. The second instruction (H-1) 3973214082Sdim moves the computed address into the PC, so it must be the second one 3974214082Sdim in the sequence. The problem, however is that whilst little endian code 3975214082Sdim stores the instructions in HI then LOW order, big endian code does the 3976214082Sdim reverse. nickc@cygnus.com. */ 3977214082Sdim 3978214082Sdim#define LOW_HI_ORDER 0xF800F000 3979214082Sdim#define HI_LOW_ORDER 0xF000F800 3980214082Sdim 3981214082Sdimstatic insn32 3982214082Sdiminsert_thumb_branch (insn32 br_insn, int rel_off) 3983214082Sdim{ 3984214082Sdim unsigned int low_bits; 3985214082Sdim unsigned int high_bits; 3986214082Sdim 3987214082Sdim BFD_ASSERT ((rel_off & 1) != 1); 3988214082Sdim 3989214082Sdim rel_off >>= 1; /* Half word aligned address. */ 3990214082Sdim low_bits = rel_off & 0x000007FF; /* The bottom 11 bits. */ 3991214082Sdim high_bits = (rel_off >> 11) & 0x000007FF; /* The top 11 bits. */ 3992214082Sdim 3993214082Sdim if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER) 3994214082Sdim br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits; 3995214082Sdim else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER) 3996214082Sdim br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits; 3997214082Sdim else 3998214082Sdim /* FIXME: abort is probably not the right call. krk@cygnus.com */ 3999214082Sdim abort (); /* Error - not a valid branch instruction form. */ 4000214082Sdim 4001214082Sdim return br_insn; 4002214082Sdim} 4003214082Sdim 4004214634Sdim 4005214634Sdim/* Store an Arm insn into an output section not processed by 4006214634Sdim elf32_arm_write_section. */ 4007214634Sdim 4008214634Sdimstatic void 4009214634Sdimput_arm_insn (struct elf32_arm_link_hash_table *htab, 4010214634Sdim bfd * output_bfd, bfd_vma val, void * ptr) 4011214634Sdim{ 4012214634Sdim if (htab->byteswap_code != bfd_little_endian (output_bfd)) 4013214634Sdim bfd_putl32 (val, ptr); 4014214634Sdim else 4015214634Sdim bfd_putb32 (val, ptr); 4016214634Sdim} 4017214634Sdim 4018214634Sdim 4019214634Sdim/* Store a 16-bit Thumb insn into an output section not processed by 4020214634Sdim elf32_arm_write_section. */ 4021214634Sdim 4022214634Sdimstatic void 4023214634Sdimput_thumb_insn (struct elf32_arm_link_hash_table *htab, 4024214634Sdim bfd * output_bfd, bfd_vma val, void * ptr) 4025214634Sdim{ 4026214634Sdim if (htab->byteswap_code != bfd_little_endian (output_bfd)) 4027214634Sdim bfd_putl16 (val, ptr); 4028214634Sdim else 4029214634Sdim bfd_putb16 (val, ptr); 4030214634Sdim} 4031214634Sdim 4032214634Sdim 4033214082Sdim/* Thumb code calling an ARM function. */ 4034214082Sdim 4035214082Sdimstatic int 4036214082Sdimelf32_thumb_to_arm_stub (struct bfd_link_info * info, 4037214082Sdim const char * name, 4038214082Sdim bfd * input_bfd, 4039214082Sdim bfd * output_bfd, 4040214082Sdim asection * input_section, 4041214082Sdim bfd_byte * hit_data, 4042214082Sdim asection * sym_sec, 4043214082Sdim bfd_vma offset, 4044214082Sdim bfd_signed_vma addend, 4045214634Sdim bfd_vma val, 4046214634Sdim char **error_message) 4047214082Sdim{ 4048214082Sdim asection * s = 0; 4049214082Sdim bfd_vma my_offset; 4050214082Sdim unsigned long int tmp; 4051214082Sdim long int ret_offset; 4052214082Sdim struct elf_link_hash_entry * myh; 4053214082Sdim struct elf32_arm_link_hash_table * globals; 4054214082Sdim 4055214634Sdim myh = find_thumb_glue (info, name, error_message); 4056214082Sdim if (myh == NULL) 4057214082Sdim return FALSE; 4058214082Sdim 4059214082Sdim globals = elf32_arm_hash_table (info); 4060214082Sdim 4061214082Sdim BFD_ASSERT (globals != NULL); 4062214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 4063214082Sdim 4064214082Sdim my_offset = myh->root.u.def.value; 4065214082Sdim 4066214082Sdim s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 4067214082Sdim THUMB2ARM_GLUE_SECTION_NAME); 4068214082Sdim 4069214082Sdim BFD_ASSERT (s != NULL); 4070214082Sdim BFD_ASSERT (s->contents != NULL); 4071214082Sdim BFD_ASSERT (s->output_section != NULL); 4072214082Sdim 4073214082Sdim if ((my_offset & 0x01) == 0x01) 4074214082Sdim { 4075214082Sdim if (sym_sec != NULL 4076214082Sdim && sym_sec->owner != NULL 4077214082Sdim && !INTERWORK_FLAG (sym_sec->owner)) 4078214082Sdim { 4079214082Sdim (*_bfd_error_handler) 4080214082Sdim (_("%B(%s): warning: interworking not enabled.\n" 4081214082Sdim " first occurrence: %B: thumb call to arm"), 4082214082Sdim sym_sec->owner, input_bfd, name); 4083214082Sdim 4084214082Sdim return FALSE; 4085214082Sdim } 4086214082Sdim 4087214082Sdim --my_offset; 4088214082Sdim myh->root.u.def.value = my_offset; 4089214082Sdim 4090214634Sdim put_thumb_insn (globals, output_bfd, (bfd_vma) t2a1_bx_pc_insn, 4091214634Sdim s->contents + my_offset); 4092214082Sdim 4093214634Sdim put_thumb_insn (globals, output_bfd, (bfd_vma) t2a2_noop_insn, 4094214634Sdim s->contents + my_offset + 2); 4095214082Sdim 4096214082Sdim ret_offset = 4097214082Sdim /* Address of destination of the stub. */ 4098214082Sdim ((bfd_signed_vma) val) 4099214082Sdim - ((bfd_signed_vma) 4100214082Sdim /* Offset from the start of the current section 4101214082Sdim to the start of the stubs. */ 4102214082Sdim (s->output_offset 4103214082Sdim /* Offset of the start of this stub from the start of the stubs. */ 4104214082Sdim + my_offset 4105214082Sdim /* Address of the start of the current section. */ 4106214082Sdim + s->output_section->vma) 4107214082Sdim /* The branch instruction is 4 bytes into the stub. */ 4108214082Sdim + 4 4109214082Sdim /* ARM branches work from the pc of the instruction + 8. */ 4110214082Sdim + 8); 4111214082Sdim 4112214634Sdim put_arm_insn (globals, output_bfd, 4113214634Sdim (bfd_vma) t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF), 4114214634Sdim s->contents + my_offset + 4); 4115214082Sdim } 4116214082Sdim 4117214082Sdim BFD_ASSERT (my_offset <= globals->thumb_glue_size); 4118214082Sdim 4119214082Sdim /* Now go back and fix up the original BL insn to point to here. */ 4120214082Sdim ret_offset = 4121214082Sdim /* Address of where the stub is located. */ 4122214082Sdim (s->output_section->vma + s->output_offset + my_offset) 4123214082Sdim /* Address of where the BL is located. */ 4124214082Sdim - (input_section->output_section->vma + input_section->output_offset 4125214082Sdim + offset) 4126214082Sdim /* Addend in the relocation. */ 4127214082Sdim - addend 4128214082Sdim /* Biassing for PC-relative addressing. */ 4129214082Sdim - 8; 4130214082Sdim 4131214082Sdim tmp = bfd_get_32 (input_bfd, hit_data 4132214082Sdim - input_section->vma); 4133214082Sdim 4134214082Sdim bfd_put_32 (output_bfd, 4135214082Sdim (bfd_vma) insert_thumb_branch (tmp, ret_offset), 4136214082Sdim hit_data - input_section->vma); 4137214082Sdim 4138214082Sdim return TRUE; 4139214082Sdim} 4140214082Sdim 4141214634Sdim/* Populate an Arm to Thumb stub. Returns the stub symbol. */ 4142214082Sdim 4143214634Sdimstatic struct elf_link_hash_entry * 4144214634Sdimelf32_arm_create_thumb_stub (struct bfd_link_info * info, 4145214634Sdim const char * name, 4146214634Sdim bfd * input_bfd, 4147214634Sdim bfd * output_bfd, 4148214634Sdim asection * sym_sec, 4149214634Sdim bfd_vma val, 4150214634Sdim asection *s, 4151214634Sdim char **error_message) 4152214082Sdim{ 4153214082Sdim bfd_vma my_offset; 4154214082Sdim long int ret_offset; 4155214082Sdim struct elf_link_hash_entry * myh; 4156214082Sdim struct elf32_arm_link_hash_table * globals; 4157214082Sdim 4158214634Sdim myh = find_arm_glue (info, name, error_message); 4159214082Sdim if (myh == NULL) 4160214634Sdim return NULL; 4161214082Sdim 4162214082Sdim globals = elf32_arm_hash_table (info); 4163214082Sdim 4164214082Sdim BFD_ASSERT (globals != NULL); 4165214082Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 4166214082Sdim 4167214082Sdim my_offset = myh->root.u.def.value; 4168214082Sdim 4169214082Sdim if ((my_offset & 0x01) == 0x01) 4170214082Sdim { 4171214082Sdim if (sym_sec != NULL 4172214082Sdim && sym_sec->owner != NULL 4173214082Sdim && !INTERWORK_FLAG (sym_sec->owner)) 4174214082Sdim { 4175214082Sdim (*_bfd_error_handler) 4176214082Sdim (_("%B(%s): warning: interworking not enabled.\n" 4177214082Sdim " first occurrence: %B: arm call to thumb"), 4178214082Sdim sym_sec->owner, input_bfd, name); 4179214082Sdim } 4180214082Sdim 4181214082Sdim --my_offset; 4182214082Sdim myh->root.u.def.value = my_offset; 4183214082Sdim 4184214634Sdim if (info->shared || globals->root.is_relocatable_executable 4185214634Sdim || globals->pic_veneer) 4186214082Sdim { 4187214082Sdim /* For relocatable objects we can't use absolute addresses, 4188214082Sdim so construct the address from a relative offset. */ 4189214082Sdim /* TODO: If the offset is small it's probably worth 4190214082Sdim constructing the address with adds. */ 4191214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t1p_ldr_insn, 4192214634Sdim s->contents + my_offset); 4193214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t2p_add_pc_insn, 4194214634Sdim s->contents + my_offset + 4); 4195214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t3p_bx_r12_insn, 4196214634Sdim s->contents + my_offset + 8); 4197214082Sdim /* Adjust the offset by 4 for the position of the add, 4198214082Sdim and 8 for the pipeline offset. */ 4199214082Sdim ret_offset = (val - (s->output_offset 4200214082Sdim + s->output_section->vma 4201214082Sdim + my_offset + 12)) 4202214082Sdim | 1; 4203214082Sdim bfd_put_32 (output_bfd, ret_offset, 4204214082Sdim s->contents + my_offset + 12); 4205214082Sdim } 4206214634Sdim else if (globals->use_blx) 4207214082Sdim { 4208214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t1v5_ldr_insn, 4209214634Sdim s->contents + my_offset); 4210214082Sdim 4211214634Sdim /* It's a thumb address. Add the low order bit. */ 4212214634Sdim bfd_put_32 (output_bfd, val | a2t2v5_func_addr_insn, 4213214082Sdim s->contents + my_offset + 4); 4214214634Sdim } 4215214634Sdim else 4216214634Sdim { 4217214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t1_ldr_insn, 4218214634Sdim s->contents + my_offset); 4219214082Sdim 4220214634Sdim put_arm_insn (globals, output_bfd, (bfd_vma) a2t2_bx_r12_insn, 4221214634Sdim s->contents + my_offset + 4); 4222214634Sdim 4223214082Sdim /* It's a thumb address. Add the low order bit. */ 4224214082Sdim bfd_put_32 (output_bfd, val | a2t3_func_addr_insn, 4225214082Sdim s->contents + my_offset + 8); 4226214082Sdim } 4227214082Sdim } 4228214082Sdim 4229214082Sdim BFD_ASSERT (my_offset <= globals->arm_glue_size); 4230214082Sdim 4231214634Sdim return myh; 4232214634Sdim} 4233214634Sdim 4234214634Sdim/* Arm code calling a Thumb function. */ 4235214634Sdim 4236214634Sdimstatic int 4237214634Sdimelf32_arm_to_thumb_stub (struct bfd_link_info * info, 4238214634Sdim const char * name, 4239214634Sdim bfd * input_bfd, 4240214634Sdim bfd * output_bfd, 4241214634Sdim asection * input_section, 4242214634Sdim bfd_byte * hit_data, 4243214634Sdim asection * sym_sec, 4244214634Sdim bfd_vma offset, 4245214634Sdim bfd_signed_vma addend, 4246214634Sdim bfd_vma val, 4247214634Sdim char **error_message) 4248214634Sdim{ 4249214634Sdim unsigned long int tmp; 4250214634Sdim bfd_vma my_offset; 4251214634Sdim asection * s; 4252214634Sdim long int ret_offset; 4253214634Sdim struct elf_link_hash_entry * myh; 4254214634Sdim struct elf32_arm_link_hash_table * globals; 4255214634Sdim 4256214634Sdim globals = elf32_arm_hash_table (info); 4257214634Sdim 4258214634Sdim BFD_ASSERT (globals != NULL); 4259214634Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 4260214634Sdim 4261214634Sdim s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 4262214634Sdim ARM2THUMB_GLUE_SECTION_NAME); 4263214634Sdim BFD_ASSERT (s != NULL); 4264214634Sdim BFD_ASSERT (s->contents != NULL); 4265214634Sdim BFD_ASSERT (s->output_section != NULL); 4266214634Sdim 4267214634Sdim myh = elf32_arm_create_thumb_stub (info, name, input_bfd, output_bfd, 4268214634Sdim sym_sec, val, s, error_message); 4269214634Sdim if (!myh) 4270214634Sdim return FALSE; 4271214634Sdim 4272214634Sdim my_offset = myh->root.u.def.value; 4273214082Sdim tmp = bfd_get_32 (input_bfd, hit_data); 4274214082Sdim tmp = tmp & 0xFF000000; 4275214082Sdim 4276214082Sdim /* Somehow these are both 4 too far, so subtract 8. */ 4277214082Sdim ret_offset = (s->output_offset 4278214082Sdim + my_offset 4279214082Sdim + s->output_section->vma 4280214082Sdim - (input_section->output_offset 4281214082Sdim + input_section->output_section->vma 4282214082Sdim + offset + addend) 4283214082Sdim - 8); 4284214082Sdim 4285214082Sdim tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF); 4286214082Sdim 4287214082Sdim bfd_put_32 (output_bfd, (bfd_vma) tmp, hit_data - input_section->vma); 4288214082Sdim 4289214082Sdim return TRUE; 4290214082Sdim} 4291214082Sdim 4292214634Sdim/* Populate Arm stub for an exported Thumb function. */ 4293214634Sdim 4294214634Sdimstatic bfd_boolean 4295214634Sdimelf32_arm_to_thumb_export_stub (struct elf_link_hash_entry *h, void * inf) 4296214634Sdim{ 4297214634Sdim struct bfd_link_info * info = (struct bfd_link_info *) inf; 4298214634Sdim asection * s; 4299214634Sdim struct elf_link_hash_entry * myh; 4300214634Sdim struct elf32_arm_link_hash_entry *eh; 4301214634Sdim struct elf32_arm_link_hash_table * globals; 4302214634Sdim asection *sec; 4303214634Sdim bfd_vma val; 4304214634Sdim char *error_message; 4305214634Sdim 4306214634Sdim eh = elf32_arm_hash_entry(h); 4307214634Sdim /* Allocate stubs for exported Thumb functions on v4t. */ 4308214634Sdim if (eh->export_glue == NULL) 4309214634Sdim return TRUE; 4310214634Sdim 4311214634Sdim globals = elf32_arm_hash_table (info); 4312214634Sdim 4313214634Sdim BFD_ASSERT (globals != NULL); 4314214634Sdim BFD_ASSERT (globals->bfd_of_glue_owner != NULL); 4315214634Sdim 4316214634Sdim s = bfd_get_section_by_name (globals->bfd_of_glue_owner, 4317214634Sdim ARM2THUMB_GLUE_SECTION_NAME); 4318214634Sdim BFD_ASSERT (s != NULL); 4319214634Sdim BFD_ASSERT (s->contents != NULL); 4320214634Sdim BFD_ASSERT (s->output_section != NULL); 4321214634Sdim 4322214634Sdim sec = eh->export_glue->root.u.def.section; 4323214634Sdim 4324214634Sdim BFD_ASSERT (sec->output_section != NULL); 4325214634Sdim 4326214634Sdim val = eh->export_glue->root.u.def.value + sec->output_offset 4327214634Sdim + sec->output_section->vma; 4328214634Sdim myh = elf32_arm_create_thumb_stub (info, h->root.root.string, 4329214634Sdim h->root.u.def.section->owner, 4330214634Sdim globals->obfd, sec, val, s, 4331214634Sdim &error_message); 4332214634Sdim BFD_ASSERT (myh); 4333214634Sdim return TRUE; 4334214634Sdim} 4335214634Sdim 4336214634Sdim/* Generate Arm stubs for exported Thumb symbols. */ 4337214634Sdimstatic void 4338214634Sdimelf32_arm_begin_write_processing (bfd *abfd ATTRIBUTE_UNUSED, 4339214634Sdim struct bfd_link_info *link_info) 4340214634Sdim{ 4341214634Sdim struct elf32_arm_link_hash_table * globals; 4342214634Sdim 4343214634Sdim if (!link_info) 4344214634Sdim return; 4345214634Sdim 4346214634Sdim globals = elf32_arm_hash_table (link_info); 4347214634Sdim /* If blx is available then exported Thumb symbols are OK and there is 4348214634Sdim nothing to do. */ 4349214634Sdim if (globals->use_blx) 4350214634Sdim return; 4351214634Sdim 4352214634Sdim elf_link_hash_traverse (&globals->root, elf32_arm_to_thumb_export_stub, 4353214634Sdim link_info); 4354214634Sdim} 4355214634Sdim 4356214082Sdim/* Some relocations map to different relocations depending on the 4357214082Sdim target. Return the real relocation. */ 4358214082Sdimstatic int 4359214082Sdimarm_real_reloc_type (struct elf32_arm_link_hash_table * globals, 4360214082Sdim int r_type) 4361214082Sdim{ 4362214082Sdim switch (r_type) 4363214082Sdim { 4364214082Sdim case R_ARM_TARGET1: 4365214082Sdim if (globals->target1_is_rel) 4366214082Sdim return R_ARM_REL32; 4367214082Sdim else 4368214082Sdim return R_ARM_ABS32; 4369214082Sdim 4370214082Sdim case R_ARM_TARGET2: 4371214082Sdim return globals->target2_reloc; 4372214082Sdim 4373214082Sdim default: 4374214082Sdim return r_type; 4375214082Sdim } 4376214082Sdim} 4377214082Sdim 4378214082Sdim/* Return the base VMA address which should be subtracted from real addresses 4379214082Sdim when resolving @dtpoff relocation. 4380214082Sdim This is PT_TLS segment p_vaddr. */ 4381214082Sdim 4382214082Sdimstatic bfd_vma 4383214082Sdimdtpoff_base (struct bfd_link_info *info) 4384214082Sdim{ 4385214082Sdim /* If tls_sec is NULL, we should have signalled an error already. */ 4386214082Sdim if (elf_hash_table (info)->tls_sec == NULL) 4387214082Sdim return 0; 4388214082Sdim return elf_hash_table (info)->tls_sec->vma; 4389214082Sdim} 4390214082Sdim 4391214082Sdim/* Return the relocation value for @tpoff relocation 4392214082Sdim if STT_TLS virtual address is ADDRESS. */ 4393214082Sdim 4394214082Sdimstatic bfd_vma 4395214082Sdimtpoff (struct bfd_link_info *info, bfd_vma address) 4396214082Sdim{ 4397214082Sdim struct elf_link_hash_table *htab = elf_hash_table (info); 4398214082Sdim bfd_vma base; 4399214082Sdim 4400214082Sdim /* If tls_sec is NULL, we should have signalled an error already. */ 4401214082Sdim if (htab->tls_sec == NULL) 4402214082Sdim return 0; 4403214082Sdim base = align_power ((bfd_vma) TCB_SIZE, htab->tls_sec->alignment_power); 4404214082Sdim return address - htab->tls_sec->vma + base; 4405214082Sdim} 4406214082Sdim 4407214082Sdim/* Perform an R_ARM_ABS12 relocation on the field pointed to by DATA. 4408214082Sdim VALUE is the relocation value. */ 4409214082Sdim 4410214082Sdimstatic bfd_reloc_status_type 4411214082Sdimelf32_arm_abs12_reloc (bfd *abfd, void *data, bfd_vma value) 4412214082Sdim{ 4413214082Sdim if (value > 0xfff) 4414214082Sdim return bfd_reloc_overflow; 4415214082Sdim 4416214082Sdim value |= bfd_get_32 (abfd, data) & 0xfffff000; 4417214082Sdim bfd_put_32 (abfd, value, data); 4418214082Sdim return bfd_reloc_ok; 4419214082Sdim} 4420214082Sdim 4421214634Sdim/* For a given value of n, calculate the value of G_n as required to 4422214634Sdim deal with group relocations. We return it in the form of an 4423214634Sdim encoded constant-and-rotation, together with the final residual. If n is 4424214634Sdim specified as less than zero, then final_residual is filled with the 4425214634Sdim input value and no further action is performed. */ 4426214634Sdim 4427214634Sdimstatic bfd_vma 4428214634Sdimcalculate_group_reloc_mask (bfd_vma value, int n, bfd_vma *final_residual) 4429214634Sdim{ 4430214634Sdim int current_n; 4431214634Sdim bfd_vma g_n; 4432214634Sdim bfd_vma encoded_g_n = 0; 4433214634Sdim bfd_vma residual = value; /* Also known as Y_n. */ 4434214634Sdim 4435214634Sdim for (current_n = 0; current_n <= n; current_n++) 4436214634Sdim { 4437214634Sdim int shift; 4438214634Sdim 4439214634Sdim /* Calculate which part of the value to mask. */ 4440214634Sdim if (residual == 0) 4441214634Sdim shift = 0; 4442214634Sdim else 4443214634Sdim { 4444214634Sdim int msb; 4445214634Sdim 4446214634Sdim /* Determine the most significant bit in the residual and 4447214634Sdim align the resulting value to a 2-bit boundary. */ 4448214634Sdim for (msb = 30; msb >= 0; msb -= 2) 4449214634Sdim if (residual & (3 << msb)) 4450214634Sdim break; 4451214634Sdim 4452214634Sdim /* The desired shift is now (msb - 6), or zero, whichever 4453214634Sdim is the greater. */ 4454214634Sdim shift = msb - 6; 4455214634Sdim if (shift < 0) 4456214634Sdim shift = 0; 4457214634Sdim } 4458214634Sdim 4459214634Sdim /* Calculate g_n in 32-bit as well as encoded constant+rotation form. */ 4460214634Sdim g_n = residual & (0xff << shift); 4461214634Sdim encoded_g_n = (g_n >> shift) 4462214634Sdim | ((g_n <= 0xff ? 0 : (32 - shift) / 2) << 8); 4463214634Sdim 4464214634Sdim /* Calculate the residual for the next time around. */ 4465214634Sdim residual &= ~g_n; 4466214634Sdim } 4467214634Sdim 4468214634Sdim *final_residual = residual; 4469214634Sdim 4470214634Sdim return encoded_g_n; 4471214634Sdim} 4472214634Sdim 4473214634Sdim/* Given an ARM instruction, determine whether it is an ADD or a SUB. 4474214634Sdim Returns 1 if it is an ADD, -1 if it is a SUB, and 0 otherwise. */ 4475214634Sdimstatic int 4476214634Sdimidentify_add_or_sub(bfd_vma insn) 4477214634Sdim{ 4478214634Sdim int opcode = insn & 0x1e00000; 4479214634Sdim 4480214634Sdim if (opcode == 1 << 23) /* ADD */ 4481214634Sdim return 1; 4482214634Sdim 4483214634Sdim if (opcode == 1 << 22) /* SUB */ 4484214634Sdim return -1; 4485214634Sdim 4486214634Sdim return 0; 4487214634Sdim} 4488214634Sdim 4489214634Sdim/* Determine if we're dealing with a Thumb-2 object. */ 4490214634Sdim 4491214634Sdimstatic int using_thumb2 (struct elf32_arm_link_hash_table *globals) 4492214634Sdim{ 4493214634Sdim int arch = bfd_elf_get_obj_attr_int (globals->obfd, OBJ_ATTR_PROC, 4494214634Sdim Tag_CPU_arch); 4495214634Sdim return arch == TAG_CPU_ARCH_V6T2 || arch >= TAG_CPU_ARCH_V7; 4496214634Sdim} 4497214634Sdim 4498214082Sdim/* Perform a relocation as part of a final link. */ 4499214082Sdim 4500214082Sdimstatic bfd_reloc_status_type 4501214082Sdimelf32_arm_final_link_relocate (reloc_howto_type * howto, 4502214082Sdim bfd * input_bfd, 4503214082Sdim bfd * output_bfd, 4504214082Sdim asection * input_section, 4505214082Sdim bfd_byte * contents, 4506214082Sdim Elf_Internal_Rela * rel, 4507214082Sdim bfd_vma value, 4508214082Sdim struct bfd_link_info * info, 4509214082Sdim asection * sym_sec, 4510214082Sdim const char * sym_name, 4511214082Sdim int sym_flags, 4512214082Sdim struct elf_link_hash_entry * h, 4513214634Sdim bfd_boolean * unresolved_reloc_p, 4514214634Sdim char **error_message) 4515214082Sdim{ 4516214082Sdim unsigned long r_type = howto->type; 4517214082Sdim unsigned long r_symndx; 4518214082Sdim bfd_byte * hit_data = contents + rel->r_offset; 4519214082Sdim bfd * dynobj = NULL; 4520214082Sdim Elf_Internal_Shdr * symtab_hdr; 4521214082Sdim struct elf_link_hash_entry ** sym_hashes; 4522214082Sdim bfd_vma * local_got_offsets; 4523214082Sdim asection * sgot = NULL; 4524214082Sdim asection * splt = NULL; 4525214082Sdim asection * sreloc = NULL; 4526214082Sdim bfd_vma addend; 4527214082Sdim bfd_signed_vma signed_addend; 4528214082Sdim struct elf32_arm_link_hash_table * globals; 4529214082Sdim 4530214082Sdim globals = elf32_arm_hash_table (info); 4531214082Sdim 4532214082Sdim /* Some relocation type map to different relocations depending on the 4533214082Sdim target. We pick the right one here. */ 4534214082Sdim r_type = arm_real_reloc_type (globals, r_type); 4535214082Sdim if (r_type != howto->type) 4536214082Sdim howto = elf32_arm_howto_from_type (r_type); 4537214082Sdim 4538214082Sdim /* If the start address has been set, then set the EF_ARM_HASENTRY 4539214082Sdim flag. Setting this more than once is redundant, but the cost is 4540214082Sdim not too high, and it keeps the code simple. 4541214082Sdim 4542214082Sdim The test is done here, rather than somewhere else, because the 4543214082Sdim start address is only set just before the final link commences. 4544214082Sdim 4545214082Sdim Note - if the user deliberately sets a start address of 0, the 4546214082Sdim flag will not be set. */ 4547214082Sdim if (bfd_get_start_address (output_bfd) != 0) 4548214082Sdim elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY; 4549214082Sdim 4550214082Sdim dynobj = elf_hash_table (info)->dynobj; 4551214082Sdim if (dynobj) 4552214082Sdim { 4553214082Sdim sgot = bfd_get_section_by_name (dynobj, ".got"); 4554214082Sdim splt = bfd_get_section_by_name (dynobj, ".plt"); 4555214082Sdim } 4556214082Sdim symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 4557214082Sdim sym_hashes = elf_sym_hashes (input_bfd); 4558214082Sdim local_got_offsets = elf_local_got_offsets (input_bfd); 4559214082Sdim r_symndx = ELF32_R_SYM (rel->r_info); 4560214082Sdim 4561214082Sdim if (globals->use_rel) 4562214082Sdim { 4563214082Sdim addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask; 4564214082Sdim 4565214082Sdim if (addend & ((howto->src_mask + 1) >> 1)) 4566214082Sdim { 4567214082Sdim signed_addend = -1; 4568214082Sdim signed_addend &= ~ howto->src_mask; 4569214082Sdim signed_addend |= addend; 4570214082Sdim } 4571214082Sdim else 4572214082Sdim signed_addend = addend; 4573214082Sdim } 4574214082Sdim else 4575214082Sdim addend = signed_addend = rel->r_addend; 4576214082Sdim 4577214082Sdim switch (r_type) 4578214082Sdim { 4579214082Sdim case R_ARM_NONE: 4580214082Sdim /* We don't need to find a value for this symbol. It's just a 4581214082Sdim marker. */ 4582214082Sdim *unresolved_reloc_p = FALSE; 4583214082Sdim return bfd_reloc_ok; 4584214082Sdim 4585214082Sdim case R_ARM_ABS12: 4586214082Sdim if (!globals->vxworks_p) 4587214082Sdim return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend); 4588214082Sdim 4589214082Sdim case R_ARM_PC24: 4590214082Sdim case R_ARM_ABS32: 4591214634Sdim case R_ARM_ABS32_NOI: 4592214082Sdim case R_ARM_REL32: 4593214634Sdim case R_ARM_REL32_NOI: 4594214082Sdim case R_ARM_CALL: 4595214082Sdim case R_ARM_JUMP24: 4596214082Sdim case R_ARM_XPC25: 4597214082Sdim case R_ARM_PREL31: 4598214082Sdim case R_ARM_PLT32: 4599214082Sdim /* Handle relocations which should use the PLT entry. ABS32/REL32 4600214082Sdim will use the symbol's value, which may point to a PLT entry, but we 4601214082Sdim don't need to handle that here. If we created a PLT entry, all 4602214082Sdim branches in this object should go to it. */ 4603214634Sdim if ((r_type != R_ARM_ABS32 && r_type != R_ARM_REL32 4604214634Sdim && r_type != R_ARM_ABS32_NOI && r_type != R_ARM_REL32_NOI) 4605214082Sdim && h != NULL 4606214082Sdim && splt != NULL 4607214082Sdim && h->plt.offset != (bfd_vma) -1) 4608214082Sdim { 4609214082Sdim /* If we've created a .plt section, and assigned a PLT entry to 4610214082Sdim this function, it should not be known to bind locally. If 4611214082Sdim it were, we would have cleared the PLT entry. */ 4612214082Sdim BFD_ASSERT (!SYMBOL_CALLS_LOCAL (info, h)); 4613214082Sdim 4614214082Sdim value = (splt->output_section->vma 4615214082Sdim + splt->output_offset 4616214082Sdim + h->plt.offset); 4617214082Sdim *unresolved_reloc_p = FALSE; 4618214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 4619214082Sdim contents, rel->r_offset, value, 4620214082Sdim rel->r_addend); 4621214082Sdim } 4622214082Sdim 4623214082Sdim /* When generating a shared object or relocatable executable, these 4624214082Sdim relocations are copied into the output file to be resolved at 4625214082Sdim run time. */ 4626214082Sdim if ((info->shared || globals->root.is_relocatable_executable) 4627214082Sdim && (input_section->flags & SEC_ALLOC) 4628214634Sdim && ((r_type != R_ARM_REL32 && r_type != R_ARM_REL32_NOI) 4629214082Sdim || !SYMBOL_CALLS_LOCAL (info, h)) 4630214082Sdim && (h == NULL 4631214082Sdim || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 4632214082Sdim || h->root.type != bfd_link_hash_undefweak) 4633214082Sdim && r_type != R_ARM_PC24 4634214082Sdim && r_type != R_ARM_CALL 4635214082Sdim && r_type != R_ARM_JUMP24 4636214082Sdim && r_type != R_ARM_PREL31 4637214082Sdim && r_type != R_ARM_PLT32) 4638214082Sdim { 4639214082Sdim Elf_Internal_Rela outrel; 4640214082Sdim bfd_byte *loc; 4641214082Sdim bfd_boolean skip, relocate; 4642214082Sdim 4643214082Sdim *unresolved_reloc_p = FALSE; 4644214082Sdim 4645214082Sdim if (sreloc == NULL) 4646214082Sdim { 4647214082Sdim const char * name; 4648214082Sdim 4649214082Sdim name = (bfd_elf_string_from_elf_section 4650214082Sdim (input_bfd, 4651214082Sdim elf_elfheader (input_bfd)->e_shstrndx, 4652214082Sdim elf_section_data (input_section)->rel_hdr.sh_name)); 4653214082Sdim if (name == NULL) 4654214082Sdim return bfd_reloc_notsupported; 4655214082Sdim 4656214082Sdim BFD_ASSERT (reloc_section_p (globals, name, input_section)); 4657214082Sdim 4658214082Sdim sreloc = bfd_get_section_by_name (dynobj, name); 4659214082Sdim BFD_ASSERT (sreloc != NULL); 4660214082Sdim } 4661214082Sdim 4662214082Sdim skip = FALSE; 4663214082Sdim relocate = FALSE; 4664214082Sdim 4665214082Sdim outrel.r_addend = addend; 4666214082Sdim outrel.r_offset = 4667214082Sdim _bfd_elf_section_offset (output_bfd, info, input_section, 4668214082Sdim rel->r_offset); 4669214082Sdim if (outrel.r_offset == (bfd_vma) -1) 4670214082Sdim skip = TRUE; 4671214082Sdim else if (outrel.r_offset == (bfd_vma) -2) 4672214082Sdim skip = TRUE, relocate = TRUE; 4673214082Sdim outrel.r_offset += (input_section->output_section->vma 4674214082Sdim + input_section->output_offset); 4675214082Sdim 4676214082Sdim if (skip) 4677214082Sdim memset (&outrel, 0, sizeof outrel); 4678214082Sdim else if (h != NULL 4679214082Sdim && h->dynindx != -1 4680214082Sdim && (!info->shared 4681214082Sdim || !info->symbolic 4682214082Sdim || !h->def_regular)) 4683214082Sdim outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 4684214082Sdim else 4685214082Sdim { 4686214082Sdim int symbol; 4687214082Sdim 4688214082Sdim /* This symbol is local, or marked to become local. */ 4689214082Sdim if (sym_flags == STT_ARM_TFUNC) 4690214082Sdim value |= 1; 4691214082Sdim if (globals->symbian_p) 4692214082Sdim { 4693214634Sdim asection *osec; 4694214634Sdim 4695214082Sdim /* On Symbian OS, the data segment and text segement 4696214082Sdim can be relocated independently. Therefore, we 4697214082Sdim must indicate the segment to which this 4698214082Sdim relocation is relative. The BPABI allows us to 4699214082Sdim use any symbol in the right segment; we just use 4700214082Sdim the section symbol as it is convenient. (We 4701214082Sdim cannot use the symbol given by "h" directly as it 4702214634Sdim will not appear in the dynamic symbol table.) 4703214634Sdim 4704214634Sdim Note that the dynamic linker ignores the section 4705214634Sdim symbol value, so we don't subtract osec->vma 4706214634Sdim from the emitted reloc addend. */ 4707214082Sdim if (sym_sec) 4708214634Sdim osec = sym_sec->output_section; 4709214082Sdim else 4710214634Sdim osec = input_section->output_section; 4711214634Sdim symbol = elf_section_data (osec)->dynindx; 4712214634Sdim if (symbol == 0) 4713214634Sdim { 4714214634Sdim struct elf_link_hash_table *htab = elf_hash_table (info); 4715214634Sdim 4716214634Sdim if ((osec->flags & SEC_READONLY) == 0 4717214634Sdim && htab->data_index_section != NULL) 4718214634Sdim osec = htab->data_index_section; 4719214634Sdim else 4720214634Sdim osec = htab->text_index_section; 4721214634Sdim symbol = elf_section_data (osec)->dynindx; 4722214634Sdim } 4723214082Sdim BFD_ASSERT (symbol != 0); 4724214082Sdim } 4725214082Sdim else 4726214082Sdim /* On SVR4-ish systems, the dynamic loader cannot 4727214082Sdim relocate the text and data segments independently, 4728214082Sdim so the symbol does not matter. */ 4729214082Sdim symbol = 0; 4730214082Sdim outrel.r_info = ELF32_R_INFO (symbol, R_ARM_RELATIVE); 4731214082Sdim if (globals->use_rel) 4732214082Sdim relocate = TRUE; 4733214082Sdim else 4734214082Sdim outrel.r_addend += value; 4735214082Sdim } 4736214082Sdim 4737214082Sdim loc = sreloc->contents; 4738214082Sdim loc += sreloc->reloc_count++ * RELOC_SIZE (globals); 4739214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 4740214082Sdim 4741214082Sdim /* If this reloc is against an external symbol, we do not want to 4742214082Sdim fiddle with the addend. Otherwise, we need to include the symbol 4743214082Sdim value so that it becomes an addend for the dynamic reloc. */ 4744214082Sdim if (! relocate) 4745214082Sdim return bfd_reloc_ok; 4746214082Sdim 4747214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 4748214082Sdim contents, rel->r_offset, value, 4749214082Sdim (bfd_vma) 0); 4750214082Sdim } 4751214082Sdim else switch (r_type) 4752214082Sdim { 4753214082Sdim case R_ARM_ABS12: 4754214082Sdim return elf32_arm_abs12_reloc (input_bfd, hit_data, value + addend); 4755214082Sdim 4756214082Sdim case R_ARM_XPC25: /* Arm BLX instruction. */ 4757214082Sdim case R_ARM_CALL: 4758214082Sdim case R_ARM_JUMP24: 4759214082Sdim case R_ARM_PC24: /* Arm B/BL instruction */ 4760214082Sdim case R_ARM_PLT32: 4761214082Sdim if (r_type == R_ARM_XPC25) 4762214082Sdim { 4763214082Sdim /* Check for Arm calling Arm function. */ 4764214082Sdim /* FIXME: Should we translate the instruction into a BL 4765214082Sdim instruction instead ? */ 4766214082Sdim if (sym_flags != STT_ARM_TFUNC) 4767214082Sdim (*_bfd_error_handler) 4768214082Sdim (_("\%B: Warning: Arm BLX instruction targets Arm function '%s'."), 4769214082Sdim input_bfd, 4770214082Sdim h ? h->root.root.string : "(local)"); 4771214082Sdim } 4772214082Sdim else if (r_type != R_ARM_CALL || !globals->use_blx) 4773214082Sdim { 4774214082Sdim /* Check for Arm calling Thumb function. */ 4775214082Sdim if (sym_flags == STT_ARM_TFUNC) 4776214082Sdim { 4777214634Sdim if (elf32_arm_to_thumb_stub (info, sym_name, input_bfd, 4778214634Sdim output_bfd, input_section, 4779214634Sdim hit_data, sym_sec, rel->r_offset, 4780214634Sdim signed_addend, value, 4781214634Sdim error_message)) 4782214634Sdim return bfd_reloc_ok; 4783214634Sdim else 4784214634Sdim return bfd_reloc_dangerous; 4785214082Sdim } 4786214082Sdim } 4787214082Sdim 4788214082Sdim /* The ARM ELF ABI says that this reloc is computed as: S - P + A 4789214082Sdim where: 4790214082Sdim S is the address of the symbol in the relocation. 4791214082Sdim P is address of the instruction being relocated. 4792214082Sdim A is the addend (extracted from the instruction) in bytes. 4793214082Sdim 4794214082Sdim S is held in 'value'. 4795214082Sdim P is the base address of the section containing the 4796214082Sdim instruction plus the offset of the reloc into that 4797214082Sdim section, ie: 4798214082Sdim (input_section->output_section->vma + 4799214082Sdim input_section->output_offset + 4800214082Sdim rel->r_offset). 4801214082Sdim A is the addend, converted into bytes, ie: 4802214082Sdim (signed_addend * 4) 4803214082Sdim 4804214082Sdim Note: None of these operations have knowledge of the pipeline 4805214082Sdim size of the processor, thus it is up to the assembler to 4806214082Sdim encode this information into the addend. */ 4807214082Sdim value -= (input_section->output_section->vma 4808214082Sdim + input_section->output_offset); 4809214082Sdim value -= rel->r_offset; 4810214082Sdim if (globals->use_rel) 4811214082Sdim value += (signed_addend << howto->size); 4812214082Sdim else 4813214082Sdim /* RELA addends do not have to be adjusted by howto->size. */ 4814214082Sdim value += signed_addend; 4815214082Sdim 4816214082Sdim signed_addend = value; 4817214082Sdim signed_addend >>= howto->rightshift; 4818214082Sdim 4819214634Sdim /* A branch to an undefined weak symbol is turned into a jump to 4820214634Sdim the next instruction. */ 4821214634Sdim if (h && h->root.type == bfd_link_hash_undefweak) 4822214082Sdim { 4823214634Sdim value = (bfd_get_32 (input_bfd, hit_data) & 0xf0000000) 4824214634Sdim | 0x0affffff; 4825214634Sdim } 4826214634Sdim else 4827214634Sdim { 4828214082Sdim /* Perform a signed range check. */ 4829214082Sdim if ( signed_addend > ((bfd_signed_vma) (howto->dst_mask >> 1)) 4830214082Sdim || signed_addend < - ((bfd_signed_vma) ((howto->dst_mask + 1) >> 1))) 4831214082Sdim return bfd_reloc_overflow; 4832214082Sdim 4833214634Sdim addend = (value & 2); 4834214082Sdim 4835214634Sdim value = (signed_addend & howto->dst_mask) 4836214634Sdim | (bfd_get_32 (input_bfd, hit_data) & (~ howto->dst_mask)); 4837214082Sdim 4838214634Sdim /* Set the H bit in the BLX instruction. */ 4839214082Sdim if (sym_flags == STT_ARM_TFUNC) 4840214082Sdim { 4841214634Sdim if (addend) 4842214634Sdim value |= (1 << 24); 4843214634Sdim else 4844214634Sdim value &= ~(bfd_vma)(1 << 24); 4845214082Sdim } 4846214634Sdim if (r_type == R_ARM_CALL) 4847214634Sdim { 4848214634Sdim /* Select the correct instruction (BL or BLX). */ 4849214634Sdim if (sym_flags == STT_ARM_TFUNC) 4850214634Sdim value |= (1 << 28); 4851214634Sdim else 4852214634Sdim { 4853214634Sdim value &= ~(bfd_vma)(1 << 28); 4854214634Sdim value |= (1 << 24); 4855214634Sdim } 4856214634Sdim } 4857214082Sdim } 4858214082Sdim break; 4859214082Sdim 4860214082Sdim case R_ARM_ABS32: 4861214082Sdim value += addend; 4862214082Sdim if (sym_flags == STT_ARM_TFUNC) 4863214082Sdim value |= 1; 4864214082Sdim break; 4865214082Sdim 4866214634Sdim case R_ARM_ABS32_NOI: 4867214634Sdim value += addend; 4868214634Sdim break; 4869214634Sdim 4870214082Sdim case R_ARM_REL32: 4871214082Sdim value += addend; 4872214082Sdim if (sym_flags == STT_ARM_TFUNC) 4873214082Sdim value |= 1; 4874214082Sdim value -= (input_section->output_section->vma 4875214082Sdim + input_section->output_offset + rel->r_offset); 4876214082Sdim break; 4877214082Sdim 4878214634Sdim case R_ARM_REL32_NOI: 4879214634Sdim value += addend; 4880214634Sdim value -= (input_section->output_section->vma 4881214634Sdim + input_section->output_offset + rel->r_offset); 4882214634Sdim break; 4883214634Sdim 4884214082Sdim case R_ARM_PREL31: 4885214082Sdim value -= (input_section->output_section->vma 4886214082Sdim + input_section->output_offset + rel->r_offset); 4887214082Sdim value += signed_addend; 4888214082Sdim if (! h || h->root.type != bfd_link_hash_undefweak) 4889214082Sdim { 4890214082Sdim /* Check for overflow */ 4891214082Sdim if ((value ^ (value >> 1)) & (1 << 30)) 4892214082Sdim return bfd_reloc_overflow; 4893214082Sdim } 4894214082Sdim value &= 0x7fffffff; 4895214082Sdim value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000); 4896214082Sdim if (sym_flags == STT_ARM_TFUNC) 4897214082Sdim value |= 1; 4898214082Sdim break; 4899214082Sdim } 4900214082Sdim 4901214082Sdim bfd_put_32 (input_bfd, value, hit_data); 4902214082Sdim return bfd_reloc_ok; 4903214082Sdim 4904214082Sdim case R_ARM_ABS8: 4905214082Sdim value += addend; 4906214082Sdim if ((long) value > 0x7f || (long) value < -0x80) 4907214082Sdim return bfd_reloc_overflow; 4908214082Sdim 4909214082Sdim bfd_put_8 (input_bfd, value, hit_data); 4910214082Sdim return bfd_reloc_ok; 4911214082Sdim 4912214082Sdim case R_ARM_ABS16: 4913214082Sdim value += addend; 4914214082Sdim 4915214082Sdim if ((long) value > 0x7fff || (long) value < -0x8000) 4916214082Sdim return bfd_reloc_overflow; 4917214082Sdim 4918214082Sdim bfd_put_16 (input_bfd, value, hit_data); 4919214082Sdim return bfd_reloc_ok; 4920214082Sdim 4921214082Sdim case R_ARM_THM_ABS5: 4922214082Sdim /* Support ldr and str instructions for the thumb. */ 4923214082Sdim if (globals->use_rel) 4924214082Sdim { 4925214082Sdim /* Need to refetch addend. */ 4926214082Sdim addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask; 4927214082Sdim /* ??? Need to determine shift amount from operand size. */ 4928214082Sdim addend >>= howto->rightshift; 4929214082Sdim } 4930214082Sdim value += addend; 4931214082Sdim 4932214082Sdim /* ??? Isn't value unsigned? */ 4933214082Sdim if ((long) value > 0x1f || (long) value < -0x10) 4934214082Sdim return bfd_reloc_overflow; 4935214082Sdim 4936214082Sdim /* ??? Value needs to be properly shifted into place first. */ 4937214082Sdim value |= bfd_get_16 (input_bfd, hit_data) & 0xf83f; 4938214082Sdim bfd_put_16 (input_bfd, value, hit_data); 4939214082Sdim return bfd_reloc_ok; 4940214082Sdim 4941214634Sdim case R_ARM_THM_ALU_PREL_11_0: 4942214634Sdim /* Corresponds to: addw.w reg, pc, #offset (and similarly for subw). */ 4943214634Sdim { 4944214634Sdim bfd_vma insn; 4945214634Sdim bfd_signed_vma relocation; 4946214634Sdim 4947214634Sdim insn = (bfd_get_16 (input_bfd, hit_data) << 16) 4948214634Sdim | bfd_get_16 (input_bfd, hit_data + 2); 4949214634Sdim 4950214634Sdim if (globals->use_rel) 4951214634Sdim { 4952214634Sdim signed_addend = (insn & 0xff) | ((insn & 0x7000) >> 4) 4953214634Sdim | ((insn & (1 << 26)) >> 15); 4954214634Sdim if (insn & 0xf00000) 4955214634Sdim signed_addend = -signed_addend; 4956214634Sdim } 4957214634Sdim 4958214634Sdim relocation = value + signed_addend; 4959214634Sdim relocation -= (input_section->output_section->vma 4960214634Sdim + input_section->output_offset 4961214634Sdim + rel->r_offset); 4962214634Sdim 4963214634Sdim value = abs (relocation); 4964214634Sdim 4965214634Sdim if (value >= 0x1000) 4966214634Sdim return bfd_reloc_overflow; 4967214634Sdim 4968214634Sdim insn = (insn & 0xfb0f8f00) | (value & 0xff) 4969214634Sdim | ((value & 0x700) << 4) 4970214634Sdim | ((value & 0x800) << 15); 4971214634Sdim if (relocation < 0) 4972214634Sdim insn |= 0xa00000; 4973214634Sdim 4974214634Sdim bfd_put_16 (input_bfd, insn >> 16, hit_data); 4975214634Sdim bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2); 4976214634Sdim 4977214634Sdim return bfd_reloc_ok; 4978214634Sdim } 4979214634Sdim 4980214634Sdim case R_ARM_THM_PC12: 4981214634Sdim /* Corresponds to: ldr.w reg, [pc, #offset]. */ 4982214634Sdim { 4983214634Sdim bfd_vma insn; 4984214634Sdim bfd_signed_vma relocation; 4985214634Sdim 4986214634Sdim insn = (bfd_get_16 (input_bfd, hit_data) << 16) 4987214634Sdim | bfd_get_16 (input_bfd, hit_data + 2); 4988214634Sdim 4989214634Sdim if (globals->use_rel) 4990214634Sdim { 4991214634Sdim signed_addend = insn & 0xfff; 4992214634Sdim if (!(insn & (1 << 23))) 4993214634Sdim signed_addend = -signed_addend; 4994214634Sdim } 4995214634Sdim 4996214634Sdim relocation = value + signed_addend; 4997214634Sdim relocation -= (input_section->output_section->vma 4998214634Sdim + input_section->output_offset 4999214634Sdim + rel->r_offset); 5000214634Sdim 5001214634Sdim value = abs (relocation); 5002214634Sdim 5003214634Sdim if (value >= 0x1000) 5004214634Sdim return bfd_reloc_overflow; 5005214634Sdim 5006214634Sdim insn = (insn & 0xff7ff000) | value; 5007214634Sdim if (relocation >= 0) 5008214634Sdim insn |= (1 << 23); 5009214634Sdim 5010214634Sdim bfd_put_16 (input_bfd, insn >> 16, hit_data); 5011214634Sdim bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2); 5012214634Sdim 5013214634Sdim return bfd_reloc_ok; 5014214634Sdim } 5015214634Sdim 5016214082Sdim case R_ARM_THM_XPC22: 5017214082Sdim case R_ARM_THM_CALL: 5018214082Sdim /* Thumb BL (branch long instruction). */ 5019214082Sdim { 5020214082Sdim bfd_vma relocation; 5021214634Sdim bfd_vma reloc_sign; 5022214082Sdim bfd_boolean overflow = FALSE; 5023214082Sdim bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data); 5024214082Sdim bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2); 5025214634Sdim bfd_signed_vma reloc_signed_max; 5026214634Sdim bfd_signed_vma reloc_signed_min; 5027214082Sdim bfd_vma check; 5028214082Sdim bfd_signed_vma signed_check; 5029214634Sdim int bitsize; 5030214634Sdim int thumb2 = using_thumb2 (globals); 5031214082Sdim 5032214634Sdim /* A branch to an undefined weak symbol is turned into a jump to 5033214634Sdim the next instruction. */ 5034214634Sdim if (h && h->root.type == bfd_link_hash_undefweak) 5035214634Sdim { 5036214634Sdim bfd_put_16 (input_bfd, 0xe000, hit_data); 5037214634Sdim bfd_put_16 (input_bfd, 0xbf00, hit_data + 2); 5038214634Sdim return bfd_reloc_ok; 5039214634Sdim } 5040214634Sdim 5041214634Sdim /* Fetch the addend. We use the Thumb-2 encoding (backwards compatible 5042214634Sdim with Thumb-1) involving the J1 and J2 bits. */ 5043214082Sdim if (globals->use_rel) 5044214082Sdim { 5045214634Sdim bfd_vma s = (upper_insn & (1 << 10)) >> 10; 5046214634Sdim bfd_vma upper = upper_insn & 0x3ff; 5047214634Sdim bfd_vma lower = lower_insn & 0x7ff; 5048214634Sdim bfd_vma j1 = (lower_insn & (1 << 13)) >> 13; 5049214634Sdim bfd_vma j2 = (lower_insn & (1 << 11)) >> 11; 5050214634Sdim bfd_vma i1 = j1 ^ s ? 0 : 1; 5051214634Sdim bfd_vma i2 = j2 ^ s ? 0 : 1; 5052214634Sdim 5053214634Sdim addend = (i1 << 23) | (i2 << 22) | (upper << 12) | (lower << 1); 5054214634Sdim /* Sign extend. */ 5055214634Sdim addend = (addend | ((s ? 0 : 1) << 24)) - (1 << 24); 5056214634Sdim 5057214082Sdim signed_addend = addend; 5058214082Sdim } 5059214082Sdim 5060214082Sdim if (r_type == R_ARM_THM_XPC22) 5061214082Sdim { 5062214082Sdim /* Check for Thumb to Thumb call. */ 5063214082Sdim /* FIXME: Should we translate the instruction into a BL 5064214082Sdim instruction instead ? */ 5065214082Sdim if (sym_flags == STT_ARM_TFUNC) 5066214082Sdim (*_bfd_error_handler) 5067214082Sdim (_("%B: Warning: Thumb BLX instruction targets thumb function '%s'."), 5068214082Sdim input_bfd, 5069214082Sdim h ? h->root.root.string : "(local)"); 5070214082Sdim } 5071214082Sdim else 5072214082Sdim { 5073214082Sdim /* If it is not a call to Thumb, assume call to Arm. 5074214082Sdim If it is a call relative to a section name, then it is not a 5075214082Sdim function call at all, but rather a long jump. Calls through 5076214082Sdim the PLT do not require stubs. */ 5077214082Sdim if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION 5078214082Sdim && (h == NULL || splt == NULL 5079214082Sdim || h->plt.offset == (bfd_vma) -1)) 5080214082Sdim { 5081214082Sdim if (globals->use_blx) 5082214082Sdim { 5083214082Sdim /* Convert BL to BLX. */ 5084214082Sdim lower_insn = (lower_insn & ~0x1000) | 0x0800; 5085214082Sdim } 5086214082Sdim else if (elf32_thumb_to_arm_stub 5087214082Sdim (info, sym_name, input_bfd, output_bfd, input_section, 5088214634Sdim hit_data, sym_sec, rel->r_offset, signed_addend, value, 5089214634Sdim error_message)) 5090214082Sdim return bfd_reloc_ok; 5091214082Sdim else 5092214082Sdim return bfd_reloc_dangerous; 5093214082Sdim } 5094214082Sdim else if (sym_flags == STT_ARM_TFUNC && globals->use_blx) 5095214082Sdim { 5096214082Sdim /* Make sure this is a BL. */ 5097214082Sdim lower_insn |= 0x1800; 5098214082Sdim } 5099214082Sdim } 5100214082Sdim 5101214082Sdim /* Handle calls via the PLT. */ 5102214082Sdim if (h != NULL && splt != NULL && h->plt.offset != (bfd_vma) -1) 5103214082Sdim { 5104214082Sdim value = (splt->output_section->vma 5105214082Sdim + splt->output_offset 5106214082Sdim + h->plt.offset); 5107214082Sdim if (globals->use_blx) 5108214082Sdim { 5109214082Sdim /* If the Thumb BLX instruction is available, convert the 5110214082Sdim BL to a BLX instruction to call the ARM-mode PLT entry. */ 5111214082Sdim lower_insn = (lower_insn & ~0x1000) | 0x0800; 5112214082Sdim } 5113214082Sdim else 5114214082Sdim /* Target the Thumb stub before the ARM PLT entry. */ 5115214082Sdim value -= PLT_THUMB_STUB_SIZE; 5116214082Sdim *unresolved_reloc_p = FALSE; 5117214082Sdim } 5118214082Sdim 5119214082Sdim relocation = value + signed_addend; 5120214082Sdim 5121214082Sdim relocation -= (input_section->output_section->vma 5122214082Sdim + input_section->output_offset 5123214082Sdim + rel->r_offset); 5124214082Sdim 5125214082Sdim check = relocation >> howto->rightshift; 5126214082Sdim 5127214082Sdim /* If this is a signed value, the rightshift just dropped 5128214082Sdim leading 1 bits (assuming twos complement). */ 5129214082Sdim if ((bfd_signed_vma) relocation >= 0) 5130214082Sdim signed_check = check; 5131214082Sdim else 5132214082Sdim signed_check = check | ~((bfd_vma) -1 >> howto->rightshift); 5133214082Sdim 5134214634Sdim /* Calculate the permissable maximum and minimum values for 5135214634Sdim this relocation according to whether we're relocating for 5136214634Sdim Thumb-2 or not. */ 5137214634Sdim bitsize = howto->bitsize; 5138214634Sdim if (!thumb2) 5139214634Sdim bitsize -= 2; 5140214634Sdim reloc_signed_max = ((1 << (bitsize - 1)) - 1) >> howto->rightshift; 5141214634Sdim reloc_signed_min = ~reloc_signed_max; 5142214634Sdim 5143214082Sdim /* Assumes two's complement. */ 5144214082Sdim if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) 5145214082Sdim overflow = TRUE; 5146214082Sdim 5147214082Sdim if ((lower_insn & 0x1800) == 0x0800) 5148214082Sdim /* For a BLX instruction, make sure that the relocation is rounded up 5149214082Sdim to a word boundary. This follows the semantics of the instruction 5150214082Sdim which specifies that bit 1 of the target address will come from bit 5151214082Sdim 1 of the base address. */ 5152214082Sdim relocation = (relocation + 2) & ~ 3; 5153214082Sdim 5154214634Sdim /* Put RELOCATION back into the insn. Assumes two's complement. 5155214634Sdim We use the Thumb-2 encoding, which is safe even if dealing with 5156214634Sdim a Thumb-1 instruction by virtue of our overflow check above. */ 5157214634Sdim reloc_sign = (signed_check < 0) ? 1 : 0; 5158214634Sdim upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) 5159214634Sdim | ((relocation >> 12) & 0x3ff) 5160214634Sdim | (reloc_sign << 10); 5161214634Sdim lower_insn = (lower_insn & ~(bfd_vma) 0x2fff) 5162214634Sdim | (((!((relocation >> 23) & 1)) ^ reloc_sign) << 13) 5163214634Sdim | (((!((relocation >> 22) & 1)) ^ reloc_sign) << 11) 5164214634Sdim | ((relocation >> 1) & 0x7ff); 5165214082Sdim 5166214082Sdim /* Put the relocated value back in the object file: */ 5167214082Sdim bfd_put_16 (input_bfd, upper_insn, hit_data); 5168214082Sdim bfd_put_16 (input_bfd, lower_insn, hit_data + 2); 5169214082Sdim 5170214082Sdim return (overflow ? bfd_reloc_overflow : bfd_reloc_ok); 5171214082Sdim } 5172214082Sdim break; 5173214082Sdim 5174214082Sdim case R_ARM_THM_JUMP24: 5175214082Sdim /* Thumb32 unconditional branch instruction. */ 5176214082Sdim { 5177214082Sdim bfd_vma relocation; 5178214082Sdim bfd_boolean overflow = FALSE; 5179214082Sdim bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data); 5180214082Sdim bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2); 5181214082Sdim bfd_signed_vma reloc_signed_max = ((1 << (howto->bitsize - 1)) - 1) >> howto->rightshift; 5182214082Sdim bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; 5183214082Sdim bfd_vma check; 5184214082Sdim bfd_signed_vma signed_check; 5185214082Sdim 5186214082Sdim /* Need to refetch the addend, reconstruct the top three bits, and glue the 5187214082Sdim two pieces together. */ 5188214082Sdim if (globals->use_rel) 5189214082Sdim { 5190214082Sdim bfd_vma S = (upper_insn & 0x0400) >> 10; 5191214082Sdim bfd_vma hi = (upper_insn & 0x03ff); 5192214082Sdim bfd_vma I1 = (lower_insn & 0x2000) >> 13; 5193214082Sdim bfd_vma I2 = (lower_insn & 0x0800) >> 11; 5194214082Sdim bfd_vma lo = (lower_insn & 0x07ff); 5195214082Sdim 5196214082Sdim I1 = !(I1 ^ S); 5197214082Sdim I2 = !(I2 ^ S); 5198214082Sdim S = !S; 5199214082Sdim 5200214082Sdim signed_addend = (S << 24) | (I1 << 23) | (I2 << 22) | (hi << 12) | (lo << 1); 5201214082Sdim signed_addend -= (1 << 24); /* Sign extend. */ 5202214082Sdim } 5203214082Sdim 5204214082Sdim /* ??? Should handle interworking? GCC might someday try to 5205214082Sdim use this for tail calls. */ 5206214082Sdim 5207214082Sdim relocation = value + signed_addend; 5208214082Sdim relocation -= (input_section->output_section->vma 5209214082Sdim + input_section->output_offset 5210214082Sdim + rel->r_offset); 5211214082Sdim 5212214082Sdim check = relocation >> howto->rightshift; 5213214082Sdim 5214214082Sdim /* If this is a signed value, the rightshift just dropped 5215214082Sdim leading 1 bits (assuming twos complement). */ 5216214082Sdim if ((bfd_signed_vma) relocation >= 0) 5217214082Sdim signed_check = check; 5218214082Sdim else 5219214082Sdim signed_check = check | ~((bfd_vma) -1 >> howto->rightshift); 5220214082Sdim 5221214082Sdim /* Assumes two's complement. */ 5222214082Sdim if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) 5223214082Sdim overflow = TRUE; 5224214082Sdim 5225214082Sdim /* Put RELOCATION back into the insn. */ 5226214082Sdim { 5227214082Sdim bfd_vma S = (relocation & 0x01000000) >> 24; 5228214082Sdim bfd_vma I1 = (relocation & 0x00800000) >> 23; 5229214082Sdim bfd_vma I2 = (relocation & 0x00400000) >> 22; 5230214082Sdim bfd_vma hi = (relocation & 0x003ff000) >> 12; 5231214082Sdim bfd_vma lo = (relocation & 0x00000ffe) >> 1; 5232214082Sdim 5233214082Sdim I1 = !(I1 ^ S); 5234214082Sdim I2 = !(I2 ^ S); 5235214082Sdim 5236214082Sdim upper_insn = (upper_insn & (bfd_vma) 0xf800) | (S << 10) | hi; 5237214082Sdim lower_insn = (lower_insn & (bfd_vma) 0xd000) | (I1 << 13) | (I2 << 11) | lo; 5238214082Sdim } 5239214082Sdim 5240214082Sdim /* Put the relocated value back in the object file: */ 5241214082Sdim bfd_put_16 (input_bfd, upper_insn, hit_data); 5242214082Sdim bfd_put_16 (input_bfd, lower_insn, hit_data + 2); 5243214082Sdim 5244214082Sdim return (overflow ? bfd_reloc_overflow : bfd_reloc_ok); 5245214082Sdim } 5246214082Sdim 5247214082Sdim case R_ARM_THM_JUMP19: 5248214082Sdim /* Thumb32 conditional branch instruction. */ 5249214082Sdim { 5250214082Sdim bfd_vma relocation; 5251214082Sdim bfd_boolean overflow = FALSE; 5252214082Sdim bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data); 5253214082Sdim bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2); 5254214634Sdim bfd_signed_vma reloc_signed_max = 0xffffe; 5255214634Sdim bfd_signed_vma reloc_signed_min = -0x100000; 5256214082Sdim bfd_signed_vma signed_check; 5257214082Sdim 5258214082Sdim /* Need to refetch the addend, reconstruct the top three bits, 5259214082Sdim and squish the two 11 bit pieces together. */ 5260214082Sdim if (globals->use_rel) 5261214082Sdim { 5262214082Sdim bfd_vma S = (upper_insn & 0x0400) >> 10; 5263214634Sdim bfd_vma upper = (upper_insn & 0x003f); 5264214082Sdim bfd_vma J1 = (lower_insn & 0x2000) >> 13; 5265214082Sdim bfd_vma J2 = (lower_insn & 0x0800) >> 11; 5266214082Sdim bfd_vma lower = (lower_insn & 0x07ff); 5267214082Sdim 5268214634Sdim upper |= J1 << 6; 5269214634Sdim upper |= J2 << 7; 5270214634Sdim upper |= (!S) << 8; 5271214082Sdim upper -= 0x0100; /* Sign extend. */ 5272214082Sdim 5273214082Sdim addend = (upper << 12) | (lower << 1); 5274214082Sdim signed_addend = addend; 5275214082Sdim } 5276214082Sdim 5277214082Sdim /* ??? Should handle interworking? GCC might someday try to 5278214082Sdim use this for tail calls. */ 5279214082Sdim 5280214082Sdim relocation = value + signed_addend; 5281214082Sdim relocation -= (input_section->output_section->vma 5282214082Sdim + input_section->output_offset 5283214082Sdim + rel->r_offset); 5284214634Sdim signed_check = (bfd_signed_vma) relocation; 5285214082Sdim 5286214082Sdim if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) 5287214082Sdim overflow = TRUE; 5288214082Sdim 5289214082Sdim /* Put RELOCATION back into the insn. */ 5290214082Sdim { 5291214082Sdim bfd_vma S = (relocation & 0x00100000) >> 20; 5292214082Sdim bfd_vma J2 = (relocation & 0x00080000) >> 19; 5293214082Sdim bfd_vma J1 = (relocation & 0x00040000) >> 18; 5294214082Sdim bfd_vma hi = (relocation & 0x0003f000) >> 12; 5295214082Sdim bfd_vma lo = (relocation & 0x00000ffe) >> 1; 5296214082Sdim 5297214634Sdim upper_insn = (upper_insn & 0xfbc0) | (S << 10) | hi; 5298214082Sdim lower_insn = (lower_insn & 0xd000) | (J1 << 13) | (J2 << 11) | lo; 5299214082Sdim } 5300214082Sdim 5301214082Sdim /* Put the relocated value back in the object file: */ 5302214082Sdim bfd_put_16 (input_bfd, upper_insn, hit_data); 5303214082Sdim bfd_put_16 (input_bfd, lower_insn, hit_data + 2); 5304214082Sdim 5305214082Sdim return (overflow ? bfd_reloc_overflow : bfd_reloc_ok); 5306214082Sdim } 5307214082Sdim 5308214082Sdim case R_ARM_THM_JUMP11: 5309214082Sdim case R_ARM_THM_JUMP8: 5310214082Sdim case R_ARM_THM_JUMP6: 5311214082Sdim /* Thumb B (branch) instruction). */ 5312214082Sdim { 5313214082Sdim bfd_signed_vma relocation; 5314214082Sdim bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; 5315214082Sdim bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; 5316214082Sdim bfd_signed_vma signed_check; 5317214082Sdim 5318214082Sdim /* CZB cannot jump backward. */ 5319214082Sdim if (r_type == R_ARM_THM_JUMP6) 5320214082Sdim reloc_signed_min = 0; 5321214082Sdim 5322214082Sdim if (globals->use_rel) 5323214082Sdim { 5324214082Sdim /* Need to refetch addend. */ 5325214082Sdim addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask; 5326214082Sdim if (addend & ((howto->src_mask + 1) >> 1)) 5327214082Sdim { 5328214082Sdim signed_addend = -1; 5329214082Sdim signed_addend &= ~ howto->src_mask; 5330214082Sdim signed_addend |= addend; 5331214082Sdim } 5332214082Sdim else 5333214082Sdim signed_addend = addend; 5334214082Sdim /* The value in the insn has been right shifted. We need to 5335214082Sdim undo this, so that we can perform the address calculation 5336214082Sdim in terms of bytes. */ 5337214082Sdim signed_addend <<= howto->rightshift; 5338214082Sdim } 5339214082Sdim relocation = value + signed_addend; 5340214082Sdim 5341214082Sdim relocation -= (input_section->output_section->vma 5342214082Sdim + input_section->output_offset 5343214082Sdim + rel->r_offset); 5344214082Sdim 5345214082Sdim relocation >>= howto->rightshift; 5346214082Sdim signed_check = relocation; 5347214082Sdim 5348214082Sdim if (r_type == R_ARM_THM_JUMP6) 5349214082Sdim relocation = ((relocation & 0x0020) << 4) | ((relocation & 0x001f) << 3); 5350214082Sdim else 5351214082Sdim relocation &= howto->dst_mask; 5352214082Sdim relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask)); 5353214082Sdim 5354214082Sdim bfd_put_16 (input_bfd, relocation, hit_data); 5355214082Sdim 5356214082Sdim /* Assumes two's complement. */ 5357214082Sdim if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) 5358214082Sdim return bfd_reloc_overflow; 5359214082Sdim 5360214082Sdim return bfd_reloc_ok; 5361214082Sdim } 5362214082Sdim 5363214082Sdim case R_ARM_ALU_PCREL7_0: 5364214082Sdim case R_ARM_ALU_PCREL15_8: 5365214082Sdim case R_ARM_ALU_PCREL23_15: 5366214082Sdim { 5367214082Sdim bfd_vma insn; 5368214082Sdim bfd_vma relocation; 5369214082Sdim 5370214082Sdim insn = bfd_get_32 (input_bfd, hit_data); 5371214082Sdim if (globals->use_rel) 5372214082Sdim { 5373214082Sdim /* Extract the addend. */ 5374214082Sdim addend = (insn & 0xff) << ((insn & 0xf00) >> 7); 5375214082Sdim signed_addend = addend; 5376214082Sdim } 5377214082Sdim relocation = value + signed_addend; 5378214082Sdim 5379214082Sdim relocation -= (input_section->output_section->vma 5380214082Sdim + input_section->output_offset 5381214082Sdim + rel->r_offset); 5382214082Sdim insn = (insn & ~0xfff) 5383214082Sdim | ((howto->bitpos << 7) & 0xf00) 5384214082Sdim | ((relocation >> howto->bitpos) & 0xff); 5385214082Sdim bfd_put_32 (input_bfd, value, hit_data); 5386214082Sdim } 5387214082Sdim return bfd_reloc_ok; 5388214082Sdim 5389214082Sdim case R_ARM_GNU_VTINHERIT: 5390214082Sdim case R_ARM_GNU_VTENTRY: 5391214082Sdim return bfd_reloc_ok; 5392214082Sdim 5393214082Sdim case R_ARM_GOTOFF32: 5394214082Sdim /* Relocation is relative to the start of the 5395214082Sdim global offset table. */ 5396214082Sdim 5397214082Sdim BFD_ASSERT (sgot != NULL); 5398214082Sdim if (sgot == NULL) 5399214082Sdim return bfd_reloc_notsupported; 5400214082Sdim 5401214082Sdim /* If we are addressing a Thumb function, we need to adjust the 5402214082Sdim address by one, so that attempts to call the function pointer will 5403214082Sdim correctly interpret it as Thumb code. */ 5404214082Sdim if (sym_flags == STT_ARM_TFUNC) 5405214082Sdim value += 1; 5406214082Sdim 5407214082Sdim /* Note that sgot->output_offset is not involved in this 5408214082Sdim calculation. We always want the start of .got. If we 5409214082Sdim define _GLOBAL_OFFSET_TABLE in a different way, as is 5410214082Sdim permitted by the ABI, we might have to change this 5411214082Sdim calculation. */ 5412214082Sdim value -= sgot->output_section->vma; 5413214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5414214082Sdim contents, rel->r_offset, value, 5415214082Sdim rel->r_addend); 5416214082Sdim 5417214082Sdim case R_ARM_GOTPC: 5418214082Sdim /* Use global offset table as symbol value. */ 5419214082Sdim BFD_ASSERT (sgot != NULL); 5420214082Sdim 5421214082Sdim if (sgot == NULL) 5422214082Sdim return bfd_reloc_notsupported; 5423214082Sdim 5424214082Sdim *unresolved_reloc_p = FALSE; 5425214082Sdim value = sgot->output_section->vma; 5426214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5427214082Sdim contents, rel->r_offset, value, 5428214082Sdim rel->r_addend); 5429214082Sdim 5430214082Sdim case R_ARM_GOT32: 5431214082Sdim case R_ARM_GOT_PREL: 5432214082Sdim /* Relocation is to the entry for this symbol in the 5433214082Sdim global offset table. */ 5434214082Sdim if (sgot == NULL) 5435214082Sdim return bfd_reloc_notsupported; 5436214082Sdim 5437214082Sdim if (h != NULL) 5438214082Sdim { 5439214082Sdim bfd_vma off; 5440214082Sdim bfd_boolean dyn; 5441214082Sdim 5442214082Sdim off = h->got.offset; 5443214082Sdim BFD_ASSERT (off != (bfd_vma) -1); 5444214082Sdim dyn = globals->root.dynamic_sections_created; 5445214082Sdim 5446214082Sdim if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 5447214082Sdim || (info->shared 5448214082Sdim && SYMBOL_REFERENCES_LOCAL (info, h)) 5449214082Sdim || (ELF_ST_VISIBILITY (h->other) 5450214082Sdim && h->root.type == bfd_link_hash_undefweak)) 5451214082Sdim { 5452214082Sdim /* This is actually a static link, or it is a -Bsymbolic link 5453214082Sdim and the symbol is defined locally. We must initialize this 5454214082Sdim entry in the global offset table. Since the offset must 5455214082Sdim always be a multiple of 4, we use the least significant bit 5456214082Sdim to record whether we have initialized it already. 5457214082Sdim 5458214082Sdim When doing a dynamic link, we create a .rel(a).got relocation 5459214082Sdim entry to initialize the value. This is done in the 5460214082Sdim finish_dynamic_symbol routine. */ 5461214082Sdim if ((off & 1) != 0) 5462214082Sdim off &= ~1; 5463214082Sdim else 5464214082Sdim { 5465214082Sdim /* If we are addressing a Thumb function, we need to 5466214082Sdim adjust the address by one, so that attempts to 5467214082Sdim call the function pointer will correctly 5468214082Sdim interpret it as Thumb code. */ 5469214082Sdim if (sym_flags == STT_ARM_TFUNC) 5470214082Sdim value |= 1; 5471214082Sdim 5472214082Sdim bfd_put_32 (output_bfd, value, sgot->contents + off); 5473214082Sdim h->got.offset |= 1; 5474214082Sdim } 5475214082Sdim } 5476214082Sdim else 5477214082Sdim *unresolved_reloc_p = FALSE; 5478214082Sdim 5479214082Sdim value = sgot->output_offset + off; 5480214082Sdim } 5481214082Sdim else 5482214082Sdim { 5483214082Sdim bfd_vma off; 5484214082Sdim 5485214082Sdim BFD_ASSERT (local_got_offsets != NULL && 5486214082Sdim local_got_offsets[r_symndx] != (bfd_vma) -1); 5487214082Sdim 5488214082Sdim off = local_got_offsets[r_symndx]; 5489214082Sdim 5490214082Sdim /* The offset must always be a multiple of 4. We use the 5491214082Sdim least significant bit to record whether we have already 5492214082Sdim generated the necessary reloc. */ 5493214082Sdim if ((off & 1) != 0) 5494214082Sdim off &= ~1; 5495214082Sdim else 5496214082Sdim { 5497214082Sdim /* If we are addressing a Thumb function, we need to 5498214082Sdim adjust the address by one, so that attempts to 5499214082Sdim call the function pointer will correctly 5500214082Sdim interpret it as Thumb code. */ 5501214082Sdim if (sym_flags == STT_ARM_TFUNC) 5502214082Sdim value |= 1; 5503214082Sdim 5504214082Sdim if (globals->use_rel) 5505214082Sdim bfd_put_32 (output_bfd, value, sgot->contents + off); 5506214082Sdim 5507214082Sdim if (info->shared) 5508214082Sdim { 5509214082Sdim asection * srelgot; 5510214082Sdim Elf_Internal_Rela outrel; 5511214082Sdim bfd_byte *loc; 5512214082Sdim 5513214082Sdim srelgot = (bfd_get_section_by_name 5514214082Sdim (dynobj, RELOC_SECTION (globals, ".got"))); 5515214082Sdim BFD_ASSERT (srelgot != NULL); 5516214082Sdim 5517214082Sdim outrel.r_addend = addend + value; 5518214082Sdim outrel.r_offset = (sgot->output_section->vma 5519214082Sdim + sgot->output_offset 5520214082Sdim + off); 5521214082Sdim outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); 5522214082Sdim loc = srelgot->contents; 5523214082Sdim loc += srelgot->reloc_count++ * RELOC_SIZE (globals); 5524214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 5525214082Sdim } 5526214082Sdim 5527214082Sdim local_got_offsets[r_symndx] |= 1; 5528214082Sdim } 5529214082Sdim 5530214082Sdim value = sgot->output_offset + off; 5531214082Sdim } 5532214082Sdim if (r_type != R_ARM_GOT32) 5533214082Sdim value += sgot->output_section->vma; 5534214082Sdim 5535214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5536214082Sdim contents, rel->r_offset, value, 5537214082Sdim rel->r_addend); 5538214082Sdim 5539214082Sdim case R_ARM_TLS_LDO32: 5540214082Sdim value = value - dtpoff_base (info); 5541214082Sdim 5542214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5543214082Sdim contents, rel->r_offset, value, 5544214082Sdim rel->r_addend); 5545214082Sdim 5546214082Sdim case R_ARM_TLS_LDM32: 5547214082Sdim { 5548214082Sdim bfd_vma off; 5549214082Sdim 5550214082Sdim if (globals->sgot == NULL) 5551214082Sdim abort (); 5552214082Sdim 5553214082Sdim off = globals->tls_ldm_got.offset; 5554214082Sdim 5555214082Sdim if ((off & 1) != 0) 5556214082Sdim off &= ~1; 5557214082Sdim else 5558214082Sdim { 5559214082Sdim /* If we don't know the module number, create a relocation 5560214082Sdim for it. */ 5561214082Sdim if (info->shared) 5562214082Sdim { 5563214082Sdim Elf_Internal_Rela outrel; 5564214082Sdim bfd_byte *loc; 5565214082Sdim 5566214082Sdim if (globals->srelgot == NULL) 5567214082Sdim abort (); 5568214082Sdim 5569214082Sdim outrel.r_addend = 0; 5570214082Sdim outrel.r_offset = (globals->sgot->output_section->vma 5571214082Sdim + globals->sgot->output_offset + off); 5572214082Sdim outrel.r_info = ELF32_R_INFO (0, R_ARM_TLS_DTPMOD32); 5573214082Sdim 5574214082Sdim if (globals->use_rel) 5575214082Sdim bfd_put_32 (output_bfd, outrel.r_addend, 5576214082Sdim globals->sgot->contents + off); 5577214082Sdim 5578214082Sdim loc = globals->srelgot->contents; 5579214082Sdim loc += globals->srelgot->reloc_count++ * RELOC_SIZE (globals); 5580214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 5581214082Sdim } 5582214082Sdim else 5583214082Sdim bfd_put_32 (output_bfd, 1, globals->sgot->contents + off); 5584214082Sdim 5585214082Sdim globals->tls_ldm_got.offset |= 1; 5586214082Sdim } 5587214082Sdim 5588214082Sdim value = globals->sgot->output_section->vma + globals->sgot->output_offset + off 5589214082Sdim - (input_section->output_section->vma + input_section->output_offset + rel->r_offset); 5590214082Sdim 5591214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5592214082Sdim contents, rel->r_offset, value, 5593214082Sdim rel->r_addend); 5594214082Sdim } 5595214082Sdim 5596214082Sdim case R_ARM_TLS_GD32: 5597214082Sdim case R_ARM_TLS_IE32: 5598214082Sdim { 5599214082Sdim bfd_vma off; 5600214082Sdim int indx; 5601214082Sdim char tls_type; 5602214082Sdim 5603214082Sdim if (globals->sgot == NULL) 5604214082Sdim abort (); 5605214082Sdim 5606214082Sdim indx = 0; 5607214082Sdim if (h != NULL) 5608214082Sdim { 5609214082Sdim bfd_boolean dyn; 5610214082Sdim dyn = globals->root.dynamic_sections_created; 5611214082Sdim if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 5612214082Sdim && (!info->shared 5613214082Sdim || !SYMBOL_REFERENCES_LOCAL (info, h))) 5614214082Sdim { 5615214082Sdim *unresolved_reloc_p = FALSE; 5616214082Sdim indx = h->dynindx; 5617214082Sdim } 5618214082Sdim off = h->got.offset; 5619214082Sdim tls_type = ((struct elf32_arm_link_hash_entry *) h)->tls_type; 5620214082Sdim } 5621214082Sdim else 5622214082Sdim { 5623214082Sdim if (local_got_offsets == NULL) 5624214082Sdim abort (); 5625214082Sdim off = local_got_offsets[r_symndx]; 5626214082Sdim tls_type = elf32_arm_local_got_tls_type (input_bfd)[r_symndx]; 5627214082Sdim } 5628214082Sdim 5629214082Sdim if (tls_type == GOT_UNKNOWN) 5630214082Sdim abort (); 5631214082Sdim 5632214082Sdim if ((off & 1) != 0) 5633214082Sdim off &= ~1; 5634214082Sdim else 5635214082Sdim { 5636214082Sdim bfd_boolean need_relocs = FALSE; 5637214082Sdim Elf_Internal_Rela outrel; 5638214082Sdim bfd_byte *loc = NULL; 5639214082Sdim int cur_off = off; 5640214082Sdim 5641214082Sdim /* The GOT entries have not been initialized yet. Do it 5642214082Sdim now, and emit any relocations. If both an IE GOT and a 5643214082Sdim GD GOT are necessary, we emit the GD first. */ 5644214082Sdim 5645214082Sdim if ((info->shared || indx != 0) 5646214082Sdim && (h == NULL 5647214082Sdim || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 5648214082Sdim || h->root.type != bfd_link_hash_undefweak)) 5649214082Sdim { 5650214082Sdim need_relocs = TRUE; 5651214082Sdim if (globals->srelgot == NULL) 5652214082Sdim abort (); 5653214082Sdim loc = globals->srelgot->contents; 5654214082Sdim loc += globals->srelgot->reloc_count * RELOC_SIZE (globals); 5655214082Sdim } 5656214082Sdim 5657214082Sdim if (tls_type & GOT_TLS_GD) 5658214082Sdim { 5659214082Sdim if (need_relocs) 5660214082Sdim { 5661214082Sdim outrel.r_addend = 0; 5662214082Sdim outrel.r_offset = (globals->sgot->output_section->vma 5663214082Sdim + globals->sgot->output_offset 5664214082Sdim + cur_off); 5665214082Sdim outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_DTPMOD32); 5666214082Sdim 5667214082Sdim if (globals->use_rel) 5668214082Sdim bfd_put_32 (output_bfd, outrel.r_addend, 5669214082Sdim globals->sgot->contents + cur_off); 5670214082Sdim 5671214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 5672214082Sdim globals->srelgot->reloc_count++; 5673214082Sdim loc += RELOC_SIZE (globals); 5674214082Sdim 5675214082Sdim if (indx == 0) 5676214082Sdim bfd_put_32 (output_bfd, value - dtpoff_base (info), 5677214082Sdim globals->sgot->contents + cur_off + 4); 5678214082Sdim else 5679214082Sdim { 5680214082Sdim outrel.r_addend = 0; 5681214082Sdim outrel.r_info = ELF32_R_INFO (indx, 5682214082Sdim R_ARM_TLS_DTPOFF32); 5683214082Sdim outrel.r_offset += 4; 5684214082Sdim 5685214082Sdim if (globals->use_rel) 5686214082Sdim bfd_put_32 (output_bfd, outrel.r_addend, 5687214082Sdim globals->sgot->contents + cur_off + 4); 5688214082Sdim 5689214082Sdim 5690214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 5691214082Sdim globals->srelgot->reloc_count++; 5692214082Sdim loc += RELOC_SIZE (globals); 5693214082Sdim } 5694214082Sdim } 5695214082Sdim else 5696214082Sdim { 5697214082Sdim /* If we are not emitting relocations for a 5698214082Sdim general dynamic reference, then we must be in a 5699214082Sdim static link or an executable link with the 5700214082Sdim symbol binding locally. Mark it as belonging 5701214082Sdim to module 1, the executable. */ 5702214082Sdim bfd_put_32 (output_bfd, 1, 5703214082Sdim globals->sgot->contents + cur_off); 5704214082Sdim bfd_put_32 (output_bfd, value - dtpoff_base (info), 5705214082Sdim globals->sgot->contents + cur_off + 4); 5706214082Sdim } 5707214082Sdim 5708214082Sdim cur_off += 8; 5709214082Sdim } 5710214082Sdim 5711214082Sdim if (tls_type & GOT_TLS_IE) 5712214082Sdim { 5713214082Sdim if (need_relocs) 5714214082Sdim { 5715214082Sdim if (indx == 0) 5716214082Sdim outrel.r_addend = value - dtpoff_base (info); 5717214082Sdim else 5718214082Sdim outrel.r_addend = 0; 5719214082Sdim outrel.r_offset = (globals->sgot->output_section->vma 5720214082Sdim + globals->sgot->output_offset 5721214082Sdim + cur_off); 5722214082Sdim outrel.r_info = ELF32_R_INFO (indx, R_ARM_TLS_TPOFF32); 5723214082Sdim 5724214082Sdim if (globals->use_rel) 5725214082Sdim bfd_put_32 (output_bfd, outrel.r_addend, 5726214082Sdim globals->sgot->contents + cur_off); 5727214082Sdim 5728214082Sdim SWAP_RELOC_OUT (globals) (output_bfd, &outrel, loc); 5729214082Sdim globals->srelgot->reloc_count++; 5730214082Sdim loc += RELOC_SIZE (globals); 5731214082Sdim } 5732214082Sdim else 5733214082Sdim bfd_put_32 (output_bfd, tpoff (info, value), 5734214082Sdim globals->sgot->contents + cur_off); 5735214082Sdim cur_off += 4; 5736214082Sdim } 5737214082Sdim 5738214082Sdim if (h != NULL) 5739214082Sdim h->got.offset |= 1; 5740214082Sdim else 5741214082Sdim local_got_offsets[r_symndx] |= 1; 5742214082Sdim } 5743214082Sdim 5744214082Sdim if ((tls_type & GOT_TLS_GD) && r_type != R_ARM_TLS_GD32) 5745214082Sdim off += 8; 5746214082Sdim value = globals->sgot->output_section->vma + globals->sgot->output_offset + off 5747214082Sdim - (input_section->output_section->vma + input_section->output_offset + rel->r_offset); 5748214082Sdim 5749214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5750214082Sdim contents, rel->r_offset, value, 5751214082Sdim rel->r_addend); 5752214082Sdim } 5753214082Sdim 5754214082Sdim case R_ARM_TLS_LE32: 5755214082Sdim if (info->shared) 5756214082Sdim { 5757214082Sdim (*_bfd_error_handler) 5758214082Sdim (_("%B(%A+0x%lx): R_ARM_TLS_LE32 relocation not permitted in shared object"), 5759214082Sdim input_bfd, input_section, 5760214082Sdim (long) rel->r_offset, howto->name); 5761214082Sdim return FALSE; 5762214082Sdim } 5763214082Sdim else 5764214082Sdim value = tpoff (info, value); 5765214082Sdim 5766214082Sdim return _bfd_final_link_relocate (howto, input_bfd, input_section, 5767214082Sdim contents, rel->r_offset, value, 5768214082Sdim rel->r_addend); 5769214082Sdim 5770214082Sdim case R_ARM_V4BX: 5771214082Sdim if (globals->fix_v4bx) 5772214082Sdim { 5773214082Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 5774214082Sdim 5775214082Sdim /* Ensure that we have a BX instruction. */ 5776214082Sdim BFD_ASSERT ((insn & 0x0ffffff0) == 0x012fff10); 5777214082Sdim 5778214082Sdim /* Preserve Rm (lowest four bits) and the condition code 5779214082Sdim (highest four bits). Other bits encode MOV PC,Rm. */ 5780214082Sdim insn = (insn & 0xf000000f) | 0x01a0f000; 5781214082Sdim 5782214082Sdim bfd_put_32 (input_bfd, insn, hit_data); 5783214082Sdim } 5784214082Sdim return bfd_reloc_ok; 5785214082Sdim 5786214634Sdim case R_ARM_MOVW_ABS_NC: 5787214634Sdim case R_ARM_MOVT_ABS: 5788214634Sdim case R_ARM_MOVW_PREL_NC: 5789214634Sdim case R_ARM_MOVT_PREL: 5790214634Sdim /* Until we properly support segment-base-relative addressing then 5791214634Sdim we assume the segment base to be zero, as for the group relocations. 5792214634Sdim Thus R_ARM_MOVW_BREL_NC has the same semantics as R_ARM_MOVW_ABS_NC 5793214634Sdim and R_ARM_MOVT_BREL has the same semantics as R_ARM_MOVT_ABS. */ 5794214634Sdim case R_ARM_MOVW_BREL_NC: 5795214634Sdim case R_ARM_MOVW_BREL: 5796214634Sdim case R_ARM_MOVT_BREL: 5797214634Sdim { 5798214634Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 5799214082Sdim 5800214634Sdim if (globals->use_rel) 5801214634Sdim { 5802214634Sdim addend = ((insn >> 4) & 0xf000) | (insn & 0xfff); 5803214634Sdim signed_addend = (addend ^ 0x10000) - 0x10000; 5804214634Sdim } 5805214082Sdim 5806214634Sdim value += signed_addend; 5807214082Sdim 5808214634Sdim if (r_type == R_ARM_MOVW_PREL_NC || r_type == R_ARM_MOVT_PREL) 5809214634Sdim value -= (input_section->output_section->vma 5810214634Sdim + input_section->output_offset + rel->r_offset); 5811214082Sdim 5812214634Sdim if (r_type == R_ARM_MOVW_BREL && value >= 0x10000) 5813214634Sdim return bfd_reloc_overflow; 5814214082Sdim 5815214634Sdim if (sym_flags == STT_ARM_TFUNC) 5816214634Sdim value |= 1; 5817214082Sdim 5818214634Sdim if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL 5819214634Sdim || r_type == R_ARM_MOVT_BREL) 5820214634Sdim value >>= 16; 5821214082Sdim 5822214634Sdim insn &= 0xfff0f000; 5823214634Sdim insn |= value & 0xfff; 5824214634Sdim insn |= (value & 0xf000) << 4; 5825214634Sdim bfd_put_32 (input_bfd, insn, hit_data); 5826214634Sdim } 5827214634Sdim return bfd_reloc_ok; 5828214082Sdim 5829214634Sdim case R_ARM_THM_MOVW_ABS_NC: 5830214634Sdim case R_ARM_THM_MOVT_ABS: 5831214634Sdim case R_ARM_THM_MOVW_PREL_NC: 5832214634Sdim case R_ARM_THM_MOVT_PREL: 5833214634Sdim /* Until we properly support segment-base-relative addressing then 5834214634Sdim we assume the segment base to be zero, as for the above relocations. 5835214634Sdim Thus R_ARM_THM_MOVW_BREL_NC has the same semantics as 5836214634Sdim R_ARM_THM_MOVW_ABS_NC and R_ARM_THM_MOVT_BREL has the same semantics 5837214634Sdim as R_ARM_THM_MOVT_ABS. */ 5838214634Sdim case R_ARM_THM_MOVW_BREL_NC: 5839214634Sdim case R_ARM_THM_MOVW_BREL: 5840214634Sdim case R_ARM_THM_MOVT_BREL: 5841214634Sdim { 5842214634Sdim bfd_vma insn; 5843214634Sdim 5844214634Sdim insn = bfd_get_16 (input_bfd, hit_data) << 16; 5845214634Sdim insn |= bfd_get_16 (input_bfd, hit_data + 2); 5846214082Sdim 5847214634Sdim if (globals->use_rel) 5848214634Sdim { 5849214634Sdim addend = ((insn >> 4) & 0xf000) 5850214634Sdim | ((insn >> 15) & 0x0800) 5851214634Sdim | ((insn >> 4) & 0x0700) 5852214634Sdim | (insn & 0x00ff); 5853214634Sdim signed_addend = (addend ^ 0x10000) - 0x10000; 5854214634Sdim } 5855214082Sdim 5856214634Sdim value += signed_addend; 5857214082Sdim 5858214634Sdim if (r_type == R_ARM_THM_MOVW_PREL_NC || r_type == R_ARM_THM_MOVT_PREL) 5859214634Sdim value -= (input_section->output_section->vma 5860214634Sdim + input_section->output_offset + rel->r_offset); 5861214082Sdim 5862214634Sdim if (r_type == R_ARM_THM_MOVW_BREL && value >= 0x10000) 5863214634Sdim return bfd_reloc_overflow; 5864214082Sdim 5865214634Sdim if (sym_flags == STT_ARM_TFUNC) 5866214634Sdim value |= 1; 5867214082Sdim 5868214634Sdim if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL 5869214634Sdim || r_type == R_ARM_THM_MOVT_BREL) 5870214634Sdim value >>= 16; 5871214082Sdim 5872214634Sdim insn &= 0xfbf08f00; 5873214634Sdim insn |= (value & 0xf000) << 4; 5874214634Sdim insn |= (value & 0x0800) << 15; 5875214634Sdim insn |= (value & 0x0700) << 4; 5876214634Sdim insn |= (value & 0x00ff); 5877214082Sdim 5878214634Sdim bfd_put_16 (input_bfd, insn >> 16, hit_data); 5879214634Sdim bfd_put_16 (input_bfd, insn & 0xffff, hit_data + 2); 5880214634Sdim } 5881214634Sdim return bfd_reloc_ok; 5882214082Sdim 5883214634Sdim case R_ARM_ALU_PC_G0_NC: 5884214634Sdim case R_ARM_ALU_PC_G1_NC: 5885214634Sdim case R_ARM_ALU_PC_G0: 5886214634Sdim case R_ARM_ALU_PC_G1: 5887214634Sdim case R_ARM_ALU_PC_G2: 5888214634Sdim case R_ARM_ALU_SB_G0_NC: 5889214634Sdim case R_ARM_ALU_SB_G1_NC: 5890214634Sdim case R_ARM_ALU_SB_G0: 5891214634Sdim case R_ARM_ALU_SB_G1: 5892214634Sdim case R_ARM_ALU_SB_G2: 5893214634Sdim { 5894214634Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 5895214634Sdim bfd_vma pc = input_section->output_section->vma 5896214634Sdim + input_section->output_offset + rel->r_offset; 5897214634Sdim /* sb should be the origin of the *segment* containing the symbol. 5898214634Sdim It is not clear how to obtain this OS-dependent value, so we 5899214634Sdim make an arbitrary choice of zero. */ 5900214634Sdim bfd_vma sb = 0; 5901214634Sdim bfd_vma residual; 5902214634Sdim bfd_vma g_n; 5903214634Sdim bfd_signed_vma signed_value; 5904214634Sdim int group = 0; 5905214082Sdim 5906214634Sdim /* Determine which group of bits to select. */ 5907214634Sdim switch (r_type) 5908214634Sdim { 5909214634Sdim case R_ARM_ALU_PC_G0_NC: 5910214634Sdim case R_ARM_ALU_PC_G0: 5911214634Sdim case R_ARM_ALU_SB_G0_NC: 5912214634Sdim case R_ARM_ALU_SB_G0: 5913214634Sdim group = 0; 5914214634Sdim break; 5915214082Sdim 5916214634Sdim case R_ARM_ALU_PC_G1_NC: 5917214634Sdim case R_ARM_ALU_PC_G1: 5918214634Sdim case R_ARM_ALU_SB_G1_NC: 5919214634Sdim case R_ARM_ALU_SB_G1: 5920214634Sdim group = 1; 5921214634Sdim break; 5922214082Sdim 5923214634Sdim case R_ARM_ALU_PC_G2: 5924214634Sdim case R_ARM_ALU_SB_G2: 5925214634Sdim group = 2; 5926214634Sdim break; 5927214082Sdim 5928214634Sdim default: 5929214634Sdim abort(); 5930214634Sdim } 5931214082Sdim 5932214634Sdim /* If REL, extract the addend from the insn. If RELA, it will 5933214634Sdim have already been fetched for us. */ 5934214634Sdim if (globals->use_rel) 5935214634Sdim { 5936214634Sdim int negative; 5937214634Sdim bfd_vma constant = insn & 0xff; 5938214634Sdim bfd_vma rotation = (insn & 0xf00) >> 8; 5939214082Sdim 5940214634Sdim if (rotation == 0) 5941214634Sdim signed_addend = constant; 5942214634Sdim else 5943214634Sdim { 5944214634Sdim /* Compensate for the fact that in the instruction, the 5945214634Sdim rotation is stored in multiples of 2 bits. */ 5946214634Sdim rotation *= 2; 5947214082Sdim 5948214634Sdim /* Rotate "constant" right by "rotation" bits. */ 5949214634Sdim signed_addend = (constant >> rotation) | 5950214634Sdim (constant << (8 * sizeof (bfd_vma) - rotation)); 5951214634Sdim } 5952214634Sdim 5953214634Sdim /* Determine if the instruction is an ADD or a SUB. 5954214634Sdim (For REL, this determines the sign of the addend.) */ 5955214634Sdim negative = identify_add_or_sub (insn); 5956214634Sdim if (negative == 0) 5957214634Sdim { 5958214634Sdim (*_bfd_error_handler) 5959214634Sdim (_("%B(%A+0x%lx): Only ADD or SUB instructions are allowed for ALU group relocations"), 5960214634Sdim input_bfd, input_section, 5961214634Sdim (long) rel->r_offset, howto->name); 5962214634Sdim return bfd_reloc_overflow; 5963214634Sdim } 5964214634Sdim 5965214634Sdim signed_addend *= negative; 5966214634Sdim } 5967214634Sdim 5968214634Sdim /* Compute the value (X) to go in the place. */ 5969214634Sdim if (r_type == R_ARM_ALU_PC_G0_NC 5970214634Sdim || r_type == R_ARM_ALU_PC_G1_NC 5971214634Sdim || r_type == R_ARM_ALU_PC_G0 5972214634Sdim || r_type == R_ARM_ALU_PC_G1 5973214634Sdim || r_type == R_ARM_ALU_PC_G2) 5974214634Sdim /* PC relative. */ 5975214634Sdim signed_value = value - pc + signed_addend; 5976214634Sdim else 5977214634Sdim /* Section base relative. */ 5978214634Sdim signed_value = value - sb + signed_addend; 5979214634Sdim 5980214634Sdim /* If the target symbol is a Thumb function, then set the 5981214634Sdim Thumb bit in the address. */ 5982214634Sdim if (sym_flags == STT_ARM_TFUNC) 5983214634Sdim signed_value |= 1; 5984214634Sdim 5985214634Sdim /* Calculate the value of the relevant G_n, in encoded 5986214634Sdim constant-with-rotation format. */ 5987214634Sdim g_n = calculate_group_reloc_mask (abs (signed_value), group, 5988214634Sdim &residual); 5989214634Sdim 5990214634Sdim /* Check for overflow if required. */ 5991214634Sdim if ((r_type == R_ARM_ALU_PC_G0 5992214634Sdim || r_type == R_ARM_ALU_PC_G1 5993214634Sdim || r_type == R_ARM_ALU_PC_G2 5994214634Sdim || r_type == R_ARM_ALU_SB_G0 5995214634Sdim || r_type == R_ARM_ALU_SB_G1 5996214634Sdim || r_type == R_ARM_ALU_SB_G2) && residual != 0) 5997214634Sdim { 5998214634Sdim (*_bfd_error_handler) 5999214634Sdim (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"), 6000214634Sdim input_bfd, input_section, 6001214634Sdim (long) rel->r_offset, abs (signed_value), howto->name); 6002214634Sdim return bfd_reloc_overflow; 6003214634Sdim } 6004214634Sdim 6005214634Sdim /* Mask out the value and the ADD/SUB part of the opcode; take care 6006214634Sdim not to destroy the S bit. */ 6007214634Sdim insn &= 0xff1ff000; 6008214634Sdim 6009214634Sdim /* Set the opcode according to whether the value to go in the 6010214634Sdim place is negative. */ 6011214634Sdim if (signed_value < 0) 6012214634Sdim insn |= 1 << 22; 6013214634Sdim else 6014214634Sdim insn |= 1 << 23; 6015214634Sdim 6016214634Sdim /* Encode the offset. */ 6017214634Sdim insn |= g_n; 6018214634Sdim 6019214634Sdim bfd_put_32 (input_bfd, insn, hit_data); 6020214634Sdim } 6021214634Sdim return bfd_reloc_ok; 6022214634Sdim 6023214634Sdim case R_ARM_LDR_PC_G0: 6024214634Sdim case R_ARM_LDR_PC_G1: 6025214634Sdim case R_ARM_LDR_PC_G2: 6026214634Sdim case R_ARM_LDR_SB_G0: 6027214634Sdim case R_ARM_LDR_SB_G1: 6028214634Sdim case R_ARM_LDR_SB_G2: 6029214634Sdim { 6030214634Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 6031214634Sdim bfd_vma pc = input_section->output_section->vma 6032214634Sdim + input_section->output_offset + rel->r_offset; 6033214634Sdim bfd_vma sb = 0; /* See note above. */ 6034214634Sdim bfd_vma residual; 6035214634Sdim bfd_signed_vma signed_value; 6036214634Sdim int group = 0; 6037214634Sdim 6038214634Sdim /* Determine which groups of bits to calculate. */ 6039214634Sdim switch (r_type) 6040214634Sdim { 6041214634Sdim case R_ARM_LDR_PC_G0: 6042214634Sdim case R_ARM_LDR_SB_G0: 6043214634Sdim group = 0; 6044214634Sdim break; 6045214634Sdim 6046214634Sdim case R_ARM_LDR_PC_G1: 6047214634Sdim case R_ARM_LDR_SB_G1: 6048214634Sdim group = 1; 6049214634Sdim break; 6050214634Sdim 6051214634Sdim case R_ARM_LDR_PC_G2: 6052214634Sdim case R_ARM_LDR_SB_G2: 6053214634Sdim group = 2; 6054214634Sdim break; 6055214634Sdim 6056214634Sdim default: 6057214634Sdim abort(); 6058214634Sdim } 6059214634Sdim 6060214634Sdim /* If REL, extract the addend from the insn. If RELA, it will 6061214634Sdim have already been fetched for us. */ 6062214634Sdim if (globals->use_rel) 6063214634Sdim { 6064214634Sdim int negative = (insn & (1 << 23)) ? 1 : -1; 6065214634Sdim signed_addend = negative * (insn & 0xfff); 6066214634Sdim } 6067214634Sdim 6068214634Sdim /* Compute the value (X) to go in the place. */ 6069214634Sdim if (r_type == R_ARM_LDR_PC_G0 6070214634Sdim || r_type == R_ARM_LDR_PC_G1 6071214634Sdim || r_type == R_ARM_LDR_PC_G2) 6072214634Sdim /* PC relative. */ 6073214634Sdim signed_value = value - pc + signed_addend; 6074214634Sdim else 6075214634Sdim /* Section base relative. */ 6076214634Sdim signed_value = value - sb + signed_addend; 6077214634Sdim 6078214634Sdim /* Calculate the value of the relevant G_{n-1} to obtain 6079214634Sdim the residual at that stage. */ 6080214634Sdim calculate_group_reloc_mask (abs (signed_value), group - 1, &residual); 6081214634Sdim 6082214634Sdim /* Check for overflow. */ 6083214634Sdim if (residual >= 0x1000) 6084214634Sdim { 6085214634Sdim (*_bfd_error_handler) 6086214634Sdim (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"), 6087214634Sdim input_bfd, input_section, 6088214634Sdim (long) rel->r_offset, abs (signed_value), howto->name); 6089214634Sdim return bfd_reloc_overflow; 6090214634Sdim } 6091214634Sdim 6092214634Sdim /* Mask out the value and U bit. */ 6093214634Sdim insn &= 0xff7ff000; 6094214634Sdim 6095214634Sdim /* Set the U bit if the value to go in the place is non-negative. */ 6096214634Sdim if (signed_value >= 0) 6097214634Sdim insn |= 1 << 23; 6098214634Sdim 6099214634Sdim /* Encode the offset. */ 6100214634Sdim insn |= residual; 6101214634Sdim 6102214634Sdim bfd_put_32 (input_bfd, insn, hit_data); 6103214634Sdim } 6104214634Sdim return bfd_reloc_ok; 6105214634Sdim 6106214634Sdim case R_ARM_LDRS_PC_G0: 6107214634Sdim case R_ARM_LDRS_PC_G1: 6108214634Sdim case R_ARM_LDRS_PC_G2: 6109214634Sdim case R_ARM_LDRS_SB_G0: 6110214634Sdim case R_ARM_LDRS_SB_G1: 6111214634Sdim case R_ARM_LDRS_SB_G2: 6112214634Sdim { 6113214634Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 6114214634Sdim bfd_vma pc = input_section->output_section->vma 6115214634Sdim + input_section->output_offset + rel->r_offset; 6116214634Sdim bfd_vma sb = 0; /* See note above. */ 6117214634Sdim bfd_vma residual; 6118214634Sdim bfd_signed_vma signed_value; 6119214634Sdim int group = 0; 6120214634Sdim 6121214634Sdim /* Determine which groups of bits to calculate. */ 6122214634Sdim switch (r_type) 6123214634Sdim { 6124214634Sdim case R_ARM_LDRS_PC_G0: 6125214634Sdim case R_ARM_LDRS_SB_G0: 6126214634Sdim group = 0; 6127214634Sdim break; 6128214634Sdim 6129214634Sdim case R_ARM_LDRS_PC_G1: 6130214634Sdim case R_ARM_LDRS_SB_G1: 6131214634Sdim group = 1; 6132214634Sdim break; 6133214634Sdim 6134214634Sdim case R_ARM_LDRS_PC_G2: 6135214634Sdim case R_ARM_LDRS_SB_G2: 6136214634Sdim group = 2; 6137214634Sdim break; 6138214634Sdim 6139214634Sdim default: 6140214634Sdim abort(); 6141214634Sdim } 6142214634Sdim 6143214634Sdim /* If REL, extract the addend from the insn. If RELA, it will 6144214634Sdim have already been fetched for us. */ 6145214634Sdim if (globals->use_rel) 6146214634Sdim { 6147214634Sdim int negative = (insn & (1 << 23)) ? 1 : -1; 6148214634Sdim signed_addend = negative * (((insn & 0xf00) >> 4) + (insn & 0xf)); 6149214634Sdim } 6150214634Sdim 6151214634Sdim /* Compute the value (X) to go in the place. */ 6152214634Sdim if (r_type == R_ARM_LDRS_PC_G0 6153214634Sdim || r_type == R_ARM_LDRS_PC_G1 6154214634Sdim || r_type == R_ARM_LDRS_PC_G2) 6155214634Sdim /* PC relative. */ 6156214634Sdim signed_value = value - pc + signed_addend; 6157214634Sdim else 6158214634Sdim /* Section base relative. */ 6159214634Sdim signed_value = value - sb + signed_addend; 6160214634Sdim 6161214634Sdim /* Calculate the value of the relevant G_{n-1} to obtain 6162214634Sdim the residual at that stage. */ 6163214634Sdim calculate_group_reloc_mask (abs (signed_value), group - 1, &residual); 6164214634Sdim 6165214634Sdim /* Check for overflow. */ 6166214634Sdim if (residual >= 0x100) 6167214634Sdim { 6168214634Sdim (*_bfd_error_handler) 6169214634Sdim (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"), 6170214634Sdim input_bfd, input_section, 6171214634Sdim (long) rel->r_offset, abs (signed_value), howto->name); 6172214634Sdim return bfd_reloc_overflow; 6173214634Sdim } 6174214634Sdim 6175214634Sdim /* Mask out the value and U bit. */ 6176214634Sdim insn &= 0xff7ff0f0; 6177214634Sdim 6178214634Sdim /* Set the U bit if the value to go in the place is non-negative. */ 6179214634Sdim if (signed_value >= 0) 6180214634Sdim insn |= 1 << 23; 6181214634Sdim 6182214634Sdim /* Encode the offset. */ 6183214634Sdim insn |= ((residual & 0xf0) << 4) | (residual & 0xf); 6184214634Sdim 6185214634Sdim bfd_put_32 (input_bfd, insn, hit_data); 6186214634Sdim } 6187214634Sdim return bfd_reloc_ok; 6188214634Sdim 6189214634Sdim case R_ARM_LDC_PC_G0: 6190214634Sdim case R_ARM_LDC_PC_G1: 6191214634Sdim case R_ARM_LDC_PC_G2: 6192214634Sdim case R_ARM_LDC_SB_G0: 6193214634Sdim case R_ARM_LDC_SB_G1: 6194214634Sdim case R_ARM_LDC_SB_G2: 6195214634Sdim { 6196214634Sdim bfd_vma insn = bfd_get_32 (input_bfd, hit_data); 6197214634Sdim bfd_vma pc = input_section->output_section->vma 6198214634Sdim + input_section->output_offset + rel->r_offset; 6199214634Sdim bfd_vma sb = 0; /* See note above. */ 6200214634Sdim bfd_vma residual; 6201214634Sdim bfd_signed_vma signed_value; 6202214634Sdim int group = 0; 6203214634Sdim 6204214634Sdim /* Determine which groups of bits to calculate. */ 6205214634Sdim switch (r_type) 6206214634Sdim { 6207214634Sdim case R_ARM_LDC_PC_G0: 6208214634Sdim case R_ARM_LDC_SB_G0: 6209214634Sdim group = 0; 6210214634Sdim break; 6211214634Sdim 6212214634Sdim case R_ARM_LDC_PC_G1: 6213214634Sdim case R_ARM_LDC_SB_G1: 6214214634Sdim group = 1; 6215214634Sdim break; 6216214634Sdim 6217214634Sdim case R_ARM_LDC_PC_G2: 6218214634Sdim case R_ARM_LDC_SB_G2: 6219214634Sdim group = 2; 6220214634Sdim break; 6221214634Sdim 6222214634Sdim default: 6223214634Sdim abort(); 6224214634Sdim } 6225214634Sdim 6226214634Sdim /* If REL, extract the addend from the insn. If RELA, it will 6227214634Sdim have already been fetched for us. */ 6228214634Sdim if (globals->use_rel) 6229214634Sdim { 6230214634Sdim int negative = (insn & (1 << 23)) ? 1 : -1; 6231214634Sdim signed_addend = negative * ((insn & 0xff) << 2); 6232214634Sdim } 6233214634Sdim 6234214634Sdim /* Compute the value (X) to go in the place. */ 6235214634Sdim if (r_type == R_ARM_LDC_PC_G0 6236214634Sdim || r_type == R_ARM_LDC_PC_G1 6237214634Sdim || r_type == R_ARM_LDC_PC_G2) 6238214634Sdim /* PC relative. */ 6239214634Sdim signed_value = value - pc + signed_addend; 6240214634Sdim else 6241214634Sdim /* Section base relative. */ 6242214634Sdim signed_value = value - sb + signed_addend; 6243214634Sdim 6244214634Sdim /* Calculate the value of the relevant G_{n-1} to obtain 6245214634Sdim the residual at that stage. */ 6246214634Sdim calculate_group_reloc_mask (abs (signed_value), group - 1, &residual); 6247214634Sdim 6248214634Sdim /* Check for overflow. (The absolute value to go in the place must be 6249214634Sdim divisible by four and, after having been divided by four, must 6250214634Sdim fit in eight bits.) */ 6251214634Sdim if ((residual & 0x3) != 0 || residual >= 0x400) 6252214634Sdim { 6253214634Sdim (*_bfd_error_handler) 6254214634Sdim (_("%B(%A+0x%lx): Overflow whilst splitting 0x%lx for group relocation %s"), 6255214634Sdim input_bfd, input_section, 6256214634Sdim (long) rel->r_offset, abs (signed_value), howto->name); 6257214634Sdim return bfd_reloc_overflow; 6258214634Sdim } 6259214634Sdim 6260214634Sdim /* Mask out the value and U bit. */ 6261214634Sdim insn &= 0xff7fff00; 6262214634Sdim 6263214634Sdim /* Set the U bit if the value to go in the place is non-negative. */ 6264214634Sdim if (signed_value >= 0) 6265214634Sdim insn |= 1 << 23; 6266214634Sdim 6267214634Sdim /* Encode the offset. */ 6268214634Sdim insn |= residual >> 2; 6269214634Sdim 6270214634Sdim bfd_put_32 (input_bfd, insn, hit_data); 6271214634Sdim } 6272214634Sdim return bfd_reloc_ok; 6273214634Sdim 6274214634Sdim default: 6275214634Sdim return bfd_reloc_notsupported; 6276214082Sdim } 6277214082Sdim} 6278214082Sdim 6279214082Sdim/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. */ 6280214082Sdimstatic void 6281214082Sdimarm_add_to_rel (bfd * abfd, 6282214082Sdim bfd_byte * address, 6283214082Sdim reloc_howto_type * howto, 6284214082Sdim bfd_signed_vma increment) 6285214082Sdim{ 6286214082Sdim bfd_signed_vma addend; 6287214082Sdim 6288214082Sdim if (howto->type == R_ARM_THM_CALL) 6289214082Sdim { 6290214082Sdim int upper_insn, lower_insn; 6291214082Sdim int upper, lower; 6292214082Sdim 6293214082Sdim upper_insn = bfd_get_16 (abfd, address); 6294214082Sdim lower_insn = bfd_get_16 (abfd, address + 2); 6295214082Sdim upper = upper_insn & 0x7ff; 6296214082Sdim lower = lower_insn & 0x7ff; 6297214082Sdim 6298214082Sdim addend = (upper << 12) | (lower << 1); 6299214082Sdim addend += increment; 6300214082Sdim addend >>= 1; 6301214082Sdim 6302214082Sdim upper_insn = (upper_insn & 0xf800) | ((addend >> 11) & 0x7ff); 6303214082Sdim lower_insn = (lower_insn & 0xf800) | (addend & 0x7ff); 6304214082Sdim 6305214082Sdim bfd_put_16 (abfd, (bfd_vma) upper_insn, address); 6306214082Sdim bfd_put_16 (abfd, (bfd_vma) lower_insn, address + 2); 6307214082Sdim } 6308214082Sdim else 6309214082Sdim { 6310214082Sdim bfd_vma contents; 6311214082Sdim 6312214082Sdim contents = bfd_get_32 (abfd, address); 6313214082Sdim 6314214082Sdim /* Get the (signed) value from the instruction. */ 6315214082Sdim addend = contents & howto->src_mask; 6316214082Sdim if (addend & ((howto->src_mask + 1) >> 1)) 6317214082Sdim { 6318214082Sdim bfd_signed_vma mask; 6319214082Sdim 6320214082Sdim mask = -1; 6321214082Sdim mask &= ~ howto->src_mask; 6322214082Sdim addend |= mask; 6323214082Sdim } 6324214082Sdim 6325214082Sdim /* Add in the increment, (which is a byte value). */ 6326214082Sdim switch (howto->type) 6327214082Sdim { 6328214082Sdim default: 6329214082Sdim addend += increment; 6330214082Sdim break; 6331214082Sdim 6332214082Sdim case R_ARM_PC24: 6333214082Sdim case R_ARM_PLT32: 6334214082Sdim case R_ARM_CALL: 6335214082Sdim case R_ARM_JUMP24: 6336214082Sdim addend <<= howto->size; 6337214082Sdim addend += increment; 6338214082Sdim 6339214082Sdim /* Should we check for overflow here ? */ 6340214082Sdim 6341214082Sdim /* Drop any undesired bits. */ 6342214082Sdim addend >>= howto->rightshift; 6343214082Sdim break; 6344214082Sdim } 6345214082Sdim 6346214082Sdim contents = (contents & ~ howto->dst_mask) | (addend & howto->dst_mask); 6347214082Sdim 6348214082Sdim bfd_put_32 (abfd, contents, address); 6349214082Sdim } 6350214082Sdim} 6351214082Sdim 6352214082Sdim#define IS_ARM_TLS_RELOC(R_TYPE) \ 6353214082Sdim ((R_TYPE) == R_ARM_TLS_GD32 \ 6354214082Sdim || (R_TYPE) == R_ARM_TLS_LDO32 \ 6355214082Sdim || (R_TYPE) == R_ARM_TLS_LDM32 \ 6356214082Sdim || (R_TYPE) == R_ARM_TLS_DTPOFF32 \ 6357214082Sdim || (R_TYPE) == R_ARM_TLS_DTPMOD32 \ 6358214082Sdim || (R_TYPE) == R_ARM_TLS_TPOFF32 \ 6359214082Sdim || (R_TYPE) == R_ARM_TLS_LE32 \ 6360214082Sdim || (R_TYPE) == R_ARM_TLS_IE32) 6361214082Sdim 6362214082Sdim/* Relocate an ARM ELF section. */ 6363214082Sdimstatic bfd_boolean 6364214082Sdimelf32_arm_relocate_section (bfd * output_bfd, 6365214082Sdim struct bfd_link_info * info, 6366214082Sdim bfd * input_bfd, 6367214082Sdim asection * input_section, 6368214082Sdim bfd_byte * contents, 6369214082Sdim Elf_Internal_Rela * relocs, 6370214082Sdim Elf_Internal_Sym * local_syms, 6371214082Sdim asection ** local_sections) 6372214082Sdim{ 6373214082Sdim Elf_Internal_Shdr *symtab_hdr; 6374214082Sdim struct elf_link_hash_entry **sym_hashes; 6375214082Sdim Elf_Internal_Rela *rel; 6376214082Sdim Elf_Internal_Rela *relend; 6377214082Sdim const char *name; 6378214082Sdim struct elf32_arm_link_hash_table * globals; 6379214082Sdim 6380214082Sdim globals = elf32_arm_hash_table (info); 6381214082Sdim 6382214082Sdim symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; 6383214082Sdim sym_hashes = elf_sym_hashes (input_bfd); 6384214082Sdim 6385214082Sdim rel = relocs; 6386214082Sdim relend = relocs + input_section->reloc_count; 6387214082Sdim for (; rel < relend; rel++) 6388214082Sdim { 6389214082Sdim int r_type; 6390214082Sdim reloc_howto_type * howto; 6391214082Sdim unsigned long r_symndx; 6392214082Sdim Elf_Internal_Sym * sym; 6393214082Sdim asection * sec; 6394214082Sdim struct elf_link_hash_entry * h; 6395214082Sdim bfd_vma relocation; 6396214082Sdim bfd_reloc_status_type r; 6397214082Sdim arelent bfd_reloc; 6398214082Sdim char sym_type; 6399214082Sdim bfd_boolean unresolved_reloc = FALSE; 6400214634Sdim char *error_message = NULL; 6401214082Sdim 6402214082Sdim r_symndx = ELF32_R_SYM (rel->r_info); 6403214082Sdim r_type = ELF32_R_TYPE (rel->r_info); 6404214082Sdim r_type = arm_real_reloc_type (globals, r_type); 6405214082Sdim 6406214082Sdim if ( r_type == R_ARM_GNU_VTENTRY 6407214082Sdim || r_type == R_ARM_GNU_VTINHERIT) 6408214082Sdim continue; 6409214082Sdim 6410214082Sdim bfd_reloc.howto = elf32_arm_howto_from_type (r_type); 6411214082Sdim howto = bfd_reloc.howto; 6412214082Sdim 6413214082Sdim h = NULL; 6414214082Sdim sym = NULL; 6415214082Sdim sec = NULL; 6416214082Sdim 6417214082Sdim if (r_symndx < symtab_hdr->sh_info) 6418214082Sdim { 6419214082Sdim sym = local_syms + r_symndx; 6420214082Sdim sym_type = ELF32_ST_TYPE (sym->st_info); 6421214082Sdim sec = local_sections[r_symndx]; 6422214082Sdim if (globals->use_rel) 6423214082Sdim { 6424214082Sdim relocation = (sec->output_section->vma 6425214082Sdim + sec->output_offset 6426214082Sdim + sym->st_value); 6427214634Sdim if (!info->relocatable 6428214634Sdim && (sec->flags & SEC_MERGE) 6429214634Sdim && ELF_ST_TYPE (sym->st_info) == STT_SECTION) 6430214082Sdim { 6431214082Sdim asection *msec; 6432214082Sdim bfd_vma addend, value; 6433214082Sdim 6434214082Sdim if (howto->rightshift) 6435214082Sdim { 6436214082Sdim (*_bfd_error_handler) 6437214082Sdim (_("%B(%A+0x%lx): %s relocation against SEC_MERGE section"), 6438214082Sdim input_bfd, input_section, 6439214082Sdim (long) rel->r_offset, howto->name); 6440214082Sdim return FALSE; 6441214082Sdim } 6442214082Sdim 6443214082Sdim value = bfd_get_32 (input_bfd, contents + rel->r_offset); 6444214082Sdim 6445214082Sdim /* Get the (signed) value from the instruction. */ 6446214082Sdim addend = value & howto->src_mask; 6447214082Sdim if (addend & ((howto->src_mask + 1) >> 1)) 6448214082Sdim { 6449214082Sdim bfd_signed_vma mask; 6450214082Sdim 6451214082Sdim mask = -1; 6452214082Sdim mask &= ~ howto->src_mask; 6453214082Sdim addend |= mask; 6454214082Sdim } 6455214082Sdim msec = sec; 6456214082Sdim addend = 6457214082Sdim _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) 6458214082Sdim - relocation; 6459214082Sdim addend += msec->output_section->vma + msec->output_offset; 6460214082Sdim value = (value & ~ howto->dst_mask) | (addend & howto->dst_mask); 6461214082Sdim bfd_put_32 (input_bfd, value, contents + rel->r_offset); 6462214082Sdim } 6463214082Sdim } 6464214082Sdim else 6465214082Sdim relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 6466214082Sdim } 6467214082Sdim else 6468214082Sdim { 6469214082Sdim bfd_boolean warned; 6470214082Sdim 6471214082Sdim RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 6472214082Sdim r_symndx, symtab_hdr, sym_hashes, 6473214082Sdim h, sec, relocation, 6474214082Sdim unresolved_reloc, warned); 6475214082Sdim 6476214082Sdim sym_type = h->type; 6477214082Sdim } 6478214082Sdim 6479214634Sdim if (sec != NULL && elf_discarded_section (sec)) 6480214634Sdim { 6481214634Sdim /* For relocs against symbols from removed linkonce sections, 6482214634Sdim or sections discarded by a linker script, we just want the 6483214634Sdim section contents zeroed. Avoid any special processing. */ 6484214634Sdim _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); 6485214634Sdim rel->r_info = 0; 6486214634Sdim rel->r_addend = 0; 6487214634Sdim continue; 6488214634Sdim } 6489214634Sdim 6490214634Sdim if (info->relocatable) 6491214634Sdim { 6492214634Sdim /* This is a relocatable link. We don't have to change 6493214634Sdim anything, unless the reloc is against a section symbol, 6494214634Sdim in which case we have to adjust according to where the 6495214634Sdim section symbol winds up in the output section. */ 6496214634Sdim if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) 6497214634Sdim { 6498214634Sdim if (globals->use_rel) 6499214634Sdim arm_add_to_rel (input_bfd, contents + rel->r_offset, 6500214634Sdim howto, (bfd_signed_vma) sec->output_offset); 6501214634Sdim else 6502214634Sdim rel->r_addend += sec->output_offset; 6503214634Sdim } 6504214634Sdim continue; 6505214634Sdim } 6506214634Sdim 6507214082Sdim if (h != NULL) 6508214082Sdim name = h->root.root.string; 6509214082Sdim else 6510214082Sdim { 6511214082Sdim name = (bfd_elf_string_from_elf_section 6512214082Sdim (input_bfd, symtab_hdr->sh_link, sym->st_name)); 6513214082Sdim if (name == NULL || *name == '\0') 6514214082Sdim name = bfd_section_name (input_bfd, sec); 6515214082Sdim } 6516214082Sdim 6517214082Sdim if (r_symndx != 0 6518214082Sdim && r_type != R_ARM_NONE 6519214082Sdim && (h == NULL 6520214082Sdim || h->root.type == bfd_link_hash_defined 6521214082Sdim || h->root.type == bfd_link_hash_defweak) 6522214082Sdim && IS_ARM_TLS_RELOC (r_type) != (sym_type == STT_TLS)) 6523214082Sdim { 6524214082Sdim (*_bfd_error_handler) 6525214082Sdim ((sym_type == STT_TLS 6526214082Sdim ? _("%B(%A+0x%lx): %s used with TLS symbol %s") 6527214082Sdim : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")), 6528214082Sdim input_bfd, 6529214082Sdim input_section, 6530214082Sdim (long) rel->r_offset, 6531214082Sdim howto->name, 6532214082Sdim name); 6533214082Sdim } 6534214082Sdim 6535214082Sdim r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, 6536214082Sdim input_section, contents, rel, 6537214082Sdim relocation, info, sec, name, 6538214082Sdim (h ? ELF_ST_TYPE (h->type) : 6539214082Sdim ELF_ST_TYPE (sym->st_info)), h, 6540214634Sdim &unresolved_reloc, &error_message); 6541214082Sdim 6542214082Sdim /* Dynamic relocs are not propagated for SEC_DEBUGGING sections 6543214082Sdim because such sections are not SEC_ALLOC and thus ld.so will 6544214082Sdim not process them. */ 6545214082Sdim if (unresolved_reloc 6546214082Sdim && !((input_section->flags & SEC_DEBUGGING) != 0 6547214082Sdim && h->def_dynamic)) 6548214082Sdim { 6549214082Sdim (*_bfd_error_handler) 6550214082Sdim (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), 6551214082Sdim input_bfd, 6552214082Sdim input_section, 6553214082Sdim (long) rel->r_offset, 6554214082Sdim howto->name, 6555214082Sdim h->root.root.string); 6556214082Sdim return FALSE; 6557214082Sdim } 6558214082Sdim 6559214082Sdim if (r != bfd_reloc_ok) 6560214082Sdim { 6561214082Sdim switch (r) 6562214082Sdim { 6563214082Sdim case bfd_reloc_overflow: 6564214082Sdim /* If the overflowing reloc was to an undefined symbol, 6565214082Sdim we have already printed one error message and there 6566214082Sdim is no point complaining again. */ 6567214082Sdim if ((! h || 6568214082Sdim h->root.type != bfd_link_hash_undefined) 6569214082Sdim && (!((*info->callbacks->reloc_overflow) 6570214082Sdim (info, (h ? &h->root : NULL), name, howto->name, 6571214082Sdim (bfd_vma) 0, input_bfd, input_section, 6572214082Sdim rel->r_offset)))) 6573214082Sdim return FALSE; 6574214082Sdim break; 6575214082Sdim 6576214082Sdim case bfd_reloc_undefined: 6577214082Sdim if (!((*info->callbacks->undefined_symbol) 6578214082Sdim (info, name, input_bfd, input_section, 6579214082Sdim rel->r_offset, TRUE))) 6580214082Sdim return FALSE; 6581214082Sdim break; 6582214082Sdim 6583214082Sdim case bfd_reloc_outofrange: 6584214634Sdim error_message = _("out of range"); 6585214082Sdim goto common_error; 6586214082Sdim 6587214082Sdim case bfd_reloc_notsupported: 6588214634Sdim error_message = _("unsupported relocation"); 6589214082Sdim goto common_error; 6590214082Sdim 6591214082Sdim case bfd_reloc_dangerous: 6592214634Sdim /* error_message should already be set. */ 6593214082Sdim goto common_error; 6594214082Sdim 6595214082Sdim default: 6596214634Sdim error_message = _("unknown error"); 6597214082Sdim /* fall through */ 6598214082Sdim 6599214082Sdim common_error: 6600214634Sdim BFD_ASSERT (error_message != NULL); 6601214634Sdim if (!((*info->callbacks->reloc_dangerous) 6602214634Sdim (info, error_message, input_bfd, input_section, 6603214082Sdim rel->r_offset))) 6604214082Sdim return FALSE; 6605214082Sdim break; 6606214082Sdim } 6607214082Sdim } 6608214082Sdim } 6609214082Sdim 6610214082Sdim return TRUE; 6611214082Sdim} 6612214082Sdim 6613214082Sdim/* Set the right machine number. */ 6614214082Sdim 6615214082Sdimstatic bfd_boolean 6616214082Sdimelf32_arm_object_p (bfd *abfd) 6617214082Sdim{ 6618214082Sdim unsigned int mach; 6619214082Sdim 6620214082Sdim mach = bfd_arm_get_mach_from_notes (abfd, ARM_NOTE_SECTION); 6621214082Sdim 6622214082Sdim if (mach != bfd_mach_arm_unknown) 6623214082Sdim bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach); 6624214082Sdim 6625214082Sdim else if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT) 6626214082Sdim bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312); 6627214082Sdim 6628214082Sdim else 6629214082Sdim bfd_default_set_arch_mach (abfd, bfd_arch_arm, mach); 6630214082Sdim 6631214082Sdim return TRUE; 6632214082Sdim} 6633214082Sdim 6634214082Sdim/* Function to keep ARM specific flags in the ELF header. */ 6635214082Sdim 6636214082Sdimstatic bfd_boolean 6637214082Sdimelf32_arm_set_private_flags (bfd *abfd, flagword flags) 6638214082Sdim{ 6639214082Sdim if (elf_flags_init (abfd) 6640214082Sdim && elf_elfheader (abfd)->e_flags != flags) 6641214082Sdim { 6642214082Sdim if (EF_ARM_EABI_VERSION (flags) == EF_ARM_EABI_UNKNOWN) 6643214082Sdim { 6644214082Sdim if (flags & EF_ARM_INTERWORK) 6645214082Sdim (*_bfd_error_handler) 6646214082Sdim (_("Warning: Not setting interworking flag of %B since it has already been specified as non-interworking"), 6647214082Sdim abfd); 6648214082Sdim else 6649214082Sdim _bfd_error_handler 6650214082Sdim (_("Warning: Clearing the interworking flag of %B due to outside request"), 6651214082Sdim abfd); 6652214082Sdim } 6653214082Sdim } 6654214082Sdim else 6655214082Sdim { 6656214082Sdim elf_elfheader (abfd)->e_flags = flags; 6657214082Sdim elf_flags_init (abfd) = TRUE; 6658214082Sdim } 6659214082Sdim 6660214082Sdim return TRUE; 6661214082Sdim} 6662214082Sdim 6663214082Sdim/* Copy backend specific data from one object module to another. */ 6664214082Sdim 6665214082Sdimstatic bfd_boolean 6666214082Sdimelf32_arm_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 6667214082Sdim{ 6668214082Sdim flagword in_flags; 6669214082Sdim flagword out_flags; 6670214082Sdim 6671214082Sdim if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour 6672214082Sdim || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 6673214082Sdim return TRUE; 6674214082Sdim 6675214082Sdim in_flags = elf_elfheader (ibfd)->e_flags; 6676214082Sdim out_flags = elf_elfheader (obfd)->e_flags; 6677214082Sdim 6678214082Sdim if (elf_flags_init (obfd) 6679214082Sdim && EF_ARM_EABI_VERSION (out_flags) == EF_ARM_EABI_UNKNOWN 6680214082Sdim && in_flags != out_flags) 6681214082Sdim { 6682214082Sdim /* Cannot mix APCS26 and APCS32 code. */ 6683214082Sdim if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26)) 6684214082Sdim return FALSE; 6685214082Sdim 6686214082Sdim /* Cannot mix float APCS and non-float APCS code. */ 6687214082Sdim if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT)) 6688214082Sdim return FALSE; 6689214082Sdim 6690214082Sdim /* If the src and dest have different interworking flags 6691214082Sdim then turn off the interworking bit. */ 6692214082Sdim if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) 6693214082Sdim { 6694214082Sdim if (out_flags & EF_ARM_INTERWORK) 6695214082Sdim _bfd_error_handler 6696214082Sdim (_("Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"), 6697214082Sdim obfd, ibfd); 6698214082Sdim 6699214082Sdim in_flags &= ~EF_ARM_INTERWORK; 6700214082Sdim } 6701214082Sdim 6702214082Sdim /* Likewise for PIC, though don't warn for this case. */ 6703214082Sdim if ((in_flags & EF_ARM_PIC) != (out_flags & EF_ARM_PIC)) 6704214082Sdim in_flags &= ~EF_ARM_PIC; 6705214082Sdim } 6706214082Sdim 6707214082Sdim elf_elfheader (obfd)->e_flags = in_flags; 6708214082Sdim elf_flags_init (obfd) = TRUE; 6709214082Sdim 6710214082Sdim /* Also copy the EI_OSABI field. */ 6711214082Sdim elf_elfheader (obfd)->e_ident[EI_OSABI] = 6712214082Sdim elf_elfheader (ibfd)->e_ident[EI_OSABI]; 6713214082Sdim 6714214634Sdim /* Copy object attributes. */ 6715214634Sdim _bfd_elf_copy_obj_attributes (ibfd, obfd); 6716214082Sdim 6717214082Sdim return TRUE; 6718214082Sdim} 6719214082Sdim 6720214082Sdim/* Values for Tag_ABI_PCS_R9_use. */ 6721214082Sdimenum 6722214082Sdim{ 6723214082Sdim AEABI_R9_V6, 6724214082Sdim AEABI_R9_SB, 6725214082Sdim AEABI_R9_TLS, 6726214082Sdim AEABI_R9_unused 6727214082Sdim}; 6728214082Sdim 6729214082Sdim/* Values for Tag_ABI_PCS_RW_data. */ 6730214082Sdimenum 6731214082Sdim{ 6732214082Sdim AEABI_PCS_RW_data_absolute, 6733214082Sdim AEABI_PCS_RW_data_PCrel, 6734214082Sdim AEABI_PCS_RW_data_SBrel, 6735214082Sdim AEABI_PCS_RW_data_unused 6736214082Sdim}; 6737214082Sdim 6738214082Sdim/* Values for Tag_ABI_enum_size. */ 6739214082Sdimenum 6740214082Sdim{ 6741214082Sdim AEABI_enum_unused, 6742214082Sdim AEABI_enum_short, 6743214082Sdim AEABI_enum_wide, 6744214082Sdim AEABI_enum_forced_wide 6745214082Sdim}; 6746214082Sdim 6747214634Sdim/* Determine whether an object attribute tag takes an integer, a 6748214634Sdim string or both. */ 6749214634Sdimstatic int 6750214634Sdimelf32_arm_obj_attrs_arg_type (int tag) 6751214634Sdim{ 6752214634Sdim if (tag == Tag_compatibility) 6753214634Sdim return 3; 6754214634Sdim else if (tag == 4 || tag == 5) 6755214634Sdim return 2; 6756214634Sdim else if (tag < 32) 6757214634Sdim return 1; 6758214634Sdim else 6759214634Sdim return (tag & 1) != 0 ? 2 : 1; 6760214634Sdim} 6761214634Sdim 6762214082Sdim/* Merge EABI object attributes from IBFD into OBFD. Raise an error if there 6763214082Sdim are conflicting attributes. */ 6764214082Sdimstatic bfd_boolean 6765214082Sdimelf32_arm_merge_eabi_attributes (bfd *ibfd, bfd *obfd) 6766214082Sdim{ 6767214634Sdim obj_attribute *in_attr; 6768214634Sdim obj_attribute *out_attr; 6769214634Sdim obj_attribute_list *in_list; 6770214082Sdim /* Some tags have 0 = don't care, 1 = strong requirement, 6771214082Sdim 2 = weak requirement. */ 6772214082Sdim static const int order_312[3] = {3, 1, 2}; 6773214082Sdim int i; 6774214082Sdim 6775214634Sdim if (!elf_known_obj_attributes_proc (obfd)[0].i) 6776214082Sdim { 6777214082Sdim /* This is the first object. Copy the attributes. */ 6778214634Sdim _bfd_elf_copy_obj_attributes (ibfd, obfd); 6779214634Sdim 6780214634Sdim /* Use the Tag_null value to indicate the attributes have been 6781214634Sdim initialized. */ 6782214634Sdim elf_known_obj_attributes_proc (obfd)[0].i = 1; 6783214634Sdim 6784214082Sdim return TRUE; 6785214082Sdim } 6786214082Sdim 6787214634Sdim in_attr = elf_known_obj_attributes_proc (ibfd); 6788214634Sdim out_attr = elf_known_obj_attributes_proc (obfd); 6789214082Sdim /* This needs to happen before Tag_ABI_FP_number_model is merged. */ 6790214082Sdim if (in_attr[Tag_ABI_VFP_args].i != out_attr[Tag_ABI_VFP_args].i) 6791214082Sdim { 6792214082Sdim /* Ignore mismatches if teh object doesn't use floating point. */ 6793214082Sdim if (out_attr[Tag_ABI_FP_number_model].i == 0) 6794214082Sdim out_attr[Tag_ABI_VFP_args].i = in_attr[Tag_ABI_VFP_args].i; 6795214082Sdim else if (in_attr[Tag_ABI_FP_number_model].i != 0) 6796214082Sdim { 6797214082Sdim _bfd_error_handler 6798214082Sdim (_("ERROR: %B uses VFP register arguments, %B does not"), 6799214082Sdim ibfd, obfd); 6800214082Sdim return FALSE; 6801214082Sdim } 6802214082Sdim } 6803214082Sdim 6804214634Sdim for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) 6805214082Sdim { 6806214082Sdim /* Merge this attribute with existing attributes. */ 6807214082Sdim switch (i) 6808214082Sdim { 6809214082Sdim case Tag_CPU_raw_name: 6810214082Sdim case Tag_CPU_name: 6811214634Sdim /* Use whichever has the greatest architecture requirements. We 6812214634Sdim won't necessarily have both the above tags, so make sure input 6813214634Sdim name is non-NULL. */ 6814214634Sdim if (in_attr[Tag_CPU_arch].i > out_attr[Tag_CPU_arch].i 6815214634Sdim && in_attr[i].s) 6816214634Sdim out_attr[i].s = _bfd_elf_attr_strdup (obfd, in_attr[i].s); 6817214082Sdim break; 6818214082Sdim 6819214082Sdim case Tag_ABI_optimization_goals: 6820214082Sdim case Tag_ABI_FP_optimization_goals: 6821214082Sdim /* Use the first value seen. */ 6822214082Sdim break; 6823214082Sdim 6824214082Sdim case Tag_CPU_arch: 6825214082Sdim case Tag_ARM_ISA_use: 6826214082Sdim case Tag_THUMB_ISA_use: 6827214082Sdim case Tag_VFP_arch: 6828214082Sdim case Tag_WMMX_arch: 6829214082Sdim case Tag_NEON_arch: 6830214082Sdim /* ??? Do NEON and WMMX conflict? */ 6831214082Sdim case Tag_ABI_FP_rounding: 6832214082Sdim case Tag_ABI_FP_denormal: 6833214082Sdim case Tag_ABI_FP_exceptions: 6834214082Sdim case Tag_ABI_FP_user_exceptions: 6835214082Sdim case Tag_ABI_FP_number_model: 6836214082Sdim case Tag_ABI_align8_preserved: 6837214082Sdim case Tag_ABI_HardFP_use: 6838214082Sdim /* Use the largest value specified. */ 6839214082Sdim if (in_attr[i].i > out_attr[i].i) 6840214082Sdim out_attr[i].i = in_attr[i].i; 6841214082Sdim break; 6842214082Sdim 6843214082Sdim case Tag_CPU_arch_profile: 6844214082Sdim /* Warn if conflicting architecture profiles used. */ 6845214082Sdim if (out_attr[i].i && in_attr[i].i && in_attr[i].i != out_attr[i].i) 6846214082Sdim { 6847214082Sdim _bfd_error_handler 6848214082Sdim (_("ERROR: %B: Conflicting architecture profiles %c/%c"), 6849214082Sdim ibfd, in_attr[i].i, out_attr[i].i); 6850214082Sdim return FALSE; 6851214082Sdim } 6852214082Sdim if (in_attr[i].i) 6853214082Sdim out_attr[i].i = in_attr[i].i; 6854214082Sdim break; 6855214082Sdim case Tag_PCS_config: 6856214082Sdim if (out_attr[i].i == 0) 6857214082Sdim out_attr[i].i = in_attr[i].i; 6858214082Sdim else if (in_attr[i].i != 0 && out_attr[i].i != 0) 6859214082Sdim { 6860214082Sdim /* It's sometimes ok to mix different configs, so this is only 6861214082Sdim a warning. */ 6862214082Sdim _bfd_error_handler 6863214082Sdim (_("Warning: %B: Conflicting platform configuration"), ibfd); 6864214082Sdim } 6865214082Sdim break; 6866214082Sdim case Tag_ABI_PCS_R9_use: 6867214634Sdim if (in_attr[i].i != out_attr[i].i 6868214634Sdim && out_attr[i].i != AEABI_R9_unused 6869214082Sdim && in_attr[i].i != AEABI_R9_unused) 6870214082Sdim { 6871214082Sdim _bfd_error_handler 6872214082Sdim (_("ERROR: %B: Conflicting use of R9"), ibfd); 6873214082Sdim return FALSE; 6874214082Sdim } 6875214082Sdim if (out_attr[i].i == AEABI_R9_unused) 6876214082Sdim out_attr[i].i = in_attr[i].i; 6877214082Sdim break; 6878214082Sdim case Tag_ABI_PCS_RW_data: 6879214082Sdim if (in_attr[i].i == AEABI_PCS_RW_data_SBrel 6880214082Sdim && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_SB 6881214082Sdim && out_attr[Tag_ABI_PCS_R9_use].i != AEABI_R9_unused) 6882214082Sdim { 6883214082Sdim _bfd_error_handler 6884214082Sdim (_("ERROR: %B: SB relative addressing conflicts with use of R9"), 6885214082Sdim ibfd); 6886214082Sdim return FALSE; 6887214082Sdim } 6888214082Sdim /* Use the smallest value specified. */ 6889214082Sdim if (in_attr[i].i < out_attr[i].i) 6890214082Sdim out_attr[i].i = in_attr[i].i; 6891214082Sdim break; 6892214082Sdim case Tag_ABI_PCS_RO_data: 6893214082Sdim /* Use the smallest value specified. */ 6894214082Sdim if (in_attr[i].i < out_attr[i].i) 6895214082Sdim out_attr[i].i = in_attr[i].i; 6896214082Sdim break; 6897214082Sdim case Tag_ABI_PCS_GOT_use: 6898214082Sdim if (in_attr[i].i > 2 || out_attr[i].i > 2 6899214082Sdim || order_312[in_attr[i].i] < order_312[out_attr[i].i]) 6900214082Sdim out_attr[i].i = in_attr[i].i; 6901214082Sdim break; 6902214082Sdim case Tag_ABI_PCS_wchar_t: 6903214082Sdim if (out_attr[i].i && in_attr[i].i && out_attr[i].i != in_attr[i].i) 6904214082Sdim { 6905214082Sdim _bfd_error_handler 6906214082Sdim (_("ERROR: %B: Conflicting definitions of wchar_t"), ibfd); 6907214082Sdim return FALSE; 6908214082Sdim } 6909214082Sdim if (in_attr[i].i) 6910214082Sdim out_attr[i].i = in_attr[i].i; 6911214082Sdim break; 6912214082Sdim case Tag_ABI_align8_needed: 6913214082Sdim /* ??? Check against Tag_ABI_align8_preserved. */ 6914214082Sdim if (in_attr[i].i > 2 || out_attr[i].i > 2 6915214082Sdim || order_312[in_attr[i].i] < order_312[out_attr[i].i]) 6916214082Sdim out_attr[i].i = in_attr[i].i; 6917214082Sdim break; 6918214082Sdim case Tag_ABI_enum_size: 6919214082Sdim if (in_attr[i].i != AEABI_enum_unused) 6920214082Sdim { 6921214082Sdim if (out_attr[i].i == AEABI_enum_unused 6922214082Sdim || out_attr[i].i == AEABI_enum_forced_wide) 6923214082Sdim { 6924214082Sdim /* The existing object is compatible with anything. 6925214082Sdim Use whatever requirements the new object has. */ 6926214082Sdim out_attr[i].i = in_attr[i].i; 6927214082Sdim } 6928214082Sdim else if (in_attr[i].i != AEABI_enum_forced_wide 6929214634Sdim && out_attr[i].i != in_attr[i].i 6930214634Sdim && !elf32_arm_tdata (obfd)->no_enum_size_warning) 6931214082Sdim { 6932214634Sdim const char *aeabi_enum_names[] = 6933214634Sdim { "", "variable-size", "32-bit", "" }; 6934214082Sdim _bfd_error_handler 6935214634Sdim (_("warning: %B uses %s enums yet the output is to use %s enums; use of enum values across objects may fail"), 6936214634Sdim ibfd, aeabi_enum_names[in_attr[i].i], 6937214634Sdim aeabi_enum_names[out_attr[i].i]); 6938214082Sdim } 6939214082Sdim } 6940214082Sdim break; 6941214082Sdim case Tag_ABI_VFP_args: 6942214082Sdim /* Aready done. */ 6943214082Sdim break; 6944214082Sdim case Tag_ABI_WMMX_args: 6945214082Sdim if (in_attr[i].i != out_attr[i].i) 6946214082Sdim { 6947214082Sdim _bfd_error_handler 6948214082Sdim (_("ERROR: %B uses iWMMXt register arguments, %B does not"), 6949214082Sdim ibfd, obfd); 6950214082Sdim return FALSE; 6951214082Sdim } 6952214082Sdim break; 6953214082Sdim default: /* All known attributes should be explicitly covered. */ 6954214082Sdim abort (); 6955214082Sdim } 6956214082Sdim } 6957214082Sdim 6958214634Sdim /* Merge Tag_compatibility attributes and any common GNU ones. */ 6959214634Sdim _bfd_elf_merge_object_attributes (ibfd, obfd); 6960214634Sdim 6961214634Sdim /* Check for any attributes not known on ARM. */ 6962214634Sdim in_list = elf_other_obj_attributes_proc (ibfd); 6963214082Sdim while (in_list && in_list->tag == Tag_compatibility) 6964214634Sdim in_list = in_list->next; 6965214082Sdim 6966214082Sdim for (; in_list; in_list = in_list->next) 6967214082Sdim { 6968214082Sdim if ((in_list->tag & 128) < 64) 6969214082Sdim { 6970214082Sdim _bfd_error_handler 6971214082Sdim (_("Warning: %B: Unknown EABI object attribute %d"), 6972214082Sdim ibfd, in_list->tag); 6973214082Sdim break; 6974214082Sdim } 6975214082Sdim } 6976214082Sdim return TRUE; 6977214082Sdim} 6978214082Sdim 6979214082Sdim 6980214082Sdim/* Return TRUE if the two EABI versions are incompatible. */ 6981214082Sdim 6982214082Sdimstatic bfd_boolean 6983214082Sdimelf32_arm_versions_compatible (unsigned iver, unsigned over) 6984214082Sdim{ 6985214082Sdim /* v4 and v5 are the same spec before and after it was released, 6986214082Sdim so allow mixing them. */ 6987214082Sdim if ((iver == EF_ARM_EABI_VER4 && over == EF_ARM_EABI_VER5) 6988214082Sdim || (iver == EF_ARM_EABI_VER5 && over == EF_ARM_EABI_VER4)) 6989214082Sdim return TRUE; 6990214082Sdim 6991214082Sdim return (iver == over); 6992214082Sdim} 6993214082Sdim 6994214082Sdim/* Merge backend specific data from an object file to the output 6995214082Sdim object file when linking. */ 6996214082Sdim 6997214082Sdimstatic bfd_boolean 6998214082Sdimelf32_arm_merge_private_bfd_data (bfd * ibfd, bfd * obfd) 6999214082Sdim{ 7000214082Sdim flagword out_flags; 7001214082Sdim flagword in_flags; 7002214082Sdim bfd_boolean flags_compatible = TRUE; 7003214082Sdim asection *sec; 7004214082Sdim 7005214082Sdim /* Check if we have the same endianess. */ 7006214082Sdim if (! _bfd_generic_verify_endian_match (ibfd, obfd)) 7007214082Sdim return FALSE; 7008214082Sdim 7009214082Sdim if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour 7010214082Sdim || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 7011214082Sdim return TRUE; 7012214082Sdim 7013214082Sdim if (!elf32_arm_merge_eabi_attributes (ibfd, obfd)) 7014214082Sdim return FALSE; 7015214082Sdim 7016214082Sdim /* The input BFD must have had its flags initialised. */ 7017214082Sdim /* The following seems bogus to me -- The flags are initialized in 7018214082Sdim the assembler but I don't think an elf_flags_init field is 7019214082Sdim written into the object. */ 7020214082Sdim /* BFD_ASSERT (elf_flags_init (ibfd)); */ 7021214082Sdim 7022214082Sdim in_flags = elf_elfheader (ibfd)->e_flags; 7023214082Sdim out_flags = elf_elfheader (obfd)->e_flags; 7024214082Sdim 7025214082Sdim if (!elf_flags_init (obfd)) 7026214082Sdim { 7027214082Sdim /* If the input is the default architecture and had the default 7028214082Sdim flags then do not bother setting the flags for the output 7029214082Sdim architecture, instead allow future merges to do this. If no 7030214082Sdim future merges ever set these flags then they will retain their 7031214082Sdim uninitialised values, which surprise surprise, correspond 7032214082Sdim to the default values. */ 7033214082Sdim if (bfd_get_arch_info (ibfd)->the_default 7034214082Sdim && elf_elfheader (ibfd)->e_flags == 0) 7035214082Sdim return TRUE; 7036214082Sdim 7037214082Sdim elf_flags_init (obfd) = TRUE; 7038214082Sdim elf_elfheader (obfd)->e_flags = in_flags; 7039214082Sdim 7040214082Sdim if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) 7041214082Sdim && bfd_get_arch_info (obfd)->the_default) 7042214082Sdim return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); 7043214082Sdim 7044214082Sdim return TRUE; 7045214082Sdim } 7046214082Sdim 7047214082Sdim /* Determine what should happen if the input ARM architecture 7048214082Sdim does not match the output ARM architecture. */ 7049214082Sdim if (! bfd_arm_merge_machines (ibfd, obfd)) 7050214082Sdim return FALSE; 7051214082Sdim 7052214082Sdim /* Identical flags must be compatible. */ 7053214082Sdim if (in_flags == out_flags) 7054214082Sdim return TRUE; 7055214082Sdim 7056214082Sdim /* Check to see if the input BFD actually contains any sections. If 7057214082Sdim not, its flags may not have been initialised either, but it 7058214082Sdim cannot actually cause any incompatiblity. Do not short-circuit 7059214082Sdim dynamic objects; their section list may be emptied by 7060214082Sdim elf_link_add_object_symbols. 7061214082Sdim 7062214082Sdim Also check to see if there are no code sections in the input. 7063214082Sdim In this case there is no need to check for code specific flags. 7064214082Sdim XXX - do we need to worry about floating-point format compatability 7065214082Sdim in data sections ? */ 7066214082Sdim if (!(ibfd->flags & DYNAMIC)) 7067214082Sdim { 7068214082Sdim bfd_boolean null_input_bfd = TRUE; 7069214082Sdim bfd_boolean only_data_sections = TRUE; 7070214082Sdim 7071214082Sdim for (sec = ibfd->sections; sec != NULL; sec = sec->next) 7072214082Sdim { 7073214082Sdim /* Ignore synthetic glue sections. */ 7074214082Sdim if (strcmp (sec->name, ".glue_7") 7075214082Sdim && strcmp (sec->name, ".glue_7t")) 7076214082Sdim { 7077214082Sdim if ((bfd_get_section_flags (ibfd, sec) 7078214082Sdim & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) 7079214082Sdim == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) 7080214082Sdim only_data_sections = FALSE; 7081214082Sdim 7082214082Sdim null_input_bfd = FALSE; 7083214082Sdim break; 7084214082Sdim } 7085214082Sdim } 7086214082Sdim 7087214082Sdim if (null_input_bfd || only_data_sections) 7088214082Sdim return TRUE; 7089214082Sdim } 7090214082Sdim 7091214082Sdim /* Complain about various flag mismatches. */ 7092214082Sdim if (!elf32_arm_versions_compatible (EF_ARM_EABI_VERSION (in_flags), 7093214082Sdim EF_ARM_EABI_VERSION (out_flags))) 7094214082Sdim { 7095214082Sdim _bfd_error_handler 7096214082Sdim (_("ERROR: Source object %B has EABI version %d, but target %B has EABI version %d"), 7097214082Sdim ibfd, obfd, 7098214082Sdim (in_flags & EF_ARM_EABIMASK) >> 24, 7099214082Sdim (out_flags & EF_ARM_EABIMASK) >> 24); 7100214082Sdim return FALSE; 7101214082Sdim } 7102214082Sdim 7103214082Sdim /* Not sure what needs to be checked for EABI versions >= 1. */ 7104214082Sdim /* VxWorks libraries do not use these flags. */ 7105214082Sdim if (get_elf_backend_data (obfd) != &elf32_arm_vxworks_bed 7106214082Sdim && get_elf_backend_data (ibfd) != &elf32_arm_vxworks_bed 7107214082Sdim && EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN) 7108214082Sdim { 7109214082Sdim if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26)) 7110214082Sdim { 7111214082Sdim _bfd_error_handler 7112214082Sdim (_("ERROR: %B is compiled for APCS-%d, whereas target %B uses APCS-%d"), 7113214082Sdim ibfd, obfd, 7114214082Sdim in_flags & EF_ARM_APCS_26 ? 26 : 32, 7115214082Sdim out_flags & EF_ARM_APCS_26 ? 26 : 32); 7116214082Sdim flags_compatible = FALSE; 7117214082Sdim } 7118214082Sdim 7119214082Sdim if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT)) 7120214082Sdim { 7121214082Sdim if (in_flags & EF_ARM_APCS_FLOAT) 7122214082Sdim _bfd_error_handler 7123214082Sdim (_("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers"), 7124214082Sdim ibfd, obfd); 7125214082Sdim else 7126214082Sdim _bfd_error_handler 7127214082Sdim (_("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers"), 7128214082Sdim ibfd, obfd); 7129214082Sdim 7130214082Sdim flags_compatible = FALSE; 7131214082Sdim } 7132214082Sdim 7133214082Sdim if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT)) 7134214082Sdim { 7135214082Sdim if (in_flags & EF_ARM_VFP_FLOAT) 7136214082Sdim _bfd_error_handler 7137214082Sdim (_("ERROR: %B uses VFP instructions, whereas %B does not"), 7138214082Sdim ibfd, obfd); 7139214082Sdim else 7140214082Sdim _bfd_error_handler 7141214082Sdim (_("ERROR: %B uses FPA instructions, whereas %B does not"), 7142214082Sdim ibfd, obfd); 7143214082Sdim 7144214082Sdim flags_compatible = FALSE; 7145214082Sdim } 7146214082Sdim 7147214082Sdim if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT)) 7148214082Sdim { 7149214082Sdim if (in_flags & EF_ARM_MAVERICK_FLOAT) 7150214082Sdim _bfd_error_handler 7151214082Sdim (_("ERROR: %B uses Maverick instructions, whereas %B does not"), 7152214082Sdim ibfd, obfd); 7153214082Sdim else 7154214082Sdim _bfd_error_handler 7155214082Sdim (_("ERROR: %B does not use Maverick instructions, whereas %B does"), 7156214082Sdim ibfd, obfd); 7157214082Sdim 7158214082Sdim flags_compatible = FALSE; 7159214082Sdim } 7160214082Sdim 7161214082Sdim#ifdef EF_ARM_SOFT_FLOAT 7162214082Sdim if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT)) 7163214082Sdim { 7164214082Sdim /* We can allow interworking between code that is VFP format 7165214082Sdim layout, and uses either soft float or integer regs for 7166214082Sdim passing floating point arguments and results. We already 7167214082Sdim know that the APCS_FLOAT flags match; similarly for VFP 7168214082Sdim flags. */ 7169214082Sdim if ((in_flags & EF_ARM_APCS_FLOAT) != 0 7170214082Sdim || (in_flags & EF_ARM_VFP_FLOAT) == 0) 7171214082Sdim { 7172214082Sdim if (in_flags & EF_ARM_SOFT_FLOAT) 7173214082Sdim _bfd_error_handler 7174214082Sdim (_("ERROR: %B uses software FP, whereas %B uses hardware FP"), 7175214082Sdim ibfd, obfd); 7176214082Sdim else 7177214082Sdim _bfd_error_handler 7178214082Sdim (_("ERROR: %B uses hardware FP, whereas %B uses software FP"), 7179214082Sdim ibfd, obfd); 7180214082Sdim 7181214082Sdim flags_compatible = FALSE; 7182214082Sdim } 7183214082Sdim } 7184214082Sdim#endif 7185214082Sdim 7186214082Sdim /* Interworking mismatch is only a warning. */ 7187214082Sdim if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) 7188214082Sdim { 7189214082Sdim if (in_flags & EF_ARM_INTERWORK) 7190214082Sdim { 7191214082Sdim _bfd_error_handler 7192214082Sdim (_("Warning: %B supports interworking, whereas %B does not"), 7193214082Sdim ibfd, obfd); 7194214082Sdim } 7195214082Sdim else 7196214082Sdim { 7197214082Sdim _bfd_error_handler 7198214082Sdim (_("Warning: %B does not support interworking, whereas %B does"), 7199214082Sdim ibfd, obfd); 7200214082Sdim } 7201214082Sdim } 7202214082Sdim } 7203214082Sdim 7204214082Sdim return flags_compatible; 7205214082Sdim} 7206214082Sdim 7207214082Sdim/* Display the flags field. */ 7208214082Sdim 7209214082Sdimstatic bfd_boolean 7210214082Sdimelf32_arm_print_private_bfd_data (bfd *abfd, void * ptr) 7211214082Sdim{ 7212214082Sdim FILE * file = (FILE *) ptr; 7213214082Sdim unsigned long flags; 7214214082Sdim 7215214082Sdim BFD_ASSERT (abfd != NULL && ptr != NULL); 7216214082Sdim 7217214082Sdim /* Print normal ELF private data. */ 7218214082Sdim _bfd_elf_print_private_bfd_data (abfd, ptr); 7219214082Sdim 7220214082Sdim flags = elf_elfheader (abfd)->e_flags; 7221214082Sdim /* Ignore init flag - it may not be set, despite the flags field 7222214082Sdim containing valid data. */ 7223214082Sdim 7224214082Sdim /* xgettext:c-format */ 7225214082Sdim fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags); 7226214082Sdim 7227214082Sdim switch (EF_ARM_EABI_VERSION (flags)) 7228214082Sdim { 7229214082Sdim case EF_ARM_EABI_UNKNOWN: 7230214082Sdim /* The following flag bits are GNU extensions and not part of the 7231214082Sdim official ARM ELF extended ABI. Hence they are only decoded if 7232214082Sdim the EABI version is not set. */ 7233214082Sdim if (flags & EF_ARM_INTERWORK) 7234214082Sdim fprintf (file, _(" [interworking enabled]")); 7235214082Sdim 7236214082Sdim if (flags & EF_ARM_APCS_26) 7237214082Sdim fprintf (file, " [APCS-26]"); 7238214082Sdim else 7239214082Sdim fprintf (file, " [APCS-32]"); 7240214082Sdim 7241214082Sdim if (flags & EF_ARM_VFP_FLOAT) 7242214082Sdim fprintf (file, _(" [VFP float format]")); 7243214082Sdim else if (flags & EF_ARM_MAVERICK_FLOAT) 7244214082Sdim fprintf (file, _(" [Maverick float format]")); 7245214082Sdim else 7246214082Sdim fprintf (file, _(" [FPA float format]")); 7247214082Sdim 7248214082Sdim if (flags & EF_ARM_APCS_FLOAT) 7249214082Sdim fprintf (file, _(" [floats passed in float registers]")); 7250214082Sdim 7251214082Sdim if (flags & EF_ARM_PIC) 7252214082Sdim fprintf (file, _(" [position independent]")); 7253214082Sdim 7254214082Sdim if (flags & EF_ARM_NEW_ABI) 7255214082Sdim fprintf (file, _(" [new ABI]")); 7256214082Sdim 7257214082Sdim if (flags & EF_ARM_OLD_ABI) 7258214082Sdim fprintf (file, _(" [old ABI]")); 7259214082Sdim 7260214082Sdim if (flags & EF_ARM_SOFT_FLOAT) 7261214082Sdim fprintf (file, _(" [software FP]")); 7262214082Sdim 7263214082Sdim flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT 7264214082Sdim | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI 7265214082Sdim | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT 7266214082Sdim | EF_ARM_MAVERICK_FLOAT); 7267214082Sdim break; 7268214082Sdim 7269214082Sdim case EF_ARM_EABI_VER1: 7270214082Sdim fprintf (file, _(" [Version1 EABI]")); 7271214082Sdim 7272214082Sdim if (flags & EF_ARM_SYMSARESORTED) 7273214082Sdim fprintf (file, _(" [sorted symbol table]")); 7274214082Sdim else 7275214082Sdim fprintf (file, _(" [unsorted symbol table]")); 7276214082Sdim 7277214082Sdim flags &= ~ EF_ARM_SYMSARESORTED; 7278214082Sdim break; 7279214082Sdim 7280214082Sdim case EF_ARM_EABI_VER2: 7281214082Sdim fprintf (file, _(" [Version2 EABI]")); 7282214082Sdim 7283214082Sdim if (flags & EF_ARM_SYMSARESORTED) 7284214082Sdim fprintf (file, _(" [sorted symbol table]")); 7285214082Sdim else 7286214082Sdim fprintf (file, _(" [unsorted symbol table]")); 7287214082Sdim 7288214082Sdim if (flags & EF_ARM_DYNSYMSUSESEGIDX) 7289214082Sdim fprintf (file, _(" [dynamic symbols use segment index]")); 7290214082Sdim 7291214082Sdim if (flags & EF_ARM_MAPSYMSFIRST) 7292214082Sdim fprintf (file, _(" [mapping symbols precede others]")); 7293214082Sdim 7294214082Sdim flags &= ~(EF_ARM_SYMSARESORTED | EF_ARM_DYNSYMSUSESEGIDX 7295214082Sdim | EF_ARM_MAPSYMSFIRST); 7296214082Sdim break; 7297214082Sdim 7298214082Sdim case EF_ARM_EABI_VER3: 7299214082Sdim fprintf (file, _(" [Version3 EABI]")); 7300214082Sdim break; 7301214082Sdim 7302214082Sdim case EF_ARM_EABI_VER4: 7303214082Sdim fprintf (file, _(" [Version4 EABI]")); 7304214082Sdim goto eabi; 7305214082Sdim 7306214082Sdim case EF_ARM_EABI_VER5: 7307214082Sdim fprintf (file, _(" [Version5 EABI]")); 7308214082Sdim eabi: 7309214082Sdim if (flags & EF_ARM_BE8) 7310214082Sdim fprintf (file, _(" [BE8]")); 7311214082Sdim 7312214082Sdim if (flags & EF_ARM_LE8) 7313214082Sdim fprintf (file, _(" [LE8]")); 7314214082Sdim 7315214082Sdim flags &= ~(EF_ARM_LE8 | EF_ARM_BE8); 7316214082Sdim break; 7317214082Sdim 7318214082Sdim default: 7319214082Sdim fprintf (file, _(" <EABI version unrecognised>")); 7320214082Sdim break; 7321214082Sdim } 7322214082Sdim 7323214082Sdim flags &= ~ EF_ARM_EABIMASK; 7324214082Sdim 7325214082Sdim if (flags & EF_ARM_RELEXEC) 7326214082Sdim fprintf (file, _(" [relocatable executable]")); 7327214082Sdim 7328214082Sdim if (flags & EF_ARM_HASENTRY) 7329214082Sdim fprintf (file, _(" [has entry point]")); 7330214082Sdim 7331214082Sdim flags &= ~ (EF_ARM_RELEXEC | EF_ARM_HASENTRY); 7332214082Sdim 7333214082Sdim if (flags) 7334214082Sdim fprintf (file, _("<Unrecognised flag bits set>")); 7335214082Sdim 7336214082Sdim fputc ('\n', file); 7337214082Sdim 7338214082Sdim return TRUE; 7339214082Sdim} 7340214082Sdim 7341214082Sdimstatic int 7342214082Sdimelf32_arm_get_symbol_type (Elf_Internal_Sym * elf_sym, int type) 7343214082Sdim{ 7344214082Sdim switch (ELF_ST_TYPE (elf_sym->st_info)) 7345214082Sdim { 7346214082Sdim case STT_ARM_TFUNC: 7347214082Sdim return ELF_ST_TYPE (elf_sym->st_info); 7348214082Sdim 7349214082Sdim case STT_ARM_16BIT: 7350214082Sdim /* If the symbol is not an object, return the STT_ARM_16BIT flag. 7351214082Sdim This allows us to distinguish between data used by Thumb instructions 7352214082Sdim and non-data (which is probably code) inside Thumb regions of an 7353214082Sdim executable. */ 7354214082Sdim if (type != STT_OBJECT && type != STT_TLS) 7355214082Sdim return ELF_ST_TYPE (elf_sym->st_info); 7356214082Sdim break; 7357214082Sdim 7358214082Sdim default: 7359214082Sdim break; 7360214082Sdim } 7361214082Sdim 7362214082Sdim return type; 7363214082Sdim} 7364214082Sdim 7365214082Sdimstatic asection * 7366214634Sdimelf32_arm_gc_mark_hook (asection *sec, 7367214634Sdim struct bfd_link_info *info, 7368214634Sdim Elf_Internal_Rela *rel, 7369214634Sdim struct elf_link_hash_entry *h, 7370214634Sdim Elf_Internal_Sym *sym) 7371214082Sdim{ 7372214082Sdim if (h != NULL) 7373214634Sdim switch (ELF32_R_TYPE (rel->r_info)) 7374214082Sdim { 7375214082Sdim case R_ARM_GNU_VTINHERIT: 7376214082Sdim case R_ARM_GNU_VTENTRY: 7377214634Sdim return NULL; 7378214634Sdim } 7379214082Sdim 7380214634Sdim return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 7381214082Sdim} 7382214082Sdim 7383214082Sdim/* Update the got entry reference counts for the section being removed. */ 7384214082Sdim 7385214082Sdimstatic bfd_boolean 7386214082Sdimelf32_arm_gc_sweep_hook (bfd * abfd, 7387214082Sdim struct bfd_link_info * info, 7388214082Sdim asection * sec, 7389214082Sdim const Elf_Internal_Rela * relocs) 7390214082Sdim{ 7391214082Sdim Elf_Internal_Shdr *symtab_hdr; 7392214082Sdim struct elf_link_hash_entry **sym_hashes; 7393214082Sdim bfd_signed_vma *local_got_refcounts; 7394214082Sdim const Elf_Internal_Rela *rel, *relend; 7395214082Sdim struct elf32_arm_link_hash_table * globals; 7396214082Sdim 7397214082Sdim globals = elf32_arm_hash_table (info); 7398214082Sdim 7399214082Sdim elf_section_data (sec)->local_dynrel = NULL; 7400214082Sdim 7401214082Sdim symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 7402214082Sdim sym_hashes = elf_sym_hashes (abfd); 7403214082Sdim local_got_refcounts = elf_local_got_refcounts (abfd); 7404214082Sdim 7405214082Sdim relend = relocs + sec->reloc_count; 7406214082Sdim for (rel = relocs; rel < relend; rel++) 7407214082Sdim { 7408214082Sdim unsigned long r_symndx; 7409214082Sdim struct elf_link_hash_entry *h = NULL; 7410214082Sdim int r_type; 7411214082Sdim 7412214082Sdim r_symndx = ELF32_R_SYM (rel->r_info); 7413214082Sdim if (r_symndx >= symtab_hdr->sh_info) 7414214082Sdim { 7415214082Sdim h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 7416214082Sdim while (h->root.type == bfd_link_hash_indirect 7417214082Sdim || h->root.type == bfd_link_hash_warning) 7418214082Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 7419214082Sdim } 7420214082Sdim 7421214082Sdim r_type = ELF32_R_TYPE (rel->r_info); 7422214082Sdim r_type = arm_real_reloc_type (globals, r_type); 7423214082Sdim switch (r_type) 7424214082Sdim { 7425214082Sdim case R_ARM_GOT32: 7426214082Sdim case R_ARM_GOT_PREL: 7427214082Sdim case R_ARM_TLS_GD32: 7428214082Sdim case R_ARM_TLS_IE32: 7429214082Sdim if (h != NULL) 7430214082Sdim { 7431214082Sdim if (h->got.refcount > 0) 7432214082Sdim h->got.refcount -= 1; 7433214082Sdim } 7434214082Sdim else if (local_got_refcounts != NULL) 7435214082Sdim { 7436214082Sdim if (local_got_refcounts[r_symndx] > 0) 7437214082Sdim local_got_refcounts[r_symndx] -= 1; 7438214082Sdim } 7439214082Sdim break; 7440214082Sdim 7441214082Sdim case R_ARM_TLS_LDM32: 7442214082Sdim elf32_arm_hash_table (info)->tls_ldm_got.refcount -= 1; 7443214082Sdim break; 7444214082Sdim 7445214082Sdim case R_ARM_ABS32: 7446214634Sdim case R_ARM_ABS32_NOI: 7447214082Sdim case R_ARM_REL32: 7448214634Sdim case R_ARM_REL32_NOI: 7449214082Sdim case R_ARM_PC24: 7450214082Sdim case R_ARM_PLT32: 7451214082Sdim case R_ARM_CALL: 7452214082Sdim case R_ARM_JUMP24: 7453214082Sdim case R_ARM_PREL31: 7454214082Sdim case R_ARM_THM_CALL: 7455214634Sdim case R_ARM_MOVW_ABS_NC: 7456214634Sdim case R_ARM_MOVT_ABS: 7457214634Sdim case R_ARM_MOVW_PREL_NC: 7458214634Sdim case R_ARM_MOVT_PREL: 7459214634Sdim case R_ARM_THM_MOVW_ABS_NC: 7460214634Sdim case R_ARM_THM_MOVT_ABS: 7461214634Sdim case R_ARM_THM_MOVW_PREL_NC: 7462214634Sdim case R_ARM_THM_MOVT_PREL: 7463214082Sdim /* Should the interworking branches be here also? */ 7464214082Sdim 7465214082Sdim if (h != NULL) 7466214082Sdim { 7467214082Sdim struct elf32_arm_link_hash_entry *eh; 7468214082Sdim struct elf32_arm_relocs_copied **pp; 7469214082Sdim struct elf32_arm_relocs_copied *p; 7470214082Sdim 7471214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 7472214082Sdim 7473214082Sdim if (h->plt.refcount > 0) 7474214082Sdim { 7475214082Sdim h->plt.refcount -= 1; 7476214082Sdim if (ELF32_R_TYPE (rel->r_info) == R_ARM_THM_CALL) 7477214082Sdim eh->plt_thumb_refcount--; 7478214082Sdim } 7479214082Sdim 7480214082Sdim if (r_type == R_ARM_ABS32 7481214634Sdim || r_type == R_ARM_REL32 7482214634Sdim || r_type == R_ARM_ABS32_NOI 7483214634Sdim || r_type == R_ARM_REL32_NOI) 7484214082Sdim { 7485214082Sdim for (pp = &eh->relocs_copied; (p = *pp) != NULL; 7486214082Sdim pp = &p->next) 7487214082Sdim if (p->section == sec) 7488214082Sdim { 7489214082Sdim p->count -= 1; 7490214634Sdim if (ELF32_R_TYPE (rel->r_info) == R_ARM_REL32 7491214634Sdim || ELF32_R_TYPE (rel->r_info) == R_ARM_REL32_NOI) 7492214082Sdim p->pc_count -= 1; 7493214082Sdim if (p->count == 0) 7494214082Sdim *pp = p->next; 7495214082Sdim break; 7496214082Sdim } 7497214082Sdim } 7498214082Sdim } 7499214082Sdim break; 7500214082Sdim 7501214082Sdim default: 7502214082Sdim break; 7503214082Sdim } 7504214082Sdim } 7505214082Sdim 7506214082Sdim return TRUE; 7507214082Sdim} 7508214082Sdim 7509214082Sdim/* Look through the relocs for a section during the first phase. */ 7510214082Sdim 7511214082Sdimstatic bfd_boolean 7512214082Sdimelf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info, 7513214082Sdim asection *sec, const Elf_Internal_Rela *relocs) 7514214082Sdim{ 7515214082Sdim Elf_Internal_Shdr *symtab_hdr; 7516214082Sdim struct elf_link_hash_entry **sym_hashes; 7517214082Sdim struct elf_link_hash_entry **sym_hashes_end; 7518214082Sdim const Elf_Internal_Rela *rel; 7519214082Sdim const Elf_Internal_Rela *rel_end; 7520214082Sdim bfd *dynobj; 7521214082Sdim asection *sreloc; 7522214082Sdim bfd_vma *local_got_offsets; 7523214082Sdim struct elf32_arm_link_hash_table *htab; 7524214082Sdim 7525214082Sdim if (info->relocatable) 7526214082Sdim return TRUE; 7527214082Sdim 7528214082Sdim htab = elf32_arm_hash_table (info); 7529214082Sdim sreloc = NULL; 7530214082Sdim 7531214082Sdim /* Create dynamic sections for relocatable executables so that we can 7532214082Sdim copy relocations. */ 7533214082Sdim if (htab->root.is_relocatable_executable 7534214082Sdim && ! htab->root.dynamic_sections_created) 7535214082Sdim { 7536214082Sdim if (! _bfd_elf_link_create_dynamic_sections (abfd, info)) 7537214082Sdim return FALSE; 7538214082Sdim } 7539214082Sdim 7540214082Sdim dynobj = elf_hash_table (info)->dynobj; 7541214082Sdim local_got_offsets = elf_local_got_offsets (abfd); 7542214082Sdim 7543214082Sdim symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 7544214082Sdim sym_hashes = elf_sym_hashes (abfd); 7545214082Sdim sym_hashes_end = sym_hashes 7546214082Sdim + symtab_hdr->sh_size / sizeof (Elf32_External_Sym); 7547214082Sdim 7548214082Sdim if (!elf_bad_symtab (abfd)) 7549214082Sdim sym_hashes_end -= symtab_hdr->sh_info; 7550214082Sdim 7551214082Sdim rel_end = relocs + sec->reloc_count; 7552214082Sdim for (rel = relocs; rel < rel_end; rel++) 7553214082Sdim { 7554214082Sdim struct elf_link_hash_entry *h; 7555214082Sdim struct elf32_arm_link_hash_entry *eh; 7556214082Sdim unsigned long r_symndx; 7557214082Sdim int r_type; 7558214082Sdim 7559214082Sdim r_symndx = ELF32_R_SYM (rel->r_info); 7560214082Sdim r_type = ELF32_R_TYPE (rel->r_info); 7561214082Sdim r_type = arm_real_reloc_type (htab, r_type); 7562214082Sdim 7563214082Sdim if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) 7564214082Sdim { 7565214082Sdim (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd, 7566214082Sdim r_symndx); 7567214082Sdim return FALSE; 7568214082Sdim } 7569214082Sdim 7570214082Sdim if (r_symndx < symtab_hdr->sh_info) 7571214082Sdim h = NULL; 7572214082Sdim else 7573214082Sdim { 7574214082Sdim h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 7575214082Sdim while (h->root.type == bfd_link_hash_indirect 7576214082Sdim || h->root.type == bfd_link_hash_warning) 7577214082Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 7578214082Sdim } 7579214082Sdim 7580214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 7581214082Sdim 7582214082Sdim switch (r_type) 7583214082Sdim { 7584214082Sdim case R_ARM_GOT32: 7585214082Sdim case R_ARM_GOT_PREL: 7586214082Sdim case R_ARM_TLS_GD32: 7587214082Sdim case R_ARM_TLS_IE32: 7588214082Sdim /* This symbol requires a global offset table entry. */ 7589214082Sdim { 7590214082Sdim int tls_type, old_tls_type; 7591214082Sdim 7592214082Sdim switch (r_type) 7593214082Sdim { 7594214082Sdim case R_ARM_TLS_GD32: tls_type = GOT_TLS_GD; break; 7595214082Sdim case R_ARM_TLS_IE32: tls_type = GOT_TLS_IE; break; 7596214082Sdim default: tls_type = GOT_NORMAL; break; 7597214082Sdim } 7598214082Sdim 7599214082Sdim if (h != NULL) 7600214082Sdim { 7601214082Sdim h->got.refcount++; 7602214082Sdim old_tls_type = elf32_arm_hash_entry (h)->tls_type; 7603214082Sdim } 7604214082Sdim else 7605214082Sdim { 7606214082Sdim bfd_signed_vma *local_got_refcounts; 7607214082Sdim 7608214082Sdim /* This is a global offset table entry for a local symbol. */ 7609214082Sdim local_got_refcounts = elf_local_got_refcounts (abfd); 7610214082Sdim if (local_got_refcounts == NULL) 7611214082Sdim { 7612214082Sdim bfd_size_type size; 7613214082Sdim 7614214082Sdim size = symtab_hdr->sh_info; 7615214082Sdim size *= (sizeof (bfd_signed_vma) + sizeof(char)); 7616214082Sdim local_got_refcounts = bfd_zalloc (abfd, size); 7617214082Sdim if (local_got_refcounts == NULL) 7618214082Sdim return FALSE; 7619214082Sdim elf_local_got_refcounts (abfd) = local_got_refcounts; 7620214082Sdim elf32_arm_local_got_tls_type (abfd) 7621214082Sdim = (char *) (local_got_refcounts + symtab_hdr->sh_info); 7622214082Sdim } 7623214082Sdim local_got_refcounts[r_symndx] += 1; 7624214082Sdim old_tls_type = elf32_arm_local_got_tls_type (abfd) [r_symndx]; 7625214082Sdim } 7626214082Sdim 7627214082Sdim /* We will already have issued an error message if there is a 7628214082Sdim TLS / non-TLS mismatch, based on the symbol type. We don't 7629214082Sdim support any linker relaxations. So just combine any TLS 7630214082Sdim types needed. */ 7631214082Sdim if (old_tls_type != GOT_UNKNOWN && old_tls_type != GOT_NORMAL 7632214082Sdim && tls_type != GOT_NORMAL) 7633214082Sdim tls_type |= old_tls_type; 7634214082Sdim 7635214082Sdim if (old_tls_type != tls_type) 7636214082Sdim { 7637214082Sdim if (h != NULL) 7638214082Sdim elf32_arm_hash_entry (h)->tls_type = tls_type; 7639214082Sdim else 7640214082Sdim elf32_arm_local_got_tls_type (abfd) [r_symndx] = tls_type; 7641214082Sdim } 7642214082Sdim } 7643214082Sdim /* Fall through */ 7644214082Sdim 7645214082Sdim case R_ARM_TLS_LDM32: 7646214082Sdim if (r_type == R_ARM_TLS_LDM32) 7647214082Sdim htab->tls_ldm_got.refcount++; 7648214082Sdim /* Fall through */ 7649214082Sdim 7650214082Sdim case R_ARM_GOTOFF32: 7651214082Sdim case R_ARM_GOTPC: 7652214082Sdim if (htab->sgot == NULL) 7653214082Sdim { 7654214082Sdim if (htab->root.dynobj == NULL) 7655214082Sdim htab->root.dynobj = abfd; 7656214082Sdim if (!create_got_section (htab->root.dynobj, info)) 7657214082Sdim return FALSE; 7658214082Sdim } 7659214082Sdim break; 7660214082Sdim 7661214082Sdim case R_ARM_ABS12: 7662214082Sdim /* VxWorks uses dynamic R_ARM_ABS12 relocations for 7663214082Sdim ldr __GOTT_INDEX__ offsets. */ 7664214082Sdim if (!htab->vxworks_p) 7665214082Sdim break; 7666214082Sdim /* Fall through */ 7667214082Sdim 7668214082Sdim case R_ARM_ABS32: 7669214634Sdim case R_ARM_ABS32_NOI: 7670214082Sdim case R_ARM_REL32: 7671214634Sdim case R_ARM_REL32_NOI: 7672214082Sdim case R_ARM_PC24: 7673214082Sdim case R_ARM_PLT32: 7674214082Sdim case R_ARM_CALL: 7675214082Sdim case R_ARM_JUMP24: 7676214082Sdim case R_ARM_PREL31: 7677214082Sdim case R_ARM_THM_CALL: 7678214634Sdim case R_ARM_MOVW_ABS_NC: 7679214634Sdim case R_ARM_MOVT_ABS: 7680214634Sdim case R_ARM_MOVW_PREL_NC: 7681214634Sdim case R_ARM_MOVT_PREL: 7682214634Sdim case R_ARM_THM_MOVW_ABS_NC: 7683214634Sdim case R_ARM_THM_MOVT_ABS: 7684214634Sdim case R_ARM_THM_MOVW_PREL_NC: 7685214634Sdim case R_ARM_THM_MOVT_PREL: 7686214082Sdim /* Should the interworking branches be listed here? */ 7687214082Sdim if (h != NULL) 7688214082Sdim { 7689214082Sdim /* If this reloc is in a read-only section, we might 7690214082Sdim need a copy reloc. We can't check reliably at this 7691214082Sdim stage whether the section is read-only, as input 7692214082Sdim sections have not yet been mapped to output sections. 7693214082Sdim Tentatively set the flag for now, and correct in 7694214082Sdim adjust_dynamic_symbol. */ 7695214082Sdim if (!info->shared) 7696214082Sdim h->non_got_ref = 1; 7697214082Sdim 7698214082Sdim /* We may need a .plt entry if the function this reloc 7699214082Sdim refers to is in a different object. We can't tell for 7700214082Sdim sure yet, because something later might force the 7701214082Sdim symbol local. */ 7702214634Sdim if (r_type != R_ARM_ABS32 7703214634Sdim && r_type != R_ARM_REL32 7704214634Sdim && r_type != R_ARM_ABS32_NOI 7705214634Sdim && r_type != R_ARM_REL32_NOI 7706214634Sdim && r_type != R_ARM_ABS12) 7707214082Sdim h->needs_plt = 1; 7708214082Sdim 7709214082Sdim /* If we create a PLT entry, this relocation will reference 7710214082Sdim it, even if it's an ABS32 relocation. */ 7711214082Sdim h->plt.refcount += 1; 7712214082Sdim 7713214082Sdim if (r_type == R_ARM_THM_CALL) 7714214082Sdim eh->plt_thumb_refcount += 1; 7715214082Sdim } 7716214082Sdim 7717214082Sdim /* If we are creating a shared library or relocatable executable, 7718214082Sdim and this is a reloc against a global symbol, or a non PC 7719214082Sdim relative reloc against a local symbol, then we need to copy 7720214082Sdim the reloc into the shared library. However, if we are linking 7721214082Sdim with -Bsymbolic, we do not need to copy a reloc against a 7722214082Sdim global symbol which is defined in an object we are 7723214082Sdim including in the link (i.e., DEF_REGULAR is set). At 7724214082Sdim this point we have not seen all the input files, so it is 7725214082Sdim possible that DEF_REGULAR is not set now but will be set 7726214082Sdim later (it is never cleared). We account for that 7727214082Sdim possibility below by storing information in the 7728214082Sdim relocs_copied field of the hash table entry. */ 7729214082Sdim if ((info->shared || htab->root.is_relocatable_executable) 7730214082Sdim && (sec->flags & SEC_ALLOC) != 0 7731214634Sdim && ((r_type == R_ARM_ABS32 || r_type == R_ARM_ABS32_NOI) 7732214082Sdim || (h != NULL && ! h->needs_plt 7733214082Sdim && (! info->symbolic || ! h->def_regular)))) 7734214082Sdim { 7735214082Sdim struct elf32_arm_relocs_copied *p, **head; 7736214082Sdim 7737214082Sdim /* When creating a shared object, we must copy these 7738214082Sdim reloc types into the output file. We create a reloc 7739214082Sdim section in dynobj and make room for this reloc. */ 7740214082Sdim if (sreloc == NULL) 7741214082Sdim { 7742214082Sdim const char * name; 7743214082Sdim 7744214082Sdim name = (bfd_elf_string_from_elf_section 7745214082Sdim (abfd, 7746214082Sdim elf_elfheader (abfd)->e_shstrndx, 7747214082Sdim elf_section_data (sec)->rel_hdr.sh_name)); 7748214082Sdim if (name == NULL) 7749214082Sdim return FALSE; 7750214082Sdim 7751214082Sdim BFD_ASSERT (reloc_section_p (htab, name, sec)); 7752214082Sdim 7753214082Sdim sreloc = bfd_get_section_by_name (dynobj, name); 7754214082Sdim if (sreloc == NULL) 7755214082Sdim { 7756214082Sdim flagword flags; 7757214082Sdim 7758214082Sdim flags = (SEC_HAS_CONTENTS | SEC_READONLY 7759214082Sdim | SEC_IN_MEMORY | SEC_LINKER_CREATED); 7760214082Sdim if ((sec->flags & SEC_ALLOC) != 0 7761214082Sdim /* BPABI objects never have dynamic 7762214082Sdim relocations mapped. */ 7763214082Sdim && !htab->symbian_p) 7764214082Sdim flags |= SEC_ALLOC | SEC_LOAD; 7765214082Sdim sreloc = bfd_make_section_with_flags (dynobj, 7766214082Sdim name, 7767214082Sdim flags); 7768214082Sdim if (sreloc == NULL 7769214082Sdim || ! bfd_set_section_alignment (dynobj, sreloc, 2)) 7770214082Sdim return FALSE; 7771214082Sdim } 7772214082Sdim 7773214082Sdim elf_section_data (sec)->sreloc = sreloc; 7774214082Sdim } 7775214082Sdim 7776214082Sdim /* If this is a global symbol, we count the number of 7777214082Sdim relocations we need for this symbol. */ 7778214082Sdim if (h != NULL) 7779214082Sdim { 7780214082Sdim head = &((struct elf32_arm_link_hash_entry *) h)->relocs_copied; 7781214082Sdim } 7782214082Sdim else 7783214082Sdim { 7784214082Sdim /* Track dynamic relocs needed for local syms too. 7785214082Sdim We really need local syms available to do this 7786214082Sdim easily. Oh well. */ 7787214082Sdim 7788214082Sdim asection *s; 7789214082Sdim void *vpp; 7790214082Sdim 7791214082Sdim s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 7792214082Sdim sec, r_symndx); 7793214082Sdim if (s == NULL) 7794214082Sdim return FALSE; 7795214082Sdim 7796214082Sdim vpp = &elf_section_data (s)->local_dynrel; 7797214082Sdim head = (struct elf32_arm_relocs_copied **) vpp; 7798214082Sdim } 7799214082Sdim 7800214082Sdim p = *head; 7801214082Sdim if (p == NULL || p->section != sec) 7802214082Sdim { 7803214082Sdim bfd_size_type amt = sizeof *p; 7804214082Sdim 7805214082Sdim p = bfd_alloc (htab->root.dynobj, amt); 7806214082Sdim if (p == NULL) 7807214082Sdim return FALSE; 7808214082Sdim p->next = *head; 7809214082Sdim *head = p; 7810214082Sdim p->section = sec; 7811214082Sdim p->count = 0; 7812214082Sdim p->pc_count = 0; 7813214082Sdim } 7814214082Sdim 7815214634Sdim if (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) 7816214082Sdim p->pc_count += 1; 7817214082Sdim p->count += 1; 7818214082Sdim } 7819214082Sdim break; 7820214082Sdim 7821214082Sdim /* This relocation describes the C++ object vtable hierarchy. 7822214082Sdim Reconstruct it for later use during GC. */ 7823214082Sdim case R_ARM_GNU_VTINHERIT: 7824214082Sdim if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 7825214082Sdim return FALSE; 7826214082Sdim break; 7827214082Sdim 7828214082Sdim /* This relocation describes which C++ vtable entries are actually 7829214082Sdim used. Record for later use during GC. */ 7830214082Sdim case R_ARM_GNU_VTENTRY: 7831214082Sdim if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) 7832214082Sdim return FALSE; 7833214082Sdim break; 7834214082Sdim } 7835214082Sdim } 7836214082Sdim 7837214082Sdim return TRUE; 7838214082Sdim} 7839214082Sdim 7840214634Sdim/* Unwinding tables are not referenced directly. This pass marks them as 7841214634Sdim required if the corresponding code section is marked. */ 7842214634Sdim 7843214634Sdimstatic bfd_boolean 7844214634Sdimelf32_arm_gc_mark_extra_sections(struct bfd_link_info *info, 7845214634Sdim elf_gc_mark_hook_fn gc_mark_hook) 7846214634Sdim{ 7847214634Sdim bfd *sub; 7848214634Sdim Elf_Internal_Shdr **elf_shdrp; 7849214634Sdim bfd_boolean again; 7850214634Sdim 7851214634Sdim /* Marking EH data may cause additional code sections to be marked, 7852214634Sdim requiring multiple passes. */ 7853214634Sdim again = TRUE; 7854214634Sdim while (again) 7855214634Sdim { 7856214634Sdim again = FALSE; 7857214634Sdim for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) 7858214634Sdim { 7859214634Sdim asection *o; 7860214634Sdim 7861214634Sdim if (bfd_get_flavour (sub) != bfd_target_elf_flavour) 7862214634Sdim continue; 7863214634Sdim 7864214634Sdim elf_shdrp = elf_elfsections (sub); 7865214634Sdim for (o = sub->sections; o != NULL; o = o->next) 7866214634Sdim { 7867214634Sdim Elf_Internal_Shdr *hdr; 7868214634Sdim hdr = &elf_section_data (o)->this_hdr; 7869214634Sdim if (hdr->sh_type == SHT_ARM_EXIDX && hdr->sh_link 7870214634Sdim && !o->gc_mark 7871214634Sdim && elf_shdrp[hdr->sh_link]->bfd_section->gc_mark) 7872214634Sdim { 7873214634Sdim again = TRUE; 7874214634Sdim if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) 7875214634Sdim return FALSE; 7876214634Sdim } 7877214634Sdim } 7878214634Sdim } 7879214634Sdim } 7880214634Sdim 7881214634Sdim return TRUE; 7882214634Sdim} 7883214634Sdim 7884214082Sdim/* Treat mapping symbols as special target symbols. */ 7885214082Sdim 7886214082Sdimstatic bfd_boolean 7887214082Sdimelf32_arm_is_target_special_symbol (bfd * abfd ATTRIBUTE_UNUSED, asymbol * sym) 7888214082Sdim{ 7889214634Sdim return bfd_is_arm_special_symbol_name (sym->name, 7890214634Sdim BFD_ARM_SPECIAL_SYM_TYPE_ANY); 7891214082Sdim} 7892214082Sdim 7893214082Sdim/* This is a copy of elf_find_function() from elf.c except that 7894214082Sdim ARM mapping symbols are ignored when looking for function names 7895214082Sdim and STT_ARM_TFUNC is considered to a function type. */ 7896214082Sdim 7897214082Sdimstatic bfd_boolean 7898214082Sdimarm_elf_find_function (bfd * abfd ATTRIBUTE_UNUSED, 7899214082Sdim asection * section, 7900214082Sdim asymbol ** symbols, 7901214082Sdim bfd_vma offset, 7902214082Sdim const char ** filename_ptr, 7903214082Sdim const char ** functionname_ptr) 7904214082Sdim{ 7905214082Sdim const char * filename = NULL; 7906214082Sdim asymbol * func = NULL; 7907214082Sdim bfd_vma low_func = 0; 7908214082Sdim asymbol ** p; 7909214082Sdim 7910214082Sdim for (p = symbols; *p != NULL; p++) 7911214082Sdim { 7912214082Sdim elf_symbol_type *q; 7913214082Sdim 7914214082Sdim q = (elf_symbol_type *) *p; 7915214082Sdim 7916214082Sdim switch (ELF_ST_TYPE (q->internal_elf_sym.st_info)) 7917214082Sdim { 7918214082Sdim default: 7919214082Sdim break; 7920214082Sdim case STT_FILE: 7921214082Sdim filename = bfd_asymbol_name (&q->symbol); 7922214082Sdim break; 7923214082Sdim case STT_FUNC: 7924214082Sdim case STT_ARM_TFUNC: 7925214082Sdim case STT_NOTYPE: 7926214634Sdim /* Skip mapping symbols. */ 7927214082Sdim if ((q->symbol.flags & BSF_LOCAL) 7928214634Sdim && bfd_is_arm_special_symbol_name (q->symbol.name, 7929214634Sdim BFD_ARM_SPECIAL_SYM_TYPE_ANY)) 7930214082Sdim continue; 7931214082Sdim /* Fall through. */ 7932214082Sdim if (bfd_get_section (&q->symbol) == section 7933214082Sdim && q->symbol.value >= low_func 7934214082Sdim && q->symbol.value <= offset) 7935214082Sdim { 7936214082Sdim func = (asymbol *) q; 7937214082Sdim low_func = q->symbol.value; 7938214082Sdim } 7939214082Sdim break; 7940214082Sdim } 7941214082Sdim } 7942214082Sdim 7943214082Sdim if (func == NULL) 7944214082Sdim return FALSE; 7945214082Sdim 7946214082Sdim if (filename_ptr) 7947214082Sdim *filename_ptr = filename; 7948214082Sdim if (functionname_ptr) 7949214082Sdim *functionname_ptr = bfd_asymbol_name (func); 7950214082Sdim 7951214082Sdim return TRUE; 7952214082Sdim} 7953214082Sdim 7954214082Sdim 7955214082Sdim/* Find the nearest line to a particular section and offset, for error 7956214082Sdim reporting. This code is a duplicate of the code in elf.c, except 7957214082Sdim that it uses arm_elf_find_function. */ 7958214082Sdim 7959214082Sdimstatic bfd_boolean 7960214082Sdimelf32_arm_find_nearest_line (bfd * abfd, 7961214082Sdim asection * section, 7962214082Sdim asymbol ** symbols, 7963214082Sdim bfd_vma offset, 7964214082Sdim const char ** filename_ptr, 7965214082Sdim const char ** functionname_ptr, 7966214082Sdim unsigned int * line_ptr) 7967214082Sdim{ 7968214082Sdim bfd_boolean found = FALSE; 7969214082Sdim 7970214082Sdim /* We skip _bfd_dwarf1_find_nearest_line since no known ARM toolchain uses it. */ 7971214082Sdim 7972214082Sdim if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, 7973214082Sdim filename_ptr, functionname_ptr, 7974214082Sdim line_ptr, 0, 7975214082Sdim & elf_tdata (abfd)->dwarf2_find_line_info)) 7976214082Sdim { 7977214082Sdim if (!*functionname_ptr) 7978214082Sdim arm_elf_find_function (abfd, section, symbols, offset, 7979214082Sdim *filename_ptr ? NULL : filename_ptr, 7980214082Sdim functionname_ptr); 7981214082Sdim 7982214082Sdim return TRUE; 7983214082Sdim } 7984214082Sdim 7985214082Sdim if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, 7986214082Sdim & found, filename_ptr, 7987214082Sdim functionname_ptr, line_ptr, 7988214082Sdim & elf_tdata (abfd)->line_info)) 7989214082Sdim return FALSE; 7990214082Sdim 7991214082Sdim if (found && (*functionname_ptr || *line_ptr)) 7992214082Sdim return TRUE; 7993214082Sdim 7994214082Sdim if (symbols == NULL) 7995214082Sdim return FALSE; 7996214082Sdim 7997214082Sdim if (! arm_elf_find_function (abfd, section, symbols, offset, 7998214082Sdim filename_ptr, functionname_ptr)) 7999214082Sdim return FALSE; 8000214082Sdim 8001214082Sdim *line_ptr = 0; 8002214082Sdim return TRUE; 8003214082Sdim} 8004214082Sdim 8005214082Sdimstatic bfd_boolean 8006214082Sdimelf32_arm_find_inliner_info (bfd * abfd, 8007214082Sdim const char ** filename_ptr, 8008214082Sdim const char ** functionname_ptr, 8009214082Sdim unsigned int * line_ptr) 8010214082Sdim{ 8011214082Sdim bfd_boolean found; 8012214082Sdim found = _bfd_dwarf2_find_inliner_info (abfd, filename_ptr, 8013214082Sdim functionname_ptr, line_ptr, 8014214082Sdim & elf_tdata (abfd)->dwarf2_find_line_info); 8015214082Sdim return found; 8016214082Sdim} 8017214082Sdim 8018214082Sdim/* Adjust a symbol defined by a dynamic object and referenced by a 8019214082Sdim regular object. The current definition is in some section of the 8020214082Sdim dynamic object, but we're not including those sections. We have to 8021214082Sdim change the definition to something the rest of the link can 8022214082Sdim understand. */ 8023214082Sdim 8024214082Sdimstatic bfd_boolean 8025214082Sdimelf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info, 8026214082Sdim struct elf_link_hash_entry * h) 8027214082Sdim{ 8028214082Sdim bfd * dynobj; 8029214082Sdim asection * s; 8030214082Sdim struct elf32_arm_link_hash_entry * eh; 8031214082Sdim struct elf32_arm_link_hash_table *globals; 8032214082Sdim 8033214082Sdim globals = elf32_arm_hash_table (info); 8034214082Sdim dynobj = elf_hash_table (info)->dynobj; 8035214082Sdim 8036214082Sdim /* Make sure we know what is going on here. */ 8037214082Sdim BFD_ASSERT (dynobj != NULL 8038214082Sdim && (h->needs_plt 8039214082Sdim || h->u.weakdef != NULL 8040214082Sdim || (h->def_dynamic 8041214082Sdim && h->ref_regular 8042214082Sdim && !h->def_regular))); 8043214082Sdim 8044214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 8045214082Sdim 8046214082Sdim /* If this is a function, put it in the procedure linkage table. We 8047214082Sdim will fill in the contents of the procedure linkage table later, 8048214082Sdim when we know the address of the .got section. */ 8049214082Sdim if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC 8050214082Sdim || h->needs_plt) 8051214082Sdim { 8052214082Sdim if (h->plt.refcount <= 0 8053214082Sdim || SYMBOL_CALLS_LOCAL (info, h) 8054214082Sdim || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT 8055214082Sdim && h->root.type == bfd_link_hash_undefweak)) 8056214082Sdim { 8057214082Sdim /* This case can occur if we saw a PLT32 reloc in an input 8058214082Sdim file, but the symbol was never referred to by a dynamic 8059214082Sdim object, or if all references were garbage collected. In 8060214082Sdim such a case, we don't actually need to build a procedure 8061214082Sdim linkage table, and we can just do a PC24 reloc instead. */ 8062214082Sdim h->plt.offset = (bfd_vma) -1; 8063214082Sdim eh->plt_thumb_refcount = 0; 8064214082Sdim h->needs_plt = 0; 8065214082Sdim } 8066214082Sdim 8067214082Sdim return TRUE; 8068214082Sdim } 8069214082Sdim else 8070214082Sdim { 8071214082Sdim /* It's possible that we incorrectly decided a .plt reloc was 8072214082Sdim needed for an R_ARM_PC24 or similar reloc to a non-function sym 8073214082Sdim in check_relocs. We can't decide accurately between function 8074214082Sdim and non-function syms in check-relocs; Objects loaded later in 8075214082Sdim the link may change h->type. So fix it now. */ 8076214082Sdim h->plt.offset = (bfd_vma) -1; 8077214082Sdim eh->plt_thumb_refcount = 0; 8078214082Sdim } 8079214082Sdim 8080214082Sdim /* If this is a weak symbol, and there is a real definition, the 8081214082Sdim processor independent code will have arranged for us to see the 8082214082Sdim real definition first, and we can just use the same value. */ 8083214082Sdim if (h->u.weakdef != NULL) 8084214082Sdim { 8085214082Sdim BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined 8086214082Sdim || h->u.weakdef->root.type == bfd_link_hash_defweak); 8087214082Sdim h->root.u.def.section = h->u.weakdef->root.u.def.section; 8088214082Sdim h->root.u.def.value = h->u.weakdef->root.u.def.value; 8089214082Sdim return TRUE; 8090214082Sdim } 8091214082Sdim 8092214082Sdim /* If there are no non-GOT references, we do not need a copy 8093214082Sdim relocation. */ 8094214082Sdim if (!h->non_got_ref) 8095214082Sdim return TRUE; 8096214082Sdim 8097214082Sdim /* This is a reference to a symbol defined by a dynamic object which 8098214082Sdim is not a function. */ 8099214082Sdim 8100214082Sdim /* If we are creating a shared library, we must presume that the 8101214082Sdim only references to the symbol are via the global offset table. 8102214082Sdim For such cases we need not do anything here; the relocations will 8103214082Sdim be handled correctly by relocate_section. Relocatable executables 8104214082Sdim can reference data in shared objects directly, so we don't need to 8105214082Sdim do anything here. */ 8106214082Sdim if (info->shared || globals->root.is_relocatable_executable) 8107214082Sdim return TRUE; 8108214082Sdim 8109214082Sdim if (h->size == 0) 8110214082Sdim { 8111214082Sdim (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), 8112214082Sdim h->root.root.string); 8113214082Sdim return TRUE; 8114214082Sdim } 8115214082Sdim 8116214082Sdim /* We must allocate the symbol in our .dynbss section, which will 8117214082Sdim become part of the .bss section of the executable. There will be 8118214082Sdim an entry for this symbol in the .dynsym section. The dynamic 8119214082Sdim object will contain position independent code, so all references 8120214082Sdim from the dynamic object to this symbol will go through the global 8121214082Sdim offset table. The dynamic linker will use the .dynsym entry to 8122214082Sdim determine the address it must put in the global offset table, so 8123214082Sdim both the dynamic object and the regular object will refer to the 8124214082Sdim same memory location for the variable. */ 8125214082Sdim s = bfd_get_section_by_name (dynobj, ".dynbss"); 8126214082Sdim BFD_ASSERT (s != NULL); 8127214082Sdim 8128214082Sdim /* We must generate a R_ARM_COPY reloc to tell the dynamic linker to 8129214082Sdim copy the initial value out of the dynamic object and into the 8130214082Sdim runtime process image. We need to remember the offset into the 8131214082Sdim .rel(a).bss section we are going to use. */ 8132214082Sdim if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 8133214082Sdim { 8134214082Sdim asection *srel; 8135214082Sdim 8136214082Sdim srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (globals, ".bss")); 8137214082Sdim BFD_ASSERT (srel != NULL); 8138214082Sdim srel->size += RELOC_SIZE (globals); 8139214082Sdim h->needs_copy = 1; 8140214082Sdim } 8141214082Sdim 8142214634Sdim return _bfd_elf_adjust_dynamic_copy (h, s); 8143214082Sdim} 8144214082Sdim 8145214082Sdim/* Allocate space in .plt, .got and associated reloc sections for 8146214082Sdim dynamic relocs. */ 8147214082Sdim 8148214082Sdimstatic bfd_boolean 8149214082Sdimallocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) 8150214082Sdim{ 8151214082Sdim struct bfd_link_info *info; 8152214082Sdim struct elf32_arm_link_hash_table *htab; 8153214082Sdim struct elf32_arm_link_hash_entry *eh; 8154214082Sdim struct elf32_arm_relocs_copied *p; 8155214082Sdim 8156214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 8157214082Sdim 8158214082Sdim if (h->root.type == bfd_link_hash_indirect) 8159214082Sdim return TRUE; 8160214082Sdim 8161214082Sdim if (h->root.type == bfd_link_hash_warning) 8162214082Sdim /* When warning symbols are created, they **replace** the "real" 8163214082Sdim entry in the hash table, thus we never get to see the real 8164214082Sdim symbol in a hash traversal. So look at it now. */ 8165214082Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 8166214082Sdim 8167214082Sdim info = (struct bfd_link_info *) inf; 8168214082Sdim htab = elf32_arm_hash_table (info); 8169214082Sdim 8170214082Sdim if (htab->root.dynamic_sections_created 8171214082Sdim && h->plt.refcount > 0) 8172214082Sdim { 8173214082Sdim /* Make sure this symbol is output as a dynamic symbol. 8174214082Sdim Undefined weak syms won't yet be marked as dynamic. */ 8175214082Sdim if (h->dynindx == -1 8176214082Sdim && !h->forced_local) 8177214082Sdim { 8178214082Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 8179214082Sdim return FALSE; 8180214082Sdim } 8181214082Sdim 8182214082Sdim if (info->shared 8183214082Sdim || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) 8184214082Sdim { 8185214082Sdim asection *s = htab->splt; 8186214082Sdim 8187214082Sdim /* If this is the first .plt entry, make room for the special 8188214082Sdim first entry. */ 8189214082Sdim if (s->size == 0) 8190214082Sdim s->size += htab->plt_header_size; 8191214082Sdim 8192214082Sdim h->plt.offset = s->size; 8193214082Sdim 8194214082Sdim /* If we will insert a Thumb trampoline before this PLT, leave room 8195214082Sdim for it. */ 8196214082Sdim if (!htab->use_blx && eh->plt_thumb_refcount > 0) 8197214082Sdim { 8198214082Sdim h->plt.offset += PLT_THUMB_STUB_SIZE; 8199214082Sdim s->size += PLT_THUMB_STUB_SIZE; 8200214082Sdim } 8201214082Sdim 8202214082Sdim /* If this symbol is not defined in a regular file, and we are 8203214082Sdim not generating a shared library, then set the symbol to this 8204214082Sdim location in the .plt. This is required to make function 8205214082Sdim pointers compare as equal between the normal executable and 8206214082Sdim the shared library. */ 8207214082Sdim if (! info->shared 8208214082Sdim && !h->def_regular) 8209214082Sdim { 8210214082Sdim h->root.u.def.section = s; 8211214082Sdim h->root.u.def.value = h->plt.offset; 8212214082Sdim 8213214082Sdim /* Make sure the function is not marked as Thumb, in case 8214214082Sdim it is the target of an ABS32 relocation, which will 8215214082Sdim point to the PLT entry. */ 8216214082Sdim if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC) 8217214082Sdim h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC); 8218214082Sdim } 8219214082Sdim 8220214082Sdim /* Make room for this entry. */ 8221214082Sdim s->size += htab->plt_entry_size; 8222214082Sdim 8223214082Sdim if (!htab->symbian_p) 8224214082Sdim { 8225214082Sdim /* We also need to make an entry in the .got.plt section, which 8226214082Sdim will be placed in the .got section by the linker script. */ 8227214082Sdim eh->plt_got_offset = htab->sgotplt->size; 8228214082Sdim htab->sgotplt->size += 4; 8229214082Sdim } 8230214082Sdim 8231214082Sdim /* We also need to make an entry in the .rel(a).plt section. */ 8232214082Sdim htab->srelplt->size += RELOC_SIZE (htab); 8233214082Sdim 8234214082Sdim /* VxWorks executables have a second set of relocations for 8235214082Sdim each PLT entry. They go in a separate relocation section, 8236214082Sdim which is processed by the kernel loader. */ 8237214082Sdim if (htab->vxworks_p && !info->shared) 8238214082Sdim { 8239214082Sdim /* There is a relocation for the initial PLT entry: 8240214082Sdim an R_ARM_32 relocation for _GLOBAL_OFFSET_TABLE_. */ 8241214082Sdim if (h->plt.offset == htab->plt_header_size) 8242214082Sdim htab->srelplt2->size += RELOC_SIZE (htab); 8243214082Sdim 8244214082Sdim /* There are two extra relocations for each subsequent 8245214082Sdim PLT entry: an R_ARM_32 relocation for the GOT entry, 8246214082Sdim and an R_ARM_32 relocation for the PLT entry. */ 8247214082Sdim htab->srelplt2->size += RELOC_SIZE (htab) * 2; 8248214082Sdim } 8249214082Sdim } 8250214082Sdim else 8251214082Sdim { 8252214082Sdim h->plt.offset = (bfd_vma) -1; 8253214082Sdim h->needs_plt = 0; 8254214082Sdim } 8255214082Sdim } 8256214082Sdim else 8257214082Sdim { 8258214082Sdim h->plt.offset = (bfd_vma) -1; 8259214082Sdim h->needs_plt = 0; 8260214082Sdim } 8261214082Sdim 8262214082Sdim if (h->got.refcount > 0) 8263214082Sdim { 8264214082Sdim asection *s; 8265214082Sdim bfd_boolean dyn; 8266214082Sdim int tls_type = elf32_arm_hash_entry (h)->tls_type; 8267214082Sdim int indx; 8268214082Sdim 8269214082Sdim /* Make sure this symbol is output as a dynamic symbol. 8270214082Sdim Undefined weak syms won't yet be marked as dynamic. */ 8271214082Sdim if (h->dynindx == -1 8272214082Sdim && !h->forced_local) 8273214082Sdim { 8274214082Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 8275214082Sdim return FALSE; 8276214082Sdim } 8277214082Sdim 8278214082Sdim if (!htab->symbian_p) 8279214082Sdim { 8280214082Sdim s = htab->sgot; 8281214082Sdim h->got.offset = s->size; 8282214082Sdim 8283214082Sdim if (tls_type == GOT_UNKNOWN) 8284214082Sdim abort (); 8285214082Sdim 8286214082Sdim if (tls_type == GOT_NORMAL) 8287214082Sdim /* Non-TLS symbols need one GOT slot. */ 8288214082Sdim s->size += 4; 8289214082Sdim else 8290214082Sdim { 8291214082Sdim if (tls_type & GOT_TLS_GD) 8292214082Sdim /* R_ARM_TLS_GD32 needs 2 consecutive GOT slots. */ 8293214082Sdim s->size += 8; 8294214082Sdim if (tls_type & GOT_TLS_IE) 8295214082Sdim /* R_ARM_TLS_IE32 needs one GOT slot. */ 8296214082Sdim s->size += 4; 8297214082Sdim } 8298214082Sdim 8299214082Sdim dyn = htab->root.dynamic_sections_created; 8300214082Sdim 8301214082Sdim indx = 0; 8302214082Sdim if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 8303214082Sdim && (!info->shared 8304214082Sdim || !SYMBOL_REFERENCES_LOCAL (info, h))) 8305214082Sdim indx = h->dynindx; 8306214082Sdim 8307214082Sdim if (tls_type != GOT_NORMAL 8308214082Sdim && (info->shared || indx != 0) 8309214082Sdim && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 8310214082Sdim || h->root.type != bfd_link_hash_undefweak)) 8311214082Sdim { 8312214082Sdim if (tls_type & GOT_TLS_IE) 8313214082Sdim htab->srelgot->size += RELOC_SIZE (htab); 8314214082Sdim 8315214082Sdim if (tls_type & GOT_TLS_GD) 8316214082Sdim htab->srelgot->size += RELOC_SIZE (htab); 8317214082Sdim 8318214082Sdim if ((tls_type & GOT_TLS_GD) && indx != 0) 8319214082Sdim htab->srelgot->size += RELOC_SIZE (htab); 8320214082Sdim } 8321214082Sdim else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 8322214082Sdim || h->root.type != bfd_link_hash_undefweak) 8323214082Sdim && (info->shared 8324214082Sdim || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) 8325214082Sdim htab->srelgot->size += RELOC_SIZE (htab); 8326214082Sdim } 8327214082Sdim } 8328214082Sdim else 8329214082Sdim h->got.offset = (bfd_vma) -1; 8330214082Sdim 8331214634Sdim /* Allocate stubs for exported Thumb functions on v4t. */ 8332214634Sdim if (!htab->use_blx && h->dynindx != -1 8333214634Sdim && h->def_regular 8334214634Sdim && ELF_ST_TYPE (h->type) == STT_ARM_TFUNC 8335214634Sdim && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) 8336214634Sdim { 8337214634Sdim struct elf_link_hash_entry * th; 8338214634Sdim struct bfd_link_hash_entry * bh; 8339214634Sdim struct elf_link_hash_entry * myh; 8340214634Sdim char name[1024]; 8341214634Sdim asection *s; 8342214634Sdim bh = NULL; 8343214634Sdim /* Create a new symbol to regist the real location of the function. */ 8344214634Sdim s = h->root.u.def.section; 8345214634Sdim sprintf(name, "__real_%s", h->root.root.string); 8346214634Sdim _bfd_generic_link_add_one_symbol (info, s->owner, 8347214634Sdim name, BSF_GLOBAL, s, 8348214634Sdim h->root.u.def.value, 8349214634Sdim NULL, TRUE, FALSE, &bh); 8350214634Sdim 8351214634Sdim myh = (struct elf_link_hash_entry *) bh; 8352214634Sdim myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC); 8353214634Sdim myh->forced_local = 1; 8354214634Sdim eh->export_glue = myh; 8355214634Sdim th = record_arm_to_thumb_glue (info, h); 8356214634Sdim /* Point the symbol at the stub. */ 8357214634Sdim h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC); 8358214634Sdim h->root.u.def.section = th->root.u.def.section; 8359214634Sdim h->root.u.def.value = th->root.u.def.value & ~1; 8360214634Sdim } 8361214634Sdim 8362214082Sdim if (eh->relocs_copied == NULL) 8363214082Sdim return TRUE; 8364214082Sdim 8365214082Sdim /* In the shared -Bsymbolic case, discard space allocated for 8366214082Sdim dynamic pc-relative relocs against symbols which turn out to be 8367214082Sdim defined in regular objects. For the normal shared case, discard 8368214082Sdim space for pc-relative relocs that have become local due to symbol 8369214082Sdim visibility changes. */ 8370214082Sdim 8371214082Sdim if (info->shared || htab->root.is_relocatable_executable) 8372214082Sdim { 8373214634Sdim /* The only relocs that use pc_count are R_ARM_REL32 and 8374214634Sdim R_ARM_REL32_NOI, which will appear on something like 8375214634Sdim ".long foo - .". We want calls to protected symbols to resolve 8376214634Sdim directly to the function rather than going via the plt. If people 8377214634Sdim want function pointer comparisons to work as expected then they 8378214634Sdim should avoid writing assembly like ".long foo - .". */ 8379214082Sdim if (SYMBOL_CALLS_LOCAL (info, h)) 8380214082Sdim { 8381214082Sdim struct elf32_arm_relocs_copied **pp; 8382214082Sdim 8383214082Sdim for (pp = &eh->relocs_copied; (p = *pp) != NULL; ) 8384214082Sdim { 8385214082Sdim p->count -= p->pc_count; 8386214082Sdim p->pc_count = 0; 8387214082Sdim if (p->count == 0) 8388214082Sdim *pp = p->next; 8389214082Sdim else 8390214082Sdim pp = &p->next; 8391214082Sdim } 8392214082Sdim } 8393214082Sdim 8394214082Sdim /* Also discard relocs on undefined weak syms with non-default 8395214082Sdim visibility. */ 8396214082Sdim if (eh->relocs_copied != NULL 8397214082Sdim && h->root.type == bfd_link_hash_undefweak) 8398214082Sdim { 8399214082Sdim if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) 8400214082Sdim eh->relocs_copied = NULL; 8401214082Sdim 8402214082Sdim /* Make sure undefined weak symbols are output as a dynamic 8403214082Sdim symbol in PIEs. */ 8404214082Sdim else if (h->dynindx == -1 8405214082Sdim && !h->forced_local) 8406214082Sdim { 8407214082Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 8408214082Sdim return FALSE; 8409214082Sdim } 8410214082Sdim } 8411214082Sdim 8412214082Sdim else if (htab->root.is_relocatable_executable && h->dynindx == -1 8413214082Sdim && h->root.type == bfd_link_hash_new) 8414214082Sdim { 8415214082Sdim /* Output absolute symbols so that we can create relocations 8416214082Sdim against them. For normal symbols we output a relocation 8417214082Sdim against the section that contains them. */ 8418214082Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 8419214082Sdim return FALSE; 8420214082Sdim } 8421214082Sdim 8422214082Sdim } 8423214082Sdim else 8424214082Sdim { 8425214082Sdim /* For the non-shared case, discard space for relocs against 8426214082Sdim symbols which turn out to need copy relocs or are not 8427214082Sdim dynamic. */ 8428214082Sdim 8429214082Sdim if (!h->non_got_ref 8430214082Sdim && ((h->def_dynamic 8431214082Sdim && !h->def_regular) 8432214082Sdim || (htab->root.dynamic_sections_created 8433214082Sdim && (h->root.type == bfd_link_hash_undefweak 8434214082Sdim || h->root.type == bfd_link_hash_undefined)))) 8435214082Sdim { 8436214082Sdim /* Make sure this symbol is output as a dynamic symbol. 8437214082Sdim Undefined weak syms won't yet be marked as dynamic. */ 8438214082Sdim if (h->dynindx == -1 8439214082Sdim && !h->forced_local) 8440214082Sdim { 8441214082Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 8442214082Sdim return FALSE; 8443214082Sdim } 8444214082Sdim 8445214082Sdim /* If that succeeded, we know we'll be keeping all the 8446214082Sdim relocs. */ 8447214082Sdim if (h->dynindx != -1) 8448214082Sdim goto keep; 8449214082Sdim } 8450214082Sdim 8451214082Sdim eh->relocs_copied = NULL; 8452214082Sdim 8453214082Sdim keep: ; 8454214082Sdim } 8455214082Sdim 8456214082Sdim /* Finally, allocate space. */ 8457214082Sdim for (p = eh->relocs_copied; p != NULL; p = p->next) 8458214082Sdim { 8459214082Sdim asection *sreloc = elf_section_data (p->section)->sreloc; 8460214082Sdim sreloc->size += p->count * RELOC_SIZE (htab); 8461214082Sdim } 8462214082Sdim 8463214082Sdim return TRUE; 8464214082Sdim} 8465214082Sdim 8466214082Sdim/* Find any dynamic relocs that apply to read-only sections. */ 8467214082Sdim 8468214082Sdimstatic bfd_boolean 8469214082Sdimelf32_arm_readonly_dynrelocs (struct elf_link_hash_entry *h, PTR inf) 8470214082Sdim{ 8471214082Sdim struct elf32_arm_link_hash_entry *eh; 8472214082Sdim struct elf32_arm_relocs_copied *p; 8473214082Sdim 8474214082Sdim if (h->root.type == bfd_link_hash_warning) 8475214082Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 8476214082Sdim 8477214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 8478214082Sdim for (p = eh->relocs_copied; p != NULL; p = p->next) 8479214082Sdim { 8480214082Sdim asection *s = p->section; 8481214082Sdim 8482214082Sdim if (s != NULL && (s->flags & SEC_READONLY) != 0) 8483214082Sdim { 8484214082Sdim struct bfd_link_info *info = (struct bfd_link_info *) inf; 8485214082Sdim 8486214082Sdim info->flags |= DF_TEXTREL; 8487214082Sdim 8488214082Sdim /* Not an error, just cut short the traversal. */ 8489214082Sdim return FALSE; 8490214082Sdim } 8491214082Sdim } 8492214082Sdim return TRUE; 8493214082Sdim} 8494214082Sdim 8495214634Sdimvoid 8496214634Sdimbfd_elf32_arm_set_byteswap_code (struct bfd_link_info *info, 8497214634Sdim int byteswap_code) 8498214634Sdim{ 8499214634Sdim struct elf32_arm_link_hash_table *globals; 8500214634Sdim 8501214634Sdim globals = elf32_arm_hash_table (info); 8502214634Sdim globals->byteswap_code = byteswap_code; 8503214634Sdim} 8504214634Sdim 8505214082Sdim/* Set the sizes of the dynamic sections. */ 8506214082Sdim 8507214082Sdimstatic bfd_boolean 8508214082Sdimelf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, 8509214082Sdim struct bfd_link_info * info) 8510214082Sdim{ 8511214082Sdim bfd * dynobj; 8512214082Sdim asection * s; 8513214082Sdim bfd_boolean plt; 8514214082Sdim bfd_boolean relocs; 8515214082Sdim bfd *ibfd; 8516214082Sdim struct elf32_arm_link_hash_table *htab; 8517214082Sdim 8518214082Sdim htab = elf32_arm_hash_table (info); 8519214082Sdim dynobj = elf_hash_table (info)->dynobj; 8520214082Sdim BFD_ASSERT (dynobj != NULL); 8521214082Sdim check_use_blx (htab); 8522214082Sdim 8523214082Sdim if (elf_hash_table (info)->dynamic_sections_created) 8524214082Sdim { 8525214082Sdim /* Set the contents of the .interp section to the interpreter. */ 8526214082Sdim if (info->executable) 8527214082Sdim { 8528214082Sdim s = bfd_get_section_by_name (dynobj, ".interp"); 8529214082Sdim BFD_ASSERT (s != NULL); 8530214082Sdim s->size = sizeof ELF_DYNAMIC_INTERPRETER; 8531214082Sdim s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 8532214082Sdim } 8533214082Sdim } 8534214082Sdim 8535214082Sdim /* Set up .got offsets for local syms, and space for local dynamic 8536214082Sdim relocs. */ 8537214082Sdim for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 8538214082Sdim { 8539214082Sdim bfd_signed_vma *local_got; 8540214082Sdim bfd_signed_vma *end_local_got; 8541214082Sdim char *local_tls_type; 8542214082Sdim bfd_size_type locsymcount; 8543214082Sdim Elf_Internal_Shdr *symtab_hdr; 8544214082Sdim asection *srel; 8545214082Sdim 8546214082Sdim if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 8547214082Sdim continue; 8548214082Sdim 8549214082Sdim for (s = ibfd->sections; s != NULL; s = s->next) 8550214082Sdim { 8551214082Sdim struct elf32_arm_relocs_copied *p; 8552214082Sdim 8553214082Sdim for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next) 8554214082Sdim { 8555214082Sdim if (!bfd_is_abs_section (p->section) 8556214082Sdim && bfd_is_abs_section (p->section->output_section)) 8557214082Sdim { 8558214082Sdim /* Input section has been discarded, either because 8559214082Sdim it is a copy of a linkonce section or due to 8560214082Sdim linker script /DISCARD/, so we'll be discarding 8561214082Sdim the relocs too. */ 8562214082Sdim } 8563214082Sdim else if (p->count != 0) 8564214082Sdim { 8565214082Sdim srel = elf_section_data (p->section)->sreloc; 8566214082Sdim srel->size += p->count * RELOC_SIZE (htab); 8567214082Sdim if ((p->section->output_section->flags & SEC_READONLY) != 0) 8568214082Sdim info->flags |= DF_TEXTREL; 8569214082Sdim } 8570214082Sdim } 8571214082Sdim } 8572214082Sdim 8573214082Sdim local_got = elf_local_got_refcounts (ibfd); 8574214082Sdim if (!local_got) 8575214082Sdim continue; 8576214082Sdim 8577214082Sdim symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 8578214082Sdim locsymcount = symtab_hdr->sh_info; 8579214082Sdim end_local_got = local_got + locsymcount; 8580214082Sdim local_tls_type = elf32_arm_local_got_tls_type (ibfd); 8581214082Sdim s = htab->sgot; 8582214082Sdim srel = htab->srelgot; 8583214082Sdim for (; local_got < end_local_got; ++local_got, ++local_tls_type) 8584214082Sdim { 8585214082Sdim if (*local_got > 0) 8586214082Sdim { 8587214082Sdim *local_got = s->size; 8588214082Sdim if (*local_tls_type & GOT_TLS_GD) 8589214082Sdim /* TLS_GD relocs need an 8-byte structure in the GOT. */ 8590214082Sdim s->size += 8; 8591214082Sdim if (*local_tls_type & GOT_TLS_IE) 8592214082Sdim s->size += 4; 8593214082Sdim if (*local_tls_type == GOT_NORMAL) 8594214082Sdim s->size += 4; 8595214082Sdim 8596214082Sdim if (info->shared || *local_tls_type == GOT_TLS_GD) 8597214082Sdim srel->size += RELOC_SIZE (htab); 8598214082Sdim } 8599214082Sdim else 8600214082Sdim *local_got = (bfd_vma) -1; 8601214082Sdim } 8602214082Sdim } 8603214082Sdim 8604214082Sdim if (htab->tls_ldm_got.refcount > 0) 8605214082Sdim { 8606214082Sdim /* Allocate two GOT entries and one dynamic relocation (if necessary) 8607214082Sdim for R_ARM_TLS_LDM32 relocations. */ 8608214082Sdim htab->tls_ldm_got.offset = htab->sgot->size; 8609214082Sdim htab->sgot->size += 8; 8610214082Sdim if (info->shared) 8611214082Sdim htab->srelgot->size += RELOC_SIZE (htab); 8612214082Sdim } 8613214082Sdim else 8614214082Sdim htab->tls_ldm_got.offset = -1; 8615214082Sdim 8616214082Sdim /* Allocate global sym .plt and .got entries, and space for global 8617214082Sdim sym dynamic relocs. */ 8618214082Sdim elf_link_hash_traverse (& htab->root, allocate_dynrelocs, info); 8619214082Sdim 8620214634Sdim /* Here we rummage through the found bfds to collect glue information. */ 8621214634Sdim for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 8622214634Sdim { 8623214634Sdim /* Initialise mapping tables for code/data. */ 8624214634Sdim bfd_elf32_arm_init_maps (ibfd); 8625214634Sdim 8626214634Sdim if (!bfd_elf32_arm_process_before_allocation (ibfd, info) 8627214634Sdim || !bfd_elf32_arm_vfp11_erratum_scan (ibfd, info)) 8628214634Sdim /* xgettext:c-format */ 8629214634Sdim _bfd_error_handler (_("Errors encountered processing file %s"), 8630214634Sdim ibfd->filename); 8631214634Sdim } 8632214634Sdim 8633214082Sdim /* The check_relocs and adjust_dynamic_symbol entry points have 8634214082Sdim determined the sizes of the various dynamic sections. Allocate 8635214082Sdim memory for them. */ 8636214082Sdim plt = FALSE; 8637214082Sdim relocs = FALSE; 8638214082Sdim for (s = dynobj->sections; s != NULL; s = s->next) 8639214082Sdim { 8640214082Sdim const char * name; 8641214082Sdim 8642214082Sdim if ((s->flags & SEC_LINKER_CREATED) == 0) 8643214082Sdim continue; 8644214082Sdim 8645214082Sdim /* It's OK to base decisions on the section name, because none 8646214082Sdim of the dynobj section names depend upon the input files. */ 8647214082Sdim name = bfd_get_section_name (dynobj, s); 8648214082Sdim 8649214082Sdim if (strcmp (name, ".plt") == 0) 8650214082Sdim { 8651214082Sdim /* Remember whether there is a PLT. */ 8652214082Sdim plt = s->size != 0; 8653214082Sdim } 8654214634Sdim else if (CONST_STRNEQ (name, ".rel")) 8655214082Sdim { 8656214082Sdim if (s->size != 0) 8657214082Sdim { 8658214082Sdim /* Remember whether there are any reloc sections other 8659214082Sdim than .rel(a).plt and .rela.plt.unloaded. */ 8660214082Sdim if (s != htab->srelplt && s != htab->srelplt2) 8661214082Sdim relocs = TRUE; 8662214082Sdim 8663214082Sdim /* We use the reloc_count field as a counter if we need 8664214082Sdim to copy relocs into the output file. */ 8665214082Sdim s->reloc_count = 0; 8666214082Sdim } 8667214082Sdim } 8668214634Sdim else if (! CONST_STRNEQ (name, ".got") 8669214082Sdim && strcmp (name, ".dynbss") != 0) 8670214082Sdim { 8671214082Sdim /* It's not one of our sections, so don't allocate space. */ 8672214082Sdim continue; 8673214082Sdim } 8674214082Sdim 8675214082Sdim if (s->size == 0) 8676214082Sdim { 8677214082Sdim /* If we don't need this section, strip it from the 8678214082Sdim output file. This is mostly to handle .rel(a).bss and 8679214082Sdim .rel(a).plt. We must create both sections in 8680214082Sdim create_dynamic_sections, because they must be created 8681214082Sdim before the linker maps input sections to output 8682214082Sdim sections. The linker does that before 8683214082Sdim adjust_dynamic_symbol is called, and it is that 8684214082Sdim function which decides whether anything needs to go 8685214082Sdim into these sections. */ 8686214082Sdim s->flags |= SEC_EXCLUDE; 8687214082Sdim continue; 8688214082Sdim } 8689214082Sdim 8690214082Sdim if ((s->flags & SEC_HAS_CONTENTS) == 0) 8691214082Sdim continue; 8692214082Sdim 8693214082Sdim /* Allocate memory for the section contents. */ 8694214082Sdim s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); 8695214082Sdim if (s->contents == NULL) 8696214082Sdim return FALSE; 8697214082Sdim } 8698214082Sdim 8699214082Sdim if (elf_hash_table (info)->dynamic_sections_created) 8700214082Sdim { 8701214082Sdim /* Add some entries to the .dynamic section. We fill in the 8702214082Sdim values later, in elf32_arm_finish_dynamic_sections, but we 8703214082Sdim must add the entries now so that we get the correct size for 8704214082Sdim the .dynamic section. The DT_DEBUG entry is filled in by the 8705214082Sdim dynamic linker and used by the debugger. */ 8706214082Sdim#define add_dynamic_entry(TAG, VAL) \ 8707214082Sdim _bfd_elf_add_dynamic_entry (info, TAG, VAL) 8708214082Sdim 8709214082Sdim if (info->executable) 8710214082Sdim { 8711214082Sdim if (!add_dynamic_entry (DT_DEBUG, 0)) 8712214082Sdim return FALSE; 8713214082Sdim } 8714214082Sdim 8715214082Sdim if (plt) 8716214082Sdim { 8717214082Sdim if ( !add_dynamic_entry (DT_PLTGOT, 0) 8718214082Sdim || !add_dynamic_entry (DT_PLTRELSZ, 0) 8719214082Sdim || !add_dynamic_entry (DT_PLTREL, 8720214082Sdim htab->use_rel ? DT_REL : DT_RELA) 8721214082Sdim || !add_dynamic_entry (DT_JMPREL, 0)) 8722214082Sdim return FALSE; 8723214082Sdim } 8724214082Sdim 8725214082Sdim if (relocs) 8726214082Sdim { 8727214082Sdim if (htab->use_rel) 8728214082Sdim { 8729214082Sdim if (!add_dynamic_entry (DT_REL, 0) 8730214082Sdim || !add_dynamic_entry (DT_RELSZ, 0) 8731214082Sdim || !add_dynamic_entry (DT_RELENT, RELOC_SIZE (htab))) 8732214082Sdim return FALSE; 8733214082Sdim } 8734214082Sdim else 8735214082Sdim { 8736214082Sdim if (!add_dynamic_entry (DT_RELA, 0) 8737214082Sdim || !add_dynamic_entry (DT_RELASZ, 0) 8738214082Sdim || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab))) 8739214082Sdim return FALSE; 8740214082Sdim } 8741214082Sdim } 8742214082Sdim 8743214082Sdim /* If any dynamic relocs apply to a read-only section, 8744214082Sdim then we need a DT_TEXTREL entry. */ 8745214082Sdim if ((info->flags & DF_TEXTREL) == 0) 8746214082Sdim elf_link_hash_traverse (&htab->root, elf32_arm_readonly_dynrelocs, 8747214082Sdim (PTR) info); 8748214082Sdim 8749214082Sdim if ((info->flags & DF_TEXTREL) != 0) 8750214082Sdim { 8751214082Sdim if (!add_dynamic_entry (DT_TEXTREL, 0)) 8752214082Sdim return FALSE; 8753214082Sdim } 8754214082Sdim } 8755214082Sdim#undef add_dynamic_entry 8756214082Sdim 8757214082Sdim return TRUE; 8758214082Sdim} 8759214082Sdim 8760214082Sdim/* Finish up dynamic symbol handling. We set the contents of various 8761214082Sdim dynamic sections here. */ 8762214082Sdim 8763214082Sdimstatic bfd_boolean 8764214082Sdimelf32_arm_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info * info, 8765214082Sdim struct elf_link_hash_entry * h, Elf_Internal_Sym * sym) 8766214082Sdim{ 8767214082Sdim bfd * dynobj; 8768214082Sdim struct elf32_arm_link_hash_table *htab; 8769214082Sdim struct elf32_arm_link_hash_entry *eh; 8770214082Sdim 8771214082Sdim dynobj = elf_hash_table (info)->dynobj; 8772214082Sdim htab = elf32_arm_hash_table (info); 8773214082Sdim eh = (struct elf32_arm_link_hash_entry *) h; 8774214082Sdim 8775214082Sdim if (h->plt.offset != (bfd_vma) -1) 8776214082Sdim { 8777214082Sdim asection * splt; 8778214082Sdim asection * srel; 8779214082Sdim bfd_byte *loc; 8780214082Sdim bfd_vma plt_index; 8781214082Sdim Elf_Internal_Rela rel; 8782214082Sdim 8783214082Sdim /* This symbol has an entry in the procedure linkage table. Set 8784214082Sdim it up. */ 8785214082Sdim 8786214082Sdim BFD_ASSERT (h->dynindx != -1); 8787214082Sdim 8788214082Sdim splt = bfd_get_section_by_name (dynobj, ".plt"); 8789214082Sdim srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".plt")); 8790214082Sdim BFD_ASSERT (splt != NULL && srel != NULL); 8791214082Sdim 8792214082Sdim /* Fill in the entry in the procedure linkage table. */ 8793214082Sdim if (htab->symbian_p) 8794214082Sdim { 8795214634Sdim put_arm_insn (htab, output_bfd, 8796214634Sdim elf32_arm_symbian_plt_entry[0], 8797214634Sdim splt->contents + h->plt.offset); 8798214634Sdim bfd_put_32 (output_bfd, 8799214634Sdim elf32_arm_symbian_plt_entry[1], 8800214634Sdim splt->contents + h->plt.offset + 4); 8801214082Sdim 8802214082Sdim /* Fill in the entry in the .rel.plt section. */ 8803214082Sdim rel.r_offset = (splt->output_section->vma 8804214082Sdim + splt->output_offset 8805214634Sdim + h->plt.offset + 4); 8806214082Sdim rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT); 8807214082Sdim 8808214082Sdim /* Get the index in the procedure linkage table which 8809214082Sdim corresponds to this symbol. This is the index of this symbol 8810214082Sdim in all the symbols for which we are making plt entries. The 8811214082Sdim first entry in the procedure linkage table is reserved. */ 8812214082Sdim plt_index = ((h->plt.offset - htab->plt_header_size) 8813214082Sdim / htab->plt_entry_size); 8814214082Sdim } 8815214082Sdim else 8816214082Sdim { 8817214082Sdim bfd_vma got_offset, got_address, plt_address; 8818214082Sdim bfd_vma got_displacement; 8819214082Sdim asection * sgot; 8820214634Sdim bfd_byte * ptr; 8821214082Sdim 8822214082Sdim sgot = bfd_get_section_by_name (dynobj, ".got.plt"); 8823214082Sdim BFD_ASSERT (sgot != NULL); 8824214082Sdim 8825214082Sdim /* Get the offset into the .got.plt table of the entry that 8826214082Sdim corresponds to this function. */ 8827214082Sdim got_offset = eh->plt_got_offset; 8828214082Sdim 8829214082Sdim /* Get the index in the procedure linkage table which 8830214082Sdim corresponds to this symbol. This is the index of this symbol 8831214082Sdim in all the symbols for which we are making plt entries. The 8832214082Sdim first three entries in .got.plt are reserved; after that 8833214082Sdim symbols appear in the same order as in .plt. */ 8834214082Sdim plt_index = (got_offset - 12) / 4; 8835214082Sdim 8836214082Sdim /* Calculate the address of the GOT entry. */ 8837214082Sdim got_address = (sgot->output_section->vma 8838214082Sdim + sgot->output_offset 8839214082Sdim + got_offset); 8840214082Sdim 8841214082Sdim /* ...and the address of the PLT entry. */ 8842214082Sdim plt_address = (splt->output_section->vma 8843214082Sdim + splt->output_offset 8844214082Sdim + h->plt.offset); 8845214082Sdim 8846214634Sdim ptr = htab->splt->contents + h->plt.offset; 8847214082Sdim if (htab->vxworks_p && info->shared) 8848214082Sdim { 8849214082Sdim unsigned int i; 8850214082Sdim bfd_vma val; 8851214082Sdim 8852214634Sdim for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4) 8853214082Sdim { 8854214082Sdim val = elf32_arm_vxworks_shared_plt_entry[i]; 8855214082Sdim if (i == 2) 8856214082Sdim val |= got_address - sgot->output_section->vma; 8857214082Sdim if (i == 5) 8858214082Sdim val |= plt_index * RELOC_SIZE (htab); 8859214634Sdim if (i == 2 || i == 5) 8860214634Sdim bfd_put_32 (output_bfd, val, ptr); 8861214634Sdim else 8862214634Sdim put_arm_insn (htab, output_bfd, val, ptr); 8863214082Sdim } 8864214082Sdim } 8865214082Sdim else if (htab->vxworks_p) 8866214082Sdim { 8867214082Sdim unsigned int i; 8868214082Sdim bfd_vma val; 8869214082Sdim 8870214634Sdim for (i = 0; i != htab->plt_entry_size / 4; i++, ptr += 4) 8871214082Sdim { 8872214082Sdim val = elf32_arm_vxworks_exec_plt_entry[i]; 8873214082Sdim if (i == 2) 8874214082Sdim val |= got_address; 8875214082Sdim if (i == 4) 8876214082Sdim val |= 0xffffff & -((h->plt.offset + i * 4 + 8) >> 2); 8877214082Sdim if (i == 5) 8878214082Sdim val |= plt_index * RELOC_SIZE (htab); 8879214634Sdim if (i == 2 || i == 5) 8880214634Sdim bfd_put_32 (output_bfd, val, ptr); 8881214634Sdim else 8882214634Sdim put_arm_insn (htab, output_bfd, val, ptr); 8883214082Sdim } 8884214082Sdim 8885214082Sdim loc = (htab->srelplt2->contents 8886214082Sdim + (plt_index * 2 + 1) * RELOC_SIZE (htab)); 8887214082Sdim 8888214082Sdim /* Create the .rela.plt.unloaded R_ARM_ABS32 relocation 8889214082Sdim referencing the GOT for this PLT entry. */ 8890214082Sdim rel.r_offset = plt_address + 8; 8891214082Sdim rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32); 8892214082Sdim rel.r_addend = got_offset; 8893214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); 8894214082Sdim loc += RELOC_SIZE (htab); 8895214082Sdim 8896214082Sdim /* Create the R_ARM_ABS32 relocation referencing the 8897214082Sdim beginning of the PLT for this GOT entry. */ 8898214082Sdim rel.r_offset = got_address; 8899214082Sdim rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32); 8900214082Sdim rel.r_addend = 0; 8901214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); 8902214082Sdim } 8903214082Sdim else 8904214082Sdim { 8905214082Sdim /* Calculate the displacement between the PLT slot and the 8906214082Sdim entry in the GOT. The eight-byte offset accounts for the 8907214082Sdim value produced by adding to pc in the first instruction 8908214082Sdim of the PLT stub. */ 8909214082Sdim got_displacement = got_address - (plt_address + 8); 8910214082Sdim 8911214082Sdim BFD_ASSERT ((got_displacement & 0xf0000000) == 0); 8912214082Sdim 8913214082Sdim if (!htab->use_blx && eh->plt_thumb_refcount > 0) 8914214082Sdim { 8915214634Sdim put_thumb_insn (htab, output_bfd, 8916214634Sdim elf32_arm_plt_thumb_stub[0], ptr - 4); 8917214634Sdim put_thumb_insn (htab, output_bfd, 8918214634Sdim elf32_arm_plt_thumb_stub[1], ptr - 2); 8919214082Sdim } 8920214082Sdim 8921214634Sdim put_arm_insn (htab, output_bfd, 8922214634Sdim elf32_arm_plt_entry[0] 8923214634Sdim | ((got_displacement & 0x0ff00000) >> 20), 8924214634Sdim ptr + 0); 8925214634Sdim put_arm_insn (htab, output_bfd, 8926214634Sdim elf32_arm_plt_entry[1] 8927214634Sdim | ((got_displacement & 0x000ff000) >> 12), 8928214634Sdim ptr+ 4); 8929214634Sdim put_arm_insn (htab, output_bfd, 8930214634Sdim elf32_arm_plt_entry[2] 8931214634Sdim | (got_displacement & 0x00000fff), 8932214634Sdim ptr + 8); 8933214082Sdim#ifdef FOUR_WORD_PLT 8934214634Sdim bfd_put_32 (output_bfd, elf32_arm_plt_entry[3], ptr + 12); 8935214082Sdim#endif 8936214082Sdim } 8937214082Sdim 8938214082Sdim /* Fill in the entry in the global offset table. */ 8939214082Sdim bfd_put_32 (output_bfd, 8940214082Sdim (splt->output_section->vma 8941214082Sdim + splt->output_offset), 8942214082Sdim sgot->contents + got_offset); 8943214082Sdim 8944214082Sdim /* Fill in the entry in the .rel(a).plt section. */ 8945214082Sdim rel.r_addend = 0; 8946214082Sdim rel.r_offset = got_address; 8947214082Sdim rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_JUMP_SLOT); 8948214082Sdim } 8949214082Sdim 8950214082Sdim loc = srel->contents + plt_index * RELOC_SIZE (htab); 8951214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); 8952214082Sdim 8953214082Sdim if (!h->def_regular) 8954214082Sdim { 8955214082Sdim /* Mark the symbol as undefined, rather than as defined in 8956214082Sdim the .plt section. Leave the value alone. */ 8957214082Sdim sym->st_shndx = SHN_UNDEF; 8958214082Sdim /* If the symbol is weak, we do need to clear the value. 8959214082Sdim Otherwise, the PLT entry would provide a definition for 8960214082Sdim the symbol even if the symbol wasn't defined anywhere, 8961214082Sdim and so the symbol would never be NULL. */ 8962214082Sdim if (!h->ref_regular_nonweak) 8963214082Sdim sym->st_value = 0; 8964214082Sdim } 8965214082Sdim } 8966214082Sdim 8967214082Sdim if (h->got.offset != (bfd_vma) -1 8968214082Sdim && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_GD) == 0 8969214082Sdim && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0) 8970214082Sdim { 8971214082Sdim asection * sgot; 8972214082Sdim asection * srel; 8973214082Sdim Elf_Internal_Rela rel; 8974214082Sdim bfd_byte *loc; 8975214082Sdim bfd_vma offset; 8976214082Sdim 8977214082Sdim /* This symbol has an entry in the global offset table. Set it 8978214082Sdim up. */ 8979214082Sdim sgot = bfd_get_section_by_name (dynobj, ".got"); 8980214082Sdim srel = bfd_get_section_by_name (dynobj, RELOC_SECTION (htab, ".got")); 8981214082Sdim BFD_ASSERT (sgot != NULL && srel != NULL); 8982214082Sdim 8983214082Sdim offset = (h->got.offset & ~(bfd_vma) 1); 8984214082Sdim rel.r_addend = 0; 8985214082Sdim rel.r_offset = (sgot->output_section->vma 8986214082Sdim + sgot->output_offset 8987214082Sdim + offset); 8988214082Sdim 8989214082Sdim /* If this is a static link, or it is a -Bsymbolic link and the 8990214082Sdim symbol is defined locally or was forced to be local because 8991214082Sdim of a version file, we just want to emit a RELATIVE reloc. 8992214082Sdim The entry in the global offset table will already have been 8993214082Sdim initialized in the relocate_section function. */ 8994214082Sdim if (info->shared 8995214082Sdim && SYMBOL_REFERENCES_LOCAL (info, h)) 8996214082Sdim { 8997214082Sdim BFD_ASSERT((h->got.offset & 1) != 0); 8998214082Sdim rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); 8999214082Sdim if (!htab->use_rel) 9000214082Sdim { 9001214082Sdim rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + offset); 9002214082Sdim bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset); 9003214082Sdim } 9004214082Sdim } 9005214082Sdim else 9006214082Sdim { 9007214082Sdim BFD_ASSERT((h->got.offset & 1) == 0); 9008214082Sdim bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset); 9009214082Sdim rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT); 9010214082Sdim } 9011214082Sdim 9012214082Sdim loc = srel->contents + srel->reloc_count++ * RELOC_SIZE (htab); 9013214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); 9014214082Sdim } 9015214082Sdim 9016214082Sdim if (h->needs_copy) 9017214082Sdim { 9018214082Sdim asection * s; 9019214082Sdim Elf_Internal_Rela rel; 9020214082Sdim bfd_byte *loc; 9021214082Sdim 9022214082Sdim /* This symbol needs a copy reloc. Set it up. */ 9023214082Sdim BFD_ASSERT (h->dynindx != -1 9024214082Sdim && (h->root.type == bfd_link_hash_defined 9025214082Sdim || h->root.type == bfd_link_hash_defweak)); 9026214082Sdim 9027214082Sdim s = bfd_get_section_by_name (h->root.u.def.section->owner, 9028214082Sdim RELOC_SECTION (htab, ".bss")); 9029214082Sdim BFD_ASSERT (s != NULL); 9030214082Sdim 9031214082Sdim rel.r_addend = 0; 9032214082Sdim rel.r_offset = (h->root.u.def.value 9033214082Sdim + h->root.u.def.section->output_section->vma 9034214082Sdim + h->root.u.def.section->output_offset); 9035214082Sdim rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY); 9036214082Sdim loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab); 9037214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, loc); 9038214082Sdim } 9039214082Sdim 9040214082Sdim /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. On VxWorks, 9041214082Sdim the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it is relative 9042214082Sdim to the ".got" section. */ 9043214082Sdim if (strcmp (h->root.root.string, "_DYNAMIC") == 0 9044214082Sdim || (!htab->vxworks_p && h == htab->root.hgot)) 9045214082Sdim sym->st_shndx = SHN_ABS; 9046214082Sdim 9047214082Sdim return TRUE; 9048214082Sdim} 9049214082Sdim 9050214082Sdim/* Finish up the dynamic sections. */ 9051214082Sdim 9052214082Sdimstatic bfd_boolean 9053214082Sdimelf32_arm_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info * info) 9054214082Sdim{ 9055214082Sdim bfd * dynobj; 9056214082Sdim asection * sgot; 9057214082Sdim asection * sdyn; 9058214082Sdim 9059214082Sdim dynobj = elf_hash_table (info)->dynobj; 9060214082Sdim 9061214082Sdim sgot = bfd_get_section_by_name (dynobj, ".got.plt"); 9062214082Sdim BFD_ASSERT (elf32_arm_hash_table (info)->symbian_p || sgot != NULL); 9063214082Sdim sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 9064214082Sdim 9065214082Sdim if (elf_hash_table (info)->dynamic_sections_created) 9066214082Sdim { 9067214082Sdim asection *splt; 9068214082Sdim Elf32_External_Dyn *dyncon, *dynconend; 9069214082Sdim struct elf32_arm_link_hash_table *htab; 9070214082Sdim 9071214082Sdim htab = elf32_arm_hash_table (info); 9072214082Sdim splt = bfd_get_section_by_name (dynobj, ".plt"); 9073214082Sdim BFD_ASSERT (splt != NULL && sdyn != NULL); 9074214082Sdim 9075214082Sdim dyncon = (Elf32_External_Dyn *) sdyn->contents; 9076214082Sdim dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); 9077214082Sdim 9078214082Sdim for (; dyncon < dynconend; dyncon++) 9079214082Sdim { 9080214082Sdim Elf_Internal_Dyn dyn; 9081214082Sdim const char * name; 9082214082Sdim asection * s; 9083214082Sdim 9084214082Sdim bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); 9085214082Sdim 9086214082Sdim switch (dyn.d_tag) 9087214082Sdim { 9088214082Sdim unsigned int type; 9089214082Sdim 9090214082Sdim default: 9091214082Sdim break; 9092214082Sdim 9093214082Sdim case DT_HASH: 9094214082Sdim name = ".hash"; 9095214082Sdim goto get_vma_if_bpabi; 9096214082Sdim case DT_STRTAB: 9097214082Sdim name = ".dynstr"; 9098214082Sdim goto get_vma_if_bpabi; 9099214082Sdim case DT_SYMTAB: 9100214082Sdim name = ".dynsym"; 9101214082Sdim goto get_vma_if_bpabi; 9102214082Sdim case DT_VERSYM: 9103214082Sdim name = ".gnu.version"; 9104214082Sdim goto get_vma_if_bpabi; 9105214082Sdim case DT_VERDEF: 9106214082Sdim name = ".gnu.version_d"; 9107214082Sdim goto get_vma_if_bpabi; 9108214082Sdim case DT_VERNEED: 9109214082Sdim name = ".gnu.version_r"; 9110214082Sdim goto get_vma_if_bpabi; 9111214082Sdim 9112214082Sdim case DT_PLTGOT: 9113214082Sdim name = ".got"; 9114214082Sdim goto get_vma; 9115214082Sdim case DT_JMPREL: 9116214082Sdim name = RELOC_SECTION (htab, ".plt"); 9117214082Sdim get_vma: 9118214082Sdim s = bfd_get_section_by_name (output_bfd, name); 9119214082Sdim BFD_ASSERT (s != NULL); 9120214082Sdim if (!htab->symbian_p) 9121214082Sdim dyn.d_un.d_ptr = s->vma; 9122214082Sdim else 9123214082Sdim /* In the BPABI, tags in the PT_DYNAMIC section point 9124214082Sdim at the file offset, not the memory address, for the 9125214082Sdim convenience of the post linker. */ 9126214082Sdim dyn.d_un.d_ptr = s->filepos; 9127214082Sdim bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 9128214082Sdim break; 9129214082Sdim 9130214082Sdim get_vma_if_bpabi: 9131214082Sdim if (htab->symbian_p) 9132214082Sdim goto get_vma; 9133214082Sdim break; 9134214082Sdim 9135214082Sdim case DT_PLTRELSZ: 9136214082Sdim s = bfd_get_section_by_name (output_bfd, 9137214082Sdim RELOC_SECTION (htab, ".plt")); 9138214082Sdim BFD_ASSERT (s != NULL); 9139214082Sdim dyn.d_un.d_val = s->size; 9140214082Sdim bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 9141214082Sdim break; 9142214082Sdim 9143214082Sdim case DT_RELSZ: 9144214082Sdim case DT_RELASZ: 9145214082Sdim if (!htab->symbian_p) 9146214082Sdim { 9147214082Sdim /* My reading of the SVR4 ABI indicates that the 9148214082Sdim procedure linkage table relocs (DT_JMPREL) should be 9149214082Sdim included in the overall relocs (DT_REL). This is 9150214082Sdim what Solaris does. However, UnixWare can not handle 9151214082Sdim that case. Therefore, we override the DT_RELSZ entry 9152214082Sdim here to make it not include the JMPREL relocs. Since 9153214082Sdim the linker script arranges for .rel(a).plt to follow all 9154214082Sdim other relocation sections, we don't have to worry 9155214082Sdim about changing the DT_REL entry. */ 9156214082Sdim s = bfd_get_section_by_name (output_bfd, 9157214082Sdim RELOC_SECTION (htab, ".plt")); 9158214082Sdim if (s != NULL) 9159214082Sdim dyn.d_un.d_val -= s->size; 9160214082Sdim bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 9161214082Sdim break; 9162214082Sdim } 9163214082Sdim /* Fall through */ 9164214082Sdim 9165214082Sdim case DT_REL: 9166214082Sdim case DT_RELA: 9167214082Sdim /* In the BPABI, the DT_REL tag must point at the file 9168214082Sdim offset, not the VMA, of the first relocation 9169214082Sdim section. So, we use code similar to that in 9170214082Sdim elflink.c, but do not check for SHF_ALLOC on the 9171214082Sdim relcoation section, since relocations sections are 9172214082Sdim never allocated under the BPABI. The comments above 9173214082Sdim about Unixware notwithstanding, we include all of the 9174214082Sdim relocations here. */ 9175214082Sdim if (htab->symbian_p) 9176214082Sdim { 9177214082Sdim unsigned int i; 9178214082Sdim type = ((dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ) 9179214082Sdim ? SHT_REL : SHT_RELA); 9180214082Sdim dyn.d_un.d_val = 0; 9181214082Sdim for (i = 1; i < elf_numsections (output_bfd); i++) 9182214082Sdim { 9183214082Sdim Elf_Internal_Shdr *hdr 9184214082Sdim = elf_elfsections (output_bfd)[i]; 9185214082Sdim if (hdr->sh_type == type) 9186214082Sdim { 9187214082Sdim if (dyn.d_tag == DT_RELSZ 9188214082Sdim || dyn.d_tag == DT_RELASZ) 9189214082Sdim dyn.d_un.d_val += hdr->sh_size; 9190214082Sdim else if ((ufile_ptr) hdr->sh_offset 9191214082Sdim <= dyn.d_un.d_val - 1) 9192214082Sdim dyn.d_un.d_val = hdr->sh_offset; 9193214082Sdim } 9194214082Sdim } 9195214082Sdim bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 9196214082Sdim } 9197214082Sdim break; 9198214082Sdim 9199214082Sdim /* Set the bottom bit of DT_INIT/FINI if the 9200214082Sdim corresponding function is Thumb. */ 9201214082Sdim case DT_INIT: 9202214082Sdim name = info->init_function; 9203214082Sdim goto get_sym; 9204214082Sdim case DT_FINI: 9205214082Sdim name = info->fini_function; 9206214082Sdim get_sym: 9207214082Sdim /* If it wasn't set by elf_bfd_final_link 9208214082Sdim then there is nothing to adjust. */ 9209214082Sdim if (dyn.d_un.d_val != 0) 9210214082Sdim { 9211214082Sdim struct elf_link_hash_entry * eh; 9212214082Sdim 9213214082Sdim eh = elf_link_hash_lookup (elf_hash_table (info), name, 9214214082Sdim FALSE, FALSE, TRUE); 9215214082Sdim if (eh != (struct elf_link_hash_entry *) NULL 9216214082Sdim && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC) 9217214082Sdim { 9218214082Sdim dyn.d_un.d_val |= 1; 9219214082Sdim bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 9220214082Sdim } 9221214082Sdim } 9222214082Sdim break; 9223214082Sdim } 9224214082Sdim } 9225214082Sdim 9226214082Sdim /* Fill in the first entry in the procedure linkage table. */ 9227214082Sdim if (splt->size > 0 && elf32_arm_hash_table (info)->plt_header_size) 9228214082Sdim { 9229214082Sdim const bfd_vma *plt0_entry; 9230214082Sdim bfd_vma got_address, plt_address, got_displacement; 9231214082Sdim 9232214082Sdim /* Calculate the addresses of the GOT and PLT. */ 9233214082Sdim got_address = sgot->output_section->vma + sgot->output_offset; 9234214082Sdim plt_address = splt->output_section->vma + splt->output_offset; 9235214082Sdim 9236214082Sdim if (htab->vxworks_p) 9237214082Sdim { 9238214082Sdim /* The VxWorks GOT is relocated by the dynamic linker. 9239214082Sdim Therefore, we must emit relocations rather than simply 9240214082Sdim computing the values now. */ 9241214082Sdim Elf_Internal_Rela rel; 9242214082Sdim 9243214082Sdim plt0_entry = elf32_arm_vxworks_exec_plt0_entry; 9244214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[0], 9245214634Sdim splt->contents + 0); 9246214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[1], 9247214634Sdim splt->contents + 4); 9248214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[2], 9249214634Sdim splt->contents + 8); 9250214082Sdim bfd_put_32 (output_bfd, got_address, splt->contents + 12); 9251214082Sdim 9252214082Sdim /* Generate a relocation for _GLOBAL_OFFSET_TABLE_. */ 9253214082Sdim rel.r_offset = plt_address + 12; 9254214082Sdim rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32); 9255214082Sdim rel.r_addend = 0; 9256214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, 9257214082Sdim htab->srelplt2->contents); 9258214082Sdim } 9259214082Sdim else 9260214082Sdim { 9261214082Sdim got_displacement = got_address - (plt_address + 16); 9262214082Sdim 9263214082Sdim plt0_entry = elf32_arm_plt0_entry; 9264214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[0], 9265214634Sdim splt->contents + 0); 9266214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[1], 9267214634Sdim splt->contents + 4); 9268214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[2], 9269214634Sdim splt->contents + 8); 9270214634Sdim put_arm_insn (htab, output_bfd, plt0_entry[3], 9271214634Sdim splt->contents + 12); 9272214082Sdim 9273214082Sdim#ifdef FOUR_WORD_PLT 9274214082Sdim /* The displacement value goes in the otherwise-unused 9275214082Sdim last word of the second entry. */ 9276214082Sdim bfd_put_32 (output_bfd, got_displacement, splt->contents + 28); 9277214082Sdim#else 9278214082Sdim bfd_put_32 (output_bfd, got_displacement, splt->contents + 16); 9279214082Sdim#endif 9280214082Sdim } 9281214082Sdim } 9282214082Sdim 9283214082Sdim /* UnixWare sets the entsize of .plt to 4, although that doesn't 9284214082Sdim really seem like the right value. */ 9285214634Sdim if (splt->output_section->owner == output_bfd) 9286214634Sdim elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; 9287214082Sdim 9288214082Sdim if (htab->vxworks_p && !info->shared && htab->splt->size > 0) 9289214082Sdim { 9290214082Sdim /* Correct the .rel(a).plt.unloaded relocations. They will have 9291214082Sdim incorrect symbol indexes. */ 9292214082Sdim int num_plts; 9293214082Sdim unsigned char *p; 9294214082Sdim 9295214082Sdim num_plts = ((htab->splt->size - htab->plt_header_size) 9296214082Sdim / htab->plt_entry_size); 9297214082Sdim p = htab->srelplt2->contents + RELOC_SIZE (htab); 9298214082Sdim 9299214082Sdim for (; num_plts; num_plts--) 9300214082Sdim { 9301214082Sdim Elf_Internal_Rela rel; 9302214082Sdim 9303214082Sdim SWAP_RELOC_IN (htab) (output_bfd, p, &rel); 9304214082Sdim rel.r_info = ELF32_R_INFO (htab->root.hgot->indx, R_ARM_ABS32); 9305214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, p); 9306214082Sdim p += RELOC_SIZE (htab); 9307214082Sdim 9308214082Sdim SWAP_RELOC_IN (htab) (output_bfd, p, &rel); 9309214082Sdim rel.r_info = ELF32_R_INFO (htab->root.hplt->indx, R_ARM_ABS32); 9310214082Sdim SWAP_RELOC_OUT (htab) (output_bfd, &rel, p); 9311214082Sdim p += RELOC_SIZE (htab); 9312214082Sdim } 9313214082Sdim } 9314214082Sdim } 9315214082Sdim 9316214082Sdim /* Fill in the first three entries in the global offset table. */ 9317214082Sdim if (sgot) 9318214082Sdim { 9319214082Sdim if (sgot->size > 0) 9320214082Sdim { 9321214082Sdim if (sdyn == NULL) 9322214082Sdim bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); 9323214082Sdim else 9324214082Sdim bfd_put_32 (output_bfd, 9325214082Sdim sdyn->output_section->vma + sdyn->output_offset, 9326214082Sdim sgot->contents); 9327214082Sdim bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); 9328214082Sdim bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); 9329214082Sdim } 9330214082Sdim 9331214082Sdim elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; 9332214082Sdim } 9333214082Sdim 9334214082Sdim return TRUE; 9335214082Sdim} 9336214082Sdim 9337214082Sdimstatic void 9338214082Sdimelf32_arm_post_process_headers (bfd * abfd, struct bfd_link_info * link_info ATTRIBUTE_UNUSED) 9339214082Sdim{ 9340214082Sdim Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */ 9341214082Sdim struct elf32_arm_link_hash_table *globals; 9342214082Sdim 9343214082Sdim i_ehdrp = elf_elfheader (abfd); 9344214082Sdim 9345214082Sdim if (EF_ARM_EABI_VERSION (i_ehdrp->e_flags) == EF_ARM_EABI_UNKNOWN) 9346214157Sdim i_ehdrp->e_ident[EI_OSABI] = ARM_ELF_OS_ABI_VERSION; 9347214082Sdim else 9348214082Sdim i_ehdrp->e_ident[EI_OSABI] = 0; 9349214082Sdim i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION; 9350214082Sdim 9351214082Sdim if (link_info) 9352214082Sdim { 9353214082Sdim globals = elf32_arm_hash_table (link_info); 9354214082Sdim if (globals->byteswap_code) 9355214082Sdim i_ehdrp->e_flags |= EF_ARM_BE8; 9356214082Sdim } 9357214082Sdim} 9358214082Sdim 9359214082Sdimstatic enum elf_reloc_type_class 9360214082Sdimelf32_arm_reloc_type_class (const Elf_Internal_Rela *rela) 9361214082Sdim{ 9362214082Sdim switch ((int) ELF32_R_TYPE (rela->r_info)) 9363214082Sdim { 9364214082Sdim case R_ARM_RELATIVE: 9365214082Sdim return reloc_class_relative; 9366214082Sdim case R_ARM_JUMP_SLOT: 9367214082Sdim return reloc_class_plt; 9368214082Sdim case R_ARM_COPY: 9369214082Sdim return reloc_class_copy; 9370214082Sdim default: 9371214082Sdim return reloc_class_normal; 9372214082Sdim } 9373214082Sdim} 9374214082Sdim 9375214082Sdim/* Set the right machine number for an Arm ELF file. */ 9376214082Sdim 9377214082Sdimstatic bfd_boolean 9378214082Sdimelf32_arm_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr) 9379214082Sdim{ 9380214082Sdim if (hdr->sh_type == SHT_NOTE) 9381214082Sdim *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS; 9382214082Sdim 9383214082Sdim return TRUE; 9384214082Sdim} 9385214082Sdim 9386214082Sdimstatic void 9387214082Sdimelf32_arm_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) 9388214082Sdim{ 9389214082Sdim bfd_arm_update_notes (abfd, ARM_NOTE_SECTION); 9390214082Sdim} 9391214082Sdim 9392214082Sdim/* Return TRUE if this is an unwinding table entry. */ 9393214082Sdim 9394214082Sdimstatic bfd_boolean 9395214082Sdimis_arm_elf_unwind_section_name (bfd * abfd ATTRIBUTE_UNUSED, const char * name) 9396214082Sdim{ 9397214634Sdim return (CONST_STRNEQ (name, ELF_STRING_ARM_unwind) 9398214634Sdim || CONST_STRNEQ (name, ELF_STRING_ARM_unwind_once)); 9399214082Sdim} 9400214082Sdim 9401214082Sdim 9402214082Sdim/* Set the type and flags for an ARM section. We do this by 9403214082Sdim the section name, which is a hack, but ought to work. */ 9404214082Sdim 9405214082Sdimstatic bfd_boolean 9406214082Sdimelf32_arm_fake_sections (bfd * abfd, Elf_Internal_Shdr * hdr, asection * sec) 9407214082Sdim{ 9408214082Sdim const char * name; 9409214082Sdim 9410214082Sdim name = bfd_get_section_name (abfd, sec); 9411214082Sdim 9412214082Sdim if (is_arm_elf_unwind_section_name (abfd, name)) 9413214082Sdim { 9414214082Sdim hdr->sh_type = SHT_ARM_EXIDX; 9415214082Sdim hdr->sh_flags |= SHF_LINK_ORDER; 9416214082Sdim } 9417214082Sdim return TRUE; 9418214082Sdim} 9419214082Sdim 9420214082Sdim/* Handle an ARM specific section when reading an object file. This is 9421214082Sdim called when bfd_section_from_shdr finds a section with an unknown 9422214082Sdim type. */ 9423214082Sdim 9424214082Sdimstatic bfd_boolean 9425214082Sdimelf32_arm_section_from_shdr (bfd *abfd, 9426214082Sdim Elf_Internal_Shdr * hdr, 9427214082Sdim const char *name, 9428214082Sdim int shindex) 9429214082Sdim{ 9430214082Sdim /* There ought to be a place to keep ELF backend specific flags, but 9431214082Sdim at the moment there isn't one. We just keep track of the 9432214082Sdim sections by their name, instead. Fortunately, the ABI gives 9433214082Sdim names for all the ARM specific sections, so we will probably get 9434214082Sdim away with this. */ 9435214082Sdim switch (hdr->sh_type) 9436214082Sdim { 9437214082Sdim case SHT_ARM_EXIDX: 9438214082Sdim case SHT_ARM_PREEMPTMAP: 9439214082Sdim case SHT_ARM_ATTRIBUTES: 9440214082Sdim break; 9441214082Sdim 9442214082Sdim default: 9443214082Sdim return FALSE; 9444214082Sdim } 9445214082Sdim 9446214082Sdim if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) 9447214082Sdim return FALSE; 9448214082Sdim 9449214082Sdim return TRUE; 9450214082Sdim} 9451214082Sdim 9452214082Sdim/* A structure used to record a list of sections, independently 9453214082Sdim of the next and prev fields in the asection structure. */ 9454214082Sdimtypedef struct section_list 9455214082Sdim{ 9456214082Sdim asection * sec; 9457214082Sdim struct section_list * next; 9458214082Sdim struct section_list * prev; 9459214082Sdim} 9460214082Sdimsection_list; 9461214082Sdim 9462214082Sdim/* Unfortunately we need to keep a list of sections for which 9463214082Sdim an _arm_elf_section_data structure has been allocated. This 9464214082Sdim is because it is possible for functions like elf32_arm_write_section 9465214082Sdim to be called on a section which has had an elf_data_structure 9466214082Sdim allocated for it (and so the used_by_bfd field is valid) but 9467214082Sdim for which the ARM extended version of this structure - the 9468214082Sdim _arm_elf_section_data structure - has not been allocated. */ 9469214082Sdimstatic section_list * sections_with_arm_elf_section_data = NULL; 9470214082Sdim 9471214082Sdimstatic void 9472214082Sdimrecord_section_with_arm_elf_section_data (asection * sec) 9473214082Sdim{ 9474214082Sdim struct section_list * entry; 9475214082Sdim 9476214082Sdim entry = bfd_malloc (sizeof (* entry)); 9477214082Sdim if (entry == NULL) 9478214082Sdim return; 9479214082Sdim entry->sec = sec; 9480214082Sdim entry->next = sections_with_arm_elf_section_data; 9481214082Sdim entry->prev = NULL; 9482214082Sdim if (entry->next != NULL) 9483214082Sdim entry->next->prev = entry; 9484214082Sdim sections_with_arm_elf_section_data = entry; 9485214082Sdim} 9486214082Sdim 9487214082Sdimstatic struct section_list * 9488214082Sdimfind_arm_elf_section_entry (asection * sec) 9489214082Sdim{ 9490214082Sdim struct section_list * entry; 9491214082Sdim static struct section_list * last_entry = NULL; 9492214082Sdim 9493214082Sdim /* This is a short cut for the typical case where the sections are added 9494214082Sdim to the sections_with_arm_elf_section_data list in forward order and 9495214082Sdim then looked up here in backwards order. This makes a real difference 9496214082Sdim to the ld-srec/sec64k.exp linker test. */ 9497214082Sdim entry = sections_with_arm_elf_section_data; 9498214082Sdim if (last_entry != NULL) 9499214082Sdim { 9500214082Sdim if (last_entry->sec == sec) 9501214082Sdim entry = last_entry; 9502214082Sdim else if (last_entry->next != NULL 9503214082Sdim && last_entry->next->sec == sec) 9504214082Sdim entry = last_entry->next; 9505214082Sdim } 9506214082Sdim 9507214082Sdim for (; entry; entry = entry->next) 9508214082Sdim if (entry->sec == sec) 9509214082Sdim break; 9510214082Sdim 9511214082Sdim if (entry) 9512214082Sdim /* Record the entry prior to this one - it is the entry we are most 9513214082Sdim likely to want to locate next time. Also this way if we have been 9514214082Sdim called from unrecord_section_with_arm_elf_section_data() we will not 9515214082Sdim be caching a pointer that is about to be freed. */ 9516214082Sdim last_entry = entry->prev; 9517214082Sdim 9518214082Sdim return entry; 9519214082Sdim} 9520214082Sdim 9521214082Sdimstatic _arm_elf_section_data * 9522214082Sdimget_arm_elf_section_data (asection * sec) 9523214082Sdim{ 9524214082Sdim struct section_list * entry; 9525214082Sdim 9526214082Sdim entry = find_arm_elf_section_entry (sec); 9527214082Sdim 9528214082Sdim if (entry) 9529214082Sdim return elf32_arm_section_data (entry->sec); 9530214082Sdim else 9531214082Sdim return NULL; 9532214082Sdim} 9533214082Sdim 9534214082Sdimstatic void 9535214082Sdimunrecord_section_with_arm_elf_section_data (asection * sec) 9536214082Sdim{ 9537214082Sdim struct section_list * entry; 9538214082Sdim 9539214082Sdim entry = find_arm_elf_section_entry (sec); 9540214082Sdim 9541214082Sdim if (entry) 9542214082Sdim { 9543214082Sdim if (entry->prev != NULL) 9544214082Sdim entry->prev->next = entry->next; 9545214082Sdim if (entry->next != NULL) 9546214082Sdim entry->next->prev = entry->prev; 9547214082Sdim if (entry == sections_with_arm_elf_section_data) 9548214082Sdim sections_with_arm_elf_section_data = entry->next; 9549214082Sdim free (entry); 9550214082Sdim } 9551214082Sdim} 9552214082Sdim 9553214082Sdim 9554214634Sdimtypedef struct 9555214634Sdim{ 9556214634Sdim void *finfo; 9557214634Sdim struct bfd_link_info *info; 9558214634Sdim asection *sec; 9559214634Sdim int sec_shndx; 9560214634Sdim bfd_boolean (*func) (void *, const char *, Elf_Internal_Sym *, 9561214634Sdim asection *, struct elf_link_hash_entry *); 9562214634Sdim} output_arch_syminfo; 9563214634Sdim 9564214634Sdimenum map_symbol_type 9565214634Sdim{ 9566214634Sdim ARM_MAP_ARM, 9567214634Sdim ARM_MAP_THUMB, 9568214634Sdim ARM_MAP_DATA 9569214634Sdim}; 9570214634Sdim 9571214634Sdim 9572214634Sdim/* Output a single PLT mapping symbol. */ 9573214634Sdim 9574214082Sdimstatic bfd_boolean 9575214634Sdimelf32_arm_ouput_plt_map_sym (output_arch_syminfo *osi, 9576214634Sdim enum map_symbol_type type, 9577214634Sdim bfd_vma offset) 9578214082Sdim{ 9579214634Sdim static const char *names[3] = {"$a", "$t", "$d"}; 9580214634Sdim struct elf32_arm_link_hash_table *htab; 9581214634Sdim Elf_Internal_Sym sym; 9582214082Sdim 9583214634Sdim htab = elf32_arm_hash_table (osi->info); 9584214634Sdim sym.st_value = osi->sec->output_section->vma 9585214634Sdim + osi->sec->output_offset 9586214634Sdim + offset; 9587214634Sdim sym.st_size = 0; 9588214634Sdim sym.st_other = 0; 9589214634Sdim sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE); 9590214634Sdim sym.st_shndx = osi->sec_shndx; 9591214634Sdim if (!osi->func (osi->finfo, names[type], &sym, osi->sec, NULL)) 9592214082Sdim return FALSE; 9593214634Sdim return TRUE; 9594214634Sdim} 9595214082Sdim 9596214082Sdim 9597214634Sdim/* Output mapping symbols for PLT entries associated with H. */ 9598214082Sdim 9599214634Sdimstatic bfd_boolean 9600214634Sdimelf32_arm_output_plt_map (struct elf_link_hash_entry *h, void *inf) 9601214634Sdim{ 9602214634Sdim output_arch_syminfo *osi = (output_arch_syminfo *) inf; 9603214634Sdim struct elf32_arm_link_hash_table *htab; 9604214634Sdim struct elf32_arm_link_hash_entry *eh; 9605214634Sdim bfd_vma addr; 9606214634Sdim 9607214634Sdim htab = elf32_arm_hash_table (osi->info); 9608214634Sdim 9609214634Sdim if (h->root.type == bfd_link_hash_indirect) 9610214082Sdim return TRUE; 9611214082Sdim 9612214634Sdim if (h->root.type == bfd_link_hash_warning) 9613214634Sdim /* When warning symbols are created, they **replace** the "real" 9614214634Sdim entry in the hash table, thus we never get to see the real 9615214634Sdim symbol in a hash traversal. So look at it now. */ 9616214634Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 9617214634Sdim 9618214634Sdim if (h->plt.offset == (bfd_vma) -1) 9619214082Sdim return TRUE; 9620214082Sdim 9621214634Sdim eh = (struct elf32_arm_link_hash_entry *) h; 9622214634Sdim addr = h->plt.offset; 9623214634Sdim if (htab->symbian_p) 9624214634Sdim { 9625214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr)) 9626214634Sdim return FALSE; 9627214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 4)) 9628214634Sdim return FALSE; 9629214634Sdim } 9630214634Sdim else if (htab->vxworks_p) 9631214634Sdim { 9632214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr)) 9633214634Sdim return FALSE; 9634214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 8)) 9635214634Sdim return FALSE; 9636214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr + 12)) 9637214634Sdim return FALSE; 9638214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 20)) 9639214634Sdim return FALSE; 9640214634Sdim } 9641214634Sdim else 9642214634Sdim { 9643214634Sdim bfd_boolean thumb_stub; 9644214082Sdim 9645214634Sdim thumb_stub = eh->plt_thumb_refcount > 0 && !htab->use_blx; 9646214634Sdim if (thumb_stub) 9647214634Sdim { 9648214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_THUMB, addr - 4)) 9649214634Sdim return FALSE; 9650214634Sdim } 9651214634Sdim#ifdef FOUR_WORD_PLT 9652214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr)) 9653214634Sdim return FALSE; 9654214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_DATA, addr + 12)) 9655214634Sdim return FALSE; 9656214634Sdim#else 9657214634Sdim /* A three-word PLT with no Thumb thunk contains only Arm code, 9658214634Sdim so only need to output a mapping symbol for the first PLT entry and 9659214634Sdim entries with thumb thunks. */ 9660214634Sdim if (thumb_stub || addr == 20) 9661214634Sdim { 9662214634Sdim if (!elf32_arm_ouput_plt_map_sym (osi, ARM_MAP_ARM, addr)) 9663214634Sdim return FALSE; 9664214634Sdim } 9665214634Sdim#endif 9666214634Sdim } 9667214634Sdim 9668214634Sdim return TRUE; 9669214634Sdim} 9670214634Sdim 9671214634Sdim 9672214634Sdim/* Output mapping symbols for linker generated sections. */ 9673214634Sdim 9674214634Sdimstatic bfd_boolean 9675214634Sdimelf32_arm_output_arch_local_syms (bfd *output_bfd, 9676214634Sdim struct bfd_link_info *info, 9677214634Sdim void *finfo, bfd_boolean (*func) (void *, const char *, 9678214634Sdim Elf_Internal_Sym *, 9679214634Sdim asection *, 9680214634Sdim struct elf_link_hash_entry *)) 9681214634Sdim{ 9682214634Sdim output_arch_syminfo osi; 9683214634Sdim struct elf32_arm_link_hash_table *htab; 9684214634Sdim bfd_vma offset; 9685214634Sdim bfd_size_type size; 9686214634Sdim 9687214634Sdim htab = elf32_arm_hash_table (info); 9688214634Sdim check_use_blx(htab); 9689214634Sdim 9690214634Sdim osi.finfo = finfo; 9691214634Sdim osi.info = info; 9692214634Sdim osi.func = func; 9693214634Sdim 9694214634Sdim /* ARM->Thumb glue. */ 9695214634Sdim if (htab->arm_glue_size > 0) 9696214082Sdim { 9697214634Sdim osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner, 9698214634Sdim ARM2THUMB_GLUE_SECTION_NAME); 9699214082Sdim 9700214634Sdim osi.sec_shndx = _bfd_elf_section_from_bfd_section 9701214634Sdim (output_bfd, osi.sec->output_section); 9702214634Sdim if (info->shared || htab->root.is_relocatable_executable 9703214634Sdim || htab->pic_veneer) 9704214634Sdim size = ARM2THUMB_PIC_GLUE_SIZE; 9705214634Sdim else if (htab->use_blx) 9706214634Sdim size = ARM2THUMB_V5_STATIC_GLUE_SIZE; 9707214634Sdim else 9708214634Sdim size = ARM2THUMB_STATIC_GLUE_SIZE; 9709214634Sdim 9710214634Sdim for (offset = 0; offset < htab->arm_glue_size; offset += size) 9711214634Sdim { 9712214634Sdim elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, offset); 9713214634Sdim elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_DATA, offset + size - 4); 9714214634Sdim } 9715214082Sdim } 9716214082Sdim 9717214634Sdim /* Thumb->ARM glue. */ 9718214634Sdim if (htab->thumb_glue_size > 0) 9719214634Sdim { 9720214634Sdim osi.sec = bfd_get_section_by_name (htab->bfd_of_glue_owner, 9721214634Sdim THUMB2ARM_GLUE_SECTION_NAME); 9722214634Sdim 9723214634Sdim osi.sec_shndx = _bfd_elf_section_from_bfd_section 9724214634Sdim (output_bfd, osi.sec->output_section); 9725214634Sdim size = THUMB2ARM_GLUE_SIZE; 9726214634Sdim 9727214634Sdim for (offset = 0; offset < htab->thumb_glue_size; offset += size) 9728214634Sdim { 9729214634Sdim elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_THUMB, offset); 9730214634Sdim elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, offset + 4); 9731214634Sdim } 9732214634Sdim } 9733214634Sdim 9734214634Sdim /* Finally, output mapping symbols for the PLT. */ 9735214634Sdim if (!htab->splt || htab->splt->size == 0) 9736214634Sdim return TRUE; 9737214634Sdim 9738214634Sdim osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, 9739214634Sdim htab->splt->output_section); 9740214634Sdim osi.sec = htab->splt; 9741214634Sdim /* Output mapping symbols for the plt header. SymbianOS does not have a 9742214634Sdim plt header. */ 9743214634Sdim if (htab->vxworks_p) 9744214634Sdim { 9745214634Sdim /* VxWorks shared libraries have no PLT header. */ 9746214634Sdim if (!info->shared) 9747214634Sdim { 9748214634Sdim if (!elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, 0)) 9749214634Sdim return FALSE; 9750214634Sdim if (!elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_DATA, 12)) 9751214634Sdim return FALSE; 9752214634Sdim } 9753214634Sdim } 9754214634Sdim else if (!htab->symbian_p) 9755214634Sdim { 9756214634Sdim if (!elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_ARM, 0)) 9757214634Sdim return FALSE; 9758214634Sdim#ifndef FOUR_WORD_PLT 9759214634Sdim if (!elf32_arm_ouput_plt_map_sym (&osi, ARM_MAP_DATA, 16)) 9760214634Sdim return FALSE; 9761214634Sdim#endif 9762214634Sdim } 9763214634Sdim 9764214634Sdim elf_link_hash_traverse (&htab->root, elf32_arm_output_plt_map, (void *) &osi); 9765214082Sdim return TRUE; 9766214082Sdim} 9767214082Sdim 9768214082Sdim/* Allocate target specific section data. */ 9769214082Sdim 9770214082Sdimstatic bfd_boolean 9771214082Sdimelf32_arm_new_section_hook (bfd *abfd, asection *sec) 9772214082Sdim{ 9773214634Sdim if (!sec->used_by_bfd) 9774214634Sdim { 9775214634Sdim _arm_elf_section_data *sdata; 9776214634Sdim bfd_size_type amt = sizeof (*sdata); 9777214082Sdim 9778214634Sdim sdata = bfd_zalloc (abfd, amt); 9779214634Sdim if (sdata == NULL) 9780214634Sdim return FALSE; 9781214634Sdim sec->used_by_bfd = sdata; 9782214634Sdim } 9783214082Sdim 9784214082Sdim record_section_with_arm_elf_section_data (sec); 9785214082Sdim 9786214082Sdim return _bfd_elf_new_section_hook (abfd, sec); 9787214082Sdim} 9788214082Sdim 9789214082Sdim 9790214082Sdim/* Used to order a list of mapping symbols by address. */ 9791214082Sdim 9792214082Sdimstatic int 9793214082Sdimelf32_arm_compare_mapping (const void * a, const void * b) 9794214082Sdim{ 9795214082Sdim return ((const elf32_arm_section_map *) a)->vma 9796214082Sdim > ((const elf32_arm_section_map *) b)->vma; 9797214082Sdim} 9798214082Sdim 9799214082Sdim 9800214082Sdim/* Do code byteswapping. Return FALSE afterwards so that the section is 9801214082Sdim written out as normal. */ 9802214082Sdim 9803214082Sdimstatic bfd_boolean 9804214634Sdimelf32_arm_write_section (bfd *output_bfd, 9805214634Sdim struct bfd_link_info *link_info, asection *sec, 9806214082Sdim bfd_byte *contents) 9807214082Sdim{ 9808214634Sdim int mapcount, errcount; 9809214082Sdim _arm_elf_section_data *arm_data; 9810214634Sdim struct elf32_arm_link_hash_table *globals = elf32_arm_hash_table (link_info); 9811214082Sdim elf32_arm_section_map *map; 9812214634Sdim elf32_vfp11_erratum_list *errnode; 9813214082Sdim bfd_vma ptr; 9814214082Sdim bfd_vma end; 9815214634Sdim bfd_vma offset = sec->output_section->vma + sec->output_offset; 9816214082Sdim bfd_byte tmp; 9817214082Sdim int i; 9818214082Sdim 9819214082Sdim /* If this section has not been allocated an _arm_elf_section_data 9820214082Sdim structure then we cannot record anything. */ 9821214082Sdim arm_data = get_arm_elf_section_data (sec); 9822214082Sdim if (arm_data == NULL) 9823214082Sdim return FALSE; 9824214082Sdim 9825214082Sdim mapcount = arm_data->mapcount; 9826214082Sdim map = arm_data->map; 9827214634Sdim errcount = arm_data->erratumcount; 9828214082Sdim 9829214634Sdim if (errcount != 0) 9830214634Sdim { 9831214634Sdim unsigned int endianflip = bfd_big_endian (output_bfd) ? 3 : 0; 9832214634Sdim 9833214634Sdim for (errnode = arm_data->erratumlist; errnode != 0; 9834214634Sdim errnode = errnode->next) 9835214634Sdim { 9836214634Sdim bfd_vma index = errnode->vma - offset; 9837214634Sdim 9838214634Sdim switch (errnode->type) 9839214634Sdim { 9840214634Sdim case VFP11_ERRATUM_BRANCH_TO_ARM_VENEER: 9841214634Sdim { 9842214634Sdim bfd_vma branch_to_veneer; 9843214634Sdim /* Original condition code of instruction, plus bit mask for 9844214634Sdim ARM B instruction. */ 9845214634Sdim unsigned int insn = (errnode->u.b.vfp_insn & 0xf0000000) 9846214634Sdim | 0x0a000000; 9847214634Sdim 9848214634Sdim /* The instruction is before the label. */ 9849214634Sdim index -= 4; 9850214634Sdim 9851214634Sdim /* Above offset included in -4 below. */ 9852214634Sdim branch_to_veneer = errnode->u.b.veneer->vma 9853214634Sdim - errnode->vma - 4; 9854214634Sdim 9855214634Sdim if ((signed) branch_to_veneer < -(1 << 25) 9856214634Sdim || (signed) branch_to_veneer >= (1 << 25)) 9857214634Sdim (*_bfd_error_handler) (_("%B: error: VFP11 veneer out of " 9858214634Sdim "range"), output_bfd); 9859214634Sdim 9860214634Sdim insn |= (branch_to_veneer >> 2) & 0xffffff; 9861214634Sdim contents[endianflip ^ index] = insn & 0xff; 9862214634Sdim contents[endianflip ^ (index + 1)] = (insn >> 8) & 0xff; 9863214634Sdim contents[endianflip ^ (index + 2)] = (insn >> 16) & 0xff; 9864214634Sdim contents[endianflip ^ (index + 3)] = (insn >> 24) & 0xff; 9865214634Sdim } 9866214634Sdim break; 9867214634Sdim 9868214634Sdim case VFP11_ERRATUM_ARM_VENEER: 9869214634Sdim { 9870214634Sdim bfd_vma branch_from_veneer; 9871214634Sdim unsigned int insn; 9872214634Sdim 9873214634Sdim /* Take size of veneer into account. */ 9874214634Sdim branch_from_veneer = errnode->u.v.branch->vma 9875214634Sdim - errnode->vma - 12; 9876214634Sdim 9877214634Sdim if ((signed) branch_from_veneer < -(1 << 25) 9878214634Sdim || (signed) branch_from_veneer >= (1 << 25)) 9879214634Sdim (*_bfd_error_handler) (_("%B: error: VFP11 veneer out of " 9880214634Sdim "range"), output_bfd); 9881214634Sdim 9882214634Sdim /* Original instruction. */ 9883214634Sdim insn = errnode->u.v.branch->u.b.vfp_insn; 9884214634Sdim contents[endianflip ^ index] = insn & 0xff; 9885214634Sdim contents[endianflip ^ (index + 1)] = (insn >> 8) & 0xff; 9886214634Sdim contents[endianflip ^ (index + 2)] = (insn >> 16) & 0xff; 9887214634Sdim contents[endianflip ^ (index + 3)] = (insn >> 24) & 0xff; 9888214634Sdim 9889214634Sdim /* Branch back to insn after original insn. */ 9890214634Sdim insn = 0xea000000 | ((branch_from_veneer >> 2) & 0xffffff); 9891214634Sdim contents[endianflip ^ (index + 4)] = insn & 0xff; 9892214634Sdim contents[endianflip ^ (index + 5)] = (insn >> 8) & 0xff; 9893214634Sdim contents[endianflip ^ (index + 6)] = (insn >> 16) & 0xff; 9894214634Sdim contents[endianflip ^ (index + 7)] = (insn >> 24) & 0xff; 9895214634Sdim } 9896214634Sdim break; 9897214634Sdim 9898214634Sdim default: 9899214634Sdim abort (); 9900214634Sdim } 9901214634Sdim } 9902214634Sdim } 9903214634Sdim 9904214082Sdim if (mapcount == 0) 9905214082Sdim return FALSE; 9906214082Sdim 9907214634Sdim if (globals->byteswap_code) 9908214082Sdim { 9909214634Sdim qsort (map, mapcount, sizeof (* map), elf32_arm_compare_mapping); 9910214082Sdim 9911214634Sdim ptr = map[0].vma; 9912214634Sdim for (i = 0; i < mapcount; i++) 9913214634Sdim { 9914214634Sdim if (i == mapcount - 1) 9915214634Sdim end = sec->size; 9916214634Sdim else 9917214634Sdim end = map[i + 1].vma; 9918214634Sdim 9919214634Sdim switch (map[i].type) 9920214082Sdim { 9921214634Sdim case 'a': 9922214634Sdim /* Byte swap code words. */ 9923214634Sdim while (ptr + 3 < end) 9924214634Sdim { 9925214634Sdim tmp = contents[ptr]; 9926214634Sdim contents[ptr] = contents[ptr + 3]; 9927214634Sdim contents[ptr + 3] = tmp; 9928214634Sdim tmp = contents[ptr + 1]; 9929214634Sdim contents[ptr + 1] = contents[ptr + 2]; 9930214634Sdim contents[ptr + 2] = tmp; 9931214634Sdim ptr += 4; 9932214634Sdim } 9933214634Sdim break; 9934214082Sdim 9935214634Sdim case 't': 9936214634Sdim /* Byte swap code halfwords. */ 9937214634Sdim while (ptr + 1 < end) 9938214634Sdim { 9939214634Sdim tmp = contents[ptr]; 9940214634Sdim contents[ptr] = contents[ptr + 1]; 9941214634Sdim contents[ptr + 1] = tmp; 9942214634Sdim ptr += 2; 9943214634Sdim } 9944214634Sdim break; 9945214634Sdim 9946214634Sdim case 'd': 9947214634Sdim /* Leave data alone. */ 9948214634Sdim break; 9949214082Sdim } 9950214634Sdim ptr = end; 9951214634Sdim } 9952214082Sdim } 9953214082Sdim 9954214082Sdim free (map); 9955214082Sdim arm_data->mapcount = 0; 9956214634Sdim arm_data->mapsize = 0; 9957214082Sdim arm_data->map = NULL; 9958214082Sdim unrecord_section_with_arm_elf_section_data (sec); 9959214082Sdim 9960214082Sdim return FALSE; 9961214082Sdim} 9962214082Sdim 9963214082Sdimstatic void 9964214082Sdimunrecord_section_via_map_over_sections (bfd * abfd ATTRIBUTE_UNUSED, 9965214082Sdim asection * sec, 9966214082Sdim void * ignore ATTRIBUTE_UNUSED) 9967214082Sdim{ 9968214082Sdim unrecord_section_with_arm_elf_section_data (sec); 9969214082Sdim} 9970214082Sdim 9971214082Sdimstatic bfd_boolean 9972214082Sdimelf32_arm_close_and_cleanup (bfd * abfd) 9973214082Sdim{ 9974214634Sdim if (abfd->sections) 9975214634Sdim bfd_map_over_sections (abfd, 9976214634Sdim unrecord_section_via_map_over_sections, 9977214634Sdim NULL); 9978214082Sdim 9979214082Sdim return _bfd_elf_close_and_cleanup (abfd); 9980214082Sdim} 9981214082Sdim 9982214634Sdimstatic bfd_boolean 9983214634Sdimelf32_arm_bfd_free_cached_info (bfd * abfd) 9984214634Sdim{ 9985214634Sdim if (abfd->sections) 9986214634Sdim bfd_map_over_sections (abfd, 9987214634Sdim unrecord_section_via_map_over_sections, 9988214634Sdim NULL); 9989214634Sdim 9990214634Sdim return _bfd_free_cached_info (abfd); 9991214634Sdim} 9992214634Sdim 9993214082Sdim/* Display STT_ARM_TFUNC symbols as functions. */ 9994214082Sdim 9995214082Sdimstatic void 9996214082Sdimelf32_arm_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED, 9997214082Sdim asymbol *asym) 9998214082Sdim{ 9999214082Sdim elf_symbol_type *elfsym = (elf_symbol_type *) asym; 10000214082Sdim 10001214082Sdim if (ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_ARM_TFUNC) 10002214082Sdim elfsym->symbol.flags |= BSF_FUNCTION; 10003214082Sdim} 10004214082Sdim 10005214082Sdim 10006214082Sdim/* Mangle thumb function symbols as we read them in. */ 10007214082Sdim 10008214634Sdimstatic bfd_boolean 10009214082Sdimelf32_arm_swap_symbol_in (bfd * abfd, 10010214082Sdim const void *psrc, 10011214082Sdim const void *pshn, 10012214082Sdim Elf_Internal_Sym *dst) 10013214082Sdim{ 10014214634Sdim if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst)) 10015214634Sdim return FALSE; 10016214082Sdim 10017214082Sdim /* New EABI objects mark thumb function symbols by setting the low bit of 10018214082Sdim the address. Turn these into STT_ARM_TFUNC. */ 10019214082Sdim if (ELF_ST_TYPE (dst->st_info) == STT_FUNC 10020214082Sdim && (dst->st_value & 1)) 10021214082Sdim { 10022214082Sdim dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_ARM_TFUNC); 10023214082Sdim dst->st_value &= ~(bfd_vma) 1; 10024214082Sdim } 10025214634Sdim return TRUE; 10026214082Sdim} 10027214082Sdim 10028214082Sdim 10029214082Sdim/* Mangle thumb function symbols as we write them out. */ 10030214082Sdim 10031214082Sdimstatic void 10032214082Sdimelf32_arm_swap_symbol_out (bfd *abfd, 10033214082Sdim const Elf_Internal_Sym *src, 10034214082Sdim void *cdst, 10035214082Sdim void *shndx) 10036214082Sdim{ 10037214082Sdim Elf_Internal_Sym newsym; 10038214082Sdim 10039214082Sdim /* We convert STT_ARM_TFUNC symbols into STT_FUNC with the low bit 10040214082Sdim of the address set, as per the new EABI. We do this unconditionally 10041214082Sdim because objcopy does not set the elf header flags until after 10042214082Sdim it writes out the symbol table. */ 10043214082Sdim if (ELF_ST_TYPE (src->st_info) == STT_ARM_TFUNC) 10044214082Sdim { 10045214082Sdim newsym = *src; 10046214082Sdim newsym.st_info = ELF_ST_INFO (ELF_ST_BIND (src->st_info), STT_FUNC); 10047214634Sdim if (newsym.st_shndx != SHN_UNDEF) 10048214634Sdim { 10049214634Sdim /* Do this only for defined symbols. At link type, the static 10050214634Sdim linker will simulate the work of dynamic linker of resolving 10051214634Sdim symbols and will carry over the thumbness of found symbols to 10052214634Sdim the output symbol table. It's not clear how it happens, but 10053214634Sdim the thumbness of undefined symbols can well be different at 10054214634Sdim runtime, and writing '1' for them will be confusing for users 10055214634Sdim and possibly for dynamic linker itself. 10056214634Sdim */ 10057214634Sdim newsym.st_value |= 1; 10058214634Sdim } 10059214082Sdim 10060214082Sdim src = &newsym; 10061214082Sdim } 10062214082Sdim bfd_elf32_swap_symbol_out (abfd, src, cdst, shndx); 10063214082Sdim} 10064214082Sdim 10065214082Sdim/* Add the PT_ARM_EXIDX program header. */ 10066214082Sdim 10067214082Sdimstatic bfd_boolean 10068214082Sdimelf32_arm_modify_segment_map (bfd *abfd, 10069214082Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 10070214082Sdim{ 10071214082Sdim struct elf_segment_map *m; 10072214082Sdim asection *sec; 10073214082Sdim 10074214082Sdim sec = bfd_get_section_by_name (abfd, ".ARM.exidx"); 10075214082Sdim if (sec != NULL && (sec->flags & SEC_LOAD) != 0) 10076214082Sdim { 10077214082Sdim /* If there is already a PT_ARM_EXIDX header, then we do not 10078214082Sdim want to add another one. This situation arises when running 10079214082Sdim "strip"; the input binary already has the header. */ 10080214082Sdim m = elf_tdata (abfd)->segment_map; 10081214082Sdim while (m && m->p_type != PT_ARM_EXIDX) 10082214082Sdim m = m->next; 10083214082Sdim if (!m) 10084214082Sdim { 10085214082Sdim m = bfd_zalloc (abfd, sizeof (struct elf_segment_map)); 10086214082Sdim if (m == NULL) 10087214082Sdim return FALSE; 10088214082Sdim m->p_type = PT_ARM_EXIDX; 10089214082Sdim m->count = 1; 10090214082Sdim m->sections[0] = sec; 10091214082Sdim 10092214082Sdim m->next = elf_tdata (abfd)->segment_map; 10093214082Sdim elf_tdata (abfd)->segment_map = m; 10094214082Sdim } 10095214082Sdim } 10096214082Sdim 10097214082Sdim return TRUE; 10098214082Sdim} 10099214082Sdim 10100214082Sdim/* We may add a PT_ARM_EXIDX program header. */ 10101214082Sdim 10102214082Sdimstatic int 10103214634Sdimelf32_arm_additional_program_headers (bfd *abfd, 10104214634Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 10105214082Sdim{ 10106214082Sdim asection *sec; 10107214082Sdim 10108214082Sdim sec = bfd_get_section_by_name (abfd, ".ARM.exidx"); 10109214082Sdim if (sec != NULL && (sec->flags & SEC_LOAD) != 0) 10110214082Sdim return 1; 10111214082Sdim else 10112214082Sdim return 0; 10113214082Sdim} 10114214082Sdim 10115214634Sdim/* We have two function types: STT_FUNC and STT_ARM_TFUNC. */ 10116214634Sdimstatic bfd_boolean 10117214634Sdimelf32_arm_is_function_type (unsigned int type) 10118214634Sdim{ 10119214634Sdim return (type == STT_FUNC) || (type == STT_ARM_TFUNC); 10120214634Sdim} 10121214634Sdim 10122214082Sdim/* We use this to override swap_symbol_in and swap_symbol_out. */ 10123214082Sdimconst struct elf_size_info elf32_arm_size_info = { 10124214082Sdim sizeof (Elf32_External_Ehdr), 10125214082Sdim sizeof (Elf32_External_Phdr), 10126214082Sdim sizeof (Elf32_External_Shdr), 10127214082Sdim sizeof (Elf32_External_Rel), 10128214082Sdim sizeof (Elf32_External_Rela), 10129214082Sdim sizeof (Elf32_External_Sym), 10130214082Sdim sizeof (Elf32_External_Dyn), 10131214082Sdim sizeof (Elf_External_Note), 10132214082Sdim 4, 10133214082Sdim 1, 10134214082Sdim 32, 2, 10135214082Sdim ELFCLASS32, EV_CURRENT, 10136214082Sdim bfd_elf32_write_out_phdrs, 10137214082Sdim bfd_elf32_write_shdrs_and_ehdr, 10138214082Sdim bfd_elf32_write_relocs, 10139214082Sdim elf32_arm_swap_symbol_in, 10140214082Sdim elf32_arm_swap_symbol_out, 10141214082Sdim bfd_elf32_slurp_reloc_table, 10142214082Sdim bfd_elf32_slurp_symbol_table, 10143214082Sdim bfd_elf32_swap_dyn_in, 10144214082Sdim bfd_elf32_swap_dyn_out, 10145214082Sdim bfd_elf32_swap_reloc_in, 10146214082Sdim bfd_elf32_swap_reloc_out, 10147214082Sdim bfd_elf32_swap_reloca_in, 10148214082Sdim bfd_elf32_swap_reloca_out 10149214082Sdim}; 10150214082Sdim 10151214082Sdim#define ELF_ARCH bfd_arch_arm 10152214082Sdim#define ELF_MACHINE_CODE EM_ARM 10153214082Sdim#ifdef __QNXTARGET__ 10154214082Sdim#define ELF_MAXPAGESIZE 0x1000 10155214082Sdim#else 10156214082Sdim#define ELF_MAXPAGESIZE 0x8000 10157214082Sdim#endif 10158214082Sdim#define ELF_MINPAGESIZE 0x1000 10159214634Sdim#define ELF_COMMONPAGESIZE 0x1000 10160214082Sdim 10161214082Sdim#define bfd_elf32_mkobject elf32_arm_mkobject 10162214082Sdim 10163214082Sdim#define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data 10164214082Sdim#define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data 10165214082Sdim#define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags 10166214082Sdim#define bfd_elf32_bfd_print_private_bfd_data elf32_arm_print_private_bfd_data 10167214082Sdim#define bfd_elf32_bfd_link_hash_table_create elf32_arm_link_hash_table_create 10168214082Sdim#define bfd_elf32_bfd_reloc_type_lookup elf32_arm_reloc_type_lookup 10169214634Sdim#define bfd_elf32_bfd_reloc_name_lookup elf32_arm_reloc_name_lookup 10170214082Sdim#define bfd_elf32_find_nearest_line elf32_arm_find_nearest_line 10171214082Sdim#define bfd_elf32_find_inliner_info elf32_arm_find_inliner_info 10172214082Sdim#define bfd_elf32_new_section_hook elf32_arm_new_section_hook 10173214082Sdim#define bfd_elf32_bfd_is_target_special_symbol elf32_arm_is_target_special_symbol 10174214082Sdim#define bfd_elf32_close_and_cleanup elf32_arm_close_and_cleanup 10175214634Sdim#define bfd_elf32_bfd_free_cached_info elf32_arm_bfd_free_cached_info 10176214082Sdim 10177214082Sdim#define elf_backend_get_symbol_type elf32_arm_get_symbol_type 10178214082Sdim#define elf_backend_gc_mark_hook elf32_arm_gc_mark_hook 10179214634Sdim#define elf_backend_gc_mark_extra_sections elf32_arm_gc_mark_extra_sections 10180214082Sdim#define elf_backend_gc_sweep_hook elf32_arm_gc_sweep_hook 10181214082Sdim#define elf_backend_check_relocs elf32_arm_check_relocs 10182214082Sdim#define elf_backend_relocate_section elf32_arm_relocate_section 10183214082Sdim#define elf_backend_write_section elf32_arm_write_section 10184214082Sdim#define elf_backend_adjust_dynamic_symbol elf32_arm_adjust_dynamic_symbol 10185214082Sdim#define elf_backend_create_dynamic_sections elf32_arm_create_dynamic_sections 10186214082Sdim#define elf_backend_finish_dynamic_symbol elf32_arm_finish_dynamic_symbol 10187214082Sdim#define elf_backend_finish_dynamic_sections elf32_arm_finish_dynamic_sections 10188214082Sdim#define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections 10189214634Sdim#define elf_backend_init_index_section _bfd_elf_init_2_index_sections 10190214082Sdim#define elf_backend_post_process_headers elf32_arm_post_process_headers 10191214082Sdim#define elf_backend_reloc_type_class elf32_arm_reloc_type_class 10192214082Sdim#define elf_backend_object_p elf32_arm_object_p 10193214082Sdim#define elf_backend_section_flags elf32_arm_section_flags 10194214082Sdim#define elf_backend_fake_sections elf32_arm_fake_sections 10195214082Sdim#define elf_backend_section_from_shdr elf32_arm_section_from_shdr 10196214082Sdim#define elf_backend_final_write_processing elf32_arm_final_write_processing 10197214082Sdim#define elf_backend_copy_indirect_symbol elf32_arm_copy_indirect_symbol 10198214082Sdim#define elf_backend_symbol_processing elf32_arm_symbol_processing 10199214082Sdim#define elf_backend_size_info elf32_arm_size_info 10200214082Sdim#define elf_backend_modify_segment_map elf32_arm_modify_segment_map 10201214082Sdim#define elf_backend_additional_program_headers \ 10202214082Sdim elf32_arm_additional_program_headers 10203214634Sdim#define elf_backend_output_arch_local_syms \ 10204214634Sdim elf32_arm_output_arch_local_syms 10205214634Sdim#define elf_backend_begin_write_processing \ 10206214634Sdim elf32_arm_begin_write_processing 10207214634Sdim#define elf_backend_is_function_type elf32_arm_is_function_type 10208214082Sdim 10209214082Sdim#define elf_backend_can_refcount 1 10210214082Sdim#define elf_backend_can_gc_sections 1 10211214082Sdim#define elf_backend_plt_readonly 1 10212214082Sdim#define elf_backend_want_got_plt 1 10213214082Sdim#define elf_backend_want_plt_sym 0 10214214082Sdim#define elf_backend_may_use_rel_p 1 10215214082Sdim#define elf_backend_may_use_rela_p 0 10216214082Sdim#define elf_backend_default_use_rela_p 0 10217214082Sdim 10218214082Sdim#define elf_backend_got_header_size 12 10219214082Sdim 10220214634Sdim#undef elf_backend_obj_attrs_vendor 10221214634Sdim#define elf_backend_obj_attrs_vendor "aeabi" 10222214634Sdim#undef elf_backend_obj_attrs_section 10223214634Sdim#define elf_backend_obj_attrs_section ".ARM.attributes" 10224214634Sdim#undef elf_backend_obj_attrs_arg_type 10225214634Sdim#define elf_backend_obj_attrs_arg_type elf32_arm_obj_attrs_arg_type 10226214634Sdim#undef elf_backend_obj_attrs_section_type 10227214634Sdim#define elf_backend_obj_attrs_section_type SHT_ARM_ATTRIBUTES 10228214634Sdim 10229214082Sdim#include "elf32-target.h" 10230214082Sdim 10231214082Sdim/* VxWorks Targets */ 10232214082Sdim 10233214082Sdim#undef TARGET_LITTLE_SYM 10234214082Sdim#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vxworks_vec 10235214082Sdim#undef TARGET_LITTLE_NAME 10236214082Sdim#define TARGET_LITTLE_NAME "elf32-littlearm-vxworks" 10237214082Sdim#undef TARGET_BIG_SYM 10238214082Sdim#define TARGET_BIG_SYM bfd_elf32_bigarm_vxworks_vec 10239214082Sdim#undef TARGET_BIG_NAME 10240214082Sdim#define TARGET_BIG_NAME "elf32-bigarm-vxworks" 10241214082Sdim 10242214082Sdim/* Like elf32_arm_link_hash_table_create -- but overrides 10243214082Sdim appropriately for VxWorks. */ 10244214082Sdimstatic struct bfd_link_hash_table * 10245214082Sdimelf32_arm_vxworks_link_hash_table_create (bfd *abfd) 10246214082Sdim{ 10247214082Sdim struct bfd_link_hash_table *ret; 10248214082Sdim 10249214082Sdim ret = elf32_arm_link_hash_table_create (abfd); 10250214082Sdim if (ret) 10251214082Sdim { 10252214082Sdim struct elf32_arm_link_hash_table *htab 10253214082Sdim = (struct elf32_arm_link_hash_table *) ret; 10254214082Sdim htab->use_rel = 0; 10255214082Sdim htab->vxworks_p = 1; 10256214082Sdim } 10257214082Sdim return ret; 10258214082Sdim} 10259214082Sdim 10260214082Sdimstatic void 10261214082Sdimelf32_arm_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker) 10262214082Sdim{ 10263214082Sdim elf32_arm_final_write_processing (abfd, linker); 10264214082Sdim elf_vxworks_final_write_processing (abfd, linker); 10265214082Sdim} 10266214082Sdim 10267214082Sdim#undef elf32_bed 10268214082Sdim#define elf32_bed elf32_arm_vxworks_bed 10269214082Sdim 10270214082Sdim#undef bfd_elf32_bfd_link_hash_table_create 10271214082Sdim#define bfd_elf32_bfd_link_hash_table_create \ 10272214082Sdim elf32_arm_vxworks_link_hash_table_create 10273214082Sdim#undef elf_backend_add_symbol_hook 10274214082Sdim#define elf_backend_add_symbol_hook \ 10275214082Sdim elf_vxworks_add_symbol_hook 10276214082Sdim#undef elf_backend_final_write_processing 10277214082Sdim#define elf_backend_final_write_processing \ 10278214082Sdim elf32_arm_vxworks_final_write_processing 10279214082Sdim#undef elf_backend_emit_relocs 10280214082Sdim#define elf_backend_emit_relocs \ 10281214082Sdim elf_vxworks_emit_relocs 10282214082Sdim 10283214082Sdim#undef elf_backend_may_use_rel_p 10284214082Sdim#define elf_backend_may_use_rel_p 0 10285214082Sdim#undef elf_backend_may_use_rela_p 10286214082Sdim#define elf_backend_may_use_rela_p 1 10287214082Sdim#undef elf_backend_default_use_rela_p 10288214082Sdim#define elf_backend_default_use_rela_p 1 10289214082Sdim#undef elf_backend_want_plt_sym 10290214082Sdim#define elf_backend_want_plt_sym 1 10291214082Sdim#undef ELF_MAXPAGESIZE 10292214082Sdim#define ELF_MAXPAGESIZE 0x1000 10293214082Sdim 10294214082Sdim#include "elf32-target.h" 10295214082Sdim 10296214082Sdim 10297214082Sdim/* Symbian OS Targets */ 10298214082Sdim 10299214082Sdim#undef TARGET_LITTLE_SYM 10300214082Sdim#define TARGET_LITTLE_SYM bfd_elf32_littlearm_symbian_vec 10301214082Sdim#undef TARGET_LITTLE_NAME 10302214082Sdim#define TARGET_LITTLE_NAME "elf32-littlearm-symbian" 10303214082Sdim#undef TARGET_BIG_SYM 10304214082Sdim#define TARGET_BIG_SYM bfd_elf32_bigarm_symbian_vec 10305214082Sdim#undef TARGET_BIG_NAME 10306214082Sdim#define TARGET_BIG_NAME "elf32-bigarm-symbian" 10307214082Sdim 10308214082Sdim/* Like elf32_arm_link_hash_table_create -- but overrides 10309214082Sdim appropriately for Symbian OS. */ 10310214082Sdimstatic struct bfd_link_hash_table * 10311214082Sdimelf32_arm_symbian_link_hash_table_create (bfd *abfd) 10312214082Sdim{ 10313214082Sdim struct bfd_link_hash_table *ret; 10314214082Sdim 10315214082Sdim ret = elf32_arm_link_hash_table_create (abfd); 10316214082Sdim if (ret) 10317214082Sdim { 10318214082Sdim struct elf32_arm_link_hash_table *htab 10319214082Sdim = (struct elf32_arm_link_hash_table *)ret; 10320214082Sdim /* There is no PLT header for Symbian OS. */ 10321214082Sdim htab->plt_header_size = 0; 10322214082Sdim /* The PLT entries are each three instructions. */ 10323214082Sdim htab->plt_entry_size = 4 * NUM_ELEM (elf32_arm_symbian_plt_entry); 10324214082Sdim htab->symbian_p = 1; 10325214082Sdim /* Symbian uses armv5t or above, so use_blx is always true. */ 10326214082Sdim htab->use_blx = 1; 10327214082Sdim htab->root.is_relocatable_executable = 1; 10328214082Sdim } 10329214082Sdim return ret; 10330214082Sdim} 10331214082Sdim 10332214082Sdimstatic const struct bfd_elf_special_section 10333214082Sdimelf32_arm_symbian_special_sections[] = 10334214082Sdim{ 10335214082Sdim /* In a BPABI executable, the dynamic linking sections do not go in 10336214082Sdim the loadable read-only segment. The post-linker may wish to 10337214082Sdim refer to these sections, but they are not part of the final 10338214082Sdim program image. */ 10339214634Sdim { STRING_COMMA_LEN (".dynamic"), 0, SHT_DYNAMIC, 0 }, 10340214634Sdim { STRING_COMMA_LEN (".dynstr"), 0, SHT_STRTAB, 0 }, 10341214634Sdim { STRING_COMMA_LEN (".dynsym"), 0, SHT_DYNSYM, 0 }, 10342214634Sdim { STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, 0 }, 10343214634Sdim { STRING_COMMA_LEN (".hash"), 0, SHT_HASH, 0 }, 10344214082Sdim /* These sections do not need to be writable as the SymbianOS 10345214082Sdim postlinker will arrange things so that no dynamic relocation is 10346214082Sdim required. */ 10347214634Sdim { STRING_COMMA_LEN (".init_array"), 0, SHT_INIT_ARRAY, SHF_ALLOC }, 10348214634Sdim { STRING_COMMA_LEN (".fini_array"), 0, SHT_FINI_ARRAY, SHF_ALLOC }, 10349214634Sdim { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC }, 10350214634Sdim { NULL, 0, 0, 0, 0 } 10351214082Sdim}; 10352214082Sdim 10353214082Sdimstatic void 10354214082Sdimelf32_arm_symbian_begin_write_processing (bfd *abfd, 10355214634Sdim struct bfd_link_info *link_info) 10356214082Sdim{ 10357214082Sdim /* BPABI objects are never loaded directly by an OS kernel; they are 10358214082Sdim processed by a postlinker first, into an OS-specific format. If 10359214082Sdim the D_PAGED bit is set on the file, BFD will align segments on 10360214082Sdim page boundaries, so that an OS can directly map the file. With 10361214082Sdim BPABI objects, that just results in wasted space. In addition, 10362214082Sdim because we clear the D_PAGED bit, map_sections_to_segments will 10363214082Sdim recognize that the program headers should not be mapped into any 10364214082Sdim loadable segment. */ 10365214082Sdim abfd->flags &= ~D_PAGED; 10366214634Sdim elf32_arm_begin_write_processing(abfd, link_info); 10367214082Sdim} 10368214082Sdim 10369214082Sdimstatic bfd_boolean 10370214082Sdimelf32_arm_symbian_modify_segment_map (bfd *abfd, 10371214082Sdim struct bfd_link_info *info) 10372214082Sdim{ 10373214082Sdim struct elf_segment_map *m; 10374214082Sdim asection *dynsec; 10375214082Sdim 10376214082Sdim /* BPABI shared libraries and executables should have a PT_DYNAMIC 10377214082Sdim segment. However, because the .dynamic section is not marked 10378214082Sdim with SEC_LOAD, the generic ELF code will not create such a 10379214082Sdim segment. */ 10380214082Sdim dynsec = bfd_get_section_by_name (abfd, ".dynamic"); 10381214082Sdim if (dynsec) 10382214082Sdim { 10383214634Sdim for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) 10384214634Sdim if (m->p_type == PT_DYNAMIC) 10385214634Sdim break; 10386214634Sdim 10387214634Sdim if (m == NULL) 10388214634Sdim { 10389214634Sdim m = _bfd_elf_make_dynamic_segment (abfd, dynsec); 10390214634Sdim m->next = elf_tdata (abfd)->segment_map; 10391214634Sdim elf_tdata (abfd)->segment_map = m; 10392214634Sdim } 10393214082Sdim } 10394214082Sdim 10395214082Sdim /* Also call the generic arm routine. */ 10396214082Sdim return elf32_arm_modify_segment_map (abfd, info); 10397214082Sdim} 10398214082Sdim 10399214082Sdim#undef elf32_bed 10400214082Sdim#define elf32_bed elf32_arm_symbian_bed 10401214082Sdim 10402214082Sdim/* The dynamic sections are not allocated on SymbianOS; the postlinker 10403214082Sdim will process them and then discard them. */ 10404214082Sdim#undef ELF_DYNAMIC_SEC_FLAGS 10405214082Sdim#define ELF_DYNAMIC_SEC_FLAGS \ 10406214082Sdim (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED) 10407214082Sdim 10408214082Sdim#undef bfd_elf32_bfd_link_hash_table_create 10409214082Sdim#define bfd_elf32_bfd_link_hash_table_create \ 10410214082Sdim elf32_arm_symbian_link_hash_table_create 10411214082Sdim#undef elf_backend_add_symbol_hook 10412214082Sdim 10413214082Sdim#undef elf_backend_special_sections 10414214082Sdim#define elf_backend_special_sections elf32_arm_symbian_special_sections 10415214082Sdim 10416214082Sdim#undef elf_backend_begin_write_processing 10417214082Sdim#define elf_backend_begin_write_processing \ 10418214082Sdim elf32_arm_symbian_begin_write_processing 10419214082Sdim#undef elf_backend_final_write_processing 10420214082Sdim#define elf_backend_final_write_processing \ 10421214082Sdim elf32_arm_final_write_processing 10422214082Sdim#undef elf_backend_emit_relocs 10423214082Sdim 10424214082Sdim#undef elf_backend_modify_segment_map 10425214082Sdim#define elf_backend_modify_segment_map elf32_arm_symbian_modify_segment_map 10426214082Sdim 10427214082Sdim/* There is no .got section for BPABI objects, and hence no header. */ 10428214082Sdim#undef elf_backend_got_header_size 10429214082Sdim#define elf_backend_got_header_size 0 10430214082Sdim 10431214082Sdim/* Similarly, there is no .got.plt section. */ 10432214082Sdim#undef elf_backend_want_got_plt 10433214082Sdim#define elf_backend_want_got_plt 0 10434214082Sdim 10435214082Sdim#undef elf_backend_may_use_rel_p 10436214082Sdim#define elf_backend_may_use_rel_p 1 10437214082Sdim#undef elf_backend_may_use_rela_p 10438214082Sdim#define elf_backend_may_use_rela_p 0 10439214082Sdim#undef elf_backend_default_use_rela_p 10440214082Sdim#define elf_backend_default_use_rela_p 0 10441214082Sdim#undef elf_backend_want_plt_sym 10442214082Sdim#define elf_backend_want_plt_sym 0 10443214082Sdim#undef ELF_MAXPAGESIZE 10444214082Sdim#define ELF_MAXPAGESIZE 0x8000 10445214082Sdim 10446214082Sdim#include "elf32-target.h" 10447