Skip to content

[lldb] Fix HeapCFA comparison to be symmetric #10127

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

Merged

Conversation

felipepiovezan
Copy link

A swift async frame A is younger than frame B if the async ctx of B can
be reached from the async ctx of A. This is implemented today.

But we fail to check the opposite:
A swift async frame A is _older_ than frame B if the async ctx of A can
be reached from the async ctx of B.

Because we lacked the opposite check, we were falling back to "vanilla"
CFA comparison, and were just being lucky that the vast majority of
cases are only interested in the "Younger" case.

@felipepiovezan
Copy link
Author

@swift-ci test

@@ -76,11 +76,34 @@ bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) {
}

// BEGIN SWIFT
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code below is just copied from the old location

// to check if `destination` can be reached from `source`. The search stops when
// it hits the end of the chain (parent_ctx == 0) or a safety limit in case of
// an invalid continuation chain.
static llvm::Expected<bool> ChaseContinuationsToFind(lldb::addr_t source,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsReachableParent or IsReachableParentContext?

parent_ctx = process.ReadPointerFromMemory(old_parent_ctx, error);
if (error.Fail())
return llvm::createStringError(llvm::formatv(
"Failed to read parent async context of: {0:x}", old_parent_ctx));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this include the error's message?

llvm::Expected<bool> lhs_younger =
ChaseContinuationsToFind(lhs_cfa, rhs_cfa, process);
if (auto E = lhs_younger.takeError())
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "");
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "{0}");

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhh nice catch

llvm::Expected<bool> lhs_older =
ChaseContinuationsToFind(rhs_cfa, lhs_cfa, process);
if (auto E = lhs_older.takeError())
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "");
LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), std::move(E), "{0}");

if (parent_ctx == destination)
return true;
}
return false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false is correct for the case where a null parent is reached. What about when the 512 limit is reached? Should this return an error? If not, should there be a log? As it is, there's no way of knowing the limit was reached.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do that, though I was hoping to just move the code as this is an NFC patch

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it just now, it does look much better indeed!

@felipepiovezan felipepiovezan force-pushed the felipe/fix_heap_cfa branch 2 times, most recently from b022ee1 to c8f82c0 Compare February 27, 2025 21:28
This will be re-used in a subsequent commit.
A swift async frame A is younger than frame B if the async ctx of B can
be reached from the async ctx of A. This is implemented today.

But we fail to check the opposite:
A swift async frame A is _older_ than frame B if the async ctx of A can
be reached from the async ctx of B.

Because we lacked the opposite check, we were falling back to "vanilla"
CFA comparison, and were just being lucky that the vast majority of
cases are only interested in the "Younger" case.
@felipepiovezan
Copy link
Author

Addressed feedback

@felipepiovezan
Copy link
Author

@swift-ci test

@felipepiovezan felipepiovezan merged commit 6e0f052 into swiftlang:stable/20240723 Feb 28, 2025
3 checks passed
@felipepiovezan felipepiovezan deleted the felipe/fix_heap_cfa branch February 28, 2025 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants