Created attachment 8304 [details] simple gdb session # Bug When a 0x66 prefix is present before a call instruction, in 64-bit mode gcc incorrectly disassembles the call's immediate to a 16-bit value, instead of a 32-bit. For example, for the instruction sequence: 66 e8 01 00 00 00 gdb only consumes the first 4 bytes, instead of all 6. On the cpu's I've tested, the 0x66 prefix is ignored by the cpu, and all 4 bytes for the immediate are consumed. This seems to align with Intel's spec for call, as it uses the f64 superscript (though it does seem to slightly contradict its use of the Jz operand/immediate encoding). The relevant documentation is as follows: > The operand size is forced to a 64-bit operand size when in 64-bit mode >(prefixes that change operand size are ignored for this instruction in 64-bit mode) > A-6 Vol. 2C **NOTE** if a rex prefix is present gdb correctly ignores the 0x66 prefix # Steps to Reproduce 1. Create a simple c program 2. compile for 64-bit mode (the default in gcc) 3. Somewhere after main, insert the instruction sequence 66 e8 01 00 00 00, ideally using hexl-find-file <name of binary> 4. gdb <name of binary> 5. break main 6. run 7. disass /r 8. Note the incorrect call disassembly I've attached a gdb session from emacs, illustrating 4-8. # Environment uname -a Linux derp 3.19.3-3-ARCH #1 SMP PREEMPT Wed Apr 8 14:10:00 CEST 2015 x86_64 GNU/Linux gcc -v gcc version 4.9.2 20150304 (prerelease) (GCC) gdb config This GDB was configured as follows: configure --host=x86_64-unknown-linux-gnu --target=x86_64-unknown-linux-gnu --with-auto-load-dir=$debugdir:$datadir/auto-load --with-auto-load-safe-path=$debugdir:$datadir/auto-load --with-expat --with-gdb-datadir=/usr/share/gdb (relocatable) --with-jit-reader-dir=/usr/lib/gdb (relocatable) --without-libunwind-ia64 --with-lzma --with-python=/usr (relocatable) --with-guile --with-separate-debug-dir=/usr/lib/debug (relocatable) --with-system-gdbinit=/etc/gdb/gdbinit --with-zlib --without-babeltrace
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a72d2af2c76f82cc8a198919f73585e11d0a4c60 commit a72d2af2c76f82cc8a198919f73585e11d0a4c60 Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri May 8 17:13:30 2015 -0700 Ignore 0x66 prefix for call/jmp/jcc in 64-bit mode The operand size prefix (0x66) is ignored for 32-bit PC-relative call, jmp and jcc in 64-bit mode. gas/testsuite/ PR binutis/18386 * gas/i386/i386.exp: Run x86-64-jump. * gas/i386/x86-64-branch.d: Updated. * gas/i386/ilp32/x86-64-branch.d: Likewise. * gas/i386/x86-64-branch.s: Add tests for the operand size prefix with call, jmp and jb. * gas/i386/x86-64-jump.d: New file. * gas/i386/x86-64-jump.s: Likewise. ld/testsuite/ PR binutis/18386 * ld-x86-64/tlsgdesc.dd: Updated. * ld-x86-64/tlspic.dd: Likewise. opcodes/ PR binutis/18386 * i386-dis.c (X86_64_E8): New. (X86_64_E9): Likewise. Update comments on 'T', 'U', 'V'. Add comments for '^'. (dis386): Replace callT/jmpT with X86_64_E8/X86_64_E9. (x86_64_table): Add X86_64_E8 and X86_64_E9. (mod_table): Replace {T|} with ^ on Jcall/Jmp. (putop): Handle '^'. (OP_J): Ignore the operand size prefix in 64-bit. Don't check REX_W.
Fixed for 2.26.
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=31955f993de7b502b7a89bba4f9c9b0a34f90b2c commit 31955f993de7b502b7a89bba4f9c9b0a34f90b2c Author: H.J. Lu <hjl.tools@gmail.com> Date: Wed May 13 04:33:45 2015 -0700 Add missing ChangeLog entries for PR binutis/18386
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5db04b0965e3e7a9344a93de22caae3c111de2cc commit 5db04b0965e3e7a9344a93de22caae3c111de2cc Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri May 15 09:47:39 2015 -0700 Support AMD64/Intel ISAs in assembler/disassembler AMD64 spec and Intel64 spec differ in direct unconditional branches in 64-bit mode. AMD64 supports direct unconditional branches with 16-bit offset via the data size prefix, which truncates RIP to 16 bits, while the data size prefix is ignored by Intel64. This patch adds -mamd64/-mintel64 option to x86-64 assembler and -Mamd64/-Mintel64 option to x86-64 disassembler. The most permissive ISA, which is AMD64, is the default. GDB can add an option, similar to (gdb) help set disassembly-flavor Set the disassembly flavor. The valid values are "att" and "intel", and the default value is "att". to select which ISA to disassemble. binutils/ PR binutis/18386 * doc/binutils.texi: Document -Mamd64 and -Mintel64. gas/ PR binutis/18386 * config/tc-i386.c (OPTION_MAMD64): New. (OPTION_MINTEL64): Likewise. (md_longopts): Add -mamd64 and -mintel64. (md_parse_option): Handle OPTION_MAMD64 and OPTION_MINTEL64. (md_show_usage): Add -mamd64 and -mintel64. * doc/c-i386.texi: Document -mamd64 and -mintel64. gas/testsuite/ PR binutis/18386 * gas/i386/i386.exp: Run x86-64-branch-2 and x86-64-branch-3. * gas/i386/x86-64-branch.d: Also pass -Mintel64 to objdump. * gas/i386/ilp32/x86-64-branch.d: Likewise. * gas/i386/x86-64-branch-2.d: New file. * gas/i386/x86-64-branch-2.s: Likewise. * gas/i386/x86-64-branch-3.l: Likewise. * gas/i386/x86-64-branch-3.s: Likewise. ld/testsuite/ PR binutis/18386 * ld-x86-64/tlsgdesc.dd: Also pass -Mintel64 to objdump. * ld-x86-64/tlspic.dd: Likewise. * ld-x86-64/x86-64.exp (x86_64tests): Also pass -Mintel64 to objdump for tlspic.dd and tlsgdesc.dd. opcodes/ PR binutis/18386 * i386-dis.c: Add comments for '@'. (x86_64_table): Use '@' on call/jmp for X86_64_E8/X86_64_E9. (enum x86_64_isa): New. (isa64): Likewise. (print_i386_disassembler_options): Add amd64 and intel64. (print_insn): Handle amd64 and intel64. (putop): Handle '@'. (OP_J): Don't ignore the operand size prefix for AMD64 in 64-bit. * i386-gen.c (cpu_flags): Add CpuAMD64 and CpuIntel64. * i386-opc.h (AMD64): New. (CpuIntel64): Likewise. (i386_cpu_flags): Add cpuamd64 and cpuintel64. * i386-opc.tbl: Add direct call/jmp with Disp16|Disp32 for AMD64. Mark direct call/jmp without Disp16|Disp32 as Intel64. * i386-init.h: Regenerated. * i386-tbl.h: Likewise.
0x66 prefix should also be ignored in 64-bit mode: [hjl@gnu-6 18386b]$ cat call.S .text .p2align 4,,15 .globl bar .type bar, @function bar: data16 jmp *foo_p(%rip) .size bar, .-bar [hjl@gnu-6 18386b]$ cat main.c #include <stdio.h> const char* (*foo_p) (void); const char* bar (void); const char* foo (void) { return "PASS"; } int main (int argc, char **argv) { foo_p = foo; printf("%s\n", bar ()); printf("%p\n", foo); return 0; } [hjl@gnu-6 18386b]$ make gcc -pie -B./ -fPIE -c -o main.o main.c gcc -pie -B./ -c -o call.o call.S gcc -pie -B./ -o x main.o call.o ./x PASS 0x56102545b6c0 [hjl@gnu-6 18386b]$ objdump -dwr call.o call.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <bar>: 0: 66 ff 25 00 00 00 00 jmpw *0x0(%rip) # 7 <bar+0x7> 3: R_X86_64_PC32 foo_p-0x4 [hjl@gnu-6 18386b]$
The master branch has been updated by H.J. Lu <hjl@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=07f5af7d3c635234284e7a0f7dd7a410b1628b8b commit 07f5af7d3c635234284e7a0f7dd7a410b1628b8b Author: H.J. Lu <hjl.tools@gmail.com> Date: Fri Jun 3 15:55:29 2016 -0700 Handle indirect branches for AMD64 and Intel64 AMD64 spec and Intel64 spec differ in indirect branches in 64-bit mode. AMD64 supports indirect branches with 16-bit address via the data size prefix while the data size prefix is ignored by Intel64. gas/ PR binutis/18386 * testsuite/gas/i386/i386.exp: Run x86-64-branch-4. * testsuite/gas/i386/x86-64-branch.d: Updated. * testsuite/gas/i386/ilp32/x86-64-branch.d: Likewise. * testsuite/gas/i386/x86-64-branch-4.l: New file. * testsuite/gas/i386/x86-64-branch-4.s: Likewise. opcodes/ PR binutis/18386 * i386-dis.c (indirEv): Replace stack_v_mode with indir_v_mode. (indir_v_mode): New. Add comments for '&'. (reg_table): Replace "{T|}" with "{&|}" on call and jmp. (putop): Handle '&'. (intel_operand_size): Handle indir_v_mode. (OP_E_register): Likewise. * i386-opc.tbl: Mark 64-bit indirect call/jmp as AMD64. Add 64-bit indirect call/jmp for AMD64. * i386-tbl.h: Regenerated
Fixed for 2.27.
*** Bug 20782 has been marked as a duplicate of this bug. ***
*** Bug 20783 has been marked as a duplicate of this bug. ***
*** Bug 20781 has been marked as a duplicate of this bug. ***
*** Bug 20780 has been marked as a duplicate of this bug. ***