https://sourceware.org/bugzilla/show_bug.cgi?id=32432
Bug ID: 32432 Summary: GAS emitting wrong operand size for some push instructions in .code16gcc mode Product: binutils Version: 2.43.1 Status: UNCONFIRMED Severity: minor Priority: P2 Component: gas Assignee: unassigned at sourceware dot org Reporter: nikolas.kraetzschmar at gmail dot com Target Milestone: --- Assembling in .code16gcc mode using intel assembly syntax fails when the assembly contains push instructions of the form: push OFFSET FLAT:0x1234 call func This produces the following binary output: Disassembly of section .text: 00000000 <func-0xa>: 0: 66 68 34 12 66 e8 pushd 0xe8661234 6: 00 00 add BYTE PTR [bx+si],al ... 0000000a <func>: a: 66 c3 retd It seems to add the 66 prefix as expected but only outputs a 2-byte operand, whereas a 4-byte operand is required. Consequently, part of the next instruction, '66 e8 00 00 00 00 calld c <func>', gets misinterpreted as part of the operand. This corrupts subsequent instructions, potentially making the entire code invalid. Why This Matters ---------------- The initial reaction might be to question why someone would use 'push OFFSET FLAT:*' in 16-bit code or why not explicitly write 'pushd OFFSET FLAT:*', which does produce the correct binary output. However, the issue arises because 'push OFFSET FLAT:*' is the form that GCC generates when passing string literals as function arguments while building with '-m16 -masm=intel'. Example Code: void function(const char *str); void init() { function("abc"); } Output Assembly: .file "test.c" .code16gcc .intel_syntax noprefix .text .section .rodata .LC0: .string "abc" .text .globl init .type init, @function init: .LFB0: .cfi_startproc push ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 mov ebp, esp .cfi_def_cfa_register 5 sub esp, 8 sub esp, 12 push OFFSET FLAT:.LC0 call function add esp, 16 nop leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc The 'push OFFSET FLAT:.LC0' instruction triggers the bug, making it impossible to pass string literals to functions when building with '-m16 -masm=intel'. Potential Fix ------------- The following patch appears to resolve the problem. However, I lack sufficient understanding of the binutils/gas internals to determine whether this is the correct place to address the issue or if it might introduce other unintended side effects. commit 39c2dc99cd0a2dae50f49f2698b718d2a49bfb9d Author: nkraetzschmar <9020053+nkraetzsch...@users.noreply.github.com> Date: Fri Dec 6 01:22:24 2024 +0100 fix gas emitting wrong push operand size for intel syntax in .code16gcc mode diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index aeb9b974451..eab43b4438b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -8299,6 +8299,8 @@ optimize_imm (void) break; case WORD_MNEM_SUFFIX: mask.bitfield.imm16 = 1; + if (current_templates.start->mnem_off == MN_push && stackop_size == LONG_MNEM_SUFFIX) + mask.bitfield.imm32 = 1; break; case BYTE_MNEM_SUFFIX: mask.bitfield.imm8 = 1; -- You are receiving this mail because: You are on the CC list for the bug.