[lldb-dev] Shared Process plugin between Linux and BSD

Pavel Labath via lldb-dev lldb-dev at lists.llvm.org
Thu Dec 15 07:08:37 PST 2016


On 15 December 2016 at 14:14, Kamil Rytarowski <n54 at gmx.com> wrote:
> On 15.12.2016 14:14, Pavel Labath wrote:
>>>>
>>>> 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


More information about the lldb-dev mailing list