gas: xtensa: make trampolines relaxation work with jumps in slots other than 0
authorMax Filippov <jcmvbkbc@gmail.com>
Wed, 22 Mar 2017 17:19:14 +0000 (10:19 -0700)
committerMax Filippov <jcmvbkbc@gmail.com>
Wed, 22 Mar 2017 17:35:18 +0000 (10:35 -0700)
add_jump_to_trampoline assumes that jump instruction is in slot 0,
when it's in other slot that results in fixup that references NULL symbol,
which results in segfault later in xtensa_make_cached_fixup.
Search for the non-NULL symbol in the tc_frag_data.slot_symbols and check
that there's exactly one such slot.

xtensa_relax_frag for RELAX_TRAMPOLINE reassigns fixup from the original
instruction with jump to generated jump in the trampoline frag, but does not
fix its fx_r_type or fx_size. That results in "undecodable fix" or
"fixup not contained within frag" error messages during relaxation.
Fix both these fields.

gas/
2017-03-22  Max Filippov  <jcmvbkbc@gmail.com>

* config/tc-xtensa.c (xtensa_relax_frag): Change fx_size of the
reassigned fixup to size of jump instruction (3) and fx_r_type
to BFD_RELOC_XTENSA_SLOT0_OP, as there's only one slot.
(add_jump_to_trampoline): Search
origfrag->tc_frag_data.slot_symbols for the slot with non-NULL
symbol and use that slot instead of slot 0.

gas/ChangeLog
gas/config/tc-xtensa.c

index e052bd820cd04ec38d779375de023881ed95295d..75f6adca0b7d1361349f932c2160fc0dba77edc9 100644 (file)
@@ -1,3 +1,12 @@
+2017-03-22  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/tc-xtensa.c (xtensa_relax_frag): Change fx_size of the
+       reassigned fixup to size of jump instruction (3) and fx_r_type
+       to BFD_RELOC_XTENSA_SLOT0_OP, as there's only one slot.
+       (add_jump_to_trampoline): Search
+       origfrag->tc_frag_data.slot_symbols for the slot with non-NULL
+       symbol and use that slot instead of slot 0.
+
 2017-03-21  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/tc-s390.c (s390_parse_cpu): Remove S390_INSTR_FLAG_VX2
index 356c3197b9e0b0e2ef1cb017bcf08972f0988e7b..c45c70d5123ed540a00ee420e2bee9de589125e5 100644 (file)
@@ -9414,7 +9414,9 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
                          /* Move the fix-up from the original j insn to this one.  */
                          fixP->fx_frag = fragP;
                          fixP->fx_where = fragP->fr_fix - 3;
+                         fixP->fx_size = 3;
                          fixP->tc_fix_data.slot = 0;
+                         fixP->fx_r_type = BFD_RELOC_XTENSA_SLOT0_OP;
 
                          xtensa_add_cached_fixup (&fixup_cache, fixP);
 
@@ -10045,11 +10047,21 @@ add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
   xtensa_format fmt;
   xtensa_isa isa = xtensa_default_isa;
   int growth = 0;
+  int i, slot = -1;
+
+  for (i = 0; i < MAX_SLOTS; ++i)
+    if (origfrag->tc_frag_data.slot_symbols[i])
+      {
+       gas_assert (slot == -1);
+       slot = i;
+      }
+
+  gas_assert (slot >= 0 && slot < MAX_SLOTS);
 
   lsym = tramp->fr_symbol;
   /* Assemble a jump to the target label in the trampoline frag.  */
-  tsym = origfrag->tc_frag_data.slot_symbols[0];
-  toffset = origfrag-> tc_frag_data.slot_offsets[0];
+  tsym = origfrag->tc_frag_data.slot_symbols[slot];
+  toffset = origfrag-> tc_frag_data.slot_offsets[slot];
   tinsn_init (&insn);
   insn.insn_type = ITYPE_INSN;
   insn.opcode = xtensa_j_opcode;
@@ -10069,8 +10081,8 @@ add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
   if (fixP)
     fixP->fx_offset += 3;
   /* Modify the original j to point here.  */
-  origfrag->tc_frag_data.slot_symbols[0] = lsym;
-  origfrag->tc_frag_data.slot_offsets[0] = tramp->fr_fix - 3;
+  origfrag->tc_frag_data.slot_symbols[slot] = lsym;
+  origfrag->tc_frag_data.slot_offsets[slot] = tramp->fr_fix - 3;
   /* If trampoline is full, remove it from the list.  */
   check_and_update_trampolines ();