1 /* 32-bit ELF support for ARM old abi option. 2 Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. 3 4 This file is part of BFD, the Binary File Descriptor library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 #define OLD_ARM_ABI 21 #define bfd_elf32_arm_allocate_interworking_sections \ 22 bfd_elf32_arm_oabi_allocate_interworking_sections 23 #define bfd_elf32_arm_get_bfd_for_interworking \ 24 bfd_elf32_arm_oabi_get_bfd_for_interworking 25 #define bfd_elf32_arm_process_before_allocation \ 26 bfd_elf32_arm_oabi_process_before_allocation 27 #define bfd_elf32_arm_add_glue_sections_to_bfd \ 28 bfd_elf32_arm_oabi_add_glue_sections_to_bfd 29 30 #include "elf/arm.h" 31 #include "bfd.h" 32 #include "sysdep.h" 33 #include "libbfd.h" 34 #include "elf-bfd.h" 35 36 #ifndef NUM_ELEM 37 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) 38 #endif 39 40 #define TARGET_LITTLE_SYM bfd_elf32_littlearm_oabi_vec 41 #define TARGET_LITTLE_NAME "elf32-littlearm-oabi" 42 #define TARGET_BIG_SYM bfd_elf32_bigarm_oabi_vec 43 #define TARGET_BIG_NAME "elf32-bigarm-oabi" 44 45 #define elf_info_to_howto elf32_arm_info_to_howto 46 #define elf_info_to_howto_rel 0 47 48 #define ARM_ELF_ABI_VERSION 0 49 #define ARM_ELF_OS_ABI_VERSION 0 50 51 static reloc_howto_type * find_howto PARAMS ((unsigned int)); 52 static void elf32_arm_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); 53 static reloc_howto_type * elf32_arm_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); 54 55 static reloc_howto_type elf32_arm_howto_table[] = 56 { 57 /* No relocation. */ 58 HOWTO (R_ARM_NONE, /* type */ 59 0, /* rightshift */ 60 0, /* size (0 = byte, 1 = short, 2 = long) */ 61 0, /* bitsize */ 62 FALSE, /* pc_relative */ 63 0, /* bitpos */ 64 complain_overflow_dont, /* complain_on_overflow */ 65 bfd_elf_generic_reloc, /* special_function */ 66 "R_ARM_NONE", /* name */ 67 FALSE, /* partial_inplace */ 68 0, /* src_mask */ 69 0, /* dst_mask */ 70 FALSE), /* pcrel_offset */ 71 72 HOWTO (R_ARM_PC24, /* type */ 73 2, /* rightshift */ 74 2, /* size (0 = byte, 1 = short, 2 = long) */ 75 24, /* bitsize */ 76 TRUE, /* pc_relative */ 77 0, /* bitpos */ 78 complain_overflow_signed, /* complain_on_overflow */ 79 bfd_elf_generic_reloc, /* special_function */ 80 "R_ARM_PC24", /* name */ 81 FALSE, /* partial_inplace */ 82 0x00ffffff, /* src_mask */ 83 0x00ffffff, /* dst_mask */ 84 TRUE), /* pcrel_offset */ 85 86 /* 32 bit absolute. */ 87 HOWTO (R_ARM_ABS32, /* type */ 88 0, /* rightshift */ 89 2, /* size (0 = byte, 1 = short, 2 = long) */ 90 32, /* bitsize */ 91 FALSE, /* pc_relative */ 92 0, /* bitpos */ 93 complain_overflow_bitfield, /* complain_on_overflow */ 94 bfd_elf_generic_reloc, /* special_function */ 95 "R_ARM_ABS32", /* name */ 96 FALSE, /* partial_inplace */ 97 0xffffffff, /* src_mask */ 98 0xffffffff, /* dst_mask */ 99 FALSE), /* pcrel_offset */ 100 101 /* Standard 32bit pc-relative reloc. */ 102 HOWTO (R_ARM_REL32, /* type */ 103 0, /* rightshift */ 104 2, /* size (0 = byte, 1 = short, 2 = long) */ 105 32, /* bitsize */ 106 TRUE, /* pc_relative */ 107 0, /* bitpos */ 108 complain_overflow_bitfield, /* complain_on_overflow */ 109 bfd_elf_generic_reloc, /* special_function */ 110 "R_ARM_REL32", /* name */ 111 FALSE, /* partial_inplace */ 112 0xffffffff, /* src_mask */ 113 0xffffffff, /* dst_mask */ 114 TRUE), /* pcrel_offset */ 115 116 /* 8 bit absolute. */ 117 HOWTO (R_ARM_ABS8, /* type */ 118 0, /* rightshift */ 119 0, /* size (0 = byte, 1 = short, 2 = long) */ 120 8, /* bitsize */ 121 FALSE, /* pc_relative */ 122 0, /* bitpos */ 123 complain_overflow_bitfield, /* complain_on_overflow */ 124 bfd_elf_generic_reloc, /* special_function */ 125 "R_ARM_ABS8", /* name */ 126 FALSE, /* partial_inplace */ 127 0x000000ff, /* src_mask */ 128 0x000000ff, /* dst_mask */ 129 FALSE), /* pcrel_offset */ 130 131 /* 16 bit absolute. */ 132 HOWTO (R_ARM_ABS16, /* type */ 133 0, /* rightshift */ 134 1, /* size (0 = byte, 1 = short, 2 = long) */ 135 16, /* bitsize */ 136 FALSE, /* pc_relative */ 137 0, /* bitpos */ 138 complain_overflow_bitfield, /* complain_on_overflow */ 139 bfd_elf_generic_reloc, /* special_function */ 140 "R_ARM_ABS16", /* name */ 141 FALSE, /* partial_inplace */ 142 0, /* src_mask */ 143 0, /* dst_mask */ 144 FALSE), /* pcrel_offset */ 145 146 /* 12 bit absolute. */ 147 HOWTO (R_ARM_ABS12, /* type */ 148 0, /* rightshift */ 149 2, /* size (0 = byte, 1 = short, 2 = long) */ 150 12, /* bitsize */ 151 FALSE, /* pc_relative */ 152 0, /* bitpos */ 153 complain_overflow_bitfield, /* complain_on_overflow */ 154 bfd_elf_generic_reloc, /* special_function */ 155 "R_ARM_ABS12", /* name */ 156 FALSE, /* partial_inplace */ 157 0x000008ff, /* src_mask */ 158 0x000008ff, /* dst_mask */ 159 FALSE), /* pcrel_offset */ 160 161 HOWTO (R_ARM_THM_ABS5, /* type */ 162 6, /* rightshift */ 163 1, /* size (0 = byte, 1 = short, 2 = long) */ 164 5, /* bitsize */ 165 FALSE, /* pc_relative */ 166 0, /* bitpos */ 167 complain_overflow_bitfield, /* complain_on_overflow */ 168 bfd_elf_generic_reloc, /* special_function */ 169 "R_ARM_THM_ABS5", /* name */ 170 FALSE, /* partial_inplace */ 171 0x000007e0, /* src_mask */ 172 0x000007e0, /* dst_mask */ 173 FALSE), /* pcrel_offset */ 174 175 HOWTO (R_ARM_THM_PC22, /* type */ 176 1, /* rightshift */ 177 2, /* size (0 = byte, 1 = short, 2 = long) */ 178 23, /* bitsize */ 179 TRUE, /* pc_relative */ 180 0, /* bitpos */ 181 complain_overflow_signed, /* complain_on_overflow */ 182 bfd_elf_generic_reloc, /* special_function */ 183 "R_ARM_THM_PC22", /* name */ 184 FALSE, /* partial_inplace */ 185 0x07ff07ff, /* src_mask */ 186 0x07ff07ff, /* dst_mask */ 187 TRUE), /* pcrel_offset */ 188 189 HOWTO (R_ARM_SBREL32, /* type */ 190 0, /* rightshift */ 191 0, /* size (0 = byte, 1 = short, 2 = long) */ 192 0, /* bitsize */ 193 FALSE, /* pc_relative */ 194 0, /* bitpos */ 195 complain_overflow_dont,/* complain_on_overflow */ 196 bfd_elf_generic_reloc, /* special_function */ 197 "R_ARM_SBREL32", /* name */ 198 FALSE, /* partial_inplace */ 199 0, /* src_mask */ 200 0, /* dst_mask */ 201 FALSE), /* pcrel_offset */ 202 203 HOWTO (R_ARM_AMP_VCALL9, /* type */ 204 1, /* rightshift */ 205 1, /* size (0 = byte, 1 = short, 2 = long) */ 206 8, /* bitsize */ 207 TRUE, /* pc_relative */ 208 0, /* bitpos */ 209 complain_overflow_signed, /* complain_on_overflow */ 210 bfd_elf_generic_reloc, /* special_function */ 211 "R_ARM_AMP_VCALL9", /* name */ 212 FALSE, /* partial_inplace */ 213 0x000000ff, /* src_mask */ 214 0x000000ff, /* dst_mask */ 215 TRUE), /* pcrel_offset */ 216 217 /* 12 bit pc relative. */ 218 HOWTO (R_ARM_THM_PC11, /* type */ 219 1, /* rightshift */ 220 1, /* size (0 = byte, 1 = short, 2 = long) */ 221 11, /* bitsize */ 222 TRUE, /* pc_relative */ 223 0, /* bitpos */ 224 complain_overflow_signed, /* complain_on_overflow */ 225 bfd_elf_generic_reloc, /* special_function */ 226 "R_ARM_THM_PC11", /* name */ 227 FALSE, /* partial_inplace */ 228 0x000007ff, /* src_mask */ 229 0x000007ff, /* dst_mask */ 230 TRUE), /* pcrel_offset */ 231 232 /* 12 bit pc relative. */ 233 HOWTO (R_ARM_THM_PC9, /* type */ 234 1, /* rightshift */ 235 1, /* size (0 = byte, 1 = short, 2 = long) */ 236 8, /* bitsize */ 237 TRUE, /* pc_relative */ 238 0, /* bitpos */ 239 complain_overflow_signed, /* complain_on_overflow */ 240 bfd_elf_generic_reloc, /* special_function */ 241 "R_ARM_THM_PC9", /* name */ 242 FALSE, /* partial_inplace */ 243 0x000000ff, /* src_mask */ 244 0x000000ff, /* dst_mask */ 245 TRUE), /* pcrel_offset */ 246 247 /* GNU extension to record C++ vtable hierarchy. */ 248 HOWTO (R_ARM_GNU_VTINHERIT, /* type */ 249 0, /* rightshift */ 250 2, /* size (0 = byte, 1 = short, 2 = long) */ 251 0, /* bitsize */ 252 FALSE, /* pc_relative */ 253 0, /* bitpos */ 254 complain_overflow_dont, /* complain_on_overflow */ 255 NULL, /* special_function */ 256 "R_ARM_GNU_VTINHERIT", /* name */ 257 FALSE, /* partial_inplace */ 258 0, /* src_mask */ 259 0, /* dst_mask */ 260 FALSE), /* pcrel_offset */ 261 262 /* GNU extension to record C++ vtable member usage. */ 263 HOWTO (R_ARM_GNU_VTENTRY, /* type */ 264 0, /* rightshift */ 265 2, /* size (0 = byte, 1 = short, 2 = long) */ 266 0, /* bitsize */ 267 FALSE, /* pc_relative */ 268 0, /* bitpos */ 269 complain_overflow_dont, /* complain_on_overflow */ 270 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 271 "R_ARM_GNU_VTENTRY", /* name */ 272 FALSE, /* partial_inplace */ 273 0, /* src_mask */ 274 0, /* dst_mask */ 275 FALSE), /* pcrel_offset */ 276 277 /* XXX - gap in index numbering here. */ 278 279 HOWTO (R_ARM_PLT32, /* type */ 280 2, /* rightshift */ 281 2, /* size (0 = byte, 1 = short, 2 = long) */ 282 26, /* bitsize */ 283 TRUE, /* pc_relative */ 284 0, /* bitpos */ 285 complain_overflow_bitfield,/* complain_on_overflow */ 286 bfd_elf_generic_reloc, /* special_function */ 287 "R_ARM_PLT32", /* name */ 288 TRUE, /* partial_inplace */ 289 0x00ffffff, /* src_mask */ 290 0x00ffffff, /* dst_mask */ 291 TRUE), /* pcrel_offset */ 292 293 /* XXX - gap in index numbering here. */ 294 295 HOWTO (R_ARM_RREL32, /* type */ 296 0, /* rightshift */ 297 0, /* size (0 = byte, 1 = short, 2 = long) */ 298 0, /* bitsize */ 299 FALSE, /* pc_relative */ 300 0, /* bitpos */ 301 complain_overflow_dont, /* complain_on_overflow */ 302 bfd_elf_generic_reloc, /* special_function */ 303 "R_ARM_RREL32", /* name */ 304 FALSE, /* partial_inplace */ 305 0, /* src_mask */ 306 0, /* dst_mask */ 307 FALSE), /* pcrel_offset */ 308 309 HOWTO (R_ARM_RABS32, /* type */ 310 0, /* rightshift */ 311 0, /* size (0 = byte, 1 = short, 2 = long) */ 312 0, /* bitsize */ 313 FALSE, /* pc_relative */ 314 0, /* bitpos */ 315 complain_overflow_dont, /* complain_on_overflow */ 316 bfd_elf_generic_reloc, /* special_function */ 317 "R_ARM_RABS32", /* name */ 318 FALSE, /* partial_inplace */ 319 0, /* src_mask */ 320 0, /* dst_mask */ 321 FALSE), /* pcrel_offset */ 322 323 HOWTO (R_ARM_RPC24, /* type */ 324 0, /* rightshift */ 325 0, /* size (0 = byte, 1 = short, 2 = long) */ 326 0, /* bitsize */ 327 FALSE, /* pc_relative */ 328 0, /* bitpos */ 329 complain_overflow_dont, /* complain_on_overflow */ 330 bfd_elf_generic_reloc, /* special_function */ 331 "R_ARM_RPC24", /* name */ 332 FALSE, /* partial_inplace */ 333 0, /* src_mask */ 334 0, /* dst_mask */ 335 FALSE), /* pcrel_offset */ 336 337 HOWTO (R_ARM_RBASE, /* type */ 338 0, /* rightshift */ 339 0, /* size (0 = byte, 1 = short, 2 = long) */ 340 0, /* bitsize */ 341 FALSE, /* pc_relative */ 342 0, /* bitpos */ 343 complain_overflow_dont, /* complain_on_overflow */ 344 bfd_elf_generic_reloc, /* special_function */ 345 "R_ARM_RBASE", /* name */ 346 FALSE, /* partial_inplace */ 347 0, /* src_mask */ 348 0, /* dst_mask */ 349 FALSE) /* pcrel_offset */ 350 }; 351 352 /* Locate a reloc in the howto table. This function must be used 353 when the entry number is is > R_ARM_GNU_VTINHERIT. */ 354 355 static reloc_howto_type * 356 find_howto (r_type) 357 unsigned int r_type; 358 { 359 int i; 360 361 for (i = NUM_ELEM (elf32_arm_howto_table); i--;) 362 if (elf32_arm_howto_table [i].type == r_type) 363 return elf32_arm_howto_table + i; 364 365 return NULL; 366 } 367 368 static void 369 elf32_arm_info_to_howto (abfd, bfd_reloc, elf_reloc) 370 bfd *abfd ATTRIBUTE_UNUSED; 371 arelent *bfd_reloc; 372 Elf_Internal_Rela *elf_reloc; 373 { 374 unsigned int r_type; 375 376 r_type = ELF32_R_TYPE (elf_reloc->r_info); 377 378 if (r_type <= R_ARM_GNU_VTINHERIT) 379 bfd_reloc->howto = & elf32_arm_howto_table[r_type]; 380 else 381 bfd_reloc->howto = find_howto (r_type); 382 } 383 384 struct elf32_arm_reloc_map 385 { 386 bfd_reloc_code_real_type bfd_reloc_val; 387 unsigned char elf_reloc_val; 388 }; 389 390 static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = 391 { 392 {BFD_RELOC_NONE, R_ARM_NONE }, 393 {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24 }, 394 {BFD_RELOC_32, R_ARM_ABS32 }, 395 {BFD_RELOC_32_PCREL, R_ARM_REL32 }, 396 {BFD_RELOC_8, R_ARM_ABS8 }, 397 {BFD_RELOC_16, R_ARM_ABS16 }, 398 {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12 }, 399 {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5 }, 400 {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22 }, 401 {BFD_RELOC_NONE, R_ARM_SBREL32 }, 402 {BFD_RELOC_NONE, R_ARM_AMP_VCALL9 }, 403 {BFD_RELOC_THUMB_PCREL_BRANCH12, R_ARM_THM_PC11 }, 404 {BFD_RELOC_THUMB_PCREL_BRANCH9, R_ARM_THM_PC9 }, 405 {BFD_RELOC_VTABLE_INHERIT, R_ARM_GNU_VTINHERIT }, 406 {BFD_RELOC_VTABLE_ENTRY, R_ARM_GNU_VTENTRY } 407 }; 408 409 static reloc_howto_type * 410 elf32_arm_reloc_type_lookup (abfd, code) 411 bfd * abfd ATTRIBUTE_UNUSED; 412 bfd_reloc_code_real_type code; 413 { 414 unsigned int i; 415 416 for (i = NUM_ELEM (elf32_arm_reloc_map); i--;) 417 if (elf32_arm_reloc_map[i].bfd_reloc_val == code) 418 return & elf32_arm_howto_table [elf32_arm_reloc_map[i].elf_reloc_val]; 419 420 if (code == BFD_RELOC_ARM_PLT32) 421 return find_howto (R_ARM_PLT32); 422 423 return NULL; 424 } 425 426 #include "elf32-arm.h" 427