[lldb] Support arm64e Objective-C signing in the expression evaluator (#187765)

When targeting arm64e, ISA pointers, class_ro_t pointers, and interface
selectors are signed in Objective-C. This PR adds support for that in
the expression evaluator.
This commit is contained in:
Jonas Devlieghere 2026-03-20 19:50:16 -05:00 committed by GitHub
parent 3d4dd4b944
commit b9d276748e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 143 additions and 0 deletions

View File

@ -731,6 +731,9 @@ static void SetPointerAuthOptionsForArm64e(LangOptions &lang_opts) {
lang_opts.PointerAuthReturns = true;
lang_opts.PointerAuthAuthTraps = true;
lang_opts.PointerAuthIndirectGotos = true;
lang_opts.PointerAuthObjcIsa = true;
lang_opts.PointerAuthObjcClassROPointers = true;
lang_opts.PointerAuthObjcInterfaceSel = true;
}
ClangExpressionParser::ClangExpressionParser(

View File

@ -0,0 +1,10 @@
OBJC_SOURCES := main.m
override ARCH := arm64e
# We need an arm64e stdlib.
USE_SYSTEM_STDLIB := 1
LD_EXTRAS := -framework Foundation
include Makefile.rules

View File

@ -0,0 +1,91 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestPtrAuthObjectiveC(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipUnlessArm64eSupported
def test_objc_message_send(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.m", False)
)
self.expect_expr(
"[obj doubleValue]",
result_type="int",
result_value="42",
)
@skipUnlessArm64eSupported
def test_objc_message_send_with_arg(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.m", False)
)
self.expect_expr(
"[obj addValue:9]",
result_type="int",
result_value="30",
)
@skipUnlessArm64eSupported
def test_objc_alloc_and_message(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.m", False)
)
self.expect_expr(
"PtrAuthTestObj *tmp = (PtrAuthTestObj *)[[PtrAuthTestObj alloc] init]; "
"tmp.value = 7; [tmp doubleValue]",
result_type="int",
result_value="14",
)
@skipUnlessArm64eSupported
def test_objc_derived_class(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.m", False)
)
self.expect_expr(
"[derived tripleValue]",
result_type="int",
result_value="30",
)
self.expect_expr(
"[derived doubleValue]",
result_type="int",
result_value="20",
)
@skipUnlessArm64eSupported
def test_objc_isa_check(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.m", False)
)
self.expect_expr(
"(bool)[derived isKindOfClass:[PtrAuthTestObj class]]",
result_type="bool",
result_value="true",
)
self.expect_expr(
"(bool)[obj isKindOfClass:[PtrAuthDerived class]]",
result_type="bool",
result_value="false",
)

View File

@ -0,0 +1,39 @@
#import <Foundation/Foundation.h>
#include <stdio.h>
@interface PtrAuthTestObj : NSObject
@property(nonatomic, assign) int value;
- (int)doubleValue;
- (int)addValue:(int)other;
@end
@implementation PtrAuthTestObj
- (int)doubleValue {
return self.value * 2;
}
- (int)addValue:(int)other {
return self.value + other;
}
@end
@interface PtrAuthDerived : PtrAuthTestObj
- (int)tripleValue;
@end
@implementation PtrAuthDerived
- (int)tripleValue {
return self.value * 3;
}
@end
int main(int argc, const char *argv[]) {
PtrAuthTestObj *obj = [[PtrAuthTestObj alloc] init];
obj.value = 21;
PtrAuthDerived *derived = [[PtrAuthDerived alloc] init];
derived.value = 10;
int result = [obj doubleValue]; // break here
printf("%d %d\n", result, [derived tripleValue]);
return 0;
}