views:

380

answers:

4

I need to get the values in the registers with GCC.

Something similar to this:

EAX=00000002  EBX=00000001  ECX=00000005  EDX=BFFC94C0
ESI=8184C544  EDI=00000000  EBP=0063FF78  ESP=0063FE3C
CF=0  SF=0  ZF=0  OF=0

Getting the 32-bit registers is easy enough, but I'm not sure what the simplest way to get the flags is.

In the examples for this book: http://kipirvine.com/asm/

They do it by getting the whole EFLAGS register and shifting for the bit in question. I also thought of doing it using Jcc's and CMOVcc's.

Any other suggestions on how to do it? Some test cases to verify would also be useful.

A: 

I think using Jcc's would be longer and not as clear using inline assembly.

Here is what I currently have, using CMOVcc's:

void dump_regs()
{
  int eax = 0;
  int ebx = 0;
  int ecx = 0;
  int edx = 0;

  int esi = 0;
  int edi = 0;
  int ebp = 0;
  int esp = 0;

  int cf = 0;
  int sf = 0;
  int zf = 0;
  int of = 0;

  int set = 1; // -52(%ebp)

  asm( 
    "movl  %eax, -4(%ebp)\n\t"
    "movl  %ebx, -8(%ebp)\n\t"
    "movl  %ecx, -12(%ebp)\n\t"
    "movl  %edx, -16(%ebp)\n\t"
    "movl  %esi, -20(%ebp)\n\t"
    "movl  %edi, -24(%ebp)\n\t"
    "movl  %ebp, -28(%ebp)\n\t"
    "movl  %esp, -32(%ebp)\n\t"

    "movl  $0, %eax\n\t"
    "cmovb -52(%ebp),%eax\n\t" // mov if CF = 1
    "movl  %eax, -36(%ebp) \n\t" // cf

    "movl  $0, %eax\n\t"
    "cmovs -52(%ebp),%eax\n\t" // mov if SF = 1
    "movl  %eax, -40(%ebp)\n\t" // sf

    "movl  $0, %eax\n\t"
    "cmove -52(%ebp),%eax\n\t" // mov if ZF = 1
    "movl  %eax, -44(%ebp)\n\t" // zf

    "movl  $0, %eax\n\t"
    "cmovo -52(%ebp),%eax\n\t" // mov if OF = 1
    "movl  %eax, -48(%ebp)\n\t" // of

    "movl  -4(%ebp), %eax\n\t" // restore EAX
  );

  printf("EAX = %#08x\tEBX = %#08x\tECX = %#08x\tEDX = %#08x\n",eax,ebx,ecx,edx);
  printf("ESI = %#08x\tEDI = %#08x\tEBP = %#08x\tESP = %#08x\n",esi,edi,ebp,esp);
  printf("CF = %d\tSF = %d\tZF = %d\tOF = %d\n",cf,sf,zf,of);
}

One important thing I haven't worked out yet are side-effects, I want to be able to call this without disturbing the state, any tips in that direction are welcome.

Marcos Lara
A: 

Of the top of my head, and correct me if I'm wrong, but you could just allocate some memory, get the address allocated, and simply write the register contents in there with an asm bracket... Or you could just push it into the stack and read it manually somehow... I guess it would take some good asm code and its probably not the ideal way to do something like that, but it'll work.

+1  A: 

There is no need to use assembler just to get the registers.

You can just use setjmp. That will write all registers into a stucture of type jmp_buf. It even kind of Works cross platform except for the fact that jmp_buf itself is different for each architecture.

However, calling setjmp (and calling your assembler code as well) will change some of the registers, so you can't really trust them.

There is a way to get a real snapshot, but that's a bit more difficult and highly OS dependent:

  1. install an exception handler for the illegal illegal opcode extension. The handler can be either a real interrupt, a signal handler or a OS exception handler (the try/except blocks form C++ will not work).

  2. Emit an illegal opcode in your code.

The trick here is, that the illegal opcode has no register side-effects. The exception handler can copy the registers either from the stack or from a exception info structure.

The same trick may work with breakpoint interrupts forced overflows, traps or so. There is usually more than one way to raise an interrupt from a piece of code.


Regarding the EFLAGS: You can get them via a stack operation:

  PUSHFD
  POP EAX  
  , eax now contains the EFLAG data
Nils Pipenbrinck
It's not very clear how to reconstruct the registers from the jmp_buf struct. I found the source for it here:http://ccrma.stanford.edu/courses/250a/docs/avrgcc/setjmp_8h-source.htmlAny ideas in producing code that does not change the registers? Some PUSH's could help...
Marcos Lara
I considered getting the whole EFLAGS register but then all the SH* to get the correct bit would make it less clear what going on. Similar to what I was thinking of doing with Jcc's.
Marcos Lara
+1  A: 

IMHO, using gdb is better than gcc.

http://www.unknownroad.com/rtfm/gdbtut/gdbadvanced.html

HTH

plan9assembler
That was useful! It helped me verify that what I had was correct. Thanks!
Marcos Lara