-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb][ObjC] Fix method list entry offset calculation #115571
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][ObjC] Fix method list entry offset calculation #115571
Conversation
The `relative_list_list_entry_t` offset field in the Objective-C runtime is of type `int64_t`. There are cases where these offsets are negative values. For negative offsets, LLDB would currently incorrectly zero-extend the offset (dropping the fact that the offset was negative), instead producing large offsets that, when added to the `m_baseMethods_ptr` result in addresses that had their upper bits set (e.g., `0x00017ff81b3241b0`). We then would try to `GetMethodList` from such an address but fail to read it (because it's an invalid address). This would manifest in Objective-C decls not getting completed correctly (and formatters not working). We noticed this in CI failures on our Intel bots. This happened to work fine on arm64 because we strip the upper bits when calling `ClassDescriptorV2::method_list_t::Read` using the `FixCodeAddress` ABI plugin API (which doesn't do that on Intel). The fix is to sign-extend the offset calculation.
@llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) ChangesThe The fix is to sign-extend the offset calculation. Example failure before this patch:
|
@@ -394,7 +394,7 @@ bool ClassDescriptorV2::relative_list_entry_t::Read(Process *process, | |||
lldb::offset_t cursor = 0; | |||
uint64_t raw_entry = extractor.GetU64_unchecked(&cursor); | |||
m_image_index = raw_entry & 0xFFFF; | |||
m_list_offset = (int64_t)(raw_entry >> 16); | |||
m_list_offset = llvm::SignExtend64<48>(raw_entry >> 16); |
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 guess that works, too, but why not (int64_t)raw_entry >> 16
?
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.
Just felt more explicit
The `relative_list_list_entry_t` offset field in the Objective-C runtime is of type `int64_t`. There are cases where these offsets are negative values. For negative offsets, LLDB would currently incorrectly zero-extend the offset (dropping the fact that the offset was negative), instead producing large offsets that, when added to the `m_baseMethods_ptr` result in addresses that had their upper bits set (e.g., `0x00017ff81b3241b0`). We then would try to `GetMethodList` from such an address but fail to read it (because it's an invalid address). This would manifest in Objective-C decls not getting completed correctly (and formatters not working). We noticed this in CI failures on our Intel bots. This happened to work fine on arm64 because we strip the upper bits when calling `ClassDescriptorV2::method_list_t::Read` using the `FixCodeAddress` ABI plugin API (which doesn't do that on Intel). The fix is to sign-extend the offset calculation. Example failure before this patch: ``` ====================================================================== FAIL: test_break_dwarf (TestRuntimeTypes.RuntimeTypesTestCase) Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1769, in test_method return attrvalue(self) File "/Users/michaelbuch/Git/llvm-project/lldb/test/API/lang/objc/foundation/TestRuntimeTypes.py", line 48, in test_break self.expect( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2370, in expect self.runCmd( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1000, in runCmd self.assertTrue(self.res.Succeeded(), msg + output) AssertionError: False is not true : Got a valid type Error output: error: <user expression 1>:1:11: no known method '+stringWithCString:encoding:'; cast the message send to the method's return type 1 | [NSString stringWithCString:"foo" encoding:1] | ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Config=x86_64-/Users/michaelbuch/Git/lldb-build-main-no-modules/bin/clang ---------------------------------------------------------------------- ``` (cherry picked from commit 04b295e)
The `relative_list_list_entry_t` offset field in the Objective-C runtime is of type `int64_t`. There are cases where these offsets are negative values. For negative offsets, LLDB would currently incorrectly zero-extend the offset (dropping the fact that the offset was negative), instead producing large offsets that, when added to the `m_baseMethods_ptr` result in addresses that had their upper bits set (e.g., `0x00017ff81b3241b0`). We then would try to `GetMethodList` from such an address but fail to read it (because it's an invalid address). This would manifest in Objective-C decls not getting completed correctly (and formatters not working). We noticed this in CI failures on our Intel bots. This happened to work fine on arm64 because we strip the upper bits when calling `ClassDescriptorV2::method_list_t::Read` using the `FixCodeAddress` ABI plugin API (which doesn't do that on Intel). The fix is to sign-extend the offset calculation. Example failure before this patch: ``` ====================================================================== FAIL: test_break_dwarf (TestRuntimeTypes.RuntimeTypesTestCase) Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1769, in test_method return attrvalue(self) File "/Users/michaelbuch/Git/llvm-project/lldb/test/API/lang/objc/foundation/TestRuntimeTypes.py", line 48, in test_break self.expect( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2370, in expect self.runCmd( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1000, in runCmd self.assertTrue(self.res.Succeeded(), msg + output) AssertionError: False is not true : Got a valid type Error output: error: <user expression 1>:1:11: no known method '+stringWithCString:encoding:'; cast the message send to the method's return type 1 | [NSString stringWithCString:"foo" encoding:1] | ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Config=x86_64-/Users/michaelbuch/Git/lldb-build-main-no-modules/bin/clang ---------------------------------------------------------------------- ``` (cherry picked from commit 04b295e)
The `relative_list_list_entry_t` offset field in the Objective-C runtime is of type `int64_t`. There are cases where these offsets are negative values. For negative offsets, LLDB would currently incorrectly zero-extend the offset (dropping the fact that the offset was negative), instead producing large offsets that, when added to the `m_baseMethods_ptr` result in addresses that had their upper bits set (e.g., `0x00017ff81b3241b0`). We then would try to `GetMethodList` from such an address but fail to read it (because it's an invalid address). This would manifest in Objective-C decls not getting completed correctly (and formatters not working). We noticed this in CI failures on our Intel bots. This happened to work fine on arm64 because we strip the upper bits when calling `ClassDescriptorV2::method_list_t::Read` using the `FixCodeAddress` ABI plugin API (which doesn't do that on Intel). The fix is to sign-extend the offset calculation. Example failure before this patch: ``` ====================================================================== FAIL: test_break_dwarf (TestRuntimeTypes.RuntimeTypesTestCase) Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1769, in test_method return attrvalue(self) File "/Users/michaelbuch/Git/llvm-project/lldb/test/API/lang/objc/foundation/TestRuntimeTypes.py", line 48, in test_break self.expect( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2370, in expect self.runCmd( File "/Users/michaelbuch/Git/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1000, in runCmd self.assertTrue(self.res.Succeeded(), msg + output) AssertionError: False is not true : Got a valid type Error output: error: <user expression 1>:1:11: no known method '+stringWithCString:encoding:'; cast the message send to the method's return type 1 | [NSString stringWithCString:"foo" encoding:1] | ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Config=x86_64-/Users/michaelbuch/Git/lldb-build-main-no-modules/bin/clang ---------------------------------------------------------------------- ```
[lldb][ObjC] Fix method list entry offset calculation (llvm#115571)
The
relative_list_list_entry_t
offset field in the Objective-C runtime is of typeint64_t
. There are cases where these offsets are negative values. For negative offsets, LLDB would currently incorrectly zero-extend the offset (dropping the fact that the offset was negative), instead producing large offsets that, when added to them_baseMethods_ptr
result in addresses that had their upper bits set (e.g.,0x00017ff81b3241b0
). We then would try toGetMethodList
from such an address but fail to read it (because it's an invalid address). This would manifest in Objective-C decls not getting completed correctly (and formatters not working). We noticed this in CI failures on our Intel bots. This happened to work fine on arm64 because we strip the upper bits when callingClassDescriptorV2::method_list_t::Read
using theFixCodeAddress
ABI plugin API (which doesn't do that on Intel).The fix is to sign-extend the offset calculation.
Example failure before this patch: