[PATCH] Partial fix for PR backtrace/1718
Michael Chastain
mec.gnu@mindspring.com
Sat Jul 31 15:09:00 GMT 2004
"Eli Zaretskii" <eliz@gnu.org> wrote:
> I debugged this. The reason it doesn't work (and AFAICT shouldn't
> work for anyone else on any i386 platform) is that, at least with GCC,
> the opcode produced by "mov 0x375aa0,%eax" and its ilk is _not_ 0xb8
> to 0xba, but rather 0xa1 for a mov to EAX and 0x8b for other
> registers. Obviously, GAS somehow produces a different opcode when
> invoked for asm blocks in C code, as you did in i386-prologue.c in the
> test suite, and for code produced from plain C.
Ah, I think the real difference is that Mark's code is for
"eax = 0x12345678", but Eli's code was "eax = * (int *) 0x12345678".
Naturally those are different instructions; there's no mystical
context-dependent assembly going on, thank goodness.
I'm gonna beat this into the ground ... apologies to those who already
know all this stuff.
I'm looking at an opcode table:
http://developer.intel.com/design/pentium/manuals/24319101.pdf
page 3-286 (page 316 in the pdf)
Opcodes 0xb8 to 0xba are for "move immediate", which moves a constant
immediate value into a register. Opcodes 0xa1 and 0x8b are for "move
register/memory".
These are different instructions. In C terms,
eax = 0x375aa0; /* move immediate, opcode 0xb8 + rd */
ebx = 0x375aa0; /* move immediate, opcode 0xb8 + rd */
eax = * (int *) 0x375aa0; /* move r/m, opcode 0xa1 */
ebx = * (int *) 0x375aa0; /* move r/m, opcode 0x8b + /r */
Eli posted the code for recursive_edit_1:
0x0005f7b0 <recursive_edit_1+0>: push %ebp
0x0005f7b1 <recursive_edit_1+1>: mov 0x375aa0,%eax
0x0005f7b6 <recursive_edit_1+6>: mov %esp,%ebp
0x0005f7b8 <recursive_edit_1+8>: push %esi
That instruction is a memory move, "eax = * (int *) 0x375aa0". Indeed,
recursive_edit_1 reads two global variables near the top of the
function:
Lisp_Object
recursive_edit_1 ()
{
int count = specpdl_ptr - specpdl;
...
}
Mark's test code is:
asm(".text\n"
" .align 8\n"
SYMBOL (gdb1718) ":\n"
" pushl %ebp\n"
" movl $0x11111111, %eax\n"
That instruction is an immediate constant move.
The '$' in the assembly code means constant. Lack of '$" means
memory address. The two forms are confusingly similar:
mov $0x1234, ax # constant value, ax = 0x1234
mov 0x1234, ax # memory location, ax = * (int *) 1234
So Mark's patch is okay but that's why it doesn't touch Eli's bug. A
lot of code in the wild will have Eli's instructions. I haven't
read or tested Eli's patch, though.
It would be nice to add more instructions to gdb1718 in
gdb.arch/i386-prologue.exp to cover this:
movl memory, %eax
movl memory, %ecx
movl %eax, %ecx
movl %ecx, %eax
The memory location has to be a real location, of course.
Michael C
More information about the Gdb-patches
mailing list