Skip site navigation (1)Skip section navigation (2)
Date:      23 Oct 2001 15:00:13 +0200
From:      Dag-Erling Smorgrav <des@ofug.org>
To:        arch@freebsd.org
Subject:   Debugging interfaces
Message-ID:  <xzpu1wq340y.fsf@flood.ping.uio.no>

next in thread | raw e-mail | index | archive | help
--=-=-=

We currently have three distinct debugging interfaces in the system:
ktrace(2), ptrace(2) and procfs(5).  I think you'll all agree that
that's two too many.  I propose to remove at least one of them.

The arguments in favor of ktrace is that it is easy to use (and to
extend) and provides information that ptrace and procfs cannot provide
(e.g. namei translations).  The argument against it is that it does
its work by stealing the traced process' context to write the
debugging information directly to a file.  It works for now, but it
may break in interesting ways as we continue pushing down locks.

The arguments in favor of ptrace is that it's clean and simple (which
makes it easy to audir) and doesn't invade the kernel much; it does
its work in the context of the calling process (i.e. the debugger),
not that of the target process.  The arguments against it is that it
is underpowered (there are things it can't do that e.g. truss needs to
do its job) and it reparents the debugged process, which is a bummer
if you use its parent is in wait4().

The arguments in favor of procfs is that it is currently the only
debugging interface that can do pretty much everything you need, and
it doesn't reparent the target process.  The arguments against it
are...  well, it's procfs.  It's vile and intrusive and has a history
of security holes.  It'd be nice to be able to truss processes without
needing procfs.  Plus, the way the procfs debugging interface is
designed, it can leave a process stuck in a loop in stopevent() and
there's nothing you can do to kill it unless you re-attach to it
using truss or procctl.

What I suggest is:

 1) Leave ktrace alone.  It's a kernel option, so people who don't
    like it can disable it.  Maybe remove it from GENERIC and change
    the message ktrace(1) prints when run on a KTRACE-less kernel to
    "re-compile kernel with 'options KTRACE' or use truss".

 2) Extend ptrace so it can support truss.

 3) Rewrite truss to use ptrace instead of procfs.

 4) Dyke out the pioctl stuff from procfs.

I have items 2) and 3) nearly done (to the point where 'truss -dS -o
truss.out ls' produces the attached truss.out; you'll notice that it's
not yet smart enough to display string arguments).  I've changed
stopevent() so it stops the process (roughly "p->p_stat = SSTOP;
mi_switch();") instead of looping, so the debugging process can use
wait4() instead of the PIOCWAIT ioctl to wait for events.

In order to support following forks in the debugged process without
upsetting the parent process (i.e. without reparenting the debugged
process), I need to make a few changes to struct proc and wait4();

 - struct proc acquires mirror p_pptr, p_sibling and p_children for
   debugging purposes

        p_dpptr         pointer to debugging "parent"
        p_dsibling      list of sibling debugged processes
        p_dchildren     pointer to list of debugging "children"

 - instead of waking up the parent process, stopevent() will wake up
   the debugging parent.

 - wait4() will scan p_dchildren in addition to p_children.

In addition, when a debugging process dies, any processes it was
debugging will be "undebugged" so you can no longer have processes
stuck in stopevent().

Some fields in struct proc (p_pfsflags for instance) will disappear as
a consequence of item 4) above.

None of these changes will affect the (limited) way gdb uses ptrace.

Comments are welcome. I estimate I will have patches ready for review
by the end of this week.

DES
-- 
Dag-Erling Smorgrav - des@ofug.org


--=-=-=
Content-Disposition: attachment; filename=truss.out

  4978 00:00.002 ptrace(0x0, 0x0, 0x0, 0x0)
  4978 00:00.003 ptrace returned 0
  4978 00:00.004 execve(0xbfbff214, 0xbfbff6c8, 0xbfbff6d0)
  4978 00:00.004 execve returned error 2: No such file or directory
  4978 00:00.004 execve(0xbfbff214, 0xbfbff6c8, 0xbfbff6d0)
  4978 00:00.005 execve returned error 2: No such file or directory
  4978 00:00.005 execve(0xbfbff214, 0xbfbff6c8, 0xbfbff6d0)
  4978 00:00.005 execve returned error 2: No such file or directory
  4978 00:00.005 execve(0xbfbff214, 0xbfbff6c8, 0xbfbff6d0)
  4978 00:00.007 exec
  4978 00:00.007 execve returned 0
  4978 00:00.008 open(fn = 0xbfbfebe0, flags = 0x0, mode = 0666)
  4978 00:00.008 open returned 4
  4978 00:00.009 fstat(0x4, 0xbfbfeab0)
  4978 00:00.009 fstat returned 0
  4978 00:00.009 readlink(0x80aef14, 0xbfbfea90, 0x3f)
  4978 00:00.009 readlink returned 1
  4978 00:00.010 __syscall(0xc5, 0x0, 0x0, 0x1000, 0x3, 0x1002, 0xffffffff, 0x0)
  4978 00:00.010 __syscall returned 671821824
  4978 00:00.010 break(0x80c9000)
  4978 00:00.011 break returned 0
  4978 00:00.011 break(0x80cb000)
  4978 00:00.011 break returned 0
  4978 00:00.011 read(fd = 4, buf = 0x80c9000, len = 8192)
  4978 00:00.012 read returned 6618
  4978 00:00.012 close(fd = 4)
  4978 00:00.012 close returned 0
  4978 00:00.013 open(fn = 0xbfbfebe0, flags = 0x0, mode = 0666)
  4978 00:00.013 open returned 4
  4978 00:00.013 fstat(0x4, 0xbfbfeb50)
  4978 00:00.013 fstat returned 0
  4978 00:00.014 fstat(0x4, 0xbfbfe9a0)
  4978 00:00.014 fstat returned 0
  4978 00:00.014 break(0x80cd000)
  4978 00:00.014 break returned 0
  4978 00:00.014 __syscall(0xc7, 0x0, 0x4, 0x0, 0x0)
  4978 00:00.015 __syscall returned 0
  4978 00:00.015 __syscall(0xc7, 0x0, 0x4, 0x0, 0x0)
  4978 00:00.015 __syscall returned 0
  4978 00:00.015 read(fd = 4, buf = 0x80cb000, len = 8192)
  4978 00:00.016 read returned 3196
  4978 00:00.016 close(fd = 4)
  4978 00:00.016 close returned 0
  4978 00:00.016 open(fn = 0xbfbfeba0, flags = 0x0, mode = 01002705061)
  4978 00:00.017 open returned 4
  4978 00:00.017 fstat(0x4, 0xbfbfeb40)
  4978 00:00.017 fstat returned 0
  4978 00:00.018 read(fd = 4, buf = 0x80ca011, len = 34)
  4978 00:00.018 read returned 34
  4978 00:00.018 close(fd = 4)
  4978 00:00.018 close returned 0
  4978 00:00.018 open(fn = 0xbfbfeba0, flags = 0x0, mode = 01002705121)
  4978 00:00.019 open returned 4
  4978 00:00.019 fstat(0x4, 0xbfbfeb40)
  4978 00:00.019 fstat returned 0
  4978 00:00.019 read(fd = 4, buf = 0x80c8091, len = 8)
  4978 00:00.020 read returned 8
  4978 00:00.020 close(fd = 4)
  4978 00:00.020 close returned 0
  4978 00:00.020 open(fn = 0xbfbfebb0, flags = 0x0, mode = 01002705161)
  4978 00:00.021 open returned 4
  4978 00:00.021 fstat(0x4, 0xbfbfeb50)
  4978 00:00.021 fstat returned 0
  4978 00:00.021 read(fd = 4, buf = 0x80cb011, len = 377)
  4978 00:00.022 read returned 377
  4978 00:00.022 close(fd = 4)
  4978 00:00.022 close returned 0
  4978 00:00.022 open(fn = 0xbfbfebb0, flags = 0x0, mode = 01002705221)
  4978 00:00.022 open returned 4
  4978 00:00.023 fstat(0x4, 0xbfbfeb50)
  4978 00:00.023 fstat returned 0
  4978 00:00.023 read(fd = 4, buf = 0x80ca051, len = 18)
  4978 00:00.023 read returned 18
  4978 00:00.023 close(fd = 4)
  4978 00:00.024 close returned 0
  4978 00:00.024 ioctl(0x1, 0x402c7413, 0xbfbff014)
  4978 00:00.024 ioctl returned 0
  4978 00:00.024 ioctl(0x1, 0x40087468, 0xbfbff088)
  4978 00:00.025 ioctl returned 0
  4978 00:00.025 getuid()
  4978 00:00.025 getuid returned 2602
  4978 00:00.025 break(0x80ce000)
  4978 00:00.025 break returned 0
  4978 00:00.025 stat(0x80cd0c0, 0xbfbfef70)
  4978 00:00.026 stat returned 0
  4978 00:00.026 open(fn = 0x80aa2eb, flags = 0x0, mode = 00)
  4978 00:00.026 open returned 4
  4978 00:00.026 fchdir(0x4)
  4978 00:00.027 fchdir returned 0
  4978 00:00.027 open(fn = 0x80aa2eb, flags = 0x0, mode = 00)
  4978 00:00.027 open returned 5
  4978 00:00.027 stat(0x80cc000, 0xbfbfef30)
  4978 00:00.028 stat returned 0
  4978 00:00.028 open(fn = 0x80cc000, flags = 0x4, mode = 00)
  4978 00:00.028 open returned 6
  4978 00:00.028 fstat(0x6, 0xbfbfef30)
  4978 00:00.029 fstat returned 0
  4978 00:00.029 fcntl(0x6, 0x2, 0x1)
  4978 00:00.029 fcntl returned 0
  4978 00:00.029 __sysctl(0xbfbfede8, 0x2, 0x80c2264, 0xbfbfede4, 0x0, 0x0)
  4978 00:00.030 __sysctl returned 0
  4978 00:00.030 fstatfs(0x6, 0xbfbfee30)
  4978 00:00.030 fstatfs returned 0
  4978 00:00.030 break(0x80cf000)
  4978 00:00.030 break returned 0
  4978 00:00.031 getdirentries(0x6, 0x80ce000, 0x1000, 0x80ca0d4)
  4978 00:00.031 getdirentries returned 1024
  4978 00:00.031 getdirentries(0x6, 0x80ce000, 0x1000, 0x80ca0d4)
  4978 00:00.032 getdirentries returned 0
  4978 00:00.032 __syscall(0xc7, 0x0, 0x6, 0x0, 0x0)
  4978 00:00.032 __syscall returned 0
  4978 00:00.032 close(fd = 6)
  4978 00:00.033 close returned 0
  4978 00:00.033 fchdir(0x5)
  4978 00:00.033 fchdir returned 0
  4978 00:00.033 close(fd = 5)
  4978 00:00.033 close returned 0
  4978 00:00.034 fstat(0x1, 0xbfbfed30)
  4978 00:00.034 fstat returned 0
  4978 00:00.034 break(0x80d0000)
  4978 00:00.034 break returned 0
  4978 00:00.034 ioctl(0x1, 0x402c7413, 0xbfbfed64)
  4978 00:00.035 ioctl returned 0
  4978 00:00.035 write(fd = 1, buf = 0x80cf000, len = 46)
  4978 00:00.035 write returned 46
  4978 00:00.037 write(fd = 1, buf = 0x80cf000, len = 42)
  4978 00:00.038 write returned 42
  4978 00:00.039 write(fd = 1, buf = 0x80cf000, len = 57)
  4978 00:00.040 write returned 57
  4978 00:00.042 write(fd = 1, buf = 0x80cf000, len = 46)
  4978 00:00.043 write returned 46
  4978 00:00.044 exit(status = 0)
  4978 00:00.045 exit 0

--=-=-=--

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




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