[lldb-dev] Creating a breakpoint on a target with no process

Zachary Turner zturner at google.com
Thu Dec 4 14:35:41 PST 2014

On Thu Dec 04 2014 at 2:29:45 PM Greg Clayton <gclayton at apple.com> wrote:

> > On Dec 4, 2014, at 12:27 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > I started working on implementing a DynamicLoader plugin.
> >
> > While it's indeed quite simple, I still have some questions about why
> it's necessary to make shared library load/unloading work.
> >
> > I do understand the use case for other platforms, because there is a
> non-trivial amount of work required to detect shared library loading /
> unloading.  On Windows however, there is no work involved because the OS
> tells us at every occurrence of a shared library load or unload.  As a
> result, my DynamicLoader implementation basically boils down to some code
> like this in my process plugin
> >
> > if (event is a module load)
> >     dynamic_loader->NotifyModuleLoad(module);
> > else if (event is a module unload)
> >     dynamic_loader->NotifyModuleUnload(module);
> >
> > In each of these two methods, all I do is construct an empty ModuleList,
> add a single item to it, set the load address, and call
> GetTarget().ModulesDidLoad() or GetTarget().ModulesDidUnload().
> >
> > So either way I'm calling ModulesDidLoad() / ModulesDidUnload()
> directly, it's just am I having the Process plugin tell the DynamicLoader
> to do it, or am I having the process do it itself.  Whichever one does it
> though, it's the same few lines of code to prepare the call to
> ModulesDidLoad().
> That is indeed simple and if you have all the info you need in the message
> that is sent to the data to the handle, then it doesn't make sense to do
> this in the dynamic loader. For us, we can use the same dynamic loader
> plug-in with different Process subclasses since it just uses the process to
> find a symbol and read data via memory reads. So our dynamic loader will
> work on core files with ProcessMachCore and it also works with
> ProcessGDBRemote. In your case, you are getting messages straight from your
> process runner via the OS which is quite different than any other platform,
> so don't change anything, but you can continue to do what you do by
> directly doing the load/unload from the process plug-in and have your
> DynamicLoaderWindows just not do anything.
> One thing you might actually need to do in the DynamicLoaderWindows is
> find out all the shared libraries that are loaded when you attach to a
> process. When you attach to a running process in windows, does it give you
> a bunch of callbacks for each shared library that is already loaded? Just
> like when you are running and a shared library loads/unloads? Or must you
> discover them in a different way?
That's a good question and it's actually still an unknown.  There's still a
bit more work I need to do before being able to attach to a process.  It
might give me a module load notification for each existing module right
when I load, and I might have to enumerate them.  Even if I have to
enumerate them, the code to do that is pretty simple.  But it might make
sense to put that code in the DynamicLoader::DidAttach method anyway.  For
that matter, it might also make sense to add the main executable's module
in DynamicLoader::DidLaunch, if nothing else for consistency.  But modules
that load or unload while the debugger is connected seem to be a natural
fit to just calling ModulesDidLoad.

> >
> > One more question: You said this: "the MacOSX version finds the global
> list of shared libraries that are loaded, iterates through them, seaches
> for any modules that are in the target, removes any images from the target
> that aren't loaded, then sets the section load address for all sections in
> all modules to the correct value".
> Indeed.
> >
> > Just to clarify some terminology, are "shared library", "module", and
> "image" here the same thing?
> Yes.
> > Why would you have a shared library that is loaded but not in the target?
> You wouldn't, but you might have said "file a.out" on the command line,
> and from just inspecting the "a.out" mach-o file it added a bunch of
> modules to your target. Before you run you would have:
> (lldb) image list
> /tmp/a.out
> /usr/lib/libc.dylib
> /usr/lib/libxml2.dylib
> But when you run you specified DYLD_LIBRARY_PATH=/tmp/my_dylibs in the
> environement so when you actually attach to "a.out" you really have a
> different set of shared libraries:
> (lldb) image list
> /tmp/a.out
> /tmp/my_dylibs/libc.dylib
> /usr/lib/libxml2.dylib
> We we start out with a target that contains the first three images, but
> when we run and get our first batch of shared library loaded notifications
> we look for "/tmp/a.out" and leave it because it is correct and set its
> load location, we remove the "/tmp/lib/libc.dylib" from the image list in
> the target and add the "/tmp/my_dylibs/libc.dylib" and then set its load
> address, and then we look for "/usr/lib/libxml2.dylib" and keep it because
> it is correct and set its load addresses.
> >  Where else would it be?
> See above.
> >  As for setting the section load address for all sections, it sounds
> like this is the same as just calling module->SetModuleLoadAddress() to the
> load address of the entire shared library.  Is this correct?
> If your system always loads all sections by sliding them all by constant
> amounts, then yes. On MacOSX, all shared libraries in the shared cache will
> have all their sections moved separately. So we need to load add sections
> to completely different addresses (we don't just add a constant slide to
> all of them like module->SetModuleLoadAddress() does). Some sections aren't
> loaded sometimes (like the "__LINKEDIT" section isn't always loaded for our
> kernel). So you need to do what you need to do to load things correctly on
> your system.

Makes sense, thanks.  Last question.  When a module loads the notification
I get contains the load address.  So I call module->SetLoadAddress(x), and
then ModulesDidLoad, at some point in the future I'm going to get a module
unloaded event with the only parameter being x.  It doesn't seem there's an
easy way for me to find the ModuleSP in the target given only this value.
Do I need to just keep my own map in the DynamicLoader or in the Process
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20141204/48cac802/attachment.html>

More information about the lldb-dev mailing list