Shared Process plugin between Linux and BSD

Hello,

I've prepared two patches to make the Linux Process Plugin buildable on
NetBSD.

The diff will help to transform the Linux process plugin to common code,
shared between Linux and BSDs (FreeBSD, NetBSD).

lldb-git: Enable Linux Process plugin on NetBSD

https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=4b00674e876ebfe427743759de13ead420112fd4

lldb-git: Disable unbuildable code-fragments in the
LinuxProcessPlugin/NetBSD

https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=e1ef012c16ab7729918ae367150b13bf0d77650b

Comments to the disabled code:

1. Thread resume/suspend operation - to be implemented on NetBSD with
ptrace(2).

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

3. PTRACE_O_TRACEEXEC, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXIT -
equivalent to be implemented.

4. No tracing of VFORK events implemented.

5. Hardware assisted watchpoints (debug registers on amd64) have their
dedicated ptrace(2) API to set/unset watchpoints, they do not export raw
debug registers.

6. Other ptrace(2) calls have their equivalents on NetBSD
(PTRACE_PEEKUSER, PTRACE_POKEUSER etc).

7. SIGTRAP has currently only two si_code values (specified by POSIX).

8. No SI_TKILL available.

9. There is no process_vm_readv/process_vm_writev call available.

10. __WALL and __WNOTHREAD are Linux specific, but they have their
counterparts.

11. The cpu_set_t structure and appropriate functions have similar
counterparts on NetBSD.

12. No <sys/procfs.h> and no dependency of procfs (/proc) is acceptable,
everything shall be accessible through ptrace(2) and sysctl(7).

13. personality.h - unsupported as header/function call, compatibility
with other OSes (mostly Linux) implemented on syscall level.

14. Process, system thread (lwp) and POSIX (pthread_t) thread are not
the same on NetBSD, unlike some other systems and cannot be mixed.

The currently missing features on the NetBSD side don't stop us from
making a functional implementation, lacing interfaces might be added
after getting the core part to work.

I am wondering if it would be better to make a common base class, like NativeProcessPtrace, where all of the common Ptrace stuff lives and then subclass and override the functions that are different. There seemed to be a bunch of "#if defined(NETBSD)" stuff in the second patch. Without extra code context in the diffs it is hard to see if the the function is all one or the other, or just a very small part is overridden. Code like this:

Error NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
                                     size_t &bytes_read) {
#if !defined(__NetBSD__)
  if (ProcessVmReadvSupported()) {
#else
  {
#endif
    // The process_vm_readv path is about 50 times faster than ptrace api. We
    // want to use
    // this syscall if it is supported.
@ -2145,7 +2173,11 @@ Error NativeProcessLinux::ReadMemory(lld
    remote_iov.iov_base = reinterpret_cast<void *>(addr);
    remote_iov.iov_len = size;

#if !defined(__NetBSD__)
    bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
#else
    bytes_read = 0;
#endif
    const bool success = bytes_read == size;

    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

All the extra #defines are the C way of doing things and really make the code a bit messy. We should probably just have NativeProcessLinux and NativeProcessNetBSD that inherit from NativeProcessPtrace, and then each would override the ReadMemory function.

That is my opinion, I would also wait for opinions from the people that actually work on the NativeProcessLinux plug-in as their opinion will count more than mine. SVN blame can probably tell you who did most of it.

Greg Clayton

I am communicating with Kamil about the possibility of sharing code
between the two plugins. We plan to have a common base class for the
shared functionality between the OSs. I have asked Kamil to perform
this experiment, so we can identify which parts of the code can be
shared in the first place. My thoughts on the noticed differences are
below

Comments to the disabled code:

1. Thread resume/suspend operation - to be implemented on NetBSD with
ptrace(2).

This is going to be the trickiest part, as thread management works
quite differently on the two OSs. we'll need to investigate more on
how much we can reuse here

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

This value is currently only used in logging code, so we can just
remove it from the code base. However, it's a useful thing to have for
the future, so it may be worth making sure the NetBSD kernel supports
it.

3. PTRACE_O_TRACEEXEC, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXIT -
equivalent to be implemented.

Do you mean "implemented in lldb-server" or "implemented in the
kernel"? Being notified when the inferior exec()s would definitely be
good. Tracing thread creation and exit is a nice-to-have but low
priority. The only reason we used it on linux is because that's the
only way to auto-attach to new threads, but I think that for you that
will happen automatically.

4. No tracing of VFORK events implemented.

5. Hardware assisted watchpoints (debug registers on amd64) have their
dedicated ptrace(2) API to set/unset watchpoints, they do not export raw
debug registers.

6. Other ptrace(2) calls have their equivalents on NetBSD
(PTRACE_PEEKUSER, PTRACE_POKEUSER etc).

Cool, I guess that means we can share (Read|Write)Memory(WithoutTrap|).

7. SIGTRAP has currently only two si_code values (specified by POSIX).

The code for decoding si_code values is already messy and in need of a
rewrite. I think the act of decoding si_code values will need to be
OS- (and maybe event architecture-) specific, but the actions taken
upon individual events should be quite similar.

8. No SI_TKILL available.

This is used because when a single thread in a process stops, we need
to go and manually stop all other threads. The whole function around
this should probably be moved into the linux-specific class, as you
don't need to do anything special to interrupt a process (IIUC).

9. There is no process_vm_readv/process_vm_writev call available.

These are used only as a preformance optimization on linux. If
(PEEK|POKE)DATA work the same way, we can put that in the base class.
Then, linux can override and do it's fancy thing.

10. __WALL and __WNOTHREAD are Linux specific, but they have their
counterparts.

We should probably have a waitpid wrapper, which adds any os-specific
flags if necessary. We can put the EINTR handling there as well to
make it's usage easier.

11. The cpu_set_t structure and appropriate functions have similar
counterparts on NetBSD.

This is only used to work around a bug in the linux arm64 kernels. I
don't think you need to worry yourself with that. It can stay hidden
in NativeThreadLinux::SingleStep

12. No <sys/procfs.h> and no dependency of procfs (/proc) is acceptable,
everything shall be accessible through ptrace(2) and sysctl(7).

We'll need to check whether the appropriate interfaces are in place to
abstract this (I expect it to be the case), and add new ones if
necessary.

13. personality.h - unsupported as header/function call, compatibility
with other OSes (mostly Linux) implemented on syscall level.

This was already dead code, and I have removed it.

14. Process, system thread (lwp) and POSIX (pthread_t) thread are not
the same on NetBSD, unlike some other systems and cannot be mixed.

I believe the code has already good separation between thread and
process IDs, and doesn't use pthread_t, so this shouldn't be a
problem. NetBSD-specific pthread_t debugging code can be contained in
the NetBSD class.

The currently missing features on the NetBSD side don't stop us from
making a functional implementation, lacing interfaces might be added
after getting the core part to work.

Agreed. The only thing that slightly worries me is the lack of
execve() tracing capability, if I understood correctly. While it
probably may be possible to work without it. I'd think about adding it
nonetheless.

good luck,
pl

I am communicating with Kamil about the possibility of sharing code
between the two plugins. We plan to have a common base class for the
shared functionality between the OSs. I have asked Kamil to perform
this experiment, so we can identify which parts of the code can be
shared in the first place. My thoughts on the noticed differences are
below

Comments to the disabled code:

1. Thread resume/suspend operation - to be implemented on NetBSD with
ptrace(2).

This is going to be the trickiest part, as thread management works
quite differently on the two OSs. we'll need to investigate more on
how much we can reuse here

My plan was to add two ptrace(2) calls like: PT_SUSPEND/PT_RESUME and
specify LWP to be resumed/suspended. It shouldn't be hard to implement
as there is already _lwp_suspend(2) and _lwp_continue(2), just call it
for other process with ptrace(2).

PT_CONTINUE could be kept to resume the whole process (modulo frozen
threads) along with PT_STEP. However, I was holding on with it as I
wanted to reflect it with needs of a real debugger like LLDB.

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

This value is currently only used in logging code, so we can just
remove it from the code base. However, it's a useful thing to have for
the future, so it may be worth making sure the NetBSD kernel supports
it.

I was wondering whether waitid(2) or wait6(2) could be used there, as
they return siginfo_t. If so, NetBSD does not need dedicated ptrace(2)
entry.

3. PTRACE_O_TRACEEXEC, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXIT -
equivalent to be implemented.

Do you mean "implemented in lldb-server" or "implemented in the
kernel"? Being notified when the inferior exec()s would definitely be
good. Tracing thread creation and exit is a nice-to-have but low
priority. The only reason we used it on linux is because that's the
only way to auto-attach to new threads, but I think that for you that
will happen automatically.

I mean implemented in the kernel.

Thread (lwp) creation and termination is currently detectable in FreeBSD
with a special event, if this is useful in the NetBSD context -- like a
user setting a break on this event explicitly -- I will add it to TODO
list. On NetBSD there is no need to explicitly start tracing new
threads, tracing is per process and it is composed of a bulk of threads
(lwp). POSIX threads are a layer with extra features built upon LWP.

There is also the the exect(3) call in our libc inherited from BSD4.2,
but it no longer works in a useful way. It used to singlestep execve(2)
call. I was thinking whether/how to make it useful again, like combine
in it execve(2) + PT_TRACE_ME + SIGSTOP/SIGTRAP on exec.

4. No tracing of VFORK events implemented.

5. Hardware assisted watchpoints (debug registers on amd64) have their
dedicated ptrace(2) API to set/unset watchpoints, they do not export raw
debug registers.

6. Other ptrace(2) calls have their equivalents on NetBSD
(PTRACE_PEEKUSER, PTRACE_POKEUSER etc).

Cool, I guess that means we can share (Read|Write)Memory(WithoutTrap|).

Functionality is the same, however the API is different.

7. SIGTRAP has currently only two si_code values (specified by POSIX).

The code for decoding si_code values is already messy and in need of a
rewrite. I think the act of decoding si_code values will need to be
OS- (and maybe event architecture-) specific, but the actions taken
upon individual events should be quite similar.

I was wondering whether it is useful to return distinct si_code for
hardware assisted traps or PT_STEP. At the moment I ignored it.

8. No SI_TKILL available.

This is used because when a single thread in a process stops, we need
to go and manually stop all other threads. The whole function around
this should probably be moved into the linux-specific class, as you
don't need to do anything special to interrupt a process (IIUC).

In NetBSD the whole process is stopped.

9. There is no process_vm_readv/process_vm_writev call available.

These are used only as a preformance optimization on linux. If
(PEEK|POKE)DATA work the same way, we can put that in the base class.
Then, linux can override and do it's fancy thing.

ptrace(2) PT_IO call is our local equivalent call.

10. __WALL and __WNOTHREAD are Linux specific, but they have their
counterparts.

We should probably have a waitpid wrapper, which adds any os-specific
flags if necessary. We can put the EINTR handling there as well to
make it's usage easier.

NetBSD ships with wait(2), wait3(2), wait4(2), wait6(2), waitid(2),
waitpid(2).

Perhaps wait4(2) or wait6(2) could be a better choice as they offer more
features, but it's an option for later.

11. The cpu_set_t structure and appropriate functions have similar
counterparts on NetBSD.

This is only used to work around a bug in the linux arm64 kernels. I
don't think you need to worry yourself with that. It can stay hidden
in NativeThreadLinux::SingleStep

Acknowledged.

12. No <sys/procfs.h> and no dependency of procfs (/proc) is acceptable,
everything shall be accessible through ptrace(2) and sysctl(7).

We'll need to check whether the appropriate interfaces are in place to
abstract this (I expect it to be the case), and add new ones if
necessary.

13. personality.h - unsupported as header/function call, compatibility
with other OSes (mostly Linux) implemented on syscall level.

This was already dead code, and I have removed it.

Acknowledged.

14. Process, system thread (lwp) and POSIX (pthread_t) thread are not
the same on NetBSD, unlike some other systems and cannot be mixed.

I believe the code has already good separation between thread and
process IDs, and doesn't use pthread_t, so this shouldn't be a
problem. NetBSD-specific pthread_t debugging code can be contained in
the NetBSD class.

Some code for NetBSD expect pthread_t which, as discussed, is wrong and
should be lwpid_t. And in case of requesting pthread_t specific data we
want to query with the lwpid_t key.

The currently missing features on the NetBSD side don't stop us from
making a functional implementation, lacing interfaces might be added
after getting the core part to work.

Agreed. The only thing that slightly worries me is the lack of
execve() tracing capability, if I understood correctly. While it
probably may be possible to work without it. I'd think about adding it
nonetheless.

I'm going to research it now and in case of required - as in
implementing a debugger much easier -- I will go for it and add support.

good luck,
pl

Thank you for your insight.

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

This value is currently only used in logging code, so we can just
remove it from the code base. However, it's a useful thing to have for
the future, so it may be worth making sure the NetBSD kernel supports
it.

I was wondering whether waitid(2) or wait6(2) could be used there, as
they return siginfo_t. If so, NetBSD does not need dedicated ptrace(2)
entry.

Note that there are two siginfo_t structures in action here. One is
the siginfo_t the *inferior* gets as a result of some action (e.g.
kill(), raise(), hitting an int3, etc.). The other is the siginfo_t
corresponding to the SIGCHLD that the *debugger* gets when something
interesting happens to the inferior. (On linux at least ), waitid(2)
returns the second one. That one, however, generally does not contain
any useful information apart from the process ID. PTRACE_GETSIGINFO
returns the first one, and that one contains the interesting stuff
(the signal the inferior recieved, and in case of a SIGTRAP, the
information about the debug event is encoded there as well). This is
usually very important information for the debugger.

PTRACE_SETSIGINFO allows you to overwrite the signal that the inferior
would receive. It can be used to inject "fake" signals into the
inferior. That can be a useful feature from time to time, but
currently we do not support that (on linux we support injecting a
signal via an argument to PTRACE_CONTINUE, which is a weaker
implementation of this call, as it can only inject a signal number,
not the full siginfo_t struct). So you may want to implement this at
some point, but on the grand scale of things, it's not something very
important.

3. PTRACE_O_TRACEEXEC, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXIT -
equivalent to be implemented.

Do you mean "implemented in lldb-server" or "implemented in the
kernel"? Being notified when the inferior exec()s would definitely be
good. Tracing thread creation and exit is a nice-to-have but low
priority. The only reason we used it on linux is because that's the
only way to auto-attach to new threads, but I think that for you that
will happen automatically.

I mean implemented in the kernel.

Thread (lwp) creation and termination is currently detectable in FreeBSD
with a special event, if this is useful in the NetBSD context -- like a
user setting a break on this event explicitly -- I will add it to TODO
list. On NetBSD there is no need to explicitly start tracing new
threads, tracing is per process and it is composed of a bulk of threads
(lwp). POSIX threads are a layer with extra features built upon LWP.

BTW, are your debug registers per-process or per-thread? If they are
per thread, then you will need to hook thread creation so you can
inject the correct watchpoints and stuff, otherwise you will miss some
hits. If this is handled by the kernel, then you are probably fine.

There is also the the exect(3) call in our libc inherited from BSD4.2,
but it no longer works in a useful way. It used to singlestep execve(2)
call. I was thinking whether/how to make it useful again, like combine
in it execve(2) + PT_TRACE_ME + SIGSTOP/SIGTRAP on exec.

4. No tracing of VFORK events implemented.

5. Hardware assisted watchpoints (debug registers on amd64) have their
dedicated ptrace(2) API to set/unset watchpoints, they do not export raw
debug registers.

6. Other ptrace(2) calls have their equivalents on NetBSD
(PTRACE_PEEKUSER, PTRACE_POKEUSER etc).

Cool, I guess that means we can share (Read|Write)Memory(WithoutTrap|).

Functionality is the same, however the API is different.

Ok. If the api differs by too much, then we might as well keep them as
separate implementations. We'll see how it goes.

7. SIGTRAP has currently only two si_code values (specified by POSIX).

The code for decoding si_code values is already messy and in need of a
rewrite. I think the act of decoding si_code values will need to be
OS- (and maybe event architecture-) specific, but the actions taken
upon individual events should be quite similar.

I was wondering whether it is useful to return distinct si_code for
hardware assisted traps or PT_STEP. At the moment I ignored it.

If you are able to do that, then I'd recommend you go for it. It's
very useful to be able to figure out what caused the application to
stop.

Imagine the following situation: The user does a single-step and the
app stops with a SIGTRAP. What do you display to the user? Most likely
the SIGTRAP just means the single-step completed. However, any one of
the following things could happen:
- the instruction happened to trigger a watchpoint (you should report
that instead)
- the instruction happened to be the syscall instruction corresponding
to the raise(SIGTRAP) done by the application
- a random other application sent a SIGTRAP to your process

The more information we get, the easier it is to display something
meaningful to the user.

Agreed. The only thing that slightly worries me is the lack of
execve() tracing capability, if I understood correctly. While it
probably may be possible to work without it. I'd think about adding it
nonetheless.

I'm going to research it now and in case of required - as in
implementing a debugger much easier -- I will go for it and add support.

A debugger needs to know when the running image has changed, so that
it can e.g. rescan the symbol table and insert new breakpoints. I
think it would be quite hard to debug across an execve() without it.

cheers,
pl

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

This value is currently only used in logging code, so we can just
remove it from the code base. However, it's a useful thing to have for
the future, so it may be worth making sure the NetBSD kernel supports
it.

I was wondering whether waitid(2) or wait6(2) could be used there, as
they return siginfo_t. If so, NetBSD does not need dedicated ptrace(2)
entry.

Note that there are two siginfo_t structures in action here. One is
the siginfo_t the *inferior* gets as a result of some action (e.g.
kill(), raise(), hitting an int3, etc.). The other is the siginfo_t
corresponding to the SIGCHLD that the *debugger* gets when something
interesting happens to the inferior. (On linux at least ), waitid(2)
returns the second one. That one, however, generally does not contain
any useful information apart from the process ID. PTRACE_GETSIGINFO
returns the first one, and that one contains the interesting stuff
(the signal the inferior recieved, and in case of a SIGTRAP, the
information about the debug event is encoded there as well). This is
usually very important information for the debugger.

PTRACE_SETSIGINFO allows you to overwrite the signal that the inferior
would receive. It can be used to inject "fake" signals into the
inferior. That can be a useful feature from time to time, but
currently we do not support that (on linux we support injecting a
signal via an argument to PTRACE_CONTINUE, which is a weaker
implementation of this call, as it can only inject a signal number,
not the full siginfo_t struct). So you may want to implement this at
some point, but on the grand scale of things, it's not something very
important.

I see, thank you for your explanation! It looks useful, but let it keep
for later.

3. PTRACE_O_TRACEEXEC, PTRACE_O_TRACECLONE, PTRACE_O_TRACEEXIT -
equivalent to be implemented.

Do you mean "implemented in lldb-server" or "implemented in the
kernel"? Being notified when the inferior exec()s would definitely be
good. Tracing thread creation and exit is a nice-to-have but low
priority. The only reason we used it on linux is because that's the
only way to auto-attach to new threads, but I think that for you that
will happen automatically.

I mean implemented in the kernel.

Thread (lwp) creation and termination is currently detectable in FreeBSD
with a special event, if this is useful in the NetBSD context -- like a
user setting a break on this event explicitly -- I will add it to TODO
list. On NetBSD there is no need to explicitly start tracing new
threads, tracing is per process and it is composed of a bulk of threads
(lwp). POSIX threads are a layer with extra features built upon LWP.

BTW, are your debug registers per-process or per-thread? If they are
per thread, then you will need to hook thread creation so you can
inject the correct watchpoints and stuff, otherwise you will miss some
hits. If this is handled by the kernel, then you are probably fine.

Debug registers (watchpoints) are per-thread (lwp) and they are not
being inherited on thread's or process' forks. It's a valid use-case.

I just checked FreeBSD and there is PTRACE_LWP:

This event flag controls tracing of LWP kernel thread creation and
destruction. When this event is enabled, new LWPs will stop and report
an event with PL_FLAG_BORN set before executing their first instruction,
and exiting LWPs will stop and report an event with PL_FLAG_EXITED set
before completing their termination.

There is also the the exect(3) call in our libc inherited from BSD4.2,
but it no longer works in a useful way. It used to singlestep execve(2)
call. I was thinking whether/how to make it useful again, like combine
in it execve(2) + PT_TRACE_ME + SIGSTOP/SIGTRAP on exec.

4. No tracing of VFORK events implemented.

5. Hardware assisted watchpoints (debug registers on amd64) have their
dedicated ptrace(2) API to set/unset watchpoints, they do not export raw
debug registers.

6. Other ptrace(2) calls have their equivalents on NetBSD
(PTRACE_PEEKUSER, PTRACE_POKEUSER etc).

Cool, I guess that means we can share (Read|Write)Memory(WithoutTrap|).

Functionality is the same, however the API is different.

Ok. If the api differs by too much, then we might as well keep them as
separate implementations. We'll see how it goes.

We will see how it goes.

7. SIGTRAP has currently only two si_code values (specified by POSIX).

The code for decoding si_code values is already messy and in need of a
rewrite. I think the act of decoding si_code values will need to be
OS- (and maybe event architecture-) specific, but the actions taken
upon individual events should be quite similar.

I was wondering whether it is useful to return distinct si_code for
hardware assisted traps or PT_STEP. At the moment I ignored it.

If you are able to do that, then I'd recommend you go for it. It's
very useful to be able to figure out what caused the application to
stop.

It looks trivial to be implemented for x86, my original concern was
usefulness of this information.

My another concern was whether it's useful to keep PT_STEP and hardware
watchpoints enabled at the same time (before returning to userspace and
resuming a thread).

And third issue was whether this feature can be portable (property
retained) across capable ports (platforms).

Imagine the following situation: The user does a single-step and the
app stops with a SIGTRAP. What do you display to the user? Most likely
the SIGTRAP just means the single-step completed. However, any one of
the following things could happen:
- the instruction happened to trigger a watchpoint (you should report
that instead)
- the instruction happened to be the syscall instruction corresponding
to the raise(SIGTRAP) done by the application
- a random other application sent a SIGTRAP to your process

The more information we get, the easier it is to display something
meaningful to the user.

I makes sense. I think we could move it for TODO list for later and make
the core functional first.

Agreed. The only thing that slightly worries me is the lack of
execve() tracing capability, if I understood correctly. While it
probably may be possible to work without it. I'd think about adding it
nonetheless.

I'm going to research it now and in case of required - as in
implementing a debugger much easier -- I will go for it and add support.

A debugger needs to know when the running image has changed, so that
it can e.g. rescan the symbol table and insert new breakpoints. I
think it would be quite hard to debug across an execve() without it.

There is also PT_SYSCALL to catch each syscall... so maybe add a
dedicated filter to tap interesting system calls. It would handle thread
(lwp) events and actions like execve(2).

I don't think that performance is critical for tracee -- as breaking on
each syscall slows the things down. I'm prioritizing reusing of already
existing interfaces.

I will research how is it done with GDB.

Hello,

For the reference in this thread, I've posted a blog entry on the NetBSD
Foundation site with a summary of the interfaces we were discussing in
this thread:

http://blog.netbsd.org/tnf/entry/summary_of_the_preliminary_lldb

This report covers the topics discussed in this E-mail thread.

I've got some thoughts on redefining current generic interface and
making NativeThreadX optional, but let's see what will happen when we
will get aboard appropriate support for still missing features
(registers' accessors, breakpoints, watchpoints etc).

2. PTRACE_SETSIGINFO - equivalent currently unsupported, I will need to
add support for it in ptrace(2).

This value is currently only used in logging code, so we can just
remove it from the code base. However, it's a useful thing to have for
the future, so it may be worth making sure the NetBSD kernel supports
it.

I was wondering whether waitid(2) or wait6(2) could be used there, as
they return siginfo_t. If so, NetBSD does not need dedicated ptrace(2)
entry.

Note that there are two siginfo_t structures in action here. One is
the siginfo_t the *inferior* gets as a result of some action (e.g.
kill(), raise(), hitting an int3, etc.). The other is the siginfo_t
corresponding to the SIGCHLD that the *debugger* gets when something
interesting happens to the inferior. (On linux at least ), waitid(2)
returns the second one. That one, however, generally does not contain
any useful information apart from the process ID. PTRACE_GETSIGINFO
returns the first one, and that one contains the interesting stuff
(the signal the inferior recieved, and in case of a SIGTRAP, the
information about the debug event is encoded there as well). This is
usually very important information for the debugger.

PTRACE_SETSIGINFO allows you to overwrite the signal that the inferior
would receive. It can be used to inject "fake" signals into the
inferior. That can be a useful feature from time to time, but
currently we do not support that (on linux we support injecting a
signal via an argument to PTRACE_CONTINUE, which is a weaker
implementation of this call, as it can only inject a signal number,
not the full siginfo_t struct). So you may want to implement this at
some point, but on the grand scale of things, it's not something very
important.

I see, thank you for your explanation! It looks useful, but let it keep
for later.

As per-blog entry, there is now an interface for it in NetBSD with
PT_GETSIGINFO and PT_SETSIGINFO.

I've published a short report for the previous milestone, with goals for
the ongoing one.

   "The first patch-bulk upstreamed to LLDB"

http://blog.netbsd.org/tnf/entry/the_first_patch_bulk_upstreamed

The next one will turn to be more exciting as I plan to start with
implementation of accessors for machine context registers, followed up
with breakpoints.