-
Notifications
You must be signed in to change notification settings - Fork 341
[lldb] Implement LLDBMemoryReader::resolvePointer #3848
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
[lldb] Implement LLDBMemoryReader::resolvePointer #3848
Conversation
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 awesome! Do you agree that we should cherry-pick this to the swift/release/5.6 branch?
I have been profiling this in combination with #3800. I will gather some profile data for this patch alone, to help us decide about 5.6. In the mean time, I will open a PR and run the tests. |
test/Shell/Swift/runtime-initialization.test is failing, by not resolving the dynamic type of a variable from the command |
In my current "perf harness", I found that during the first call to Calls to |
The test failure shines a light on something I found confusing: the name To put it another way, What does this have to do with this test failure? Well some code calls llvm::Optional<StoredPointer>
readResolvedPointerValue(StoredPointer address) {
if (auto pointer = readPointer(address)) {
if (!pointer->isResolved())
return None;
return (StoredPointer)pointer->getResolvedAddress().getAddressData();
}
return None;
} I wonder if there's a simple fix: instead of returning |
The "simple fix" does work, I'll have to get feedback/review and run tests. |
In a live process resolvePointer is an identity function, because all pointers are in memory that has been patched by dyld to resolve to the correct address. So if you're patching the if(!resolved) path any breakage would surface either in swift-reflection-dump or lldb. The function is used only(?) here:
I originally thought an ExistentialAddress would never be a symbol, because it points to the address of a live object in heap or stack. But the failing testcase is a global variable, and that could actually have a symbol which LLDB finds, but which we would not want to return in LLDBMemoryReader. LLDBMemoryReader reads live process memory and reflection metdata and we only want symbols in the latter case. |
So an alternative fix in LLDB would be to check if the symbol is in a reflection section or in __DATA,const and explicitly not in the rest of __DATA. |
Yes, with a bit of thinking through this, I now understand this better. Your comment helps clarify. I have added an |
if (section->GetName() == "__const") | ||
return true; | ||
if (auto segment = section->GetParent()) | ||
if (segment->GetName() == "__DATA_CONST") |
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 shouldn't be hardcoding implementation details of the MachO format here, but I'm sure we can sink this into Target or somewhere more appropriate
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.
thanks I am on the same page, I put this change together quickly primarily to test asynchronously.
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.
🎉🎉🎉
@shafik I have added a virtual function ( |
@@ -390,6 +390,10 @@ void Section::SetPermissions(uint32_t permissions) { | |||
m_executable = (permissions & ePermissionsExecutable) != 0; | |||
} | |||
|
|||
bool Section::CanContainSwiftReflectionData() const { |
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.
Maybe GetCanContainSwiftReflectionData
having this function be the same name feels confusing especially in this PR. e.g. we can see below GetSectionData
calls m_obj_file->ReadSectionData
.
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.
Don't suppose you have alternative naming suggestions? I would say that Can
is like Is
or Has
, which are not conventionally combined with Get
. Using same name was by design, the idea is to connect them by name. If that's confusing, then I am open to other names, but I don't think GetCan…
should be it.
@@ -689,6 +690,8 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>, | |||
virtual llvm::StringRef | |||
GetReflectionSectionIdentifier(swift::ReflectionSectionKind section); | |||
|
|||
virtual bool CanContainSwiftReflectionData(const Section §ion); |
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 see we assert false in the implementation why don't we make it pure virtual using =0
instead? I see we use a mix in this class. Detecting we have not implemented an override
at runtime seems less ideal.
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 gave it a default behavior of return false
, instead of making it pure virtual.
nice, passing! |
148d7c7
to
9f230a1
Compare
@swift-ci test |
…esolvePointer [lldb] Implement LLDBMemoryReader::resolvePointer (cherry picked from commit bb7505d)
Looking at the list of individual commits, this PR would have been a great candidate for squashing into a single commit. I'm all for always writing the smallest possible patch, but only if each patch can stand for itself and has a meaningful commit message. |
@JDevlieghere also brought this up. I will squash in the future. |
Override
MemoryReader::resolvePointer
inLLDBMemoryReader
.This function lets a memory reader implementation optionally convert an address into a symbol. This functionality is used in places where
MetadataReader
can benefit from knowing the symbol for an address. A Swift symbol can provide extra (but optional) data toMetadataReader
. In particular, profiling has shown it to be quite costly forMetadataReader
to load context descriptors, build a demangle node tree from those descriptors, and finally mangling it to a symbol. This work to compute the symbol can be avoided by implementingresolvePointer
.