Message ID | 4F715FEF.4070809@codesourcery.com |
---|---|
State | New |
Headers | show |
Chung-Lin Tang <cltang@codesourcery.com> wrote: > This patch fixes a case in sh.c:find_barrier(), triggered by a testcase > in glibc. The scanning starts from a GOT move instruction, records > itself in 'last_got', but does not find a second GOT move (to reset > last_got to NULL). > > It finishes by trying to insert a new barrier in the insn stream, sees > last_got != NULL, and tries to insert at PREV_INSN(last_got), which goes > above the original start insn. > > The caller, sh_reorg(), then gets the barrier scan target above the orig > insn, tries (in vain) to find it using a forward scan, and segfaults > when it goes past the insn stream... > > The attached patch adds an additional equality check, plus some comment > updates. Cross-tested without regressions, is this okay for trunk? OK. Thanks for catching this! Regards, kaz
Index: config/sh/sh.c =================================================================== --- config/sh/sh.c (revision 185837) +++ config/sh/sh.c (working copy) @@ -4751,8 +4751,12 @@ find_barrier (int num_mova, rtx mova, rtx from) /* Don't emit a constant table int the middle of global pointer setting, since that that would move the addressing base GOT into another table. We need the first mov instruction before the _GLOBAL_OFFSET_TABLE_ - in the pool anyway, so just move up the whole constant pool. */ - if (last_got) + in the pool anyway, so just move up the whole constant pool. + + However, avoid doing so when the last single GOT mov is the starting + insn itself. Going past above the start insn would create a negative + offset, causing errors. */ + if (last_got && last_got != orig) from = PREV_INSN (last_got); /* Don't insert the constant pool table at the position which