-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[lldb] Enable locate module callback for main executable #160199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
90823c1
to
aed6a69
Compare
@llvm/pr-subscribers-lldb Author: None (GeorgeHuyubo) ChangesMain executables were bypassing the locate module callback that shared Fixed by modifying Platform::ResolveExecutable() to call This ensures both main executables and shared libraries get the same Full diff: https://github.com/llvm/llvm-project/pull/160199.diff 1 Files Affected:
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 8681adaf5ea76..bbbe066cdea9e 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -750,12 +750,30 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
- Status error =
- ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
- module_search_paths_ptr, nullptr, nullptr);
+ // Call locate module callback first to give it a chance to find/register
+ // symbol file specs for the main executable, similar to how shared
+ // libraries are handled in Platform::GetRemoteSharedModule()
+ FileSpec symbol_file_spec;
+ CallLocateModuleCallbackIfSet(resolved_module_spec, exe_module_sp,
+ symbol_file_spec, nullptr);
- if (exe_module_sp && exe_module_sp->GetObjectFile())
- return error;
+ Status error;
+ if (!exe_module_sp) {
+ // If locate module callback didn't provide a module, fallback to standard
+ // path
+ error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
+ module_search_paths_ptr, nullptr,
+ nullptr);
+ }
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile()) {
+ // Set the symbol file if locate module callback returned one
+ if (symbol_file_spec) {
+ exe_module_sp->SetSymbolFileFileSpec(symbol_file_spec);
+ }
+ return error; // Return the actual status from GetSharedModule (or success
+ // from callback)
+ }
exe_module_sp.reset();
}
// No valid architecture was specified or the exact arch wasn't found.
@@ -767,12 +785,26 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
Status error;
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
resolved_module_spec.GetArchitecture() = arch;
- error =
- ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
- module_search_paths_ptr, nullptr, nullptr);
+
+ // Call locate module callback first, then fallback to standard path
+ FileSpec symbol_file_spec;
+ CallLocateModuleCallbackIfSet(resolved_module_spec, exe_module_sp,
+ symbol_file_spec, nullptr);
+
+ if (!exe_module_sp) {
+ error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
+ module_search_paths_ptr, nullptr,
+ nullptr);
+ }
+
if (error.Success()) {
- if (exe_module_sp && exe_module_sp->GetObjectFile())
+ if (exe_module_sp && exe_module_sp->GetObjectFile()) {
+ // Set the symbol file if locate module callback returned one
+ if (symbol_file_spec) {
+ exe_module_sp->SetSymbolFileFileSpec(symbol_file_spec);
+ }
break;
+ }
error = Status::FromErrorString("no exe object file");
}
|
This works functionality wise but I have two concerns:
|
When you are asked to resolve a shared library, it's always real when you first hear about it, because it's always the dynamic loader or the main executable's load commands that tell you about it. So at that point, all you need to do is GetSharedModule. |
For point 1) lldb's current assumption is if two binaries have the same UUID they are interchangeable. So it's always preferable to go with the one you've already ingested. Any fancier searches should be fallbacks to that. |
@jimingham |
Thought about this too, but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please follow the LLVM coding style and really just the style used by the surrounding code:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to see this functionality in ModuleList::GetSharedModule(...)
, even if we must pass a target in there. We pass down the module_search_paths_ptr
which come from the target's settings anyway, so it would be worth seeing all of the callers to this function and see if they all can pass in a target. If we have a target, we can access all target settings without manually passing module_search_paths_ptr
in and the target has a platform inside of it. Any solution we come up with should work for both executables and shared libraries in a consistent way.
This seems fine to me as well - I can't imagine anywhere that we're asking for a Module that we don't have a Target on hand. And GetSharedModule does have the job of creating modules it doesn't already have cached, so that seems like a reasonable place to put this. But that doesn't resolve the ordering question. I still think if you come into GetSharedModule with a ModuleSpec with a UUID in it, we should first look for that UUID amongst the Modules already in the SharedModuleList. Only if that fails should it go into any of the "create" mechanisms. We're okay with switching out the symbol file in a Module we already have, but I don't think we'd handle two Modules with the same UUID but different contents well, so we shouldn't allow that to happen. Also, though fetching the Executable module once you have a ModuleSpec for it should be a straightforward call to GetSharedModule, I don't think we want to start trying to put all the code that you have to do to figure out what ModuleSpec is meant by the arguments passed to |
65fe283
to
dffcc73
Compare
685bb1f
to
9c69309
Compare
@jimingham @jeffreytan81 @clayborg @JDevlieghere Updated with several changes. Ready for another round of review. |
@JDevlieghere Addressed your comments |
lldb/include/lldb/Core/ModuleSpec.h
Outdated
ArchSpec m_arch; | ||
UUID m_uuid; | ||
ConstString m_object_name; | ||
std::weak_ptr<Target> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put comment above with ///
// See if the file is present in any of the module_search_paths_ptr | ||
TargetSP target_sp = module_spec.GetTargetSP(); | ||
FileSpecList module_search_paths; | ||
if (target_sp) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apply elsewhere
lldb/source/Target/Target.cpp
Outdated
arch_spec.GetTriple().getTriple().c_str()); | ||
ModuleSpec module_spec(executable_sp->GetFileSpec(), other); | ||
FileSpecList search_paths = GetExecutableSearchPaths(); | ||
module_spec.SetTarget(this->shared_from_this()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this->
lldb/source/Target/Target.cpp
Outdated
|
||
// Apply any remappings specified in target.object-map: | ||
ModuleSpec module_spec(orig_module_spec); | ||
module_spec.SetTarget(this->shared_from_this()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this->
lldb/source/Target/Target.cpp
Outdated
transformed_spec.GetFileSpec().SetDirectory(transformed_dir); | ||
transformed_spec.GetFileSpec().SetFilename( | ||
module_spec.GetFileSpec().GetFilename()); | ||
transformed_spec.SetTarget(this->shared_from_this()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this->
✅ With the latest revision this PR passed the C/C++ code formatter. |
@jimingham @JDevlieghere @clayborg Fixed code style issue, and added test. Can I have another round of review? Thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things to fix mentioned in inline comments. We should add the ability to set the target in SBModuleSpec in the public API. So we need to add:
SBTarget SBModuleSpec::GetTarget();
void SBModuleSpec::SetTarget(SBTarget target);
ConstString m_object_name; | ||
/// This is set to take advantage of the target's search path and platform's | ||
/// locate module callback | ||
std::weak_ptr<Target> m_target; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change the name to m_target_wp
to indicate a weak pointer. We name shared pointers with a _sp
suffix and weak pointers with a _wp
// Get module search paths from the target if available. | ||
lldb::TargetSP target_sp = module_spec.GetTargetSP(); | ||
FileSpecList module_search_paths; | ||
FileSpecList *module_search_paths_ptr = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need this pointer, just use module_search_paths
everywhere in this function.
lldb::TargetSP target_sp = module_spec.GetTargetSP(); | ||
FileSpecList module_search_paths; | ||
FileSpecList *module_search_paths_ptr = nullptr; | ||
if (target_sp && target_sp->IsValid()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to check target_sp->IsValid()
here
Main executables were bypassing the locate module callback that shared
libraries use, preventing custom symbol file location logic from working
consistently.
This PR fix this by
This ensures both main executables and shared libraries get the same
callback treatment for symbol file resolution.