[lldb-dev] POP instruction causes process continuation

jingham at apple.com jingham at apple.com
Thu Mar 26 11:37:49 PDT 2015


step-over of any sort as currently implemented depends on being able to tell whether the current frame is older or younger than the frame we started in.  So if we step and end up in a frame that is younger than the one we started from, we step back out to the parent frame.  Your pop %ebp is fooling the unwinder into thinking this is a newer frame, so we try to step back out, which turns into a continue.  You are adding instructions that look like frame setup instructions, which is probably what is fooling us.

We can probably make this work better in odd cases like this by taking a look at the instruction we are about to execute, and if it is not a branch, then we know it hasn't pushed a real new execution frame, so we should stop.  The nice thing about dealing just the results of each operation, rather than trying to predict what each instruction is going to do, is that we don't have to reason about all the instructions in the instruction set.  The downside is that you do get fooled by odd patterns like this. I'm not sure corner-cases like this are enough to motivate me to switch to a more architecture-specific algorithm, however.

For now, just use "step-inst" not "next-inst" when you are stepping over code that looks like it might be frame setup but isn't.

Jim




> On Mar 26, 2015, at 11:14 AM, Christian Mayer <christian at fox21.at> wrote:
> 
> Hi,
> 
> I have the following i386 assembly code:
> 
> 
> ##########
> .text
> .globl _main
> 
> _main:
> 	
> 	nop
> 	
> 	push %ebp
> 	mov %esp, %ebp
> 	
> 	sub $0x4, %esp
> 	push $msg1
> 	call _puts
> 	add $0x8, %esp
> 	
> 	pop %ebp
> 	push %ebp
> 	
> 	sub $0x4, %esp
> 	push $msg2
> 	call _puts
> 	add $0x8, %esp
> 	
> 	mov $5, %eax
> 	pop %ebp
> 	ret
> 
> .data
> msg1:
> 	.ascii "Hello World!\0"
> 	len = . - msg1
> 
> msg2:
> 	.ascii "This is a second line.\0"
> 	len = . - msg2
> ##########
> 
> 
> 
> Compiled under Mac OS X 10.10 with the following commands:
> 
> as -W -arch i386 -o build/test3-i386.o test3-i386.s
> ld -arch i386 -macosx_version_min 10.10 -no_pie -o build/test3-i386
> build/test3-i386.o -lSystem
> 
> 
> When I run the compiled binary in the shell everything works fine,
> but when I debug it from _main step-by-step with "thread step-inst-over"
> in LLDB 340.99.0 (ToT) - LLDB automatically continues on the first "pop
> %ebp" instruction.
> 
> 
> :> lldb build/test3-i386
> lldb:> target create "build/test3-i386"
> Current executable set to 'build/test3-i386' (i386).
> lldb:> br s -n main
> Breakpoint 1: where = test3-i386`main, address = 0x00001f6d
> lldb:> process launch
> Process 66822 launched: 'build/test3-i386' (i386)
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f6d test3-i386`main, queue =
> 'com.apple.main-thread', stop reason = breakpoint 1.1
>    frame #0: 0x00001f6d test3-i386`main
> -> 	 0x1f6d <test3-i386`main+0>: nop
>   	 0x1f6e <test3-i386`main+1>: pushl  %ebp
>   	 0x1f6f <test3-i386`main+2>: movl   %esp, %ebp
>   	 0x1f71 <test3-i386`main+4>: subl   $0x4, %esp
> lldb:> ni
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f6e test3-i386`main + 1, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f6e test3-i386`main + 1
> -> 	 0x1f6e <test3-i386`main+1>: pushl  %ebp
>   	 0x1f6f <test3-i386`main+2>: movl   %esp, %ebp
>   	 0x1f71 <test3-i386`main+4>: subl   $0x4, %esp
>   	 0x1f74 <test3-i386`main+7>: pushl  $0x200c
> lldb:>
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f6f test3-i386`main + 2, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f6f test3-i386`main + 2
> -> 	 0x1f6f <test3-i386`main+2>:  movl   %esp, %ebp
>   	 0x1f71 <test3-i386`main+4>:  subl   $0x4, %esp
>   	 0x1f74 <test3-i386`main+7>:  pushl  $0x200c
>   	 0x1f79 <test3-i386`main+12>: calll  0x1f9a ; symbol stub for: puts
> lldb:>
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f71 test3-i386`main + 4, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f71 test3-i386`main + 4
> -> 	 0x1f71 <test3-i386`main+4>:  subl   $0x4, %esp
>   	 0x1f74 <test3-i386`main+7>:  pushl  $0x200c
>   	 0x1f79 <test3-i386`main+12>: calll  0x1f9a ; symbol stub for: puts
>   	 0x1f7e <test3-i386`main+17>: addl   $0x8, %esp
> lldb:>
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f74 test3-i386`main + 7, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f74 test3-i386`main + 7
> -> 	 0x1f74 <test3-i386`main+7>:  pushl  $0x200c
>   	 0x1f79 <test3-i386`main+12>: calll  0x1f9a ; symbol stub for: puts
>   	 0x1f7e <test3-i386`main+17>: addl   $0x8, %esp
>   	 0x1f81 <test3-i386`main+20>: popl   %ebp
> lldb:>
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f79 test3-i386`main + 12, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f79 test3-i386`main + 12
> -> 	 0x1f79 <test3-i386`main+12>: calll  0x1f9a ; symbol stub for: puts
>   	 0x1f7e <test3-i386`main+17>: addl   $0x8, %esp
>   	 0x1f81 <test3-i386`main+20>: popl   %ebp
>   	 0x1f82 <test3-i386`main+21>: pushl  %ebp
> lldb:>
> Hello World!
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f7e test3-i386`main + 17, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f7e test3-i386`main + 17
> -> 	 0x1f7e <test3-i386`main+17>: addl   $0x8, %esp
>   	 0x1f81 <test3-i386`main+20>: popl   %ebp
>   	 0x1f82 <test3-i386`main+21>: pushl  %ebp
>   	 0x1f83 <test3-i386`main+22>: subl   $0x4, %esp
> lldb:>
> Process 66822 stopped
> * thread #1: tid = 0x2af723, 0x00001f81 test3-i386`main + 20, queue =
> 'com.apple.main-thread', stop reason = instruction step over
>    frame #0: 0x00001f81 test3-i386`main + 20
> -> 	 0x1f81 <test3-i386`main+20>: popl   %ebp
>   	 0x1f82 <test3-i386`main+21>: pushl  %ebp
>   	 0x1f83 <test3-i386`main+22>: subl   $0x4, %esp
>   	 0x1f86 <test3-i386`main+25>: pushl  $0x2019
> lldb:>
> This is a second line.
> Process 66822 exited with status = 5 (0x00000005)
> lldb:> ^D
> 
> When I remove
> 
> 	pop %ebp
> 	push %ebp
> 
> it works fine. Then LLDB stops after each single instruction step over
> until to the end of the program.
> 
> 
> When I also remove the instructions for the output of the second puts()
> it continues at the bottom "pop %ebp", before "ret":
> 
> ##########
> .text
> .globl _main
> 
> _main:
> 	
> 	nop
> 	
> 	push %ebp
> 	mov %esp, %ebp
> 	
> 	sub $0x4, %esp
> 	push $msg1
> 	call _puts
> 	add $0x8, %esp
> 	
> 	mov $5, %eax
> 	pop %ebp
> 	ret
> 
> .data
> msg1:
> 	.ascii "Hello World!\0"
> 	len = . - msg1
> 
> msg2:
> 	.ascii "This is a second line.\0"
> 	len = . - msg2
> ##########
> 
> It should do only one instruction step over.
> 
> What am I doing wrong?
> 
> 
> Br,
> Christian
> 
> -- 
> Christian Mayer
> software developer
> http://fox21.at
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev





More information about the lldb-dev mailing list