This is an archive of the discontinued LLVM Phabricator instance.

Add __lldb_init_module_with_target for use when sourcing modules for a target
Needs ReviewPublic

Authored by jingham on Mar 15 2023, 10:16 AM.

Details

Summary

We load python modules in two main ways: through command script import and automatically when we read in a dSYM and find a scripting resource in the dSYM. The latter case has a slight flaw currently which is that when the scripting resource from the dSYM is loaded, the target it's being loaded for is in the process of being created, so the module being imported has no way of knowing what that target is. Even if the debugger had selected this new target before loading the scripting resource, it would still be relying on that being the "currently selected target" which is racy. It's better to do this explicitly.

This patch adds a detector for an optional:

__lldb_init_module_with_target

and if that is present it will run that routine - passing in the target - before running __lldb_init_module.

I considered making an overload of __lldb_init_module that also passed in the target, but that trick seems to end up being confusing. And this will allow more convenient "dual use" modules, where if you are being sourced for a target you can prime the state for the regular init, and if not, then run the regular init.

Diff Detail

Event Timeline

jingham created this revision.Mar 15 2023, 10:16 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 10:16 AM
jingham requested review of this revision.Mar 15 2023, 10:16 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 15 2023, 10:16 AM

Thanks for adding this, Jim. This is one of those things that comes up one in a while when it confuses our users. It's great we'll be able to help them adopt this.

lldb/bindings/python/python-wrapper.swig
1031–1048

I'm surprised we might call both. The way I expected this to work is that if __lldb_init_module_with_target is defined, that's what we use if wee have a target and otherwise fall back to __lldb_init_module assuming it's defined.

What's the benefit of calling both? Do you expect the implementation to be different? Or do you think it's more likely that the implementations will be similar, just one having access to the target?

bulbazord added inline comments.Mar 15 2023, 11:46 AM
lldb/bindings/python/python-wrapper.swig
1031–1048

I can see the advantage to calling both: The use of __lldb_init_module_with_target can be used to set up things specific to your target and __lldb_init_module can be used for more general things. That being said, you should be able to do everything with __lldb_init_module_with_target since if you have a target, you should have a debugger too.

Whatever we choose to go with, the behavior should be explicitly documented here: https://lldb.llvm.org/use/python-reference.html (llvm-project/lldb/docs/use/python-reference.rst). We already document one, we should be documenting this one and the expected behavior when both are present.

1056

I know you didn't touch this but we're assuming debugger isn't nullptr here right? Should we add an assert? I know we'd have to be in a bad state to get to this point but an assertion may help catch that kind of thing if we do hit this point...

jingham added inline comments.Mar 15 2023, 5:00 PM
lldb/bindings/python/python-wrapper.swig
1031–1048

How you would use this depends on how you expect your python module to be used.

  1. If your python module is only going to be sourced from a Scripting Resource in a Module, then you could just implement __lldb_init_module_with_target.
  1. If your python module is imported through command script import, then it will have to implement __lldb_init_module since it's really never initialized in the presence of a specific target, so I wouldn't have a valid target to pass in. I don't want to pass in something like the "currently selected target" in this case just so there's something you can get a debugger from, that kinda lying...
  1. It's only if you want this python module to be used in either mode, or if you need to support lldb's that have and don't have this new API, that you need to have both API's. In that case, it seemed more useful to let the user separate the "I'm being initialized as a particular target's scripting resource" part of the initialization from the more general part.
1031–1048

I will add docs once we've decided the right way to do this.

1056

That doesn't seem to be the practice in this file for any of the shared pointer parameters that we call ToSWIGWrapper on. If we're going to start being more careful about this, we should do so consistently, which seems outside the scope of this patch.

Polite review ping...

bulbazord added inline comments.Mar 23 2023, 4:01 PM
lldb/bindings/python/python-wrapper.swig
1031–1048

I feel like this may lead to some confusion. __lldb_init_module_with_target makes sense as the thing that runs when you source the python file from dSYM and __lldb_init_module makes sense as the thing that runs when you do command script import. Implicitly running __lldb_init_module when you are imported as a scripting resource in a module would mean there's no way to get different behavior depending on which thing ran. Specifically, __lldb_init_module is always guaranteed to run. If a user wanted both to run, I think it might be better as an explicit thing. Like __lldb_init_module_with_target can call __lldb_init_module... I'm not sure, what do you think?