Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Nov 1998 16:13:05 +1030
From:      Greg Lehey <grog@lemis.com>
To:        Joel Ray Holveck <joelh@gnu.org>
Cc:        SysAdmin <sa@ns.online.samara.ru>, freebsd-hackers@FreeBSD.ORG
Subject:   Re: breakpoint on i/o in kernel
Message-ID:  <19981124161305.W63366@freebie.lemis.com>
In-Reply-To: <86af1hn411.fsf@detlev.UUCP>; from Joel Ray Holveck on Mon, Nov 23, 1998 at 09:49:46PM -0600
References:  <AAnyMMsCYR@ns.online.samara.ru> <19981123205619.Q430@freebie.lemis.com> <86iug6mcnq.fsf@detlev.UUCP> <19981124093537.R430@freebie.lemis.com> <86af1hn411.fsf@detlev.UUCP>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday, 23 November 1998 at 21:49:46 -0600, Joel Ray Holveck wrote:
>>> I don't know what CPUs have instrumentation for this.
>> All i386 architectures, in varying degrees.
>
> Since I wrote that message, I dragged out my Intel docs so I could
> follow along with the rest of the class.
>
>>> (It might theoretically be possible with GDB using a semicomplex
>>> series of isteps and tests, but it would slow down your system
>>> possibly hundredfold.)
>> The correct thing to do would be to implement I/O (and memory access)
>> breakpoints, not kludge it.
>
> Memory access breakpoints are already implemented:
>
>      watch addr,size
>      Set a watchpoint for a region.  Execution stops when an attempt to modify
>      the region occurs.  The size argument defaults to 4.  If you specify a
>      wrong space address, the request is rejected with an error message.

Last time I looked, watchpoints worked by tracing the program and only
stopping if the condition was met.  That makes it ridiculously slow,
especially if you're debugging over a serial line.  It also applies
only for write access, not for read access.

Here's the relevant part of the documentation for Lowbug (September
1992):

   3.1.2  Breakpoints
   
   Up to four breakpoints can be set using the hardware breakpoint
   facility of the 386 architecture.
   
   These enable breakpoints to be set not only on instructions but also
   on memory read and memory write.  To set a breakpoint, enter
   
            b  addr [option [, option]]  for  a  persistent  breakpoint  or
            B  addr [option [, option]]  for  a  temporary  breakpoint
   
   The first form (persistent breakpoint) will create a breakpoint which
   will remain in effect until explicitly removed.  The second form
   (temporary breakpoint) will create a breakpoint which will go away as
   soon as it is encountered.  This form is useful to get to a certain
   point and then forget the breakpoint.  It is also used internally by
   the leave command.
   
   
   addr is an expression which represents a symbolic address.  This is
        the first byte of the address upon which the breakpoint will be set.
   
   
   options modify the breakpoint action.  They can be any combination of:
   
   
   a action [; action]
   
                    After encountering the breakpoint, the commands
                    specified as action are executed.  The commands may
                    be any valid Lowbug command, including instructions
                    to con- tinue execution.  If this happens, there may
                    be no indication that the breakpoint was hit.
                    Breakpoint actions are executed for each breakpoint
                    whose condition is fulfilled, in the order of the
                    breakpoint number (which corresponds to the hardware
                    breakpoint register).  In particular, if two
                    breakpoint conditions are valid at the same time, and
                    the action of the first (i.e.  lower numbered)
                    breakpoint involves a return to the program, the
                    second breakpoint will not be recognised, and its
                    actions will not be executed.
   
                    Note that action may consist of several subcommands,
                    separated by semicolons (;).  Since this is also the
                    Lowbug command delimiter, some restrictions are
                    imposed.
   
                    Breakpoint subcommands are separated by commas.  The
                    action subcommand is taken to start immediately after
                    the letter a and to continue to the next comma or to
                    the end of the input line.  If something is input
                    like
   
                            b  _myioctl#23,al;&;v;b;c
   
                    the commands b and c will be considered part of the
                    action and will be executed when the breakpoint is
                    encountered.  In order to continue execution
                    immediately, enter
   
                            b  _myioctl#23,al;&;v,b;c
   
                    It is probably better, however, to never put further
                    instructions behind a breakpoint instruction.
   
   i[f] condition
   
                    Only stop program execution if the expression
                    condition evaluates to non-zero.
   
   
   l expr           The memory address monitored by the breakpoint starts at the
                    address addr; it continues for 1, 2 or 4 bytes.  This
                    length defaults to 1, but may be specified by the l
                    subcommand.  Note that alignment rules are enforced
                    by 80386 and 80486 hardware; a length of 2 implies
                    that the high-order 31 address bits are the same.  In
                    addition, an instruction breakpoint may only have a
                    length of 1, and in the case of a multi-byte opcode,
                    it must be on the first byte.  A length of 4 implies
                    that the high-order 30 address bits are the same.
                    Lowbug will reject combinations of start address and
                    length which do not adhere to the length and
                    alignment rules, but it cannot detect when an
                    instruction breakpoint is set on other than the first
                    byte of an instruction.
   
   
   p pid		  The breakpoint only applies to process pid.  It will
   		 be ignored for others.
   
   
   t type		 Normally, a breakpoint occurs when an instruction
                    starting at address addr is exe- cuted.  The 80386
                    and 80486 hardware also support breakpoints which
                    occur when memory reads or write are made at the
                    specified location.  This is specified with the t
                    subcommand: type may be one of i (default), for
                    instruction breakpoint, w, memory write - a
                    breakpoint trap will occur after the memory write
                    occurs; or m - memory read or write breakpoint.  An
                    breakpoint trap will occur after a data word is
                    transferred to the memory location, a trap will not
                    occur on an instruction fetch.
   
   Breakpoints slow the execution of the program minimally, since some of
   the internal pipelining of the chip must be turned off in order to get
   the correct address for the breakpoint return.  In practice, this does
   not make much difference unless many "invisible" conditional
   breakpoints are executed.


>> I look at it once, and the code turned my stomach.
>
> Was this for kdb, ddb, or kgdb?  I don't know much about ddb.

gdb.  ddb is too limited to be of much use.

> Going over its code, it appears that ddb uses the VMM to handle
> watchpoints instead of using the processor's debugging
> instrumentation.  (This is fine with me, and more portable to boot.)

The question is speed.

> A quick review doesn't show any major problems implementing I/O
> breakpoints.  Is there any reason that the same entry mechanism to
> enter ddb on a page fault couldn't also enter ddb on a debug
> exception?  If that's the case, then it would appear that all we need
> to do is to write something to manage four I/O breakpoints and we've
> got the basics.

The main reason is that it's so slow as to be unusable.  We have an
alternative which *is* usable.

> gdb already has some instrumentation for hardware breakpoints; it may
> be extendable to allow for this sort of thing.  I haven't looked into
> that.

It must be new, then.  If you point me to it, I may take a look at it.

>>> I generally recommend another method of debugging than I/O
>>> breakpoints.
>>
>> That's a workaround, not a solution.  I/O breakpoints are really
>> useful.
>
> Yes, but they are also frequently misused.  I myself used to be a
> frequent debugger abuser, and would rely on the debugger instead of
> thinking about the driver and knowing what's going on wrong.

Sure, there's a certain tendency to do that.  That doesn't make the
tool bad, though.

> And now I hope that I'm not starting a holy war.

Who knows? :-)

Greg
--
See complete headers for address, home page and phone numbers
finger grog@lemis.com for PGP public key

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19981124161305.W63366>