Re: Breakpoint Implementation
Re: Breakpoint Implementation
- Subject: Re: Breakpoint Implementation
- From: Dave Keck <email@hidden>
- Date: Thu, 7 Oct 2010 20:07:32 -0400
>> 1. Suspend every thread
>
> This procedure is not instantaneous.
I see. Is there a technique to determine when a thread has actually
stopped executing? My testing shows that the information returned by
thread_info() cannot be used for this purpose.
> (1) Security features will often prevent a page from being both writeable and executable, and may prevent a page from moving to executable if it has once been writable. The only exception to this would be operations in protected mode in the kernel to change these mappings (e.g. this is how dtrace emulates instructions when it replaces function preambles for FBT - Function Boundary Tracing). You can see this sort of thing in AntiVirus software or in copy protection, etc..
>
> (2) Your code signature for the modified page will no longer be valid. If it gets checked after you modify it, depending on your signing flags, your program may be immediately killed.
I can live with these problems for this hobby project.
> (4) The syscall instruction is not a single byte; if it's tripped non-aligned, e.g. not on a 4 byte boundary, or crossing a cache line boundary, the update of an in progress instruction stream can be undefined. Because it's a single byte (0xCC), this is typically why people use INT3 for this type of thing in the first place, rather than trying to replace other instructions. Modifications are typically followed by a flush of the instruction cache, in case it's not write-back, since otherwise your changes may not be visible. This is typically why self-modifying code is strongly frowned upon these days.
>
> (5) Other threads in the same process can be running through the same code path at the same time, and if they happen to be on the same core as an SMT thread, depending on the cache and instruction scheduling microarchitecture, you could be running through the instruction stream being modified at the time of the modification, resulting in undefined behaviour (see #3, #4).
I see – my (incorrect) assumptions regarding suspending every thread
led me to believe I'd be safe here.
>> 6. When Thread A hits the INT3 from step #4, set Thread A's EIP to the
>> instruction after the cached EIP (from step #3) and resume
>
> You won't know why the INT3 got hit, and you won't be able to store per-thread state with the thread structure as a trigger indicator in any case. So for example, if someone is dtrace'ing at the same time (e.g. running "Instruments" as you are doing your thing, or your code is intended ), you are going to have a conflict. The way dtrace avoids this is that in the trap handler (by which I mean the protected mode kernel code used for handling hardware and software exceptions), it has a list of locations where it has placed its INT3's, and will look in the table to see if it sees one. If it doesn't, it will pass it through. However, there is nothing to prevent your code from mistaking a dtrace INT3 for one of its own, and there's nothing to prevent either of you from instrumenting over top of each other.
This should also be acceptable for this project – I don't intend for
it to be used simultaneously with other debugging utilities.
Thanks Terry. As usual your help is much appreciated and beyond humbling. =)
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden