This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Partial fix for PR backtrace/1718


"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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]