diff options
author | Nick Clifton <nickc@redhat.com> | 2011-10-05 14:13:31 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2011-10-05 14:13:31 +0000 |
commit | d4cb0ea0caf03bea93ae6891017bb2301facb33f (patch) | |
tree | cf3cb39ee841888cd026e0063f36241cc514fefb /bfd/elf32-rx.c | |
parent | b1c8db38fceb8464f02f1673b52c926c56203593 (diff) | |
download | binutils-d4cb0ea0caf03bea93ae6891017bb2301facb33f.zip binutils-d4cb0ea0caf03bea93ae6891017bb2301facb33f.tar.gz binutils-d4cb0ea0caf03bea93ae6891017bb2301facb33f.tar.bz2 |
* readelf.c (get_machine_dlags): Add support for RX's PID mode.
* ld-scripts/phdrs.exp: Expect to fail for the RX.
* elf32-rx.c: Add support for PID mode.
(rx_elf_relocate_section): Add checks for unsafe PID relocations.
Include addend in R_RX_SYM relocations.
* config/rx-defs.h (rx_pid_register): New.
(rx_gp_register): New.
* config/rx-parse.y (rx_lex): Add support for %gpreg and %pidreg.
(displacement): Add PID support.
* config/tc-rx.c (rx_pid_mode): New.
(rx_num_int_regs): New.
(rx_pid_register): New.
(rx_gp_register): New.
(options): Add -mpid and -mint-register= options.
(md_longopts): Likewise.
(md_parse_option): Likewise.
(md_show_usage): Likewise.
(rx_pid_symbol): New.
(rx_pidreg_symbol): New.
(rx_gpreg_symbol): New.
(md_begin): Support PID.
(rx_validate_fix_sub): Support PID.
(tc_gen_reloc): Support PID.
* doc/c-rx.texi: Document PID support.
* rx.h (E_FLAG_RX_PID): New.
Diffstat (limited to 'bfd/elf32-rx.c')
-rw-r--r-- | bfd/elf32-rx.c | 72 |
1 files changed, 68 insertions, 4 deletions
diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index f049f6e..99cffc0 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -462,6 +462,13 @@ rx_elf_relocate_section struct elf_link_hash_entry ** sym_hashes; Elf_Internal_Rela * rel; Elf_Internal_Rela * relend; + bfd_boolean pid_mode; + bfd_boolean saw_subtract = FALSE; + + if (elf_elfheader (output_bfd)->e_flags & E_FLAG_RX_PID) + pid_mode = TRUE; + else + pid_mode = FALSE; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -488,6 +495,9 @@ rx_elf_relocate_section sec = NULL; relocation = 0; + if (rx_stack_top == 0) + saw_subtract = FALSE; + if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; @@ -553,6 +563,28 @@ rx_elf_relocate_section _bfd_error_handler (_("%B:%A: Warning: deprecated Red Hat reloc " type " detected against: %s."), \ input_bfd, input_section, name) + /* Check for unsafe relocs in PID mode. These are any relocs where + an absolute address is being computed. There are special cases + for relocs against symbols that are known to be referenced in + crt0.o before the PID base address register has been initialised. */ +#define UNSAFE_FOR_PID \ + do \ + { \ + if (pid_mode \ + && sec != NULL \ + && sec->flags & SEC_READONLY \ + && !(input_section->flags & SEC_DEBUGGING) \ + && strcmp (name, "__pid_base") != 0 \ + && strcmp (name, "__gp") != 0 \ + && strcmp (name, "__romdatastart") != 0 \ + && !saw_subtract) \ + _bfd_error_handler (_("%B(%A): unsafe PID relocation %s at 0x%08lx (against %s in %s)"), \ + input_bfd, input_section, howto->name, \ + input_section->output_section->vma + input_section->output_offset + rel->r_offset, \ + name, sec->name); \ + } \ + while (0) + /* Opcode relocs are always big endian. Data relocs are bi-endian. */ switch (r_type) { @@ -573,16 +605,19 @@ rx_elf_relocate_section WARN_REDHAT ("RX_RH_8_NEG"); relocation = - relocation; case R_RX_DIR8S_PCREL: + UNSAFE_FOR_PID; RANGE (-128, 127); OP (0) = relocation; break; case R_RX_DIR8S: + UNSAFE_FOR_PID; RANGE (-128, 255); OP (0) = relocation; break; case R_RX_DIR8U: + UNSAFE_FOR_PID; RANGE (0, 255); OP (0) = relocation; break; @@ -591,6 +626,7 @@ rx_elf_relocate_section WARN_REDHAT ("RX_RH_16_NEG"); relocation = - relocation; case R_RX_DIR16S_PCREL: + UNSAFE_FOR_PID; RANGE (-32768, 32767); #if RX_OPCODE_BIG_ENDIAN #else @@ -601,6 +637,7 @@ rx_elf_relocate_section case R_RX_RH_16_OP: WARN_REDHAT ("RX_RH_16_OP"); + UNSAFE_FOR_PID; RANGE (-32768, 32767); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -612,6 +649,7 @@ rx_elf_relocate_section break; case R_RX_DIR16S: + UNSAFE_FOR_PID; RANGE (-32768, 65535); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) { @@ -626,6 +664,7 @@ rx_elf_relocate_section break; case R_RX_DIR16U: + UNSAFE_FOR_PID; RANGE (0, 65536); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -637,6 +676,7 @@ rx_elf_relocate_section break; case R_RX_DIR16: + UNSAFE_FOR_PID; RANGE (-32768, 65536); #if RX_OPCODE_BIG_ENDIAN OP (1) = relocation; @@ -648,6 +688,7 @@ rx_elf_relocate_section break; case R_RX_DIR16_REV: + UNSAFE_FOR_PID; RANGE (-32768, 65536); #if RX_OPCODE_BIG_ENDIAN OP (0) = relocation; @@ -665,6 +706,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_NEG: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_NEG"); relocation = - relocation; case R_RX_DIR24S_PCREL: @@ -681,6 +723,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_OP: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_OP"); RANGE (-0x800000, 0x7fffff); #if RX_OPCODE_BIG_ENDIAN @@ -695,6 +738,7 @@ rx_elf_relocate_section break; case R_RX_DIR24S: + UNSAFE_FOR_PID; RANGE (-0x800000, 0x7fffff); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) { @@ -711,6 +755,7 @@ rx_elf_relocate_section break; case R_RX_RH_24_UNS: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_24_UNS"); RANGE (0, 0xffffff); #if RX_OPCODE_BIG_ENDIAN @@ -725,6 +770,7 @@ rx_elf_relocate_section break; case R_RX_RH_32_NEG: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_32_NEG"); relocation = - relocation; #if RX_OPCODE_BIG_ENDIAN @@ -741,6 +787,7 @@ rx_elf_relocate_section break; case R_RX_RH_32_OP: + UNSAFE_FOR_PID; WARN_REDHAT ("RX_RH_32_OP"); #if RX_OPCODE_BIG_ENDIAN OP (3) = relocation; @@ -920,6 +967,7 @@ rx_elf_relocate_section /* Complex reloc handling: */ case R_RX_ABS32: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); #if RX_OPCODE_BIG_ENDIAN OP (3) = relocation; @@ -935,6 +983,7 @@ rx_elf_relocate_section break; case R_RX_ABS32_REV: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); #if RX_OPCODE_BIG_ENDIAN OP (0) = relocation; @@ -951,6 +1000,7 @@ rx_elf_relocate_section case R_RX_ABS24S_PCREL: case R_RX_ABS24S: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-0x800000, 0x7fffff); if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) @@ -968,6 +1018,7 @@ rx_elf_relocate_section break; case R_RX_ABS16: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-32768, 65535); #if RX_OPCODE_BIG_ENDIAN @@ -980,6 +1031,7 @@ rx_elf_relocate_section break; case R_RX_ABS16_REV: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-32768, 65535); #if RX_OPCODE_BIG_ENDIAN @@ -1008,6 +1060,7 @@ rx_elf_relocate_section break; case R_RX_ABS16U: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (0, 65536); #if RX_OPCODE_BIG_ENDIAN @@ -1020,6 +1073,7 @@ rx_elf_relocate_section break; case R_RX_ABS16UL: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 2; RANGE (0, 65536); @@ -1033,6 +1087,7 @@ rx_elf_relocate_section break; case R_RX_ABS16UW: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 1; RANGE (0, 65536); @@ -1046,18 +1101,21 @@ rx_elf_relocate_section break; case R_RX_ABS8: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (-128, 255); OP (0) = relocation; break; case R_RX_ABS8U: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); RANGE (0, 255); OP (0) = relocation; break; case R_RX_ABS8UL: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 2; RANGE (0, 255); @@ -1065,14 +1123,16 @@ rx_elf_relocate_section break; case R_RX_ABS8UW: + UNSAFE_FOR_PID; RX_STACK_POP (relocation); relocation >>= 1; RANGE (0, 255); OP (0) = relocation; break; - case R_RX_ABS8S_PCREL: case R_RX_ABS8S: + UNSAFE_FOR_PID; + case R_RX_ABS8S_PCREL: RX_STACK_POP (relocation); RANGE (-128, 127); OP (0) = relocation; @@ -1082,7 +1142,8 @@ rx_elf_relocate_section if (r_symndx < symtab_hdr->sh_info) RX_STACK_PUSH (sec->output_section->vma + sec->output_offset - + sym->st_value); + + sym->st_value + + rel->r_addend); else { if (h != NULL @@ -1090,7 +1151,8 @@ rx_elf_relocate_section || h->root.type == bfd_link_hash_defweak)) RX_STACK_PUSH (h->root.u.def.value + sec->output_section->vma - + sec->output_offset); + + sec->output_offset + + rel->r_addend); else _bfd_error_handler (_("Warning: RX_SYM reloc with an unknown symbol")); } @@ -1121,6 +1183,7 @@ rx_elf_relocate_section { int32_t tmp1, tmp2; + saw_subtract = TRUE; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); tmp2 -= tmp1; @@ -1143,6 +1206,7 @@ rx_elf_relocate_section { int32_t tmp1, tmp2; + saw_subtract = TRUE; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); tmp1 /= tmp2; @@ -2893,7 +2957,7 @@ rx_elf_merge_private_bfd_data (bfd * ibfd, bfd * obfd) } else if (old_flags != new_flags) { - flagword known_flags = E_FLAG_RX_64BIT_DOUBLES | E_FLAG_RX_DSP; + flagword known_flags = E_FLAG_RX_64BIT_DOUBLES | E_FLAG_RX_DSP | E_FLAG_RX_PID; if ((old_flags ^ new_flags) & known_flags) { |