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

Kamil Rytarowski via lldb-dev lldb-dev at lists.llvm.org
Mon Jan 23 06:21:16 PST 2017


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).

On 15.12.2016 17:21, Kamil Rytarowski wrote:
> On 15.12.2016 16:08, Pavel Labath wrote:
>> 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.
>>
>>
> 
> 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.

>>>
>>>>>>
>>>>>> 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.
> 
>> cheers,
>> pl
>>
> 
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20170123/9d09fc52/attachment.sig>


More information about the lldb-dev mailing list