[lldb-dev] lldb -- architecture level question -- linux v. darwin
jingham at apple.com
Wed Mar 16 12:59:58 PDT 2011
To make this be an "all lldb" solution, some parts of the way that lldb does expression evaluation would have to be enhanced. Right now, for instance, we compile, JIT and evaluate expressions, and then clean up after ourselves completely. We don't insert code and, for instance, put it in a nice bundle with symbols et al and tell the linker about it so anybody else could reuse it. We just inject a raw blob of code, set the pc somewhere and go. So even if we didn't clean up the injected code once the execution is complete, there isn't any way to reuse the functionality you've compiled up. Actually this is a bit of a lie, there are a couple of fairly special purpose mechanisms to do this (ClangFunction, and ClangUtilityFunction) but you have to be inside lldb to use them...
We also don't generate debug information, 'cause in this context it wouldn't make sense to. And there isn't a way to say "evaluate this expression in language X" if X is not C/C++/ObjC…
We certainly want to come up with a clean way to reuse functions defined in "expressions" from lldb, though that's not at the front of our queue. Making them debuggable would also be important: once you allow this sort of thing it's bound to grow in complexity to the point where you'll need to be able to debug it. And we would be happy to support other languages, though at present we're tied to Clang as our expression front end…
Another way to do this would be to build a little code injection rig and insert it into the debuggee - for instance by having a dylib that does this job and calling "dlopen" from the debugger to insert it. Then when you wanted to insert some new code, you would put it in a file, and call some "MyRigInsertCode" type routine in your dylib. Then that would make a little bundle, stuff it into the target, tell the loader about it (which would tell the debugger about it) and then those new functions would be available in further expressions you write from the debugger.
On Mar 16, 2011, at 12:30 PM, Jason E. Aten wrote:
> On Wed, Mar 16, 2011 at 2:18 PM, Reid Kleckner <reid.kleckner at gmail.com> wrote:
> If your use
> case is to do your own codegen and then throw some debug info over to
> the debugger, you'll have to be able to generate it (ie DWARF) and
> wrap it in the native object file for your platform in memory. LLVM
> has some code to produce ELF, so I used that.* At the time, I wasn't
> worried about other platforms.
> * Actually, that code for ELF generation is old and this interface is
> the last user of it so far as I know.
> Great! Yes, that is exactly my use case: Suppose I am stopped in the middle of code, in LLDB,
> with a variable that has a debugger symbol for a collection that needs to be sorted differently than it is at the moment, in order
> to determine if the code is producing the correct collection.
> So I'd like to be able to define a new sorting function from the command line (like the Clang Expression stuff I think let's one do), but
> in this case it's in a non-C++ language that I have a compiler for. Then JIT-compile that new "how to sort" function, and have it talk to already
> defined data and code, and have it run from the within the debugger. After the sort, be able (from LLDB) be able to re-inspect the
> output of the collection.
> Does this make sense? Are there obstacles that I'm not envisioning? Any critique or commentary welcome.
> Since I'm on Linux, ELF works perfectly, and I already have ELF codegen that produces Ahead-of-time compiled ELF's now, I just need to figure out how to convert that to use the JIT engine instead, I presume. I assume I would need to produce an in-memory .so dynamically loaded library format file then. Does that sound right?
> Lastly, could the JITDebugRegisterer.(cpp|h) functionality be made a part of the DNB.h interface?
> On Wed, Mar 16, 2011 at 3:02 PM, Jason E. Aten <j.e.aten at gmail.com> wrote:
> > Thank you Reid, that makes alot of sense now. Is there an API to the JIT
> > functionality? If so,
> > could you point out where in the code base it lives, and if there are
> > examples of clients (how to
> > use it?)
> > Thanks!
> > Jason
> > On Wed, Mar 16, 2011 at 1:58 PM, Reid Kleckner <reid.kleckner at gmail.com>
> > wrote:
> >> On Wed, Mar 16, 2011 at 2:52 PM, Jason E. Aten <j.e.aten at gmail.com> wrote:
> >> > Jim, thank you--that makes alot of sense. I hadn't thought through the
> >> > signal implications. And re-reading Reid's post, he does make it clear
> >> > that
> >> > the JIT-code injection is somehow a part of an interprocess
> >> > communication.
> >> > The question then becomes, does the DNB.h protocol support the JIT-code
> >> > injection, or if not, could that be a part of it?
> >> Yup, it works similar to the way debuggers find out about dynamically
> >> loaded libraries. There's a particular loader stub that gets called
> >> after every library load or unload. Debuggers put a breakpoint on it
> >> to stop the inferior process and re-read the list of loaded libraries
> >> with remote memory examination routines, so there's your (hacky) IPC.
> >> Reid
> > --
> > Jason E. Aten, Ph.D.
> Jason E. Aten, Ph.D.
More information about the lldb-dev