[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug gas/29494] New: Trailing jump table leads to "Error: unaligned opco
From: |
gus at projectgus dot com |
Subject: |
[Bug gas/29494] New: Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb |
Date: |
Mon, 15 Aug 2022 11:31:52 +0000 |
https://sourceware.org/bugzilla/show_bug.cgi?id=29494
Bug ID: 29494
Summary: Trailing jump table leads to "Error: unaligned opcodes
detected in executable segment" on ARM thumb
Product: binutils
Version: 2.39
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: gas
Assignee: unassigned at sourceware dot org
Reporter: gus at projectgus dot com
Target Milestone: ---
Created attachment 14281
--> https://sourceware.org/bugzilla/attachment.cgi?id=14281&action=edit
ltrans assembler listing that exhibits the problem
When LTO is enabled then it's possible for gcc to generate a jump table where
the table data is the last thing in its executable section. (i.e. all of the
jump table entries point to offsets earlier in the section, and no other
instructions appear after it.)
On ARM thumb (min 2 byte instructions), if a jump table with single byte
entries has an odd number of entries then the section ends at an odd numbered
offset.
If also generating DWARF debug info, it appears the check in gas/dwarf2db.c
scale_addr_delta() will then fail with "unaligned opcodes detected in
executable segment".
However, the assembly listing is otherwise correct.
I ran across this in the MicroPython project, with a code snippet in
objint_mpz.c:315 as follows:
...
switch (op) {
case MP_BINARY_OP_LESS:
return mp_obj_new_bool(cmp < 0);
case MP_BINARY_OP_MORE:
return mp_obj_new_bool(cmp > 0);
case MP_BINARY_OP_LESS_EQUAL:
return mp_obj_new_bool(cmp <= 0);
case MP_BINARY_OP_MORE_EQUAL:
return mp_obj_new_bool(cmp >= 0);
case MP_BINARY_OP_EQUAL:
return mp_obj_new_bool(cmp == 0);
default:
return MP_OBJ_NULL; // op not supported
}
}
With -Os and no LTO, gcc 12.1 generates a jump table, and emits more assembly
after it:
...
.loc 1 315 9 view .LVU1204
bl __gnu_thumb1_case_uqi
.L105:
.byte (.L109-.L105)/2
.byte (.L108-.L105)/2
.byte (.L107-.L105)/2
.byte (.L106-.L105)/2
.byte (.L104-.L105)/2
.p2align 1
.L109:
.loc 1 317 17 is_stmt 1 view .LVU1205
.LVL211:
.LBB240:
.LBI237:
.loc 3 781 24 view .LVU1206
.LBB239:
.loc 3 782 5 view .LVU1207
.loc 3 782 30 is_stmt 0 view .LVU1208
cmp r3, #0
blt .LCB2415
b .L70 @long jump
...
With LTO enabled, the local translations further optimise and rearrange until
the jump table appears at the end of the executable listing for the enclosing
function and section:
...
.LBB303:
.loc 2 315 9 is_stmt 1 view .LVU1105
ldr r2, [sp, #16]
cmp r2, #4
bhi .L13
movs r0, r2
bl __gnu_thumb1_case_sqi
.L111:
.byte (.L109-.L111)/2
.byte (.L108-.L111)/2
.byte (.L118-.L111)/2
.byte (.L106-.L111)/2
.byte (.L104-.L111)/2
.LBE303:
.cfi_endproc
.LFE0:
.size mp_obj_int_binary_op, .-mp_obj_int_binary_op
.text
.Letext0:
.file 10 "<built-in>"
.section .debug_info,"",%progbits
...
As a result, the executable section ends with an odd length, and linking fails
due to the assembler DWARF generation error:
build-NUCLEO_F091RC/firmware.elf.ltrans1932.ltrans.s: Assembler messages:
build-NUCLEO_F091RC/firmware.elf.ltrans1932.ltrans.s: Error: unaligned opcodes
detected in executable segment
make[1]: *** [/tmp/ccfzQYxO.mk:3866:
build-NUCLEO_F091RC/firmware.elf.ltrans1932.ltrans.o] Error 1
Manually running "arm-none-eabi-as firmware.elf.ltrans1932.ltrans.s" produces
the same error, and inserting a padding ".byte 0" in the listing after the jump
table will fix the error.
It might be the case that this is gcc's fault for generating an executable
section with an odd length, but given the table is the last thing in the
section it seems reasonable not to pad it.
Indeed, if "-g" isn't passed to the compiler then the assembler produces valid
binary code and everything works, it's only DWARF generation which fails.
I am wondering if a suitable patch would be to ignore this check if there are
no additional opcodes following the odd offset, i.e. ignore the failure
condition if it's positioned at the end of a section. If so, I'm happy to try
and write that patch. However, I'm not very familiar with gas or DWARF so I'm
guessing it might be much more complex than this!
Looks like I can only attach one file, so rather than an archive I've attached
the ltrans assembler listing which exhibits the issue. If it's helpful then I
can provide more example files, or write a simpler assembler listing to
reproduce.
Thanks in advance for any insights!
--
You are receiving this mail because:
You are on the CC list for the bug.
- [Bug gas/29494] New: Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb,
gus at projectgus dot com <=
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, nickc at redhat dot com, 2022/08/17
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, nickc at redhat dot com, 2022/08/22
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, amodra at gmail dot com, 2022/08/23
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, nickc at redhat dot com, 2022/08/23
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, gus at projectgus dot com, 2022/08/23
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, gus at projectgus dot com, 2022/08/27
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, cvs-commit at gcc dot gnu.org, 2022/08/28
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, amodra at gmail dot com, 2022/08/28
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, cvs-commit at gcc dot gnu.org, 2022/08/30
- [Bug gas/29494] Trailing jump table leads to "Error: unaligned opcodes detected in executable segment" on ARM thumb, nickc at redhat dot com, 2022/08/30