1/* 32-bit ELF support for ARM new 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#include "elf/arm.h" 21#include "bfd.h" 22#include "sysdep.h" 23#include "libbfd.h" 24#include "elf-bfd.h" 25 26#ifndef NUM_ELEM 27#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0])) 28#endif 29 30#define USE_REL 1 31 32#define elf_info_to_howto 0 33#define elf_info_to_howto_rel elf32_arm_info_to_howto 34 35#define ARM_ELF_ABI_VERSION 0 36#define ARM_ELF_OS_ABI_VERSION ELFOSABI_ARM 37 38static reloc_howto_type * elf32_arm_reloc_type_lookup 39 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code)); 40static bfd_boolean elf32_arm_nabi_grok_prstatus 41 PARAMS ((bfd *abfd, Elf_Internal_Note *note)); 42static bfd_boolean elf32_arm_nabi_grok_psinfo 43 PARAMS ((bfd *abfd, Elf_Internal_Note *note)); 44 45/* Note: code such as elf32_arm_reloc_type_lookup expect to use e.g. 46 R_ARM_PC24 as an index into this, and find the R_ARM_PC24 HOWTO 47 in that slot. */ 48 49static reloc_howto_type elf32_arm_howto_table[] = 50{ 51 /* No relocation */ 52 HOWTO (R_ARM_NONE, /* type */ 53 0, /* rightshift */ 54 0, /* size (0 = byte, 1 = short, 2 = long) */ 55 0, /* bitsize */ 56 FALSE, /* pc_relative */ 57 0, /* bitpos */ 58 complain_overflow_dont,/* complain_on_overflow */ 59 bfd_elf_generic_reloc, /* special_function */ 60 "R_ARM_NONE", /* name */ 61 FALSE, /* partial_inplace */ 62 0, /* src_mask */ 63 0, /* dst_mask */ 64 FALSE), /* pcrel_offset */ 65 66 HOWTO (R_ARM_PC24, /* type */ 67 2, /* rightshift */ 68 2, /* size (0 = byte, 1 = short, 2 = long) */ 69 24, /* bitsize */ 70 TRUE, /* pc_relative */ 71 0, /* bitpos */ 72 complain_overflow_signed,/* complain_on_overflow */ 73 bfd_elf_generic_reloc, /* special_function */ 74 "R_ARM_PC24", /* name */ 75 FALSE, /* partial_inplace */ 76 0x00ffffff, /* src_mask */ 77 0x00ffffff, /* dst_mask */ 78 TRUE), /* pcrel_offset */ 79 80 /* 32 bit absolute */ 81 HOWTO (R_ARM_ABS32, /* type */ 82 0, /* rightshift */ 83 2, /* size (0 = byte, 1 = short, 2 = long) */ 84 32, /* bitsize */ 85 FALSE, /* pc_relative */ 86 0, /* bitpos */ 87 complain_overflow_bitfield,/* complain_on_overflow */ 88 bfd_elf_generic_reloc, /* special_function */ 89 "R_ARM_ABS32", /* name */ 90 FALSE, /* partial_inplace */ 91 0xffffffff, /* src_mask */ 92 0xffffffff, /* dst_mask */ 93 FALSE), /* pcrel_offset */ 94 95 /* standard 32bit pc-relative reloc */ 96 HOWTO (R_ARM_REL32, /* type */ 97 0, /* rightshift */ 98 2, /* size (0 = byte, 1 = short, 2 = long) */ 99 32, /* bitsize */ 100 TRUE, /* pc_relative */ 101 0, /* bitpos */ 102 complain_overflow_bitfield,/* complain_on_overflow */ 103 bfd_elf_generic_reloc, /* special_function */ 104 "R_ARM_REL32", /* name */ 105 FALSE, /* partial_inplace */ 106 0xffffffff, /* src_mask */ 107 0xffffffff, /* dst_mask */ 108 TRUE), /* pcrel_offset */ 109 110 /* 8 bit absolute */ 111 HOWTO (R_ARM_PC13, /* type */ 112 0, /* rightshift */ 113 0, /* size (0 = byte, 1 = short, 2 = long) */ 114 8, /* bitsize */ 115 FALSE, /* pc_relative */ 116 0, /* bitpos */ 117 complain_overflow_bitfield,/* complain_on_overflow */ 118 bfd_elf_generic_reloc, /* special_function */ 119 "R_ARM_PC13", /* name */ 120 FALSE, /* partial_inplace */ 121 0x000000ff, /* src_mask */ 122 0x000000ff, /* dst_mask */ 123 FALSE), /* pcrel_offset */ 124 125 /* 16 bit absolute */ 126 HOWTO (R_ARM_ABS16, /* type */ 127 0, /* rightshift */ 128 1, /* size (0 = byte, 1 = short, 2 = long) */ 129 16, /* bitsize */ 130 FALSE, /* pc_relative */ 131 0, /* bitpos */ 132 complain_overflow_bitfield,/* complain_on_overflow */ 133 bfd_elf_generic_reloc, /* special_function */ 134 "R_ARM_ABS16", /* name */ 135 FALSE, /* partial_inplace */ 136 0x0000ffff, /* src_mask */ 137 0x0000ffff, /* dst_mask */ 138 FALSE), /* pcrel_offset */ 139 140 /* 12 bit absolute */ 141 HOWTO (R_ARM_ABS12, /* type */ 142 0, /* rightshift */ 143 2, /* size (0 = byte, 1 = short, 2 = long) */ 144 12, /* bitsize */ 145 FALSE, /* pc_relative */ 146 0, /* bitpos */ 147 complain_overflow_bitfield,/* complain_on_overflow */ 148 bfd_elf_generic_reloc, /* special_function */ 149 "R_ARM_ABS12", /* name */ 150 FALSE, /* partial_inplace */ 151 0x000008ff, /* src_mask */ 152 0x000008ff, /* dst_mask */ 153 FALSE), /* pcrel_offset */ 154 155 HOWTO (R_ARM_THM_ABS5, /* type */ 156 6, /* rightshift */ 157 1, /* size (0 = byte, 1 = short, 2 = long) */ 158 5, /* bitsize */ 159 FALSE, /* pc_relative */ 160 0, /* bitpos */ 161 complain_overflow_bitfield,/* complain_on_overflow */ 162 bfd_elf_generic_reloc, /* special_function */ 163 "R_ARM_THM_ABS5", /* name */ 164 FALSE, /* partial_inplace */ 165 0x000007e0, /* src_mask */ 166 0x000007e0, /* dst_mask */ 167 FALSE), /* pcrel_offset */ 168 169 /* 8 bit absolute */ 170 HOWTO (R_ARM_ABS8, /* type */ 171 0, /* rightshift */ 172 0, /* size (0 = byte, 1 = short, 2 = long) */ 173 8, /* bitsize */ 174 FALSE, /* pc_relative */ 175 0, /* bitpos */ 176 complain_overflow_bitfield,/* complain_on_overflow */ 177 bfd_elf_generic_reloc, /* special_function */ 178 "R_ARM_ABS8", /* name */ 179 FALSE, /* partial_inplace */ 180 0x000000ff, /* src_mask */ 181 0x000000ff, /* dst_mask */ 182 FALSE), /* pcrel_offset */ 183 184 HOWTO (R_ARM_SBREL32, /* type */ 185 0, /* rightshift */ 186 2, /* size (0 = byte, 1 = short, 2 = long) */ 187 32, /* bitsize */ 188 FALSE, /* pc_relative */ 189 0, /* bitpos */ 190 complain_overflow_dont,/* complain_on_overflow */ 191 bfd_elf_generic_reloc, /* special_function */ 192 "R_ARM_SBREL32", /* name */ 193 FALSE, /* partial_inplace */ 194 0xffffffff, /* src_mask */ 195 0xffffffff, /* dst_mask */ 196 FALSE), /* pcrel_offset */ 197 198 HOWTO (R_ARM_THM_PC22, /* type */ 199 1, /* rightshift */ 200 2, /* size (0 = byte, 1 = short, 2 = long) */ 201 23, /* bitsize */ 202 TRUE, /* pc_relative */ 203 0, /* bitpos */ 204 complain_overflow_signed,/* complain_on_overflow */ 205 bfd_elf_generic_reloc, /* special_function */ 206 "R_ARM_THM_PC22", /* name */ 207 FALSE, /* partial_inplace */ 208 0x07ff07ff, /* src_mask */ 209 0x07ff07ff, /* dst_mask */ 210 TRUE), /* pcrel_offset */ 211 212 HOWTO (R_ARM_THM_PC8, /* type */ 213 1, /* rightshift */ 214 1, /* size (0 = byte, 1 = short, 2 = long) */ 215 8, /* bitsize */ 216 TRUE, /* pc_relative */ 217 0, /* bitpos */ 218 complain_overflow_signed,/* complain_on_overflow */ 219 bfd_elf_generic_reloc, /* special_function */ 220 "R_ARM_THM_PC8", /* name */ 221 FALSE, /* partial_inplace */ 222 0x000000ff, /* src_mask */ 223 0x000000ff, /* dst_mask */ 224 TRUE), /* pcrel_offset */ 225 226 HOWTO (R_ARM_AMP_VCALL9, /* type */ 227 1, /* rightshift */ 228 1, /* size (0 = byte, 1 = short, 2 = long) */ 229 8, /* bitsize */ 230 TRUE, /* pc_relative */ 231 0, /* bitpos */ 232 complain_overflow_signed,/* complain_on_overflow */ 233 bfd_elf_generic_reloc, /* special_function */ 234 "R_ARM_AMP_VCALL9", /* name */ 235 FALSE, /* partial_inplace */ 236 0x000000ff, /* src_mask */ 237 0x000000ff, /* dst_mask */ 238 TRUE), /* pcrel_offset */ 239 240 HOWTO (R_ARM_SWI24, /* type */ 241 0, /* rightshift */ 242 0, /* size (0 = byte, 1 = short, 2 = long) */ 243 0, /* bitsize */ 244 FALSE, /* pc_relative */ 245 0, /* bitpos */ 246 complain_overflow_signed,/* complain_on_overflow */ 247 bfd_elf_generic_reloc, /* special_function */ 248 "R_ARM_SWI24", /* name */ 249 FALSE, /* partial_inplace */ 250 0x00000000, /* src_mask */ 251 0x00000000, /* dst_mask */ 252 FALSE), /* pcrel_offset */ 253 254 HOWTO (R_ARM_THM_SWI8, /* type */ 255 0, /* rightshift */ 256 0, /* size (0 = byte, 1 = short, 2 = long) */ 257 0, /* bitsize */ 258 FALSE, /* pc_relative */ 259 0, /* bitpos */ 260 complain_overflow_signed,/* complain_on_overflow */ 261 bfd_elf_generic_reloc, /* special_function */ 262 "R_ARM_SWI8", /* name */ 263 FALSE, /* partial_inplace */ 264 0x00000000, /* src_mask */ 265 0x00000000, /* dst_mask */ 266 FALSE), /* pcrel_offset */ 267 268 /* BLX instruction for the ARM. */ 269 HOWTO (R_ARM_XPC25, /* type */ 270 2, /* rightshift */ 271 2, /* size (0 = byte, 1 = short, 2 = long) */ 272 25, /* bitsize */ 273 TRUE, /* pc_relative */ 274 0, /* bitpos */ 275 complain_overflow_signed,/* complain_on_overflow */ 276 bfd_elf_generic_reloc, /* special_function */ 277 "R_ARM_XPC25", /* name */ 278 FALSE, /* partial_inplace */ 279 0x00ffffff, /* src_mask */ 280 0x00ffffff, /* dst_mask */ 281 TRUE), /* pcrel_offset */ 282 283 /* BLX instruction for the Thumb. */ 284 HOWTO (R_ARM_THM_XPC22, /* type */ 285 2, /* rightshift */ 286 2, /* size (0 = byte, 1 = short, 2 = long) */ 287 22, /* bitsize */ 288 TRUE, /* pc_relative */ 289 0, /* bitpos */ 290 complain_overflow_signed,/* complain_on_overflow */ 291 bfd_elf_generic_reloc, /* special_function */ 292 "R_ARM_THM_XPC22", /* name */ 293 FALSE, /* partial_inplace */ 294 0x07ff07ff, /* src_mask */ 295 0x07ff07ff, /* dst_mask */ 296 TRUE), /* pcrel_offset */ 297 298 /* These next three relocs are not defined, but we need to fill the space. */ 299 300 HOWTO (R_ARM_NONE, /* type */ 301 0, /* rightshift */ 302 0, /* size (0 = byte, 1 = short, 2 = long) */ 303 0, /* bitsize */ 304 FALSE, /* pc_relative */ 305 0, /* bitpos */ 306 complain_overflow_dont,/* complain_on_overflow */ 307 bfd_elf_generic_reloc, /* special_function */ 308 "R_ARM_unknown_17", /* name */ 309 FALSE, /* partial_inplace */ 310 0, /* src_mask */ 311 0, /* dst_mask */ 312 FALSE), /* pcrel_offset */ 313 314 HOWTO (R_ARM_NONE, /* type */ 315 0, /* rightshift */ 316 0, /* size (0 = byte, 1 = short, 2 = long) */ 317 0, /* bitsize */ 318 FALSE, /* pc_relative */ 319 0, /* bitpos */ 320 complain_overflow_dont,/* complain_on_overflow */ 321 bfd_elf_generic_reloc, /* special_function */ 322 "R_ARM_unknown_18", /* name */ 323 FALSE, /* partial_inplace */ 324 0, /* src_mask */ 325 0, /* dst_mask */ 326 FALSE), /* pcrel_offset */ 327 328 HOWTO (R_ARM_NONE, /* type */ 329 0, /* rightshift */ 330 0, /* size (0 = byte, 1 = short, 2 = long) */ 331 0, /* bitsize */ 332 FALSE, /* pc_relative */ 333 0, /* bitpos */ 334 complain_overflow_dont,/* complain_on_overflow */ 335 bfd_elf_generic_reloc, /* special_function */ 336 "R_ARM_unknown_19", /* name */ 337 FALSE, /* partial_inplace */ 338 0, /* src_mask */ 339 0, /* dst_mask */ 340 FALSE), /* pcrel_offset */ 341 342 /* Relocs used in ARM Linux */ 343 344 HOWTO (R_ARM_COPY, /* type */ 345 0, /* rightshift */ 346 2, /* size (0 = byte, 1 = short, 2 = long) */ 347 32, /* bitsize */ 348 FALSE, /* pc_relative */ 349 0, /* bitpos */ 350 complain_overflow_bitfield,/* complain_on_overflow */ 351 bfd_elf_generic_reloc, /* special_function */ 352 "R_ARM_COPY", /* name */ 353 TRUE, /* partial_inplace */ 354 0xffffffff, /* src_mask */ 355 0xffffffff, /* dst_mask */ 356 FALSE), /* pcrel_offset */ 357 358 HOWTO (R_ARM_GLOB_DAT, /* type */ 359 0, /* rightshift */ 360 2, /* size (0 = byte, 1 = short, 2 = long) */ 361 32, /* bitsize */ 362 FALSE, /* pc_relative */ 363 0, /* bitpos */ 364 complain_overflow_bitfield,/* complain_on_overflow */ 365 bfd_elf_generic_reloc, /* special_function */ 366 "R_ARM_GLOB_DAT", /* name */ 367 TRUE, /* partial_inplace */ 368 0xffffffff, /* src_mask */ 369 0xffffffff, /* dst_mask */ 370 FALSE), /* pcrel_offset */ 371 372 HOWTO (R_ARM_JUMP_SLOT, /* type */ 373 0, /* rightshift */ 374 2, /* size (0 = byte, 1 = short, 2 = long) */ 375 32, /* bitsize */ 376 FALSE, /* pc_relative */ 377 0, /* bitpos */ 378 complain_overflow_bitfield,/* complain_on_overflow */ 379 bfd_elf_generic_reloc, /* special_function */ 380 "R_ARM_JUMP_SLOT", /* name */ 381 TRUE, /* partial_inplace */ 382 0xffffffff, /* src_mask */ 383 0xffffffff, /* dst_mask */ 384 FALSE), /* pcrel_offset */ 385 386 HOWTO (R_ARM_RELATIVE, /* type */ 387 0, /* rightshift */ 388 2, /* size (0 = byte, 1 = short, 2 = long) */ 389 32, /* bitsize */ 390 FALSE, /* pc_relative */ 391 0, /* bitpos */ 392 complain_overflow_bitfield,/* complain_on_overflow */ 393 bfd_elf_generic_reloc, /* special_function */ 394 "R_ARM_RELATIVE", /* name */ 395 TRUE, /* partial_inplace */ 396 0xffffffff, /* src_mask */ 397 0xffffffff, /* dst_mask */ 398 FALSE), /* pcrel_offset */ 399 400 HOWTO (R_ARM_GOTOFF, /* type */ 401 0, /* rightshift */ 402 2, /* size (0 = byte, 1 = short, 2 = long) */ 403 32, /* bitsize */ 404 FALSE, /* pc_relative */ 405 0, /* bitpos */ 406 complain_overflow_bitfield,/* complain_on_overflow */ 407 bfd_elf_generic_reloc, /* special_function */ 408 "R_ARM_GOTOFF", /* name */ 409 TRUE, /* partial_inplace */ 410 0xffffffff, /* src_mask */ 411 0xffffffff, /* dst_mask */ 412 FALSE), /* pcrel_offset */ 413 414 HOWTO (R_ARM_GOTPC, /* type */ 415 0, /* rightshift */ 416 2, /* size (0 = byte, 1 = short, 2 = long) */ 417 32, /* bitsize */ 418 TRUE, /* pc_relative */ 419 0, /* bitpos */ 420 complain_overflow_bitfield,/* complain_on_overflow */ 421 bfd_elf_generic_reloc, /* special_function */ 422 "R_ARM_GOTPC", /* name */ 423 TRUE, /* partial_inplace */ 424 0xffffffff, /* src_mask */ 425 0xffffffff, /* dst_mask */ 426 TRUE), /* pcrel_offset */ 427 428 HOWTO (R_ARM_GOT32, /* type */ 429 0, /* rightshift */ 430 2, /* size (0 = byte, 1 = short, 2 = long) */ 431 32, /* bitsize */ 432 FALSE, /* pc_relative */ 433 0, /* bitpos */ 434 complain_overflow_bitfield,/* complain_on_overflow */ 435 bfd_elf_generic_reloc, /* special_function */ 436 "R_ARM_GOT32", /* name */ 437 TRUE, /* partial_inplace */ 438 0xffffffff, /* src_mask */ 439 0xffffffff, /* dst_mask */ 440 FALSE), /* pcrel_offset */ 441 442 HOWTO (R_ARM_PLT32, /* type */ 443 2, /* rightshift */ 444 2, /* size (0 = byte, 1 = short, 2 = long) */ 445 26, /* bitsize */ 446 TRUE, /* pc_relative */ 447 0, /* bitpos */ 448 complain_overflow_bitfield,/* complain_on_overflow */ 449 bfd_elf_generic_reloc, /* special_function */ 450 "R_ARM_PLT32", /* name */ 451 TRUE, /* partial_inplace */ 452 0x00ffffff, /* src_mask */ 453 0x00ffffff, /* dst_mask */ 454 TRUE), /* pcrel_offset */ 455 456 /* End of relocs used in ARM Linux */ 457 458 HOWTO (R_ARM_RREL32, /* type */ 459 0, /* rightshift */ 460 0, /* size (0 = byte, 1 = short, 2 = long) */ 461 0, /* bitsize */ 462 FALSE, /* pc_relative */ 463 0, /* bitpos */ 464 complain_overflow_dont,/* complain_on_overflow */ 465 bfd_elf_generic_reloc, /* special_function */ 466 "R_ARM_RREL32", /* name */ 467 FALSE, /* partial_inplace */ 468 0, /* src_mask */ 469 0, /* dst_mask */ 470 FALSE), /* pcrel_offset */ 471 472 HOWTO (R_ARM_RABS32, /* type */ 473 0, /* rightshift */ 474 0, /* size (0 = byte, 1 = short, 2 = long) */ 475 0, /* bitsize */ 476 FALSE, /* pc_relative */ 477 0, /* bitpos */ 478 complain_overflow_dont,/* complain_on_overflow */ 479 bfd_elf_generic_reloc, /* special_function */ 480 "R_ARM_RABS32", /* name */ 481 FALSE, /* partial_inplace */ 482 0, /* src_mask */ 483 0, /* dst_mask */ 484 FALSE), /* pcrel_offset */ 485 486 HOWTO (R_ARM_RPC24, /* type */ 487 0, /* rightshift */ 488 0, /* size (0 = byte, 1 = short, 2 = long) */ 489 0, /* bitsize */ 490 FALSE, /* pc_relative */ 491 0, /* bitpos */ 492 complain_overflow_dont,/* complain_on_overflow */ 493 bfd_elf_generic_reloc, /* special_function */ 494 "R_ARM_RPC24", /* name */ 495 FALSE, /* partial_inplace */ 496 0, /* src_mask */ 497 0, /* dst_mask */ 498 FALSE), /* pcrel_offset */ 499 500 HOWTO (R_ARM_RBASE, /* type */ 501 0, /* rightshift */ 502 0, /* size (0 = byte, 1 = short, 2 = long) */ 503 0, /* bitsize */ 504 FALSE, /* pc_relative */ 505 0, /* bitpos */ 506 complain_overflow_dont,/* complain_on_overflow */ 507 bfd_elf_generic_reloc, /* special_function */ 508 "R_ARM_RBASE", /* name */ 509 FALSE, /* partial_inplace */ 510 0, /* src_mask */ 511 0, /* dst_mask */ 512 FALSE), /* pcrel_offset */ 513 514 HOWTO (R_ARM_ALU_PCREL7_0, /* type */ 515 0, /* rightshift */ 516 2, /* size (0 = byte, 1 = short, 2 = long) */ 517 12, /* bitsize */ 518 TRUE, /* pc_relative */ 519 0, /* bitpos */ 520 complain_overflow_dont,/* complain_on_overflow */ 521 bfd_elf_generic_reloc, /* special_function */ 522 "R_ARM_ALU_PCREL_7_0", /* name */ 523 FALSE, /* partial_inplace */ 524 0x00000fff, /* src_mask */ 525 0x00000fff, /* dst_mask */ 526 TRUE), /* pcrel_offset */ 527 528 HOWTO (R_ARM_ALU_PCREL15_8, /* type */ 529 0, /* rightshift */ 530 2, /* size (0 = byte, 1 = short, 2 = long) */ 531 12, /* bitsize */ 532 TRUE, /* pc_relative */ 533 8, /* bitpos */ 534 complain_overflow_dont,/* complain_on_overflow */ 535 bfd_elf_generic_reloc, /* special_function */ 536 "R_ARM_ALU_PCREL_15_8",/* name */ 537 FALSE, /* partial_inplace */ 538 0x00000fff, /* src_mask */ 539 0x00000fff, /* dst_mask */ 540 TRUE), /* pcrel_offset */ 541 542 HOWTO (R_ARM_ALU_PCREL23_15, /* type */ 543 0, /* rightshift */ 544 2, /* size (0 = byte, 1 = short, 2 = long) */ 545 12, /* bitsize */ 546 TRUE, /* pc_relative */ 547 16, /* bitpos */ 548 complain_overflow_dont,/* complain_on_overflow */ 549 bfd_elf_generic_reloc, /* special_function */ 550 "R_ARM_ALU_PCREL_23_15",/* name */ 551 FALSE, /* partial_inplace */ 552 0x00000fff, /* src_mask */ 553 0x00000fff, /* dst_mask */ 554 TRUE), /* pcrel_offset */ 555 556 HOWTO (R_ARM_LDR_SBREL_11_0, /* type */ 557 0, /* rightshift */ 558 2, /* size (0 = byte, 1 = short, 2 = long) */ 559 12, /* bitsize */ 560 FALSE, /* pc_relative */ 561 0, /* bitpos */ 562 complain_overflow_dont,/* complain_on_overflow */ 563 bfd_elf_generic_reloc, /* special_function */ 564 "R_ARM_LDR_SBREL_11_0",/* name */ 565 FALSE, /* partial_inplace */ 566 0x00000fff, /* src_mask */ 567 0x00000fff, /* dst_mask */ 568 FALSE), /* pcrel_offset */ 569 570 HOWTO (R_ARM_ALU_SBREL_19_12, /* type */ 571 0, /* rightshift */ 572 2, /* size (0 = byte, 1 = short, 2 = long) */ 573 8, /* bitsize */ 574 FALSE, /* pc_relative */ 575 12, /* bitpos */ 576 complain_overflow_dont,/* complain_on_overflow */ 577 bfd_elf_generic_reloc, /* special_function */ 578 "R_ARM_ALU_SBREL_19_12",/* name */ 579 FALSE, /* partial_inplace */ 580 0x000ff000, /* src_mask */ 581 0x000ff000, /* dst_mask */ 582 FALSE), /* pcrel_offset */ 583 584 HOWTO (R_ARM_ALU_SBREL_27_20, /* type */ 585 0, /* rightshift */ 586 2, /* size (0 = byte, 1 = short, 2 = long) */ 587 8, /* bitsize */ 588 FALSE, /* pc_relative */ 589 20, /* bitpos */ 590 complain_overflow_dont,/* complain_on_overflow */ 591 bfd_elf_generic_reloc, /* special_function */ 592 "R_ARM_ALU_SBREL_27_20",/* name */ 593 FALSE, /* partial_inplace */ 594 0x0ff00000, /* src_mask */ 595 0x0ff00000, /* dst_mask */ 596 FALSE), /* pcrel_offset */ 597 598 HOWTO (R_ARM_TARGET1, /* type */ 599 0, /* rightshift */ 600 2, /* size (0 = byte, 1 = short, 2 = long) */ 601 32, /* bitsize */ 602 FALSE, /* pc_relative */ 603 0, /* bitpos */ 604 complain_overflow_dont,/* complain_on_overflow */ 605 bfd_elf_generic_reloc, /* special_function */ 606 "R_ARM_TARGET1", /* name */ 607 FALSE, /* partial_inplace */ 608 0xffffffff, /* src_mask */ 609 0xffffffff, /* dst_mask */ 610 FALSE), /* pcrel_offset */ 611 612 HOWTO (R_ARM_ROSEGREL32, /* type */ 613 0, /* rightshift */ 614 2, /* size (0 = byte, 1 = short, 2 = long) */ 615 32, /* bitsize */ 616 FALSE, /* pc_relative */ 617 0, /* bitpos */ 618 complain_overflow_dont,/* complain_on_overflow */ 619 bfd_elf_generic_reloc, /* special_function */ 620 "R_ARM_ROSEGREL32", /* name */ 621 FALSE, /* partial_inplace */ 622 0xffffffff, /* src_mask */ 623 0xffffffff, /* dst_mask */ 624 FALSE), /* pcrel_offset */ 625 626 HOWTO (R_ARM_V4BX, /* type */ 627 0, /* rightshift */ 628 2, /* size (0 = byte, 1 = short, 2 = long) */ 629 32, /* bitsize */ 630 FALSE, /* pc_relative */ 631 0, /* bitpos */ 632 complain_overflow_dont,/* complain_on_overflow */ 633 bfd_elf_generic_reloc, /* special_function */ 634 "R_ARM_V4BX", /* name */ 635 FALSE, /* partial_inplace */ 636 0xffffffff, /* src_mask */ 637 0xffffffff, /* dst_mask */ 638 FALSE), /* pcrel_offset */ 639 640 HOWTO (R_ARM_TARGET2, /* type */ 641 0, /* rightshift */ 642 2, /* size (0 = byte, 1 = short, 2 = long) */ 643 32, /* bitsize */ 644 FALSE, /* pc_relative */ 645 0, /* bitpos */ 646 complain_overflow_signed,/* complain_on_overflow */ 647 bfd_elf_generic_reloc, /* special_function */ 648 "R_ARM_TARGET2", /* name */ 649 FALSE, /* partial_inplace */ 650 0xffffffff, /* src_mask */ 651 0xffffffff, /* dst_mask */ 652 TRUE), /* pcrel_offset */ 653 654 HOWTO (R_ARM_PREL31, /* type */ 655 0, /* rightshift */ 656 2, /* size (0 = byte, 1 = short, 2 = long) */ 657 31, /* bitsize */ 658 TRUE, /* pc_relative */ 659 0, /* bitpos */ 660 complain_overflow_signed,/* complain_on_overflow */ 661 bfd_elf_generic_reloc, /* special_function */ 662 "R_ARM_PREL31", /* name */ 663 FALSE, /* partial_inplace */ 664 0x7fffffff, /* src_mask */ 665 0x7fffffff, /* dst_mask */ 666 TRUE), /* pcrel_offset */ 667}; 668 669 /* GNU extension to record C++ vtable hierarchy */ 670static reloc_howto_type elf32_arm_vtinherit_howto = 671 HOWTO (R_ARM_GNU_VTINHERIT, /* type */ 672 0, /* rightshift */ 673 2, /* size (0 = byte, 1 = short, 2 = long) */ 674 0, /* bitsize */ 675 FALSE, /* pc_relative */ 676 0, /* bitpos */ 677 complain_overflow_dont, /* complain_on_overflow */ 678 NULL, /* special_function */ 679 "R_ARM_GNU_VTINHERIT", /* name */ 680 FALSE, /* partial_inplace */ 681 0, /* src_mask */ 682 0, /* dst_mask */ 683 FALSE); /* pcrel_offset */ 684 685 /* GNU extension to record C++ vtable member usage */ 686static reloc_howto_type elf32_arm_vtentry_howto = 687 HOWTO (R_ARM_GNU_VTENTRY, /* type */ 688 0, /* rightshift */ 689 2, /* size (0 = byte, 1 = short, 2 = long) */ 690 0, /* bitsize */ 691 FALSE, /* pc_relative */ 692 0, /* bitpos */ 693 complain_overflow_dont, /* complain_on_overflow */ 694 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 695 "R_ARM_GNU_VTENTRY", /* name */ 696 FALSE, /* partial_inplace */ 697 0, /* src_mask */ 698 0, /* dst_mask */ 699 FALSE); /* pcrel_offset */ 700 701 /* 12 bit pc relative */ 702static reloc_howto_type elf32_arm_thm_pc11_howto = 703 HOWTO (R_ARM_THM_PC11, /* type */ 704 1, /* rightshift */ 705 1, /* size (0 = byte, 1 = short, 2 = long) */ 706 11, /* bitsize */ 707 TRUE, /* pc_relative */ 708 0, /* bitpos */ 709 complain_overflow_signed, /* complain_on_overflow */ 710 bfd_elf_generic_reloc, /* special_function */ 711 "R_ARM_THM_PC11", /* name */ 712 FALSE, /* partial_inplace */ 713 0x000007ff, /* src_mask */ 714 0x000007ff, /* dst_mask */ 715 TRUE); /* pcrel_offset */ 716 717 /* 12 bit pc relative */ 718static reloc_howto_type elf32_arm_thm_pc9_howto = 719 HOWTO (R_ARM_THM_PC9, /* type */ 720 1, /* rightshift */ 721 1, /* size (0 = byte, 1 = short, 2 = long) */ 722 8, /* bitsize */ 723 TRUE, /* pc_relative */ 724 0, /* bitpos */ 725 complain_overflow_signed, /* complain_on_overflow */ 726 bfd_elf_generic_reloc, /* special_function */ 727 "R_ARM_THM_PC9", /* name */ 728 FALSE, /* partial_inplace */ 729 0x000000ff, /* src_mask */ 730 0x000000ff, /* dst_mask */ 731 TRUE); /* pcrel_offset */ 732 733/* Place relative GOT-indirect. */ 734static reloc_howto_type elf32_arm_got_prel = 735 HOWTO (R_ARM_GOT_PREL, /* type */ 736 0, /* rightshift */ 737 2, /* size (0 = byte, 1 = short, 2 = long) */ 738 32, /* bitsize */ 739 TRUE, /* pc_relative */ 740 0, /* bitpos */ 741 complain_overflow_dont, /* complain_on_overflow */ 742 bfd_elf_generic_reloc, /* special_function */ 743 "R_ARM_GOT_PREL", /* name */ 744 FALSE, /* partial_inplace */ 745 0xffffffff, /* src_mask */ 746 0xffffffff, /* dst_mask */ 747 TRUE); /* pcrel_offset */ 748 749static reloc_howto_type * 750elf32_arm_howto_from_type (unsigned int r_type) 751{ 752 if (r_type < NUM_ELEM (elf32_arm_howto_table)) 753 return &elf32_arm_howto_table[r_type]; 754 755 switch (r_type) 756 { 757 case R_ARM_GOT_PREL: 758 return &elf32_arm_got_prel; 759 760 case R_ARM_GNU_VTINHERIT: 761 return &elf32_arm_vtinherit_howto; 762 763 case R_ARM_GNU_VTENTRY: 764 return &elf32_arm_vtentry_howto; 765 766 case R_ARM_THM_PC11: 767 return &elf32_arm_thm_pc11_howto; 768 769 case R_ARM_THM_PC9: 770 return &elf32_arm_thm_pc9_howto; 771 772 default: 773 return NULL; 774 } 775} 776 777static void 778elf32_arm_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, arelent * bfd_reloc, 779 Elf_Internal_Rela * elf_reloc) 780{ 781 unsigned int r_type; 782 783 r_type = ELF32_R_TYPE (elf_reloc->r_info); 784 bfd_reloc->howto = elf32_arm_howto_from_type (r_type); 785} 786 787struct elf32_arm_reloc_map 788 { 789 bfd_reloc_code_real_type bfd_reloc_val; 790 unsigned char elf_reloc_val; 791 }; 792 793/* All entries in this list must also be present in elf32_arm_howto_table. */ 794static const struct elf32_arm_reloc_map elf32_arm_reloc_map[] = 795 { 796 {BFD_RELOC_NONE, R_ARM_NONE}, 797 {BFD_RELOC_ARM_PCREL_BRANCH, R_ARM_PC24}, 798 {BFD_RELOC_ARM_PCREL_BLX, R_ARM_XPC25}, 799 {BFD_RELOC_THUMB_PCREL_BLX, R_ARM_THM_XPC22}, 800 {BFD_RELOC_32, R_ARM_ABS32}, 801 {BFD_RELOC_32_PCREL, R_ARM_REL32}, 802 {BFD_RELOC_8, R_ARM_ABS8}, 803 {BFD_RELOC_16, R_ARM_ABS16}, 804 {BFD_RELOC_ARM_OFFSET_IMM, R_ARM_ABS12}, 805 {BFD_RELOC_ARM_THUMB_OFFSET, R_ARM_THM_ABS5}, 806 {BFD_RELOC_THUMB_PCREL_BRANCH23, R_ARM_THM_PC22}, 807 {BFD_RELOC_ARM_COPY, R_ARM_COPY}, 808 {BFD_RELOC_ARM_GLOB_DAT, R_ARM_GLOB_DAT}, 809 {BFD_RELOC_ARM_JUMP_SLOT, R_ARM_JUMP_SLOT}, 810 {BFD_RELOC_ARM_RELATIVE, R_ARM_RELATIVE}, 811 {BFD_RELOC_ARM_GOTOFF, R_ARM_GOTOFF}, 812 {BFD_RELOC_ARM_GOTPC, R_ARM_GOTPC}, 813 {BFD_RELOC_ARM_GOT32, R_ARM_GOT32}, 814 {BFD_RELOC_ARM_PLT32, R_ARM_PLT32}, 815 {BFD_RELOC_ARM_TARGET1, R_ARM_TARGET1}, 816 {BFD_RELOC_ARM_ROSEGREL32, R_ARM_ROSEGREL32}, 817 {BFD_RELOC_ARM_SBREL32, R_ARM_SBREL32}, 818 {BFD_RELOC_ARM_PREL31, R_ARM_PREL31}, 819 {BFD_RELOC_ARM_TARGET2, R_ARM_TARGET2} 820 }; 821 822static reloc_howto_type * 823elf32_arm_reloc_type_lookup (abfd, code) 824 bfd *abfd ATTRIBUTE_UNUSED; 825 bfd_reloc_code_real_type code; 826{ 827 unsigned int i; 828 829 switch (code) 830 { 831 case BFD_RELOC_VTABLE_INHERIT: 832 return & elf32_arm_vtinherit_howto; 833 834 case BFD_RELOC_VTABLE_ENTRY: 835 return & elf32_arm_vtentry_howto; 836 837 case BFD_RELOC_THUMB_PCREL_BRANCH12: 838 return & elf32_arm_thm_pc11_howto; 839 840 case BFD_RELOC_THUMB_PCREL_BRANCH9: 841 return & elf32_arm_thm_pc9_howto; 842 843 default: 844 for (i = 0; i < NUM_ELEM (elf32_arm_reloc_map); i ++) 845 if (elf32_arm_reloc_map[i].bfd_reloc_val == code) 846 return & elf32_arm_howto_table[elf32_arm_reloc_map[i].elf_reloc_val]; 847 848 return NULL; 849 } 850} 851 852/* Support for core dump NOTE sections */ 853static bfd_boolean 854elf32_arm_nabi_grok_prstatus (abfd, note) 855 bfd *abfd; 856 Elf_Internal_Note *note; 857{ 858 int offset; 859 size_t size; 860 861 switch (note->descsz) 862 { 863 default: 864 return FALSE; 865 866 case 148: /* Linux/ARM 32-bit*/ 867 /* pr_cursig */ 868 elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 869 870 /* pr_pid */ 871 elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 872 873 /* pr_reg */ 874 offset = 72; 875 size = 72; 876 877 break; 878 } 879 880 /* Make a ".reg/999" section. */ 881 return _bfd_elfcore_make_pseudosection (abfd, ".reg", 882 size, note->descpos + offset); 883} 884 885static bfd_boolean 886elf32_arm_nabi_grok_psinfo (abfd, note) 887 bfd *abfd; 888 Elf_Internal_Note *note; 889{ 890 switch (note->descsz) 891 { 892 default: 893 return FALSE; 894 895 case 124: /* Linux/ARM elf_prpsinfo */ 896 elf_tdata (abfd)->core_program 897 = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); 898 elf_tdata (abfd)->core_command 899 = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); 900 } 901 902 /* Note that for some reason, a spurious space is tacked 903 onto the end of the args in some (at least one anyway) 904 implementations, so strip it off if it exists. */ 905 906 { 907 char *command = elf_tdata (abfd)->core_command; 908 int n = strlen (command); 909 910 if (0 < n && command[n - 1] == ' ') 911 command[n - 1] = '\0'; 912 } 913 914 return TRUE; 915} 916 917#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec 918#define TARGET_LITTLE_NAME "elf32-littlearm" 919#define TARGET_BIG_SYM bfd_elf32_bigarm_vec 920#define TARGET_BIG_NAME "elf32-bigarm" 921 922#define elf_backend_grok_prstatus elf32_arm_nabi_grok_prstatus 923#define elf_backend_grok_psinfo elf32_arm_nabi_grok_psinfo 924 925#include "elf32-arm.h" 926 927/* Symbian OS Targets */ 928 929#undef TARGET_LITTLE_SYM 930#define TARGET_LITTLE_SYM bfd_elf32_littlearm_symbian_vec 931#undef TARGET_LITTLE_NAME 932#define TARGET_LITTLE_NAME "elf32-littlearm-symbian" 933#undef TARGET_BIG_SYM 934#define TARGET_BIG_SYM bfd_elf32_bigarm_symbian_vec 935#undef TARGET_BIG_NAME 936#define TARGET_BIG_NAME "elf32-bigarm-symbian" 937 938/* Like elf32_arm_link_hash_table_create -- but overrides 939 appropriately for Symbian OS. */ 940static struct bfd_link_hash_table * 941elf32_arm_symbian_link_hash_table_create (bfd *abfd) 942{ 943 struct bfd_link_hash_table *ret; 944 945 ret = elf32_arm_link_hash_table_create (abfd); 946 if (ret) 947 { 948 struct elf32_arm_link_hash_table *htab 949 = (struct elf32_arm_link_hash_table *)ret; 950 /* There is no PLT header for Symbian OS. */ 951 htab->plt_header_size = 0; 952 /* The PLT entries are each three instructions. */ 953 htab->plt_entry_size = 4 * NUM_ELEM (elf32_arm_symbian_plt_entry); 954 htab->symbian_p = 1; 955 } 956 return ret; 957} 958 959/* In a BPABI executable, the dynamic linking sections do not go in 960 the loadable read-only segment. The post-linker may wish to refer 961 to these sections, but they are not part of the final program 962 image. */ 963static struct bfd_elf_special_section const 964 elf32_arm_symbian_special_sections[]= 965{ 966 { ".dynamic", 8, 0, SHT_DYNAMIC, 0 }, 967 { ".dynstr", 7, 0, SHT_STRTAB, 0 }, 968 { ".dynsym", 7, 0, SHT_DYNSYM, 0 }, 969 { ".got", 4, 0, SHT_PROGBITS, 0 }, 970 { ".hash", 5, 0, SHT_HASH, 0 }, 971 { NULL, 0, 0, 0, 0 } 972}; 973 974static bfd_boolean 975elf32_arm_symbian_modify_segment_map 976 PARAMS ((bfd *, struct bfd_link_info *)); 977 978static bfd_boolean 979elf32_arm_symbian_modify_segment_map (abfd, info) 980 bfd *abfd; 981 struct bfd_link_info *info ATTRIBUTE_UNUSED; 982{ 983 struct elf_segment_map *m; 984 asection *dynsec; 985 986 /* The first PT_LOAD segment will have the program headers and file 987 headers in it by default -- but BPABI object files should not 988 include these headers in any loadable segment. */ 989 for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next) 990 if (m->p_type == PT_LOAD) 991 { 992 m->includes_filehdr = 0; 993 m->includes_phdrs = 0; 994 } 995 996 /* BPABI shared libraries and executables should have a PT_DYNAMIC 997 segment. However, because the .dynamic section is not marked 998 with SEC_LOAD, the generic ELF code will not create such a 999 segment. */ 1000 dynsec = bfd_get_section_by_name (abfd, ".dynamic"); 1001 if (dynsec) 1002 { 1003 m = _bfd_elf_make_dynamic_segment (abfd, dynsec); 1004 m->next = elf_tdata (abfd)->segment_map; 1005 elf_tdata (abfd)->segment_map = m; 1006 } 1007 1008 return TRUE; 1009} 1010 1011#undef elf32_bed 1012#define elf32_bed elf32_arm_symbian_bed 1013 1014#undef ELF_DYNAMIC_SEC_FLAGS 1015#define ELF_DYNAMIC_SEC_FLAGS \ 1016 (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED) 1017 1018#undef bfd_elf32_bfd_link_hash_table_create 1019#define bfd_elf32_bfd_link_hash_table_create \ 1020 elf32_arm_symbian_link_hash_table_create 1021 1022#undef elf_backend_special_sections 1023#define elf_backend_special_sections elf32_arm_symbian_special_sections 1024 1025#undef elf_backend_modify_segment_map 1026#define elf_backend_modify_segment_map elf32_arm_symbian_modify_segment_map 1027 1028/* There is no .got section for BPABI objects, and hence no header. */ 1029#undef elf_backend_got_header_size 1030#define elf_backend_got_header_size 0 1031 1032/* Similarly, there is no .got.plt section. */ 1033#undef elf_backend_want_got_plt 1034#define elf_backend_want_got_plt 0 1035 1036#include "elf32-target.h" 1037 1038