[lldb-dev] lldb -- architecture level question -- linux v. darwin

Jason E. Aten j.e.aten at gmail.com
Wed Mar 16 11:00:31 PDT 2011

Thank you Greg for the detailed reply.  I read it with great interest.

The main thing that got me interested in LLDB in the first place was the
potential to be able to (add the capability to) JIT-up code from the command
line, and inject that new code into a running process (after going through
the Kaleidoscope tutorial and reading the post (quoted below) from Reid

To this end, I'm actually most interested in exploring the very un-remote
direction, where the debugger and the debuggee are as close as poosible,
even in the same process space (as would probably be necessary). The aim is
to get minimum re-compile times to support JIT-based everything, for an
incremental style development with JIT-support, and simultaneous access to
debugger level ability to step through the just JIT-ed code. The goal would
be to obtain something akin to the rapid LISP development environment with
hot-swappable functions, but rather than interpreted, have it be llvm

But perhaps my thoughts on adding this kind of feature to LLDB are not
realistic.  If LLDB always needs its target process to be a separate process
(how baked in is that assumption, by the way, I guess that is really a key
and important question!?), then I may not be able to implement the
description above, inspired by Reid Kleckners post below.


Written by Reid Kleckner


Without special runtime support, debugging dynamically generated code with
GDB (as well as most debuggers) can be quite painful. Debuggers generally
read debug information from the object file of the code, but for JITed code,
there is no such file to look for.

Depending on the architecture, this can impact the debugging experience in
different ways. For example, on most 32-bit x86 architectures, you can
simply compile with -fno-omit-frame-pointer for GCC and -disable-fp-elim for
LLVM. When GDB creates a backtrace, it can properly unwind the stack, but
the stack frames owned by JITed code have ??'s instead of the appropriate
symbol name. However, on Linux x86_64 in particular, GDB relies on the DWARF
call frame address (CFA) debug information to unwind the stack, so even if
you compile your program to leave the frame pointer untouched, GDB will
usually be unable to unwind the stack past any JITed code stack frames.

In order to communicate the necessary debug info to GDB, an interface for
registering JITed code with debuggers has been designed and implemented for
GDB and LLVM. At a high level, *whenever LLVM generates new machine code, it
also generates an object file in memory containing the debug information.
LLVM then adds the object file to the global list of object files and calls
a special function **(__jit_debug_register_code)** marked noinline that GDB
knows about. When GDB attaches to a process, it puts a breakpoint in this
function and loads all of the object files in the global list. When LLVM
calls the registration function, GDB catches the breakpoint signal, loads
the new object file from LLVM's memory, and resumes the execution. In this
way, GDB can get the necessary debug information.*

At the time of this writing, LLVM only supports architectures that use ELF
object files and it only generates symbols and DWARF CFA information.
However, it would be easy to add more information to the object file, so we
don't need to coordinate with GDB to get better debug information.

On Wed, Mar 16, 2011 at 12:40 PM, Greg Clayton <gclayton at apple.com> wrote:

> See my other reply to the previous thread on this subject.
> To quickly summarize why we use debugserver on macosx:
> - If we are always debugging remotely even when debugging locally, adding
> remote debugging for MacOSX comes for free and we don't need to test local
> vs remote debugging.
> - Having a separate process be the parent of an inferior process helps to
> isolate the "lldb" binary from bad things
> On Mar 16, 2011, at 10:14 AM, Jason E. Aten wrote:
> > Dear Steve and lldb-dev,
> >
> > (starting a new thread to give a better, more appropriate, thread title)
> >
> > I've investigated a little bit more and I am coming to understand there
> is a big difference at the moment in how lldb initiates target processes in
> darwin vs linux (see the comparative ps output details below).  Perhaps it
> is more direct on linux in order to avoid having to port the debugserver?
> >
> > Any insight into plans for lldb on linux would be appreciated.  I do see
> there are significant architectural differences at the moment, in that lldb
> on darwin goes through the debugserver process.  I wonder if that is
> intended as a temporary quick fix, or done with an eye to simplification.
>  e.g. I don't know, but perhaps it is much simpler to ptrace directly on
> linux than to use a separate process?  I'm pretty clueless here, and just
> starting to explore lldb on linux, so feel free to point me towards
> background threads or information I might wish to review.
> >
> > Thanks everyone!
> >
> > cheers,
> > Jason
> >
> >
> > details:
> >
> > ### On darwin, lldb starts a debugserver child process, and debugserver
> in turn starts a child process to contain the debug target a.out.
> >
> >  UID   PID  PPID
> >                                                    bash
> >                                                     |
> >                                                     V
> >  2086 42103 22537   0   0:00.07 ttyp0      0:00.16 ../lldb a.out
> >                                                     |
> >                                                     V
> >  2086 42104 42103   0   0:00.01 ??         0:00.02
> /Users/jaten/pkg/llvm+lldb+ldc/llvm-2.8/tools/lldb/build/Debug/LLDB.framework/Versions/A/Resources/debugserver
> localhost:11358 --native-regs --setsid
> >                                                     |
> >                                                     V
> >  2086 42105 42104   0   0:00.00 ??         0:00.00
> /Users/jaten/pkg/llvm+lldb+ldc/llvm-2.8/tools/lldb/build/Debug/test-lldb/a.out
> >
> >
> > ### On linux, at the moment, what I see in contrast is that lldb is the
> direct parent of the debug target (a.out here).
> >
> > jaten     4532  0.0  0.3  25752  8160 pts/3    Ss   03:59   0:01
>      |       \_ /bin/bash --noediting -i
> > jaten    22645  0.6  0.8 148260 18256 pts/3    Sl+  11:57   0:00
>      |       |   \_ ./lldb test-lldb/a.out
> > jaten    22650  0.0  0.0  11728   960 pts/11   Ts+  11:58   0:00
>      |       |       \_
> /home/jaten/pkg/latest-svn-llvm/llvm-build-r127600-with-lldb/Release+Debug+Profile+Asserts/bin/test-lldb/a.out
> >
> >
> > On Wed, Mar 16, 2011 at 9:40 AM, Jason E. Aten <j.e.aten at gmail.com>
> wrote:
> > On Mon, Mar 14, 2011 at 11:11 PM, Stephen Wilson <wilsons at start.ca>
> wrote:
> > Well, in a nutshell you would need to implement something similar to
> > what ProcessLinux::DoLaunch does, but in this case you want things to
> > boil down to a ptrace(ATTACH) instead of a fork() + ptrace(TRACEME).
> > The basic sketch would be:
> >   - Define a new ProcessMonitor ctor that takes a pid as argument.
> >   - Define ProcessMonitor::Attach which does the actual ptrace magic.
> >   - Write a another StartOperationThread method that takes a (new)
> >     AttachArgs struct as argument (could just contain the pid for now)
> >     and sets up the monitoring business in essentially the same way as
> >     the current launch-based code does.  Probably rename
> >     OperationThread to LaunchOpThread or similar and write your own
> >     AttachOpThread analog.
> > It would certainly be nice to have that implemented.  I do not see
> > anything that would cause any complications off hand, and it should
> > remain fairly isolated from all the other work that needs to happen wrt
> > linux support.
> >
> >
> > Thanks Steve!  I scoped out the work a little bit, mostly by stepping
> through in the debuggers both the Xcode version and the current Linux
> version.  Btw it looks like the current version of lldb has been incremented
> (now r127600), which is very good news.
> >
> > I note that the main contrast is this: the darwin built lldb uses the
> ProcessGDBRemote class, implemented in the
> "llvm/tools/lldb/source/Plugins/Process/gdb-remote" directory, rather than
> ProcessLinux.
> >
> > The curious thing is: when I look through the gdb-remote code, there are
> only two lines that are #ifdef APPLE.  It seems fairly reusable.
> >
> > My naive question then is, why not just reuse the ProcessGDBRemote code
> for Linux as well?   There's probably higher level design issues that I'm
> not familiar with, so anyone on lldb-dev should feel free to chime in here.
>  The second lazy inclination is to just port that code to linux if it must
> go in it's own directory.
> >
> > Let me know what you think.  I'm probably asking silly questions, but I'm
> just trying to get my bearings. Please bear with me! :-)
> >
> > Thanks,
> > Jason
> >
> > p.s. the one thing that kept me from trying this directly was figuring
> out where in the Makefile system this got chosen, because by default on
> linux, the gdb-remote directory isn't built.  If anyone knows where this
> controlled, please point it out. Thank you!
> >
> >
> >
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Jason E. Aten, Ph.D.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20110316/8854f7ae/attachment.html>

More information about the lldb-dev mailing list