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