* write.c (write_object_file) [!WORKING_DOT_WORD]: When patching
authorHans-Peter Nilsson <hp@axis.com>
Tue, 10 Mar 2009 14:38:03 +0000 (14:38 +0000)
committerHans-Peter Nilsson <hp@axis.com>
Tue, 10 Mar 2009 14:38:03 +0000 (14:38 +0000)
the jump table for multiple overflowing entries with the same
target, handle base symbols being different.
(relax_segment) <case rs_broken_word, second loop>: Whenever a
single entry overflows, arrange to redirect all entries with the
same target.

gas/ChangeLog
gas/write.c

index d16cfddb02b04b6102fc64ca2eb97cd09e1a9187..d0df00cc5002b948af4e22f157894492225fefb3 100644 (file)
@@ -1,3 +1,12 @@
+2009-03-10  Hans-Peter Nilsson  <hp@axis.com>
+
+       * write.c (write_object_file) [!WORKING_DOT_WORD]: When patching
+       the jump table for multiple overflowing entries with the same
+       target, handle base symbols being different.
+       (relax_segment) <case rs_broken_word, second loop>: Whenever a
+       single entry overflows, arrange to redirect all entries with the
+       same target.
+
 2009-03-10  Alan Modra  <amodra@bigpond.net.au>
 
        * config/tc-ppc.c (parse_cpu): Delete.
index 1af81a7df9ba97232835fcce6567a4c966876ea9..9d681f2687473a8d3c6230314518fa1446929605 100644 (file)
@@ -1671,18 +1671,22 @@ write_object_file (void)
            if (lie->added == 2)
              continue;
            /* Patch the jump table.  */
-           /* This is the offset from ??? to table_ptr+0.  */
-           to_addr = table_addr - S_GET_VALUE (lie->sub);
-#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD
-           TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_addr, lie);
-#endif
-           md_number_to_chars (lie->word_goes_here, to_addr, 2);
-           for (untruth = lie->next_broken_word;
+           for (untruth = (struct broken_word *) (fragP->fr_symbol);
                 untruth && untruth->dispfrag == fragP;
                 untruth = untruth->next_broken_word)
              {
                if (untruth->use_jump == lie)
-                 md_number_to_chars (untruth->word_goes_here, to_addr, 2);
+                 {
+                   /* This is the offset from ??? to table_ptr+0.
+                      The target is the same for all users of this
+                      md_long_jump, but the "sub" bases (and hence the
+                      offsets) may be different.  */
+                   addressT to_word = table_addr - S_GET_VALUE (untruth->sub);
+#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD
+                   TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_word, untruth);
+#endif
+                   md_number_to_chars (untruth->word_goes_here, to_word, 2);
+                 }
              }
 
            /* Install the long jump.  */
@@ -2226,13 +2230,17 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                                             S_GET_NAME (lie->sub),
                                             buf);
                            }
-                         lie->added = 1;
                          if (fragP->fr_subtype == 0)
                            {
                              fragP->fr_subtype++;
                              growth += md_short_jump_size;
                            }
-                         for (untruth = lie->next_broken_word;
+
+                         /* Redirect *all* words of this table with the same
+                            target, lest we have to handle the case where the
+                            same target but with a offset that fits on this
+                            round overflows at the next relaxation round.  */
+                         for (untruth = (struct broken_word *) (fragP->fr_symbol);
                               untruth && untruth->dispfrag == lie->dispfrag;
                               untruth = untruth->next_broken_word)
                            if ((symbol_get_frag (untruth->add)
@@ -2243,6 +2251,8 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                                untruth->added = 2;
                                untruth->use_jump = lie;
                              }
+
+                         lie->added = 1;
                          growth += md_long_jump_size;
                        }
                    }