Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong debugging execution after a "ldrls" instruction (ARM) #3893

Closed
daniel-rome opened this issue Dec 30, 2015 · 12 comments
Closed

Wrong debugging execution after a "ldrls" instruction (ARM) #3893

daniel-rome opened this issue Dec 30, 2015 · 12 comments

Comments

@daniel-rome
Copy link
Contributor

r2 is not debugging the execution properly after a "ldrls" instruction.

// Debugging we found a switch case (ldrls) instruction
[0x0000cdc0]> pd 5 @ pc
            ;-- pc:
            ;-- r15:
            0x0000cdc0      03f19f97       ldrls pc, [pc, r3, lsl 2]   ; [0xcdc8:4]=0xce00 
        ,=< 0x0000cdc4      190000ea       b 0xce30
        |   0x0000cdc8      00ce0000       andeq ip, r0, r0, lsl 28
        |   0x0000cdcc      e0cd0000       andeq ip, r0, r0, ror 27
        |   0x0000cdd0      30ce0000       andeq ip, r0, r0, lsr lr

// CPU registers
[0x0000cdc0]> dr=
  lr 0x0000cd90      pc 0x0000cdc0    cpsr 0x60000010     or0 0x01c6cd18
  r0 0x01c6cd18      r1 0x7ea53e50      r2 0x7ea53e50      r3 0x00000005
  r4 0x01c67008      r5 0x01c6cd18      r6 0x7ea54250      r7 0x00000000
  r8 0x00000000      r9 0x7ea5467c     r10 0x01c6ca48     r11 0x00024094
 r12 0x00000000     r13 0x7ea53e50     r14 0x0000cd90     r15 0x0000cdc0
 r16 0x60000010     r17 0x01c6cd18    

// Calculating the (ldrls) instruction result ( PC = [ PC + R3 * 4] )
[0x0000cdc0]> ? 0xcdc8 + 0x5 * 4
52700 0xcddc 0146734 51.5K 0000:0ddc 52700 11011100 52700.0 0.000000f 0.000000
[0x0000cdc0]> px/a 0xcddc
0x0000cddc  0x0000cde0 0xe1a00004                      ........        

// Single step instruction. We should have been redirected to "0x0000cde0" 
//but r2 did something like a "dc or dso" command. (The pc=0x5858.. is normal)
[0x0000cdc0]> ds
[+] SIGNAL 11 errno=0 addr=0x58585858 code=1 ret=0
[+] signal 11 aka SIGSEGV received 0

--- Same execution in gdb
Breakpoint 1, 0x0000cdc0 in ?? ()
(gdb) x/5i $pc
=> 0xcdc0:      ldrls   pc, [pc, r3, lsl #2]
   0xcdc4:      b       0xce30
   0xcdc8:      andeq   r12, r0, r0, lsl #28
   0xcdcc:      andeq   r12, r0, r0, ror #27
   0xcdd0:      andeq   r12, r0, r0, lsr lr
(gdb) ni
0x0000cde0 in ?? () 
(gdb) 
@daniel-rome
Copy link
Contributor Author

Btw, I have noticed that the Visual (Vpp) mode has a incorrect register in order to show the stack. r2 used the r14 register to show the stack instead the r13 register:

[0x0000cdc0 285 /tmp/binary]> f tmp;sr S.. @ pc 
**0x0000cd90  0xe2505000 0x0a000023 0xe5953018 0xe3530000  .PP.#....0....S. 
0x0000cda0  0x0a000003 0xe1a00004 0xe12fff33 0xe3500000  ........3./...P.
0x0000cdb0  0xba00001e 0xe5953004 0xe2433001 0xe3530005  .....0...0C...S. 
0x0000cdc0  0x979ff103 0xea000019 0x0000ce00 0x0000cde0  ................

  lr 0x0000cd90      pc 0x0000cdc0    cpsr 0x60000010     or0 0x010cbd18 
  r0 0x010cbd18      r1 0x7eb22e50      r2 0x7eb22e50      r3 0x00000005 
  r4 0x010c6008      r5 0x010cbd18      r6 0x7eb23250      r7 0x00000000 
  r8 0x00000000      r9 0x7eb2367c     r10 0x010cba48     r11 0x00024094 
 r12 0x00000000     r13 0x7eb22e50     **r14 0x0000cd90     r15 0x0000cdc0 
 r16 0x60000010     r17 0x010cbd18 

            ;-- pc:
            ;-- r15:
            0x0000cdc0 b    03f19f97       ldrls pc, [pc, r3, lsl 2]   ; [0xcdc8:4]=0xce00 
        ,=< 0x0000cdc4      190000ea       b 0xce30                    ;[1] 
        |   0x0000cdc8      00ce0000       andeq ip, r0, r0, lsl 28

@daniel-rome daniel-rome changed the title Wrong debugging execution after a "ldrls" instruction Wrong debugging execution after a "ldrls" instruction (ARM) Dec 30, 2015
@radare
Copy link
Collaborator

radare commented Dec 31, 2015

Thanks! i have fixed that R13 issue, it was only happening in some debugger backends. it was ok for iOS for example.. nice catch!

@radare
Copy link
Collaborator

radare commented Dec 31, 2015

The ESIL expression for that ldrls instruction is also wrong, can you submit a PR for it too?

esil: 8,pc,+,0,+,[4],pc,=

@daniel-rome
Copy link
Contributor Author

I don't know much the r2 source code, but when I have some time I am going to try to create a PR ;)

Thanks!!

@radare
Copy link
Collaborator

radare commented Jan 3, 2016

Its just editing the libr/anal/p/anal_arm_cs.c to change the expression that is generated for that instruction.

But i dont see a reason why this should fail when debugging. Esil will fix the emulation only.

@daniel-rome
Copy link
Contributor Author

ESIL seems that is working properly. This is my code:

    0x0000cdc0      03f19f97       ldrls pc, [pc, r3, lsl 2]   ; [0xcdc8:4]=0xce00 ; pc=0xcde0 -> 0xe1a00000
,=< 0x0000cdc4      190000ea       b 0xce30                    ;[1]; pc=0xce30 -> 0xe1a00000
|   0x0000cdc8      00ce0000       andeq ip, r0, r0, lsl 28   ; ip=0x0

ESIL says that PC will be "0xcde0", so it is right, isn't it?

@daniel-rome
Copy link
Contributor Author

The problem could be into "libr/bp/bp.c". When a single step "ds" is done, this function try to add the breakpoint in "0xcdc4", so the next address is not calculated properly.

In the "r_bp_get_in" function it can be seen the next address:

libr/bp/bp.c:99     if (addr >= b->addr && addr <= (b->addr+b->size) && 
libr/bp/bp.c:100        (!rwx || rwx&b->rwx))

(gdb) p addr
$24 = 52676 >> 0xcdc4

On the other hand, I have noticed that when a breakpoint is set and we are in the bp address, the "ds" command returns:

[0x0000cdb4]> ds
Breakpoint already set at this address.
Interrupted by a breakpoint

Here is the "r_bp_get_in" variables

libr/bp/bp.c:99     if (addr >= b->addr && addr <= (b->addr+b->size) && 
libr/bp/bp.c:100        (!rwx || rwx&b->rwx))

(gdb) p addr  
$9 = 52664
(gdb) p b->addr
$10 = 52660
(gdb) p b->size
$13 = 4
(gdb) p rwx
$17 = 4
(gdb) p rwx&b->rwx
$18 = 4

Due to "(b->addr+b->size) = addr" the function does not allow add a new bp in order to continue with the execution.

If instead of "ds" command we type the "dso" command a bp is set an we can continue with the execution.

Maybe the "addr <= (b->addr+b->size)" should be changed by "addr < (b->addr+b->size)"?

@radare
Copy link
Collaborator

radare commented Jan 3, 2016

Stepping shouldnt be using breakpoints on arm for linux because there's already hardware support for it. So you can check the value of dbg.swstep, it should be set to false.

But the breakpoint thing is a bug indeed.

About the esil expression, check the expression instead of the final value, i have the impression that this is only working for some cases. Didnt had much time to check it out. Im afk right now.

Thx

On 03 Jan 2016, at 13:44, daniel-rome notifications@github.com wrote:

The problem could be into "libr/bp/bp.c". When a single step "ds" is done, this function try to add the breakpoint in "0xcdc4", so the next address is not calculated properly.

In the "r_bp_get_in" function it can be seen the next address:

libr/bp/bp.c:99 if (addr >= b->addr && addr <= (b->addr+b->size) &&
libr/bp/bp.c:100 (!rwx || rwx&b->rwx))

(gdb) p addr
$24 = 52676 >> 0xcdc4
On the other hand, I have noticed that when a breakpoint is set and we are in the bp address, the "ds" command returns:

[0x0000cdb4]> ds
Breakpoint already set at this address.
Interrupted by a breakpoint
Here is the "r_bp_get_in" variables

libr/bp/bp.c:99 if (addr >= b->addr && addr <= (b->addr+b->size) &&
libr/bp/bp.c:100 (!rwx || rwx&b->rwx))

(gdb) p addr
$9 = 52664
(gdb) p b->addr
$10 = 52660
(gdb) p b->size
$13 = 4
(gdb) p rwx
$17 = 4
(gdb) p rwx&b->rwx
$18 = 4

Due to "(b->addr+b->size) = addr" the function does not allow add a new bp in order to continue with the execution.

If instead of "ds" command we type the "dso" command a bp is set an we can continue with the execution.

Maybe the "addr <= (b->addr+b->size)" should be changed by "addr < (b->addr+b->size)"?


Reply to this email directly or view it on GitHub.

@radare
Copy link
Collaborator

radare commented Jan 4, 2016

The ESIL expression for ldrls pc, [pc, r3, lsl 2] looks wrong to me because:

now: 8,pc,+,0,+,[4],pc,=

should be: 2,8,$$,r3,+,+,<<,pc,= or any other equivalent expression

@radare
Copy link
Collaborator

radare commented Jan 5, 2016

I have pushed a fix for the ESIL expression thing, but it turns out that it happens because of a bug in capstone. So i can't retrieve the value of the lshift field because it's always 0.

@radare
Copy link
Collaborator

radare commented Jan 7, 2016

Found the way capstone handles the shift in there and fixed the test and ESIL implementation. i'll look into the breakpoint issue later

@radare
Copy link
Collaborator

radare commented Jan 11, 2016

Should be fixed now. Please confirm :)

@radare radare closed this as completed Jan 11, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants