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

Zachary Turner zturner at google.com
Tue Dec 2 16:09:08 PST 2014


Yes, the target is stopped, it's just that I'm not on LLDB's main thread.
That was the only concern.

On Tue Dec 02 2014 at 4:06:59 PM Greg Clayton <gclayton at apple.com> wrote:

> You really want your shared library loads to be synchronous. There has to
> be a way to stop your target when a shared library loads? If not, you might
> miss your breakpoint if it is in a "PluginInitialize()" call and you stop
> the target after receiving the shared library load/unload notification. So
> try as hard as you can to make this happen synchronously...
>
> > On Dec 2, 2014, at 3:10 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > Sounds good.  I tested with calling ModulesDidLoad() directly and it
> seems to resolve the breakpoints, so now that I know that that was the
> issue blocking me, I can try to do it the "right" way via a DynamicLoader
> plugin.
> >
> > One thing I'm uncertain about though, is that I get the notification
> asynchronously instead of going through this breakpoint / callback
> mechanism.  So I can send a notification from my event listener thread to
> the DynamicLoader plugin, but it's not going to be on the main thread.
> Will this cause a problem?
> >
> > On Tue Dec 02 2014 at 2:58:57 PM Greg Clayton <gclayton at apple.com>
> wrote:
> > You must implement a DynamicLoaderWindows. Shared library
> loading/unloading won't work otherwise.
> >
> > The theory is simple: after launching or attaching, the plug-in will
> find the list of shared libraries to get the initial state. Also when you
> program dynamically loads/unloads DLLs, you need to update anything that
> changed (load/unload sections for things that got loaded/unloaded).
> >
> > Please do NOT call ModulesDidLoad directly. You can do this temporarily,
> but you really do need a dynamic loader.
> >
> > The MacOSX version finds the global list of shared libraries that are
> loaded, iterates though them, searches for and adds any modules that are in
> the target, removes any images from the target that aren't loaded, then
> sets the section load addresses for all sections in all modules to the
> correct value and then calls ModulesDidLoad(). This causes all breakpoints
> to get resolved.
> >
> > We then set a breakpoint at a location that gets hit after /usr/lib/dyld
> loads/unloads new shared libraries so we can keep up. This is a synchronous
> breakpoint where we detect the new shared libraries that were
> loaded/unloaded, we add/remove modules and set them to the loaded or
> unloaded and then continue. So it is a very easy plug-in to write and is
> required so that dynamic plug-in loading/unloaded can track breakpoints
> correctly.
> >
> > Greg
> >
> >
> > > On Dec 2, 2014, at 2:29 PM, Zachary Turner <zturner at google.com> wrote:
> > >
> > > Thanks.  For now I'll experiment with your suggestion of just calling
> ModulesDidLoad directly in the callback, since getting the actual
> notification that a library is loaded is trivial on Windows and all the
> work is done for us by the OS.  Is it safe to update the module list from a
> thread other than the main thread?  All threads of the inferior will be
> stopped while I process this notification, but I know for example that with
> thread creation / thread exit, I have to maintain this thread list, and
> then only in UpdateThreadList do I actually update the thread list on the
> target.  Is this restriction not the same with the module list?
> > >
> > > One more question, how do I find the module that is loaded at a
> specific address?  When this shared library is unloaded, the only
> information I have is its load address, but the only method for getting a
> Module from the target is to call GetSharedModule() with a ModuleSpec,
> which I won't have.  Is there a way to search based only on the load
> address?
> > >
> > > On Tue Dec 02 2014 at 2:19:33 PM <jingham at apple.com> wrote:
> > > The dynamic loader plugin has a couple of different jobs.
> > >
> > > The one that is relevant to your question is that it is responsible
> for hooking up the mechanism whereby lldb gets notified of new shared
> library loads.  It gets called when we attach or launch a process, at which
> point it is supposed to make whatever instrumentation is needed for
> tracking the loader.  On most platforms this is done by setting some
> breakpoint in the correct place in the loader code and then decoding the
> meaning of the event when the breakpoint to gets hit (load or unload, what
> got loaded, etc.)  Since this is often a non-trivial bit of code, and one
> that changes as the versions of the OS go by, so it seemed worthwhile to
> have it be a separate module.  If you wanted to use this model for Windows,
> you would have your DynamicLoader plugin register the callback for the
> "Shared libraries changed" event that your main loop is getting, and then
> call into that to process the event.
> > >
> > > In the short term you can probably just call ModulesDidLoad in the
> code you have below.  Note, this isn't done in GetSharedModule because it
> is expensive to go looking through new modules for breakpoints, so you
> don't want to hang it off some call that might be called many times.
> Instead we have an explicit "Okay here's the set of new libraries" type
> call.
> > >
> > > There isn't good documentation on this in the code, which we should
> fix.  Also, it would arguably be cleaner to separate out the "discover new
> modules" part of the DynamicLoader, and the "Make these new modules work
> correctly" into separate steps within the Dynamic loader plugin.  The
> former is going to be specific to the various subclasses, but the latter
> job is pretty generic.  Then each port would know it had to call the
> DynamicLoader::RegisterNewModules or whatever it was when it was done
> with the platform specific side of registering them.  But since that job
> currently consists of calling Target::ModulesDidLoad, we haven't been
> motivated to move the code around to do this.
> > >
> > > The other main dynamic loader job is not relevant to your question,
> but for completeness sake is that it is also the place where knowledge of
> the library intercalling mechanism resides.  Most importantly, most
> inter-library calls are implemented using some sort of stub that
> trampolines over to the actual call. That stub generally doesn't have debug
> information, so the normal behavior of "next" when it lands in the stub
> would be to say "I've stepped into code with no debug information, so I'll
> step out".  But if the stub was going to resolve to a routine that did have
> debug info, that would be the wrong behavior.  So before we decide to step
> out of unknown code, we always ask the current dynamic loader plugin to
> "GetStepThroughTrampolinePlan" to see if it knows how to get from this PC
> to somewhere more interesting, and if so to return a plan that does that
> job.
> > >
> > > Jim
> > >
> > >
> > > > On Dec 2, 2014, at 1:15 PM, Zachary Turner <zturner at google.com>
> wrote:
> > > >
> > > > I actually don't even have a dynamic loader plugin implemented at
> all.  I wasn't completely sure what the purpose of it was.  I saw that
> Virgile had implemented one in his original patch to get debugging working
> on Windows [https://github.com/xen2/lldb/commit/
> 515956244784a9162183a6135068e893ba994532], but it did very little actual
> work, and in particular does not seem to do anything related to what you
> are suggesting above.
> > > >
> > > > As for adding new modules when they load, basically this is the
> entirety of what I do.
> > > >
> > > >     Error error;
> > > >     ModuleSP module = GetTarget().GetSharedModule(module_spec,
> &error);
> > > >     module->SetLoadAddress(GetTarget(), module_addr, false, false);
> > > >
> > > > However, as mentioned I don't do this from a DynamicLoader plugin.
> Instead I just run this code directly from the same background thread that
> gets other debug events from the process, such as thread creation,
> exceptions, etc.
> > > >
> > > > I guess can you elaborate a little bit on the interaction between
> the DynamicLoader plugin and the process plugin, and the responsibilities
> of each?
> > > >
> > > > On Tue Dec 02 2014 at 1:07:35 PM <jingham at apple.com> wrote:
> > > > It is the responsibility of the dynamic loader plugin to tell the
> breakpoints to re-scan for new locations when shared libraries get added to
> the process.  You should do this by collecting a list of the added
> libraries, and calling:
> > > >
> > > > m_process->GetTarget().ModulesDidLoad(added_list);
> > > >
> > > > How are you adding new modules as they get loaded?
> > > >
> > > > Jim
> > > >
> > > >
> > > > > On Dec 2, 2014, at 12:45 PM, Zachary Turner <zturner at google.com>
> wrote:
> > > > >
> > > > > In my effort to get tests working on Windows, I've run across an
> issue with test\expression_command\timeout\TestCallWithTimeout.py ::
> TestCallWithTimeout.ExprCommandWithTimeoutsTestCase
> > > > >
> > > > > This test creates a target and immediately puts a breakpoint on it
> before attempting to launch the process.  Is this something that is
> supposed to work?  BreakpointLocation::ResolveBreakpointSite() contains
> this line:
> > > > >
> > > > >     Process *process = m_owner.GetTarget().GetProcessSP().get();
> > > > >     if (process == NULL)
> > > > >         return false;
> > > > >
> > > > > So naturally the breakpoint site cannot be resolved because there
> is no process.  The end result of this is that this breakpoint never gets
> hit and the test fails.
> > > > >
> > > > > Presumably this test works on other platforms, so any tips as to
> where I should look to track down this bug on Windows?
> > > > > _______________________________________________
> > > > > lldb-dev mailing list
> > > > > lldb-dev at cs.uiuc.edu
> > > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> > > >
> > >
> > > _______________________________________________
> > > lldb-dev mailing list
> > > lldb-dev at cs.uiuc.edu
> > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20141203/edfefc27/attachment.html>


More information about the lldb-dev mailing list