aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp')
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp3872
1 files changed, 1900 insertions, 1972 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index e9a799bb3651..e9958a5ef759 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -19,9 +19,9 @@
#include "clang/AST/DeclObjC.h"
// Project includes
-#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/CompilerType.h"
+#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
@@ -56,21 +56,22 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "AppleObjCRuntimeV2.h"
#include "AppleObjCClassDescriptorV2.h"
-#include "AppleObjCTypeEncodingParser.h"
#include "AppleObjCDeclVendor.h"
+#include "AppleObjCRuntimeV2.h"
#include "AppleObjCTrampolineHandler.h"
-
+#include "AppleObjCTypeEncodingParser.h"
using namespace lldb;
using namespace lldb_private;
// 2 second timeout when running utility functions
-#define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000
+static constexpr std::chrono::seconds g_utility_function_timeout(2);
-static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+static const char *g_get_dynamic_class_info_name =
+ "__lldb_apple_objc_v2_get_dynamic_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we
+// will
// need to revert to the code above...
static const char *g_get_dynamic_class_info_body = R"(
@@ -152,8 +153,10 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
)";
-static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info";
-// Testing using the new C++11 raw string literals. If this breaks GCC then we will
+static const char *g_get_shared_cache_class_info_name =
+ "__lldb_apple_objc_v2_get_shared_cache_class_info";
+// Testing using the new C++11 raw string literals. If this breaks GCC then we
+// will
// need to revert to the code above...
static const char *g_get_shared_cache_class_info_body = R"(
@@ -334,2187 +337,2112 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
)";
static uint64_t
-ExtractRuntimeGlobalSymbol (Process* process,
- ConstString name,
- const ModuleSP &module_sp,
- Error& error,
- bool read_value = true,
- uint8_t byte_size = 0,
- uint64_t default_value = LLDB_INVALID_ADDRESS,
- SymbolType sym_type = lldb::eSymbolTypeData)
-{
- if (!process)
- {
- error.SetErrorString("no process");
- return default_value;
- }
- if (!module_sp)
- {
- error.SetErrorString("no module");
- return default_value;
- }
- if (!byte_size)
- byte_size = process->GetAddressByteSize();
- const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
- if (symbol && symbol->ValueIsAddress())
- {
- lldb::addr_t symbol_load_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- {
- if (read_value)
- return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error);
- else
- return symbol_load_addr;
- }
- else
- {
- error.SetErrorString("symbol address invalid");
- return default_value;
- }
- }
- else
- {
- error.SetErrorString("no symbol");
- return default_value;
+ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
+ const ModuleSP &module_sp, Error &error,
+ bool read_value = true, uint8_t byte_size = 0,
+ uint64_t default_value = LLDB_INVALID_ADDRESS,
+ SymbolType sym_type = lldb::eSymbolTypeData) {
+ if (!process) {
+ error.SetErrorString("no process");
+ return default_value;
+ }
+ if (!module_sp) {
+ error.SetErrorString("no module");
+ return default_value;
+ }
+ if (!byte_size)
+ byte_size = process->GetAddressByteSize();
+ const Symbol *symbol =
+ module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
+ if (symbol && symbol->ValueIsAddress()) {
+ lldb::addr_t symbol_load_addr =
+ symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
+ if (read_value)
+ return process->ReadUnsignedIntegerFromMemory(
+ symbol_load_addr, byte_size, default_value, error);
+ else
+ return symbol_load_addr;
+ } else {
+ error.SetErrorString("symbol address invalid");
+ return default_value;
}
+ } else {
+ error.SetErrorString("no symbol");
+ return default_value;
+ }
}
-AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, const ModuleSP &objc_module_sp)
- : AppleObjCRuntime(process),
- m_get_class_info_code(),
+AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
+ const ModuleSP &objc_module_sp)
+ : AppleObjCRuntime(process), m_get_class_info_code(),
m_get_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_class_info_args_mutex(),
- m_get_shared_cache_class_info_code(),
+ m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
- m_get_shared_cache_class_info_args_mutex(),
- m_decl_vendor_ap(),
- m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
- m_hash_signature(),
- m_has_object_getClass(false),
- m_loaded_objc_opt(false),
- m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this, objc_module_sp)),
- m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
- m_encoding_to_type_sp(),
- m_noclasses_warning_emitted(false)
-{
- static const ConstString g_gdb_object_getClass("gdb_object_getClass");
- m_has_object_getClass =
- (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+ m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_ap(),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
+ m_has_object_getClass(false), m_loaded_objc_opt(false),
+ m_non_pointer_isa_cache_ap(
+ NonPointerISACache::CreateInstance(*this, objc_module_sp)),
+ m_tagged_pointer_vendor_ap(
+ TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
+ m_encoding_to_type_sp(), m_noclasses_warning_emitted(false),
+ m_CFBoolean_values() {
+ static const ConstString g_gdb_object_getClass("gdb_object_getClass");
+ m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_gdb_object_getClass, eSymbolTypeCode) != NULL);
}
-bool
-AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
- DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type)
-{
- // We should never get here with a null process...
- assert (m_process != NULL);
-
- // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
- // Note, however, the process might be NULL (e.g. if the value was made with SBTarget::EvaluateExpression...)
- // in which case it is sufficient if the target's match:
-
- Process *process = in_value.GetProcessSP().get();
- if (process)
- assert (process == m_process);
- else
- assert (in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
-
- class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
-
- // Make sure we can have a dynamic value before starting...
- if (CouldHaveDynamicValue (in_value))
- {
- // First job, pull out the address at 0 offset from the object That will be the ISA pointer.
- ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
- if (objc_class_sp)
- {
- const addr_t object_ptr = in_value.GetPointerValue();
- address.SetRawAddress(object_ptr);
-
- ConstString class_name (objc_class_sp->GetClassName());
- class_type_or_name.SetName(class_name);
- TypeSP type_sp (objc_class_sp->GetType());
- if (type_sp)
- class_type_or_name.SetTypeSP (type_sp);
- else
- {
- type_sp = LookupInCompleteClassCache (class_name);
- if (type_sp)
- {
- objc_class_sp->SetType (type_sp);
- class_type_or_name.SetTypeSP (type_sp);
- }
- else
- {
- // try to go for a CompilerType at least
- DeclVendor* vendor = GetDeclVendor();
- if (vendor)
- {
- std::vector<clang::NamedDecl*> decls;
- if (vendor->FindDecls(class_name, false, 1, decls) && decls.size())
- class_type_or_name.SetCompilerType(ClangASTContext::GetTypeForDecl(decls[0]));
- }
- }
- }
+bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
+ ValueObject &in_value, DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ // We should never get here with a null process...
+ assert(m_process != NULL);
+
+ // The Runtime is attached to a particular process, you shouldn't pass in a
+ // value from another process.
+ // Note, however, the process might be NULL (e.g. if the value was made with
+ // SBTarget::EvaluateExpression...)
+ // in which case it is sufficient if the target's match:
+
+ Process *process = in_value.GetProcessSP().get();
+ if (process)
+ assert(process == m_process);
+ else
+ assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
+
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+
+ // Make sure we can have a dynamic value before starting...
+ if (CouldHaveDynamicValue(in_value)) {
+ // First job, pull out the address at 0 offset from the object That will be
+ // the ISA pointer.
+ ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(in_value));
+ if (objc_class_sp) {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+
+ ConstString class_name(objc_class_sp->GetClassName());
+ class_type_or_name.SetName(class_name);
+ TypeSP type_sp(objc_class_sp->GetType());
+ if (type_sp)
+ class_type_or_name.SetTypeSP(type_sp);
+ else {
+ type_sp = LookupInCompleteClassCache(class_name);
+ if (type_sp) {
+ objc_class_sp->SetType(type_sp);
+ class_type_or_name.SetTypeSP(type_sp);
+ } else {
+ // try to go for a CompilerType at least
+ DeclVendor *vendor = GetDeclVendor();
+ if (vendor) {
+ std::vector<clang::NamedDecl *> decls;
+ if (vendor->FindDecls(class_name, false, 1, decls) && decls.size())
+ class_type_or_name.SetCompilerType(
+ ClangASTContext::GetTypeForDecl(decls[0]));
+ }
}
- }
- return class_type_or_name.IsEmpty() == false;
+ }
+ }
+ }
+ return class_type_or_name.IsEmpty() == false;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
-LanguageRuntime *
-AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
-{
- // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make
- // sure we aren't using the V1 runtime.
- if (language == eLanguageTypeObjC)
- {
- ModuleSP objc_module_sp;
-
- if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V2)
- return new AppleObjCRuntimeV2 (process, objc_module_sp);
- else
- return NULL;
- }
+LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process,
+ LanguageType language) {
+ // FIXME: This should be a MacOS or iOS process, and we need to look for the
+ // OBJC section to make
+ // sure we aren't using the V1 runtime.
+ if (language == eLanguageTypeObjC) {
+ ModuleSP objc_module_sp;
+
+ if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
+ ObjCRuntimeVersions::eAppleObjC_V2)
+ return new AppleObjCRuntimeV2(process, objc_module_sp);
else
- return NULL;
+ return NULL;
+ } else
+ return NULL;
}
-class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed
-{
-public:
- class CommandOptions : public Options
- {
- public:
- CommandOptions (CommandInterpreter &interpreter) :
- Options(interpreter),
- m_verbose(false,false)
- {}
-
- ~CommandOptions() override = default;
-
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
- switch (short_option)
- {
- case 'v':
- m_verbose.SetCurrentValue(true);
- m_verbose.SetOptionWasSet();
- break;
-
- default:
- error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
- break;
- }
-
- return error;
- }
-
- void
- OptionParsingStarting() override
- {
- m_verbose.Clear();
- }
-
- const OptionDefinition*
- GetDefinitions() override
- {
- return g_option_table;
- }
+static OptionDefinition g_objc_classtable_dump_options[] = {
+ {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument,
+ nullptr, nullptr, 0, eArgTypeNone,
+ "Print ivar and method information in detail"}};
- OptionValueBoolean m_verbose;
- static OptionDefinition g_option_table[];
- };
-
- CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "dump",
- "Dump information on Objective-C classes known to the current process.",
- "language objc class-table dump",
- eCommandRequiresProcess |
- eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused ),
- m_options(interpreter)
- {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeRegularExpression;
- index_arg.arg_repetition = eArgRepeatOptional;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (index_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
+class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
+public:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_verbose(false, false) {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+ switch (short_option) {
+ case 'v':
+ m_verbose.SetCurrentValue(true);
+ m_verbose.SetOptionWasSet();
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
}
- ~CommandObjectObjC_ClassTable_Dump() override = default;
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_verbose.Clear();
+ }
- Options *
- GetOptions() override
- {
- return &m_options;
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_objc_classtable_dump_options);
}
-
+
+ OptionValueBoolean m_verbose;
+ };
+
+ CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "dump", "Dump information on Objective-C classes "
+ "known to the current process.",
+ "language objc class-table dump",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
+ m_options() {
+ CommandArgumentEntry arg;
+ CommandArgumentData index_arg;
+
+ // Define the first (and only) variant of this arg.
+ index_arg.arg_type = eArgTypeRegularExpression;
+ index_arg.arg_repetition = eArgRepeatOptional;
+
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg.push_back(index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg);
+ }
+
+ ~CommandObjectObjC_ClassTable_Dump() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
protected:
- bool
- DoExecute(Args& command, CommandReturnObject &result) override
- {
- std::unique_ptr<RegularExpression> regex_up;
- switch(command.GetArgumentCount())
- {
- case 0:
- break;
- case 1:
- {
- regex_up.reset(new RegularExpression());
- if (!regex_up->Compile(command.GetArgumentAtIndex(0)))
- {
- result.AppendError("invalid argument - please provide a valid regular expression");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
- }
- break;
- }
- default:
- {
- result.AppendError("please provide 0 or 1 arguments");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
- }
- }
-
- Process *process = m_exe_ctx.GetProcessPtr();
- ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
- if (objc_runtime)
- {
- auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
- auto iterator = iterators_pair.first;
- auto &std_out = result.GetOutputStream();
- for(; iterator != iterators_pair.second; iterator++)
- {
- if (iterator->second)
- {
- const char* class_name = iterator->second->GetClassName().AsCString("<unknown>");
- if (regex_up && class_name && !regex_up->Execute(class_name))
- continue;
- std_out.Printf("isa = 0x%" PRIx64, iterator->first);
- std_out.Printf(" name = %s", class_name);
- std_out.Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize());
- std_out.Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars());
- if (auto superclass = iterator->second->GetSuperclass())
- {
- std_out.Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>"));
- }
- std_out.Printf("\n");
- if (m_options.m_verbose)
- {
- for(size_t i = 0;
- i < iterator->second->GetNumIVars();
- i++)
- {
- auto ivar = iterator->second->GetIVarAtIndex(i);
- std_out.Printf(" ivar name = %s type = %s size = %" PRIu64 " offset = %" PRId32 "\n",
- ivar.m_name.AsCString("<unknown>"),
- ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
- ivar.m_size,
- ivar.m_offset);
- }
- iterator->second->Describe(nullptr,
- [objc_runtime, &std_out] (const char* name, const char* type) -> bool {
- std_out.Printf(" instance method name = %s type = %s\n",
- name,
- type);
- return false;
- },
- [objc_runtime, &std_out] (const char* name, const char* type) -> bool {
- std_out.Printf(" class method name = %s type = %s\n",
- name,
- type);
- return false;
- },
- nullptr);
- }
- }
- else
- {
- if (regex_up && !regex_up->Execute(""))
- continue;
- std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n", iterator->first);
- }
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ std::unique_ptr<RegularExpression> regex_up;
+ switch (command.GetArgumentCount()) {
+ case 0:
+ break;
+ case 1: {
+ regex_up.reset(new RegularExpression());
+ if (!regex_up->Compile(llvm::StringRef::withNullAsEmpty(
+ command.GetArgumentAtIndex(0)))) {
+ result.AppendError(
+ "invalid argument - please provide a valid regular expression");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ break;
+ }
+ default: {
+ result.AppendError("please provide 0 or 1 arguments");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ if (objc_runtime) {
+ auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
+ auto iterator = iterators_pair.first;
+ auto &std_out = result.GetOutputStream();
+ for (; iterator != iterators_pair.second; iterator++) {
+ if (iterator->second) {
+ const char *class_name =
+ iterator->second->GetClassName().AsCString("<unknown>");
+ if (regex_up && class_name &&
+ !regex_up->Execute(llvm::StringRef(class_name)))
+ continue;
+ std_out.Printf("isa = 0x%" PRIx64, iterator->first);
+ std_out.Printf(" name = %s", class_name);
+ std_out.Printf(" instance size = %" PRIu64,
+ iterator->second->GetInstanceSize());
+ std_out.Printf(" num ivars = %" PRIuPTR,
+ (uintptr_t)iterator->second->GetNumIVars());
+ if (auto superclass = iterator->second->GetSuperclass()) {
+ std_out.Printf(" superclass = %s",
+ superclass->GetClassName().AsCString("<unknown>"));
+ }
+ std_out.Printf("\n");
+ if (m_options.m_verbose) {
+ for (size_t i = 0; i < iterator->second->GetNumIVars(); i++) {
+ auto ivar = iterator->second->GetIVarAtIndex(i);
+ std_out.Printf(
+ " ivar name = %s type = %s size = %" PRIu64
+ " offset = %" PRId32 "\n",
+ ivar.m_name.AsCString("<unknown>"),
+ ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
+ ivar.m_size, ivar.m_offset);
}
- result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
- return true;
- }
- else
- {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
+ iterator->second->Describe(
+ nullptr,
+ [objc_runtime, &std_out](const char *name,
+ const char *type) -> bool {
+ std_out.Printf(" instance method name = %s type = %s\n",
+ name, type);
+ return false;
+ },
+ [objc_runtime, &std_out](const char *name,
+ const char *type) -> bool {
+ std_out.Printf(" class method name = %s type = %s\n", name,
+ type);
+ return false;
+ },
+ nullptr);
+ }
+ } else {
+ if (regex_up && !regex_up->Execute(llvm::StringRef()))
+ continue;
+ std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n",
+ iterator->first);
}
+ }
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ return true;
+ } else {
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
-
- CommandOptions m_options;
-};
+ }
-OptionDefinition
-CommandObjectObjC_ClassTable_Dump::CommandOptions::g_option_table[] =
-{
- { LLDB_OPT_SET_ALL, false, "verbose" , 'v', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print ivar and method information in detail"},
- { 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr }
+ CommandOptions m_options;
};
-class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed
-{
+class CommandObjectMultiwordObjC_TaggedPointer_Info
+ : public CommandObjectParsed {
public:
- CommandObjectMultiwordObjC_TaggedPointer_Info (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "info",
- "Dump information on a tagged pointer.",
- "language objc tagged-pointer info",
- eCommandRequiresProcess |
- eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused )
- {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeAddress;
- index_arg.arg_repetition = eArgRepeatPlus;
-
- // There is only one variant this argument could be; put it into the argument entry.
- arg.push_back (index_arg);
-
- // Push the data for the first argument into the m_arguments vector.
- m_arguments.push_back (arg);
- }
+ CommandObjectMultiwordObjC_TaggedPointer_Info(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "info", "Dump information on a tagged pointer.",
+ "language objc tagged-pointer info",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {
+ CommandArgumentEntry arg;
+ CommandArgumentData index_arg;
- ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
+ // Define the first (and only) variant of this arg.
+ index_arg.arg_type = eArgTypeAddress;
+ index_arg.arg_repetition = eArgRepeatPlus;
+
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg.push_back(index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg);
+ }
+
+ ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
protected:
- bool
- DoExecute(Args& command, CommandReturnObject &result) override
- {
- if (command.GetArgumentCount() == 0)
- {
- result.AppendError("this command requires arguments");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
- }
-
- Process *process = m_exe_ctx.GetProcessPtr();
- ExecutionContext exe_ctx(process);
- ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
- 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;
- Error error;
- lldb::addr_t arg_addr = Args::StringToAddress(&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("<unknown>"));
- }
- else
- {
- result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", (uint64_t)arg_addr);
- }
- }
- }
- else
- {
- result.AppendError("current process has no tagged pointer support");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
- }
- result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
- return true;
- }
- else
- {
- result.AppendError("current process has no Objective-C runtime loaded");
- result.SetStatus(lldb::eReturnStatusFailed);
- return false;
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (command.GetArgumentCount() == 0) {
+ result.AppendError("this command requires arguments");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+
+ Process *process = m_exe_ctx.GetProcessPtr();
+ ExecutionContext exe_ctx(process);
+ ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime();
+ 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;
+ Error error;
+ lldb::addr_t arg_addr = Args::StringToAddress(
+ &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("<unknown>"));
+ } else {
+ result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n",
+ (uint64_t)arg_addr);
+ }
}
+ } else {
+ result.AppendError("current process has no tagged pointer support");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
+ }
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ return true;
+ } else {
+ result.AppendError("current process has no Objective-C runtime loaded");
+ result.SetStatus(lldb::eReturnStatusFailed);
+ return false;
}
+ }
};
-class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword
-{
+class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword {
public:
- CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "class-table", "Commands for operating on the Objective-C class table.",
- "class-table <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("dump", CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter)));
- }
-
- ~CommandObjectMultiwordObjC_ClassTable() override = default;
+ CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "class-table",
+ "Commands for operating on the Objective-C class table.",
+ "class-table <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "dump",
+ CommandObjectSP(new CommandObjectObjC_ClassTable_Dump(interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC_ClassTable() override = default;
};
-class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword
-{
+class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword {
public:
- CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "tagged-pointer",
- "Commands for operating on Objective-C tagged pointers.",
- "class-table <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("info", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter)));
- }
-
- ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
+ CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "tagged-pointer",
+ "Commands for operating on Objective-C tagged pointers.",
+ "class-table <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "info",
+ CommandObjectSP(
+ new CommandObjectMultiwordObjC_TaggedPointer_Info(interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
};
-class CommandObjectMultiwordObjC : public CommandObjectMultiword
-{
+class CommandObjectMultiwordObjC : public CommandObjectMultiword {
public:
- CommandObjectMultiwordObjC(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "objc", "Commands for operating on the Objective-C language runtime.",
- "objc <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("class-table", CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter)));
- LoadSubCommand ("tagged-pointer", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter)));
- }
-
- ~CommandObjectMultiwordObjC() override = default;
+ CommandObjectMultiwordObjC(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "objc",
+ "Commands for operating on the Objective-C language runtime.",
+ "objc <subcommand> [<subcommand-options>]") {
+ LoadSubCommand("class-table",
+ CommandObjectSP(
+ new CommandObjectMultiwordObjC_ClassTable(interpreter)));
+ LoadSubCommand("tagged-pointer",
+ CommandObjectSP(new CommandObjectMultiwordObjC_TaggedPointer(
+ interpreter)));
+ }
+
+ ~CommandObjectMultiwordObjC() override = default;
};
-void
-AppleObjCRuntimeV2::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Apple Objective C Language Runtime - Version 2",
- CreateInstance,
- [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP {
- return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
- });
+void AppleObjCRuntimeV2::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 2",
+ CreateInstance,
+ [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
+ return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
+ });
}
-void
-AppleObjCRuntimeV2::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void AppleObjCRuntimeV2::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-AppleObjCRuntimeV2::GetPluginNameStatic()
-{
- static ConstString g_name("apple-objc-v2");
- return g_name;
+lldb_private::ConstString AppleObjCRuntimeV2::GetPluginNameStatic() {
+ static ConstString g_name("apple-objc-v2");
+ return g_name;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-AppleObjCRuntimeV2::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString AppleObjCRuntimeV2::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-AppleObjCRuntimeV2::GetPluginVersion()
-{
- return 1;
-}
+uint32_t AppleObjCRuntimeV2::GetPluginVersion() { return 1; }
BreakpointResolverSP
-AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
-{
- BreakpointResolverSP resolver_sp;
-
- if (throw_bp)
- resolver_sp.reset (new BreakpointResolverName (bkpt,
- "objc_exception_throw",
- eFunctionNameTypeBase,
- eLanguageTypeUnknown,
- Breakpoint::Exact,
- 0,
- eLazyBoolNo));
- // FIXME: We don't do catch breakpoints for ObjC yet.
- // Should there be some way for the runtime to specify what it can do in this regard?
- return resolver_sp;
+AppleObjCRuntimeV2::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
+ bool throw_bp) {
+ BreakpointResolverSP resolver_sp;
+
+ if (throw_bp)
+ resolver_sp.reset(new BreakpointResolverName(
+ bkpt, "objc_exception_throw", eFunctionNameTypeBase,
+ eLanguageTypeUnknown, Breakpoint::Exact, 0, eLazyBoolNo));
+ // FIXME: We don't do catch breakpoints for ObjC yet.
+ // Should there be some way for the runtime to specify what it can do in this
+ // regard?
+ return resolver_sp;
}
-UtilityFunction *
-AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
-{
- char check_function_code[2048];
-
- int len = 0;
- if (m_has_object_getClass)
- {
- len = ::snprintf (check_function_code,
- sizeof(check_function_code),
- "extern \"C\" void *gdb_object_getClass(void *); \n"
- "extern \"C\" int printf(const char *format, ...); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " if ($__lldb_arg_obj == (void *)0) \n"
- " return; // nil is ok \n"
- " if (!gdb_object_getClass($__lldb_arg_obj)) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- " else if ($__lldb_arg_selector != (void *)0) \n"
- " { \n"
- " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
- " respondsToSelector: \n"
- " (struct objc_selector *) $__lldb_arg_selector]; \n"
- " if (responds == (signed char) 0) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- " } \n"
- "} \n",
- name);
- }
- else
- {
- len = ::snprintf (check_function_code,
- sizeof(check_function_code),
- "extern \"C\" void *gdb_class_getClass(void *); \n"
- "extern \"C\" int printf(const char *format, ...); \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " if ($__lldb_arg_obj == (void *)0) \n"
- " return; // nil is ok \n"
- " void **$isa_ptr = (void **)$__lldb_arg_obj; \n"
- " if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr)) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- " else if ($__lldb_arg_selector != (void *)0) \n"
- " { \n"
- " signed char responds = (signed char) [(id) $__lldb_arg_obj \n"
- " respondsToSelector: \n"
- " (struct objc_selector *) $__lldb_arg_selector]; \n"
- " if (responds == (signed char) 0) \n"
- " *((volatile int *)0) = 'ocgc'; \n"
- " } \n"
- "} \n",
- name);
- }
-
- assert (len < (int)sizeof(check_function_code));
-
- Error error;
- return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error);
+UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) {
+ char check_function_code[2048];
+
+ int len = 0;
+ if (m_has_object_getClass) {
+ len = ::snprintf(check_function_code, sizeof(check_function_code),
+ "extern \"C\" void *gdb_object_getClass(void *); "
+ " \n"
+ "extern \"C\" int printf(const char *format, ...); "
+ " \n"
+ "extern \"C\" void "
+ " \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
+ " \n"
+ "{ "
+ " \n"
+ " if ($__lldb_arg_obj == (void *)0) "
+ " \n"
+ " return; // nil is ok "
+ " \n"
+ " if (!gdb_object_getClass($__lldb_arg_obj)) "
+ " \n"
+ " *((volatile int *)0) = 'ocgc'; "
+ " \n"
+ " else if ($__lldb_arg_selector != (void *)0) "
+ " \n"
+ " { "
+ " \n"
+ " signed char responds = (signed char) [(id) "
+ "$__lldb_arg_obj \n"
+ " "
+ "respondsToSelector: \n"
+ " (struct "
+ "objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) "
+ " \n"
+ " *((volatile int *)0) = 'ocgc'; "
+ " \n"
+ " } "
+ " \n"
+ "} "
+ " \n",
+ name);
+ } else {
+ len = ::snprintf(check_function_code, sizeof(check_function_code),
+ "extern \"C\" void *gdb_class_getClass(void *); "
+ " \n"
+ "extern \"C\" int printf(const char *format, ...); "
+ " \n"
+ "extern \"C\" void "
+ " \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
+ " \n"
+ "{ "
+ " \n"
+ " if ($__lldb_arg_obj == (void *)0) "
+ " \n"
+ " return; // nil is ok "
+ " \n"
+ " void **$isa_ptr = (void **)$__lldb_arg_obj; "
+ " \n"
+ " if (*$isa_ptr == (void *)0 || "
+ "!gdb_class_getClass(*$isa_ptr)) \n"
+ " *((volatile int *)0) = 'ocgc'; "
+ " \n"
+ " else if ($__lldb_arg_selector != (void *)0) "
+ " \n"
+ " { "
+ " \n"
+ " signed char responds = (signed char) [(id) "
+ "$__lldb_arg_obj \n"
+ " "
+ "respondsToSelector: \n"
+ " (struct "
+ "objc_selector *) $__lldb_arg_selector]; \n"
+ " if (responds == (signed char) 0) "
+ " \n"
+ " *((volatile int *)0) = 'ocgc'; "
+ " \n"
+ " } "
+ " \n"
+ "} "
+ " \n",
+ name);
+ }
+
+ assert(len < (int)sizeof(check_function_code));
+
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(
+ check_function_code, eLanguageTypeObjC, name, error);
}
-size_t
-AppleObjCRuntimeV2::GetByteOffsetForIvar (CompilerType &parent_ast_type, const char *ivar_name)
-{
- uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
-
- const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
- if (class_name && class_name[0] && ivar_name && ivar_name[0])
- {
- //----------------------------------------------------------------------
- // Make the objective C V2 mangled name for the ivar offset from the
- // class name and ivar name
- //----------------------------------------------------------------------
- std::string buffer("OBJC_IVAR_$_");
- buffer.append (class_name);
- buffer.push_back ('.');
- buffer.append (ivar_name);
- ConstString ivar_const_str (buffer.c_str());
-
- //----------------------------------------------------------------------
- // Try to get the ivar offset address from the symbol table first using
- // the name we created above
- //----------------------------------------------------------------------
- SymbolContextList sc_list;
- Target &target = m_process->GetTarget();
- target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list);
-
- addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
-
- Error error;
- SymbolContext ivar_offset_symbol;
- if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol))
- {
- if (ivar_offset_symbol.symbol)
- ivar_offset_address = ivar_offset_symbol.symbol->GetLoadAddress (&target);
- }
+size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
+ const char *ivar_name) {
+ uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
+
+ const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
+ if (class_name && class_name[0] && ivar_name && ivar_name[0]) {
+ //----------------------------------------------------------------------
+ // Make the objective C V2 mangled name for the ivar offset from the
+ // class name and ivar name
+ //----------------------------------------------------------------------
+ std::string buffer("OBJC_IVAR_$_");
+ buffer.append(class_name);
+ buffer.push_back('.');
+ buffer.append(ivar_name);
+ ConstString ivar_const_str(buffer.c_str());
+
+ //----------------------------------------------------------------------
+ // Try to get the ivar offset address from the symbol table first using
+ // the name we created above
+ //----------------------------------------------------------------------
+ SymbolContextList sc_list;
+ Target &target = m_process->GetTarget();
+ target.GetImages().FindSymbolsWithNameAndType(ivar_const_str,
+ eSymbolTypeObjCIVar, sc_list);
+
+ addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
- //----------------------------------------------------------------------
- // If we didn't get the ivar offset address from the symbol table, fall
- // back to getting it from the runtime
- //----------------------------------------------------------------------
- if (ivar_offset_address == LLDB_INVALID_ADDRESS)
- ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
-
- if (ivar_offset_address != LLDB_INVALID_ADDRESS)
- ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address,
- 4,
- LLDB_INVALID_IVAR_OFFSET,
- error);
+ Error error;
+ SymbolContext ivar_offset_symbol;
+ if (sc_list.GetSize() == 1 &&
+ sc_list.GetContextAtIndex(0, ivar_offset_symbol)) {
+ if (ivar_offset_symbol.symbol)
+ ivar_offset_address =
+ ivar_offset_symbol.symbol->GetLoadAddress(&target);
}
- return ivar_offset;
+
+ //----------------------------------------------------------------------
+ // If we didn't get the ivar offset address from the symbol table, fall
+ // back to getting it from the runtime
+ //----------------------------------------------------------------------
+ if (ivar_offset_address == LLDB_INVALID_ADDRESS)
+ ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
+
+ if (ivar_offset_address != LLDB_INVALID_ADDRESS)
+ ivar_offset = m_process->ReadUnsignedIntegerFromMemory(
+ ivar_offset_address, 4, LLDB_INVALID_IVAR_OFFSET, error);
+ }
+ return ivar_offset;
}
-// tagged pointers are special not-a-real-pointer values that contain both type and value information
-// this routine attempts to check with as little computational effort as possible whether something
-// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't
-bool
-AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr)
-{
- if (!m_tagged_pointer_vendor_ap)
- return false;
- return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
+// tagged pointers are special not-a-real-pointer values that contain both type
+// and value information
+// this routine attempts to check with as little computational effort as
+// possible whether something
+// could possibly be a tagged pointer - false positives are possible but false
+// negatives shouldn't
+bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
+ if (!m_tagged_pointer_vendor_ap)
+ return false;
+ return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr);
}
-class RemoteNXMapTable
-{
+class RemoteNXMapTable {
public:
- RemoteNXMapTable () :
- m_count (0),
- m_num_buckets_minus_one (0),
- m_buckets_ptr (LLDB_INVALID_ADDRESS),
- m_process (NULL),
- m_end_iterator (*this, -1),
- m_load_addr (LLDB_INVALID_ADDRESS),
- m_map_pair_size (0),
- m_invalid_key (0)
- {
+ RemoteNXMapTable()
+ : m_count(0), m_num_buckets_minus_one(0),
+ m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(NULL),
+ m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS),
+ m_map_pair_size(0), m_invalid_key(0) {}
+
+ void Dump() {
+ printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
+ printf("RemoteNXMapTable.m_count = %u\n", m_count);
+ printf("RemoteNXMapTable.m_num_buckets_minus_one = %u\n",
+ m_num_buckets_minus_one);
+ printf("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
+ }
+
+ bool ParseHeader(Process *process, lldb::addr_t load_addr) {
+ m_process = process;
+ m_load_addr = load_addr;
+ m_map_pair_size = m_process->GetAddressByteSize() * 2;
+ m_invalid_key =
+ m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
+ Error err;
+
+ // This currently holds true for all platforms we support, but we might
+ // need to change this to use get the actually byte size of "unsigned"
+ // from the target AST...
+ const uint32_t unsigned_byte_size = sizeof(uint32_t);
+ // Skip the prototype as we don't need it (const struct +NXMapTablePrototype
+ // *prototype)
+
+ bool success = true;
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ success = false;
+ else {
+ lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
+
+ // unsigned count;
+ m_count = m_process->ReadUnsignedIntegerFromMemory(
+ cursor, unsigned_byte_size, 0, err);
+ if (m_count) {
+ cursor += unsigned_byte_size;
+
+ // unsigned nbBucketsMinusOne;
+ m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(
+ cursor, unsigned_byte_size, 0, err);
+ cursor += unsigned_byte_size;
+
+ // void *buckets;
+ m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
+
+ success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
+ }
}
-
- void
- Dump ()
- {
- printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
- printf ("RemoteNXMapTable.m_count = %u\n", m_count);
- printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one);
- printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
+
+ if (!success) {
+ m_count = 0;
+ m_num_buckets_minus_one = 0;
+ m_buckets_ptr = LLDB_INVALID_ADDRESS;
}
-
- bool
- ParseHeader (Process* process, lldb::addr_t load_addr)
- {
- m_process = process;
- m_load_addr = load_addr;
- m_map_pair_size = m_process->GetAddressByteSize() * 2;
- m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
- Error err;
-
- // This currently holds true for all platforms we support, but we might
- // need to change this to use get the actually byte size of "unsigned"
- // from the target AST...
- const uint32_t unsigned_byte_size = sizeof(uint32_t);
- // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype)
-
- bool success = true;
- if (load_addr == LLDB_INVALID_ADDRESS)
- success = false;
- else
- {
- lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
-
- // unsigned count;
- m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
- if (m_count)
- {
- cursor += unsigned_byte_size;
-
- // unsigned nbBucketsMinusOne;
- m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err);
- cursor += unsigned_byte_size;
-
- // void *buckets;
- m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
-
- success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
- }
- }
-
- if (!success)
- {
- m_count = 0;
- m_num_buckets_minus_one = 0;
- m_buckets_ptr = LLDB_INVALID_ADDRESS;
- }
- return success;
+ return success;
+ }
+
+ // const_iterator mimics NXMapState and its code comes from NXInitMapState and
+ // NXNextMapState.
+ typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
+
+ friend class const_iterator;
+ class const_iterator {
+ public:
+ const_iterator(RemoteNXMapTable &parent, int index)
+ : m_parent(parent), m_index(index) {
+ AdvanceToValidIndex();
}
-
- // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
- typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
-
- friend class const_iterator;
- class const_iterator
- {
- public:
- const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index)
- {
- AdvanceToValidIndex();
- }
-
- const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index)
- {
- // AdvanceToValidIndex() has been called by rhs already.
- }
-
- const_iterator &operator=(const const_iterator &rhs)
- {
- // AdvanceToValidIndex() has been called by rhs already.
- assert (&m_parent == &rhs.m_parent);
- m_index = rhs.m_index;
- return *this;
- }
-
- bool operator==(const const_iterator &rhs) const
- {
- if (&m_parent != &rhs.m_parent)
- return false;
- if (m_index != rhs.m_index)
- return false;
-
- return true;
- }
-
- bool operator!=(const const_iterator &rhs) const
- {
- return !(operator==(rhs));
- }
-
- const_iterator &operator++()
- {
- AdvanceToValidIndex();
- return *this;
- }
-
- const element operator*() const
- {
- if (m_index == -1)
- {
- // TODO find a way to make this an error, but not an assert
- return element();
- }
-
- lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
- size_t map_pair_size = m_parent.m_map_pair_size;
- lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
-
- Error err;
-
- lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
- if (!err.Success())
- return element();
- lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
- if (!err.Success())
- return element();
-
- std::string key_string;
-
- m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
- if (!err.Success())
- return element();
-
- return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value);
- }
- private:
- void AdvanceToValidIndex ()
- {
- if (m_index == -1)
- return;
-
- const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
- const size_t map_pair_size = m_parent.m_map_pair_size;
- const lldb::addr_t invalid_key = m_parent.m_invalid_key;
- Error err;
+ const_iterator(const const_iterator &rhs)
+ : m_parent(rhs.m_parent), m_index(rhs.m_index) {
+ // AdvanceToValidIndex() has been called by rhs already.
+ }
- while (m_index--)
- {
- lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
- lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
-
- if (!err.Success())
- {
- m_index = -1;
- return;
- }
-
- if (key != invalid_key)
- return;
- }
- }
- RemoteNXMapTable &m_parent;
- int m_index;
- };
-
- const_iterator begin ()
- {
- return const_iterator(*this, m_num_buckets_minus_one + 1);
+ const_iterator &operator=(const const_iterator &rhs) {
+ // AdvanceToValidIndex() has been called by rhs already.
+ assert(&m_parent == &rhs.m_parent);
+ m_index = rhs.m_index;
+ return *this;
}
-
- const_iterator end ()
- {
- return m_end_iterator;
+
+ bool operator==(const const_iterator &rhs) const {
+ if (&m_parent != &rhs.m_parent)
+ return false;
+ if (m_index != rhs.m_index)
+ return false;
+
+ return true;
}
-
- uint32_t
- GetCount () const
- {
- return m_count;
+
+ bool operator!=(const const_iterator &rhs) const {
+ return !(operator==(rhs));
}
-
- uint32_t
- GetBucketCount () const
- {
- return m_num_buckets_minus_one;
+
+ const_iterator &operator++() {
+ AdvanceToValidIndex();
+ return *this;
}
-
- lldb::addr_t
- GetBucketDataPointer () const
- {
- return m_buckets_ptr;
+
+ const element operator*() const {
+ if (m_index == -1) {
+ // TODO find a way to make this an error, but not an assert
+ return element();
+ }
+
+ lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ size_t map_pair_size = m_parent.m_map_pair_size;
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+
+ Error err;
+
+ lldb::addr_t key =
+ m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+ if (!err.Success())
+ return element();
+ lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(
+ pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
+ if (!err.Success())
+ return element();
+
+ std::string key_string;
+
+ m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
+ if (!err.Success())
+ return element();
+
+ return element(ConstString(key_string.c_str()),
+ (ObjCLanguageRuntime::ObjCISA)value);
}
-
- lldb::addr_t
- GetTableLoadAddress() const
- {
- return m_load_addr;
+
+ private:
+ void AdvanceToValidIndex() {
+ if (m_index == -1)
+ return;
+
+ const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
+ const size_t map_pair_size = m_parent.m_map_pair_size;
+ const lldb::addr_t invalid_key = m_parent.m_invalid_key;
+ Error err;
+
+ while (m_index--) {
+ lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
+ lldb::addr_t key =
+ m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
+
+ if (!err.Success()) {
+ m_index = -1;
+ return;
+ }
+
+ if (key != invalid_key)
+ return;
+ }
}
+ RemoteNXMapTable &m_parent;
+ int m_index;
+ };
+
+ const_iterator begin() {
+ return const_iterator(*this, m_num_buckets_minus_one + 1);
+ }
+
+ const_iterator end() { return m_end_iterator; }
+
+ uint32_t GetCount() const { return m_count; }
+
+ uint32_t GetBucketCount() const { return m_num_buckets_minus_one; }
+
+ lldb::addr_t GetBucketDataPointer() const { return m_buckets_ptr; }
+
+ lldb::addr_t GetTableLoadAddress() const { return m_load_addr; }
private:
- // contents of _NXMapTable struct
- uint32_t m_count;
- uint32_t m_num_buckets_minus_one;
- lldb::addr_t m_buckets_ptr;
- lldb_private::Process *m_process;
- const_iterator m_end_iterator;
- lldb::addr_t m_load_addr;
- size_t m_map_pair_size;
- lldb::addr_t m_invalid_key;
+ // contents of _NXMapTable struct
+ uint32_t m_count;
+ uint32_t m_num_buckets_minus_one;
+ lldb::addr_t m_buckets_ptr;
+ lldb_private::Process *m_process;
+ const_iterator m_end_iterator;
+ lldb::addr_t m_load_addr;
+ size_t m_map_pair_size;
+ lldb::addr_t m_invalid_key;
};
-AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() :
- m_count (0),
- m_num_buckets (0),
- m_buckets_ptr (0)
-{
-}
+AppleObjCRuntimeV2::HashTableSignature::HashTableSignature()
+ : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {}
-void
-AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table)
-{
- m_count = hash_table.GetCount();
- m_num_buckets = hash_table.GetBucketCount();
- m_buckets_ptr = hash_table.GetBucketDataPointer();
+void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
+ const RemoteNXMapTable &hash_table) {
+ m_count = hash_table.GetCount();
+ m_num_buckets = hash_table.GetBucketCount();
+ m_buckets_ptr = hash_table.GetBucketDataPointer();
}
-bool
-AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table)
-{
- if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ()))
- {
- return false; // Failed to parse the header, no need to update anything
- }
-
- // Check with out current signature and return true if the count,
- // number of buckets or the hash table address changes.
- if (m_count == hash_table.GetCount() &&
- m_num_buckets == hash_table.GetBucketCount() &&
- m_buckets_ptr == hash_table.GetBucketDataPointer())
- {
- // Hash table hasn't changed
- return false;
- }
- // Hash table data has changed, we need to update
- return true;
+bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
+ Process *process, AppleObjCRuntimeV2 *runtime,
+ RemoteNXMapTable &hash_table) {
+ if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer())) {
+ return false; // Failed to parse the header, no need to update anything
+ }
+
+ // Check with out current signature and return true if the count,
+ // number of buckets or the hash table address changes.
+ if (m_count == hash_table.GetCount() &&
+ m_num_buckets == hash_table.GetBucketCount() &&
+ m_buckets_ptr == hash_table.GetBucketDataPointer()) {
+ // Hash table hasn't changed
+ return false;
+ }
+ // Hash table data has changed, we need to update
+ return true;
}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::GetClassDescriptorFromISA (ObjCISA isa)
-{
- ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
- if (m_non_pointer_isa_cache_ap.get())
- class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
- if (!class_descriptor_sp)
- class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
- return class_descriptor_sp;
+AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
+ ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
+ if (m_non_pointer_isa_cache_ap.get())
+ class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa);
+ if (!class_descriptor_sp)
+ class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
+ return class_descriptor_sp;
}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
-{
- ClassDescriptorSP objc_class_sp;
- if (valobj.IsBaseClass())
- {
- ValueObject *parent = valobj.GetParent();
- // if I am my own parent, bail out of here fast..
- if (parent && parent != &valobj)
- {
- ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
- if (parent_descriptor_sp)
- return parent_descriptor_sp->GetSuperclass();
- }
- return nullptr;
+AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
+ ClassDescriptorSP objc_class_sp;
+ if (valobj.IsBaseClass()) {
+ ValueObject *parent = valobj.GetParent();
+ // if I am my own parent, bail out of here fast..
+ if (parent && parent != &valobj) {
+ ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
+ if (parent_descriptor_sp)
+ return parent_descriptor_sp->GetSuperclass();
}
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
- if (valobj.GetCompilerType().IsValid())
- {
- addr_t isa_pointer = valobj.GetPointerValue();
-
- // tagged pointer
- if (IsTaggedPointer(isa_pointer))
- {
- return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
- }
- else
- {
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
-
- Process *process = exe_ctx.GetProcessPtr();
- if (process)
- {
- Error error;
- ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
- if (isa != LLDB_INVALID_ADDRESS)
- {
- objc_class_sp = GetClassDescriptorFromISA (isa);
- if (isa && !objc_class_sp)
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64,
- isa_pointer,
- isa);
- }
- }
- }
+ return nullptr;
+ }
+ // if we get an invalid VO (which might still happen when playing around
+ // with pointers returned by the expression parser, don't consider this
+ // a valid ObjC object)
+ if (valobj.GetCompilerType().IsValid()) {
+ addr_t isa_pointer = valobj.GetPointerValue();
+
+ // tagged pointer
+ if (IsTaggedPointer(isa_pointer)) {
+ return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
+ } else {
+ ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process) {
+ Error error;
+ ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
+ if (isa != LLDB_INVALID_ADDRESS) {
+ objc_class_sp = GetClassDescriptorFromISA(isa);
+ if (isa && !objc_class_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("0x%" PRIx64
+ ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
+ "not in class descriptor cache 0x%" PRIx64,
+ isa_pointer, isa);
+ }
}
+ }
}
- return objc_class_sp;
+ }
+ return objc_class_sp;
}
-lldb::addr_t
-AppleObjCRuntimeV2::GetISAHashTablePointer ()
-{
- if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
- {
- Process *process = GetProcess();
+lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
+ Process *process = GetProcess();
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (!objc_module_sp)
- return LLDB_INVALID_ADDRESS;
+ ModuleSP objc_module_sp(GetObjCModule());
- static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
-
- const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
- if (symbol)
- {
- lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetLoadAddress(&process->GetTarget());
-
- if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS)
- {
- Error error;
- m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error);
- }
- }
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
+ if (symbol) {
+ lldb::addr_t gdb_objc_realized_classes_ptr =
+ symbol->GetLoadAddress(&process->GetTarget());
+
+ if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) {
+ Error error;
+ m_isa_hash_table_ptr = process->ReadPointerFromMemory(
+ gdb_objc_realized_classes_ptr, error);
+ }
}
- return m_isa_hash_table_ptr;
+ }
+ return m_isa_hash_table_ptr;
}
-bool
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
-{
- Process *process = GetProcess();
-
- if (process == NULL)
- return false;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- ExecutionContext exe_ctx;
-
- ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
-
- if (!thread_sp)
- return false;
-
- thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
-
- if (!ast)
- return false;
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
+ RemoteNXMapTable &hash_table) {
+ Process *process = GetProcess();
- Address function_address;
+ if (process == NULL)
+ return DescriptorMapUpdateResult::Fail();
- DiagnosticManager diagnostics;
+ uint32_t num_class_infos = 0;
- const uint32_t addr_size = process->GetAddressByteSize();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- Error err;
-
- // Read the total number of classes from the hash table
- const uint32_t num_classes = hash_table.GetCount();
- if (num_classes == 0)
- {
- if (log)
- log->Printf ("No dynamic classes found in gdb_objc_realized_classes.");
- return false;
- }
-
- // Make some types for our arguments
- CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
-
- ValueList arguments;
- FunctionCaller *get_class_info_function = nullptr;
+ ExecutionContext exe_ctx;
- if (!m_get_class_info_code.get())
- {
- Error error;
- m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body,
- eLanguageTypeObjC,
- g_get_dynamic_class_info_name,
- error));
- if (error.Fail())
- {
- if (log)
- log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString());
- m_get_class_info_code.reset();
- }
- else
- {
- diagnostics.Clear();
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
- if (!m_get_class_info_code->Install(diagnostics, exe_ctx))
- {
- if (log)
- {
- log->Printf("Failed to install implementation lookup");
- diagnostics.Dump(log);
- }
- m_get_class_info_code.reset();
- }
- }
- if (!m_get_class_info_code.get())
- return false;
-
- // Next make the runner function for our implementation utility function.
- Value value;
- value.SetValueType (Value::eValueTypeScalar);
- value.SetCompilerType (clang_void_pointer_type);
- arguments.PushValue (value);
- arguments.PushValue (value);
-
- value.SetValueType (Value::eValueTypeScalar);
- value.SetCompilerType (clang_uint32_t_type);
- arguments.PushValue (value);
- arguments.PushValue (value);
-
- get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
- arguments,
- thread_sp,
- error);
-
- if (error.Fail())
- {
- if (log)
- log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString());
- return false;
- }
- }
- else
- {
- get_class_info_function = m_get_class_info_code->GetFunctionCaller();
- if (!get_class_info_function)
- {
- if (log)
- {
- log->Printf("Failed to get implementation lookup function caller.");
- diagnostics.Dump(log);
- }
+ if (!thread_sp)
+ return DescriptorMapUpdateResult::Fail();
- return false;
- }
- arguments = get_class_info_function->GetArgumentValues();
- }
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
- diagnostics.Clear();
+ if (!ast)
+ return DescriptorMapUpdateResult::Fail();
- const uint32_t class_info_byte_size = addr_size + 4;
- const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
- lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size,
- ePermissionsReadable | ePermissionsWritable,
- err);
-
- if (class_infos_addr == LLDB_INVALID_ADDRESS)
- return false;
+ Address function_address;
- std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);
+ DiagnosticManager diagnostics;
- // Fill in our function argument values
- arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
- arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
- arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1);
+ const uint32_t addr_size = process->GetAddressByteSize();
-
- bool success = false;
+ Error err;
- diagnostics.Clear();
+ // Read the total number of classes from the hash table
+ const uint32_t num_classes = hash_table.GetCount();
+ if (num_classes == 0) {
+ if (log)
+ log->Printf("No dynamic classes found in gdb_objc_realized_classes.");
+ return DescriptorMapUpdateResult::Success(0);
+ }
- // Write our function arguments into the process so we can run our function
- if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics))
- {
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(false);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
-
- Value return_value;
- return_value.SetValueType (Value::eValueTypeScalar);
- //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
- return_value.SetCompilerType(clang_uint32_t_type);
- return_value.GetScalar() = 0;
-
- diagnostics.Clear();
-
- // Run the function
- ExpressionResults results = get_class_info_function->ExecuteFunction(exe_ctx, &m_get_class_info_args, options,
- diagnostics, return_value);
-
- if (results == eExpressionCompleted)
- {
- // The result is the number of ClassInfo structures that were filled in
- uint32_t num_class_infos = return_value.GetScalar().ULong();
- if (log)
- log->Printf("Discovered %u ObjC classes\n",num_class_infos);
- if (num_class_infos > 0)
- {
- // Read the ClassInfo structures
- DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
- if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize())
- {
- DataExtractor class_infos_data (buffer.GetBytes(),
- buffer.GetByteSize(),
- process->GetByteOrder(),
- addr_size);
- ParseClassInfoArray (class_infos_data, num_class_infos);
- }
- }
- success = true;
- }
- else
- {
- if (log)
- {
- log->Printf("Error evaluating our find class name function.");
- diagnostics.Dump(log);
- }
+ // Make some types for our arguments
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ ValueList arguments;
+ FunctionCaller *get_class_info_function = nullptr;
+
+ if (!m_get_class_info_code.get()) {
+ Error error;
+ m_get_class_info_code.reset(GetTargetRef().GetUtilityFunctionForLanguage(
+ g_get_dynamic_class_info_body, eLanguageTypeObjC,
+ g_get_dynamic_class_info_name, error));
+ if (error.Fail()) {
+ if (log)
+ log->Printf(
+ "Failed to get Utility Function for implementation lookup: %s",
+ error.AsCString());
+ m_get_class_info_code.reset();
+ } else {
+ diagnostics.Clear();
+
+ if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) {
+ if (log) {
+ log->Printf("Failed to install implementation lookup");
+ diagnostics.Dump(log);
}
+ m_get_class_info_code.reset();
+ }
}
- else
- {
- if (log)
- {
- log->Printf("Error writing function arguments.");
- diagnostics.Dump(log);
+ if (!m_get_class_info_code.get())
+ return DescriptorMapUpdateResult::Fail();
+
+ // Next make the runner function for our implementation utility function.
+ Value value;
+ value.SetValueType(Value::eValueTypeScalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::eValueTypeScalar);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ get_class_info_function = m_get_class_info_code->MakeFunctionCaller(
+ clang_uint32_t_type, arguments, thread_sp, error);
+
+ if (error.Fail()) {
+ if (log)
+ log->Printf(
+ "Failed to make function caller for implementation lookup: %s.",
+ error.AsCString());
+ return DescriptorMapUpdateResult::Fail();
+ }
+ } else {
+ get_class_info_function = m_get_class_info_code->GetFunctionCaller();
+ if (!get_class_info_function) {
+ if (log) {
+ log->Printf("Failed to get implementation lookup function caller.");
+ diagnostics.Dump(log);
+ }
+
+ return DescriptorMapUpdateResult::Fail();
+ }
+ arguments = get_class_info_function->GetArgumentValues();
+ }
+
+ diagnostics.Clear();
+
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory(
+ class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("unable to allocate %" PRIu32
+ " bytes in process for shared cache read",
+ class_infos_byte_size);
+ return DescriptorMapUpdateResult::Fail();
+ }
+
+ std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+ arguments.GetValueAtIndex(3)->GetScalar() =
+ (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1);
+
+ bool success = false;
+
+ diagnostics.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (get_class_info_function->WriteFunctionArguments(
+ exe_ctx, m_get_class_info_args, arguments, diagnostics)) {
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(false);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeout(g_utility_function_timeout);
+
+ Value return_value;
+ return_value.SetValueType(Value::eValueTypeScalar);
+ // return_value.SetContext (Value::eContextTypeClangType,
+ // clang_uint32_t_type);
+ return_value.SetCompilerType(clang_uint32_t_type);
+ return_value.GetScalar() = 0;
+
+ diagnostics.Clear();
+
+ // Run the function
+ ExpressionResults results = get_class_info_function->ExecuteFunction(
+ exe_ctx, &m_get_class_info_args, options, diagnostics, return_value);
+
+ if (results == eExpressionCompleted) {
+ // The result is the number of ClassInfo structures that were filled in
+ num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes\n", num_class_infos);
+ if (num_class_infos > 0) {
+ // Read the ClassInfo structures
+ DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
+ buffer.GetByteSize(),
+ err) == buffer.GetByteSize()) {
+ DataExtractor class_infos_data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(), addr_size);
+ ParseClassInfoArray(class_infos_data, num_class_infos);
}
+ }
+ success = true;
+ } else {
+ if (log) {
+ log->Printf("Error evaluating our find class name function.");
+ diagnostics.Dump(log);
+ }
}
+ } else {
+ if (log) {
+ log->Printf("Error writing function arguments.");
+ diagnostics.Dump(log);
+ }
+ }
- // Deallocate the memory we allocated for the ClassInfo array
- process->DeallocateMemory(class_infos_addr);
-
- return success;
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return DescriptorMapUpdateResult(success, num_class_infos);
}
-uint32_t
-AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos)
-{
- // Parses an array of "num_class_infos" packed ClassInfo structures:
- //
- // struct ClassInfo
- // {
- // Class isa;
- // uint32_t hash;
- // } __attribute__((__packed__));
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- uint32_t num_parsed = 0;
-
- // Iterate through all ClassInfo structures
- lldb::offset_t offset = 0;
- for (uint32_t i=0; i<num_class_infos; ++i)
- {
- ObjCISA isa = data.GetPointer(&offset);
-
- if (isa == 0)
- {
- if (log)
- log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
- continue;
- }
- // Check if we already know about this ISA, if we do, the info will
- // never change, so we can just skip it.
- if (ISAIsCached(isa))
- {
- offset += 4;
- }
- else
- {
- // Read the 32 bit hash for the class name
- const uint32_t name_hash = data.GetU32(&offset);
- ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL));
- AddClass (isa, descriptor_sp, name_hash);
- num_parsed++;
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x, name=%s", isa, name_hash,descriptor_sp->GetClassName().AsCString("<unknown>"));
- }
+uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
+ uint32_t num_class_infos) {
+ // Parses an array of "num_class_infos" packed ClassInfo structures:
+ //
+ // struct ClassInfo
+ // {
+ // Class isa;
+ // uint32_t hash;
+ // } __attribute__((__packed__));
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ uint32_t num_parsed = 0;
+
+ // Iterate through all ClassInfo structures
+ lldb::offset_t offset = 0;
+ for (uint32_t i = 0; i < num_class_infos; ++i) {
+ ObjCISA isa = data.GetPointer(&offset);
+
+ if (isa == 0) {
+ if (log)
+ log->Printf(
+ "AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
+ continue;
}
- return num_parsed;
+ // Check if we already know about this ISA, if we do, the info will
+ // never change, so we can just skip it.
+ if (ISAIsCached(isa)) {
+ if (log)
+ log->Printf("AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
+ ", ignoring this class info",
+ isa);
+ offset += 4;
+ } else {
+ // Read the 32 bit hash for the class name
+ const uint32_t name_hash = data.GetU32(&offset);
+ ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, NULL));
+ AddClass(isa, descriptor_sp, name_hash);
+ num_parsed++;
+ if (log)
+ log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64
+ ", hash=0x%8.8x, name=%s",
+ isa, name_hash,
+ descriptor_sp->GetClassName().AsCString("<unknown>"));
+ }
+ }
+ if (log)
+ log->Printf("AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
+ num_parsed);
+ return num_parsed;
}
AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
-{
- Process *process = GetProcess();
-
- if (process == NULL)
- return DescriptorMapUpdateResult::Fail();
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- ExecutionContext exe_ctx;
-
- ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
-
- if (!thread_sp)
- return DescriptorMapUpdateResult::Fail();
-
- thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
-
- if (!ast)
- return DescriptorMapUpdateResult::Fail();
-
- Address function_address;
-
- DiagnosticManager diagnostics;
-
- const uint32_t addr_size = process->GetAddressByteSize();
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
+ Process *process = GetProcess();
- Error err;
-
- const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
-
- if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
- return DescriptorMapUpdateResult::Fail();
-
- // Read the total number of classes from the hash table
- const uint32_t num_classes = 128*1024;
- if (num_classes == 0)
- {
- if (log)
- log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr.");
- return DescriptorMapUpdateResult::Fail();
- }
-
- // Make some types for our arguments
- CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
- CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
-
- ValueList arguments;
- FunctionCaller *get_shared_cache_class_info_function = nullptr;
-
- if (!m_get_shared_cache_class_info_code.get())
- {
- Error error;
- m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body,
- eLanguageTypeObjC,
- g_get_shared_cache_class_info_name,
- error));
- if (error.Fail())
- {
- if (log)
- log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString());
- m_get_shared_cache_class_info_code.reset();
- }
- else
- {
- diagnostics.Clear();
+ if (process == NULL)
+ return DescriptorMapUpdateResult::Fail();
- if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx))
- {
- if (log)
- {
- log->Printf("Failed to install implementation lookup.");
- diagnostics.Dump(log);
- }
- m_get_shared_cache_class_info_code.reset();
- }
- }
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- if (!m_get_shared_cache_class_info_code.get())
- return DescriptorMapUpdateResult::Fail();
-
- // Next make the function caller for our implementation utility function.
- Value value;
- value.SetValueType (Value::eValueTypeScalar);
- //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
- value.SetCompilerType (clang_void_pointer_type);
- arguments.PushValue (value);
- arguments.PushValue (value);
-
- value.SetValueType (Value::eValueTypeScalar);
- //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
- value.SetCompilerType (clang_uint32_t_type);
- arguments.PushValue (value);
- arguments.PushValue (value);
-
- get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
- arguments,
- thread_sp,
- error);
-
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
-
- }
- else
- {
- get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller();
- if (get_shared_cache_class_info_function == nullptr)
- return DescriptorMapUpdateResult::Fail();
- arguments = get_shared_cache_class_info_function->GetArgumentValues();
- }
+ ExecutionContext exe_ctx;
- diagnostics.Clear();
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
+
+ if (!thread_sp)
+ return DescriptorMapUpdateResult::Fail();
+
+ thread_sp->CalculateExecutionContext(exe_ctx);
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ if (!ast)
+ return DescriptorMapUpdateResult::Fail();
+
+ Address function_address;
+
+ DiagnosticManager diagnostics;
- const uint32_t class_info_byte_size = addr_size + 4;
- const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
- lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
- ePermissionsReadable | ePermissionsWritable,
- err);
-
- if (class_infos_addr == LLDB_INVALID_ADDRESS)
- return DescriptorMapUpdateResult::Fail();
+ const uint32_t addr_size = process->GetAddressByteSize();
- std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex);
+ Error err;
- // Fill in our function argument values
- arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
- arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
- arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1);
-
+ uint32_t num_class_infos = 0;
- bool success = false;
- bool any_found = false;
+ const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
+
+ if (objc_opt_ptr == LLDB_INVALID_ADDRESS)
+ return DescriptorMapUpdateResult::Fail();
+
+ const uint32_t num_classes = 128 * 1024;
+
+ // Make some types for our arguments
+ CompilerType clang_uint32_t_type =
+ ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+ CompilerType clang_void_pointer_type =
+ ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ ValueList arguments;
+ FunctionCaller *get_shared_cache_class_info_function = nullptr;
+
+ if (!m_get_shared_cache_class_info_code.get()) {
+ Error error;
+ m_get_shared_cache_class_info_code.reset(
+ GetTargetRef().GetUtilityFunctionForLanguage(
+ g_get_shared_cache_class_info_body, eLanguageTypeObjC,
+ g_get_shared_cache_class_info_name, error));
+ if (error.Fail()) {
+ if (log)
+ log->Printf(
+ "Failed to get Utility function for implementation lookup: %s.",
+ error.AsCString());
+ m_get_shared_cache_class_info_code.reset();
+ } else {
+ diagnostics.Clear();
+
+ if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) {
+ if (log) {
+ log->Printf("Failed to install implementation lookup.");
+ diagnostics.Dump(log);
+ }
+ m_get_shared_cache_class_info_code.reset();
+ }
+ }
+
+ if (!m_get_shared_cache_class_info_code.get())
+ return DescriptorMapUpdateResult::Fail();
+
+ // Next make the function caller for our implementation utility function.
+ Value value;
+ value.SetValueType(Value::eValueTypeScalar);
+ // value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ value.SetValueType(Value::eValueTypeScalar);
+ // value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
+ value.SetCompilerType(clang_uint32_t_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ get_shared_cache_class_info_function =
+ m_get_shared_cache_class_info_code->MakeFunctionCaller(
+ clang_uint32_t_type, arguments, thread_sp, error);
+
+ if (get_shared_cache_class_info_function == nullptr)
+ return DescriptorMapUpdateResult::Fail();
+
+ } else {
+ get_shared_cache_class_info_function =
+ m_get_shared_cache_class_info_code->GetFunctionCaller();
+ if (get_shared_cache_class_info_function == nullptr)
+ return DescriptorMapUpdateResult::Fail();
+ arguments = get_shared_cache_class_info_function->GetArgumentValues();
+ }
+
+ diagnostics.Clear();
+
+ const uint32_t class_info_byte_size = addr_size + 4;
+ const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
+ lldb::addr_t class_infos_addr = process->AllocateMemory(
+ class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
+
+ if (class_infos_addr == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("unable to allocate %" PRIu32
+ " bytes in process for shared cache read",
+ class_infos_byte_size);
+ return DescriptorMapUpdateResult::Fail();
+ }
+
+ std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex);
+
+ // Fill in our function argument values
+ arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
+ arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
+ arguments.GetValueAtIndex(3)->GetScalar() =
+ (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1);
+
+ bool success = false;
+
+ diagnostics.Clear();
+
+ // Write our function arguments into the process so we can run our function
+ if (get_shared_cache_class_info_function->WriteFunctionArguments(
+ exe_ctx, m_get_shared_cache_class_info_args, arguments,
+ diagnostics)) {
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(false);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeout(g_utility_function_timeout);
+
+ Value return_value;
+ return_value.SetValueType(Value::eValueTypeScalar);
+ // return_value.SetContext (Value::eContextTypeClangType,
+ // clang_uint32_t_type);
+ return_value.SetCompilerType(clang_uint32_t_type);
+ return_value.GetScalar() = 0;
diagnostics.Clear();
- // Write our function arguments into the process so we can run our function
- if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args,
- arguments, diagnostics))
- {
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(false);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC);
-
- Value return_value;
- return_value.SetValueType (Value::eValueTypeScalar);
- //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
- return_value.SetCompilerType(clang_uint32_t_type);
- return_value.GetScalar() = 0;
-
- diagnostics.Clear();
-
- // Run the function
- ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction(
- exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, return_value);
-
- if (results == eExpressionCompleted)
- {
- // The result is the number of ClassInfo structures that were filled in
- uint32_t num_class_infos = return_value.GetScalar().ULong();
- if (log)
- log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos);
+ // Run the function
+ ExpressionResults results =
+ get_shared_cache_class_info_function->ExecuteFunction(
+ exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics,
+ return_value);
+
+ if (results == eExpressionCompleted) {
+ // The result is the number of ClassInfo structures that were filled in
+ num_class_infos = return_value.GetScalar().ULong();
+ if (log)
+ log->Printf("Discovered %u ObjC classes in shared cache\n",
+ num_class_infos);
#ifdef LLDB_CONFIGURATION_DEBUG
- assert (num_class_infos <= num_classes);
+ assert(num_class_infos <= num_classes);
#endif
- if (num_class_infos > 0)
- {
- if (num_class_infos > num_classes)
- {
- num_class_infos = num_classes;
-
- success = false;
- }
- else
- {
- success = true;
- }
-
- // Read the ClassInfo structures
- DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0);
- if (process->ReadMemory(class_infos_addr,
- buffer.GetBytes(),
- buffer.GetByteSize(),
- err) == buffer.GetByteSize())
- {
- DataExtractor class_infos_data (buffer.GetBytes(),
- buffer.GetByteSize(),
- process->GetByteOrder(),
- addr_size);
+ if (num_class_infos > 0) {
+ if (num_class_infos > num_classes) {
+ num_class_infos = num_classes;
- any_found = (ParseClassInfoArray (class_infos_data, num_class_infos) > 0);
- }
- }
- else
- {
- success = true;
- }
+ success = false;
+ } else {
+ success = true;
}
- else
- {
- if (log)
- {
- log->Printf("Error evaluating our find class name function.");
- diagnostics.Dump(log);
- }
+
+ // Read the ClassInfo structures
+ DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
+ if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
+ buffer.GetByteSize(),
+ err) == buffer.GetByteSize()) {
+ DataExtractor class_infos_data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process->GetByteOrder(), addr_size);
+
+ ParseClassInfoArray(class_infos_data, num_class_infos);
}
+ } else {
+ success = true;
+ }
+ } else {
+ if (log) {
+ log->Printf("Error evaluating our find class name function.");
+ diagnostics.Dump(log);
+ }
}
- else
- {
- if (log)
- {
- log->Printf("Error writing function arguments.");
- diagnostics.Dump(log);
- }
+ } else {
+ if (log) {
+ log->Printf("Error writing function arguments.");
+ diagnostics.Dump(log);
}
+ }
- // Deallocate the memory we allocated for the ClassInfo array
- process->DeallocateMemory(class_infos_addr);
-
- return DescriptorMapUpdateResult(success, any_found);
+ // Deallocate the memory we allocated for the ClassInfo array
+ process->DeallocateMemory(class_infos_addr);
+
+ return DescriptorMapUpdateResult(success, num_class_infos);
}
-bool
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- Process *process = GetProcess();
+bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory(
+ RemoteNXMapTable &hash_table) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- if (process == NULL)
- return false;
-
- uint32_t num_map_table_isas = 0;
-
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (objc_module_sp)
- {
- for (RemoteNXMapTable::element elt : hash_table)
- {
- ++num_map_table_isas;
-
- if (ISAIsCached(elt.second))
- continue;
-
- ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString());
-
- AddClass (elt.second, descriptor_sp, elt.first.AsCString());
- }
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return false;
+
+ uint32_t num_map_table_isas = 0;
+
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp) {
+ for (RemoteNXMapTable::element elt : hash_table) {
+ ++num_map_table_isas;
+
+ if (ISAIsCached(elt.second))
+ continue;
+
+ ClassDescriptorSP descriptor_sp = ClassDescriptorSP(
+ new ClassDescriptorV2(*this, elt.second, elt.first.AsCString()));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64
+ " (%s) from dynamic table to isa->descriptor cache",
+ elt.second, elt.first.AsCString());
+
+ AddClass(elt.second, descriptor_sp, elt.first.AsCString());
}
-
- return num_map_table_isas > 0;
+ }
+
+ return num_map_table_isas > 0;
}
-lldb::addr_t
-AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress()
-{
- Process *process = GetProcess();
-
- if (process)
- {
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (objc_module_sp)
- {
- ObjectFile *objc_object = objc_module_sp->GetObjectFile();
-
- if (objc_object)
- {
- SectionList *section_list = objc_module_sp->GetSectionList();
-
- if (section_list)
- {
- SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT")));
-
- if (text_segment_sp)
- {
- SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro")));
-
- if (objc_opt_section_sp)
- {
- return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget());
- }
- }
- }
+lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
+ Process *process = GetProcess();
+
+ if (process) {
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (objc_module_sp) {
+ ObjectFile *objc_object = objc_module_sp->GetObjectFile();
+
+ if (objc_object) {
+ SectionList *section_list = objc_module_sp->GetSectionList();
+
+ if (section_list) {
+ SectionSP text_segment_sp(
+ section_list->FindSectionByName(ConstString("__TEXT")));
+
+ if (text_segment_sp) {
+ SectionSP objc_opt_section_sp(
+ text_segment_sp->GetChildren().FindSectionByName(
+ ConstString("__objc_opt_ro")));
+
+ if (objc_opt_section_sp) {
+ return objc_opt_section_sp->GetLoadBaseAddress(
+ &process->GetTarget());
}
+ }
}
+ }
}
- return LLDB_INVALID_ADDRESS;
+ }
+ return LLDB_INVALID_ADDRESS;
}
-void
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded()
-{
- Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
-
- // Else we need to check with our process to see when the map was updated.
- Process *process = GetProcess();
+void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- if (process)
- {
- RemoteNXMapTable hash_table;
-
- // Update the process stop ID that indicates the last time we updated the
- // map, whether it was successful or not.
- m_isa_to_descriptor_stop_id = process->GetStopID();
-
- if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
- return;
-
- m_hash_signature.UpdateSignature (hash_table);
-
- // Grab the dynamically loaded objc classes from the hash table in memory
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+
+ // Else we need to check with our process to see when the map was updated.
+ Process *process = GetProcess();
+
+ if (process) {
+ RemoteNXMapTable hash_table;
+
+ // Update the process stop ID that indicates the last time we updated the
+ // map, whether it was successful or not.
+ m_isa_to_descriptor_stop_id = process->GetStopID();
+
+ if (!m_hash_signature.NeedsUpdate(process, this, hash_table))
+ return;
+
+ m_hash_signature.UpdateSignature(hash_table);
+
+ // Grab the dynamically loaded objc classes from the hash table in memory
+ DescriptorMapUpdateResult dynamic_update_result =
UpdateISAToDescriptorMapDynamic(hash_table);
- // Now get the objc classes that are baked into the Objective C runtime
- // in the shared cache, but only once per process as this data never
- // changes
- if (!m_loaded_objc_opt)
- {
- DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache();
- if (!shared_cache_update_result.any_found)
- WarnIfNoClassesCached ();
- else
- m_loaded_objc_opt = true;
- }
- }
- else
- {
- m_isa_to_descriptor_stop_id = UINT32_MAX;
+ // Now get the objc classes that are baked into the Objective C runtime
+ // in the shared cache, but only once per process as this data never
+ // changes
+ if (!m_loaded_objc_opt) {
+ // it is legitimately possible for the shared cache to be empty - in that
+ // case, the dynamic hash table
+ // will contain all the class information we need; the situation we're
+ // trying to detect is one where
+ // we aren't seeing class information from the runtime - in order to
+ // detect that vs. just the shared cache
+ // being empty or sparsely populated, we set an arbitrary (very low)
+ // threshold for the number of classes
+ // that we want to see in a "good" scenario - anything below that is
+ // suspicious (Foundation alone has thousands
+ // of classes)
+ const uint32_t num_classes_to_warn_at = 500;
+
+ DescriptorMapUpdateResult shared_cache_update_result =
+ UpdateISAToDescriptorMapSharedCache();
+
+ if (log)
+ log->Printf("attempted to read objc class data - results: "
+ "[dynamic_update]: ran: %s, count: %" PRIu32
+ " [shared_cache_update]: ran: %s, count: %" PRIu32,
+ dynamic_update_result.m_update_ran ? "yes" : "no",
+ dynamic_update_result.m_num_found,
+ shared_cache_update_result.m_update_ran ? "yes" : "no",
+ shared_cache_update_result.m_num_found);
+
+ // warn if:
+ // - we could not run either expression
+ // - we found fewer than num_classes_to_warn_at classes total
+ if ((false == shared_cache_update_result.m_update_ran) ||
+ (false == dynamic_update_result.m_update_ran))
+ WarnIfNoClassesCached(
+ SharedCacheWarningReason::eExpressionExecutionFailure);
+ else if (dynamic_update_result.m_num_found +
+ shared_cache_update_result.m_num_found <
+ num_classes_to_warn_at)
+ WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead);
+ else
+ m_loaded_objc_opt = true;
}
+ } else {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
}
-void
-AppleObjCRuntimeV2::WarnIfNoClassesCached ()
-{
- if (m_noclasses_warning_emitted)
- return;
+static bool DoesProcessHaveSharedCache(Process &process) {
+ PlatformSP platform_sp = process.GetTarget().GetPlatform();
+ if (!platform_sp)
+ return true; // this should not happen
- if (m_process &&
- m_process->GetTarget().GetPlatform() &&
- m_process->GetTarget().GetPlatform()->GetPluginName().GetStringRef().endswith("-simulator"))
- {
- // Simulators do not have the objc_opt_ro class table so don't actually complain to the user
- m_noclasses_warning_emitted = true;
- return;
- }
+ ConstString platform_plugin_name = platform_sp->GetPluginName();
+ if (platform_plugin_name) {
+ llvm::StringRef platform_plugin_name_sr =
+ platform_plugin_name.GetStringRef();
+ if (platform_plugin_name_sr.endswith("-simulator"))
+ return false;
+ }
- Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
-
- if (debugger.GetAsyncOutputStream())
- {
- debugger.GetAsyncOutputStream()->PutCString("warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.\n");
- m_noclasses_warning_emitted = true;
+ return true;
+}
+
+void AppleObjCRuntimeV2::WarnIfNoClassesCached(
+ SharedCacheWarningReason reason) {
+ if (m_noclasses_warning_emitted)
+ return;
+
+ if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) {
+ // Simulators do not have the objc_opt_ro class table so don't actually
+ // complain to the user
+ m_noclasses_warning_emitted = true;
+ return;
+ }
+
+ Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
+ if (auto stream = debugger.GetAsyncOutputStream()) {
+ switch (reason) {
+ case SharedCacheWarningReason::eNotEnoughClassesRead:
+ stream->PutCString("warning: could not find Objective-C class data in "
+ "the process. This may reduce the quality of type "
+ "information available.\n");
+ m_noclasses_warning_emitted = true;
+ break;
+ case SharedCacheWarningReason::eExpressionExecutionFailure:
+ stream->PutCString("warning: could not execute support code to read "
+ "Objective-C class data in the process. This may "
+ "reduce the quality of type information available.\n");
+ m_noclasses_warning_emitted = true;
+ break;
}
+ }
}
-// TODO: should we have a transparent_kvo parameter here to say if we
-// want to replace the KVO swizzled class with the actual user-level type?
ConstString
-AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa)
-{
- if (isa == g_objc_Tagged_ISA)
- {
- static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA");
- return g_objc_tagged_isa_name;
- }
- if (isa == g_objc_Tagged_ISA_NSAtom)
- {
- static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom");
- return g_objc_tagged_isa_nsatom_name;
- }
- if (isa == g_objc_Tagged_ISA_NSNumber)
- {
- static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber");
- return g_objc_tagged_isa_nsnumber_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDateTS)
- {
- static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS");
- return g_objc_tagged_isa_nsdatets_name;
- }
- if (isa == g_objc_Tagged_ISA_NSManagedObject)
- {
- static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject");
- return g_objc_tagged_isa_nsmanagedobject_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDate)
- {
- static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate");
- return g_objc_tagged_isa_nsdate_name;
- }
- return ObjCLanguageRuntime::GetActualTypeName(isa);
+AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
+ if (isa == g_objc_Tagged_ISA) {
+ static const ConstString g_objc_tagged_isa_name("_lldb_Tagged_ObjC_ISA");
+ return g_objc_tagged_isa_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSAtom) {
+ static const ConstString g_objc_tagged_isa_nsatom_name("NSAtom");
+ return g_objc_tagged_isa_nsatom_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSNumber) {
+ static const ConstString g_objc_tagged_isa_nsnumber_name("NSNumber");
+ return g_objc_tagged_isa_nsnumber_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDateTS) {
+ static const ConstString g_objc_tagged_isa_nsdatets_name("NSDateTS");
+ return g_objc_tagged_isa_nsdatets_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSManagedObject) {
+ static const ConstString g_objc_tagged_isa_nsmanagedobject_name(
+ "NSManagedObject");
+ return g_objc_tagged_isa_nsmanagedobject_name;
+ }
+ if (isa == g_objc_Tagged_ISA_NSDate) {
+ static const ConstString g_objc_tagged_isa_nsdate_name("NSDate");
+ return g_objc_tagged_isa_nsdate_name;
+ }
+ return ObjCLanguageRuntime::GetActualTypeName(isa);
}
-DeclVendor *
-AppleObjCRuntimeV2::GetDeclVendor()
-{
- if (!m_decl_vendor_ap.get())
- m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
-
- return m_decl_vendor_ap.get();
+DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
+ if (!m_decl_vendor_ap.get())
+ m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
+
+ return m_decl_vendor_ap.get();
}
-lldb::addr_t
-AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name)
-{
- lldb::addr_t ret = LLDB_INVALID_ADDRESS;
+lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(const ConstString &name) {
+ lldb::addr_t ret = LLDB_INVALID_ADDRESS;
- const char *name_cstr = name.AsCString();
-
- if (name_cstr)
- {
- llvm::StringRef name_strref(name_cstr);
-
- static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
- static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
-
- if (name_strref.startswith(ivar_prefix))
- {
- llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size());
- std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.');
-
- if (class_and_ivar.first.size() && class_and_ivar.second.size())
- {
- const ConstString class_name_cs(class_and_ivar.first);
- ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
-
- if (descriptor)
- {
- const ConstString ivar_name_cs(class_and_ivar.second);
- const char *ivar_name_cstr = ivar_name_cs.AsCString();
-
- auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t
- {
- if (!strcmp(name, ivar_name_cstr))
- {
- ret = offset_addr;
- return true;
- }
- return false;
- };
-
- descriptor->Describe(std::function<void (ObjCISA)>(nullptr),
- std::function<bool (const char *, const char *)>(nullptr),
- std::function<bool (const char *, const char *)>(nullptr),
- ivar_func);
- }
+ const char *name_cstr = name.AsCString();
+
+ if (name_cstr) {
+ llvm::StringRef name_strref(name_cstr);
+
+ static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
+ static const llvm::StringRef class_prefix("OBJC_CLASS_$_");
+
+ if (name_strref.startswith(ivar_prefix)) {
+ llvm::StringRef ivar_skipped_prefix =
+ name_strref.substr(ivar_prefix.size());
+ std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
+ ivar_skipped_prefix.split('.');
+
+ if (class_and_ivar.first.size() && class_and_ivar.second.size()) {
+ const ConstString class_name_cs(class_and_ivar.first);
+ ClassDescriptorSP descriptor =
+ ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor) {
+ const ConstString ivar_name_cs(class_and_ivar.second);
+ const char *ivar_name_cstr = ivar_name_cs.AsCString();
+
+ auto ivar_func = [&ret, ivar_name_cstr](
+ const char *name, const char *type, lldb::addr_t offset_addr,
+ uint64_t size) -> lldb::addr_t {
+ if (!strcmp(name, ivar_name_cstr)) {
+ ret = offset_addr;
+ return true;
}
+ return false;
+ };
+
+ descriptor->Describe(
+ std::function<void(ObjCISA)>(nullptr),
+ std::function<bool(const char *, const char *)>(nullptr),
+ std::function<bool(const char *, const char *)>(nullptr),
+ ivar_func);
}
- else if (name_strref.startswith(class_prefix))
- {
- llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size());
- const ConstString class_name_cs(class_skipped_prefix);
- ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs);
-
- if (descriptor)
- ret = descriptor->GetISA();
- }
+ }
+ } else if (name_strref.startswith(class_prefix)) {
+ llvm::StringRef class_skipped_prefix =
+ name_strref.substr(class_prefix.size());
+ const ConstString class_name_cs(class_skipped_prefix);
+ ClassDescriptorSP descriptor =
+ GetClassDescriptorFromClassName(class_name_cs);
+
+ if (descriptor)
+ ret = descriptor->GetISA();
}
-
- return ret;
+ }
+
+ return ret;
}
-AppleObjCRuntimeV2::NonPointerISACache*
-AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
-{
- Process* process(runtime.GetProcess());
-
- Error error;
-
- auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_isa_magic_mask"),
- objc_module_sp,
- error);
- if (error.Fail())
- return NULL;
+AppleObjCRuntimeV2::NonPointerISACache *
+AppleObjCRuntimeV2::NonPointerISACache::CreateInstance(
+ AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
+ Process *process(runtime.GetProcess());
- auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_isa_magic_value"),
- objc_module_sp,
- error);
- if (error.Fail())
- return NULL;
+ Error error;
- auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_isa_class_mask"),
- objc_module_sp,
- error);
- if (error.Fail())
- return NULL;
-
- // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...)
-
- return new NonPointerISACache(runtime,
- objc_debug_isa_class_mask,
- objc_debug_isa_magic_mask,
- objc_debug_isa_magic_value);
+ auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_isa_magic_value"), objc_module_sp,
+ error);
+ if (error.Fail())
+ return NULL;
+
+ auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error);
+ if (error.Fail())
+ return NULL;
+
+ // we might want to have some rules to outlaw these other values (e.g if the
+ // mask is zero but the value is non-zero, ...)
+
+ return new NonPointerISACache(runtime, objc_debug_isa_class_mask,
+ objc_debug_isa_magic_mask,
+ objc_debug_isa_magic_value);
}
-AppleObjCRuntimeV2::TaggedPointerVendorV2*
-AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp)
-{
- Process* process(runtime.GetProcess());
-
- Error error;
-
- auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_mask"),
- objc_module_sp,
- error);
- if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
-
- auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_slot_shift"),
- objc_module_sp,
- error,
- true,
- 4);
+AppleObjCRuntimeV2::TaggedPointerVendorV2 *
+AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
+ AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
+ Process *process(runtime.GetProcess());
+
+ Error error;
+
+ auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp,
+ error);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_slot_shift"),
+ objc_module_sp, error, true, 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_slot_mask"),
+ objc_module_sp, error, true, 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_payload_lshift"),
+ objc_module_sp, error, true, 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_payload_rshift"),
+ objc_module_sp, error, true, 4);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp,
+ error, false);
+ if (error.Fail())
+ return new TaggedPointerVendorLegacy(runtime);
+
+ // try to detect the "extended tagged pointer" variables - if any are missing,
+ // use the non-extended vendor
+ do {
+ auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_mask"),
+ objc_module_sp, error);
if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
-
- auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_slot_mask"),
- objc_module_sp,
- error,
- true,
- 4);
+ break;
+
+ auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_slot_shift"),
+ objc_module_sp, error, true, 4);
if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
-
- auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_payload_lshift"),
- objc_module_sp,
- error,
- true,
- 4);
+ break;
+
+ auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_slot_mask"),
+ objc_module_sp, error, true, 4);
if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
-
- auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_payload_rshift"),
- objc_module_sp,
- error,
- true,
- 4);
+ break;
+
+ auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_classes"),
+ objc_module_sp, error, false);
if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
-
- auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_classes"),
- objc_module_sp,
- error,
- false);
+ break;
+
+ auto objc_debug_taggedpointer_ext_payload_lshift =
+ ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
+ objc_module_sp, error, true, 4);
if (error.Fail())
- return new TaggedPointerVendorLegacy(runtime);
+ break;
- // try to detect the "extended tagged pointer" variables - if any are missing, use the non-extended vendor
- do
- {
- auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_mask"),
- objc_module_sp,
- error);
- if (error.Fail())
- break;
-
- auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_slot_shift"),
- objc_module_sp,
- error,
- true,
- 4);
- if (error.Fail())
- break;
-
- auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_slot_mask"),
- objc_module_sp,
- error,
- true,
- 4);
- if (error.Fail())
- break;
-
- auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_classes"),
- objc_module_sp,
- error,
- false);
- if (error.Fail())
- break;
-
- auto objc_debug_taggedpointer_ext_payload_lshift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
- objc_module_sp,
- error,
- true,
- 4);
- if (error.Fail())
- break;
-
- auto objc_debug_taggedpointer_ext_payload_rshift = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
- objc_module_sp,
- error,
- true,
- 4);
- if (error.Fail())
- break;
-
- return new TaggedPointerVendorExtended(runtime,
- objc_debug_taggedpointer_mask,
- objc_debug_taggedpointer_ext_mask,
- objc_debug_taggedpointer_slot_shift,
- objc_debug_taggedpointer_ext_slot_shift,
- objc_debug_taggedpointer_slot_mask,
- objc_debug_taggedpointer_ext_slot_mask,
- objc_debug_taggedpointer_payload_lshift,
- objc_debug_taggedpointer_payload_rshift,
- objc_debug_taggedpointer_ext_payload_lshift,
- objc_debug_taggedpointer_ext_payload_rshift,
- objc_debug_taggedpointer_classes,
- objc_debug_taggedpointer_ext_classes);
- } while(false);
-
- // we might want to have some rules to outlaw these values (e.g if the table's address is zero)
-
- return new TaggedPointerVendorRuntimeAssisted(runtime,
- objc_debug_taggedpointer_mask,
- objc_debug_taggedpointer_slot_shift,
- objc_debug_taggedpointer_slot_mask,
- objc_debug_taggedpointer_payload_lshift,
- objc_debug_taggedpointer_payload_rshift,
- objc_debug_taggedpointer_classes);
+ auto objc_debug_taggedpointer_ext_payload_rshift =
+ ExtractRuntimeGlobalSymbol(
+ process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
+ objc_module_sp, error, true, 4);
+ if (error.Fail())
+ break;
+
+ return new TaggedPointerVendorExtended(
+ runtime, objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
+ objc_debug_taggedpointer_ext_slot_shift,
+ objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_ext_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_ext_payload_lshift,
+ objc_debug_taggedpointer_ext_payload_rshift,
+ objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
+ } while (false);
+
+ // we might want to have some rules to outlaw these values (e.g if the table's
+ // address is zero)
+
+ return new TaggedPointerVendorRuntimeAssisted(
+ runtime, objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_classes);
}
-bool
-AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr)
-{
- return (ptr & 1);
+bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer(
+ lldb::addr_t ptr) {
+ return (ptr & 1);
}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr)
-{
- if (!IsPossibleTaggedPointer(ptr))
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- uint32_t foundation_version = m_runtime.GetFoundationVersion();
-
- if (foundation_version == LLDB_INVALID_MODULE_VERSION)
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- uint64_t class_bits = (ptr & 0xE) >> 1;
- ConstString name;
-
- // TODO: make a table
- if (foundation_version >= 900)
- {
- switch (class_bits)
- {
- case 0:
- name = ConstString("NSAtom");
- break;
- case 3:
- name = ConstString("NSNumber");
- break;
- case 4:
- name = ConstString("NSDateTS");
- break;
- case 5:
- name = ConstString("NSManagedObject");
- break;
- case 6:
- name = ConstString("NSDate");
- break;
- default:
- return ObjCLanguageRuntime::ClassDescriptorSP();
- }
+AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
+ lldb::addr_t ptr) {
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uint32_t foundation_version = m_runtime.GetFoundationVersion();
+
+ if (foundation_version == LLDB_INVALID_MODULE_VERSION)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uint64_t class_bits = (ptr & 0xE) >> 1;
+ ConstString name;
+
+ static ConstString g_NSAtom("NSAtom");
+ static ConstString g_NSNumber("NSNumber");
+ static ConstString g_NSDateTS("NSDateTS");
+ static ConstString g_NSManagedObject("NSManagedObject");
+ static ConstString g_NSDate("NSDate");
+
+ if (foundation_version >= 900) {
+ switch (class_bits) {
+ case 0:
+ name = g_NSAtom;
+ break;
+ case 3:
+ name = g_NSNumber;
+ break;
+ case 4:
+ name = g_NSDateTS;
+ break;
+ case 5:
+ name = g_NSManagedObject;
+ break;
+ case 6:
+ name = g_NSDate;
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
}
- else
- {
- switch (class_bits)
- {
- case 1:
- name = ConstString("NSNumber");
- break;
- case 5:
- name = ConstString("NSManagedObject");
- break;
- case 6:
- name = ConstString("NSDate");
- break;
- case 7:
- name = ConstString("NSDateTS");
- break;
- default:
- return ObjCLanguageRuntime::ClassDescriptorSP();
- }
+ } else {
+ switch (class_bits) {
+ case 1:
+ name = g_NSNumber;
+ break;
+ case 5:
+ name = g_NSManagedObject;
+ break;
+ case 6:
+ name = g_NSDate;
+ break;
+ case 7:
+ name = g_NSDateTS;
+ break;
+ default:
+ return ObjCLanguageRuntime::ClassDescriptorSP();
}
- return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr));
+ }
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, ptr));
}
-AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime,
- uint64_t objc_debug_taggedpointer_mask,
- uint32_t objc_debug_taggedpointer_slot_shift,
- uint32_t objc_debug_taggedpointer_slot_mask,
- uint32_t objc_debug_taggedpointer_payload_lshift,
- uint32_t objc_debug_taggedpointer_payload_rshift,
- lldb::addr_t objc_debug_taggedpointer_classes) :
-TaggedPointerVendorV2(runtime),
-m_cache(),
-m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
-m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift),
-m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
-m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift),
-m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift),
-m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes)
-{
-}
-
-bool
-AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr)
-{
- return (ptr & m_objc_debug_taggedpointer_mask) != 0;
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
+ TaggedPointerVendorRuntimeAssisted(
+ AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes)
+ : TaggedPointerVendorV2(runtime), m_cache(),
+ m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
+ m_objc_debug_taggedpointer_slot_shift(
+ objc_debug_taggedpointer_slot_shift),
+ m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
+ m_objc_debug_taggedpointer_payload_lshift(
+ objc_debug_taggedpointer_payload_lshift),
+ m_objc_debug_taggedpointer_payload_rshift(
+ objc_debug_taggedpointer_payload_rshift),
+ m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}
+
+bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
+ IsPossibleTaggedPointer(lldb::addr_t ptr) {
+ return (ptr & m_objc_debug_taggedpointer_mask) != 0;
}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr)
-{
- ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
-
- if (!IsPossibleTaggedPointer(ptr))
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask;
-
- CacheIterator iterator = m_cache.find(slot),
- end = m_cache.end();
- if (iterator != end)
- {
- actual_class_descriptor_sp = iterator->second;
- }
- else
- {
- Process* process(m_runtime.GetProcess());
- uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes;
- Error error;
- uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
- if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
- return nullptr;
- actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
- if (!actual_class_descriptor_sp)
- return ObjCLanguageRuntime::ClassDescriptorSP();
- m_cache[slot] = actual_class_descriptor_sp;
- }
-
- data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift);
-
- return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
+ lldb::addr_t ptr) {
+ ClassDescriptorSP actual_class_descriptor_sp;
+ uint64_t data_payload;
+
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
+ m_objc_debug_taggedpointer_slot_mask;
+
+ CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
+ if (iterator != end) {
+ actual_class_descriptor_sp = iterator->second;
+ } else {
+ Process *process(m_runtime.GetProcess());
+ uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
+ m_objc_debug_taggedpointer_classes;
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 ||
+ slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
+ return nullptr;
+ actual_class_descriptor_sp =
+ m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_cache[slot] = actual_class_descriptor_sp;
+ }
+
+ data_payload =
+ (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >>
+ m_objc_debug_taggedpointer_payload_rshift);
+
+ return ClassDescriptorSP(
+ new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
}
-AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended (AppleObjCRuntimeV2& runtime,
- uint64_t objc_debug_taggedpointer_mask,
- uint64_t objc_debug_taggedpointer_ext_mask,
- uint32_t objc_debug_taggedpointer_slot_shift,
- uint32_t objc_debug_taggedpointer_ext_slot_shift,
- uint32_t objc_debug_taggedpointer_slot_mask,
- uint32_t objc_debug_taggedpointer_ext_slot_mask,
- uint32_t objc_debug_taggedpointer_payload_lshift,
- uint32_t objc_debug_taggedpointer_payload_rshift,
- uint32_t objc_debug_taggedpointer_ext_payload_lshift,
- uint32_t objc_debug_taggedpointer_ext_payload_rshift,
- lldb::addr_t objc_debug_taggedpointer_classes,
- lldb::addr_t objc_debug_taggedpointer_ext_classes) :
-TaggedPointerVendorRuntimeAssisted(runtime,
- objc_debug_taggedpointer_mask,
- objc_debug_taggedpointer_slot_shift,
- objc_debug_taggedpointer_slot_mask,
- objc_debug_taggedpointer_payload_lshift,
- objc_debug_taggedpointer_payload_rshift,
- objc_debug_taggedpointer_classes),
-m_ext_cache(),
-m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
-m_objc_debug_taggedpointer_ext_slot_shift(objc_debug_taggedpointer_ext_slot_shift),
-m_objc_debug_taggedpointer_ext_slot_mask(objc_debug_taggedpointer_ext_slot_mask),
-m_objc_debug_taggedpointer_ext_payload_lshift(objc_debug_taggedpointer_ext_payload_lshift),
-m_objc_debug_taggedpointer_ext_payload_rshift(objc_debug_taggedpointer_ext_payload_rshift),
-m_objc_debug_taggedpointer_ext_classes(objc_debug_taggedpointer_ext_classes)
-{
-}
+AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
+ AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
+ uint64_t objc_debug_taggedpointer_ext_mask,
+ uint32_t objc_debug_taggedpointer_slot_shift,
+ uint32_t objc_debug_taggedpointer_ext_slot_shift,
+ uint32_t objc_debug_taggedpointer_slot_mask,
+ uint32_t objc_debug_taggedpointer_ext_slot_mask,
+ uint32_t objc_debug_taggedpointer_payload_lshift,
+ uint32_t objc_debug_taggedpointer_payload_rshift,
+ uint32_t objc_debug_taggedpointer_ext_payload_lshift,
+ uint32_t objc_debug_taggedpointer_ext_payload_rshift,
+ lldb::addr_t objc_debug_taggedpointer_classes,
+ lldb::addr_t objc_debug_taggedpointer_ext_classes)
+ : TaggedPointerVendorRuntimeAssisted(
+ runtime, objc_debug_taggedpointer_mask,
+ objc_debug_taggedpointer_slot_shift,
+ objc_debug_taggedpointer_slot_mask,
+ objc_debug_taggedpointer_payload_lshift,
+ objc_debug_taggedpointer_payload_rshift,
+ objc_debug_taggedpointer_classes),
+ m_ext_cache(),
+ m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
+ m_objc_debug_taggedpointer_ext_slot_shift(
+ objc_debug_taggedpointer_ext_slot_shift),
+ m_objc_debug_taggedpointer_ext_slot_mask(
+ objc_debug_taggedpointer_ext_slot_mask),
+ m_objc_debug_taggedpointer_ext_payload_lshift(
+ objc_debug_taggedpointer_ext_payload_lshift),
+ m_objc_debug_taggedpointer_ext_payload_rshift(
+ objc_debug_taggedpointer_ext_payload_rshift),
+ m_objc_debug_taggedpointer_ext_classes(
+ objc_debug_taggedpointer_ext_classes) {}
+
+bool AppleObjCRuntimeV2::TaggedPointerVendorExtended::
+ IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) {
+ if (!IsPossibleTaggedPointer(ptr))
+ return false;
-bool
-AppleObjCRuntimeV2::TaggedPointerVendorExtended::IsPossibleExtendedTaggedPointer (lldb::addr_t ptr)
-{
- if (!IsPossibleTaggedPointer(ptr))
- return false;
-
- if (m_objc_debug_taggedpointer_ext_mask == 0)
- return false;
-
- return ((ptr & m_objc_debug_taggedpointer_ext_mask) == m_objc_debug_taggedpointer_ext_mask);
+ if (m_objc_debug_taggedpointer_ext_mask == 0)
+ return false;
+
+ return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
+ m_objc_debug_taggedpointer_ext_mask);
}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor (lldb::addr_t ptr)
-{
- ClassDescriptorSP actual_class_descriptor_sp;
- uint64_t data_payload;
-
- if (!IsPossibleTaggedPointer(ptr))
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- if (!IsPossibleExtendedTaggedPointer(ptr))
- return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
-
- uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & m_objc_debug_taggedpointer_ext_slot_mask;
-
- CacheIterator iterator = m_ext_cache.find(slot),
- end = m_ext_cache.end();
- if (iterator != end)
- {
- actual_class_descriptor_sp = iterator->second;
- }
- else
- {
- Process* process(m_runtime.GetProcess());
- uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_ext_classes;
- Error error;
- uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
- if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
- return nullptr;
- actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
- if (!actual_class_descriptor_sp)
- return ObjCLanguageRuntime::ClassDescriptorSP();
- m_ext_cache[slot] = actual_class_descriptor_sp;
- }
-
- data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift);
-
- return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload));
+AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
+ lldb::addr_t ptr) {
+ ClassDescriptorSP actual_class_descriptor_sp;
+ uint64_t data_payload;
+
+ if (!IsPossibleTaggedPointer(ptr))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ if (!IsPossibleExtendedTaggedPointer(ptr))
+ return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
+
+ uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
+ m_objc_debug_taggedpointer_ext_slot_mask;
+
+ CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
+ if (iterator != end) {
+ actual_class_descriptor_sp = iterator->second;
+ } else {
+ Process *process(m_runtime.GetProcess());
+ uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
+ m_objc_debug_taggedpointer_ext_classes;
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 ||
+ slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
+ return nullptr;
+ actual_class_descriptor_sp =
+ m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_ext_cache[slot] = actual_class_descriptor_sp;
+ }
+
+ data_payload =
+ (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ m_objc_debug_taggedpointer_ext_payload_rshift);
+
+ return ClassDescriptorSP(
+ new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
}
-AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
- uint64_t objc_debug_isa_class_mask,
- uint64_t objc_debug_isa_magic_mask,
- uint64_t objc_debug_isa_magic_value) :
-m_runtime(runtime),
-m_cache(),
-m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
-m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
-m_objc_debug_isa_magic_value(objc_debug_isa_magic_value)
-{
-}
+AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
+ AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask, uint64_t objc_debug_isa_magic_value)
+ : m_runtime(runtime), m_cache(),
+ m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
+ m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
+ m_objc_debug_isa_magic_value(objc_debug_isa_magic_value) {}
ObjCLanguageRuntime::ClassDescriptorSP
-AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa)
-{
- ObjCISA real_isa = 0;
- if (EvaluateNonPointerISA(isa, real_isa) == false)
- return ObjCLanguageRuntime::ClassDescriptorSP();
- auto cache_iter = m_cache.find(real_isa);
- if (cache_iter != m_cache.end())
- return cache_iter->second;
- auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
- if (descriptor_sp) // cache only positive matches since the table might grow
- m_cache[real_isa] = descriptor_sp;
- return descriptor_sp;
+AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
+ ObjCISA real_isa = 0;
+ if (EvaluateNonPointerISA(isa, real_isa) == false)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ auto cache_iter = m_cache.find(real_isa);
+ if (cache_iter != m_cache.end())
+ return cache_iter->second;
+ auto descriptor_sp =
+ m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
+ if (descriptor_sp) // cache only positive matches since the table might grow
+ m_cache[real_isa] = descriptor_sp;
+ return descriptor_sp;
}
-bool
-AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa)
-{
- if ( (isa & ~m_objc_debug_isa_class_mask) == 0)
- return false;
- if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value)
- {
- ret_isa = isa & m_objc_debug_isa_class_mask;
- return (ret_isa != 0); // this is a pointer so 0 is not a valid value
- }
+bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
+ ObjCISA isa, ObjCISA &ret_isa) {
+ if ((isa & ~m_objc_debug_isa_class_mask) == 0)
return false;
+ if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
+ ret_isa = isa & m_objc_debug_isa_class_mask;
+ return (ret_isa != 0); // this is a pointer so 0 is not a valid value
+ }
+ return false;
}
-ObjCLanguageRuntime::EncodingToTypeSP
-AppleObjCRuntimeV2::GetEncodingToType ()
-{
- if (!m_encoding_to_type_sp)
- m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this));
- return m_encoding_to_type_sp;
+ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() {
+ if (!m_encoding_to_type_sp)
+ m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this));
+ return m_encoding_to_type_sp;
}
lldb_private::AppleObjCRuntime::ObjCISA
-AppleObjCRuntimeV2::GetPointerISA (ObjCISA isa)
-{
- ObjCISA ret = isa;
-
- if (m_non_pointer_isa_cache_ap)
- m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret);
-
- return ret;
+AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
+ ObjCISA ret = isa;
+
+ if (m_non_pointer_isa_cache_ap)
+ m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret);
+
+ return ret;
+}
+
+bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
+ if (m_CFBoolean_values)
+ return true;
+
+ static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
+ static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
+
+ std::function<lldb::addr_t(ConstString)> get_symbol =
+ [this](ConstString sym) -> lldb::addr_t {
+ SymbolContextList sc_list;
+ if (GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
+ g_kCFBooleanFalse, lldb::eSymbolTypeData, sc_list) == 1) {
+ SymbolContext sc;
+ sc_list.GetContextAtIndex(0, sc);
+ if (sc.symbol)
+ return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
+ }
+
+ return LLDB_INVALID_ADDRESS;
+ };
+
+ lldb::addr_t false_addr = get_symbol(g_kCFBooleanFalse);
+ lldb::addr_t true_addr = get_symbol(g_kCFBooleanTrue);
+
+ return (m_CFBoolean_values = {false_addr, true_addr}).operator bool();
+}
+
+void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
+ lldb::addr_t &cf_false) {
+ if (GetCFBooleanValuesIfNeeded()) {
+ cf_true = m_CFBoolean_values->second;
+ cf_false = m_CFBoolean_values->first;
+ } else
+ this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
}