tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ptrace(2) interface for hardware watchpoints (breakpoints)



On 13.12.2016 04:12, Valery Ushakov wrote:
> On Tue, Dec 13, 2016 at 02:04:36 +0100, Kamil Rytarowski wrote:
> 
>> The design is as follows:
>>
>> 1. Accessors through:
>>  - PT_WRITE_WATCHPOINT - write new watchpoint's state (set, unset, ...),
>>  - PT_READ_WATCHPOINT - read watchpoints's state,
>>  - PT_COUNT_WATCHPOINT - receive the number of available watchpoints.
> 
> Gdb supports hardware assisted watchpoints.  That implies that other
> OSes have existing designs for them.  Have you studied those existing
> designs?  Why do you think they are not suitable to be copied?
> 

They are based on the concept of exporting debug registers to tracee's
context (machine context/userdata/etc). FreeBSD exposes MD-specific
DBREGS to be set/get by a user, similar with Linux and with MacOSX.

GDB supports hardware and software assisted watchpoints. Software ones
are stepping the code and checking each instruction, hardware ones make
use of the registers.

I propose to export an interface that is not limited to one type of
hardware assisted action, while it can be fully used for hardware
watchpoints (if CPU supports it). This interface will abstract
underlying hardware specific capabilities with a MI ptrace(2) calls (but
MD-specific ptrace_watchpoint structure).

These interfaces are already platform specific and aren't shared between
OSes.

Some time ago I checked and IIRC the only two users of these interfaces
were GDB and LLDB, I implied from this that there is no danger from
heavy patching 3rd party software.

> 
>> 4. Do not set watchpoints globally per process, limit them to
>> threads (LWP). [...]  Adding process-wide management in the
>> ptrace(2) interface calls adds extra complexity that should be
>> pushed away to user-land code in debuggers.
> 
> 
> I have no idea what amd64 debug registers do, but this smells like you
> are exposing in the MI interface some of those details.  I don't think
> this can be done in hardware on sh3, e.g.  
> 

No, I'm not exposing anything in MI code - except the number of
available watchpoints defined by MD code (but this information goes
through a function called from MD part).

The functions are hidden under __HAVE_PTRACE_WATCHPOINTS ifdefs.

"watchpoint" terminology can be misleading, but since I couldn't get
better, I called this interface with this word.

> Also, you quite often have no idea which thread stomps on your data,
> so I'd imagine most of the time you do want a global watchpoint.

This is true.

With the proposed interface per-thread a debugger can set the same
hardware watchpoint for each LWP and achieve the same result. There are
no performance or synchronization challenges as watchpoints can be set
only when a process is stopped.

In my older code I had logic per-process to access watchpoints, but it
required extra logic in thread-specific functions to access process
specific data. I assumed that saving few dozens of CPU cycles before
each thread entering user-space is precious. (I know it's a small
optimization, however it's for free)

A user-interface of a debugger ("from a user point of view") is agnostic
to both approaches.

> Note, that if you want to restrict your watchpoint to one thread, you
> can probably (I don't know and I haven't checked) do this with gdb
> "command" that "continue"s if it's on the wrong thread.
> 

The proposed approach is just on the level of ptrace(2) implementation,
any debugger is free to support free to implement it in any way it's
possible, while making an option to set watchpoints per thread.

I don't want to appear like escaping the choice, but I'm trying to
propose an implementation that was easier to be applied on the kernel
side. From a userland point of view I think it does not matter.

> 
>> 5. Do not allow to mix PT_STEP and hardware watchpoint, in case of
>> single-stepping the code, disable (it means: don't set) hardware
>> watchpoints for threads. Some platforms might implement single-step with
>> hardware watchpoints and managing both at the same time is generating
>> extra pointless complexity.
> 
> I don't think I see how "extra pointless complexity" follows.
> 

1. At least in MD x86 specific code, watchpoint traps triggered with
stepped code are reported differently to those reported with plain steps
and also differently to plain hardware watchpoint traps. They are 3rd
type of a trap.

2. Single stepping can be implemented with hardware assisted watchpoints
(technically breakpoints) on the kernel side in MD. And if so, trying to
apply watchpoints and singlestep will conflict and this will need
additional handling on the kernel side.

To oppose extra complexity I propose to make stepping and watchpoints
separable, one or the other, but not both.

> Also, you might want both, single-stepping and waiting for a
> watchpoint.  Will debugger have switch dynamically to software
> watchpoints when single-stepping?  Can it even do that already?
> 

My understanding of stepping the code is that we want to go one and only
one instruction ahead (unless port restricts it and its 1 or more),
followed with a break.

What's the use case of waiting for data access and stepping in the same
time? Is it needed? Does it solve some issues that cannot be solved
otherwise? Could it be implemented in software (in case of watch?

My original intention was to make it friendly for ports, without too
specific expectations with flexible

> 
> In general I'd appreciate if handwavy "this is pointless/extra
> complexity" arguments were spelled out.  They might be obvious to you,
> but most people reading this don't have relevant information swapped
> in, or don't know enough details.
> 
> -uwe
> 

Thank you for your input, I hope I explained and expressed my thoughts
more clearly.


Attachment: signature.asc
Description: OpenPGP digital signature



Home | Main Index | Thread Index | Old Index