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 <ztur...@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 <gclay...@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 <ztur...@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 <jing...@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 <ztur...@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 <jing...@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 <ztur...@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@cs.uiuc.edu
> > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> > >
> >
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev@cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> 


_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to