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

Kamil Rytarowski via lldb-dev lldb-dev at lists.llvm.org
Mon Feb 13 19:39:14 PST 2017


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.

On 23.01.2017 15:21, Kamil Rytarowski wrote:
> 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/20170214/42121723/attachment.sig>


More information about the lldb-dev mailing list