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.