Well, if I have to use it then I will.
Yes, the code could be reworked by moving some of the data from the CPU
hw-breakpoint info into the thread's info. I'll see how much simpler it
ends up being.
It isn't quite that easy. Even though the number of user breakpoints may
not have changed, their identities may have. So the unlikely case has to
encompass two possibilities: the number of installable user breakpoints
has changed, or any user breakpoints have been registered or unregistered.
This shouldn't be necessary. So long as DR_GLOBAL_ENABLE always belongs
to the kernel's part of DR7 and DR_LOCAL_ENABLE always belongs to the
thread's part there will be no interference between them.
Maybe. I always had in the back of my mind the possibility that there
might be a user I/O breakpoint set. It could be triggered by an interrupt
handler even in the SIGKILL case. But since we're not supporting I/O
breakpoints now, that's a moot point.
Actually the code _doesn't_ already know what's there; the chbi area
doesn't include any storage for the kernel DR7 value. I figured it was at
least as easy to read it from the CPU register as to read it from memory.
But maybe that's not true; according to my ancient processor manual, moves
to/from debug registers take many more clock cycles than moves to/from
memory.
Okay. That test was for situations when it's necessary to install only
the kernel's debug registers, with no thread registers. It can easily
be made into a separate routine.
I was being overly cautious. If interrupts were enabled then it might be
possible to trip a user I/O breakpoint. But since they aren't, that code
isn't needed.
No. If a debugger has removed some user breakpoints since the last time
the thread ran, the chbi->bps[] entries could still be present. Likewise
if the previously-running task had more breakpoints than the current one.
Of course it doesn't actually hurt to have stale pointers lying around;
they refer to breakpoints which aren't enabled. So clearing them isn't
really necessary.
This proposed change is wrong. Remember that ptrace breakpoints are
virtualized; they are assigned to different debug registers from what the
debugger thinks. That's why I added args.ret.
This sounds like a better solution.
I don't like using DR_LEN_1, because it would force asm/debugreg.h to be
#included by any user of hw_breakpoint. The raw numerical value should do
just as well.
So there's no way to trap on accesses to a particular byte within a
string?
Not quite that simple, but close to it. (len | type) ends up being
shifted by 4*drnum whereas the enable bit gets shifted by 2*drnum (where
drnum is the debug register assigned to the breakpoint), so they can't be
stored together. But the enable bit doesn't need to be present in
bp->bits; it is implied.
Better yet, if type is HW_BREAKPOINT_TYPE_EXECUTE then just ignore the
caller's len and always use the correct value.
Since PPC doesn't allow lengths shorter than 8, perhaps on that
architecture the bottom bits of the address should silently be cleared.
It gives drivers a way to tell whether or not the breakpoint is currently
installed without having to do explicit tracking of installed() and
uninstalled() callbacks.
These changes to the API sound pretty good. Stay tuned for the next
version...
Alan Stern
-