From b7bfdfcc729e11b745f1884926b616a4dd95f60c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 5 Oct 2011 14:13:24 +0000 Subject: * 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. --- bfd/elf32-rx.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 4 deletions(-) (limited to 'bfd/elf32-rx.c') diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index f049f6e339..99cffc0e00 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) { -- cgit v1.2.1