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.cpp576
1 files changed, 436 insertions, 140 deletions
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 584449430829..e9a799bb3651 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -36,12 +36,14 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
@@ -60,9 +62,6 @@
#include "AppleObjCDeclVendor.h"
#include "AppleObjCTrampolineHandler.h"
-#if defined(__APPLE__)
-#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
-#endif
using namespace lldb;
using namespace lldb_private;
@@ -81,12 +80,7 @@ extern "C"
char *strncpy (char * s1, const char * s2, size_t n);
int printf(const char * format, ...);
}
-//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
-#ifdef ENABLE_DEBUG_PRINTF
-#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_PRINTF(fmt, ...)
-#endif
+#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
typedef struct _NXMapTable {
void *prototype;
@@ -112,7 +106,8 @@ struct ClassInfo
uint32_t
__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
void *class_infos_ptr,
- uint32_t class_infos_byte_size)
+ uint32_t class_infos_byte_size,
+ uint32_t should_log)
{
DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
@@ -170,12 +165,7 @@ extern "C"
int printf(const char * format, ...);
}
-// #define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
-#ifdef ENABLE_DEBUG_PRINTF
-#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
-#else
-#define DEBUG_PRINTF(fmt, ...)
-#endif
+#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
struct objc_classheader_t {
@@ -224,12 +214,13 @@ struct ClassInfo
uint32_t
__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
void *class_infos_ptr,
- uint32_t class_infos_byte_size)
+ uint32_t class_infos_byte_size,
+ uint32_t should_log)
{
uint32_t idx = 0;
DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
- DEBUG_PRINTF ("class_infos_byte_size = %u (%" PRIu64 " class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo)));
+ DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
if (objc_opt_ro_ptr)
{
const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
@@ -250,7 +241,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
}
- if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14)
+ if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15)
{
const objc_clsopt_t* clsopt = NULL;
if (is_v14_format)
@@ -258,6 +249,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
else
clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
+ DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
int32_t invalidEntryOffset = 0;
// this is safe to do because the version field order is invariant
@@ -269,13 +261,21 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
+ DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset);
for (uint32_t i=0; i<clsopt->capacity; ++i)
{
const int32_t clsOffset = classOffsets[i].clsOffset;
+ DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset);
if (clsOffset & 1)
+ {
+ DEBUG_PRINTF("clsOffset & 1\n");
continue; // duplicate
+ }
else if (clsOffset == invalidEntryOffset)
+ {
+ DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
continue; // invalid offset
+ }
if (class_infos && idx < max_class_infos)
{
@@ -289,6 +289,10 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
h = ((h << 5) + h) + c;
class_infos[idx].hash = h;
}
+ else
+ {
+ DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
+ }
++idx;
}
@@ -375,27 +379,27 @@ ExtractRuntimeGlobalSymbol (Process* process,
}
}
-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 (Mutex::eMutexTypeNormal),
- 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 (Mutex::eMutexTypeNormal),
- 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)
+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_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_has_object_getClass =
+ (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL);
}
bool
@@ -485,6 +489,52 @@ AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language)
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;
+ }
+
+ OptionValueBoolean m_verbose;
+ static OptionDefinition g_option_table[];
+ };
+
CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"dump",
@@ -492,39 +542,116 @@ public:
"language objc class-table dump",
eCommandRequiresProcess |
eCommandProcessMustBeLaunched |
- eCommandProcessMustBePaused )
+ 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);
}
~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++)
{
- result.GetOutputStream().Printf("isa = 0x%" PRIx64, iterator->first);
if (iterator->second)
{
- result.GetOutputStream().Printf(" name = %s", iterator->second->GetClassName().AsCString("<unknown>"));
- result.GetOutputStream().Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize());
- result.GetOutputStream().Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars());
+ 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())
{
- result.GetOutputStream().Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>"));
+ 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);
}
- result.GetOutputStream().Printf("\n");
}
else
{
- result.GetOutputStream().Printf(" has no associated class.\n");
+ if (regex_up && !regex_up->Execute(""))
+ continue;
+ std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n", iterator->first);
}
}
result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
@@ -537,6 +664,15 @@ protected:
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 }
};
class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed
@@ -639,11 +775,9 @@ protected:
class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword
{
public:
- CommandObjectMultiwordObjC_ClassTable (CommandInterpreter &interpreter) :
- CommandObjectMultiword (interpreter,
- "class-table",
- "A set of commands for operating on the Objective-C class table.",
- "class-table <subcommand> [<subcommand-options>]")
+ 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)));
}
@@ -654,12 +788,10 @@ public:
class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword
{
public:
-
- CommandObjectMultiwordObjC_TaggedPointer (CommandInterpreter &interpreter) :
- CommandObjectMultiword (interpreter,
- "tagged-pointer",
- "A set of commands for operating on Objective-C tagged pointers.",
- "class-table <subcommand> [<subcommand-options>]")
+ 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)));
}
@@ -670,11 +802,9 @@ public:
class CommandObjectMultiwordObjC : public CommandObjectMultiword
{
public:
- CommandObjectMultiwordObjC (CommandInterpreter &interpreter) :
- CommandObjectMultiword (interpreter,
- "objc",
- "A set of commands for operating on the Objective-C Language Runtime.",
- "objc <subcommand> [<subcommand-options>]")
+ 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)));
@@ -733,6 +863,7 @@ AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo
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?
@@ -1231,7 +1362,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
ExecutionContext exe_ctx;
- ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
if (!thread_sp)
return false;
@@ -1241,13 +1372,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
if (!ast)
return false;
-
+
Address function_address;
-
- StreamString errors;
-
+
+ DiagnosticManager diagnostics;
+
const uint32_t addr_size = process->GetAddressByteSize();
-
+
Error err;
// Read the total number of classes from the hash table
@@ -1281,12 +1412,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
}
else
{
- errors.Clear();
-
- if (!m_get_class_info_code->Install(errors, exe_ctx))
+ diagnostics.Clear();
+
+ if (!m_get_class_info_code->Install(diagnostics, exe_ctx))
{
if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ {
+ log->Printf("Failed to install implementation lookup");
+ diagnostics.Dump(log);
+ }
m_get_class_info_code.reset();
}
}
@@ -1303,9 +1437,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
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())
@@ -1321,14 +1457,18 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
if (!get_class_info_function)
{
if (log)
- log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData());
+ {
+ log->Printf("Failed to get implementation lookup function caller.");
+ diagnostics.Dump(log);
+ }
+
return false;
}
arguments = get_class_info_function->GetArgumentValues();
}
- errors.Clear();
-
+ 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,
@@ -1337,23 +1477,22 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
if (class_infos_addr == LLDB_INVALID_ADDRESS)
return false;
-
- Mutex::Locker locker(m_get_class_info_args_mutex);
-
+
+ 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;
-
- errors.Clear();
-
+
+ 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,
- errors))
+ if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics))
{
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@@ -1365,18 +1504,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
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.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
-
- errors.Clear();
-
+
+ diagnostics.Clear();
+
// Run the function
- ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx,
- &m_get_class_info_args,
- options,
- errors,
- return_value);
-
+ 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
@@ -1401,15 +1537,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
else
{
if (log)
- log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
+ {
+ log->Printf("Error evaluating our find class name function.");
+ diagnostics.Dump(log);
+ }
}
}
else
{
if (log)
- log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ {
+ log->Printf("Error writing function arguments.");
+ diagnostics.Dump(log);
+ }
}
-
+
// Deallocate the memory we allocated for the ClassInfo array
process->DeallocateMemory(class_infos_addr);
@@ -1475,7 +1617,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
ExecutionContext exe_ctx;
- ThreadSP thread_sp = process->GetThreadList().GetSelectedThread();
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
if (!thread_sp)
return DescriptorMapUpdateResult::Fail();
@@ -1485,13 +1627,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
if (!ast)
return DescriptorMapUpdateResult::Fail();
-
+
Address function_address;
-
- StreamString errors;
-
+
+ DiagnosticManager diagnostics;
+
const uint32_t addr_size = process->GetAddressByteSize();
-
+
Error err;
const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress();
@@ -1530,16 +1672,19 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
}
else
{
- errors.Clear();
-
- if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
+ diagnostics.Clear();
+
+ if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx))
{
if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ {
+ 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();
@@ -1555,9 +1700,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
//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)
@@ -1571,9 +1718,9 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
return DescriptorMapUpdateResult::Fail();
arguments = get_shared_cache_class_info_function->GetArgumentValues();
}
-
- errors.Clear();
-
+
+ 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,
@@ -1582,24 +1729,24 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
if (class_infos_addr == LLDB_INVALID_ADDRESS)
return DescriptorMapUpdateResult::Fail();
-
- Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex);
-
+
+ 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;
bool any_found = false;
-
- errors.Clear();
-
+
+ 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,
- errors))
+ if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args,
+ arguments, diagnostics))
{
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@@ -1611,18 +1758,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
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.SetCompilerType(clang_uint32_t_type);
return_value.GetScalar() = 0;
-
- errors.Clear();
-
+
+ diagnostics.Clear();
+
// Run the function
- ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
- &m_get_shared_cache_class_info_args,
- options,
- errors,
- return_value);
-
+ 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
@@ -1668,15 +1812,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
else
{
if (log)
- log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData());
+ {
+ log->Printf("Error evaluating our find class name function.");
+ diagnostics.Dump(log);
+ }
}
}
else
{
if (log)
- log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
+ {
+ log->Printf("Error writing function arguments.");
+ diagnostics.Dump(log);
+ }
}
-
+
// Deallocate the memory we allocated for the ClassInfo array
process->DeallocateMemory(class_infos_addr);
@@ -1803,17 +1953,14 @@ AppleObjCRuntimeV2::WarnIfNoClassesCached ()
if (m_noclasses_warning_emitted)
return;
-#if defined(__APPLE__)
if (m_process &&
m_process->GetTarget().GetPlatform() &&
- m_process->GetTarget().GetPlatform()->GetPluginName() == PlatformiOSSimulator::GetPluginNameStatic())
+ m_process->GetTarget().GetPlatform()->GetPluginName().GetStringRef().endswith("-simulator"))
{
- // the iOS simulator does not have the objc_opt_ro class table
- // so don't actually complain to the user
+ // Simulators do not have the objc_opt_ro class table so don't actually complain to the user
m_noclasses_warning_emitted = true;
return;
}
-#endif
Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
@@ -2025,6 +2172,74 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& r
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())
+ 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)
@@ -2164,6 +2379,87 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb
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)
+{
+}
+
+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);
+}
+
+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::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime,
uint64_t objc_debug_isa_class_mask,
uint64_t objc_debug_isa_magic_mask,