mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-26 13:56:22 +08:00
RISC-V: Fixed the missing $x+arch when adding odd paddings for alignment.
Consider the case, .option arch, rv32i .option norelax .option arch, +c .byte 1 .align 2 addi a0, zero, 1 Assembler adds $d for the odd .byte, and then adds $x+arch for the alignment. Since norelax, riscv_add_odd_padding_symbol will add the $d and $x for the odd alignment, but accidently remove the $x+arch because it has the same address as $d. Therefore, we will get the unexpected result before applying this patch, .byte 1 # $d .align 2 # odd alignment, $xrv32ic replaced by $d + $x After this patch, the expected result should be, .byte 1 # $d .align 2 # odd alignment, $xrv32ic replaced by $d + $xrv32ic gas/ * config/tc-riscv.c (make_mapping_symbol): If we are adding mapping symbol for odd alignment, then we probably will remove the $x+arch by accidently when it has the same address of $d. Try to add the removed $x+arch back after the $d rather than just $x. (riscv_mapping_state): Updated since parameters of make_mapping_symbol are changed. (riscv_add_odd_padding_symbol): Likewise. (riscv_remove_mapping_symbol): Removed and moved the code into the riscv_check_mapping_symbols. (riscv_check_mapping_symbols): Updated. * testsuite/gas/riscv/mapping-dis.d: Updated and added new testcase. * testsuite/gas/riscv/mapping-symbols.d: Likewise. * testsuite/gas/riscv/mapping.s: Likewise.
This commit is contained in:
@ -476,7 +476,8 @@ static void
|
||||
make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
valueT value,
|
||||
fragS *frag,
|
||||
bool reset_seg_arch_str)
|
||||
const char *arch_str,
|
||||
bool odd_data_padding)
|
||||
{
|
||||
const char *name;
|
||||
char *buff = NULL;
|
||||
@ -486,12 +487,11 @@ make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
name = "$d";
|
||||
break;
|
||||
case MAP_INSN:
|
||||
if (reset_seg_arch_str)
|
||||
if (arch_str != NULL)
|
||||
{
|
||||
const char *isa = riscv_rps_as.subset_list->arch_str;
|
||||
size_t size = strlen (isa) + 3; /* "rv" + '\0' */
|
||||
size_t size = strlen (arch_str) + 3; /* "$x" + '\0' */
|
||||
buff = xmalloc (size);
|
||||
snprintf (buff, size, "$x%s", isa);
|
||||
snprintf (buff, size, "$x%s", arch_str);
|
||||
name = buff;
|
||||
}
|
||||
else
|
||||
@ -503,7 +503,7 @@ make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
|
||||
symbolS *symbol = symbol_new (name, now_seg, frag, value);
|
||||
symbol_get_bfdsym (symbol)->flags |= (BSF_NO_FLAGS | BSF_LOCAL);
|
||||
if (reset_seg_arch_str)
|
||||
if (arch_str != NULL)
|
||||
{
|
||||
/* Store current $x+arch into tc_segment_info. */
|
||||
seg_info (now_seg)->tc_segment_info_data.arch_map_symbol = symbol;
|
||||
@ -517,6 +517,7 @@ make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
and .text.zero.fill.last. */
|
||||
symbolS *first = frag->tc_frag_data.first_map_symbol;
|
||||
symbolS *last = frag->tc_frag_data.last_map_symbol;
|
||||
symbolS *removed = NULL;
|
||||
if (value == 0)
|
||||
{
|
||||
if (first != NULL)
|
||||
@ -524,7 +525,7 @@ make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
know (S_GET_VALUE (first) == S_GET_VALUE (symbol)
|
||||
&& first == last);
|
||||
/* Remove the old one. */
|
||||
symbol_remove (first, &symbol_rootP, &symbol_lastP);
|
||||
removed = first;
|
||||
}
|
||||
frag->tc_frag_data.first_map_symbol = symbol;
|
||||
}
|
||||
@ -534,9 +535,23 @@ make_mapping_symbol (enum riscv_seg_mstate state,
|
||||
know (S_GET_VALUE (last) <= S_GET_VALUE (symbol));
|
||||
/* Remove the old one. */
|
||||
if (S_GET_VALUE (last) == S_GET_VALUE (symbol))
|
||||
symbol_remove (last, &symbol_rootP, &symbol_lastP);
|
||||
removed = last;
|
||||
}
|
||||
frag->tc_frag_data.last_map_symbol = symbol;
|
||||
|
||||
if (removed == NULL)
|
||||
return;
|
||||
|
||||
if (odd_data_padding)
|
||||
{
|
||||
/* If the removed mapping symbol is $x+arch, then add it back to
|
||||
the next $x. */
|
||||
const char *str = strncmp (S_GET_NAME (removed), "$xrv", 4) == 0
|
||||
? S_GET_NAME (removed) + 2 : NULL;
|
||||
make_mapping_symbol (MAP_INSN, frag->fr_fix + 1, frag, str,
|
||||
false/* odd_data_padding */);
|
||||
}
|
||||
symbol_remove (removed, &symbol_rootP, &symbol_lastP);
|
||||
}
|
||||
|
||||
/* Set the mapping state for frag_now. */
|
||||
@ -580,7 +595,10 @@ riscv_mapping_state (enum riscv_seg_mstate to_state,
|
||||
|
||||
valueT value = (valueT) (frag_now_fix () - max_chars);
|
||||
seg_info (now_seg)->tc_segment_info_data.map_state = to_state;
|
||||
make_mapping_symbol (to_state, value, frag_now, reset_seg_arch_str);
|
||||
const char *arch_str = reset_seg_arch_str
|
||||
? riscv_rps_as.subset_list->arch_str : NULL;
|
||||
make_mapping_symbol (to_state, value, frag_now, arch_str,
|
||||
false/* odd_data_padding */);
|
||||
}
|
||||
|
||||
/* Add the odd bytes of paddings for riscv_handle_align. */
|
||||
@ -591,25 +609,9 @@ riscv_add_odd_padding_symbol (fragS *frag)
|
||||
/* If there was already a mapping symbol, it should be
|
||||
removed in the make_mapping_symbol.
|
||||
|
||||
Please see gas/testsuite/gas/riscv/mapping.s: .text.odd.align. */
|
||||
make_mapping_symbol (MAP_DATA, frag->fr_fix, frag, false);
|
||||
make_mapping_symbol (MAP_INSN, frag->fr_fix + 1, frag, false);
|
||||
}
|
||||
|
||||
/* If previous and current mapping symbol have same value, then remove the
|
||||
current $x only if the previous is $x+arch; Otherwise, always remove the
|
||||
previous. */
|
||||
|
||||
static void
|
||||
riscv_remove_mapping_symbol (symbolS *pre, symbolS *cur)
|
||||
{
|
||||
know (pre != NULL && cur != NULL
|
||||
&& S_GET_VALUE (pre) == S_GET_VALUE (cur));
|
||||
symbolS *removed = pre;
|
||||
if (strncmp (S_GET_NAME (pre), "$xrv", 4) == 0
|
||||
&& strcmp (S_GET_NAME (cur), "$x") == 0)
|
||||
removed = cur;
|
||||
symbol_remove (removed, &symbol_rootP, &symbol_lastP);
|
||||
Please see gas/testsuite/gas/riscv/mapping.s: .text.odd.align.*. */
|
||||
make_mapping_symbol (MAP_DATA, frag->fr_fix, frag,
|
||||
NULL/* arch_str */, true/* odd_data_padding */);
|
||||
}
|
||||
|
||||
/* Remove any excess mapping symbols generated for alignment frags in
|
||||
@ -654,7 +656,12 @@ riscv_check_mapping_symbols (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
|
||||
Please see the gas/testsuite/gas/riscv/mapping.s:
|
||||
.text.zero.fill.align.A and .text.zero.fill.align.B. */
|
||||
riscv_remove_mapping_symbol (last, next_first);
|
||||
know (S_GET_VALUE (last) == S_GET_VALUE (next_first));
|
||||
symbolS *removed = last;
|
||||
if (strncmp (S_GET_NAME (last), "$xrv", 4) == 0
|
||||
&& strcmp (S_GET_NAME (next_first), "$x") == 0)
|
||||
removed = next_first;
|
||||
symbol_remove (removed, &symbol_rootP, &symbol_lastP);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,9 @@ Disassembly of section .text.data:
|
||||
[ ]+[0-9a-f]+:[ ]+4509[ ]+li[ ]+a0,2
|
||||
[ ]+[0-9a-f]+:[ ]+05000302[ ]+.word[ ]+0x05000302
|
||||
|
||||
Disassembly of section .text.odd.align:
|
||||
Disassembly of section .text.odd.align.start.insn:
|
||||
|
||||
0+000 <.text.odd.align>:
|
||||
0+000 <.text.odd.align.start.insn>:
|
||||
[ ]+[0-9a-f]+:[ ]+4505[ ]+li[ ]+a0,1
|
||||
[ ]+[0-9a-f]+:[ ]+01[ ]+.byte[ ]+0x01
|
||||
[ ]+[0-9a-f]+:[ ]+00[ ]+.byte[ ]+0x00
|
||||
@ -36,6 +36,15 @@ Disassembly of section .text.odd.align:
|
||||
[ ]+[0-9a-f]+:[ ]+00200513[ ]+li[ ]+a0,2
|
||||
[ ]+[0-9a-f]+:[ ]+00000013[ ]+nop
|
||||
|
||||
Disassembly of section .text.odd.align.start.data:
|
||||
|
||||
0+000 <.text.odd.align.start.data>:
|
||||
[ ]+[0-9a-f]+:[ ]+01[ ]+.byte[ ]+0x01
|
||||
[ ]+[0-9a-f]+:[ ]+00[ ]+.byte[ ]+0x00
|
||||
[ ]+[0-9a-f]+:[ ]+0001[ ]+nop
|
||||
[ ]+[0-9a-f]+:[ ]+4505[ ]+li[ ]+a0,1
|
||||
[ ]+[0-9a-f]+:[ ]+0001[ ]+nop
|
||||
|
||||
Disassembly of section .text.zero.fill.first:
|
||||
|
||||
0+000 <.text.zero.fill.first>:
|
||||
|
@ -17,10 +17,12 @@ SYMBOL TABLE:
|
||||
0+00 l .text.data 0+00 \$d
|
||||
0+08 l .text.data 0+00 \$xrv32i2p1_c2p0
|
||||
0+0c l .text.data 0+00 \$d
|
||||
0+00 l d .text.odd.align 0+00 .text.odd.align
|
||||
0+00 l .text.odd.align 0+00 \$xrv32i2p1_c2p0
|
||||
0+02 l .text.odd.align 0+00 \$d
|
||||
0+08 l .text.odd.align 0+00 \$xrv32i2p1
|
||||
0+00 l d .text.odd.align.start.insn 0+00 .text.odd.align.start.insn
|
||||
0+00 l .text.odd.align.start.insn 0+00 \$xrv32i2p1_c2p0
|
||||
0+02 l .text.odd.align.start.insn 0+00 \$d
|
||||
0+08 l .text.odd.align.start.insn 0+00 \$xrv32i2p1
|
||||
0+00 l d .text.odd.align.start.data 0+00 .text.odd.align.start.data
|
||||
0+00 l .text.odd.align.start.data 0+00 \$d
|
||||
0+00 l d .text.zero.fill.first 0+00 .text.zero.fill.first
|
||||
0+00 l .text.zero.fill.first 0+00 \$xrv32i2p1_c2p0
|
||||
0+00 l d .text.zero.fill.last 0+00 .text.zero.fill.last
|
||||
@ -41,8 +43,10 @@ SYMBOL TABLE:
|
||||
0+00 l .text.relax.align 0+00 \$xrv32i2p1_c2p0
|
||||
0+08 l .text.relax.align 0+00 \$xrv32i2p1
|
||||
0+0a l .text.section.padding 0+00 \$x
|
||||
0+03 l .text.odd.align 0+00 \$d
|
||||
0+04 l .text.odd.align 0+00 \$x
|
||||
0+03 l .text.odd.align.start.insn 0+00 \$d
|
||||
0+04 l .text.odd.align.start.insn 0+00 \$x
|
||||
0+01 l .text.odd.align.start.data 0+00 \$d
|
||||
0+02 l .text.odd.align.start.data 0+00 \$xrv32i2p1_c2p0
|
||||
0+00 l d .riscv.attributes 0+00 .riscv.attributes
|
||||
0+00 g .text.cross.section.A 0+00 funcA
|
||||
0+00 g .text.corss.section.B 0+00 funcB
|
||||
|
@ -32,7 +32,7 @@ addi a0, zero, 2 # $x, but same as previous addi, so removed
|
||||
.byte 5
|
||||
.option pop
|
||||
|
||||
.section .text.odd.align, "ax"
|
||||
.section .text.odd.align.start.insn, "ax"
|
||||
.option push
|
||||
.option norelax
|
||||
.option arch, +c
|
||||
@ -43,6 +43,15 @@ addi a0, zero, 1 # $xrv32ic
|
||||
addi a0, zero, 2 # $xrv32i
|
||||
.option pop
|
||||
|
||||
.section .text.odd.align.start.data, "ax"
|
||||
.option push
|
||||
.option norelax
|
||||
.option arch, +c
|
||||
.byte 1 # $d
|
||||
.align 2 # odd alignment, $xrv32ic replaced by $d + $xrv32ic
|
||||
addi a0, zero, 1
|
||||
.option pop
|
||||
|
||||
.section .text.zero.fill.first, "ax"
|
||||
.option push
|
||||
.option norelax
|
||||
|
Reference in New Issue
Block a user