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