From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 61739 invoked by alias); 5 Apr 2017 21:20:37 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 61716 invoked by uid 89); 5 Apr 2017 21:20:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-23.4 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,FROM_LOCAL_NOVOWEL,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,HK_RANDOM_ENVFROM,HK_RANDOM_FROM,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=earliest, positioning, 8*, H*Ad:U*marc X-HELO: mail-lf0-f65.google.com Received: from mail-lf0-f65.google.com (HELO mail-lf0-f65.google.com) (209.85.215.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 05 Apr 2017 21:20:26 +0000 Received: by mail-lf0-f65.google.com with SMTP id v2so2166292lfi.2 for ; Wed, 05 Apr 2017 14:20:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=AsZwnGhb2uOqO8cZCIWRGmrNNaa5JdRxnkHYpYSWp6U=; b=dse++FESCQCtjQ2x4pxBp0IpNWijozGUg0IoRz/ypuCkAmFwhYtxYrcGj74dSBczC+ ytIbW9WMY9XGRfr6rqFWX1f1gEbkf/m1rdVEy0L760prRTbemxhUe6N87S/MrmBvfOsQ T4Vx9wLs81cHzKVPoh2UKf9mgBjn5ieH1oJWhdZwYwRRE5uDh2u2QTBP6Q0zl7m5pcsX 0lioAnXnpWtIqTvbmo/BURkifRQmQZaSzKa1/hv/SMVDmfBA/4CO5VNRj7V4TIP8w0G2 d4fTQLTcwINxCP6lc6PPzv/A7jF0vYIESTKEdoEvZrm4kwFvCFO5xmMBeh37coSVGDQ5 5Xuw== X-Gm-Message-State: AFeK/H1vIl1cmjXyIzd3JrsVZWMSn8uyR5JNvJmDgHI6PW+aVgyW2bRAsCkubGa684y1yg== X-Received: by 10.25.67.12 with SMTP id q12mr9882529lfa.169.1491427224378; Wed, 05 Apr 2017 14:20:24 -0700 (PDT) Received: from octofox.metropolis ([5.19.183.212]) by smtp.gmail.com with ESMTPSA id 26sm3913300lfs.19.2017.04.05.14.20.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Apr 2017 14:20:23 -0700 (PDT) From: Max Filippov To: binutils@sourceware.org Cc: Sterling Augustine , David Weatherford , Marc Gauthier , linux-xtensa@linux-xtensa.org, Max Filippov Subject: [PATCH] gas: xtensa: fix incorrect code generated with auto litpools Date: Wed, 05 Apr 2017 21:20:00 -0000 Message-Id: <1491427212-18970-1-git-send-email-jcmvbkbc@gmail.com> X-IsSubscribed: yes X-SW-Source: 2017-04/txt/msg00045.txt.bz2 Assembling xtensa code w/o implicit (entry instruction) or explicit (.literal_position directive) literal pool positioning hint with --auto-litpools option may generate incorrect code when first literal is emitted before the first automatic literal pool. In that case literal pool without skipping jump is created right before the literal, potentially allowing program flow to enter literal pool. This bug is triggered e.g. by the following xtensa softfloat code from libgcc built for call0 ABI: #ifdef L_negdf2 .align 4 .global __negdf2 .type __negdf2, @function __negdf2: leaf_entry sp, 16 movi a4, 0x80000000 xor xh, xh, a4 leaf_return #endif /* L_negdf2 */ It turns into the following binary: Contents of section .text: 0000 00000080 41ffff40 33300df0 ....A..@30.. Disassembly of section .text: 00000000 <__negdf2>: 0: 000000 ill 3: ff4180 excw 4: R_XTENSA_SLOT0_OP .text 6: ff .byte 0xff 7: 303340 xor a3, a3, a4 a: f00d ret.n and it manifests itself as an illegal instruction exception happening in __negdf2. gas/ 2017-03-31 Max Filippov * config/tc-xtensa.c (xtensa_maybe_create_literal_pool_frag): Initialize lps->frag_count with auto_litpool_limit. (xg_promote_candidate_litpool): New function. (xtensa_move_literals): Extract candidate litpool promotion code into separate function. Call it for all possible found candidates. (xtensa_switch_to_literal_fragment): Drop 'recursive' flag and call to xtensa_mark_literal_pool_location that it guards. Replace it with call to xtensa_maybe_create_literal_pool_frag. Initialize pool_location with created literal pool candidate. * testsuite/gas/xtensa/all.exp: Add new tests. * testsuite/gas/xtensa/auto-litpools-first1.d: New test results. * testsuite/gas/xtensa/auto-litpools-first1.s: New test. * testsuite/gas/xtensa/auto-litpools-first2.d: New test results. * testsuite/gas/xtensa/auto-litpools-first2.s: New test. * testsuite/gas/xtensa/auto-litpools.d: Fix offsets changed due to additional jump instruction. --- gas/config/tc-xtensa.c | 66 ++++++++++++++----------- gas/testsuite/gas/xtensa/all.exp | 2 + gas/testsuite/gas/xtensa/auto-litpools-first1.d | 12 +++++ gas/testsuite/gas/xtensa/auto-litpools-first1.s | 3 ++ gas/testsuite/gas/xtensa/auto-litpools-first2.d | 15 ++++++ gas/testsuite/gas/xtensa/auto-litpools-first2.s | 3 ++ gas/testsuite/gas/xtensa/auto-litpools.d | 6 +-- 7 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-first1.d create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-first1.s create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-first2.d create mode 100644 gas/testsuite/gas/xtensa/auto-litpools-first2.s diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index c45c70d..e1efaae 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -7547,6 +7547,10 @@ xtensa_maybe_create_literal_pool_frag (bfd_boolean create, lps->seg = now_seg; lps->frag_list.next = &lps->frag_list; lps->frag_list.prev = &lps->frag_list; + /* Put candidate literal pool at the beginning of every section, + so that even when section starts with literal load there's a + literal pool available. */ + lps->frag_count = auto_litpool_limit; } lps->frag_count++; @@ -11035,6 +11039,30 @@ xtensa_move_seg_list_to_beginning (seg_list *head) static void mark_literal_frags (seg_list *); static void +xg_promote_candidate_litpool (struct litpool_seg *lps, + struct litpool_frag *lp) +{ + fragS *poolbeg; + fragS *poolend; + symbolS *lsym; + char label[10 + 2 * sizeof (fragS *)]; + + poolbeg = lp->fragP; + lp->priority = 1; + poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN; + poolend = poolbeg->fr_next; + gas_assert (poolend->fr_type == rs_machine_dependent && + poolend->fr_subtype == RELAX_LITERAL_POOL_END); + /* Create a local symbol pointing to the + end of the pool. */ + sprintf (label, ".L0_LT_%p", poolbeg); + lsym = (symbolS *)local_symbol_make (label, lps->seg, + 0, poolend); + poolbeg->fr_symbol = lsym; + /* Rest is done in xtensa_relax_frag. */ +} + +static void xtensa_move_literals (void) { seg_list *segment; @@ -11121,27 +11149,17 @@ xtensa_move_literals (void) /* This is still a "candidate" but the next one will be too far away, so revert to the nearest one, convert it and add the jump around. */ - fragS *poolbeg; - fragS *poolend; - symbolS *lsym; - char label[10 + 2 * sizeof (fragS *)]; lp = lpf->prev; - poolbeg = lp->fragP; - lp->priority = 1; - poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN; - poolend = poolbeg->fr_next; - gas_assert (poolend->fr_type == rs_machine_dependent && - poolend->fr_subtype == RELAX_LITERAL_POOL_END); - /* Create a local symbol pointing to the - end of the pool. */ - sprintf (label, ".L0_LT_%p", poolbeg); - lsym = (symbolS *)local_symbol_make (label, lps->seg, - 0, poolend); - poolbeg->fr_symbol = lsym; - /* Rest is done in xtensa_relax_frag. */ + break; } } } + + /* Convert candidate and add the jump around. */ + if (lp->fragP->fr_subtype == + RELAX_LITERAL_POOL_CANDIDATE_BEGIN) + xg_promote_candidate_litpool (lps, lp); + if (! litfrag->tc_frag_data.literal_frag) { /* Take earliest use of this literal to avoid @@ -11413,7 +11431,6 @@ xtensa_switch_to_literal_fragment (emit_state *result) static void xtensa_switch_to_non_abs_literal_fragment (emit_state *result) { - static bfd_boolean recursive = FALSE; fragS *pool_location = get_literal_pool_location (now_seg); segT lit_seg; bfd_boolean is_init = @@ -11423,23 +11440,14 @@ xtensa_switch_to_non_abs_literal_fragment (emit_state *result) if (pool_location == NULL && !use_literal_section - && !recursive && !is_init && ! is_fini) { if (!auto_litpools) { as_bad (_("literal pool location required for text-section-literals; specify with .literal_position")); } - - /* When we mark a literal pool location, we want to put a frag in - the literal pool that points to it. But to do that, we want to - switch_to_literal_fragment. But literal sections don't have - literal pools, so their location is always null, so we would - recurse forever. This is kind of hacky, but it works. */ - - recursive = TRUE; - xtensa_mark_literal_pool_location (); - recursive = FALSE; + xtensa_maybe_create_literal_pool_frag (TRUE, TRUE); + pool_location = get_literal_pool_location (now_seg); } lit_seg = cache_literal_section (FALSE); diff --git a/gas/testsuite/gas/xtensa/all.exp b/gas/testsuite/gas/xtensa/all.exp index 98041b5..1ab3827 100644 --- a/gas/testsuite/gas/xtensa/all.exp +++ b/gas/testsuite/gas/xtensa/all.exp @@ -101,6 +101,8 @@ if [istarget xtensa*-*-*] then { run_dump_test "trampoline" run_dump_test "first_frag_align" run_dump_test "auto-litpools" + run_dump_test "auto-litpools-first1" + run_dump_test "auto-litpools-first2" run_dump_test "loc" run_dump_test "init-fini-literals" } diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first1.d b/gas/testsuite/gas/xtensa/auto-litpools-first1.d new file mode 100644 index 0000000..322cdc5 --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-first1.d @@ -0,0 +1,12 @@ +#as: --auto-litpools +#objdump: -ds +#name: auto-litpools-first1 (check that literal pool is created when source starts with literal) + +.*: +file format .*xtensa.* +#... +Contents of section .text: + 0000 ........ 20170331 .* +#... +00000000 : +.*0:.*j.8 .* +#... diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first1.s b/gas/testsuite/gas/xtensa/auto-litpools-first1.s new file mode 100644 index 0000000..7ac0bf8 --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-first1.s @@ -0,0 +1,3 @@ +f: + .literal .L0, 0x20170331 + l32r a2, .L0 diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first2.d b/gas/testsuite/gas/xtensa/auto-litpools-first2.d new file mode 100644 index 0000000..a6b798e --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-first2.d @@ -0,0 +1,15 @@ +#as: --auto-litpools +#objdump: -ds +#name: auto-litpools-first2 (check that literal pool with jump around is created for generated literal) + +.*: +file format .*xtensa.* +#... +Contents of section .text: + 0000 ........ ........ 20170331 .* +#... +00000000 : + 0:.*addi.*a1.* + 3:.*j.*c.* +#... + c:.*l32r.*a2, 8.* +#... diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first2.s b/gas/testsuite/gas/xtensa/auto-litpools-first2.s new file mode 100644 index 0000000..c097dac --- /dev/null +++ b/gas/testsuite/gas/xtensa/auto-litpools-first2.s @@ -0,0 +1,3 @@ +f: + addi a1, a1, -16 + movi a2, 0x20170331 diff --git a/gas/testsuite/gas/xtensa/auto-litpools.d b/gas/testsuite/gas/xtensa/auto-litpools.d index 4d1a690..fc6f5cb 100644 --- a/gas/testsuite/gas/xtensa/auto-litpools.d +++ b/gas/testsuite/gas/xtensa/auto-litpools.d @@ -4,9 +4,9 @@ .*: +file format .*xtensa.* #... -.*4:.*l32r.a2, 0 .* +.*8:.*l32r.a2, 4 .* #... -.*3e437:.*j.3e440 .* +.*3e43b:.*j.3e444 .* #... -.*40750:.*l32r.a2, 3e43c .* +.*40754:.*l32r.a2, 3e440 .* #... -- 2.1.4