From 7db2accc3fdea0aaa0c3a76a413d8e8030e022c3 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Tue, 16 Feb 2016 02:23:28 +0300 Subject: [PATCH] xtensa: fix .init/.fini literals moving Despite the documentation and the comment in xtensa_move_literals, in the presence of --text-section-literals and --auto-litpools literals are moved from the separate literal sections into .init and .fini, because the check in the xtensa_move_literals is incorrect. This moving was broken with introduction of auto litpools: some literals now may be lost. This happens because literal frags emitted from .init and .fini are not closed when new .literal_position marks new literal pool. Then frag_align(2, 0, 0) changes type of the last literal frag to rs_align. rs_align frags are skipped in the xtensa_move_literals. As a result fixups against such literals are not moved out of .init.literal/ .fini.literal sections producing the following assembler error: test.S: Warning: fixes not all moved from .init.literal test.S: Internal error! Fix check for .init.literal/.fini.literal in the xtensa_move_literals and don't let it move literals from there in the presence of --text-section-literals or --auto-litpools. 2016-02-17 Max Filippov gas/ * config/tc-xtensa.c (xtensa_move_literals): Fix check for .init.literal/.fini.literal section name. Signed-off-by: Max Filippov --- Backported from: 4111950f363221c4641dc2f33bea61cc94f34906 gas/config/tc-xtensa.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 36a06cc..5773634 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -10625,5 +10625,9 @@ xtensa_move_literals (void) fixS *fix, *next_fix, **fix_splice; sym_list *lit; + const char *init_name = INIT_SECTION_NAME; + const char *fini_name = FINI_SECTION_NAME; + int init_name_len = strlen(init_name); + int fini_name_len = strlen(fini_name); mark_literal_frags (literal_head->next); @@ -10632,9 +10636,13 @@ xtensa_move_literals (void) for (segment = literal_head->next; segment; segment = segment->next) { + const char *seg_name = segment_name (segment->seg); + /* Keep the literals for .init and .fini in separate sections. */ - if (!strcmp (segment_name (segment->seg), INIT_SECTION_NAME) - || !strcmp (segment_name (segment->seg), FINI_SECTION_NAME)) + if ((!memcmp (seg_name, init_name, init_name_len) && + !strcmp (seg_name + init_name_len, ".literal")) || + (!memcmp (seg_name, fini_name, fini_name_len) && + !strcmp (seg_name + fini_name_len, ".literal"))) continue; frchain_from = seg_info (segment->seg)->frchainP; -- 2.1.4