diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -951,50 +951,65 @@ Process *process = m_exe_ctx.GetProcessPtr(); ExecutionContext exe_ctx(process); + ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); - if (objc_runtime) { - ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = - objc_runtime->GetTaggedPointerVendor(); - if (tagged_ptr_vendor) { - for (size_t i = 0; i < command.GetArgumentCount(); i++) { - const char *arg_str = command.GetArgumentAtIndex(i); - if (!arg_str) - continue; - Status error; - lldb::addr_t arg_addr = OptionArgParser::ToAddress( - &exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error); - if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail()) - continue; - auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr); - if (!descriptor_sp) - continue; - uint64_t info_bits = 0; - uint64_t value_bits = 0; - uint64_t payload = 0; - if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits, - &payload)) { - result.GetOutputStream().Printf( - "0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64 - "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64 - "\n\tclass = %s\n", - (uint64_t)arg_addr, payload, value_bits, info_bits, - descriptor_sp->GetClassName().AsCString("")); - } else { - result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", - (uint64_t)arg_addr); - } - } - } else { - result.AppendError("current process has no tagged pointer support"); + if (!objc_runtime) { + result.AppendError("current process has no Objective-C runtime loaded"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + + ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = + objc_runtime->GetTaggedPointerVendor(); + if (!tagged_ptr_vendor) { + result.AppendError("current process has no tagged pointer support"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + + for (size_t i = 0; i < command.GetArgumentCount(); i++) { + const char *arg_str = command.GetArgumentAtIndex(i); + if (!arg_str) + continue; + + Status error; + lldb::addr_t arg_addr = OptionArgParser::ToAddress( + &exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error); + if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail()) { + result.AppendErrorWithFormat( + "could not convert '%s' to a valid address\n", arg_str); result.SetStatus(lldb::eReturnStatusFailed); return false; } - result.SetStatus(lldb::eReturnStatusSuccessFinishResult); - return true; + + auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr); + if (!descriptor_sp) { + result.AppendErrorWithFormat( + "could not get class descriptor for 0x%" PRIx64 "\n", + (uint64_t)arg_addr); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + + uint64_t info_bits = 0; + uint64_t value_bits = 0; + uint64_t payload = 0; + if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits, + &payload)) { + result.GetOutputStream().Printf( + "0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64 + "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64 + "\n\tclass = %s\n", + (uint64_t)arg_addr, payload, value_bits, info_bits, + descriptor_sp->GetClassName().AsCString("")); + } else { + result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", + (uint64_t)arg_addr); + } } - result.AppendError("current process has no Objective-C runtime loaded"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; + + result.SetStatus(lldb::eReturnStatusSuccessFinishResult); + return true; } }; diff --git a/lldb/test/API/lang/objc/tagged-pointer/Makefile b/lldb/test/API/lang/objc/tagged-pointer/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/objc/tagged-pointer/Makefile @@ -0,0 +1,4 @@ +OBJC_SOURCES := main.m +LD_EXTRAS := -lobjc -framework Foundation + +include Makefile.rules diff --git a/lldb/test/API/lang/objc/tagged-pointer/TestTaggedPointerCmd.py b/lldb/test/API/lang/objc/tagged-pointer/TestTaggedPointerCmd.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/objc/tagged-pointer/TestTaggedPointerCmd.py @@ -0,0 +1,20 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestTaggedPointerCommand(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self,"// break here", lldb.SBFileSpec("main.m")) + + self.expect("lang objc tagged-pointer info bogus", error=True, + patterns=["could not convert 'bogus' to a valid address"]) + + self.expect("lang objc tagged-pointer info 0x1", error=True, + patterns=["could not get class descriptor for 0x1"]) + diff --git a/lldb/test/API/lang/objc/tagged-pointer/main.m b/lldb/test/API/lang/objc/tagged-pointer/main.m new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/objc/tagged-pointer/main.m @@ -0,0 +1,6 @@ +#import +int main() { + id n1 = [NSNumber numberWithInt:1]; + printf("%x", n1); // break here + return 0; +}