*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index c49feb0..c5fe21c 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -1,4 +1,5 @@
-//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
+//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*-
+//C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -40,579 +41,535 @@
static const char *vtable_demangled_prefix = "vtable for ";
-bool
-ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
-{
- const bool check_cxx = true;
- const bool check_objc = false;
- return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
+bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ const bool check_cxx = true;
+ const bool check_objc = false;
+ return in_value.GetCompilerType().IsPossibleDynamicType(NULL, check_cxx,
+ check_objc);
}
-TypeAndOrName
-ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr,
- lldb::addr_t vtable_load_addr)
-{
- if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS)
- {
- // Find the symbol that contains the "vtable_load_addr" address
- Address vtable_addr;
- Target &target = m_process->GetTarget();
- if (!target.GetSectionLoadList().IsEmpty())
- {
- if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, vtable_addr))
- {
- // See if we have cached info for this type already
- TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr);
- if (type_info)
- return type_info;
+TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
+ ValueObject &in_value, lldb::addr_t original_ptr,
+ lldb::addr_t vtable_load_addr) {
+ if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) {
+ // Find the symbol that contains the "vtable_load_addr" address
+ Address vtable_addr;
+ Target &target = m_process->GetTarget();
+ if (!target.GetSectionLoadList().IsEmpty()) {
+ if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr,
+ vtable_addr)) {
+ // See if we have cached info for this type already
+ TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr);
+ if (type_info)
+ return type_info;
- SymbolContext sc;
- target.GetImages().ResolveSymbolContextForAddress(vtable_addr, eSymbolContextSymbol, sc);
- Symbol *symbol = sc.symbol;
- if (symbol != NULL)
- {
- const char *name = symbol->GetMangled().GetDemangledName(lldb::eLanguageTypeC_plus_plus).AsCString();
- if (name && strstr(name, vtable_demangled_prefix) == name)
- {
- Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
- if (log)
- log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
- original_ptr,
- in_value.GetTypeName().GetCString(),
- name);
- // We are a C++ class, that's good. Get the class name and look it up:
- const char *class_name = name + strlen(vtable_demangled_prefix);
- type_info.SetName(class_name);
- const bool exact_match = true;
- TypeList class_types;
+ SymbolContext sc;
+ target.GetImages().ResolveSymbolContextForAddress(
+ vtable_addr, eSymbolContextSymbol, sc);
+ Symbol *symbol = sc.symbol;
+ if (symbol != NULL) {
+ const char *name =
+ symbol->GetMangled()
+ .GetDemangledName(lldb::eLanguageTypeC_plus_plus)
+ .AsCString();
+ if (name && strstr(name, vtable_demangled_prefix) == name) {
+ Log *log(
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("0x%16.16" PRIx64
+ ": static-type = '%s' has vtable symbol '%s'\n",
+ original_ptr, in_value.GetTypeName().GetCString(),
+ name);
+ // We are a C++ class, that's good. Get the class name and look it
+ // up:
+ const char *class_name = name + strlen(vtable_demangled_prefix);
+ type_info.SetName(class_name);
+ const bool exact_match = true;
+ TypeList class_types;
- uint32_t num_matches = 0;
- // First look in the module that the vtable symbol came from
- // and look for a single exact match.
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- if (sc.module_sp)
- {
- num_matches = sc.module_sp->FindTypes (sc,
- ConstString(class_name),
- exact_match,
- 1,
- searched_symbol_files,
- class_types);
- }
-
- // If we didn't find a symbol, then move on to the entire
- // module list in the target and get as many unique matches
- // as possible
- if (num_matches == 0)
- {
- num_matches = target.GetImages().FindTypes(sc, ConstString(class_name), exact_match,
- UINT32_MAX, searched_symbol_files, class_types);
- }
-
- lldb::TypeSP type_sp;
- if (num_matches == 0)
- {
- if (log)
- log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
- return TypeAndOrName();
- }
- if (num_matches == 1)
- {
- type_sp = class_types.GetTypeAtIndex(0);
- if (type_sp)
- {
- if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType()))
- {
- if (log)
- log->Printf("0x%16.16" PRIx64
- ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
- "}, type-name='%s'\n",
- original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(),
- type_sp->GetName().GetCString());
- type_info.SetTypeSP(type_sp);
- }
- }
- }
- else if (num_matches > 1)
- {
- size_t i;
- if (log)
- {
- for (i = 0; i < num_matches; i++)
- {
- type_sp = class_types.GetTypeAtIndex(i);
- if (type_sp)
- {
- if (log)
- log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
- original_ptr,
- in_value.GetTypeName().AsCString(),
- type_sp->GetID(),
- type_sp->GetName().GetCString());
- }
- }
- }
-
- for (i = 0; i < num_matches; i++)
- {
- type_sp = class_types.GetTypeAtIndex(i);
- if (type_sp)
- {
- if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType()))
- {
- if (log)
- log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
- original_ptr,
- in_value.GetTypeName().AsCString(),
- type_sp->GetID(),
- type_sp->GetName().GetCString());
- type_info.SetTypeSP(type_sp);
- }
- }
- }
-
- if (log && i == num_matches)
- {
- log->Printf("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic "
- "types, didn't find a C++ match\n",
- original_ptr, in_value.GetTypeName().AsCString());
- }
- }
- if (type_info)
- SetDynamicTypeInfo(vtable_addr, type_info);
- return type_info;
- }
- }
+ uint32_t num_matches = 0;
+ // First look in the module that the vtable symbol came from
+ // and look for a single exact match.
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ if (sc.module_sp) {
+ num_matches = sc.module_sp->FindTypes(
+ sc, ConstString(class_name), exact_match, 1,
+ searched_symbol_files, class_types);
}
- }
- }
- return TypeAndOrName();
-}
-bool
-ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &dynamic_address,
- Value::ValueType &value_type)
-{
- // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
- // in the object. That will point to the "address point" within the vtable (not the beginning of the
- // vtable.) We can then look up the symbol containing this "address point" and that symbol's name
- // demangled will contain the full class name.
- // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the
- // start of the value object which holds the dynamic type.
- //
-
- class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
-
- // Only a pointer or reference type can have a different dynamic and static type:
- if (CouldHaveDynamicValue(in_value))
- {
- // First job, pull out the address at 0 offset from the object.
- AddressType address_type;
- lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
- if (original_ptr == LLDB_INVALID_ADDRESS)
- return false;
-
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process == nullptr)
- return false;
-
- Error error;
- const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error);
-
- if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS)
- {
- return false;
- }
-
- class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point);
-
- if (class_type_or_name)
- {
- TypeSP type_sp = class_type_or_name.GetTypeSP();
- // There can only be one type with a given name,
- // so we've just found duplicate definitions, and this
- // one will do as well as any other.
- // We don't consider something to have a dynamic type if
- // it is the same as the static type. So compare against
- // the value we were handed.
- if (type_sp)
- {
- if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType()))
- {
- // The dynamic type we found was the same type,
- // so we don't have a dynamic type here...
- return false;
- }
-
- // The offset_to_top is two pointers above the vtable pointer.
- const uint32_t addr_byte_size = process->GetAddressByteSize();
- const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size;
- // Watch for underflow, offset_to_top_location should be less than vtable_address_point
- if (offset_to_top_location >= vtable_address_point)
- return false;
- const int64_t offset_to_top =
- process->ReadSignedIntegerFromMemory(offset_to_top_location, addr_byte_size, INT64_MIN, error);
-
- if (offset_to_top == INT64_MIN)
- return false;
- // So the dynamic type is a value that starts at offset_to_top
- // above the original address.
- lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
- if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(dynamic_addr, dynamic_address))
- {
- dynamic_address.SetRawAddress(dynamic_addr);
- }
- return true;
+ // If we didn't find a symbol, then move on to the entire
+ // module list in the target and get as many unique matches
+ // as possible
+ if (num_matches == 0) {
+ num_matches = target.GetImages().FindTypes(
+ sc, ConstString(class_name), exact_match, UINT32_MAX,
+ searched_symbol_files, class_types);
}
+
+ lldb::TypeSP type_sp;
+ if (num_matches == 0) {
+ if (log)
+ log->Printf("0x%16.16" PRIx64 ": is not dynamic\n",
+ original_ptr);
+ return TypeAndOrName();
+ }
+ if (num_matches == 1) {
+ type_sp = class_types.GetTypeAtIndex(0);
+ if (type_sp) {
+ if (ClangASTContext::IsCXXClassType(
+ type_sp->GetForwardCompilerType())) {
+ if (log)
+ log->Printf(
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has dynamic type: uid={0x%" PRIx64
+ "}, type-name='%s'\n",
+ original_ptr, in_value.GetTypeName().AsCString(),
+ type_sp->GetID(), type_sp->GetName().GetCString());
+ type_info.SetTypeSP(type_sp);
+ }
+ }
+ } else if (num_matches > 1) {
+ size_t i;
+ if (log) {
+ for (i = 0; i < num_matches; i++) {
+ type_sp = class_types.GetTypeAtIndex(i);
+ if (type_sp) {
+ if (log)
+ log->Printf(
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has multiple matching dynamic "
+ "types: uid={0x%" PRIx64 "}, type-name='%s'\n",
+ original_ptr, in_value.GetTypeName().AsCString(),
+ type_sp->GetID(), type_sp->GetName().GetCString());
+ }
+ }
+ }
+
+ for (i = 0; i < num_matches; i++) {
+ type_sp = class_types.GetTypeAtIndex(i);
+ if (type_sp) {
+ if (ClangASTContext::IsCXXClassType(
+ type_sp->GetForwardCompilerType())) {
+ if (log)
+ log->Printf(
+ "0x%16.16" PRIx64 ": static-type = '%s' has multiple "
+ "matching dynamic types, picking "
+ "this one: uid={0x%" PRIx64
+ "}, type-name='%s'\n",
+ original_ptr, in_value.GetTypeName().AsCString(),
+ type_sp->GetID(), type_sp->GetName().GetCString());
+ type_info.SetTypeSP(type_sp);
+ }
+ }
+ }
+
+ if (log && i == num_matches) {
+ log->Printf(
+ "0x%16.16" PRIx64
+ ": static-type = '%s' has multiple matching dynamic "
+ "types, didn't find a C++ match\n",
+ original_ptr, in_value.GetTypeName().AsCString());
+ }
+ }
+ if (type_info)
+ SetDynamicTypeInfo(vtable_addr, type_info);
+ return type_info;
+ }
}
+ }
}
-
- return class_type_or_name.IsEmpty() == false;
+ }
+ return TypeAndOrName();
}
-TypeAndOrName
-ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name,
- ValueObject& static_value)
-{
- CompilerType static_type(static_value.GetCompilerType());
- Flags static_type_flags(static_type.GetTypeInfo());
-
- TypeAndOrName ret(type_and_or_name);
- if (type_and_or_name.HasType())
- {
- // The type will always be the type of the dynamic object. If our parent's type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
- // should be okay...
- CompilerType orig_type = type_and_or_name.GetCompilerType();
- CompilerType corrected_type = orig_type;
- if (static_type_flags.AllSet(eTypeIsPointer))
- corrected_type = orig_type.GetPointerType ();
- else if (static_type_flags.AllSet(eTypeIsReference))
- corrected_type = orig_type.GetLValueReferenceType();
- ret.SetCompilerType(corrected_type);
- }
- else
- {
- // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
- std::string corrected_name (type_and_or_name.GetName().GetCString());
- if (static_type_flags.AllSet(eTypeIsPointer))
- corrected_name.append(" *");
- else if (static_type_flags.AllSet(eTypeIsReference))
- corrected_name.append(" &");
- // the parent type should be a correctly pointer'ed or referenc'ed type
- ret.SetCompilerType(static_type);
- ret.SetName(corrected_name.c_str());
- }
- return ret;
-}
+bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &dynamic_address,
+ Value::ValueType &value_type) {
+ // For Itanium, if the type has a vtable pointer in the object, it will be at
+ // offset 0
+ // in the object. That will point to the "address point" within the vtable
+ // (not the beginning of the
+ // vtable.) We can then look up the symbol containing this "address point"
+ // and that symbol's name
+ // demangled will contain the full class name.
+ // The second pointer above the "address point" is the "offset_to_top". We'll
+ // use that to get the
+ // start of the value object which holds the dynamic type.
+ //
-bool
-ItaniumABILanguageRuntime::IsVTableName (const char *name)
-{
- if (name == NULL)
- return false;
-
- // Can we maybe ask Clang about this?
- if (strstr (name, "_vptr$") == name)
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+
+ // Only a pointer or reference type can have a different dynamic and static
+ // type:
+ if (CouldHaveDynamicValue(in_value)) {
+ // First job, pull out the address at 0 offset from the object.
+ AddressType address_type;
+ lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
+ if (original_ptr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == nullptr)
+ return false;
+
+ Error error;
+ const lldb::addr_t vtable_address_point =
+ process->ReadPointerFromMemory(original_ptr, error);
+
+ if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) {
+ return false;
+ }
+
+ class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr,
+ vtable_address_point);
+
+ if (class_type_or_name) {
+ TypeSP type_sp = class_type_or_name.GetTypeSP();
+ // There can only be one type with a given name,
+ // so we've just found duplicate definitions, and this
+ // one will do as well as any other.
+ // We don't consider something to have a dynamic type if
+ // it is the same as the static type. So compare against
+ // the value we were handed.
+ if (type_sp) {
+ if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(),
+ type_sp->GetForwardCompilerType())) {
+ // The dynamic type we found was the same type,
+ // so we don't have a dynamic type here...
+ return false;
+ }
+
+ // The offset_to_top is two pointers above the vtable pointer.
+ const uint32_t addr_byte_size = process->GetAddressByteSize();
+ const lldb::addr_t offset_to_top_location =
+ vtable_address_point - 2 * addr_byte_size;
+ // Watch for underflow, offset_to_top_location should be less than
+ // vtable_address_point
+ if (offset_to_top_location >= vtable_address_point)
+ return false;
+ const int64_t offset_to_top = process->ReadSignedIntegerFromMemory(
+ offset_to_top_location, addr_byte_size, INT64_MIN, error);
+
+ if (offset_to_top == INT64_MIN)
+ return false;
+ // So the dynamic type is a value that starts at offset_to_top
+ // above the original address.
+ lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
+ if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
+ dynamic_addr, dynamic_address)) {
+ dynamic_address.SetRawAddress(dynamic_addr);
+ }
return true;
- else
- return false;
+ }
+ }
+ }
+
+ return class_type_or_name.IsEmpty() == false;
+}
+
+TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
+ const TypeAndOrName &type_and_or_name, ValueObject &static_value) {
+ CompilerType static_type(static_value.GetCompilerType());
+ Flags static_type_flags(static_type.GetTypeInfo());
+
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType()) {
+ // The type will always be the type of the dynamic object. If our parent's
+ // type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If
+ // a reference, then the original type
+ // should be okay...
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ CompilerType corrected_type = orig_type;
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_type = orig_type.GetPointerType();
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_type = orig_type.GetLValueReferenceType();
+ ret.SetCompilerType(corrected_type);
+ } else {
+ // If we are here we need to adjust our dynamic type name to include the
+ // correct & or * symbol
+ std::string corrected_name(type_and_or_name.GetName().GetCString());
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_name.append(" *");
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_name.append(" &");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetCompilerType(static_type);
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
+}
+
+bool ItaniumABILanguageRuntime::IsVTableName(const char *name) {
+ if (name == NULL)
+ return false;
+
+ // Can we maybe ask Clang about this?
+ if (strstr(name, "_vptr$") == name)
+ return true;
+ else
+ return false;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
-ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
-{
- // FIXME: We have to check the process and make sure we actually know that this process supports
- // the Itanium ABI.
- if (language == eLanguageTypeC_plus_plus ||
- language == eLanguageTypeC_plus_plus_03 ||
- language == eLanguageTypeC_plus_plus_11 ||
- language == eLanguageTypeC_plus_plus_14)
- return new ItaniumABILanguageRuntime (process);
- else
- return NULL;
+ItaniumABILanguageRuntime::CreateInstance(Process *process,
+ lldb::LanguageType language) {
+ // FIXME: We have to check the process and make sure we actually know that
+ // this process supports
+ // the Itanium ABI.
+ if (language == eLanguageTypeC_plus_plus ||
+ language == eLanguageTypeC_plus_plus_03 ||
+ language == eLanguageTypeC_plus_plus_11 ||
+ language == eLanguageTypeC_plus_plus_14)
+ return new ItaniumABILanguageRuntime(process);
+ else
+ return NULL;
}
-class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed
-{
+class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed {
public:
- CommandObjectMultiwordItaniumABI_Demangle (CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "demangle",
- "Demangle a C++ mangled name.",
- "language cplusplus demangle")
- {
- CommandArgumentEntry arg;
- CommandArgumentData index_arg;
-
- // Define the first (and only) variant of this arg.
- index_arg.arg_type = eArgTypeSymbol;
- 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);
- }
-
- ~CommandObjectMultiwordItaniumABI_Demangle() override = default;
-
+ CommandObjectMultiwordItaniumABI_Demangle(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "demangle",
+ "Demangle a C++ mangled name.",
+ "language cplusplus demangle") {
+ CommandArgumentEntry arg;
+ CommandArgumentData index_arg;
+
+ // Define the first (and only) variant of this arg.
+ index_arg.arg_type = eArgTypeSymbol;
+ 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);
+ }
+
+ ~CommandObjectMultiwordItaniumABI_Demangle() override = default;
+
protected:
- bool
- DoExecute(Args& command, CommandReturnObject &result) override
- {
- bool demangled_any = false;
- bool error_any = false;
- for (size_t i = 0; i < command.GetArgumentCount(); i++)
- {
- auto arg = command.GetArgumentAtIndex(i);
- if (arg && *arg)
- {
- ConstString mangled_cs(arg);
-
- // the actual Mangled class should be strict about this, but on the command line
- // if you're copying mangled names out of 'nm' on Darwin, they will come out with
- // an extra underscore - be willing to strip this on behalf of the user
- // This is the moral equivalent of the -_/-n options to c++filt
- if (mangled_cs.GetStringRef().startswith("__Z"))
- mangled_cs.SetCString(arg+1);
-
- Mangled mangled(mangled_cs, true);
- if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus)
- {
- ConstString demangled(mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus));
- demangled_any = true;
- result.AppendMessageWithFormat("%s ---> %s\n", arg, demangled.GetCString());
- }
- else
- {
- error_any = true;
- result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", arg);
- }
- }
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ bool demangled_any = false;
+ bool error_any = false;
+ for (size_t i = 0; i < command.GetArgumentCount(); i++) {
+ auto arg = command.GetArgumentAtIndex(i);
+ if (arg && *arg) {
+ ConstString mangled_cs(arg);
+
+ // the actual Mangled class should be strict about this, but on the
+ // command line
+ // if you're copying mangled names out of 'nm' on Darwin, they will come
+ // out with
+ // an extra underscore - be willing to strip this on behalf of the user
+ // This is the moral equivalent of the -_/-n options to c++filt
+ if (mangled_cs.GetStringRef().startswith("__Z"))
+ mangled_cs.SetCString(arg + 1);
+
+ Mangled mangled(mangled_cs, true);
+ if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) {
+ ConstString demangled(
+ mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus));
+ demangled_any = true;
+ result.AppendMessageWithFormat("%s ---> %s\n", arg,
+ demangled.GetCString());
+ } else {
+ error_any = true;
+ result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n",
+ arg);
}
-
- result.SetStatus(error_any ? lldb::eReturnStatusFailed :
- (demangled_any ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult));
- return result.Succeeded();
+ }
}
+
+ result.SetStatus(
+ error_any ? lldb::eReturnStatusFailed
+ : (demangled_any ? lldb::eReturnStatusSuccessFinishResult
+ : lldb::eReturnStatusSuccessFinishNoResult));
+ return result.Succeeded();
+ }
};
-class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword
-{
+class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword {
public:
- CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "cplusplus", "Commands for operating on the C++ language runtime.",
- "cplusplus <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("demangle", CommandObjectSP (new CommandObjectMultiwordItaniumABI_Demangle (interpreter)));
- }
-
- ~CommandObjectMultiwordItaniumABI() override = default;
+ CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "cplusplus",
+ "Commands for operating on the C++ language runtime.",
+ "cplusplus <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "demangle",
+ CommandObjectSP(
+ new CommandObjectMultiwordItaniumABI_Demangle(interpreter)));
+ }
+
+ ~CommandObjectMultiwordItaniumABI() override = default;
};
-void
-ItaniumABILanguageRuntime::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Itanium ABI for the C++ language",
- CreateInstance,
- [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP {
- return CommandObjectSP(new CommandObjectMultiwordItaniumABI(interpreter));
- });
+void ItaniumABILanguageRuntime::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), "Itanium ABI for the C++ language", CreateInstance,
+ [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
+ return CommandObjectSP(
+ new CommandObjectMultiwordItaniumABI(interpreter));
+ });
}
-void
-ItaniumABILanguageRuntime::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void ItaniumABILanguageRuntime::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-ItaniumABILanguageRuntime::GetPluginNameStatic()
-{
- static ConstString g_name("itanium");
- return g_name;
+lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginNameStatic() {
+ static ConstString g_name("itanium");
+ return g_name;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-ItaniumABILanguageRuntime::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString ItaniumABILanguageRuntime::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-ItaniumABILanguageRuntime::GetPluginVersion()
-{
- return 1;
+uint32_t ItaniumABILanguageRuntime::GetPluginVersion() { return 1; }
+
+BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
+ Breakpoint *bkpt, bool catch_bp, bool throw_bp) {
+ return CreateExceptionResolver(bkpt, catch_bp, throw_bp, false);
}
-BreakpointResolverSP
-ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
-{
- return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
+BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
+ Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) {
+ // One complication here is that most users DON'T want to stop at
+ // __cxa_allocate_expression, but until we can do
+ // anything better with predicting unwinding the expression parser does. So
+ // we have two forms of the exception
+ // breakpoints, one for expressions that leaves out __cxa_allocate_exception,
+ // and one that includes it.
+ // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint
+ // in the runtime the former.
+ static const char *g_catch_name = "__cxa_begin_catch";
+ static const char *g_throw_name1 = "__cxa_throw";
+ static const char *g_throw_name2 = "__cxa_rethrow";
+ static const char *g_exception_throw_name = "__cxa_allocate_exception";
+ std::vector<const char *> exception_names;
+ exception_names.reserve(4);
+ if (catch_bp)
+ exception_names.push_back(g_catch_name);
+
+ if (throw_bp) {
+ exception_names.push_back(g_throw_name1);
+ exception_names.push_back(g_throw_name2);
+ }
+
+ if (for_expressions)
+ exception_names.push_back(g_exception_throw_name);
+
+ BreakpointResolverSP resolver_sp(new BreakpointResolverName(
+ bkpt, exception_names.data(), exception_names.size(),
+ eFunctionNameTypeBase, eLanguageTypeUnknown, 0, eLazyBoolNo));
+
+ return resolver_sp;
}
-BreakpointResolverSP
-ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
-{
- // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
- // anything better with predicting unwinding the expression parser does. So we have two forms of the exception
- // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
- // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
- static const char *g_catch_name = "__cxa_begin_catch";
- static const char *g_throw_name1 = "__cxa_throw";
- static const char *g_throw_name2 = "__cxa_rethrow";
- static const char *g_exception_throw_name = "__cxa_allocate_exception";
- std::vector<const char *> exception_names;
- exception_names.reserve(4);
- if (catch_bp)
- exception_names.push_back(g_catch_name);
+lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() {
+ Target &target = m_process->GetTarget();
- if (throw_bp)
- {
- exception_names.push_back(g_throw_name1);
- exception_names.push_back(g_throw_name2);
- }
-
- if (for_expressions)
- exception_names.push_back(g_exception_throw_name);
-
- BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
- exception_names.data(),
- exception_names.size(),
- eFunctionNameTypeBase,
- eLanguageTypeUnknown,
- 0,
- eLazyBoolNo));
-
- return resolver_sp;
-}
-
-
-
-lldb::SearchFilterSP
-ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
-{
- Target &target = m_process->GetTarget();
-
- if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
- {
- // Limit the number of modules that are searched for these breakpoints for
- // Apple binaries.
- FileSpecList filter_modules;
- filter_modules.Append(FileSpec("libc++abi.dylib", false));
- filter_modules.Append(FileSpec("libSystem.B.dylib", false));
- return target.GetSearchFilterForModuleList(&filter_modules);
- }
- else
- {
- return LanguageRuntime::CreateExceptionSearchFilter();
- }
-}
-
-lldb::BreakpointSP
-ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
- bool throw_bp,
- bool for_expressions,
- bool is_internal)
-{
- Target &target = m_process->GetTarget();
+ if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
+ // Limit the number of modules that are searched for these breakpoints for
+ // Apple binaries.
FileSpecList filter_modules;
- BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
- SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
- const bool hardware = false;
- const bool resolve_indirect_functions = false;
- return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
+ filter_modules.Append(FileSpec("libc++abi.dylib", false));
+ filter_modules.Append(FileSpec("libSystem.B.dylib", false));
+ return target.GetSearchFilterForModuleList(&filter_modules);
+ } else {
+ return LanguageRuntime::CreateExceptionSearchFilter();
+ }
}
-void
-ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
-{
- if (!m_process)
- return;
-
- const bool catch_bp = false;
- const bool throw_bp = true;
- const bool is_internal = true;
- const bool for_expressions = true;
-
- // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
- // stop at exception allocation as well.
-
+lldb::BreakpointSP ItaniumABILanguageRuntime::CreateExceptionBreakpoint(
+ bool catch_bp, bool throw_bp, bool for_expressions, bool is_internal) {
+ Target &target = m_process->GetTarget();
+ FileSpecList filter_modules;
+ BreakpointResolverSP exception_resolver_sp =
+ CreateExceptionResolver(NULL, catch_bp, throw_bp, for_expressions);
+ SearchFilterSP filter_sp(CreateExceptionSearchFilter());
+ const bool hardware = false;
+ const bool resolve_indirect_functions = false;
+ return target.CreateBreakpoint(filter_sp, exception_resolver_sp, is_internal,
+ hardware, resolve_indirect_functions);
+}
+
+void ItaniumABILanguageRuntime::SetExceptionBreakpoints() {
+ if (!m_process)
+ return;
+
+ const bool catch_bp = false;
+ const bool throw_bp = true;
+ const bool is_internal = true;
+ const bool for_expressions = true;
+
+ // For the exception breakpoints set by the Expression parser, we'll be a
+ // little more aggressive and
+ // stop at exception allocation as well.
+
+ if (m_cxx_exception_bp_sp) {
+ m_cxx_exception_bp_sp->SetEnabled(true);
+ } else {
+ m_cxx_exception_bp_sp = CreateExceptionBreakpoint(
+ catch_bp, throw_bp, for_expressions, is_internal);
if (m_cxx_exception_bp_sp)
- {
- m_cxx_exception_bp_sp->SetEnabled (true);
- }
- else
- {
- m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
- if (m_cxx_exception_bp_sp)
- m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
- }
-
+ m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
+ }
}
-void
-ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
-{
- if (!m_process)
- return;
-
- if (m_cxx_exception_bp_sp)
- {
- m_cxx_exception_bp_sp->SetEnabled (false);
- }
+void ItaniumABILanguageRuntime::ClearExceptionBreakpoints() {
+ if (!m_process)
+ return;
+
+ if (m_cxx_exception_bp_sp) {
+ m_cxx_exception_bp_sp->SetEnabled(false);
+ }
}
-bool
-ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
-{
- return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
+bool ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet() {
+ return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
}
-bool
-ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
-{
- if (!m_process)
- return false;
-
- if (!stop_reason ||
- stop_reason->GetStopReason() != eStopReasonBreakpoint)
- return false;
-
- uint64_t break_site_id = stop_reason->GetValue();
- return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
- m_cxx_exception_bp_sp->GetID());
-
+bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop(
+ lldb::StopInfoSP stop_reason) {
+ if (!m_process)
+ return false;
+
+ if (!stop_reason || stop_reason->GetStopReason() != eStopReasonBreakpoint)
+ return false;
+
+ uint64_t break_site_id = stop_reason->GetValue();
+ return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(
+ break_site_id, m_cxx_exception_bp_sp->GetID());
}
-TypeAndOrName
-ItaniumABILanguageRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr)
-{
- std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
- DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
- if (pos == m_dynamic_type_map.end())
- return TypeAndOrName();
- else
- return pos->second;
+TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo(
+ const lldb_private::Address &vtable_addr) {
+ std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
+ DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr);
+ if (pos == m_dynamic_type_map.end())
+ return TypeAndOrName();
+ else
+ return pos->second;
}
-void
-ItaniumABILanguageRuntime::SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info)
-{
- std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
- m_dynamic_type_map[vtable_addr] = type_info;
+void ItaniumABILanguageRuntime::SetDynamicTypeInfo(
+ const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) {
+ std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
+ m_dynamic_type_map[vtable_addr] = type_info;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index 86bd728..480c326 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -18,116 +18,98 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Target/LanguageRuntime.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Value.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-
- class ItaniumABILanguageRuntime :
- public lldb_private::CPPLanguageRuntime
- {
- public:
- ~ItaniumABILanguageRuntime() override = default;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance (Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString
- GetPluginNameStatic();
- bool
- IsVTableName(const char *name) override;
-
- bool
- GetDynamicTypeAndAddress(ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
-
- TypeAndOrName
- FixUpDynamicType(const TypeAndOrName& type_and_or_name,
- ValueObject& static_value) override;
-
- bool
- CouldHaveDynamicValue(ValueObject &in_value) override;
-
- void
- SetExceptionBreakpoints() override;
-
- void
- ClearExceptionBreakpoints() override;
-
- bool
- ExceptionBreakpointsAreSet() override;
-
- bool
- ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
+class ItaniumABILanguageRuntime : public lldb_private::CPPLanguageRuntime {
+public:
+ ~ItaniumABILanguageRuntime() override = default;
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
-
- lldb::SearchFilterSP
- CreateExceptionSearchFilter() override;
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
+ static void Terminate();
- protected:
- lldb::BreakpointResolverSP
- CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions);
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
- lldb::BreakpointSP
- CreateExceptionBreakpoint(bool catch_bp,
- bool throw_bp,
- bool for_expressions,
- bool is_internal);
-
- private:
- typedef std::map<lldb_private::Address, TypeAndOrName> DynamicTypeCache;
+ static lldb_private::ConstString GetPluginNameStatic();
- ItaniumABILanguageRuntime(Process *process)
- : // Call CreateInstance instead.
- lldb_private::CPPLanguageRuntime(process),
- m_cxx_exception_bp_sp(),
- m_dynamic_type_map(),
- m_dynamic_type_map_mutex()
- {
- }
+ bool IsVTableName(const char *name) override;
- lldb::BreakpointSP m_cxx_exception_bp_sp;
- DynamicTypeCache m_dynamic_type_map;
- std::mutex m_dynamic_type_map_mutex;
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- TypeAndOrName
- GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, lldb::addr_t vtable_addr);
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
- TypeAndOrName
- GetDynamicTypeInfo(const lldb_private::Address &vtable_addr);
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- void
- SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info);
- };
-
+ void SetExceptionBreakpoints() override;
+
+ void ClearExceptionBreakpoints() override;
+
+ bool ExceptionBreakpointsAreSet() override;
+
+ bool ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
+
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override;
+
+ lldb::SearchFilterSP CreateExceptionSearchFilter() override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+protected:
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp,
+ bool for_expressions);
+
+ lldb::BreakpointSP CreateExceptionBreakpoint(bool catch_bp, bool throw_bp,
+ bool for_expressions,
+ bool is_internal);
+
+private:
+ typedef std::map<lldb_private::Address, TypeAndOrName> DynamicTypeCache;
+
+ ItaniumABILanguageRuntime(Process *process)
+ : // Call CreateInstance instead.
+ lldb_private::CPPLanguageRuntime(process),
+ m_cxx_exception_bp_sp(), m_dynamic_type_map(),
+ m_dynamic_type_map_mutex() {}
+
+ lldb::BreakpointSP m_cxx_exception_bp_sp;
+ DynamicTypeCache m_dynamic_type_map;
+ std::mutex m_dynamic_type_map_mutex;
+
+ TypeAndOrName GetTypeInfoFromVTableAddress(ValueObject &in_value,
+ lldb::addr_t original_ptr,
+ lldb::addr_t vtable_addr);
+
+ TypeAndOrName GetDynamicTypeInfo(const lldb_private::Address &vtable_addr);
+
+ void SetDynamicTypeInfo(const lldb_private::Address &vtable_addr,
+ const TypeAndOrName &type_info);
+};
+
} // namespace lldb_private
#endif // liblldb_ItaniumABILanguageRuntime_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
index c752971..1450835 100644
--- a/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
@@ -1,4 +1,5 @@
-//===-- GoLanguageRuntime.cpp --------------------------------------*- C++ -*-===//
+//===-- GoLanguageRuntime.cpp --------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -36,206 +37,179 @@
using namespace lldb_private;
namespace {
-ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) {
- ConstString name_const_str(name);
- ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
- if (dereference && result && result->IsPointerType()) {
- Error err;
- result = result->Dereference(err);
- if (err.Fail())
- result.reset();
- }
- return result;
+ValueObjectSP GetChild(ValueObject &obj, const char *name,
+ bool dereference = true) {
+ ConstString name_const_str(name);
+ ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
+ if (dereference && result && result->IsPointerType()) {
+ Error err;
+ result = result->Dereference(err);
+ if (err.Fail())
+ result.reset();
+ }
+ return result;
}
-ConstString ReadString(ValueObject& str, Process* process) {
- ConstString result;
- ValueObjectSP data = GetChild(str, "str", false);
- ValueObjectSP len = GetChild(str, "len");
- if (len && data)
- {
- Error err;
- lldb::addr_t addr = data->GetPointerValue();
- if (addr == LLDB_INVALID_ADDRESS)
- return result;
- uint64_t byte_size = len->GetValueAsUnsigned(0);
- char* buf = new char[byte_size + 1];
- buf[byte_size] = 0;
- size_t bytes_read = process->ReadMemory (addr,
- buf,
- byte_size,
- err);
- if (!(err.Fail() || bytes_read != byte_size))
- result = ConstString(buf, bytes_read);
- delete[] buf;
- }
- return result;
+ConstString ReadString(ValueObject &str, Process *process) {
+ ConstString result;
+ ValueObjectSP data = GetChild(str, "str", false);
+ ValueObjectSP len = GetChild(str, "len");
+ if (len && data) {
+ Error err;
+ lldb::addr_t addr = data->GetPointerValue();
+ if (addr == LLDB_INVALID_ADDRESS)
+ return result;
+ uint64_t byte_size = len->GetValueAsUnsigned(0);
+ char *buf = new char[byte_size + 1];
+ buf[byte_size] = 0;
+ size_t bytes_read = process->ReadMemory(addr, buf, byte_size, err);
+ if (!(err.Fail() || bytes_read != byte_size))
+ result = ConstString(buf, bytes_read);
+ delete[] buf;
+ }
+ return result;
}
-ConstString
-ReadTypeName(ValueObjectSP type, Process* process)
-{
- if (ValueObjectSP uncommon = GetChild(*type, "x"))
- {
- ValueObjectSP name = GetChild(*uncommon, "name");
- ValueObjectSP package = GetChild(*uncommon, "pkgpath");
- if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0)
- {
- ConstString package_const_str = ReadString(*package, process);
- ConstString name_const_str = ReadString(*name, process);
- if (package_const_str.GetLength() == 0)
- return name_const_str;
- return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str());
- }
+ConstString ReadTypeName(ValueObjectSP type, Process *process) {
+ if (ValueObjectSP uncommon = GetChild(*type, "x")) {
+ ValueObjectSP name = GetChild(*uncommon, "name");
+ ValueObjectSP package = GetChild(*uncommon, "pkgpath");
+ if (name && name->GetPointerValue() != 0 && package &&
+ package->GetPointerValue() != 0) {
+ ConstString package_const_str = ReadString(*package, process);
+ ConstString name_const_str = ReadString(*name, process);
+ if (package_const_str.GetLength() == 0)
+ return name_const_str;
+ return ConstString((package_const_str.GetStringRef() + "." +
+ name_const_str.GetStringRef())
+ .str());
}
- ValueObjectSP name = GetChild(*type, "_string");
- if (name)
- return ReadString(*name, process);
- return ConstString("");
+ }
+ ValueObjectSP name = GetChild(*type, "_string");
+ if (name)
+ return ReadString(*name, process);
+ return ConstString("");
}
-CompilerType
-LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct)
-{
- uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
- *is_direct = GoASTContext::IsDirectIface(kind);
- if (GoASTContext::IsPointerKind(kind))
- {
- CompilerType type_ptr = type->GetCompilerType().GetPointerType();
- Error err;
- ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err);
- if (err.Fail())
- return CompilerType();
- bool tmp_direct;
- return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
- }
- Target *target = exe_ctx->GetTargetPtr();
- Process *process = exe_ctx->GetProcessPtr();
-
- ConstString const_typename = ReadTypeName(type, process);
- if (const_typename.GetLength() == 0)
- return CompilerType();
-
- SymbolContext sc;
- TypeList type_list;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- uint32_t num_matches = target->GetImages().FindTypes (sc,
- const_typename,
- false,
- 2,
- searched_symbol_files,
- type_list);
- if (num_matches > 0) {
- return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
- }
+CompilerType LookupRuntimeType(ValueObjectSP type, ExecutionContext *exe_ctx,
+ bool *is_direct) {
+ uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
+ *is_direct = GoASTContext::IsDirectIface(kind);
+ if (GoASTContext::IsPointerKind(kind)) {
+ CompilerType type_ptr = type->GetCompilerType().GetPointerType();
+ Error err;
+ ValueObjectSP elem =
+ type->CreateValueObjectFromAddress("elem", type->GetAddressOf() +
+ type->GetByteSize(),
+ *exe_ctx, type_ptr)
+ ->Dereference(err);
+ if (err.Fail())
+ return CompilerType();
+ bool tmp_direct;
+ return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
+ }
+ Target *target = exe_ctx->GetTargetPtr();
+ Process *process = exe_ctx->GetProcessPtr();
+
+ ConstString const_typename = ReadTypeName(type, process);
+ if (const_typename.GetLength() == 0)
return CompilerType();
+
+ SymbolContext sc;
+ TypeList type_list;
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ uint32_t num_matches = target->GetImages().FindTypes(
+ sc, const_typename, false, 2, searched_symbol_files, type_list);
+ if (num_matches > 0) {
+ return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+ }
+ return CompilerType();
+}
}
+bool GoLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ return GoASTContext::IsGoInterface(in_value.GetCompilerType());
}
-bool
-GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
-{
- return GoASTContext::IsGoInterface(in_value.GetCompilerType());
-}
+bool GoLanguageRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &dynamic_address,
+ Value::ValueType &value_type) {
+ value_type = Value::eValueTypeScalar;
+ class_type_or_name.Clear();
+ if (CouldHaveDynamicValue(in_value)) {
+ Error err;
+ ValueObjectSP iface = in_value.GetStaticValue();
+ ValueObjectSP data_sp = GetChild(*iface, "data", false);
+ if (!data_sp)
+ return false;
-bool
-GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &dynamic_address,
- Value::ValueType &value_type)
-{
- value_type = Value::eValueTypeScalar;
- class_type_or_name.Clear();
- if (CouldHaveDynamicValue (in_value))
- {
- Error err;
- ValueObjectSP iface = in_value.GetStaticValue();
- ValueObjectSP data_sp = GetChild(*iface, "data", false);
- if (!data_sp)
- return false;
-
- if (ValueObjectSP tab = GetChild(*iface, "tab"))
- iface = tab;
- ValueObjectSP type = GetChild(*iface, "_type");
- if (!type)
- {
- return false;
- }
-
- bool direct;
- ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
- CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
- if (!final_type)
- return false;
- if (direct)
- {
- class_type_or_name.SetCompilerType(final_type);
- }
- else
- {
- // TODO: implement reference types or fix caller to support dynamic types that aren't pointers
- // so we don't have to introduce this extra pointer.
- class_type_or_name.SetCompilerType(final_type.GetPointerType());
- }
-
- dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr());
-
- return true;
+ if (ValueObjectSP tab = GetChild(*iface, "tab"))
+ iface = tab;
+ ValueObjectSP type = GetChild(*iface, "_type");
+ if (!type) {
+ return false;
}
- return false;
+
+ bool direct;
+ ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+ CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
+ if (!final_type)
+ return false;
+ if (direct) {
+ class_type_or_name.SetCompilerType(final_type);
+ } else {
+ // TODO: implement reference types or fix caller to support dynamic types
+ // that aren't pointers
+ // so we don't have to introduce this extra pointer.
+ class_type_or_name.SetCompilerType(final_type.GetPointerType());
+ }
+
+ dynamic_address.SetLoadAddress(data_sp->GetPointerValue(),
+ exe_ctx.GetTargetPtr());
+
+ return true;
+ }
+ return false;
}
TypeAndOrName
-GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
-{
- return type_and_or_name;
+GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) {
+ return type_and_or_name;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
-GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
-{
- if (language == eLanguageTypeGo)
- return new GoLanguageRuntime (process);
- else
- return NULL;
+GoLanguageRuntime::CreateInstance(Process *process,
+ lldb::LanguageType language) {
+ if (language == eLanguageTypeGo)
+ return new GoLanguageRuntime(process);
+ else
+ return NULL;
}
-void
-GoLanguageRuntime::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Go Language Runtime",
- CreateInstance);
+void GoLanguageRuntime::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language Runtime",
+ CreateInstance);
}
-void
-GoLanguageRuntime::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void GoLanguageRuntime::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-GoLanguageRuntime::GetPluginNameStatic()
-{
- static ConstString g_name("golang");
- return g_name;
+lldb_private::ConstString GoLanguageRuntime::GetPluginNameStatic() {
+ static ConstString g_name("golang");
+ return g_name;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-GoLanguageRuntime::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString GoLanguageRuntime::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-GoLanguageRuntime::GetPluginVersion()
-{
- return 1;
-}
-
+uint32_t GoLanguageRuntime::GetPluginVersion() { return 1; }
diff --git a/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
index 596d288..9c2ee15 100644
--- a/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
@@ -14,80 +14,73 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/BreakpointResolver.h"
-#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Core/Value.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-
- class GoLanguageRuntime :
- public lldb_private::LanguageRuntime
- {
- public:
- ~GoLanguageRuntime() override = default;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString
- GetPluginNameStatic();
+class GoLanguageRuntime : public lldb_private::LanguageRuntime {
+public:
+ ~GoLanguageRuntime() override = default;
- lldb::LanguageType
- GetLanguageType() const override
- {
- return lldb::eLanguageTypeGo;
- }
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- bool
- GetObjectDescription(Stream &str, ValueObject &object) override
- {
- // TODO(ribrdb): Maybe call String() method?
- return false;
- }
+ static void Terminate();
- bool
- GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override
- {
- return false;
- }
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
- bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type) override;
+ static lldb_private::ConstString GetPluginNameStatic();
- bool CouldHaveDynamicValue(ValueObject &in_value) override;
+ lldb::LanguageType GetLanguageType() const override {
+ return lldb::eLanguageTypeGo;
+ }
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override
- {
- return lldb::BreakpointResolverSP();
- }
+ bool GetObjectDescription(Stream &str, ValueObject &object) override {
+ // TODO(ribrdb): Maybe call String() method?
+ return false;
+ }
- TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+ bool GetObjectDescription(Stream &str, Value &value,
+ ExecutionContextScope *exe_scope) override {
+ return false;
+ }
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- private:
- GoLanguageRuntime(Process *process) : lldb_private::LanguageRuntime(process) { } // Call CreateInstance instead.
- };
-
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
+
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override {
+ return lldb::BreakpointResolverSP();
+ }
+
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+private:
+ GoLanguageRuntime(Process *process)
+ : lldb_private::LanguageRuntime(process) {
+ } // Call CreateInstance instead.
+};
+
} // namespace lldb_private
#endif // liblldb_GoLanguageRuntime_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp
index 07312a8..36c30a9 100644
--- a/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp
@@ -23,154 +23,135 @@
using namespace lldb;
using namespace lldb_private;
-JavaLanguageRuntime::JavaLanguageRuntime(Process *process) : LanguageRuntime(process)
-{
-}
+JavaLanguageRuntime::JavaLanguageRuntime(Process *process)
+ : LanguageRuntime(process) {}
LanguageRuntime *
-JavaLanguageRuntime::CreateInstance(Process *process, lldb::LanguageType language)
-{
- if (language == eLanguageTypeJava)
- return new JavaLanguageRuntime(process);
- return nullptr;
+JavaLanguageRuntime::CreateInstance(Process *process,
+ lldb::LanguageType language) {
+ if (language == eLanguageTypeJava)
+ return new JavaLanguageRuntime(process);
+ return nullptr;
}
-void
-JavaLanguageRuntime::Initialize()
-{
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java language runtime", CreateInstance);
+void JavaLanguageRuntime::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java language runtime",
+ CreateInstance);
}
-void
-JavaLanguageRuntime::Terminate()
-{
- PluginManager::UnregisterPlugin(CreateInstance);
+void JavaLanguageRuntime::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-JavaLanguageRuntime::GetPluginNameStatic()
-{
- static ConstString g_name("java");
- return g_name;
+lldb_private::ConstString JavaLanguageRuntime::GetPluginNameStatic() {
+ static ConstString g_name("java");
+ return g_name;
}
-lldb_private::ConstString
-JavaLanguageRuntime::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString JavaLanguageRuntime::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-JavaLanguageRuntime::GetPluginVersion()
-{
- return 1;
+uint32_t JavaLanguageRuntime::GetPluginVersion() { return 1; }
+
+bool JavaLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ return true;
}
-bool
-JavaLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value)
-{
- return true;
-}
+static ConstString GetDynamicTypeId(ExecutionContext *exe_ctx, Target *target,
+ ValueObject &in_value) {
+ SymbolContext sc;
+ TypeList class_types;
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ size_t num_matches = target->GetImages().FindTypes(
+ sc, ConstString("Object"),
+ true, // name_is_fully_qualified
+ UINT32_MAX, searched_symbol_files, class_types);
+ for (size_t i = 0; i < num_matches; ++i) {
+ TypeSP type_sp = class_types.GetTypeAtIndex(i);
+ CompilerType compiler_type = type_sp->GetFullCompilerType();
-static ConstString
-GetDynamicTypeId(ExecutionContext *exe_ctx, Target *target, ValueObject &in_value)
-{
- SymbolContext sc;
- TypeList class_types;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- size_t num_matches = target->GetImages().FindTypes(sc, ConstString("Object"),
- true, // name_is_fully_qualified
- UINT32_MAX, searched_symbol_files, class_types);
- for (size_t i = 0; i < num_matches; ++i)
- {
- TypeSP type_sp = class_types.GetTypeAtIndex(i);
- CompilerType compiler_type = type_sp->GetFullCompilerType();
+ if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava ||
+ compiler_type.GetTypeName() != ConstString("java::lang::Object"))
+ continue;
- if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava ||
- compiler_type.GetTypeName() != ConstString("java::lang::Object"))
- continue;
-
- if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType())
- {
- uint64_t type_id = JavaASTContext::CalculateDynamicTypeId(exe_ctx, compiler_type, in_value);
- if (type_id != UINT64_MAX)
- {
- char id[32];
- snprintf(id, sizeof(id), "0x%" PRIX64, type_id);
- return ConstString(id);
- }
- }
+ if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) {
+ uint64_t type_id = JavaASTContext::CalculateDynamicTypeId(
+ exe_ctx, compiler_type, in_value);
+ if (type_id != UINT64_MAX) {
+ char id[32];
+ snprintf(id, sizeof(id), "0x%" PRIX64, type_id);
+ return ConstString(id);
+ }
}
- return ConstString();
+ }
+ return ConstString();
}
-bool
-JavaLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &dynamic_address,
- Value::ValueType &value_type)
-{
- class_type_or_name.Clear();
+bool JavaLanguageRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &dynamic_address,
+ Value::ValueType &value_type) {
+ class_type_or_name.Clear();
- // null references don't have a dynamic type
- if (in_value.IsNilReference())
- return false;
-
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
- Target *target = exe_ctx.GetTargetPtr();
- if (!target)
- return false;
-
- ConstString linkage_name;
- CompilerType in_type = in_value.GetCompilerType();
- if (in_type.IsPossibleDynamicType(nullptr, false, false))
- linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value);
- else
- linkage_name = JavaASTContext::GetLinkageName(in_type);
-
- if (!linkage_name)
- return false;
-
- class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName());
-
- SymbolContext sc;
- TypeList class_types;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- size_t num_matches = target->GetImages().FindTypes(sc, linkage_name,
- true, // name_is_fully_qualified
- UINT32_MAX, searched_symbol_files, class_types);
-
- for (size_t i = 0; i < num_matches; ++i)
- {
- TypeSP type_sp = class_types.GetTypeAtIndex(i);
- CompilerType compiler_type = type_sp->GetFullCompilerType();
-
- if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava)
- continue;
-
- if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType())
- {
- class_type_or_name.SetTypeSP(type_sp);
-
- Value &value = in_value.GetValue();
- value_type = value.GetValueType();
- dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0));
- return true;
- }
- }
+ // null references don't have a dynamic type
+ if (in_value.IsNilReference())
return false;
+
+ ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target)
+ return false;
+
+ ConstString linkage_name;
+ CompilerType in_type = in_value.GetCompilerType();
+ if (in_type.IsPossibleDynamicType(nullptr, false, false))
+ linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value);
+ else
+ linkage_name = JavaASTContext::GetLinkageName(in_type);
+
+ if (!linkage_name)
+ return false;
+
+ class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName());
+
+ SymbolContext sc;
+ TypeList class_types;
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ size_t num_matches = target->GetImages().FindTypes(
+ sc, linkage_name,
+ true, // name_is_fully_qualified
+ UINT32_MAX, searched_symbol_files, class_types);
+
+ for (size_t i = 0; i < num_matches; ++i) {
+ TypeSP type_sp = class_types.GetTypeAtIndex(i);
+ CompilerType compiler_type = type_sp->GetFullCompilerType();
+
+ if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava)
+ continue;
+
+ if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) {
+ class_type_or_name.SetTypeSP(type_sp);
+
+ Value &value = in_value.GetValue();
+ value_type = value.GetValueType();
+ dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0));
+ return true;
+ }
+ }
+ return false;
}
TypeAndOrName
-JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
-{
- CompilerType static_type(static_value.GetCompilerType());
+JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) {
+ CompilerType static_type(static_value.GetCompilerType());
- TypeAndOrName ret(type_and_or_name);
- if (type_and_or_name.HasType())
- {
- CompilerType orig_type = type_and_or_name.GetCompilerType();
- if (static_type.IsReferenceType())
- ret.SetCompilerType(orig_type.GetLValueReferenceType());
- }
- return ret;
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType()) {
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ if (static_type.IsReferenceType())
+ ret.SetCompilerType(orig_type.GetLValueReferenceType());
+ }
+ return ret;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h
index 83ed35d..6eeb404 100644
--- a/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h
@@ -19,70 +19,58 @@
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
-namespace lldb_private
-{
+namespace lldb_private {
-class JavaLanguageRuntime : public LanguageRuntime
-{
+class JavaLanguageRuntime : public LanguageRuntime {
public:
- static void
- Initialize();
+ static void Initialize();
- static void
- Terminate();
+ static void Terminate();
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
- static lldb_private::ConstString
- GetPluginNameStatic();
+ static lldb_private::ConstString GetPluginNameStatic();
- lldb_private::ConstString
- GetPluginName() override;
+ lldb_private::ConstString GetPluginName() override;
- uint32_t
- GetPluginVersion() override;
+ uint32_t GetPluginVersion() override;
- lldb::LanguageType
- GetLanguageType() const override
- {
- return lldb::eLanguageTypeJava;
- }
+ lldb::LanguageType GetLanguageType() const override {
+ return lldb::eLanguageTypeJava;
+ }
- bool
- GetObjectDescription(Stream &str, ValueObject &object) override
- {
- return false;
- }
+ bool GetObjectDescription(Stream &str, ValueObject &object) override {
+ return false;
+ }
- bool
- GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override
- {
- return false;
- }
+ bool GetObjectDescription(Stream &str, Value &value,
+ ExecutionContextScope *exe_scope) override {
+ return false;
+ }
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override
- {
- return nullptr;
- }
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override {
+ return nullptr;
+ }
- TypeAndOrName
- FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
- bool
- CouldHaveDynamicValue(ValueObject &in_value) override;
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- bool
- GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type) override;
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
protected:
- JavaLanguageRuntime(Process *process);
+ JavaLanguageRuntime(Process *process);
private:
- DISALLOW_COPY_AND_ASSIGN(JavaLanguageRuntime);
+ DISALLOW_COPY_AND_ASSIGN(JavaLanguageRuntime);
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index 5cf99a5..477f4df 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -1,4 +1,5 @@
-//===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++ -*-===//
+//===-- AppleObjCClassDescriptorV2.cpp -----------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,557 +16,533 @@
using namespace lldb;
using namespace lldb_private;
-bool
-ClassDescriptorV2::Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const
-{
- objc_class.reset(new objc_class_t);
-
- bool ret = objc_class->Read (process, m_objc_class_ptr);
-
- if (!ret)
- objc_class.reset();
-
- return ret;
+bool ClassDescriptorV2::Read_objc_class(
+ Process *process, std::unique_ptr<objc_class_t> &objc_class) const {
+ objc_class.reset(new objc_class_t);
+
+ bool ret = objc_class->Read(process, m_objc_class_ptr);
+
+ if (!ret)
+ objc_class.reset();
+
+ return ret;
}
-bool
-ClassDescriptorV2::objc_class_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t ptr_size = process->GetAddressByteSize();
-
- size_t objc_class_size = ptr_size // uintptr_t isa;
- + ptr_size // Class superclass;
- + ptr_size // void *cache;
- + ptr_size // IMP *vtable;
- + ptr_size; // uintptr_t data_NEVER_USE;
-
- DataBufferHeap objc_class_buf (objc_class_size, '\0');
- Error error;
-
- process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
- m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
- m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
- m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
- lldb::addr_t data_NEVER_USE = extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
-
- m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
- m_data_ptr = data_NEVER_USE & ~(lldb::addr_t)3;
-
- return true;
+bool ClassDescriptorV2::objc_class_t::Read(Process *process,
+ lldb::addr_t addr) {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t objc_class_size = ptr_size // uintptr_t isa;
+ + ptr_size // Class superclass;
+ + ptr_size // void *cache;
+ + ptr_size // IMP *vtable;
+ + ptr_size; // uintptr_t data_NEVER_USE;
+
+ DataBufferHeap objc_class_buf(objc_class_size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, objc_class_buf.GetBytes(), objc_class_size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(objc_class_buf.GetBytes(), objc_class_size,
+ process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_isa = extractor.GetAddress_unchecked(&cursor); // uintptr_t isa;
+ m_superclass = extractor.GetAddress_unchecked(&cursor); // Class superclass;
+ m_cache_ptr = extractor.GetAddress_unchecked(&cursor); // void *cache;
+ m_vtable_ptr = extractor.GetAddress_unchecked(&cursor); // IMP *vtable;
+ lldb::addr_t data_NEVER_USE =
+ extractor.GetAddress_unchecked(&cursor); // uintptr_t data_NEVER_USE;
+
+ m_flags = (uint8_t)(data_NEVER_USE & (lldb::addr_t)3);
+ m_data_ptr = data_NEVER_USE & ~(lldb::addr_t)3;
+
+ return true;
}
-bool
-ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t ptr_size = process->GetAddressByteSize();
-
- size_t size = sizeof(uint32_t) // uint32_t flags;
- + sizeof(uint32_t) // uint32_t version;
- + ptr_size // const class_ro_t *ro;
- + ptr_size // union { method_list_t **method_lists; method_list_t *method_list; };
- + ptr_size // struct chained_property_list *properties;
- + ptr_size // const protocol_list_t **protocols;
- + ptr_size // Class firstSubclass;
- + ptr_size; // Class nextSiblingClass;
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_flags = extractor.GetU32_unchecked(&cursor);
- m_version = extractor.GetU32_unchecked(&cursor);
- m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
- m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
- m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
- m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
- m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
-
- return true;
+bool ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr) {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t version;
+ + ptr_size // const class_ro_t *ro;
+ + ptr_size // union { method_list_t **method_lists;
+ // method_list_t *method_list; };
+ + ptr_size // struct chained_property_list *properties;
+ + ptr_size // const protocol_list_t **protocols;
+ + ptr_size // Class firstSubclass;
+ + ptr_size; // Class nextSiblingClass;
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_version = extractor.GetU32_unchecked(&cursor);
+ m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_method_list_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_properties_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
+ m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
+
+ return true;
}
-bool
-ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t ptr_size = process->GetAddressByteSize();
-
- size_t size = sizeof(uint32_t) // uint32_t flags;
- + sizeof(uint32_t) // uint32_t instanceStart;
- + sizeof(uint32_t) // uint32_t instanceSize;
- + (ptr_size == 8 ? sizeof(uint32_t) : 0) // uint32_t reserved; // __LP64__ only
- + ptr_size // const uint8_t *ivarLayout;
- + ptr_size // const char *name;
- + ptr_size // const method_list_t *baseMethods;
- + ptr_size // const protocol_list_t *baseProtocols;
- + ptr_size // const ivar_list_t *ivars;
- + ptr_size // const uint8_t *weakIvarLayout;
- + ptr_size; // const property_list_t *baseProperties;
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_flags = extractor.GetU32_unchecked(&cursor);
- m_instanceStart = extractor.GetU32_unchecked(&cursor);
- m_instanceSize = extractor.GetU32_unchecked(&cursor);
- if (ptr_size == 8)
- m_reserved = extractor.GetU32_unchecked(&cursor);
- else
- m_reserved = 0;
- m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
- m_name_ptr = extractor.GetAddress_unchecked(&cursor);
- m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
- m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
- m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
- m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
- m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
-
- DataBufferHeap name_buf(1024, '\0');
-
- process->ReadCStringFromMemory(m_name_ptr, (char*)name_buf.GetBytes(), name_buf.GetByteSize(), error);
-
- if (error.Fail())
- {
- return false;
- }
-
- m_name.assign((char*)name_buf.GetBytes());
-
- return true;
+bool ClassDescriptorV2::class_ro_t::Read(Process *process, lldb::addr_t addr) {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ size_t size = sizeof(uint32_t) // uint32_t flags;
+ + sizeof(uint32_t) // uint32_t instanceStart;
+ + sizeof(uint32_t) // uint32_t instanceSize;
+ + (ptr_size == 8 ? sizeof(uint32_t)
+ : 0) // uint32_t reserved; // __LP64__ only
+ + ptr_size // const uint8_t *ivarLayout;
+ + ptr_size // const char *name;
+ + ptr_size // const method_list_t *baseMethods;
+ + ptr_size // const protocol_list_t *baseProtocols;
+ + ptr_size // const ivar_list_t *ivars;
+ + ptr_size // const uint8_t *weakIvarLayout;
+ + ptr_size; // const property_list_t *baseProperties;
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_flags = extractor.GetU32_unchecked(&cursor);
+ m_instanceStart = extractor.GetU32_unchecked(&cursor);
+ m_instanceSize = extractor.GetU32_unchecked(&cursor);
+ if (ptr_size == 8)
+ m_reserved = extractor.GetU32_unchecked(&cursor);
+ else
+ m_reserved = 0;
+ m_ivarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseMethods_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProtocols_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_ivars_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_weakIvarLayout_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_baseProperties_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ DataBufferHeap name_buf(1024, '\0');
+
+ process->ReadCStringFromMemory(m_name_ptr, (char *)name_buf.GetBytes(),
+ name_buf.GetByteSize(), error);
+
+ if (error.Fail()) {
+ return false;
+ }
+
+ m_name.assign((char *)name_buf.GetBytes());
+
+ return true;
}
-bool
-ClassDescriptorV2::Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const
-{
- class_ro.reset();
- class_rw.reset();
-
- Error error;
- uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
- if (!error.Success())
- return false;
-
- if (class_row_t_flags & RW_REALIZED)
- {
- class_rw.reset(new class_rw_t);
-
- if (!class_rw->Read(process, objc_class.m_data_ptr))
- {
- class_rw.reset();
- return false;
- }
-
- class_ro.reset(new class_ro_t);
-
- if (!class_ro->Read(process, class_rw->m_ro_ptr))
- {
- class_rw.reset();
- class_ro.reset();
- return false;
- }
+bool ClassDescriptorV2::Read_class_row(
+ Process *process, const objc_class_t &objc_class,
+ std::unique_ptr<class_ro_t> &class_ro,
+ std::unique_ptr<class_rw_t> &class_rw) const {
+ class_ro.reset();
+ class_rw.reset();
+
+ Error error;
+ uint32_t class_row_t_flags = process->ReadUnsignedIntegerFromMemory(
+ objc_class.m_data_ptr, sizeof(uint32_t), 0, error);
+ if (!error.Success())
+ return false;
+
+ if (class_row_t_flags & RW_REALIZED) {
+ class_rw.reset(new class_rw_t);
+
+ if (!class_rw->Read(process, objc_class.m_data_ptr)) {
+ class_rw.reset();
+ return false;
}
- else
- {
- class_ro.reset(new class_ro_t);
-
- if (!class_ro->Read(process, objc_class.m_data_ptr))
- {
- class_ro.reset();
- return false;
- }
+
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, class_rw->m_ro_ptr)) {
+ class_rw.reset();
+ class_ro.reset();
+ return false;
}
-
- return true;
+ } else {
+ class_ro.reset(new class_ro_t);
+
+ if (!class_ro->Read(process, objc_class.m_data_ptr)) {
+ class_ro.reset();
+ return false;
+ }
+ }
+
+ return true;
}
-bool
-ClassDescriptorV2::method_list_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
- + sizeof(uint32_t); // uint32_t count;
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
- m_count = extractor.GetU32_unchecked(&cursor);
- m_first_ptr = addr + cursor;
-
- return true;
+bool ClassDescriptorV2::method_list_t::Read(Process *process,
+ lldb::addr_t addr) {
+ size_t size = sizeof(uint32_t) // uint32_t entsize_NEVER_USE;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor) & ~(uint32_t)3;
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
}
-bool
-ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t size = GetSize(process);
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_name_ptr = extractor.GetAddress_unchecked(&cursor);
- m_types_ptr = extractor.GetAddress_unchecked(&cursor);
- m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
-
- process->ReadCStringFromMemory(m_name_ptr, m_name, error);
- if (error.Fail())
- {
- return false;
- }
-
- process->ReadCStringFromMemory(m_types_ptr, m_types, error);
- if (error.Fail())
- {
- return false;
- }
-
- return true;
+bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) {
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_types_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_imp_ptr = extractor.GetAddress_unchecked(&cursor);
+
+ process->ReadCStringFromMemory(m_name_ptr, m_name, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ process->ReadCStringFromMemory(m_types_ptr, m_types, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ return true;
}
-bool
-ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t size = sizeof(uint32_t) // uint32_t entsize;
- + sizeof(uint32_t); // uint32_t count;
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_entsize = extractor.GetU32_unchecked(&cursor);
- m_count = extractor.GetU32_unchecked(&cursor);
- m_first_ptr = addr + cursor;
-
- return true;
+bool ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr) {
+ size_t size = sizeof(uint32_t) // uint32_t entsize;
+ + sizeof(uint32_t); // uint32_t count;
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_entsize = extractor.GetU32_unchecked(&cursor);
+ m_count = extractor.GetU32_unchecked(&cursor);
+ m_first_ptr = addr + cursor;
+
+ return true;
}
-bool
-ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr)
-{
- size_t size = GetSize(process);
-
- DataBufferHeap buffer (size, '\0');
- Error error;
-
- process->ReadMemory(addr, buffer.GetBytes(), size, error);
- if (error.Fail())
- {
- return false;
- }
-
- DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(), process->GetAddressByteSize());
-
- lldb::offset_t cursor = 0;
-
- m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
- m_name_ptr = extractor.GetAddress_unchecked(&cursor);
- m_type_ptr = extractor.GetAddress_unchecked(&cursor);
- m_alignment = extractor.GetU32_unchecked(&cursor);
- m_size = extractor.GetU32_unchecked(&cursor);
-
- process->ReadCStringFromMemory(m_name_ptr, m_name, error);
- if (error.Fail())
- {
- return false;
- }
-
- process->ReadCStringFromMemory(m_type_ptr, m_type, error);
- if (error.Fail())
- {
- return false;
- }
-
- return true;
+bool ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr) {
+ size_t size = GetSize(process);
+
+ DataBufferHeap buffer(size, '\0');
+ Error error;
+
+ process->ReadMemory(addr, buffer.GetBytes(), size, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ DataExtractor extractor(buffer.GetBytes(), size, process->GetByteOrder(),
+ process->GetAddressByteSize());
+
+ lldb::offset_t cursor = 0;
+
+ m_offset_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_name_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_type_ptr = extractor.GetAddress_unchecked(&cursor);
+ m_alignment = extractor.GetU32_unchecked(&cursor);
+ m_size = extractor.GetU32_unchecked(&cursor);
+
+ process->ReadCStringFromMemory(m_name_ptr, m_name, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ process->ReadCStringFromMemory(m_type_ptr, m_type, error);
+ if (error.Fail()) {
+ return false;
+ }
+
+ return true;
}
-bool
-ClassDescriptorV2::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
- std::function <bool (const char *, const char *)> const &instance_method_func,
- std::function <bool (const char *, const char *)> const &class_method_func,
- std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
-{
+bool ClassDescriptorV2::Describe(
+ std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function<bool(const char *, const char *)> const &instance_method_func,
+ std::function<bool(const char *, const char *)> const &class_method_func,
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)> const &ivar_func) const {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return 0;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return 0;
+
+ static ConstString NSObject_name("NSObject");
+
+ if (m_name != NSObject_name && superclass_func)
+ superclass_func(objc_class->m_superclass);
+
+ if (instance_method_func) {
+ std::unique_ptr<method_list_t> base_method_list;
+
+ base_method_list.reset(new method_list_t);
+ if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
+ return false;
+
+ if (base_method_list->m_entsize != method_t::GetSize(process))
+ return false;
+
+ std::unique_ptr<method_t> method;
+ method.reset(new method_t);
+
+ for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) {
+ method->Read(process, base_method_list->m_first_ptr +
+ (i * base_method_list->m_entsize));
+
+ if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
+ break;
+ }
+ }
+
+ if (class_method_func) {
+ AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
+
+ // We don't care about the metaclass's superclass, or its class methods.
+ // Its instance methods are
+ // our class methods.
+
+ if (metaclass) {
+ metaclass->Describe(
+ std::function<void(ObjCLanguageRuntime::ObjCISA)>(nullptr),
+ class_method_func,
+ std::function<bool(const char *, const char *)>(nullptr),
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)>(nullptr));
+ }
+ }
+
+ if (ivar_func) {
+ if (class_ro->m_ivars_ptr != 0) {
+ ivar_list_t ivar_list;
+ if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
+ return false;
+
+ if (ivar_list.m_entsize != ivar_t::GetSize(process))
+ return false;
+
+ ivar_t ivar;
+
+ for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i) {
+ ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
+
+ if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(),
+ ivar.m_offset_ptr, ivar.m_size))
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+ConstString ClassDescriptorV2::GetClassName() {
+ if (!m_name) {
lldb_private::Process *process = m_runtime.GetProcess();
-
+
+ if (process) {
+ std::unique_ptr<objc_class_t> objc_class;
+ std::unique_ptr<class_ro_t> class_ro;
+ std::unique_ptr<class_rw_t> class_rw;
+
+ if (!Read_objc_class(process, objc_class))
+ return m_name;
+ if (!Read_class_row(process, *objc_class, class_ro, class_rw))
+ return m_name;
+
+ m_name = ConstString(class_ro->m_name.c_str());
+ }
+ }
+ return m_name;
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP ClassDescriptorV2::GetSuperclass() {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (!process)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ std::unique_ptr<objc_class_t> objc_class;
+
+ if (!Read_objc_class(process, objc_class))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(
+ objc_class->m_superclass);
+}
+
+ObjCLanguageRuntime::ClassDescriptorSP ClassDescriptorV2::GetMetaclass() const {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (!process)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ std::unique_ptr<objc_class_t> objc_class;
+
+ if (!Read_objc_class(process, objc_class))
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+
+ lldb::addr_t candidate_isa = m_runtime.GetPointerISA(objc_class->m_isa);
+
+ return ObjCLanguageRuntime::ClassDescriptorSP(
+ new ClassDescriptorV2(m_runtime, candidate_isa, nullptr));
+}
+
+uint64_t ClassDescriptorV2::GetInstanceSize() {
+ lldb_private::Process *process = m_runtime.GetProcess();
+
+ if (process) {
std::unique_ptr<objc_class_t> objc_class;
std::unique_ptr<class_ro_t> class_ro;
std::unique_ptr<class_rw_t> class_rw;
-
+
if (!Read_objc_class(process, objc_class))
- return 0;
+ return 0;
if (!Read_class_row(process, *objc_class, class_ro, class_rw))
- return 0;
-
- static ConstString NSObject_name("NSObject");
-
- if (m_name != NSObject_name && superclass_func)
- superclass_func(objc_class->m_superclass);
-
- if (instance_method_func)
- {
- std::unique_ptr<method_list_t> base_method_list;
-
- base_method_list.reset(new method_list_t);
- if (!base_method_list->Read(process, class_ro->m_baseMethods_ptr))
- return false;
-
- if (base_method_list->m_entsize != method_t::GetSize(process))
- return false;
-
- std::unique_ptr<method_t> method;
- method.reset(new method_t);
-
- for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i)
- {
- method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize));
-
- if (instance_method_func(method->m_name.c_str(), method->m_types.c_str()))
- break;
- }
- }
-
- if (class_method_func)
- {
- AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
-
- // We don't care about the metaclass's superclass, or its class methods. Its instance methods are
- // our class methods.
-
- if (metaclass) {
- metaclass->Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> (nullptr),
- class_method_func,
- std::function <bool (const char *, const char *)> (nullptr),
- std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr));
- }
- }
-
- if (ivar_func)
- {
- if (class_ro->m_ivars_ptr != 0)
- {
- ivar_list_t ivar_list;
- if (!ivar_list.Read(process, class_ro->m_ivars_ptr))
- return false;
-
- if (ivar_list.m_entsize != ivar_t::GetSize(process))
- return false;
-
- ivar_t ivar;
-
- for (uint32_t i = 0, e = ivar_list.m_count; i < e; ++i)
- {
- ivar.Read(process, ivar_list.m_first_ptr + (i * ivar_list.m_entsize));
-
- if (ivar_func(ivar.m_name.c_str(), ivar.m_type.c_str(), ivar.m_offset_ptr, ivar.m_size))
- break;
- }
- }
- }
-
- return true;
+ return 0;
+
+ return class_ro->m_instanceSize;
+ }
+
+ return 0;
}
-ConstString
-ClassDescriptorV2::GetClassName ()
-{
- if (!m_name)
- {
- lldb_private::Process *process = m_runtime.GetProcess();
-
- if (process)
- {
- std::unique_ptr<objc_class_t> objc_class;
- std::unique_ptr<class_ro_t> class_ro;
- std::unique_ptr<class_rw_t> class_rw;
-
- if (!Read_objc_class(process, objc_class))
- return m_name;
- if (!Read_class_row(process, *objc_class, class_ro, class_rw))
- return m_name;
-
- m_name = ConstString(class_ro->m_name.c_str());
- }
- }
- return m_name;
+ClassDescriptorV2::iVarsStorage::iVarsStorage()
+ : m_filled(false), m_ivars(), m_mutex() {}
+
+size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); }
+
+ClassDescriptorV2::iVarDescriptor &ClassDescriptorV2::iVarsStorage::
+operator[](size_t idx) {
+ return m_ivars[idx];
}
-ObjCLanguageRuntime::ClassDescriptorSP
-ClassDescriptorV2::GetSuperclass ()
-{
- lldb_private::Process *process = m_runtime.GetProcess();
-
- if (!process)
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- std::unique_ptr<objc_class_t> objc_class;
-
- if (!Read_objc_class(process, objc_class))
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- return m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(objc_class->m_superclass);
-}
-
-ObjCLanguageRuntime::ClassDescriptorSP
-ClassDescriptorV2::GetMetaclass () const
-{
- lldb_private::Process *process = m_runtime.GetProcess();
-
- if (!process)
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- std::unique_ptr<objc_class_t> objc_class;
-
- if (!Read_objc_class(process, objc_class))
- return ObjCLanguageRuntime::ClassDescriptorSP();
-
- lldb::addr_t candidate_isa = m_runtime.GetPointerISA(objc_class->m_isa);
-
- return ObjCLanguageRuntime::ClassDescriptorSP(new ClassDescriptorV2(m_runtime, candidate_isa, nullptr));
-}
-
-uint64_t
-ClassDescriptorV2::GetInstanceSize ()
-{
- lldb_private::Process *process = m_runtime.GetProcess();
-
- if (process)
- {
- std::unique_ptr<objc_class_t> objc_class;
- std::unique_ptr<class_ro_t> class_ro;
- std::unique_ptr<class_rw_t> class_rw;
-
- if (!Read_objc_class(process, objc_class))
- return 0;
- if (!Read_class_row(process, *objc_class, class_ro, class_rw))
- return 0;
-
- return class_ro->m_instanceSize;
- }
-
- return 0;
-}
-
-ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_filled(false), m_ivars(), m_mutex()
-{
-}
-
-size_t
-ClassDescriptorV2::iVarsStorage::size ()
-{
- return m_ivars.size();
-}
-
-ClassDescriptorV2::iVarDescriptor&
-ClassDescriptorV2::iVarsStorage::operator[] (size_t idx)
-{
- return m_ivars[idx];
-}
-
-void
-ClassDescriptorV2::iVarsStorage::fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor)
-{
- if (m_filled)
- return;
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES | LIBLLDB_LOG_VERBOSE));
+void ClassDescriptorV2::iVarsStorage::fill(AppleObjCRuntimeV2 &runtime,
+ ClassDescriptorV2 &descriptor) {
+ if (m_filled)
+ return;
+ std::lock_guard<std::recursive_mutex> guard(m_mutex);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] class_name = %s",
+ descriptor.GetClassName().AsCString("<unknown"));
+ m_filled = true;
+ ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(
+ runtime.GetEncodingToType());
+ Process *process(runtime.GetProcess());
+ if (!encoding_to_type_sp)
+ return;
+ descriptor.Describe(nullptr, nullptr, nullptr, [this, process,
+ encoding_to_type_sp,
+ log](const char *name,
+ const char *type,
+ lldb::addr_t offset_ptr,
+ uint64_t size) -> bool {
+ const bool for_expression = false;
+ const bool stop_loop = false;
if (log)
- log->Printf("[ClassDescriptorV2::iVarsStorage::fill] class_name = %s", descriptor.GetClassName().AsCString("<unknown"));
- m_filled = true;
- ObjCLanguageRuntime::EncodingToTypeSP encoding_to_type_sp(runtime.GetEncodingToType());
- Process* process(runtime.GetProcess());
- if (!encoding_to_type_sp)
- return;
- descriptor.Describe(nullptr,
- nullptr,
- nullptr,
- [this,process,encoding_to_type_sp,log](const char * name, const char * type, lldb::addr_t offset_ptr, uint64_t size) -> bool {
- const bool for_expression = false;
- const bool stop_loop = false;
- if (log)
- log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, encoding = %s, offset_ptr = %" PRIx64 ", size = %" PRIu64,
- name,type,offset_ptr,size);
- CompilerType ivar_type = encoding_to_type_sp->RealizeType(type, for_expression);
- if (ivar_type)
- {
- if (log)
- log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, encoding = %s, offset_ptr = %" PRIx64 ", size = %" PRIu64 " , type_size = %" PRIu64,
- name,type,offset_ptr,size,ivar_type.GetByteSize(nullptr));
- Scalar offset_scalar;
- Error error;
- const int offset_ptr_size = 4;
- const bool is_signed = false;
- size_t read = process->ReadScalarIntegerFromMemory(offset_ptr, offset_ptr_size, is_signed, offset_scalar, error);
- if (error.Success() && 4 == read)
- {
- if (log)
- log->Printf("[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64 " --> %" PRIu32,
- offset_ptr, offset_scalar.SInt());
- m_ivars.push_back({ ConstString(name), ivar_type, size, offset_scalar.SInt() });
- }
- else if (log)
- log->Printf("[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64 " --> read fail, read = %zu",
- offset_ptr, read);
- }
- return stop_loop;
- });
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, encoding "
+ "= %s, offset_ptr = %" PRIx64 ", size = %" PRIu64,
+ name, type, offset_ptr, size);
+ CompilerType ivar_type =
+ encoding_to_type_sp->RealizeType(type, for_expression);
+ if (ivar_type) {
+ if (log)
+ log->Printf("[ClassDescriptorV2::iVarsStorage::fill] name = %s, "
+ "encoding = %s, offset_ptr = %" PRIx64 ", size = %" PRIu64
+ " , type_size = %" PRIu64,
+ name, type, offset_ptr, size,
+ ivar_type.GetByteSize(nullptr));
+ Scalar offset_scalar;
+ Error error;
+ const int offset_ptr_size = 4;
+ const bool is_signed = false;
+ size_t read = process->ReadScalarIntegerFromMemory(
+ offset_ptr, offset_ptr_size, is_signed, offset_scalar, error);
+ if (error.Success() && 4 == read) {
+ if (log)
+ log->Printf(
+ "[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64
+ " --> %" PRIu32,
+ offset_ptr, offset_scalar.SInt());
+ m_ivars.push_back(
+ {ConstString(name), ivar_type, size, offset_scalar.SInt()});
+ } else if (log)
+ log->Printf(
+ "[ClassDescriptorV2::iVarsStorage::fill] offset_ptr = %" PRIx64
+ " --> read fail, read = %zu",
+ offset_ptr, read);
+ }
+ return stop_loop;
+ });
}
-void
-ClassDescriptorV2::GetIVarInformation ()
-{
- m_ivars_storage.fill(m_runtime, *this);
+void ClassDescriptorV2::GetIVarInformation() {
+ m_ivars_storage.fill(m_runtime, *this);
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
index f5fc8bc..787423b 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -16,397 +16,320 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "AppleObjCRuntimeV2.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor
-{
+class ClassDescriptorV2 : public ObjCLanguageRuntime::ClassDescriptor {
public:
- friend class lldb_private::AppleObjCRuntimeV2;
-
- ~ClassDescriptorV2() override = default;
+ friend class lldb_private::AppleObjCRuntimeV2;
- ConstString
- GetClassName() override;
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetSuperclass() override;
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetMetaclass() const override;
-
- bool
- IsValid() override
- {
- return true; // any Objective-C v2 runtime class descriptor we vend is valid
- }
-
- // a custom descriptor is used for tagged pointers
- bool
- GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
- uint64_t* value_bits = nullptr,
- uint64_t* payload = nullptr) override
- {
- return false;
- }
-
- uint64_t
- GetInstanceSize() override;
-
- ObjCLanguageRuntime::ObjCISA
- GetISA() override
- {
- return m_objc_class_ptr;
- }
-
- bool
- Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
- std::function <bool (const char *, const char *)> const &instance_method_func,
- std::function <bool (const char *, const char *)> const &class_method_func,
- std::function <bool (const char *, const char *,
- lldb::addr_t, uint64_t)> const &ivar_func) const override;
+ ~ClassDescriptorV2() override = default;
- size_t
- GetNumIVars() override
- {
- GetIVarInformation();
- return m_ivars_storage.size();
- }
-
- iVarDescriptor
- GetIVarAtIndex(size_t idx) override
- {
- if (idx >= GetNumIVars())
- return iVarDescriptor();
- return m_ivars_storage[idx];
- }
-
+ ConstString GetClassName() override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override;
+
+ bool IsValid() override {
+ return true; // any Objective-C v2 runtime class descriptor we vend is valid
+ }
+
+ // a custom descriptor is used for tagged pointers
+ bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
+ uint64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
+ uint64_t GetInstanceSize() override;
+
+ ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }
+
+ bool Describe(
+ std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function<bool(const char *, const char *)> const
+ &instance_method_func,
+ std::function<bool(const char *, const char *)> const &class_method_func,
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)> const &ivar_func) const override;
+
+ size_t GetNumIVars() override {
+ GetIVarInformation();
+ return m_ivars_storage.size();
+ }
+
+ iVarDescriptor GetIVarAtIndex(size_t idx) override {
+ if (idx >= GetNumIVars())
+ return iVarDescriptor();
+ return m_ivars_storage[idx];
+ }
+
protected:
- void
- GetIVarInformation ();
-
+ void GetIVarInformation();
+
private:
- static const uint32_t RW_REALIZED = (1 << 31);
-
- struct objc_class_t {
- ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
- ObjCLanguageRuntime::ObjCISA m_superclass;
- lldb::addr_t m_cache_ptr;
- lldb::addr_t m_vtable_ptr;
- lldb::addr_t m_data_ptr;
- uint8_t m_flags;
-
- objc_class_t () :
- m_isa (0),
- m_superclass (0),
- m_cache_ptr (0),
- m_vtable_ptr (0),
- m_data_ptr (0),
- m_flags (0)
- {
- }
-
- void
- Clear()
- {
- m_isa = 0;
- m_superclass = 0;
- m_cache_ptr = 0;
- m_vtable_ptr = 0;
- m_data_ptr = 0;
- m_flags = 0;
- }
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- struct class_ro_t {
- uint32_t m_flags;
- uint32_t m_instanceStart;
- uint32_t m_instanceSize;
- uint32_t m_reserved;
-
- lldb::addr_t m_ivarLayout_ptr;
- lldb::addr_t m_name_ptr;
- lldb::addr_t m_baseMethods_ptr;
- lldb::addr_t m_baseProtocols_ptr;
- lldb::addr_t m_ivars_ptr;
-
- lldb::addr_t m_weakIvarLayout_ptr;
- lldb::addr_t m_baseProperties_ptr;
-
- std::string m_name;
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- struct class_rw_t {
- uint32_t m_flags;
- uint32_t m_version;
-
- lldb::addr_t m_ro_ptr;
- union {
- lldb::addr_t m_method_list_ptr;
- lldb::addr_t m_method_lists_ptr;
- };
- lldb::addr_t m_properties_ptr;
- lldb::addr_t m_protocols_ptr;
-
- ObjCLanguageRuntime::ObjCISA m_firstSubclass;
- ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- struct method_list_t
- {
- uint32_t m_entsize;
- uint32_t m_count;
- lldb::addr_t m_first_ptr;
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- struct method_t
- {
- lldb::addr_t m_name_ptr;
- lldb::addr_t m_types_ptr;
- lldb::addr_t m_imp_ptr;
-
- std::string m_name;
- std::string m_types;
-
- static size_t GetSize(Process *process)
- {
- size_t ptr_size = process->GetAddressByteSize();
-
- return ptr_size // SEL name;
- + ptr_size // const char *types;
- + ptr_size; // IMP imp;
- }
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- struct ivar_list_t
- {
- uint32_t m_entsize;
- uint32_t m_count;
- lldb::addr_t m_first_ptr;
-
- bool Read(Process *process, lldb::addr_t addr);
- };
-
- struct ivar_t
- {
- lldb::addr_t m_offset_ptr;
- lldb::addr_t m_name_ptr;
- lldb::addr_t m_type_ptr;
- uint32_t m_alignment;
- uint32_t m_size;
-
- std::string m_name;
- std::string m_type;
-
- static size_t GetSize(Process *process)
- {
- size_t ptr_size = process->GetAddressByteSize();
-
- return ptr_size // uintptr_t *offset;
- + ptr_size // const char *name;
- + ptr_size // const char *type;
- + sizeof(uint32_t) // uint32_t alignment;
- + sizeof(uint32_t); // uint32_t size;
- }
-
- bool
- Read(Process *process, lldb::addr_t addr);
- };
-
- class iVarsStorage
- {
- public:
- iVarsStorage ();
-
- size_t
- size ();
-
- iVarDescriptor&
- operator[] (size_t idx);
-
- void
- fill (AppleObjCRuntimeV2& runtime, ClassDescriptorV2& descriptor);
-
- private:
- bool m_filled;
- std::vector<iVarDescriptor> m_ivars;
- std::recursive_mutex m_mutex;
- };
-
- // The constructor should only be invoked by the runtime as it builds its caches
- // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
- ClassDescriptorV2(AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name) :
- m_runtime (runtime),
- m_objc_class_ptr (isa),
- m_name (name),
- m_ivars_storage()
- {
+ static const uint32_t RW_REALIZED = (1 << 31);
+
+ struct objc_class_t {
+ ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
+ ObjCLanguageRuntime::ObjCISA m_superclass;
+ lldb::addr_t m_cache_ptr;
+ lldb::addr_t m_vtable_ptr;
+ lldb::addr_t m_data_ptr;
+ uint8_t m_flags;
+
+ objc_class_t()
+ : m_isa(0), m_superclass(0), m_cache_ptr(0), m_vtable_ptr(0),
+ m_data_ptr(0), m_flags(0) {}
+
+ void Clear() {
+ m_isa = 0;
+ m_superclass = 0;
+ m_cache_ptr = 0;
+ m_vtable_ptr = 0;
+ m_data_ptr = 0;
+ m_flags = 0;
}
-
- bool
- Read_objc_class (Process* process, std::unique_ptr<objc_class_t> &objc_class) const;
-
- bool
- Read_class_row (Process* process, const objc_class_t &objc_class, std::unique_ptr<class_ro_t> &class_ro, std::unique_ptr<class_rw_t> &class_rw) const;
-
- AppleObjCRuntimeV2 &m_runtime; // The runtime, so we can read information lazily.
- lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e., objects of this class type have this as their ISA)
- ConstString m_name; // May be NULL
- iVarsStorage m_ivars_storage;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct class_ro_t {
+ uint32_t m_flags;
+ uint32_t m_instanceStart;
+ uint32_t m_instanceSize;
+ uint32_t m_reserved;
+
+ lldb::addr_t m_ivarLayout_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_baseMethods_ptr;
+ lldb::addr_t m_baseProtocols_ptr;
+ lldb::addr_t m_ivars_ptr;
+
+ lldb::addr_t m_weakIvarLayout_ptr;
+ lldb::addr_t m_baseProperties_ptr;
+
+ std::string m_name;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct class_rw_t {
+ uint32_t m_flags;
+ uint32_t m_version;
+
+ lldb::addr_t m_ro_ptr;
+ union {
+ lldb::addr_t m_method_list_ptr;
+ lldb::addr_t m_method_lists_ptr;
+ };
+ lldb::addr_t m_properties_ptr;
+ lldb::addr_t m_protocols_ptr;
+
+ ObjCLanguageRuntime::ObjCISA m_firstSubclass;
+ ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct method_list_t {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct method_t {
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_types_ptr;
+ lldb::addr_t m_imp_ptr;
+
+ std::string m_name;
+ std::string m_types;
+
+ static size_t GetSize(Process *process) {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // SEL name;
+ + ptr_size // const char *types;
+ + ptr_size; // IMP imp;
+ }
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct ivar_list_t {
+ uint32_t m_entsize;
+ uint32_t m_count;
+ lldb::addr_t m_first_ptr;
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ struct ivar_t {
+ lldb::addr_t m_offset_ptr;
+ lldb::addr_t m_name_ptr;
+ lldb::addr_t m_type_ptr;
+ uint32_t m_alignment;
+ uint32_t m_size;
+
+ std::string m_name;
+ std::string m_type;
+
+ static size_t GetSize(Process *process) {
+ size_t ptr_size = process->GetAddressByteSize();
+
+ return ptr_size // uintptr_t *offset;
+ + ptr_size // const char *name;
+ + ptr_size // const char *type;
+ + sizeof(uint32_t) // uint32_t alignment;
+ + sizeof(uint32_t); // uint32_t size;
+ }
+
+ bool Read(Process *process, lldb::addr_t addr);
+ };
+
+ class iVarsStorage {
+ public:
+ iVarsStorage();
+
+ size_t size();
+
+ iVarDescriptor &operator[](size_t idx);
+
+ void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
+
+ private:
+ bool m_filled;
+ std::vector<iVarDescriptor> m_ivars;
+ std::recursive_mutex m_mutex;
+ };
+
+ // The constructor should only be invoked by the runtime as it builds its
+ // caches
+ // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
+ ClassDescriptorV2(AppleObjCRuntimeV2 &runtime,
+ ObjCLanguageRuntime::ObjCISA isa, const char *name)
+ : m_runtime(runtime), m_objc_class_ptr(isa), m_name(name),
+ m_ivars_storage() {}
+
+ bool Read_objc_class(Process *process,
+ std::unique_ptr<objc_class_t> &objc_class) const;
+
+ bool Read_class_row(Process *process, const objc_class_t &objc_class,
+ std::unique_ptr<class_ro_t> &class_ro,
+ std::unique_ptr<class_rw_t> &class_rw) const;
+
+ AppleObjCRuntimeV2
+ &m_runtime; // The runtime, so we can read information lazily.
+ lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e.,
+ // objects of this class type have this as
+ // their ISA)
+ ConstString m_name; // May be NULL
+ iVarsStorage m_ivars_storage;
};
// tagged pointer descriptor
-class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor
-{
+class ClassDescriptorV2Tagged : public ObjCLanguageRuntime::ClassDescriptor {
public:
- ClassDescriptorV2Tagged (ConstString class_name,
- uint64_t payload)
- {
- m_name = class_name;
- if (!m_name)
- {
- m_valid = false;
- return;
- }
- m_valid = true;
- m_payload = payload;
- m_info_bits = (m_payload & 0xF0ULL) >> 4;
- m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+ ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
+ m_name = class_name;
+ if (!m_name) {
+ m_valid = false;
+ return;
}
-
- ClassDescriptorV2Tagged (ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
- uint64_t payload)
- {
- if (!actual_class_sp)
- {
- m_valid = false;
- return;
- }
- m_name = actual_class_sp->GetClassName();
- if (!m_name)
- {
- m_valid = false;
- return;
- }
- m_valid = true;
- m_payload = payload;
- m_info_bits = (m_payload & 0x0FULL);
- m_value_bits = (m_payload & ~0x0FULL) >> 4;
- }
-
- ~ClassDescriptorV2Tagged() override = default;
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0xF0ULL) >> 4;
+ m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
+ }
- ConstString
- GetClassName() override
- {
- return m_name;
+ ClassDescriptorV2Tagged(
+ ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp,
+ uint64_t payload) {
+ if (!actual_class_sp) {
+ m_valid = false;
+ return;
}
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetSuperclass() override
- {
- // tagged pointers can represent a class that has a superclass, but since that information is not
- // stored in the object itself, we would have to query the runtime to discover the hierarchy
- // for the time being, we skip this step in the interest of static discovery
- return ObjCLanguageRuntime::ClassDescriptorSP();
+ m_name = actual_class_sp->GetClassName();
+ if (!m_name) {
+ m_valid = false;
+ return;
}
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetMetaclass() const override
- {
- return ObjCLanguageRuntime::ClassDescriptorSP();
- }
-
- bool
- IsValid() override
- {
- return m_valid;
- }
-
- bool
- IsKVO() override
- {
- return false; // tagged pointers are not KVO'ed
- }
-
- bool
- IsCFType() override
- {
- return false; // tagged pointers are not CF objects
- }
-
- bool
- GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
- uint64_t* value_bits = nullptr,
- uint64_t* payload = nullptr) override
- {
- if (info_bits)
- *info_bits = GetInfoBits();
- if (value_bits)
- *value_bits = GetValueBits();
- if (payload)
- *payload = GetPayload();
- return true;
- }
-
- uint64_t
- GetInstanceSize() override
- {
- return (IsValid() ? m_pointer_size : 0);
- }
-
- ObjCLanguageRuntime::ObjCISA
- GetISA() override
- {
- return 0; // tagged pointers have no ISA
- }
-
- // these calls are not part of any formal tagged pointers specification
- virtual uint64_t
- GetValueBits ()
- {
- return (IsValid() ? m_value_bits : 0);
- }
-
- virtual uint64_t
- GetInfoBits ()
- {
- return (IsValid() ? m_info_bits : 0);
- }
-
- virtual uint64_t
- GetPayload ()
- {
- return (IsValid() ? m_payload : 0);
- }
+ m_valid = true;
+ m_payload = payload;
+ m_info_bits = (m_payload & 0x0FULL);
+ m_value_bits = (m_payload & ~0x0FULL) >> 4;
+ }
+
+ ~ClassDescriptorV2Tagged() override = default;
+
+ ConstString GetClassName() override { return m_name; }
+
+ ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override {
+ // tagged pointers can represent a class that has a superclass, but since
+ // that information is not
+ // stored in the object itself, we would have to query the runtime to
+ // discover the hierarchy
+ // for the time being, we skip this step in the interest of static discovery
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override {
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+ }
+
+ bool IsValid() override { return m_valid; }
+
+ bool IsKVO() override {
+ return false; // tagged pointers are not KVO'ed
+ }
+
+ bool IsCFType() override {
+ return false; // tagged pointers are not CF objects
+ }
+
+ bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
+ uint64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ if (info_bits)
+ *info_bits = GetInfoBits();
+ if (value_bits)
+ *value_bits = GetValueBits();
+ if (payload)
+ *payload = GetPayload();
+ return true;
+ }
+
+ uint64_t GetInstanceSize() override {
+ return (IsValid() ? m_pointer_size : 0);
+ }
+
+ ObjCLanguageRuntime::ObjCISA GetISA() override {
+ return 0; // tagged pointers have no ISA
+ }
+
+ // these calls are not part of any formal tagged pointers specification
+ virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
+
+ virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
+
+ virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
private:
- ConstString m_name;
- uint8_t m_pointer_size;
- bool m_valid;
- uint64_t m_info_bits;
- uint64_t m_value_bits;
- uint64_t m_payload;
+ ConstString m_name;
+ uint8_t m_pointer_size;
+ bool m_valid;
+ uint64_t m_info_bits;
+ uint64_t m_value_bits;
+ uint64_t m_payload;
};
-
+
} // namespace lldb_private
#endif // liblldb_AppleObjCClassDescriptorV2_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 0c0e4f1..922d192 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -23,659 +23,628 @@
using namespace lldb_private;
-class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon
-{
+class lldb_private::AppleObjCExternalASTSource
+ : public ClangExternalASTSourceCommon {
public:
- AppleObjCExternalASTSource (AppleObjCDeclVendor &decl_vendor) :
- m_decl_vendor(decl_vendor)
- {
+ AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
+ : m_decl_vendor(decl_vendor) {}
+
+ bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx,
+ clang::DeclarationName name) override {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(
+ LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log) {
+ log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%"
+ "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
+ current_id,
+ static_cast<void *>(&decl_ctx->getParentASTContext()),
+ name.getAsString().c_str(), decl_ctx->getDeclKindName(),
+ static_cast<const void *>(decl_ctx));
}
- bool
- FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, clang::DeclarationName name) override
- {
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
+ do {
+ const clang::ObjCInterfaceDecl *interface_decl =
+ llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+ if (!interface_decl)
+ break;
- if (log)
- {
- log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
- current_id,
- static_cast<void*>(&decl_ctx->getParentASTContext()),
- name.getAsString().c_str(), decl_ctx->getDeclKindName(),
- static_cast<const void*>(decl_ctx));
- }
+ clang::ObjCInterfaceDecl *non_const_interface_decl =
+ const_cast<clang::ObjCInterfaceDecl *>(interface_decl);
- do
- {
- const clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
+ if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
+ break;
- if (!interface_decl)
- break;
+ clang::DeclContext::lookup_result result =
+ non_const_interface_decl->lookup(name);
- clang::ObjCInterfaceDecl *non_const_interface_decl = const_cast<clang::ObjCInterfaceDecl*>(interface_decl);
+ return (result.size() != 0);
+ } while (0);
- if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
- break;
+ SetNoExternalVisibleDeclsForName(decl_ctx, name);
+ return false;
+ }
- clang::DeclContext::lookup_result result = non_const_interface_decl->lookup(name);
+ void CompleteType(clang::TagDecl *tag_decl) override {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
- return (result.size() != 0);
- }
- while(0);
+ Log *log(GetLogIfAllCategoriesSet(
+ LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- SetNoExternalVisibleDeclsForName(decl_ctx, name);
- return false;
+ if (log) {
+ log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on "
+ "(ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id, static_cast<void *>(&tag_decl->getASTContext()),
+ static_cast<void *>(tag_decl),
+ tag_decl->getName().str().c_str());
+
+ log->Printf(" AOEAS::CT[%u] Before:", current_id);
+ ASTDumper dumper((clang::Decl *)tag_decl);
+ dumper.ToLog(log, " [CT] ");
}
- void
- CompleteType(clang::TagDecl *tag_decl) override
- {
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
+ if (log) {
+ log->Printf(" AOEAS::CT[%u] After:", current_id);
+ ASTDumper dumper((clang::Decl *)tag_decl);
+ dumper.ToLog(log, " [CT] ");
+ }
+ return;
+ }
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+ void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
- if (log)
- {
- log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
- current_id,
- static_cast<void*>(&tag_decl->getASTContext()),
- static_cast<void*>(tag_decl),
- tag_decl->getName().str().c_str());
+ Log *log(GetLogIfAllCategoriesSet(
+ LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- log->Printf(" AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl*)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
+ if (log) {
+ log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on "
+ "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
+ current_id,
+ static_cast<void *>(&interface_decl->getASTContext()),
+ static_cast<void *>(interface_decl),
+ interface_decl->getName().str().c_str());
- if (log)
- {
- log->Printf(" AOEAS::CT[%u] After:", current_id);
- ASTDumper dumper((clang::Decl*)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
- return;
+ log->Printf(" AOEAS::CT[%u] Before:", current_id);
+ ASTDumper dumper((clang::Decl *)interface_decl);
+ dumper.ToLog(log, " [CT] ");
}
- void
- CompleteType(clang::ObjCInterfaceDecl *interface_decl) override
- {
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
+ m_decl_vendor.FinishDecl(interface_decl);
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
-
- if (log)
- {
- log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
- current_id,
- static_cast<void*>(&interface_decl->getASTContext()),
- static_cast<void*>(interface_decl),
- interface_decl->getName().str().c_str());
-
- log->Printf(" AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl*)interface_decl);
- dumper.ToLog(log, " [CT] ");
- }
-
- m_decl_vendor.FinishDecl(interface_decl);
-
- if (log)
- {
- log->Printf(" [CT] After:");
- ASTDumper dumper((clang::Decl*)interface_decl);
- dumper.ToLog(log, " [CT] ");
- }
- return;
+ if (log) {
+ log->Printf(" [CT] After:");
+ ASTDumper dumper((clang::Decl *)interface_decl);
+ dumper.ToLog(log, " [CT] ");
}
+ return;
+ }
- bool
- layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override
- {
- return false;
- }
+ bool layoutRecordType(
+ const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+ &BaseOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
+ &VirtualBaseOffsets) override {
+ return false;
+ }
- void
- StartTranslationUnit(clang::ASTConsumer *Consumer) override
- {
- clang::TranslationUnitDecl *translation_unit_decl = m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
- translation_unit_decl->setHasExternalVisibleStorage();
- translation_unit_decl->setHasExternalLexicalStorage();
- }
+ void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
+ clang::TranslationUnitDecl *translation_unit_decl =
+ m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
+ translation_unit_decl->setHasExternalVisibleStorage();
+ translation_unit_decl->setHasExternalLexicalStorage();
+ }
+
private:
- AppleObjCDeclVendor &m_decl_vendor;
+ AppleObjCDeclVendor &m_decl_vendor;
};
-AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime) :
- DeclVendor(),
- m_runtime(runtime),
- m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()),
- m_type_realizer_sp(m_runtime.GetEncodingToType())
-{
- m_external_source = new AppleObjCExternalASTSource (*this);
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source);
- m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
+AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
+ : DeclVendor(), m_runtime(runtime), m_ast_ctx(runtime.GetProcess()
+ ->GetTarget()
+ .GetArchitecture()
+ .GetTriple()
+ .getTriple()
+ .c_str()),
+ m_type_realizer_sp(m_runtime.GetEncodingToType()) {
+ m_external_source = new AppleObjCExternalASTSource(*this);
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
+ m_external_source);
+ m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
}
-clang::ObjCInterfaceDecl*
-AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa)
-{
- ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
-
- if (iter != m_isa_to_interface.end())
- return iter->second;
-
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
-
- ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(isa);
-
- if (!descriptor)
- return NULL;
-
- const ConstString &name(descriptor->GetClassName());
-
- clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
+clang::ObjCInterfaceDecl *
+AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
+ ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
- clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx,
- ast_ctx->getTranslationUnitDecl(),
- clang::SourceLocation(),
- &identifier_info,
- nullptr,
- nullptr);
-
- ClangASTMetadata meta_data;
- meta_data.SetISAPtr(isa);
- m_external_source->SetMetadata(new_iface_decl, meta_data);
-
- new_iface_decl->setHasExternalVisibleStorage();
- new_iface_decl->setHasExternalLexicalStorage();
-
- ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
-
- m_isa_to_interface[isa] = new_iface_decl;
-
- return new_iface_decl;
+ if (iter != m_isa_to_interface.end())
+ return iter->second;
+
+ clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor =
+ m_runtime.GetClassDescriptorFromISA(isa);
+
+ if (!descriptor)
+ return NULL;
+
+ const ConstString &name(descriptor->GetClassName());
+
+ clang::IdentifierInfo &identifier_info =
+ ast_ctx->Idents.get(name.GetStringRef());
+
+ clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
+ *ast_ctx, ast_ctx->getTranslationUnitDecl(), clang::SourceLocation(),
+ &identifier_info, nullptr, nullptr);
+
+ ClangASTMetadata meta_data;
+ meta_data.SetISAPtr(isa);
+ m_external_source->SetMetadata(new_iface_decl, meta_data);
+
+ new_iface_decl->setHasExternalVisibleStorage();
+ new_iface_decl->setHasExternalLexicalStorage();
+
+ ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
+
+ m_isa_to_interface[isa] = new_iface_decl;
+
+ return new_iface_decl;
}
-class ObjCRuntimeMethodType
-{
+class ObjCRuntimeMethodType {
public:
- ObjCRuntimeMethodType (const char *types) : m_is_valid(false)
- {
- const char *cursor = types;
- enum ParserState {
- Start = 0,
- InType,
- InPos
- } state = Start;
- const char *type = NULL;
- int brace_depth = 0;
-
- uint32_t stepsLeft = 256;
-
- while (1)
- {
- if (--stepsLeft == 0)
- {
- m_is_valid = false;
- return;
- }
-
- switch (state)
- {
- case Start:
- {
- switch (*cursor)
- {
- default:
- state = InType;
- type = cursor;
- break;
- case '\0':
- m_is_valid = true;
- return;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- m_is_valid = false;
- return;
- }
- }
- break;
- case InType:
- {
- switch (*cursor)
- {
- default:
- ++cursor;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (!brace_depth)
- {
- state = InPos;
- if (type)
- {
- m_type_vector.push_back(std::string(type, (cursor - type)));
- }
- else
- {
- m_is_valid = false;
- return;
- }
- type = NULL;
- }
- else
- {
- ++cursor;
- }
- break;
- case '[': case '{': case '(':
- ++brace_depth;
- ++cursor;
- break;
- case ']': case '}': case ')':
- if (!brace_depth)
- {
- m_is_valid = false;
- return;
- }
- --brace_depth;
- ++cursor;
- break;
- case '\0':
- m_is_valid = false;
- return;
- }
- }
- break;
- case InPos:
- {
- switch (*cursor)
- {
- default:
- state = InType;
- type = cursor;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- ++cursor;
- break;
- case '\0':
- m_is_valid = true;
- return;
- }
- }
- break;
- }
+ ObjCRuntimeMethodType(const char *types) : m_is_valid(false) {
+ const char *cursor = types;
+ enum ParserState { Start = 0, InType, InPos } state = Start;
+ const char *type = NULL;
+ int brace_depth = 0;
+
+ uint32_t stepsLeft = 256;
+
+ while (1) {
+ if (--stepsLeft == 0) {
+ m_is_valid = false;
+ return;
+ }
+
+ switch (state) {
+ case Start: {
+ switch (*cursor) {
+ default:
+ state = InType;
+ type = cursor;
+ break;
+ case '\0':
+ m_is_valid = true;
+ return;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ m_is_valid = false;
+ return;
}
- }
-
- clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name, bool instance, ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp)
- {
- if (!m_is_valid || m_type_vector.size() < 3)
- return NULL;
-
- clang::ASTContext &ast_ctx(interface_decl->getASTContext());
-
- clang::QualType return_qual_type;
-
- const bool isInstance = instance;
- const bool isVariadic = false;
- const bool isSynthesized = false;
- const bool isImplicitlyDeclared = true;
- const bool isDefined = false;
- const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
- const bool HasRelatedResultType = false;
- const bool for_expression = true;
-
- std::vector <clang::IdentifierInfo *> selector_components;
-
- const char *name_cursor = name;
- bool is_zero_argument = true;
-
-
- while (*name_cursor != '\0')
- {
- const char *colon_loc = strchr(name_cursor, ':');
- if (!colon_loc)
- {
- selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
- break;
+ } break;
+ case InType: {
+ switch (*cursor) {
+ default:
+ ++cursor;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (!brace_depth) {
+ state = InPos;
+ if (type) {
+ m_type_vector.push_back(std::string(type, (cursor - type)));
+ } else {
+ m_is_valid = false;
+ return;
}
- else
- {
- is_zero_argument = false;
- selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor, colon_loc - name_cursor)));
- name_cursor = colon_loc + 1;
- }
- }
-
- clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data());
-
- clang::QualType ret_type = ClangUtil::GetQualType(
- type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression));
-
- if (ret_type.isNull())
- return NULL;
-
- clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(ast_ctx,
- clang::SourceLocation(),
- clang::SourceLocation(),
- sel,
- ret_type,
- NULL,
- interface_decl,
- isInstance,
- isVariadic,
- isSynthesized,
- isImplicitlyDeclared,
- isDefined,
- impControl,
- HasRelatedResultType);
-
- std::vector <clang::ParmVarDecl*> parm_vars;
-
- for (size_t ai = 3, ae = m_type_vector.size();
- ai != ae;
- ++ai)
- {
- const bool for_expression = true;
- clang::QualType arg_type = ClangUtil::GetQualType(
- type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression));
-
- if (arg_type.isNull())
- return NULL; // well, we just wasted a bunch of time. Wish we could delete the stuff we'd just made!
-
- parm_vars.push_back(clang::ParmVarDecl::Create(ast_ctx,
- ret,
- clang::SourceLocation(),
- clang::SourceLocation(),
- NULL,
- arg_type,
- NULL,
- clang::SC_None,
- NULL));
- }
-
- ret->setMethodParams(ast_ctx, llvm::ArrayRef<clang::ParmVarDecl*>(parm_vars), llvm::ArrayRef<clang::SourceLocation>());
-
- return ret;
- }
-
- explicit operator bool ()
- {
- return m_is_valid;
- }
-
- size_t
- GetNumTypes ()
- {
- return m_type_vector.size();
- }
-
- const char*
- GetTypeAtIndex (size_t idx)
- {
- return m_type_vector[idx].c_str();
- }
-
-private:
- typedef std::vector <std::string> TypeVector;
-
- TypeVector m_type_vector;
- bool m_is_valid;
-};
-
-bool
-AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
-
- ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
- ObjCLanguageRuntime::ObjCISA objc_isa = 0;
- if (metadata)
- objc_isa = metadata->GetISAPtr();
-
- if (!objc_isa)
- return false;
-
- if (!interface_decl->hasExternalVisibleStorage())
- return true;
-
- interface_decl->startDefinition();
-
- interface_decl->setHasExternalVisibleStorage(false);
- interface_decl->setHasExternalLexicalStorage(false);
-
- ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(objc_isa);
-
- if (!descriptor)
- return false;
-
- auto superclass_func = [interface_decl, this](ObjCLanguageRuntime::ObjCISA isa)
- {
- clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
-
- if (!superclass_decl)
+ type = NULL;
+ } else {
+ ++cursor;
+ }
+ break;
+ case '[':
+ case '{':
+ case '(':
+ ++brace_depth;
+ ++cursor;
+ break;
+ case ']':
+ case '}':
+ case ')':
+ if (!brace_depth) {
+ m_is_valid = false;
return;
-
- FinishDecl(superclass_decl);
- clang::ASTContext *context = m_ast_ctx.getASTContext();
- interface_decl->setSuperClass(
- context->getTrivialTypeSourceInfo(context->getObjCInterfaceType(superclass_decl)));
- };
-
- auto instance_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
- {
- if (!name || !types)
- return false; // skip this one
-
- ObjCRuntimeMethodType method_type(types);
-
- clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, true, m_type_realizer_sp);
-
- if (log)
- log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types);
-
- if (method_decl)
- interface_decl->addDecl(method_decl);
-
- return false;
- };
-
- auto class_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
- {
- if (!name || !types)
- return false; // skip this one
-
- ObjCRuntimeMethodType method_type(types);
-
- clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, false, m_type_realizer_sp);
-
- if (log)
- log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types);
-
- if (method_decl)
- interface_decl->addDecl(method_decl);
-
- return false;
- };
-
- auto ivar_func = [log, interface_decl, this](const char *name, const char *type, lldb::addr_t offset_ptr, uint64_t size) -> bool
- {
- if (!name || !type)
- return false;
-
- const bool for_expression = false;
-
- if (log)
- log->Printf("[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name, type, offset_ptr);
-
- CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(m_ast_ctx, type, for_expression);
-
- if (ivar_type.IsValid())
- {
- clang::TypeSourceInfo * const type_source_info = nullptr;
- const bool is_synthesized = false;
- clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
- *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(), clang::SourceLocation(),
- &m_ast_ctx.getASTContext()->Idents.get(name), ClangUtil::GetQualType(ivar_type),
- type_source_info, // TypeSourceInfo *
- clang::ObjCIvarDecl::Public, 0, is_synthesized);
-
- if (ivar_decl)
- {
- interface_decl->addDecl(ivar_decl);
- }
+ }
+ --brace_depth;
+ ++cursor;
+ break;
+ case '\0':
+ m_is_valid = false;
+ return;
}
-
- return false;
- };
-
- if (log)
- {
- ASTDumper method_dumper ((clang::Decl*)interface_decl);
-
- log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C interface for %s", descriptor->GetClassName().AsCString());
+ } break;
+ case InPos: {
+ switch (*cursor) {
+ default:
+ state = InType;
+ type = cursor;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ ++cursor;
+ break;
+ case '\0':
+ m_is_valid = true;
+ return;
+ }
+ } break;
+ }
}
-
-
- if (!descriptor->Describe(superclass_func,
- instance_method_func,
- class_method_func,
- ivar_func))
- return false;
-
- if (log)
- {
- ASTDumper method_dumper ((clang::Decl*)interface_decl);
-
- log->Printf("[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
-
- method_dumper.ToLog(log, " [AOTV::FD] ");
+ }
+
+ clang::ObjCMethodDecl *
+ BuildMethod(clang::ObjCInterfaceDecl *interface_decl, const char *name,
+ bool instance,
+ ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
+ if (!m_is_valid || m_type_vector.size() < 3)
+ return NULL;
+
+ clang::ASTContext &ast_ctx(interface_decl->getASTContext());
+
+ clang::QualType return_qual_type;
+
+ const bool isInstance = instance;
+ const bool isVariadic = false;
+ const bool isSynthesized = false;
+ const bool isImplicitlyDeclared = true;
+ const bool isDefined = false;
+ const clang::ObjCMethodDecl::ImplementationControl impControl =
+ clang::ObjCMethodDecl::None;
+ const bool HasRelatedResultType = false;
+ const bool for_expression = true;
+
+ std::vector<clang::IdentifierInfo *> selector_components;
+
+ const char *name_cursor = name;
+ bool is_zero_argument = true;
+
+ while (*name_cursor != '\0') {
+ const char *colon_loc = strchr(name_cursor, ':');
+ if (!colon_loc) {
+ selector_components.push_back(
+ &ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
+ break;
+ } else {
+ is_zero_argument = false;
+ selector_components.push_back(&ast_ctx.Idents.get(
+ llvm::StringRef(name_cursor, colon_loc - name_cursor)));
+ name_cursor = colon_loc + 1;
+ }
}
-
+
+ clang::Selector sel = ast_ctx.Selectors.getSelector(
+ is_zero_argument ? 0 : selector_components.size(),
+ selector_components.data());
+
+ clang::QualType ret_type =
+ ClangUtil::GetQualType(type_realizer_sp->RealizeType(
+ interface_decl->getASTContext(), m_type_vector[0].c_str(),
+ for_expression));
+
+ if (ret_type.isNull())
+ return NULL;
+
+ clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
+ ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
+ ret_type, NULL, interface_decl, isInstance, isVariadic, isSynthesized,
+ isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
+
+ std::vector<clang::ParmVarDecl *> parm_vars;
+
+ for (size_t ai = 3, ae = m_type_vector.size(); ai != ae; ++ai) {
+ const bool for_expression = true;
+ clang::QualType arg_type =
+ ClangUtil::GetQualType(type_realizer_sp->RealizeType(
+ ast_ctx, m_type_vector[ai].c_str(), for_expression));
+
+ if (arg_type.isNull())
+ return NULL; // well, we just wasted a bunch of time. Wish we could
+ // delete the stuff we'd just made!
+
+ parm_vars.push_back(clang::ParmVarDecl::Create(
+ ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), NULL,
+ arg_type, NULL, clang::SC_None, NULL));
+ }
+
+ ret->setMethodParams(ast_ctx,
+ llvm::ArrayRef<clang::ParmVarDecl *>(parm_vars),
+ llvm::ArrayRef<clang::SourceLocation>());
+
+ return ret;
+ }
+
+ explicit operator bool() { return m_is_valid; }
+
+ size_t GetNumTypes() { return m_type_vector.size(); }
+
+ const char *GetTypeAtIndex(size_t idx) { return m_type_vector[idx].c_str(); }
+
+private:
+ typedef std::vector<std::string> TypeVector;
+
+ TypeVector m_type_vector;
+ bool m_is_valid;
+};
+
+bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
+ Log *log(GetLogIfAllCategoriesSet(
+ LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
+ ObjCLanguageRuntime::ObjCISA objc_isa = 0;
+ if (metadata)
+ objc_isa = metadata->GetISAPtr();
+
+ if (!objc_isa)
+ return false;
+
+ if (!interface_decl->hasExternalVisibleStorage())
return true;
+
+ interface_decl->startDefinition();
+
+ interface_decl->setHasExternalVisibleStorage(false);
+ interface_decl->setHasExternalLexicalStorage(false);
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor =
+ m_runtime.GetClassDescriptorFromISA(objc_isa);
+
+ if (!descriptor)
+ return false;
+
+ auto superclass_func = [interface_decl,
+ this](ObjCLanguageRuntime::ObjCISA isa) {
+ clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
+
+ if (!superclass_decl)
+ return;
+
+ FinishDecl(superclass_decl);
+ clang::ASTContext *context = m_ast_ctx.getASTContext();
+ interface_decl->setSuperClass(context->getTrivialTypeSourceInfo(
+ context->getObjCInterfaceType(superclass_decl)));
+ };
+
+ auto instance_method_func =
+ [log, interface_decl, this](const char *name, const char *types) -> bool {
+ if (!name || !types)
+ return false; // skip this one
+
+ ObjCRuntimeMethodType method_type(types);
+
+ clang::ObjCMethodDecl *method_decl =
+ method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp);
+
+ if (log)
+ log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types);
+
+ if (method_decl)
+ interface_decl->addDecl(method_decl);
+
+ return false;
+ };
+
+ auto class_method_func = [log, interface_decl,
+ this](const char *name, const char *types) -> bool {
+ if (!name || !types)
+ return false; // skip this one
+
+ ObjCRuntimeMethodType method_type(types);
+
+ clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
+ interface_decl, name, false, m_type_realizer_sp);
+
+ if (log)
+ log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types);
+
+ if (method_decl)
+ interface_decl->addDecl(method_decl);
+
+ return false;
+ };
+
+ auto ivar_func = [log, interface_decl,
+ this](const char *name, const char *type,
+ lldb::addr_t offset_ptr, uint64_t size) -> bool {
+ if (!name || !type)
+ return false;
+
+ const bool for_expression = false;
+
+ if (log)
+ log->Printf(
+ "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name,
+ type, offset_ptr);
+
+ CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(
+ m_ast_ctx, type, for_expression);
+
+ if (ivar_type.IsValid()) {
+ clang::TypeSourceInfo *const type_source_info = nullptr;
+ const bool is_synthesized = false;
+ clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
+ *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
+ clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name),
+ ClangUtil::GetQualType(ivar_type),
+ type_source_info, // TypeSourceInfo *
+ clang::ObjCIvarDecl::Public, 0, is_synthesized);
+
+ if (ivar_decl) {
+ interface_decl->addDecl(ivar_decl);
+ }
+ }
+
+ return false;
+ };
+
+ if (log) {
+ ASTDumper method_dumper((clang::Decl *)interface_decl);
+
+ log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
+ "interface for %s",
+ descriptor->GetClassName().AsCString());
+ }
+
+ if (!descriptor->Describe(superclass_func, instance_method_func,
+ class_method_func, ivar_func))
+ return false;
+
+ if (log) {
+ ASTDumper method_dumper((clang::Decl *)interface_decl);
+
+ log->Printf(
+ "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
+
+ method_dumper.ToLog(log, " [AOTV::FD] ");
+ }
+
+ return true;
}
uint32_t
-AppleObjCDeclVendor::FindDecls (const ConstString &name,
- bool append,
- uint32_t max_matches,
- std::vector <clang::NamedDecl *> &decls)
-{
- static unsigned int invocation_id = 0;
- unsigned int current_id = invocation_id++;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
-
- if (log)
- log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
- current_id,
- (const char*)name.AsCString(),
- append ? "true" : "false",
- max_matches);
-
- if (!append)
- decls.clear();
-
- uint32_t ret = 0;
-
- do
- {
- // See if the type is already in our ASTContext.
-
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
-
- clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
- clang::DeclarationName decl_name = ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
-
- clang::DeclContext::lookup_result lookup_result = ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
-
- if (!lookup_result.empty())
- {
- if (clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0]))
- {
- if (log)
- {
- clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);
- ASTDumper dumper(result_iface_type);
-
- uint64_t isa_value = LLDB_INVALID_ADDRESS;
- ClangASTMetadata *metadata = m_external_source->GetMetadata(result_iface_decl);
- if (metadata)
- isa_value = metadata->GetISAPtr();
-
- log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 ") in the ASTContext",
- current_id,
- dumper.GetCString(),
- isa_value);
- }
-
- decls.push_back(result_iface_decl);
- ret++;
- break;
- }
- else
- {
- if (log)
- log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but it's not something we know about",
- current_id);
- break;
- }
+AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append,
+ uint32_t max_matches,
+ std::vector<clang::NamedDecl *> &decls) {
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(GetLogIfAllCategoriesSet(
+ LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
+
+ if (log)
+ log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
+ current_id, (const char *)name.AsCString(),
+ append ? "true" : "false", max_matches);
+
+ if (!append)
+ decls.clear();
+
+ uint32_t ret = 0;
+
+ do {
+ // See if the type is already in our ASTContext.
+
+ clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+
+ clang::IdentifierInfo &identifier_info =
+ ast_ctx->Idents.get(name.GetStringRef());
+ clang::DeclarationName decl_name =
+ ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
+
+ clang::DeclContext::lookup_result lookup_result =
+ ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
+
+ if (!lookup_result.empty()) {
+ if (clang::ObjCInterfaceDecl *result_iface_decl =
+ llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
+ if (log) {
+ clang::QualType result_iface_type =
+ ast_ctx->getObjCInterfaceType(result_iface_decl);
+ ASTDumper dumper(result_iface_type);
+
+ uint64_t isa_value = LLDB_INVALID_ADDRESS;
+ ClangASTMetadata *metadata =
+ m_external_source->GetMetadata(result_iface_decl);
+ if (metadata)
+ isa_value = metadata->GetISAPtr();
+
+ log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
+ ") in the ASTContext",
+ current_id, dumper.GetCString(), isa_value);
}
- else if(log)
- {
- log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
- current_id,
- name.AsCString());
- }
-
- // It's not. If it exists, we have to put it into our ASTContext.
-
- ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
-
- if (!isa)
- {
- if (log)
- log->Printf("AOCTV::FT [%u] Couldn't find the isa",
- current_id);
-
- break;
- }
-
- clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
-
- if (!iface_decl)
- {
- if (log)
- log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for isa 0x%" PRIx64,
- current_id,
- (uint64_t)isa);
-
- break;
- }
-
- if (log)
- {
- clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl);
- ASTDumper dumper(new_iface_type);
- log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
- current_id,
- dumper.GetCString(),
- (uint64_t)isa);
- }
-
- decls.push_back(iface_decl);
+
+ decls.push_back(result_iface_decl);
ret++;
break;
- } while (0);
-
- return ret;
+ } else {
+ if (log)
+ log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but "
+ "it's not something we know about",
+ current_id);
+ break;
+ }
+ } else if (log) {
+ log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
+ current_id, name.AsCString());
+ }
+
+ // It's not. If it exists, we have to put it into our ASTContext.
+
+ ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
+
+ if (!isa) {
+ if (log)
+ log->Printf("AOCTV::FT [%u] Couldn't find the isa", current_id);
+
+ break;
+ }
+
+ clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
+
+ if (!iface_decl) {
+ if (log)
+ log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for "
+ "isa 0x%" PRIx64,
+ current_id, (uint64_t)isa);
+
+ break;
+ }
+
+ if (log) {
+ clang::QualType new_iface_type =
+ ast_ctx->getObjCInterfaceType(iface_decl);
+ ASTDumper dumper(new_iface_type);
+ log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", current_id,
+ dumper.GetCString(), (uint64_t)isa);
+ }
+
+ decls.push_back(iface_decl);
+ ret++;
+ break;
+ } while (0);
+
+ return ret;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
index 88789c7..2682407 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
@@ -14,40 +14,38 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
class AppleObjCExternalASTSource;
-
-class AppleObjCDeclVendor : public DeclVendor
-{
+
+class AppleObjCDeclVendor : public DeclVendor {
public:
- AppleObjCDeclVendor(ObjCLanguageRuntime &runtime);
-
- uint32_t
- FindDecls(const ConstString &name,
- bool append,
- uint32_t max_matches,
- std::vector <clang::NamedDecl *> &decls) override;
-
- friend class AppleObjCExternalASTSource;
+ AppleObjCDeclVendor(ObjCLanguageRuntime &runtime);
+
+ uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches,
+ std::vector<clang::NamedDecl *> &decls) override;
+
+ friend class AppleObjCExternalASTSource;
private:
- clang::ObjCInterfaceDecl *GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa);
- bool FinishDecl(clang::ObjCInterfaceDecl *decl);
-
- ObjCLanguageRuntime &m_runtime;
- ClangASTContext m_ast_ctx;
- ObjCLanguageRuntime::EncodingToTypeSP m_type_realizer_sp;
- AppleObjCExternalASTSource *m_external_source;
-
- typedef llvm::DenseMap<ObjCLanguageRuntime::ObjCISA, clang::ObjCInterfaceDecl *> ISAToInterfaceMap;
+ clang::ObjCInterfaceDecl *GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa);
+ bool FinishDecl(clang::ObjCInterfaceDecl *decl);
- ISAToInterfaceMap m_isa_to_interface;
+ ObjCLanguageRuntime &m_runtime;
+ ClangASTContext m_ast_ctx;
+ ObjCLanguageRuntime::EncodingToTypeSP m_type_realizer_sp;
+ AppleObjCExternalASTSource *m_external_source;
+
+ typedef llvm::DenseMap<ObjCLanguageRuntime::ObjCISA,
+ clang::ObjCInterfaceDecl *>
+ ISAToInterfaceMap;
+
+ ISAToInterfaceMap m_isa_to_interface;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 84d5f81..24eddb5 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -1,4 +1,5 @@
-//===-- AppleObjCRuntime.cpp -------------------------------------*- C++ -*-===//
+//===-- AppleObjCRuntime.cpp -------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -39,516 +40,450 @@
using namespace lldb;
using namespace lldb_private;
-#define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000
+#define PO_FUNCTION_TIMEOUT_USEC 15 * 1000 * 1000
-AppleObjCRuntime::~AppleObjCRuntime()
-{
+AppleObjCRuntime::~AppleObjCRuntime() {}
+
+AppleObjCRuntime::AppleObjCRuntime(Process *process)
+ : ObjCLanguageRuntime(process), m_read_objc_library(false),
+ m_objc_trampoline_handler_ap(), m_Foundation_major() {
+ ReadObjCLibraryIfNeeded(process->GetTarget().GetImages());
}
-AppleObjCRuntime::AppleObjCRuntime(Process *process) :
- ObjCLanguageRuntime (process),
- m_read_objc_library (false),
- m_objc_trampoline_handler_ap (),
- m_Foundation_major()
-{
- ReadObjCLibraryIfNeeded (process->GetTarget().GetImages());
-}
-
-bool
-AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj)
-{
- CompilerType compiler_type(valobj.GetCompilerType());
- bool is_signed;
- // ObjC objects can only be pointers (or numbers that actually represents pointers
- // but haven't been typecast, because reasons..)
- if (!compiler_type.IsIntegerType (is_signed) && !compiler_type.IsPointerType ())
- return false;
-
- // Make the argument list: we pass one arg, the address of our pointer, to the print function.
- Value val;
-
- if (!valobj.ResolveValue(val.GetScalar()))
- return false;
-
- // Value Objects may not have a process in their ExecutionContextRef. But we need to have one
- // in the ref we pass down to eventually call description. Get it from the target if it isn't
- // present.
- ExecutionContext exe_ctx;
- if (valobj.GetProcessSP())
- {
- exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
- }
- else
- {
- exe_ctx.SetContext(valobj.GetTargetSP(), true);
- if (!exe_ctx.HasProcessScope())
- return false;
- }
- return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope());
-
-}
-bool
-AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope)
-{
- if (!m_read_objc_library)
- return false;
-
- ExecutionContext exe_ctx;
- exe_scope->CalculateExecutionContext(exe_ctx);
- Process *process = exe_ctx.GetProcessPtr();
- if (!process)
- return false;
-
- // We need other parts of the exe_ctx, but the processes have to match.
- assert (m_process == process);
-
- // Get the function address for the print function.
- const Address *function_address = GetPrintForDebuggerAddr();
- if (!function_address)
- return false;
-
- Target *target = exe_ctx.GetTargetPtr();
- CompilerType compiler_type = value.GetCompilerType();
- if (compiler_type)
- {
- if (!ClangASTContext::IsObjCObjectPointerType(compiler_type))
- {
- strm.Printf ("Value doesn't point to an ObjC object.\n");
- return false;
- }
- }
- else
- {
- // If it is not a pointer, see if we can make it into a pointer.
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
- CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
- if (!opaque_type)
- opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- //value.SetContext(Value::eContextTypeClangType, opaque_type_ptr);
- value.SetCompilerType (opaque_type);
- }
-
- ValueList arg_value_list;
- arg_value_list.PushValue(value);
-
- // This is the return value:
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
-
- CompilerType return_compiler_type = ast_context->GetCStringType(true);
- Value ret;
-// ret.SetContext(Value::eContextTypeClangType, return_compiler_type);
- ret.SetCompilerType (return_compiler_type);
-
- if (exe_ctx.GetFramePtr() == NULL)
- {
- Thread *thread = exe_ctx.GetThreadPtr();
- if (thread == NULL)
- {
- exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread());
- thread = exe_ctx.GetThreadPtr();
- }
- if (thread)
- {
- exe_ctx.SetFrameSP(thread->GetSelectedFrame());
- }
- }
-
- // Now we're ready to call the function:
-
- DiagnosticManager diagnostics;
- lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
-
- if (!m_print_object_caller_up)
- {
- Error error;
- m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC,
- return_compiler_type,
- *function_address,
- arg_value_list,
- "objc-object-description",
- error));
- if (error.Fail())
- {
- m_print_object_caller_up.reset();
- strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString());
- return false;
- }
- m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics);
- }
- else
- {
- m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics);
- }
-
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(true);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
-
- ExpressionResults results =
- m_print_object_caller_up->ExecuteFunction(exe_ctx, &wrapper_struct_addr, options, diagnostics, ret);
- if (results != eExpressionCompleted)
- {
- strm.Printf("Error evaluating Print Object function: %d.\n", results);
- return false;
- }
-
- addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
-
- char buf[512];
- size_t cstr_len = 0;
- size_t full_buffer_len = sizeof (buf) - 1;
- size_t curr_len = full_buffer_len;
- while (curr_len == full_buffer_len)
- {
- Error error;
- curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf), error);
- strm.Write (buf, curr_len);
- cstr_len += curr_len;
- }
- return cstr_len > 0;
-}
-
-lldb::ModuleSP
-AppleObjCRuntime::GetObjCModule ()
-{
- ModuleSP module_sp (m_objc_module_wp.lock());
- if (module_sp)
- return module_sp;
-
- Process *process = GetProcess();
- if (process)
- {
- const ModuleList& modules = process->GetTarget().GetImages();
- for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
- {
- module_sp = modules.GetModuleAtIndex(idx);
- if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp))
- {
- m_objc_module_wp = module_sp;
- return module_sp;
- }
- }
- }
- return ModuleSP();
-}
-
-Address *
-AppleObjCRuntime::GetPrintForDebuggerAddr()
-{
- if (!m_PrintForDebugger_addr.get())
- {
- const ModuleList &modules = m_process->GetTarget().GetImages();
-
- SymbolContextList contexts;
- SymbolContext context;
-
- if ((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) &&
- (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts)))
- return NULL;
-
- contexts.GetContextAtIndex(0, context);
-
- m_PrintForDebugger_addr.reset(new Address(context.symbol->GetAddress()));
- }
-
- return m_PrintForDebugger_addr.get();
-}
-
-bool
-AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value)
-{
- return in_value.GetCompilerType().IsPossibleDynamicType (NULL,
- false, // do not check C++
- true); // check ObjC
-}
-
-bool
-AppleObjCRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type)
-{
+bool AppleObjCRuntime::GetObjectDescription(Stream &str, ValueObject &valobj) {
+ CompilerType compiler_type(valobj.GetCompilerType());
+ bool is_signed;
+ // ObjC objects can only be pointers (or numbers that actually represents
+ // pointers
+ // but haven't been typecast, because reasons..)
+ if (!compiler_type.IsIntegerType(is_signed) && !compiler_type.IsPointerType())
return false;
+
+ // Make the argument list: we pass one arg, the address of our pointer, to the
+ // print function.
+ Value val;
+
+ if (!valobj.ResolveValue(val.GetScalar()))
+ return false;
+
+ // Value Objects may not have a process in their ExecutionContextRef. But we
+ // need to have one
+ // in the ref we pass down to eventually call description. Get it from the
+ // target if it isn't
+ // present.
+ ExecutionContext exe_ctx;
+ if (valobj.GetProcessSP()) {
+ exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
+ } else {
+ exe_ctx.SetContext(valobj.GetTargetSP(), true);
+ if (!exe_ctx.HasProcessScope())
+ return false;
+ }
+ return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope());
+}
+bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
+ ExecutionContextScope *exe_scope) {
+ if (!m_read_objc_library)
+ return false;
+
+ ExecutionContext exe_ctx;
+ exe_scope->CalculateExecutionContext(exe_ctx);
+ Process *process = exe_ctx.GetProcessPtr();
+ if (!process)
+ return false;
+
+ // We need other parts of the exe_ctx, but the processes have to match.
+ assert(m_process == process);
+
+ // Get the function address for the print function.
+ const Address *function_address = GetPrintForDebuggerAddr();
+ if (!function_address)
+ return false;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ CompilerType compiler_type = value.GetCompilerType();
+ if (compiler_type) {
+ if (!ClangASTContext::IsObjCObjectPointerType(compiler_type)) {
+ strm.Printf("Value doesn't point to an ObjC object.\n");
+ return false;
+ }
+ } else {
+ // If it is not a pointer, see if we can make it into a pointer.
+ ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
+ if (!opaque_type)
+ opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ // value.SetContext(Value::eContextTypeClangType, opaque_type_ptr);
+ value.SetCompilerType(opaque_type);
+ }
+
+ ValueList arg_value_list;
+ arg_value_list.PushValue(value);
+
+ // This is the return value:
+ ClangASTContext *ast_context = target->GetScratchClangASTContext();
+
+ CompilerType return_compiler_type = ast_context->GetCStringType(true);
+ Value ret;
+ // ret.SetContext(Value::eContextTypeClangType, return_compiler_type);
+ ret.SetCompilerType(return_compiler_type);
+
+ if (exe_ctx.GetFramePtr() == NULL) {
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (thread == NULL) {
+ exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread());
+ thread = exe_ctx.GetThreadPtr();
+ }
+ if (thread) {
+ exe_ctx.SetFrameSP(thread->GetSelectedFrame());
+ }
+ }
+
+ // Now we're ready to call the function:
+
+ DiagnosticManager diagnostics;
+ lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
+
+ if (!m_print_object_caller_up) {
+ Error error;
+ m_print_object_caller_up.reset(
+ exe_scope->CalculateTarget()->GetFunctionCallerForLanguage(
+ eLanguageTypeObjC, return_compiler_type, *function_address,
+ arg_value_list, "objc-object-description", error));
+ if (error.Fail()) {
+ m_print_object_caller_up.reset();
+ strm.Printf("Could not get function runner to call print for debugger "
+ "function: %s.",
+ error.AsCString());
+ return false;
+ }
+ m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr,
+ diagnostics);
+ } else {
+ m_print_object_caller_up->WriteFunctionArguments(
+ exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics);
+ }
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
+
+ ExpressionResults results = m_print_object_caller_up->ExecuteFunction(
+ exe_ctx, &wrapper_struct_addr, options, diagnostics, ret);
+ if (results != eExpressionCompleted) {
+ strm.Printf("Error evaluating Print Object function: %d.\n", results);
+ return false;
+ }
+
+ addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+
+ char buf[512];
+ size_t cstr_len = 0;
+ size_t full_buffer_len = sizeof(buf) - 1;
+ size_t curr_len = full_buffer_len;
+ while (curr_len == full_buffer_len) {
+ Error error;
+ curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf,
+ sizeof(buf), error);
+ strm.Write(buf, curr_len);
+ cstr_len += curr_len;
+ }
+ return cstr_len > 0;
+}
+
+lldb::ModuleSP AppleObjCRuntime::GetObjCModule() {
+ ModuleSP module_sp(m_objc_module_wp.lock());
+ if (module_sp)
+ return module_sp;
+
+ Process *process = GetProcess();
+ if (process) {
+ const ModuleList &modules = process->GetTarget().GetImages();
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++) {
+ module_sp = modules.GetModuleAtIndex(idx);
+ if (AppleObjCRuntime::AppleIsModuleObjCLibrary(module_sp)) {
+ m_objc_module_wp = module_sp;
+ return module_sp;
+ }
+ }
+ }
+ return ModuleSP();
+}
+
+Address *AppleObjCRuntime::GetPrintForDebuggerAddr() {
+ if (!m_PrintForDebugger_addr.get()) {
+ const ModuleList &modules = m_process->GetTarget().GetImages();
+
+ SymbolContextList contexts;
+ SymbolContext context;
+
+ if ((!modules.FindSymbolsWithNameAndType(ConstString("_NSPrintForDebugger"),
+ eSymbolTypeCode, contexts)) &&
+ (!modules.FindSymbolsWithNameAndType(ConstString("_CFPrintForDebugger"),
+ eSymbolTypeCode, contexts)))
+ return NULL;
+
+ contexts.GetContextAtIndex(0, context);
+
+ m_PrintForDebugger_addr.reset(new Address(context.symbol->GetAddress()));
+ }
+
+ return m_PrintForDebugger_addr.get();
+}
+
+bool AppleObjCRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ return in_value.GetCompilerType().IsPossibleDynamicType(
+ NULL,
+ false, // do not check C++
+ true); // check ObjC
+}
+
+bool AppleObjCRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ return false;
}
TypeAndOrName
-AppleObjCRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
- ValueObject& static_value)
-{
- CompilerType static_type(static_value.GetCompilerType());
- Flags static_type_flags(static_type.GetTypeInfo());
-
- TypeAndOrName ret(type_and_or_name);
- if (type_and_or_name.HasType())
- {
- // The type will always be the type of the dynamic object. If our parent's type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
- // should be okay...
- CompilerType orig_type = type_and_or_name.GetCompilerType();
- CompilerType corrected_type = orig_type;
- if (static_type_flags.AllSet(eTypeIsPointer))
- corrected_type = orig_type.GetPointerType ();
- ret.SetCompilerType(corrected_type);
- }
- else
- {
- // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
- std::string corrected_name (type_and_or_name.GetName().GetCString());
- if (static_type_flags.AllSet(eTypeIsPointer))
- corrected_name.append(" *");
- // the parent type should be a correctly pointer'ed or referenc'ed type
- ret.SetCompilerType(static_type);
- ret.SetName(corrected_name.c_str());
- }
- return ret;
+AppleObjCRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) {
+ CompilerType static_type(static_value.GetCompilerType());
+ Flags static_type_flags(static_type.GetTypeInfo());
+
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType()) {
+ // The type will always be the type of the dynamic object. If our parent's
+ // type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If
+ // a reference, then the original type
+ // should be okay...
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ CompilerType corrected_type = orig_type;
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_type = orig_type.GetPointerType();
+ ret.SetCompilerType(corrected_type);
+ } else {
+ // If we are here we need to adjust our dynamic type name to include the
+ // correct & or * symbol
+ std::string corrected_name(type_and_or_name.GetName().GetCString());
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_name.append(" *");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetCompilerType(static_type);
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
}
-bool
-AppleObjCRuntime::AppleIsModuleObjCLibrary (const ModuleSP &module_sp)
-{
- if (module_sp)
- {
- const FileSpec &module_file_spec = module_sp->GetFileSpec();
- static ConstString ObjCName ("libobjc.A.dylib");
-
- if (module_file_spec)
- {
- if (module_file_spec.GetFilename() == ObjCName)
- return true;
- }
+bool AppleObjCRuntime::AppleIsModuleObjCLibrary(const ModuleSP &module_sp) {
+ if (module_sp) {
+ const FileSpec &module_file_spec = module_sp->GetFileSpec();
+ static ConstString ObjCName("libobjc.A.dylib");
+
+ if (module_file_spec) {
+ if (module_file_spec.GetFilename() == ObjCName)
+ return true;
}
+ }
+ return false;
+}
+
+// we use the version of Foundation to make assumptions about the ObjC runtime
+// on a target
+uint32_t AppleObjCRuntime::GetFoundationVersion() {
+ if (!m_Foundation_major.hasValue()) {
+ const ModuleList &modules = m_process->GetTarget().GetImages();
+ uint32_t major = UINT32_MAX;
+ for (uint32_t idx = 0; idx < modules.GetSize(); idx++) {
+ lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
+ if (!module_sp)
+ continue;
+ if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),
+ "Foundation") == 0) {
+ module_sp->GetVersion(&major, 1);
+ m_Foundation_major = major;
+ return major;
+ }
+ }
+ return LLDB_INVALID_MODULE_VERSION;
+ } else
+ return m_Foundation_major.getValue();
+}
+
+void AppleObjCRuntime::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
+ lldb::addr_t &cf_false) {
+ cf_true = cf_false = LLDB_INVALID_ADDRESS;
+}
+
+bool AppleObjCRuntime::IsModuleObjCLibrary(const ModuleSP &module_sp) {
+ return AppleIsModuleObjCLibrary(module_sp);
+}
+
+bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) {
+ // Maybe check here and if we have a handler already, and the UUID of this
+ // module is the same as the one in the
+ // current module, then we don't have to reread it?
+ m_objc_trampoline_handler_ap.reset(
+ new AppleObjCTrampolineHandler(m_process->shared_from_this(), module_sp));
+ if (m_objc_trampoline_handler_ap.get() != NULL) {
+ m_read_objc_library = true;
+ return true;
+ } else
return false;
}
-// we use the version of Foundation to make assumptions about the ObjC runtime on a target
-uint32_t
-AppleObjCRuntime::GetFoundationVersion ()
-{
- if (!m_Foundation_major.hasValue())
- {
- const ModuleList& modules = m_process->GetTarget().GetImages();
- uint32_t major = UINT32_MAX;
- for (uint32_t idx = 0; idx < modules.GetSize(); idx++)
- {
- lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
- if (!module_sp)
- continue;
- if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),"Foundation") == 0)
- {
- module_sp->GetVersion(&major,1);
- m_Foundation_major = major;
- return major;
- }
- }
- return LLDB_INVALID_MODULE_VERSION;
- }
- else
- return m_Foundation_major.getValue();
-}
-
-void
-AppleObjCRuntime::GetValuesForGlobalCFBooleans(lldb::addr_t& cf_true,
- lldb::addr_t& cf_false)
-{
- cf_true = cf_false = LLDB_INVALID_ADDRESS;
-}
-
-bool
-AppleObjCRuntime::IsModuleObjCLibrary (const ModuleSP &module_sp)
-{
- return AppleIsModuleObjCLibrary(module_sp);
-}
-
-bool
-AppleObjCRuntime::ReadObjCLibrary (const ModuleSP &module_sp)
-{
- // Maybe check here and if we have a handler already, and the UUID of this module is the same as the one in the
- // current module, then we don't have to reread it?
- m_objc_trampoline_handler_ap.reset(new AppleObjCTrampolineHandler (m_process->shared_from_this(), module_sp));
- if (m_objc_trampoline_handler_ap.get() != NULL)
- {
- m_read_objc_library = true;
- return true;
- }
- else
- return false;
-}
-
-ThreadPlanSP
-AppleObjCRuntime::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
-{
- ThreadPlanSP thread_plan_sp;
- if (m_objc_trampoline_handler_ap.get())
- thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan (thread, stop_others);
- return thread_plan_sp;
+ThreadPlanSP AppleObjCRuntime::GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others) {
+ ThreadPlanSP thread_plan_sp;
+ if (m_objc_trampoline_handler_ap.get())
+ thread_plan_sp = m_objc_trampoline_handler_ap->GetStepThroughDispatchPlan(
+ thread, stop_others);
+ return thread_plan_sp;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
ObjCLanguageRuntime::ObjCRuntimeVersions
-AppleObjCRuntime::GetObjCVersion (Process *process, ModuleSP &objc_module_sp)
-{
- if (!process)
- return ObjCRuntimeVersions::eObjC_VersionUnknown;
-
- Target &target = process->GetTarget();
- if (target.GetArchitecture().GetTriple().getVendor() != llvm::Triple::VendorType::Apple)
- return ObjCRuntimeVersions::eObjC_VersionUnknown;
-
- const ModuleList &target_modules = target.GetImages();
- std::lock_guard<std::recursive_mutex> gaurd(target_modules.GetMutex());
-
- size_t num_images = target_modules.GetSize();
- for (size_t i = 0; i < num_images; i++)
- {
- ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
- // One tricky bit here is that we might get called as part of the initial module loading, but
- // before all the pre-run libraries get winnowed from the module list. So there might actually
- // be an old and incorrect ObjC library sitting around in the list, and we don't want to look at that.
- // That's why we call IsLoadedInTarget.
-
- if (AppleIsModuleObjCLibrary (module_sp) && module_sp->IsLoadedInTarget(&target))
- {
- objc_module_sp = module_sp;
- ObjectFile *ofile = module_sp->GetObjectFile();
- if (!ofile)
- return ObjCRuntimeVersions::eObjC_VersionUnknown;
-
- SectionList *sections = module_sp->GetSectionList();
- if (!sections)
- return ObjCRuntimeVersions::eObjC_VersionUnknown;
- SectionSP v1_telltale_section_sp = sections->FindSectionByName(ConstString ("__OBJC"));
- if (v1_telltale_section_sp)
- {
- return ObjCRuntimeVersions::eAppleObjC_V1;
- }
- return ObjCRuntimeVersions::eAppleObjC_V2;
- }
- }
-
+AppleObjCRuntime::GetObjCVersion(Process *process, ModuleSP &objc_module_sp) {
+ if (!process)
return ObjCRuntimeVersions::eObjC_VersionUnknown;
-}
-void
-AppleObjCRuntime::SetExceptionBreakpoints ()
-{
- const bool catch_bp = false;
- const bool throw_bp = true;
- const bool is_internal = true;
-
- if (!m_objc_exception_bp_sp)
- {
- m_objc_exception_bp_sp = LanguageRuntime::CreateExceptionBreakpoint (m_process->GetTarget(),
- GetLanguageType(),
- catch_bp,
- throw_bp,
- is_internal);
- if (m_objc_exception_bp_sp)
- m_objc_exception_bp_sp->SetBreakpointKind("ObjC exception");
+ Target &target = process->GetTarget();
+ if (target.GetArchitecture().GetTriple().getVendor() !=
+ llvm::Triple::VendorType::Apple)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+
+ const ModuleList &target_modules = target.GetImages();
+ std::lock_guard<std::recursive_mutex> gaurd(target_modules.GetMutex());
+
+ size_t num_images = target_modules.GetSize();
+ for (size_t i = 0; i < num_images; i++) {
+ ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
+ // One tricky bit here is that we might get called as part of the initial
+ // module loading, but
+ // before all the pre-run libraries get winnowed from the module list. So
+ // there might actually
+ // be an old and incorrect ObjC library sitting around in the list, and we
+ // don't want to look at that.
+ // That's why we call IsLoadedInTarget.
+
+ if (AppleIsModuleObjCLibrary(module_sp) &&
+ module_sp->IsLoadedInTarget(&target)) {
+ objc_module_sp = module_sp;
+ ObjectFile *ofile = module_sp->GetObjectFile();
+ if (!ofile)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+
+ SectionList *sections = module_sp->GetSectionList();
+ if (!sections)
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
+ SectionSP v1_telltale_section_sp =
+ sections->FindSectionByName(ConstString("__OBJC"));
+ if (v1_telltale_section_sp) {
+ return ObjCRuntimeVersions::eAppleObjC_V1;
+ }
+ return ObjCRuntimeVersions::eAppleObjC_V2;
}
- else
- m_objc_exception_bp_sp->SetEnabled(true);
+ }
+
+ return ObjCRuntimeVersions::eObjC_VersionUnknown;
}
+void AppleObjCRuntime::SetExceptionBreakpoints() {
+ const bool catch_bp = false;
+ const bool throw_bp = true;
+ const bool is_internal = true;
-void
-AppleObjCRuntime::ClearExceptionBreakpoints ()
-{
- if (!m_process)
- return;
-
- if (m_objc_exception_bp_sp.get())
- {
- m_objc_exception_bp_sp->SetEnabled (false);
+ if (!m_objc_exception_bp_sp) {
+ m_objc_exception_bp_sp = LanguageRuntime::CreateExceptionBreakpoint(
+ m_process->GetTarget(), GetLanguageType(), catch_bp, throw_bp,
+ is_internal);
+ if (m_objc_exception_bp_sp)
+ m_objc_exception_bp_sp->SetBreakpointKind("ObjC exception");
+ } else
+ m_objc_exception_bp_sp->SetEnabled(true);
+}
+
+void AppleObjCRuntime::ClearExceptionBreakpoints() {
+ if (!m_process)
+ return;
+
+ if (m_objc_exception_bp_sp.get()) {
+ m_objc_exception_bp_sp->SetEnabled(false);
+ }
+}
+
+bool AppleObjCRuntime::ExceptionBreakpointsAreSet() {
+ return m_objc_exception_bp_sp && m_objc_exception_bp_sp->IsEnabled();
+}
+
+bool AppleObjCRuntime::ExceptionBreakpointsExplainStop(
+ lldb::StopInfoSP stop_reason) {
+ if (!m_process)
+ return false;
+
+ if (!stop_reason || stop_reason->GetStopReason() != eStopReasonBreakpoint)
+ return false;
+
+ uint64_t break_site_id = stop_reason->GetValue();
+ return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(
+ break_site_id, m_objc_exception_bp_sp->GetID());
+}
+
+bool AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() {
+ if (!m_process)
+ return false;
+
+ Target &target(m_process->GetTarget());
+
+ static ConstString s_method_signature(
+ "-[NSDictionary objectForKeyedSubscript:]");
+ static ConstString s_arclite_method_signature(
+ "__arclite_objectForKeyedSubscript");
+
+ SymbolContextList sc_list;
+
+ if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature,
+ eSymbolTypeCode, sc_list) ||
+ target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature,
+ eSymbolTypeCode, sc_list))
+ return true;
+ else
+ return false;
+}
+
+lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() {
+ Target &target = m_process->GetTarget();
+
+ if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
+ FileSpecList filter_modules;
+ filter_modules.Append(FileSpec("libobjc.A.dylib", false));
+ return target.GetSearchFilterForModuleList(&filter_modules);
+ } else {
+ return LanguageRuntime::CreateExceptionSearchFilter();
+ }
+}
+
+void AppleObjCRuntime::ReadObjCLibraryIfNeeded(const ModuleList &module_list) {
+ if (!HasReadObjCLibrary()) {
+ std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
+
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++) {
+ auto mod = module_list.GetModuleAtIndex(i);
+ if (IsModuleObjCLibrary(mod)) {
+ ReadObjCLibrary(mod);
+ break;
+ }
}
+ }
}
-bool
-AppleObjCRuntime::ExceptionBreakpointsAreSet ()
-{
- return m_objc_exception_bp_sp && m_objc_exception_bp_sp->IsEnabled();
+void AppleObjCRuntime::ModulesDidLoad(const ModuleList &module_list) {
+ ReadObjCLibraryIfNeeded(module_list);
}
-
-bool
-AppleObjCRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
-{
- if (!m_process)
- return false;
-
- if (!stop_reason ||
- stop_reason->GetStopReason() != eStopReasonBreakpoint)
- return false;
-
- uint64_t break_site_id = stop_reason->GetValue();
- return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint (break_site_id,
- m_objc_exception_bp_sp->GetID());
-}
-
-bool
-AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing()
-{
- if (!m_process)
- return false;
-
- Target &target(m_process->GetTarget());
-
- static ConstString s_method_signature("-[NSDictionary objectForKeyedSubscript:]");
- static ConstString s_arclite_method_signature("__arclite_objectForKeyedSubscript");
-
- SymbolContextList sc_list;
-
- if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature, eSymbolTypeCode, sc_list) ||
- target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature, eSymbolTypeCode, sc_list))
- return true;
- else
- return false;
-}
-
-lldb::SearchFilterSP
-AppleObjCRuntime::CreateExceptionSearchFilter ()
-{
- Target &target = m_process->GetTarget();
-
- if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
- {
- FileSpecList filter_modules;
- filter_modules.Append(FileSpec("libobjc.A.dylib", false));
- return target.GetSearchFilterForModuleList(&filter_modules);
- }
- else
- {
- return LanguageRuntime::CreateExceptionSearchFilter();
- }
-}
-
-void
-AppleObjCRuntime::ReadObjCLibraryIfNeeded (const ModuleList &module_list)
-{
- if (!HasReadObjCLibrary ())
- {
- std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
-
- size_t num_modules = module_list.GetSize();
- for (size_t i = 0; i < num_modules; i++)
- {
- auto mod = module_list.GetModuleAtIndex (i);
- if (IsModuleObjCLibrary (mod))
- {
- ReadObjCLibrary (mod);
- break;
- }
- }
- }
-}
-
-void
-AppleObjCRuntime::ModulesDidLoad (const ModuleList &module_list)
-{
- ReadObjCLibraryIfNeeded (module_list);
-}
-
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
index b66700f..57d98fb 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -16,137 +16,112 @@
#include "llvm/ADT/Optional.h"
// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Target/LanguageRuntime.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "AppleObjCTrampolineHandler.h"
#include "AppleThreadPlanStepThroughObjCTrampoline.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-
-class AppleObjCRuntime :
- public lldb_private::ObjCLanguageRuntime
-{
+
+class AppleObjCRuntime : public lldb_private::ObjCLanguageRuntime {
public:
- ~AppleObjCRuntime() override;
+ ~AppleObjCRuntime() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- // Note there is no CreateInstance, Initialize & Terminate functions here, because
- // you can't make an instance of this generic runtime.
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ // Note there is no CreateInstance, Initialize & Terminate functions here,
+ // because
+ // you can't make an instance of this generic runtime.
- static bool classof(const ObjCLanguageRuntime* runtime)
- {
- switch (runtime->GetRuntimeVersion())
- {
- case ObjCRuntimeVersions::eAppleObjC_V1:
- case ObjCRuntimeVersions::eAppleObjC_V2:
- return true;
- default:
- return false;
- }
+ static bool classof(const ObjCLanguageRuntime *runtime) {
+ switch (runtime->GetRuntimeVersion()) {
+ case ObjCRuntimeVersions::eAppleObjC_V1:
+ case ObjCRuntimeVersions::eAppleObjC_V2:
+ return true;
+ default:
+ return false;
}
-
- // These are generic runtime functions:
- bool
- GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) override;
-
- bool
- GetObjectDescription (Stream &str, ValueObject &object) override;
-
- bool
- CouldHaveDynamicValue (ValueObject &in_value) override;
-
- bool
- GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
+ }
- TypeAndOrName
- FixUpDynamicType (const TypeAndOrName& type_and_or_name,
- ValueObject& static_value) override;
-
- // These are the ObjC specific functions.
-
- bool
- IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) override;
-
- bool
- ReadObjCLibrary (const lldb::ModuleSP &module_sp) override;
+ // These are generic runtime functions:
+ bool GetObjectDescription(Stream &str, Value &value,
+ ExecutionContextScope *exe_scope) override;
- bool
- HasReadObjCLibrary () override
- {
- return m_read_objc_library;
- }
-
- lldb::ThreadPlanSP
- GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) override;
-
- // Get the "libobjc.A.dylib" module from the current target if we can find
- // it, also cache it once it is found to ensure quick lookups.
- lldb::ModuleSP
- GetObjCModule ();
-
- // Sync up with the target
+ bool GetObjectDescription(Stream &str, ValueObject &object) override;
- void
- ModulesDidLoad (const ModuleList &module_list) override;
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- void
- SetExceptionBreakpoints() override;
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- void
- ClearExceptionBreakpoints() override;
-
- bool
- ExceptionBreakpointsAreSet() override;
-
- bool
- ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
-
- lldb::SearchFilterSP
- CreateExceptionSearchFilter() override;
-
- uint32_t
- GetFoundationVersion();
-
- virtual void
- GetValuesForGlobalCFBooleans(lldb::addr_t& cf_true,
- lldb::addr_t& cf_false);
-
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
+
+ // These are the ObjC specific functions.
+
+ bool IsModuleObjCLibrary(const lldb::ModuleSP &module_sp) override;
+
+ bool ReadObjCLibrary(const lldb::ModuleSP &module_sp) override;
+
+ bool HasReadObjCLibrary() override { return m_read_objc_library; }
+
+ lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others) override;
+
+ // Get the "libobjc.A.dylib" module from the current target if we can find
+ // it, also cache it once it is found to ensure quick lookups.
+ lldb::ModuleSP GetObjCModule();
+
+ // Sync up with the target
+
+ void ModulesDidLoad(const ModuleList &module_list) override;
+
+ void SetExceptionBreakpoints() override;
+
+ void ClearExceptionBreakpoints() override;
+
+ bool ExceptionBreakpointsAreSet() override;
+
+ bool ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
+
+ lldb::SearchFilterSP CreateExceptionSearchFilter() override;
+
+ uint32_t GetFoundationVersion();
+
+ virtual void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
+ lldb::addr_t &cf_false);
+
protected:
- // Call CreateInstance instead.
- AppleObjCRuntime(Process *process);
+ // Call CreateInstance instead.
+ AppleObjCRuntime(Process *process);
- bool
- CalculateHasNewLiteralsAndIndexing() override;
-
- static bool
- AppleIsModuleObjCLibrary(const lldb::ModuleSP &module_sp);
+ bool CalculateHasNewLiteralsAndIndexing() override;
- static ObjCRuntimeVersions
- GetObjCVersion(Process *process, lldb::ModuleSP &objc_module_sp);
+ static bool AppleIsModuleObjCLibrary(const lldb::ModuleSP &module_sp);
- void
- ReadObjCLibraryIfNeeded(const ModuleList &module_list);
+ static ObjCRuntimeVersions GetObjCVersion(Process *process,
+ lldb::ModuleSP &objc_module_sp);
- Address *
- GetPrintForDebuggerAddr();
-
- std::unique_ptr<Address> m_PrintForDebugger_addr;
- bool m_read_objc_library;
- std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
- lldb::BreakpointSP m_objc_exception_bp_sp;
- lldb::ModuleWP m_objc_module_wp;
- std::unique_ptr<FunctionCaller> m_print_object_caller_up;
-
- llvm::Optional<uint32_t> m_Foundation_major;
+ void ReadObjCLibraryIfNeeded(const ModuleList &module_list);
+
+ Address *GetPrintForDebuggerAddr();
+
+ std::unique_ptr<Address> m_PrintForDebugger_addr;
+ bool m_read_objc_library;
+ std::unique_ptr<lldb_private::AppleObjCTrampolineHandler>
+ m_objc_trampoline_handler_ap;
+ lldb::BreakpointSP m_objc_exception_bp_sp;
+ lldb::ModuleWP m_objc_module_wp;
+ std::unique_ptr<FunctionCaller> m_print_object_caller_up;
+
+ llvm::Optional<uint32_t> m_Foundation_major;
};
-
+
} // namespace lldb_private
#endif // liblldb_AppleObjCRuntime_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 805fca7..83df1fc 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -1,4 +1,5 @@
-//===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++ -*-===//
+//===-- AppleObjCRuntimeV1.cpp --------------------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -8,8 +9,8 @@
//===----------------------------------------------------------------------===//
#include "AppleObjCRuntimeV1.h"
-#include "AppleObjCTrampolineHandler.h"
#include "AppleObjCDeclVendor.h"
+#include "AppleObjCTrampolineHandler.h"
#include "clang/AST/Type.h"
@@ -36,425 +37,403 @@
using namespace lldb;
using namespace lldb_private;
-AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process) :
- AppleObjCRuntime (process),
- m_hash_signature (),
- m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS)
-{
-}
+AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process)
+ : AppleObjCRuntime(process), m_hash_signature(),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {}
-// for V1 runtime we just try to return a class name as that is the minimum level of support
+// for V1 runtime we just try to return a class name as that is the minimum
+// level of support
// required for the data formatters to work
-bool
-AppleObjCRuntimeV1::GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type)
-{
- class_type_or_name.Clear();
- value_type = Value::ValueType::eValueTypeScalar;
- if (CouldHaveDynamicValue(in_value))
- {
- auto class_descriptor(GetClassDescriptor(in_value));
- if (class_descriptor && class_descriptor->IsValid() && class_descriptor->GetClassName())
- {
- const addr_t object_ptr = in_value.GetPointerValue();
- address.SetRawAddress(object_ptr);
- class_type_or_name.SetName(class_descriptor->GetClassName());
- }
+bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
+ if (CouldHaveDynamicValue(in_value)) {
+ auto class_descriptor(GetClassDescriptor(in_value));
+ if (class_descriptor && class_descriptor->IsValid() &&
+ class_descriptor->GetClassName()) {
+ const addr_t object_ptr = in_value.GetPointerValue();
+ address.SetRawAddress(object_ptr);
+ class_type_or_name.SetName(class_descriptor->GetClassName());
}
- return class_type_or_name.IsEmpty() == false;
+ }
+ return class_type_or_name.IsEmpty() == false;
}
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
lldb_private::LanguageRuntime *
-AppleObjCRuntimeV1::CreateInstance (Process *process, lldb::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_V1)
- return new AppleObjCRuntimeV1 (process);
- else
- return NULL;
- }
+AppleObjCRuntimeV1::CreateInstance(Process *process,
+ lldb::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_V1)
+ return new AppleObjCRuntimeV1(process);
else
- return NULL;
+ return NULL;
+ } else
+ return NULL;
}
-
-void
-AppleObjCRuntimeV1::Initialize()
-{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- "Apple Objective C Language Runtime - Version 1",
- CreateInstance);
+void AppleObjCRuntimeV1::Initialize() {
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 1",
+ CreateInstance);
}
-void
-AppleObjCRuntimeV1::Terminate()
-{
- PluginManager::UnregisterPlugin (CreateInstance);
+void AppleObjCRuntimeV1::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-AppleObjCRuntimeV1::GetPluginNameStatic()
-{
- static ConstString g_name("apple-objc-v1");
- return g_name;
+lldb_private::ConstString AppleObjCRuntimeV1::GetPluginNameStatic() {
+ static ConstString g_name("apple-objc-v1");
+ return g_name;
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-ConstString
-AppleObjCRuntimeV1::GetPluginName()
-{
- return GetPluginNameStatic();
+ConstString AppleObjCRuntimeV1::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-AppleObjCRuntimeV1::GetPluginVersion()
-{
- return 1;
-}
+uint32_t AppleObjCRuntimeV1::GetPluginVersion() { return 1; }
BreakpointResolverSP
-AppleObjCRuntimeV1::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: don't do catch yet.
- return resolver_sp;
+AppleObjCRuntimeV1::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: don't do catch yet.
+ return resolver_sp;
}
struct BufStruct {
- char contents[2048];
+ char contents[2048];
};
-UtilityFunction *
-AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
-{
- std::unique_ptr<BufStruct> buf(new BufStruct);
-
- assert(snprintf(&buf->contents[0], sizeof(buf->contents),
- "struct __objc_class \n"
- "{ \n"
- " struct __objc_class *isa; \n"
- " struct __objc_class *super_class; \n"
- " const char *name; \n"
- " // rest of struct elided because unused \n"
- "}; \n"
- " \n"
- "struct __objc_object \n"
- "{ \n"
- " struct __objc_class *isa; \n"
- "}; \n"
- " \n"
- "extern \"C\" void \n"
- "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n"
- "{ \n"
- " struct __objc_object *obj = (struct __objc_object*)$__lldb_arg_obj; \n"
- " (int)strlen(obj->isa->name); \n"
- "} \n",
- name) < (int)sizeof(buf->contents));
+UtilityFunction *AppleObjCRuntimeV1::CreateObjectChecker(const char *name) {
+ std::unique_ptr<BufStruct> buf(new BufStruct);
- Error error;
- return GetTargetRef().GetUtilityFunctionForLanguage(buf->contents, eLanguageTypeObjC, name, error);
+ assert(snprintf(&buf->contents[0], sizeof(buf->contents),
+ "struct __objc_class "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_class *isa; "
+ " \n"
+ " struct __objc_class *super_class; "
+ " \n"
+ " const char *name; "
+ " \n"
+ " // rest of struct elided because unused "
+ " \n"
+ "}; "
+ " \n"
+ " "
+ " \n"
+ "struct __objc_object "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_class *isa; "
+ " \n"
+ "}; "
+ " \n"
+ " "
+ " \n"
+ "extern \"C\" void "
+ " \n"
+ "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) "
+ " \n"
+ "{ "
+ " \n"
+ " struct __objc_object *obj = (struct "
+ "__objc_object*)$__lldb_arg_obj; \n"
+ " (int)strlen(obj->isa->name); "
+ " \n"
+ "} "
+ " \n",
+ name) < (int)sizeof(buf->contents));
+
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(
+ buf->contents, eLanguageTypeObjC, name, error);
}
-AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
-{
- Initialize (isa_pointer.GetValueAsUnsigned(0),
- isa_pointer.GetProcessSP());
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
+ ValueObject &isa_pointer) {
+ Initialize(isa_pointer.GetValueAsUnsigned(0), isa_pointer.GetProcessSP());
}
-AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp)
-{
- Initialize (isa, process_sp);
+AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1(
+ ObjCISA isa, lldb::ProcessSP process_sp) {
+ Initialize(isa, process_sp);
}
-void
-AppleObjCRuntimeV1::ClassDescriptorV1::Initialize (ObjCISA isa, lldb::ProcessSP process_sp)
-{
- if (!isa || !process_sp)
- {
- m_valid = false;
- return;
- }
-
- m_valid = true;
-
- Error error;
-
- m_isa = process_sp->ReadPointerFromMemory(isa, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- uint32_t ptr_size = process_sp->GetAddressByteSize();
-
- if (!IsPointerValid(m_isa,ptr_size))
- {
- m_valid = false;
- return;
- }
+void AppleObjCRuntimeV1::ClassDescriptorV1::Initialize(
+ ObjCISA isa, lldb::ProcessSP process_sp) {
+ if (!isa || !process_sp) {
+ m_valid = false;
+ return;
+ }
- m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size,error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- if (!IsPointerValid(m_parent_isa,ptr_size,true))
- {
- m_valid = false;
- return;
- }
-
- lldb::addr_t name_ptr = process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size,error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
-
- size_t count = process_sp->ReadCStringFromMemory(name_ptr, (char*)buffer_sp->GetBytes(), 1024, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- if (count)
- m_name = ConstString((char*)buffer_sp->GetBytes());
- else
- m_name = ConstString();
-
- m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(m_isa + 5 * ptr_size, ptr_size, 0, error);
-
- if (error.Fail())
- {
- m_valid = false;
- return;
- }
-
- m_process_wp = lldb::ProcessWP(process_sp);
+ m_valid = true;
+
+ Error error;
+
+ m_isa = process_sp->ReadPointerFromMemory(isa, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ if (!IsPointerValid(m_isa, ptr_size)) {
+ m_valid = false;
+ return;
+ }
+
+ m_parent_isa = process_sp->ReadPointerFromMemory(m_isa + ptr_size, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ if (!IsPointerValid(m_parent_isa, ptr_size, true)) {
+ m_valid = false;
+ return;
+ }
+
+ lldb::addr_t name_ptr =
+ process_sp->ReadPointerFromMemory(m_isa + 2 * ptr_size, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+
+ size_t count = process_sp->ReadCStringFromMemory(
+ name_ptr, (char *)buffer_sp->GetBytes(), 1024, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ if (count)
+ m_name = ConstString((char *)buffer_sp->GetBytes());
+ else
+ m_name = ConstString();
+
+ m_instance_size = process_sp->ReadUnsignedIntegerFromMemory(
+ m_isa + 5 * ptr_size, ptr_size, 0, error);
+
+ if (error.Fail()) {
+ m_valid = false;
+ return;
+ }
+
+ m_process_wp = lldb::ProcessWP(process_sp);
}
AppleObjCRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass ()
-{
- if (!m_valid)
- return AppleObjCRuntime::ClassDescriptorSP();
- ProcessSP process_sp = m_process_wp.lock();
- if (!process_sp)
- return AppleObjCRuntime::ClassDescriptorSP();
- return ObjCLanguageRuntime::ClassDescriptorSP(new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa,process_sp));
+AppleObjCRuntimeV1::ClassDescriptorV1::GetSuperclass() {
+ if (!m_valid)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ ProcessSP process_sp = m_process_wp.lock();
+ if (!process_sp)
+ return AppleObjCRuntime::ClassDescriptorSP();
+ return ObjCLanguageRuntime::ClassDescriptorSP(
+ new AppleObjCRuntimeV1::ClassDescriptorV1(m_parent_isa, process_sp));
}
AppleObjCRuntime::ClassDescriptorSP
-AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass () const
-{
- return ClassDescriptorSP();
+AppleObjCRuntimeV1::ClassDescriptorV1::GetMetaclass() const {
+ return ClassDescriptorSP();
}
-bool
-AppleObjCRuntimeV1::ClassDescriptorV1::Describe (std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
- std::function <bool (const char *, const char *)> const &instance_method_func,
- std::function <bool (const char *, const char *)> const &class_method_func,
- std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const
-{
- return false;
+bool AppleObjCRuntimeV1::ClassDescriptorV1::Describe(
+ std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
+ std::function<bool(const char *, const char *)> const &instance_method_func,
+ std::function<bool(const char *, const char *)> const &class_method_func,
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)> const &ivar_func) const {
+ return false;
}
-lldb::addr_t
-AppleObjCRuntimeV1::GetISAHashTablePointer ()
-{
- if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
- {
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (!objc_module_sp)
- return LLDB_INVALID_ADDRESS;
-
- static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
-
- const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_objc_debug_class_hash, lldb::eSymbolTypeData);
- if (symbol && symbol->ValueIsAddress())
- {
- Process *process = GetProcess();
- if (process)
- {
+lldb::addr_t AppleObjCRuntimeV1::GetISAHashTablePointer() {
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
+ ModuleSP objc_module_sp(GetObjCModule());
- lldb::addr_t objc_debug_class_hash_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
-
- if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS)
- {
- Error error;
- lldb::addr_t objc_debug_class_hash_ptr = process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
- if (objc_debug_class_hash_ptr != 0 &&
- objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS)
- {
- m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
- }
- }
- }
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_objc_debug_class_hash("_objc_debug_class_hash");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_objc_debug_class_hash, lldb::eSymbolTypeData);
+ if (symbol && symbol->ValueIsAddress()) {
+ Process *process = GetProcess();
+ if (process) {
+
+ lldb::addr_t objc_debug_class_hash_addr =
+ symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
+
+ if (objc_debug_class_hash_addr != LLDB_INVALID_ADDRESS) {
+ Error error;
+ lldb::addr_t objc_debug_class_hash_ptr =
+ process->ReadPointerFromMemory(objc_debug_class_hash_addr, error);
+ if (objc_debug_class_hash_ptr != 0 &&
+ objc_debug_class_hash_ptr != LLDB_INVALID_ADDRESS) {
+ m_isa_hash_table_ptr = objc_debug_class_hash_ptr;
+ }
}
+ }
}
- return m_isa_hash_table_ptr;
+ }
+ return m_isa_hash_table_ptr;
}
-void
-AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
-{
- // TODO: implement HashTableSignature...
- Process *process = GetProcess();
-
- if (process)
- {
- // 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();
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- ProcessSP process_sp = process->shared_from_this();
-
- ModuleSP objc_module_sp(GetObjCModule());
-
- if (!objc_module_sp)
- return;
-
- uint32_t isa_count = 0;
-
- lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
- if (hash_table_ptr != LLDB_INVALID_ADDRESS)
- {
- // Read the NXHashTable struct:
- //
- // typedef struct {
- // const NXHashTablePrototype *prototype;
- // unsigned count;
- // unsigned nbBuckets;
- // void *buckets;
- // const void *info;
- // } NXHashTable;
+void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
+ // TODO: implement HashTableSignature...
+ Process *process = GetProcess();
- Error error;
- DataBufferHeap buffer(1024, 0);
- if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
- {
- const uint32_t addr_size = m_process->GetAddressByteSize();
- const ByteOrder byte_order = m_process->GetByteOrder();
- DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
- lldb::offset_t offset = addr_size; // Skip prototype
- const uint32_t count = data.GetU32(&offset);
- const uint32_t num_buckets = data.GetU32(&offset);
- const addr_t buckets_ptr = data.GetPointer(&offset);
- if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
- {
- m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);
+ if (process) {
+ // 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();
- const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
- buffer.SetByteSize(data_size);
-
- if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
- {
- data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
- offset = 0;
- for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
- {
- const uint32_t bucket_isa_count = data.GetU32 (&offset);
- const lldb::addr_t bucket_data = data.GetU32 (&offset);
-
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (bucket_isa_count == 0)
- continue;
-
- isa_count += bucket_isa_count;
+ ProcessSP process_sp = process->shared_from_this();
- ObjCISA isa;
- if (bucket_isa_count == 1)
- {
- // When we only have one entry in the bucket, the bucket data is the "isa"
- isa = bucket_data;
- if (isa)
- {
- if (!ISAIsCached(isa))
- {
- ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
-
- AddClass (isa, descriptor_sp);
- }
- }
- }
- else
- {
- // When we have more than one entry in the bucket, the bucket data is a pointer
- // to an array of "isa" values
- addr_t isa_addr = bucket_data;
- for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
- {
- isa = m_process->ReadPointerFromMemory(isa_addr, error);
+ ModuleSP objc_module_sp(GetObjCModule());
- if (isa && isa != LLDB_INVALID_ADDRESS)
- {
- if (!ISAIsCached(isa))
- {
- ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
-
- if (log && log->GetVerbose())
- log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
-
- AddClass (isa, descriptor_sp);
- }
- }
- }
- }
- }
- }
+ if (!objc_module_sp)
+ return;
+
+ uint32_t isa_count = 0;
+
+ lldb::addr_t hash_table_ptr = GetISAHashTablePointer();
+ if (hash_table_ptr != LLDB_INVALID_ADDRESS) {
+ // Read the NXHashTable struct:
+ //
+ // typedef struct {
+ // const NXHashTablePrototype *prototype;
+ // unsigned count;
+ // unsigned nbBuckets;
+ // void *buckets;
+ // const void *info;
+ // } NXHashTable;
+
+ Error error;
+ DataBufferHeap buffer(1024, 0);
+ if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) ==
+ 20) {
+ const uint32_t addr_size = m_process->GetAddressByteSize();
+ const ByteOrder byte_order = m_process->GetByteOrder();
+ DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), byte_order,
+ addr_size);
+ lldb::offset_t offset = addr_size; // Skip prototype
+ const uint32_t count = data.GetU32(&offset);
+ const uint32_t num_buckets = data.GetU32(&offset);
+ const addr_t buckets_ptr = data.GetPointer(&offset);
+ if (m_hash_signature.NeedsUpdate(count, num_buckets, buckets_ptr)) {
+ m_hash_signature.UpdateSignature(count, num_buckets, buckets_ptr);
+
+ const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
+ buffer.SetByteSize(data_size);
+
+ if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size,
+ error) == data_size) {
+ data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
+ offset = 0;
+ for (uint32_t bucket_idx = 0; bucket_idx < num_buckets;
+ ++bucket_idx) {
+ const uint32_t bucket_isa_count = data.GetU32(&offset);
+ const lldb::addr_t bucket_data = data.GetU32(&offset);
+
+ if (bucket_isa_count == 0)
+ continue;
+
+ isa_count += bucket_isa_count;
+
+ ObjCISA isa;
+ if (bucket_isa_count == 1) {
+ // When we only have one entry in the bucket, the bucket data is
+ // the "isa"
+ isa = bucket_data;
+ if (isa) {
+ if (!ISAIsCached(isa)) {
+ ClassDescriptorSP descriptor_sp(
+ new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
+ " from _objc_debug_class_hash to "
+ "isa->descriptor cache",
+ isa);
+
+ AddClass(isa, descriptor_sp);
+ }
}
+ } else {
+ // When we have more than one entry in the bucket, the bucket
+ // data is a pointer
+ // to an array of "isa" values
+ addr_t isa_addr = bucket_data;
+ for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count;
+ ++isa_idx, isa_addr += addr_size) {
+ isa = m_process->ReadPointerFromMemory(isa_addr, error);
+
+ if (isa && isa != LLDB_INVALID_ADDRESS) {
+ if (!ISAIsCached(isa)) {
+ ClassDescriptorSP descriptor_sp(
+ new ClassDescriptorV1(isa, process_sp));
+
+ if (log && log->GetVerbose())
+ log->Printf(
+ "AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64
+ " from _objc_debug_class_hash to isa->descriptor "
+ "cache",
+ isa);
+
+ AddClass(isa, descriptor_sp);
+ }
+ }
+ }
+ }
}
- }
+ }
+ }
+ }
}
- else
- {
- m_isa_to_descriptor_stop_id = UINT32_MAX;
- }
+ } else {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
}
-DeclVendor *
-AppleObjCRuntimeV1::GetDeclVendor()
-{
- if (!m_decl_vendor_ap.get())
- m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
-
- return m_decl_vendor_ap.get();
+DeclVendor *AppleObjCRuntimeV1::GetDeclVendor() {
+ if (!m_decl_vendor_ap.get())
+ m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this));
+
+ return m_decl_vendor_ap.get();
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 9f9fcc6..3dddf1b 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -14,194 +14,148 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "AppleObjCRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_private {
-
-class AppleObjCRuntimeV1 :
- public AppleObjCRuntime
-{
+
+class AppleObjCRuntimeV1 : public AppleObjCRuntime {
public:
- ~AppleObjCRuntimeV1() override = default;
+ ~AppleObjCRuntimeV1() override = default;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString
- GetPluginNameStatic();
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- static bool classof(const ObjCLanguageRuntime* runtime)
- {
- switch (runtime->GetRuntimeVersion())
- {
- case ObjCRuntimeVersions::eAppleObjC_V1:
- return true;
- default:
- return false;
- }
+ static void Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static bool classof(const ObjCLanguageRuntime *runtime) {
+ switch (runtime->GetRuntimeVersion()) {
+ case ObjCRuntimeVersions::eAppleObjC_V1:
+ return true;
+ default:
+ return false;
}
-
- class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor
- {
- public:
- ClassDescriptorV1 (ValueObject &isa_pointer);
- ClassDescriptorV1 (ObjCISA isa, lldb::ProcessSP process_sp);
-
- ~ClassDescriptorV1() override = default;
+ }
- ConstString
- GetClassName() override
- {
- return m_name;
- }
-
- ClassDescriptorSP
- GetSuperclass() override;
-
- ClassDescriptorSP
- GetMetaclass() const override;
-
- bool
- IsValid() override
- {
- return m_valid;
- }
-
- // v1 does not support tagged pointers
- bool
- GetTaggedPointerInfo(uint64_t* info_bits = nullptr,
- uint64_t* value_bits = nullptr,
- uint64_t* payload = nullptr) override
- {
- return false;
- }
-
- uint64_t
- GetInstanceSize() override
- {
- return m_instance_size;
- }
-
- ObjCISA
- GetISA() override
- {
- return m_isa;
- }
-
- bool
- Describe(std::function <void (ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
- std::function <bool (const char *, const char *)> const &instance_method_func,
- std::function <bool (const char *, const char *)> const &class_method_func,
- std::function <bool (const char *, const char *,
- lldb::addr_t, uint64_t)> const &ivar_func) const override;
+ class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor {
+ public:
+ ClassDescriptorV1(ValueObject &isa_pointer);
+ ClassDescriptorV1(ObjCISA isa, lldb::ProcessSP process_sp);
- protected:
- void
- Initialize (ObjCISA isa, lldb::ProcessSP process_sp);
-
- private:
- ConstString m_name;
- ObjCISA m_isa;
- ObjCISA m_parent_isa;
- bool m_valid;
- lldb::ProcessWP m_process_wp;
- uint64_t m_instance_size;
- };
+ ~ClassDescriptorV1() override = default;
- // These are generic runtime functions:
+ ConstString GetClassName() override { return m_name; }
+
+ ClassDescriptorSP GetSuperclass() override;
+
+ ClassDescriptorSP GetMetaclass() const override;
+
+ bool IsValid() override { return m_valid; }
+
+ // v1 does not support tagged pointers
+ bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
+ uint64_t *value_bits = nullptr,
+ uint64_t *payload = nullptr) override {
+ return false;
+ }
+
+ uint64_t GetInstanceSize() override { return m_instance_size; }
+
+ ObjCISA GetISA() override { return m_isa; }
+
bool
- GetDynamicTypeAndAddress(ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
+ Describe(std::function<void(ObjCLanguageRuntime::ObjCISA)> const
+ &superclass_func,
+ std::function<bool(const char *, const char *)> const
+ &instance_method_func,
+ std::function<bool(const char *, const char *)> const
+ &class_method_func,
+ std::function<bool(const char *, const char *, lldb::addr_t,
+ uint64_t)> const &ivar_func) const override;
- UtilityFunction *
- CreateObjectChecker(const char *) override;
+ protected:
+ void Initialize(ObjCISA isa, lldb::ProcessSP process_sp);
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- ObjCRuntimeVersions
- GetRuntimeVersion() const override
- {
- return ObjCRuntimeVersions::eAppleObjC_V1;
- }
-
- void
- UpdateISAToDescriptorMapIfNeeded() override;
-
- DeclVendor *
- GetDeclVendor() override;
+ private:
+ ConstString m_name;
+ ObjCISA m_isa;
+ ObjCISA m_parent_isa;
+ bool m_valid;
+ lldb::ProcessWP m_process_wp;
+ uint64_t m_instance_size;
+ };
+
+ // These are generic runtime functions:
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
+
+ UtilityFunction *CreateObjectChecker(const char *) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ ObjCRuntimeVersions GetRuntimeVersion() const override {
+ return ObjCRuntimeVersions::eAppleObjC_V1;
+ }
+
+ void UpdateISAToDescriptorMapIfNeeded() override;
+
+ DeclVendor *GetDeclVendor() override;
protected:
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
-
- class HashTableSignature
- {
- public:
- HashTableSignature () :
- m_count (0),
- m_num_buckets (0),
- m_buckets_ptr (LLDB_INVALID_ADDRESS)
- {
- }
-
- bool
- NeedsUpdate (uint32_t count,
- uint32_t num_buckets,
- lldb::addr_t buckets_ptr)
- {
- return m_count != count ||
- m_num_buckets != num_buckets ||
- m_buckets_ptr != buckets_ptr ;
- }
-
- void
- UpdateSignature (uint32_t count,
- uint32_t num_buckets,
- lldb::addr_t buckets_ptr)
- {
- m_count = count;
- m_num_buckets = num_buckets;
- m_buckets_ptr = buckets_ptr;
- }
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override;
- protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
- };
-
- lldb::addr_t
- GetISAHashTablePointer ();
-
- HashTableSignature m_hash_signature;
- lldb::addr_t m_isa_hash_table_ptr;
- std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ class HashTableSignature {
+ public:
+ HashTableSignature()
+ : m_count(0), m_num_buckets(0), m_buckets_ptr(LLDB_INVALID_ADDRESS) {}
+
+ bool NeedsUpdate(uint32_t count, uint32_t num_buckets,
+ lldb::addr_t buckets_ptr) {
+ return m_count != count || m_num_buckets != num_buckets ||
+ m_buckets_ptr != buckets_ptr;
+ }
+
+ void UpdateSignature(uint32_t count, uint32_t num_buckets,
+ lldb::addr_t buckets_ptr) {
+ m_count = count;
+ m_num_buckets = num_buckets;
+ m_buckets_ptr = buckets_ptr;
+ }
+
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
+
+ lldb::addr_t GetISAHashTablePointer();
+
+ HashTableSignature m_hash_signature;
+ lldb::addr_t m_isa_hash_table_ptr;
+ std::unique_ptr<DeclVendor> m_decl_vendor_ap;
private:
- AppleObjCRuntimeV1(Process *process);
+ AppleObjCRuntimeV1(Process *process);
};
-
+
} // namespace lldb_private
#endif // liblldb_AppleObjCRuntimeV1_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 6888532..afa443f 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/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
+#define UTILITY_FUNCTION_TIMEOUT_USEC 2 * 1000 * 1000
-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 @@
)";
-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,2287 +337,2110 @@
)";
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;
+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;
}
- 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;
- }
+ } 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),
- 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);
+ 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);
+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;
+ // 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:
- // 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);
+ Process *process = in_value.GetProcessSP().get();
+ if (process)
+ assert(process == m_process);
+ else
+ assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
- 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]));
- }
- }
- }
+ 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
-{
+class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
public:
- class CommandOptions : public Options
- {
- public:
- CommandOptions() :
- Options(),
- m_verbose(false,false)
- {}
-
- ~CommandOptions() override = default;
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_verbose(false, false) {}
- Error
- SetOptionValue(uint32_t option_idx, const char *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;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- m_verbose.Clear();
- }
-
- const OptionDefinition*
- GetDefinitions() override
- {
- return g_option_table;
- }
+ ~CommandOptions() override = default;
- OptionValueBoolean m_verbose;
- static OptionDefinition g_option_table[];
- };
+ Error SetOptionValue(uint32_t option_idx, const char *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;
- 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);
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
}
- ~CommandObjectObjC_ClassTable_Dump() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
+ void OptionParsingStarting(ExecutionContext *execution_context) 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", "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);
- }
- }
- 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 {
+ 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;
}
-
- CommandOptions m_options;
+ 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);
+ }
+ }
+ 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 }
-};
+ 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
-{
+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;
+ 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);
+ }
}
-
- 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;
- }
+ } 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(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() 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(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() 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(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() 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));
+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;
- 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);
- }
-
- //----------------------------------------------------------------------
- // 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);
+ 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)
- {
- }
-
- 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;
- }
- }
-
- if (!success)
- {
- m_count = 0;
- m_num_buckets_minus_one = 0;
- m_buckets_ptr = LLDB_INVALID_ADDRESS;
- }
- return success;
- }
-
- // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState.
- typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
+ 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) {}
- 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);
+ 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;
+ }
+ }
+
+ if (!success) {
+ m_count = 0;
+ m_num_buckets_minus_one = 0;
+ m_buckets_ptr = LLDB_INVALID_ADDRESS;
+ }
+ 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(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;
+
+ 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;
}
- 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;
+ if (key != invalid_key)
+ return;
+ }
+ }
+ RemoteNXMapTable &m_parent;
+ int m_index;
+ };
- 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;
- }
+ 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
+ }
-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;
+ // 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 objc_class_sp;
-}
+ 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();
-lldb::addr_t
-AppleObjCRuntimeV2::GetISAHashTablePointer ()
-{
- if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS)
- {
- Process *process = GetProcess();
+ // tagged pointer
+ if (IsTaggedPointer(isa_pointer)) {
+ return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer);
+ } else {
+ ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
- ModuleSP objc_module_sp(GetObjCModule());
-
- 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;
-}
-
-AppleObjCRuntimeV2::DescriptorMapUpdateResult
-AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table)
-{
- Process *process = GetProcess();
-
- if (process == NULL)
- return DescriptorMapUpdateResult::Fail();
-
- uint32_t num_class_infos = 0;
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
-
- 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();
-
- 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 DescriptorMapUpdateResult::Success(0);
- }
-
- // 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())
- {
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process) {
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())
- {
+ 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 ("Failed to get Utility Function for implementation lookup: %s", error.AsCString());
- m_get_class_info_code.reset();
+ log->Printf("0x%" PRIx64
+ ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
+ "not in class descriptor cache 0x%" PRIx64,
+ isa_pointer, isa);
+ }
}
- 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();
- }
- }
- 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.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
- 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 DescriptorMapUpdateResult(success, num_class_infos);
+ }
+ return objc_class_sp;
}
-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;
- }
- // 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(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
-
- 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();
-
- Error err;
-
- uint32_t num_class_infos = 0;
-
- 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.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
- 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);
-#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);
-
- 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);
- }
- }
-
- // 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(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
-
+lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
+ if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
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());
- }
+
+ 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 num_map_table_isas > 0;
+ }
+ return m_isa_hash_table_ptr;
}
-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());
- }
- }
- }
+AppleObjCRuntimeV2::DescriptorMapUpdateResult
+AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
+ RemoteNXMapTable &hash_table) {
+ Process *process = GetProcess();
+
+ if (process == NULL)
+ return DescriptorMapUpdateResult::Fail();
+
+ uint32_t num_class_infos = 0;
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ 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();
+
+ 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 DescriptorMapUpdateResult::Success(0);
+ }
+
+ // 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();
+ }
+ }
+ 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.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
+ 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 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(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;
+ }
+ // 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(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ 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();
+
+ Error err;
+
+ uint32_t num_class_infos = 0;
+
+ 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.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
+ 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);
+#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);
+
+ 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);
+ }
+ }
+
+ // 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(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+
+ 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;
+}
+
+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()
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- 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();
+ Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
- 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);
+ // Else we need to check with our process to see when the map was updated.
+ Process *process = GetProcess();
- // Grab the dynamically loaded objc classes from the hash table in memory
- DescriptorMapUpdateResult dynamic_update_result = UpdateISAToDescriptorMapDynamic(hash_table);
+ if (process) {
+ RemoteNXMapTable 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)
- {
- // 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;
- }
+ // 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) {
+ // 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;
- }
+ } else {
+ m_isa_to_descriptor_stop_id = UINT32_MAX;
+ }
}
-static bool
-DoesProcessHaveSharedCache (Process& process)
-{
- PlatformSP platform_sp = process.GetTarget().GetPlatform();
- if (!platform_sp)
- return true; // this should not happen
-
- 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;
- }
-
- return true;
+static bool DoesProcessHaveSharedCache(Process &process) {
+ PlatformSP platform_sp = process.GetTarget().GetPlatform();
+ if (!platform_sp)
+ return true; // this should not happen
+
+ 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;
+ }
+
+ return true;
}
-void
-AppleObjCRuntimeV2::WarnIfNoClassesCached (SharedCacheWarningReason reason)
-{
- if (m_noclasses_warning_emitted)
- return;
+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;
- }
+ 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;
- default:
- break;
- }
+ 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;
+ default:
+ 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;
- };
+ const char *name_cstr = name.AsCString();
- 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);
- }
+ 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());
-
+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;
+
+ 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);
+ 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())
+ 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);
+}
+
+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();
+ }
+ } 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();
+ }
+ }
+ 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;
+}
+
+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;
-
- auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_isa_magic_mask"),
- objc_module_sp,
- error);
- if (error.Fail())
- return NULL;
+ 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;
+ }
- auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process,
- ConstString("objc_debug_isa_magic_value"),
- objc_module_sp,
- error);
- if (error.Fail())
- return NULL;
+ data_payload =
+ (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >>
+ m_objc_debug_taggedpointer_payload_rshift);
- 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);
+ return ClassDescriptorSP(
+ new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload));
}
-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);
+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) {}
- 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())
- 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);
-}
-
-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();
- }
- }
- 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();
- }
- }
- 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;
-}
-
-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::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,
- 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;
-}
-
-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::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::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::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, 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;
+}
+
+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;
}
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();
-}
+bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
+ if (m_CFBoolean_values)
+ return true;
-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;
+ 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());
}
- else
- this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
+
+ 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);
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 09bb13d..7180730 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -18,374 +18,314 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
#include "AppleObjCRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
class RemoteNXMapTable;
namespace lldb_private {
-class AppleObjCRuntimeV2 :
- public AppleObjCRuntime
-{
+class AppleObjCRuntimeV2 : public AppleObjCRuntime {
public:
- ~AppleObjCRuntimeV2() override = default;
+ ~AppleObjCRuntimeV2() override = default;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
-
- static void
- Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance (Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString
- GetPluginNameStatic();
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- static bool classof(const ObjCLanguageRuntime* runtime)
- {
- switch (runtime->GetRuntimeVersion())
- {
- case ObjCRuntimeVersions::eAppleObjC_V2:
- return true;
- default:
- return false;
- }
+ static void Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static bool classof(const ObjCLanguageRuntime *runtime) {
+ switch (runtime->GetRuntimeVersion()) {
+ case ObjCRuntimeVersions::eAppleObjC_V2:
+ return true;
+ default:
+ return false;
}
+ }
- // These are generic runtime functions:
- bool
- GetDynamicTypeAndAddress(ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
-
- UtilityFunction *
- CreateObjectChecker(const char *) override;
+ // These are generic runtime functions:
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- ObjCRuntimeVersions
- GetRuntimeVersion() const override
- {
- return ObjCRuntimeVersions::eAppleObjC_V2;
- }
+ UtilityFunction *CreateObjectChecker(const char *) override;
- size_t
- GetByteOffsetForIvar(CompilerType &parent_qual_type, const char *ivar_name) override;
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
- void
- UpdateISAToDescriptorMapIfNeeded() override;
-
- ConstString
- GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
-
- ClassDescriptorSP
- GetClassDescriptor(ValueObject& in_value) override;
-
- ClassDescriptorSP
- GetClassDescriptorFromISA(ObjCISA isa) override;
-
- DeclVendor *
- GetDeclVendor() override;
-
- lldb::addr_t
- LookupRuntimeSymbol(const ConstString &name) override;
-
- EncodingToTypeSP
- GetEncodingToType() override;
-
- TaggedPointerVendor*
- GetTaggedPointerVendor() override
- {
- return m_tagged_pointer_vendor_ap.get();
- }
-
- void
- GetValuesForGlobalCFBooleans(lldb::addr_t& cf_true,
- lldb::addr_t& cf_false) override;
-
- // none of these are valid ISAs - we use them to infer the type
- // of tagged pointers - if we have something meaningful to say
- // we report an actual type - otherwise, we just say tagged
- // there is no connection between the values here and the tagged pointers map
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2;
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3;
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4;
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject = 5;
- static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
+ uint32_t GetPluginVersion() override;
+
+ ObjCRuntimeVersions GetRuntimeVersion() const override {
+ return ObjCRuntimeVersions::eAppleObjC_V2;
+ }
+
+ size_t GetByteOffsetForIvar(CompilerType &parent_qual_type,
+ const char *ivar_name) override;
+
+ void UpdateISAToDescriptorMapIfNeeded() override;
+
+ ConstString GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
+
+ ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override;
+
+ ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
+
+ DeclVendor *GetDeclVendor() override;
+
+ lldb::addr_t LookupRuntimeSymbol(const ConstString &name) override;
+
+ EncodingToTypeSP GetEncodingToType() override;
+
+ TaggedPointerVendor *GetTaggedPointerVendor() override {
+ return m_tagged_pointer_vendor_ap.get();
+ }
+
+ void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
+ lldb::addr_t &cf_false) override;
+
+ // none of these are valid ISAs - we use them to infer the type
+ // of tagged pointers - if we have something meaningful to say
+ // we report an actual type - otherwise, we just say tagged
+ // there is no connection between the values here and the tagged pointers map
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA = 1;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSAtom = 2;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSNumber = 3;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDateTS = 4;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSManagedObject =
+ 5;
+ static const ObjCLanguageRuntime::ObjCISA g_objc_Tagged_ISA_NSDate = 6;
protected:
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override;
private:
- class HashTableSignature
- {
- public:
- HashTableSignature ();
+ class HashTableSignature {
+ public:
+ HashTableSignature();
- bool
- NeedsUpdate (Process *process,
- AppleObjCRuntimeV2 *runtime,
+ bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime,
RemoteNXMapTable &hash_table);
-
- void
- UpdateSignature (const RemoteNXMapTable &hash_table);
- protected:
- uint32_t m_count;
- uint32_t m_num_buckets;
- lldb::addr_t m_buckets_ptr;
- };
+ void UpdateSignature(const RemoteNXMapTable &hash_table);
- class NonPointerISACache
- {
- public:
- static NonPointerISACache*
- CreateInstance (AppleObjCRuntimeV2& runtime,
- const lldb::ModuleSP& objc_module_sp);
-
+ protected:
+ uint32_t m_count;
+ uint32_t m_num_buckets;
+ lldb::addr_t m_buckets_ptr;
+ };
- ObjCLanguageRuntime::ClassDescriptorSP
- GetClassDescriptor (ObjCISA isa);
+ class NonPointerISACache {
+ public:
+ static NonPointerISACache *
+ CreateInstance(AppleObjCRuntimeV2 &runtime,
+ const lldb::ModuleSP &objc_module_sp);
- private:
- NonPointerISACache (AppleObjCRuntimeV2& runtime,
- uint64_t objc_debug_isa_class_mask,
- uint64_t objc_debug_isa_magic_mask,
- uint64_t objc_debug_isa_magic_value);
-
- bool
- EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa);
-
- AppleObjCRuntimeV2& m_runtime;
- std::map<ObjCISA,ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
- uint64_t m_objc_debug_isa_class_mask;
- uint64_t m_objc_debug_isa_magic_mask;
- uint64_t m_objc_debug_isa_magic_value;
+ ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa);
- friend class AppleObjCRuntimeV2;
-
- DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
- };
-
- class TaggedPointerVendorV2 : public ObjCLanguageRuntime::TaggedPointerVendor
- {
- public:
- ~TaggedPointerVendorV2() override = default;
+ private:
+ NonPointerISACache(AppleObjCRuntimeV2 &runtime,
+ uint64_t objc_debug_isa_class_mask,
+ uint64_t objc_debug_isa_magic_mask,
+ uint64_t objc_debug_isa_magic_value);
- static TaggedPointerVendorV2*
- CreateInstance (AppleObjCRuntimeV2& runtime,
- const lldb::ModuleSP& objc_module_sp);
+ bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa);
- protected:
- AppleObjCRuntimeV2& m_runtime;
-
- TaggedPointerVendorV2 (AppleObjCRuntimeV2& runtime) :
- TaggedPointerVendor(),
- m_runtime(runtime)
- {
- }
+ AppleObjCRuntimeV2 &m_runtime;
+ std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
+ uint64_t m_objc_debug_isa_class_mask;
+ uint64_t m_objc_debug_isa_magic_mask;
+ uint64_t m_objc_debug_isa_magic_value;
- private:
- DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorV2);
- };
-
- class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2
- {
- public:
- bool
- IsPossibleTaggedPointer(lldb::addr_t ptr) override;
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetClassDescriptor(lldb::addr_t ptr) override;
+ friend class AppleObjCRuntimeV2;
- protected:
- 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);
-
- typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
- typedef Cache::iterator CacheIterator;
- Cache m_cache;
- uint64_t m_objc_debug_taggedpointer_mask;
- uint32_t m_objc_debug_taggedpointer_slot_shift;
- uint32_t m_objc_debug_taggedpointer_slot_mask;
- uint32_t m_objc_debug_taggedpointer_payload_lshift;
- uint32_t m_objc_debug_taggedpointer_payload_rshift;
- lldb::addr_t m_objc_debug_taggedpointer_classes;
-
- friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
-
- DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
- };
-
- class TaggedPointerVendorExtended : public TaggedPointerVendorRuntimeAssisted
- {
- public:
- ObjCLanguageRuntime::ClassDescriptorSP
- GetClassDescriptor(lldb::addr_t ptr) override;
+ DISALLOW_COPY_AND_ASSIGN(NonPointerISACache);
+ };
- protected:
- 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);
+ class TaggedPointerVendorV2
+ : public ObjCLanguageRuntime::TaggedPointerVendor {
+ public:
+ ~TaggedPointerVendorV2() override = default;
- bool
- IsPossibleExtendedTaggedPointer (lldb::addr_t ptr);
+ static TaggedPointerVendorV2 *
+ CreateInstance(AppleObjCRuntimeV2 &runtime,
+ const lldb::ModuleSP &objc_module_sp);
- typedef std::map<uint8_t,ObjCLanguageRuntime::ClassDescriptorSP> Cache;
- typedef Cache::iterator CacheIterator;
- Cache m_ext_cache;
- uint64_t m_objc_debug_taggedpointer_ext_mask;
- uint32_t m_objc_debug_taggedpointer_ext_slot_shift;
- uint32_t m_objc_debug_taggedpointer_ext_slot_mask;
- uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;
- uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;
- lldb::addr_t m_objc_debug_taggedpointer_ext_classes;
+ protected:
+ AppleObjCRuntimeV2 &m_runtime;
- friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
+ TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime)
+ : TaggedPointerVendor(), m_runtime(runtime) {}
- DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended);
- };
-
- class TaggedPointerVendorLegacy : public TaggedPointerVendorV2
- {
- public:
- bool
- IsPossibleTaggedPointer(lldb::addr_t ptr) override;
-
- ObjCLanguageRuntime::ClassDescriptorSP
- GetClassDescriptor (lldb::addr_t ptr) override;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorV2);
+ };
- protected:
- TaggedPointerVendorLegacy (AppleObjCRuntimeV2& runtime) :
- TaggedPointerVendorV2 (runtime)
- {
- }
-
- friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
-
- DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
- };
-
- struct DescriptorMapUpdateResult
- {
- bool m_update_ran;
- uint32_t m_num_found;
-
- DescriptorMapUpdateResult (bool ran,
- uint32_t found)
- {
- m_update_ran = ran;
- m_num_found = found;
- }
-
- static DescriptorMapUpdateResult
- Fail ()
- {
- return {false, 0};
- }
-
- static DescriptorMapUpdateResult
- Success (uint32_t found)
- {
- return {true, found};
- }
- };
-
- AppleObjCRuntimeV2 (Process *process,
- const lldb::ModuleSP &objc_module_sp);
-
- ObjCISA
- GetPointerISA (ObjCISA isa);
-
- bool
- IsTaggedPointer(lldb::addr_t ptr);
-
- lldb::addr_t
- GetISAHashTablePointer ();
+ class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 {
+ public:
+ bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
- bool
- UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table);
-
- DescriptorMapUpdateResult
- UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
-
- uint32_t
- ParseClassInfoArray (const lldb_private::DataExtractor &data,
- uint32_t num_class_infos);
-
- DescriptorMapUpdateResult
- UpdateISAToDescriptorMapSharedCache ();
-
- enum class SharedCacheWarningReason
- {
- eExpressionExecutionFailure,
- eNotEnoughClassesRead
- };
-
- void
- WarnIfNoClassesCached (SharedCacheWarningReason reason);
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor(lldb::addr_t ptr) override;
- lldb::addr_t
- GetSharedCacheReadOnlyAddress();
-
- bool
- GetCFBooleanValuesIfNeeded ();
-
- friend class ClassDescriptorV2;
+ protected:
+ 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);
- std::unique_ptr<UtilityFunction> m_get_class_info_code;
- lldb::addr_t m_get_class_info_args;
- std::mutex m_get_class_info_args_mutex;
+ typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+ typedef Cache::iterator CacheIterator;
+ Cache m_cache;
+ uint64_t m_objc_debug_taggedpointer_mask;
+ uint32_t m_objc_debug_taggedpointer_slot_shift;
+ uint32_t m_objc_debug_taggedpointer_slot_mask;
+ uint32_t m_objc_debug_taggedpointer_payload_lshift;
+ uint32_t m_objc_debug_taggedpointer_payload_rshift;
+ lldb::addr_t m_objc_debug_taggedpointer_classes;
- std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
- lldb::addr_t m_get_shared_cache_class_info_args;
- std::mutex m_get_shared_cache_class_info_args_mutex;
+ friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
- std::unique_ptr<DeclVendor> m_decl_vendor_ap;
- lldb::addr_t m_isa_hash_table_ptr;
- HashTableSignature m_hash_signature;
- bool m_has_object_getClass;
- bool m_loaded_objc_opt;
- std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
- std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
- EncodingToTypeSP m_encoding_to_type_sp;
- bool m_noclasses_warning_emitted;
- llvm::Optional<std::pair<lldb::addr_t,
- lldb::addr_t>> m_CFBoolean_values;
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted);
+ };
+
+ class TaggedPointerVendorExtended
+ : public TaggedPointerVendorRuntimeAssisted {
+ public:
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor(lldb::addr_t ptr) override;
+
+ protected:
+ 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);
+
+ bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr);
+
+ typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
+ typedef Cache::iterator CacheIterator;
+ Cache m_ext_cache;
+ uint64_t m_objc_debug_taggedpointer_ext_mask;
+ uint32_t m_objc_debug_taggedpointer_ext_slot_shift;
+ uint32_t m_objc_debug_taggedpointer_ext_slot_mask;
+ uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;
+ uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;
+ lldb::addr_t m_objc_debug_taggedpointer_ext_classes;
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended);
+ };
+
+ class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 {
+ public:
+ bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
+
+ ObjCLanguageRuntime::ClassDescriptorSP
+ GetClassDescriptor(lldb::addr_t ptr) override;
+
+ protected:
+ TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime)
+ : TaggedPointerVendorV2(runtime) {}
+
+ friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
+
+ DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorLegacy);
+ };
+
+ struct DescriptorMapUpdateResult {
+ bool m_update_ran;
+ uint32_t m_num_found;
+
+ DescriptorMapUpdateResult(bool ran, uint32_t found) {
+ m_update_ran = ran;
+ m_num_found = found;
+ }
+
+ static DescriptorMapUpdateResult Fail() { return {false, 0}; }
+
+ static DescriptorMapUpdateResult Success(uint32_t found) {
+ return {true, found};
+ }
+ };
+
+ AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
+
+ ObjCISA GetPointerISA(ObjCISA isa);
+
+ bool IsTaggedPointer(lldb::addr_t ptr);
+
+ lldb::addr_t GetISAHashTablePointer();
+
+ bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table);
+
+ DescriptorMapUpdateResult
+ UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table);
+
+ uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,
+ uint32_t num_class_infos);
+
+ DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache();
+
+ enum class SharedCacheWarningReason {
+ eExpressionExecutionFailure,
+ eNotEnoughClassesRead
+ };
+
+ void WarnIfNoClassesCached(SharedCacheWarningReason reason);
+
+ lldb::addr_t GetSharedCacheReadOnlyAddress();
+
+ bool GetCFBooleanValuesIfNeeded();
+
+ friend class ClassDescriptorV2;
+
+ std::unique_ptr<UtilityFunction> m_get_class_info_code;
+ lldb::addr_t m_get_class_info_args;
+ std::mutex m_get_class_info_args_mutex;
+
+ std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
+ lldb::addr_t m_get_shared_cache_class_info_args;
+ std::mutex m_get_shared_cache_class_info_args_mutex;
+
+ std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ lldb::addr_t m_isa_hash_table_ptr;
+ HashTableSignature m_hash_signature;
+ bool m_has_object_getClass;
+ bool m_loaded_objc_opt;
+ std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
+ std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
+ EncodingToTypeSP m_encoding_to_type_sp;
+ bool m_noclasses_warning_emitted;
+ llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
};
-
+
} // namespace lldb_private
#endif // liblldb_AppleObjCRuntimeV2_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index 5fedb80..1dc20c1 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -1,4 +1,5 @@
-//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===//
+//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++
+//-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -43,8 +44,11 @@
using namespace lldb;
using namespace lldb_private;
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = " \n\
+const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name =
+ "__lldb_objc_find_implementation_for_selector";
+const char *AppleObjCTrampolineHandler::
+ g_lookup_implementation_with_stret_function_code =
+ " \n\
extern \"C\" \n\
{ \n\
extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
@@ -159,7 +163,9 @@
return return_struct.impl_addr; \n\
} \n\
";
-const char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = " \n\
+const char *
+ AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code =
+ " \n\
extern \"C\" \n\
{ \n\
extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
@@ -266,887 +272,879 @@
} \n\
";
-AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
- m_valid (true),
- m_owner(owner),
- m_header_addr (header_addr),
- m_code_start_addr(0),
- m_code_end_addr (0),
- m_next_region (0)
-{
- SetUpRegion ();
+AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(
+ AppleObjCVTables *owner, lldb::addr_t header_addr)
+ : m_valid(true), m_owner(owner), m_header_addr(header_addr),
+ m_code_start_addr(0), m_code_end_addr(0), m_next_region(0) {
+ SetUpRegion();
}
-AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler()
-{
+AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() {}
+
+void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
+ // The header looks like:
+ //
+ // uint16_t headerSize
+ // uint16_t descSize
+ // uint32_t descCount
+ // void * next
+ //
+ // First read in the header:
+
+ char memory_buffer[16];
+ ProcessSP process_sp = m_owner->GetProcessSP();
+ if (!process_sp)
+ return;
+ DataExtractor data(memory_buffer, sizeof(memory_buffer),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ size_t actual_size = 8 + process_sp->GetAddressByteSize();
+ Error error;
+ size_t bytes_read =
+ process_sp->ReadMemory(m_header_addr, memory_buffer, actual_size, error);
+ if (bytes_read != actual_size) {
+ m_valid = false;
+ return;
+ }
+
+ lldb::offset_t offset = 0;
+ const uint16_t header_size = data.GetU16(&offset);
+ const uint16_t descriptor_size = data.GetU16(&offset);
+ const size_t num_descriptors = data.GetU32(&offset);
+
+ m_next_region = data.GetPointer(&offset);
+
+ // If the header size is 0, that means we've come in too early before this
+ // data is set up.
+ // Set ourselves as not valid, and continue.
+ if (header_size == 0 || num_descriptors == 0) {
+ m_valid = false;
+ return;
+ }
+
+ // Now read in all the descriptors:
+ // The descriptor looks like:
+ //
+ // uint32_t offset
+ // uint32_t flags
+ //
+ // Where offset is either 0 - in which case it is unused, or
+ // it is the offset of the vtable code from the beginning of the descriptor
+ // record.
+ // Below, we'll convert that into an absolute code address, since I don't want
+ // to have
+ // to compute it over and over.
+
+ // Ingest the whole descriptor array:
+ const lldb::addr_t desc_ptr = m_header_addr + header_size;
+ const size_t desc_array_size = num_descriptors * descriptor_size;
+ DataBufferSP data_sp(new DataBufferHeap(desc_array_size, '\0'));
+ uint8_t *dst = (uint8_t *)data_sp->GetBytes();
+
+ DataExtractor desc_extractor(dst, desc_array_size, process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ bytes_read = process_sp->ReadMemory(desc_ptr, dst, desc_array_size, error);
+ if (bytes_read != desc_array_size) {
+ m_valid = false;
+ return;
+ }
+
+ // The actual code for the vtables will be laid out consecutively, so I also
+ // compute the start and end of the whole code block.
+
+ offset = 0;
+ m_code_start_addr = 0;
+ m_code_end_addr = 0;
+
+ for (size_t i = 0; i < num_descriptors; i++) {
+ lldb::addr_t start_offset = offset;
+ uint32_t voffset = desc_extractor.GetU32(&offset);
+ uint32_t flags = desc_extractor.GetU32(&offset);
+ lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
+ m_descriptors.push_back(VTableDescriptor(flags, code_addr));
+
+ if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
+ m_code_start_addr = code_addr;
+ if (code_addr > m_code_end_addr)
+ m_code_end_addr = code_addr;
+
+ offset = start_offset + descriptor_size;
+ }
+ // Finally, a little bird told me that all the vtable code blocks are the same
+ // size.
+ // Let's compute the blocks and if they are all the same add the size to the
+ // code end address:
+ lldb::addr_t code_size = 0;
+ bool all_the_same = true;
+ for (size_t i = 0; i < num_descriptors - 1; i++) {
+ lldb::addr_t this_size =
+ m_descriptors[i + 1].code_start - m_descriptors[i].code_start;
+ if (code_size == 0)
+ code_size = this_size;
+ else {
+ if (this_size != code_size)
+ all_the_same = false;
+ if (this_size > code_size)
+ code_size = this_size;
+ }
+ }
+ if (all_the_same)
+ m_code_end_addr += code_size;
}
-void
-AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
-{
- // The header looks like:
- //
- // uint16_t headerSize
- // uint16_t descSize
- // uint32_t descCount
- // void * next
- //
- // First read in the header:
-
- char memory_buffer[16];
- ProcessSP process_sp = m_owner->GetProcessSP();
- if (!process_sp)
- return;
- DataExtractor data(memory_buffer, sizeof(memory_buffer),
- process_sp->GetByteOrder(),
- process_sp->GetAddressByteSize());
- size_t actual_size = 8 + process_sp->GetAddressByteSize();
- Error error;
- size_t bytes_read = process_sp->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
- if (bytes_read != actual_size)
- {
- m_valid = false;
- return;
- }
-
- lldb::offset_t offset = 0;
- const uint16_t header_size = data.GetU16(&offset);
- const uint16_t descriptor_size = data.GetU16(&offset);
- const size_t num_descriptors = data.GetU32(&offset);
-
- m_next_region = data.GetPointer(&offset);
-
- // If the header size is 0, that means we've come in too early before this data is set up.
- // Set ourselves as not valid, and continue.
- if (header_size == 0 || num_descriptors == 0)
- {
- m_valid = false;
- return;
- }
-
- // Now read in all the descriptors:
- // The descriptor looks like:
- //
- // uint32_t offset
- // uint32_t flags
- //
- // Where offset is either 0 - in which case it is unused, or
- // it is the offset of the vtable code from the beginning of the descriptor record.
- // Below, we'll convert that into an absolute code address, since I don't want to have
- // to compute it over and over.
-
- // Ingest the whole descriptor array:
- const lldb::addr_t desc_ptr = m_header_addr + header_size;
- const size_t desc_array_size = num_descriptors * descriptor_size;
- DataBufferSP data_sp(new DataBufferHeap (desc_array_size, '\0'));
- uint8_t* dst = (uint8_t*)data_sp->GetBytes();
-
- DataExtractor desc_extractor (dst, desc_array_size,
- process_sp->GetByteOrder(),
- process_sp->GetAddressByteSize());
- bytes_read = process_sp->ReadMemory(desc_ptr, dst, desc_array_size, error);
- if (bytes_read != desc_array_size)
- {
- m_valid = false;
- return;
- }
-
- // The actual code for the vtables will be laid out consecutively, so I also
- // compute the start and end of the whole code block.
-
- offset = 0;
- m_code_start_addr = 0;
- m_code_end_addr = 0;
-
- for (size_t i = 0; i < num_descriptors; i++)
- {
- lldb::addr_t start_offset = offset;
- uint32_t voffset = desc_extractor.GetU32 (&offset);
- uint32_t flags = desc_extractor.GetU32 (&offset);
- lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
- m_descriptors.push_back (VTableDescriptor(flags, code_addr));
-
- if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
- m_code_start_addr = code_addr;
- if (code_addr > m_code_end_addr)
- m_code_end_addr = code_addr;
-
- offset = start_offset + descriptor_size;
- }
- // Finally, a little bird told me that all the vtable code blocks are the same size.
- // Let's compute the blocks and if they are all the same add the size to the code end address:
- lldb::addr_t code_size = 0;
- bool all_the_same = true;
- for (size_t i = 0; i < num_descriptors - 1; i++)
- {
- lldb::addr_t this_size = m_descriptors[i + 1].code_start - m_descriptors[i].code_start;
- if (code_size == 0)
- code_size = this_size;
- else
- {
- if (this_size != code_size)
- all_the_same = false;
- if (this_size > code_size)
- code_size = this_size;
- }
- }
- if (all_the_same)
- m_code_end_addr += code_size;
-}
-
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::AddressInRegion (lldb::addr_t addr, uint32_t &flags)
-{
- if (!IsValid())
- return false;
-
- if (addr < m_code_start_addr || addr > m_code_end_addr)
- return false;
-
- std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end();
- for (pos = m_descriptors.begin(); pos != end; pos++)
- {
- if (addr <= (*pos).code_start)
- {
- flags = (*pos).flags;
- return true;
- }
- }
+bool AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::
+ AddressInRegion(lldb::addr_t addr, uint32_t &flags) {
+ if (!IsValid())
return false;
-}
-void
-AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
-{
- s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
- m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
- size_t num_elements = m_descriptors.size();
- for (size_t i = 0; i < num_elements; i++)
- {
- s.Indent();
- s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
- }
-}
-
-AppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp,
- const ModuleSP &objc_module_sp) :
- m_process_wp (),
- m_trampoline_header (LLDB_INVALID_ADDRESS),
- m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID),
- m_objc_module_sp (objc_module_sp)
-{
- if (process_sp)
- m_process_wp = process_sp;
-}
-
-AppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables()
-{
- ProcessSP process_sp = GetProcessSP ();
- if (process_sp)
- {
- if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
- process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
- }
-}
-
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
-{
- if (m_trampoline_header != LLDB_INVALID_ADDRESS)
- return true;
-
- ProcessSP process_sp = GetProcessSP ();
- if (process_sp)
- {
- Target &target = process_sp->GetTarget();
-
- const ModuleList &target_modules = target.GetImages();
- std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
- size_t num_modules = target_modules.GetSize();
- if (!m_objc_module_sp)
- {
- for (size_t i = 0; i < num_modules; i++)
- {
- if (process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
- {
- m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
- break;
- }
- }
- }
-
- if (m_objc_module_sp)
- {
- ConstString trampoline_name ("gdb_objc_trampolines");
- const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
- eSymbolTypeData);
- if (trampoline_symbol != NULL)
- {
- m_trampoline_header = trampoline_symbol->GetLoadAddress(&target);
- if (m_trampoline_header == LLDB_INVALID_ADDRESS)
- return false;
-
- // Next look up the "changed" symbol and set a breakpoint on that...
- ConstString changed_name ("gdb_objc_trampolines_changed");
- const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
- eSymbolTypeCode);
- if (changed_symbol != NULL)
- {
- const Address changed_symbol_addr = changed_symbol->GetAddress();
- if (!changed_symbol_addr.IsValid())
- return false;
-
- lldb::addr_t changed_addr = changed_symbol_addr.GetOpcodeLoadAddress (&target);
- if (changed_addr != LLDB_INVALID_ADDRESS)
- {
- BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true, false);
- if (trampolines_changed_bp_sp)
- {
- m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
- trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
- trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
- return true;
- }
- }
- }
- }
- }
- }
+ if (addr < m_code_start_addr || addr > m_code_end_addr)
return false;
-}
-
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id)
-{
- AppleObjCVTables *vtable_handler = (AppleObjCVTables *) baton;
- if (vtable_handler->InitializeVTableSymbols())
- {
- // The Update function is called with the address of an added region. So we grab that address, and
- // feed it into ReadRegions. Of course, our friend the ABI will get the values for us.
- ExecutionContext exe_ctx (context->exe_ctx_ref);
- Process *process = exe_ctx.GetProcessPtr();
- const ABI *abi = process->GetABI().get();
-
- ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
- ValueList argument_values;
- Value input_value;
- CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- input_value.SetValueType (Value::eValueTypeScalar);
- //input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
- input_value.SetCompilerType (clang_void_ptr_type);
- argument_values.PushValue(input_value);
-
- bool success = abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values);
- if (!success)
- return false;
-
- // Now get a pointer value from the zeroth argument.
- Error error;
- DataExtractor data;
- error = argument_values.GetValueAtIndex(0)->GetValueAsData (&exe_ctx,
- data,
- 0,
- NULL);
- lldb::offset_t offset = 0;
- lldb::addr_t region_addr = data.GetPointer(&offset);
-
- if (region_addr != 0)
- vtable_handler->ReadRegions(region_addr);
+ std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end();
+ for (pos = m_descriptors.begin(); pos != end; pos++) {
+ if (addr <= (*pos).code_start) {
+ flags = (*pos).flags;
+ return true;
}
- return false;
+ }
+ return false;
}
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
-{
- // The no argument version reads the start region from the value of the gdb_regions_header, and
- // gets started from there.
-
- m_regions.clear();
- if (!InitializeVTableSymbols())
- return false;
- Error error;
- ProcessSP process_sp = GetProcessSP ();
- if (process_sp)
- {
- lldb::addr_t region_addr = process_sp->ReadPointerFromMemory (m_trampoline_header, error);
- if (error.Success())
- return ReadRegions (region_addr);
- }
- return false;
+void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump(
+ Stream &s) {
+ s.Printf("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64
+ " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
+ m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
+ size_t num_elements = m_descriptors.size();
+ for (size_t i = 0; i < num_elements; i++) {
+ s.Indent();
+ s.Printf("Code start: 0x%" PRIx64 " Flags: %d\n",
+ m_descriptors[i].code_start, m_descriptors[i].flags);
+ }
}
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr)
-{
- ProcessSP process_sp = GetProcessSP ();
- if (!process_sp)
- return false;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
-
- // We aren't starting at the trampoline symbol.
- InitializeVTableSymbols ();
- lldb::addr_t next_region = region_addr;
-
- // Read in the sizes of the headers.
- while (next_region != 0)
- {
- m_regions.push_back (VTableRegion(this, next_region));
- if (!m_regions.back().IsValid())
- {
- m_regions.clear();
- return false;
- }
- if (log)
- {
- StreamString s;
- m_regions.back().Dump(s);
- log->Printf("Read vtable region: \n%s", s.GetData());
- }
-
- next_region = m_regions.back().GetNextRegionAddr();
- }
-
+AppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables(
+ const ProcessSP &process_sp, const ModuleSP &objc_module_sp)
+ : m_process_wp(), m_trampoline_header(LLDB_INVALID_ADDRESS),
+ m_trampolines_changed_bp_id(LLDB_INVALID_BREAK_ID),
+ m_objc_module_sp(objc_module_sp) {
+ if (process_sp)
+ m_process_wp = process_sp;
+}
+
+AppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables() {
+ ProcessSP process_sp = GetProcessSP();
+ if (process_sp) {
+ if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
+ process_sp->GetTarget().RemoveBreakpointByID(m_trampolines_changed_bp_id);
+ }
+}
+
+bool AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols() {
+ if (m_trampoline_header != LLDB_INVALID_ADDRESS)
return true;
-}
-
-bool
-AppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables (lldb::addr_t addr, uint32_t &flags)
-{
- region_collection::iterator pos, end = m_regions.end();
- for (pos = m_regions.begin(); pos != end; pos++)
- {
- if ((*pos).AddressInRegion (addr, flags))
- return true;
+
+ ProcessSP process_sp = GetProcessSP();
+ if (process_sp) {
+ Target &target = process_sp->GetTarget();
+
+ const ModuleList &target_modules = target.GetImages();
+ std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
+ size_t num_modules = target_modules.GetSize();
+ if (!m_objc_module_sp) {
+ for (size_t i = 0; i < num_modules; i++) {
+ if (process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary(
+ target_modules.GetModuleAtIndexUnlocked(i))) {
+ m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
+ break;
+ }
+ }
}
+
+ if (m_objc_module_sp) {
+ ConstString trampoline_name("gdb_objc_trampolines");
+ const Symbol *trampoline_symbol =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(trampoline_name,
+ eSymbolTypeData);
+ if (trampoline_symbol != NULL) {
+ m_trampoline_header = trampoline_symbol->GetLoadAddress(&target);
+ if (m_trampoline_header == LLDB_INVALID_ADDRESS)
+ return false;
+
+ // Next look up the "changed" symbol and set a breakpoint on that...
+ ConstString changed_name("gdb_objc_trampolines_changed");
+ const Symbol *changed_symbol =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(changed_name,
+ eSymbolTypeCode);
+ if (changed_symbol != NULL) {
+ const Address changed_symbol_addr = changed_symbol->GetAddress();
+ if (!changed_symbol_addr.IsValid())
+ return false;
+
+ lldb::addr_t changed_addr =
+ changed_symbol_addr.GetOpcodeLoadAddress(&target);
+ if (changed_addr != LLDB_INVALID_ADDRESS) {
+ BreakpointSP trampolines_changed_bp_sp =
+ target.CreateBreakpoint(changed_addr, true, false);
+ if (trampolines_changed_bp_sp) {
+ m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
+ trampolines_changed_bp_sp->SetCallback(RefreshTrampolines, this,
+ true);
+ trampolines_changed_bp_sp->SetBreakpointKind(
+ "objc-trampolines-changed");
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
+ void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id) {
+ AppleObjCVTables *vtable_handler = (AppleObjCVTables *)baton;
+ if (vtable_handler->InitializeVTableSymbols()) {
+ // The Update function is called with the address of an added region. So we
+ // grab that address, and
+ // feed it into ReadRegions. Of course, our friend the ABI will get the
+ // values for us.
+ ExecutionContext exe_ctx(context->exe_ctx_ref);
+ Process *process = exe_ctx.GetProcessPtr();
+ const ABI *abi = process->GetABI().get();
+
+ ClangASTContext *clang_ast_context =
+ process->GetTarget().GetScratchClangASTContext();
+ ValueList argument_values;
+ Value input_value;
+ CompilerType clang_void_ptr_type =
+ clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ input_value.SetValueType(Value::eValueTypeScalar);
+ // input_value.SetContext (Value::eContextTypeClangType,
+ // clang_void_ptr_type);
+ input_value.SetCompilerType(clang_void_ptr_type);
+ argument_values.PushValue(input_value);
+
+ bool success =
+ abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values);
+ if (!success)
+ return false;
+
+ // Now get a pointer value from the zeroth argument.
+ Error error;
+ DataExtractor data;
+ error = argument_values.GetValueAtIndex(0)->GetValueAsData(&exe_ctx, data,
+ 0, NULL);
+ lldb::offset_t offset = 0;
+ lldb::addr_t region_addr = data.GetPointer(&offset);
+
+ if (region_addr != 0)
+ vtable_handler->ReadRegions(region_addr);
+ }
+ return false;
+}
+
+bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions() {
+ // The no argument version reads the start region from the value of the
+ // gdb_regions_header, and
+ // gets started from there.
+
+ m_regions.clear();
+ if (!InitializeVTableSymbols())
return false;
+ Error error;
+ ProcessSP process_sp = GetProcessSP();
+ if (process_sp) {
+ lldb::addr_t region_addr =
+ process_sp->ReadPointerFromMemory(m_trampoline_header, error);
+ if (error.Success())
+ return ReadRegions(region_addr);
+ }
+ return false;
+}
+
+bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions(
+ lldb::addr_t region_addr) {
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ // We aren't starting at the trampoline symbol.
+ InitializeVTableSymbols();
+ lldb::addr_t next_region = region_addr;
+
+ // Read in the sizes of the headers.
+ while (next_region != 0) {
+ m_regions.push_back(VTableRegion(this, next_region));
+ if (!m_regions.back().IsValid()) {
+ m_regions.clear();
+ return false;
+ }
+ if (log) {
+ StreamString s;
+ m_regions.back().Dump(s);
+ log->Printf("Read vtable region: \n%s", s.GetData());
+ }
+
+ next_region = m_regions.back().GetNextRegionAddr();
+ }
+
+ return true;
+}
+
+bool AppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables(
+ lldb::addr_t addr, uint32_t &flags) {
+ region_collection::iterator pos, end = m_regions.end();
+ for (pos = m_regions.begin(); pos != end; pos++) {
+ if ((*pos).AddressInRegion(addr, flags))
+ return true;
+ }
+ return false;
}
const AppleObjCTrampolineHandler::DispatchFunction
-AppleObjCTrampolineHandler::g_dispatch_functions[] =
-{
- // NAME STRET SUPER SUPER2 FIXUP TYPE
- {"objc_msgSend", false, false, false, DispatchFunction::eFixUpNone },
- {"objc_msgSend_fixup", false, false, false, DispatchFunction::eFixUpToFix },
- {"objc_msgSend_fixedup", false, false, false, DispatchFunction::eFixUpFixed },
- {"objc_msgSend_stret", true, false, false, DispatchFunction::eFixUpNone },
- {"objc_msgSend_stret_fixup", true, false, false, DispatchFunction::eFixUpToFix },
- {"objc_msgSend_stret_fixedup", true, false, false, DispatchFunction::eFixUpFixed },
- {"objc_msgSend_fpret", false, false, false, DispatchFunction::eFixUpNone },
- {"objc_msgSend_fpret_fixup", false, false, false, DispatchFunction::eFixUpToFix },
- {"objc_msgSend_fpret_fixedup", false, false, false, DispatchFunction::eFixUpFixed },
- {"objc_msgSend_fp2ret", false, false, true, DispatchFunction::eFixUpNone },
- {"objc_msgSend_fp2ret_fixup", false, false, true, DispatchFunction::eFixUpToFix },
- {"objc_msgSend_fp2ret_fixedup", false, false, true, DispatchFunction::eFixUpFixed },
- {"objc_msgSendSuper", false, true, false, DispatchFunction::eFixUpNone },
- {"objc_msgSendSuper_stret", true, true, false, DispatchFunction::eFixUpNone },
- {"objc_msgSendSuper2", false, true, true, DispatchFunction::eFixUpNone },
- {"objc_msgSendSuper2_fixup", false, true, true, DispatchFunction::eFixUpToFix },
- {"objc_msgSendSuper2_fixedup", false, true, true, DispatchFunction::eFixUpFixed },
- {"objc_msgSendSuper2_stret", true, true, true, DispatchFunction::eFixUpNone },
- {"objc_msgSendSuper2_stret_fixup", true, true, true, DispatchFunction::eFixUpToFix },
- {"objc_msgSendSuper2_stret_fixedup", true, true, true, DispatchFunction::eFixUpFixed },
+ AppleObjCTrampolineHandler::g_dispatch_functions[] = {
+ // NAME STRET SUPER SUPER2 FIXUP TYPE
+ {"objc_msgSend", false, false, false, DispatchFunction::eFixUpNone},
+ {"objc_msgSend_fixup", false, false, false,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSend_fixedup", false, false, false,
+ DispatchFunction::eFixUpFixed},
+ {"objc_msgSend_stret", true, false, false,
+ DispatchFunction::eFixUpNone},
+ {"objc_msgSend_stret_fixup", true, false, false,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSend_stret_fixedup", true, false, false,
+ DispatchFunction::eFixUpFixed},
+ {"objc_msgSend_fpret", false, false, false,
+ DispatchFunction::eFixUpNone},
+ {"objc_msgSend_fpret_fixup", false, false, false,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSend_fpret_fixedup", false, false, false,
+ DispatchFunction::eFixUpFixed},
+ {"objc_msgSend_fp2ret", false, false, true,
+ DispatchFunction::eFixUpNone},
+ {"objc_msgSend_fp2ret_fixup", false, false, true,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSend_fp2ret_fixedup", false, false, true,
+ DispatchFunction::eFixUpFixed},
+ {"objc_msgSendSuper", false, true, false, DispatchFunction::eFixUpNone},
+ {"objc_msgSendSuper_stret", true, true, false,
+ DispatchFunction::eFixUpNone},
+ {"objc_msgSendSuper2", false, true, true, DispatchFunction::eFixUpNone},
+ {"objc_msgSendSuper2_fixup", false, true, true,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSendSuper2_fixedup", false, true, true,
+ DispatchFunction::eFixUpFixed},
+ {"objc_msgSendSuper2_stret", true, true, true,
+ DispatchFunction::eFixUpNone},
+ {"objc_msgSendSuper2_stret_fixup", true, true, true,
+ DispatchFunction::eFixUpToFix},
+ {"objc_msgSendSuper2_stret_fixedup", true, true, true,
+ DispatchFunction::eFixUpFixed},
};
-AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp,
- const ModuleSP &objc_module_sp) :
- m_process_wp (),
- m_objc_module_sp (objc_module_sp),
- m_lookup_implementation_function_code(nullptr),
- m_impl_fn_addr (LLDB_INVALID_ADDRESS),
- m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
- m_msg_forward_addr (LLDB_INVALID_ADDRESS)
-{
- if (process_sp)
- m_process_wp = process_sp;
- // Look up the known resolution functions:
-
- ConstString get_impl_name("class_getMethodImplementation");
- ConstString get_impl_stret_name("class_getMethodImplementation_stret");
- ConstString msg_forward_name("_objc_msgForward");
- ConstString msg_forward_stret_name("_objc_msgForward_stret");
-
- Target *target = process_sp ? &process_sp->GetTarget() : NULL;
- const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
- const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
- const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode);
- const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
-
- if (class_getMethodImplementation)
- m_impl_fn_addr = class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress (target);
- if (class_getMethodImplementation_stret)
- m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress (target);
- if (msg_forward)
- m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target);
- if (msg_forward_stret)
- m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
-
- // FIXME: Do some kind of logging here.
- if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
- {
- // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
- // step through any method dispatches. Warn to that effect and get out of here.
- if (process_sp->CanJIT())
- {
- process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf ("Could not find implementation lookup function \"%s\""
- " step in through ObjC method dispatch will not work.\n",
- get_impl_name.AsCString());
- }
- return;
- }
- else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
- {
- // It there is no stret return lookup function, assume that it is the same as the straight lookup:
- m_impl_stret_fn_addr = m_impl_fn_addr;
- // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
- m_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
- }
- else
- {
- m_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
- }
-
- // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol
- // names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can
- // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map
- // from there.
+AppleObjCTrampolineHandler::AppleObjCTrampolineHandler(
+ const ProcessSP &process_sp, const ModuleSP &objc_module_sp)
+ : m_process_wp(), m_objc_module_sp(objc_module_sp),
+ m_lookup_implementation_function_code(nullptr),
+ m_impl_fn_addr(LLDB_INVALID_ADDRESS),
+ m_impl_stret_fn_addr(LLDB_INVALID_ADDRESS),
+ m_msg_forward_addr(LLDB_INVALID_ADDRESS) {
+ if (process_sp)
+ m_process_wp = process_sp;
+ // Look up the known resolution functions:
- for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++)
- {
- ConstString name_const_str(g_dispatch_functions[i].name);
- const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode);
- if (msgSend_symbol && msgSend_symbol->ValueIsAddress())
- {
- // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index.
- // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret
- // dispatch functions. If that's as complex as it gets, we're fine.
-
- lldb::addr_t sym_addr = msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target);
-
- m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
- }
+ ConstString get_impl_name("class_getMethodImplementation");
+ ConstString get_impl_stret_name("class_getMethodImplementation_stret");
+ ConstString msg_forward_name("_objc_msgForward");
+ ConstString msg_forward_stret_name("_objc_msgForward_stret");
+
+ Target *target = process_sp ? &process_sp->GetTarget() : NULL;
+ const Symbol *class_getMethodImplementation =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_name,
+ eSymbolTypeCode);
+ const Symbol *class_getMethodImplementation_stret =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(get_impl_stret_name,
+ eSymbolTypeCode);
+ const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType(
+ msg_forward_name, eSymbolTypeCode);
+ const Symbol *msg_forward_stret =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(msg_forward_stret_name,
+ eSymbolTypeCode);
+
+ if (class_getMethodImplementation)
+ m_impl_fn_addr =
+ class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress(
+ target);
+ if (class_getMethodImplementation_stret)
+ m_impl_stret_fn_addr =
+ class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress(
+ target);
+ if (msg_forward)
+ m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target);
+ if (msg_forward_stret)
+ m_msg_forward_stret_addr =
+ msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
+
+ // FIXME: Do some kind of logging here.
+ if (m_impl_fn_addr == LLDB_INVALID_ADDRESS) {
+ // If we can't even find the ordinary get method implementation function,
+ // then we aren't going to be able to
+ // step through any method dispatches. Warn to that effect and get out of
+ // here.
+ if (process_sp->CanJIT()) {
+ process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf(
+ "Could not find implementation lookup function \"%s\""
+ " step in through ObjC method dispatch will not work.\n",
+ get_impl_name.AsCString());
}
-
- // Build our vtable dispatch handler here:
- m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp));
- if (m_vtables_ap.get())
- m_vtables_ap->ReadRegions();
+ return;
+ } else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS) {
+ // It there is no stret return lookup function, assume that it is the same
+ // as the straight lookup:
+ m_impl_stret_fn_addr = m_impl_fn_addr;
+ // Also we will use the version of the lookup code that doesn't rely on the
+ // stret version of the function.
+ m_lookup_implementation_function_code =
+ g_lookup_implementation_no_stret_function_code;
+ } else {
+ m_lookup_implementation_function_code =
+ g_lookup_implementation_with_stret_function_code;
+ }
+
+ // Look up the addresses for the objc dispatch functions and cache them. For
+ // now I'm inspecting the symbol
+ // names dynamically to figure out how to dispatch to them. If it becomes
+ // more complicated than this we can
+ // turn the g_dispatch_functions char * array into a template table, and
+ // populate the DispatchFunction map
+ // from there.
+
+ for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) {
+ ConstString name_const_str(g_dispatch_functions[i].name);
+ const Symbol *msgSend_symbol =
+ m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str,
+ eSymbolTypeCode);
+ if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) {
+ // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and
+ // have the map be address->index.
+ // Problem is we also need to lookup the dispatch function. For now we
+ // could have a side table of stret & non-stret
+ // dispatch functions. If that's as complex as it gets, we're fine.
+
+ lldb::addr_t sym_addr =
+ msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target);
+
+ m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
+ }
+ }
+
+ // Build our vtable dispatch handler here:
+ m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp));
+ if (m_vtables_ap.get())
+ m_vtables_ap->ReadRegions();
}
lldb::addr_t
-AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, ValueList &dispatch_values)
-{
- ThreadSP thread_sp(thread.shared_from_this());
- ExecutionContext exe_ctx (thread_sp);
- DiagnosticManager diagnostics;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
+ ValueList &dispatch_values) {
+ ThreadSP thread_sp(thread.shared_from_this());
+ ExecutionContext exe_ctx(thread_sp);
+ DiagnosticManager diagnostics;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
- FunctionCaller *impl_function_caller = nullptr;
+ lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ FunctionCaller *impl_function_caller = nullptr;
- // Scope for mutex locker:
- {
- std::lock_guard<std::mutex> guard(m_impl_function_mutex);
+ // Scope for mutex locker:
+ {
+ std::lock_guard<std::mutex> guard(m_impl_function_mutex);
- // First stage is to make the ClangUtility to hold our injected function:
+ // First stage is to make the ClangUtility to hold our injected function:
- if (!m_impl_code.get())
- {
- if (m_lookup_implementation_function_code != NULL)
- {
- Error error;
- m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (m_lookup_implementation_function_code,
- eLanguageTypeObjC,
- g_lookup_implementation_function_name,
- error));
- if (error.Fail())
- {
- if (log)
- log->Printf ("Failed to get Utility Function for implementation lookup: %s.", error.AsCString());
- m_impl_code.reset();
- return args_addr;
- }
-
- if (!m_impl_code->Install(diagnostics, exe_ctx))
- {
- if (log)
- {
- log->Printf("Failed to install implementation lookup.");
- diagnostics.Dump(log);
- }
- m_impl_code.reset();
- return args_addr;
- }
- }
- else
- {
- if (log)
- log->Printf("No method lookup implementation code.");
- return LLDB_INVALID_ADDRESS;
- }
-
- // Next make the runner function for our implementation utility function.
- ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
- CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- Error error;
-
- impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type,
- dispatch_values,
- thread_sp,
- error);
- if (error.Fail())
- {
- if (log)
- log->Printf ("Error getting function caller for dispatch lookup: \"%s\".", error.AsCString());
- return args_addr;
- }
+ if (!m_impl_code.get()) {
+ if (m_lookup_implementation_function_code != NULL) {
+ Error error;
+ m_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
+ m_lookup_implementation_function_code, eLanguageTypeObjC,
+ g_lookup_implementation_function_name, error));
+ if (error.Fail()) {
+ if (log)
+ log->Printf(
+ "Failed to get Utility Function for implementation lookup: %s.",
+ error.AsCString());
+ m_impl_code.reset();
+ return args_addr;
}
- else
- {
- impl_function_caller = m_impl_code->GetFunctionCaller();
- }
- }
- diagnostics.Clear();
-
- // Now write down the argument values for this particular call. This looks like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
-
- if (!impl_function_caller->WriteFunctionArguments(exe_ctx, args_addr, dispatch_values, diagnostics))
- {
- if (log)
- {
- log->Printf("Error writing function arguments.");
+ if (!m_impl_code->Install(diagnostics, exe_ctx)) {
+ if (log) {
+ log->Printf("Failed to install implementation lookup.");
diagnostics.Dump(log);
+ }
+ m_impl_code.reset();
+ return args_addr;
}
- return args_addr;
- }
+ } else {
+ if (log)
+ log->Printf("No method lookup implementation code.");
+ return LLDB_INVALID_ADDRESS;
+ }
+ // Next make the runner function for our implementation utility function.
+ ClangASTContext *clang_ast_context =
+ thread.GetProcess()->GetTarget().GetScratchClangASTContext();
+ CompilerType clang_void_ptr_type =
+ clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ Error error;
+
+ impl_function_caller = m_impl_code->MakeFunctionCaller(
+ clang_void_ptr_type, dispatch_values, thread_sp, error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf(
+ "Error getting function caller for dispatch lookup: \"%s\".",
+ error.AsCString());
+ return args_addr;
+ }
+ } else {
+ impl_function_caller = m_impl_code->GetFunctionCaller();
+ }
+ }
+
+ diagnostics.Clear();
+
+ // Now write down the argument values for this particular call. This looks
+ // like it might be a race condition
+ // if other threads were calling into here, but actually it isn't because we
+ // allocate a new args structure for
+ // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+
+ if (!impl_function_caller->WriteFunctionArguments(
+ exe_ctx, args_addr, dispatch_values, diagnostics)) {
+ if (log) {
+ log->Printf("Error writing function arguments.");
+ diagnostics.Dump(log);
+ }
return args_addr;
+ }
+
+ return args_addr;
}
ThreadPlanSP
-AppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
-{
- ThreadPlanSP ret_plan_sp;
- lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
-
- DispatchFunction this_dispatch;
- bool found_it = false;
-
- // First step is to look and see if we are in one of the known ObjC dispatch functions. We've already compiled
- // a table of same, so consult it.
-
- MsgsendMap::iterator pos;
- pos = m_msgSend_map.find (curr_pc);
- if (pos != m_msgSend_map.end())
- {
- this_dispatch = g_dispatch_functions[(*pos).second];
- found_it = true;
+AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
+ bool stop_others) {
+ ThreadPlanSP ret_plan_sp;
+ lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
+
+ DispatchFunction this_dispatch;
+ bool found_it = false;
+
+ // First step is to look and see if we are in one of the known ObjC dispatch
+ // functions. We've already compiled
+ // a table of same, so consult it.
+
+ MsgsendMap::iterator pos;
+ pos = m_msgSend_map.find(curr_pc);
+ if (pos != m_msgSend_map.end()) {
+ this_dispatch = g_dispatch_functions[(*pos).second];
+ found_it = true;
+ }
+
+ // Next check to see if we are in a vtable region:
+
+ if (!found_it) {
+ uint32_t flags;
+ if (m_vtables_ap.get()) {
+ found_it = m_vtables_ap->IsAddressInVTables(curr_pc, flags);
+ if (found_it) {
+ this_dispatch.name = "vtable";
+ this_dispatch.stret_return =
+ (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) ==
+ AppleObjCVTables::eOBJC_TRAMPOLINE_STRET;
+ this_dispatch.is_super = false;
+ this_dispatch.is_super2 = false;
+ this_dispatch.fixedup = DispatchFunction::eFixUpFixed;
+ }
}
-
- // Next check to see if we are in a vtable region:
-
- if (!found_it)
- {
- uint32_t flags;
- if (m_vtables_ap.get())
- {
- found_it = m_vtables_ap->IsAddressInVTables (curr_pc, flags);
- if (found_it)
- {
- this_dispatch.name = "vtable";
- this_dispatch.stret_return
- = (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == AppleObjCVTables::eOBJC_TRAMPOLINE_STRET;
- this_dispatch.is_super = false;
- this_dispatch.is_super2 = false;
- this_dispatch.fixedup = DispatchFunction::eFixUpFixed;
- }
- }
+ }
+
+ if (found_it) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ // We are decoding a method dispatch.
+ // First job is to pull the arguments out:
+
+ lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
+
+ const ABI *abi = NULL;
+ ProcessSP process_sp(thread.CalculateProcess());
+ if (process_sp)
+ abi = process_sp->GetABI().get();
+ if (abi == NULL)
+ return ret_plan_sp;
+
+ TargetSP target_sp(thread.CalculateTarget());
+
+ ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
+ ValueList argument_values;
+ Value void_ptr_value;
+ CompilerType clang_void_ptr_type =
+ clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ void_ptr_value.SetValueType(Value::eValueTypeScalar);
+ // void_ptr_value.SetContext (Value::eContextTypeClangType,
+ // clang_void_ptr_type);
+ void_ptr_value.SetCompilerType(clang_void_ptr_type);
+
+ int obj_index;
+ int sel_index;
+
+ // If this is a struct return dispatch, then the first argument is the
+ // return struct pointer, and the object is the second, and the selector is
+ // the third.
+ // Otherwise the object is the first and the selector the second.
+ if (this_dispatch.stret_return) {
+ obj_index = 1;
+ sel_index = 2;
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
+ } else {
+ obj_index = 0;
+ sel_index = 1;
+ argument_values.PushValue(void_ptr_value);
+ argument_values.PushValue(void_ptr_value);
}
-
- if (found_it)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- // We are decoding a method dispatch.
- // First job is to pull the arguments out:
-
- lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
-
- const ABI *abi = NULL;
- ProcessSP process_sp (thread.CalculateProcess());
- if (process_sp)
- abi = process_sp->GetABI().get();
- if (abi == NULL)
- return ret_plan_sp;
-
- TargetSP target_sp (thread.CalculateTarget());
-
- ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
- ValueList argument_values;
- Value void_ptr_value;
- CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- void_ptr_value.SetValueType (Value::eValueTypeScalar);
- //void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
- void_ptr_value.SetCompilerType (clang_void_ptr_type);
-
- int obj_index;
- int sel_index;
-
- // If this is a struct return dispatch, then the first argument is the
- // return struct pointer, and the object is the second, and the selector is the third.
- // Otherwise the object is the first and the selector the second.
- if (this_dispatch.stret_return)
- {
- obj_index = 1;
- sel_index = 2;
- argument_values.PushValue(void_ptr_value);
- argument_values.PushValue(void_ptr_value);
- argument_values.PushValue(void_ptr_value);
- }
- else
- {
- obj_index = 0;
- sel_index = 1;
- argument_values.PushValue(void_ptr_value);
- argument_values.PushValue(void_ptr_value);
- }
+ bool success = abi->GetArgumentValues(thread, argument_values);
+ if (!success)
+ return ret_plan_sp;
-
- bool success = abi->GetArgumentValues (thread, argument_values);
- if (!success)
- return ret_plan_sp;
-
- lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong();
- if (obj_addr == 0x0)
- {
- if (log)
- log->Printf("Asked to step to dispatch to nil object, returning empty plan.");
- return ret_plan_sp;
- }
-
- ExecutionContext exe_ctx (thread.shared_from_this());
- Process *process = exe_ctx.GetProcessPtr();
- // isa_addr will store the class pointer that the method is being dispatched to - so either the class
- // directly or the super class if this is one of the objc_msgSendSuper flavors. That's mostly used to
- // look up the class/selector pair in our cache.
-
- lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
- lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
-
- // Figure out the class this is being dispatched to and see if we've already cached this method call,
- // If so we can push a run-to-address plan directly. Otherwise we have to figure out where
- // the implementation lives.
-
- if (this_dispatch.is_super)
- {
- if (this_dispatch.is_super2)
- {
- // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing
- // the object and the class to which the super message is being sent. So we need to dig the super
- // out of the class and use that.
-
- Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
- super_value.GetScalar() += process->GetAddressByteSize();
- super_value.ResolveValue (&exe_ctx);
-
- if (super_value.GetScalar().IsValid())
- {
-
- // isa_value now holds the class pointer. The second word of the class pointer is the super-class pointer:
- super_value.GetScalar() += process->GetAddressByteSize();
- super_value.ResolveValue (&exe_ctx);
- if (super_value.GetScalar().IsValid())
- isa_addr = super_value.GetScalar().ULongLong();
- else
- {
- if (log)
- log->Printf("Failed to extract the super class value from the class in objc_super.");
- }
- }
- else
- {
- if (log)
- log->Printf("Failed to extract the class value from objc_super.");
- }
- }
- else
- {
- // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing
- // the object and the super class to which the super message is being sent. So the class we want is
- // the second element of this structure.
-
- Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
- super_value.GetScalar() += process->GetAddressByteSize();
- super_value.ResolveValue (&exe_ctx);
-
- if (super_value.GetScalar().IsValid())
- {
- isa_addr = super_value.GetScalar().ULongLong();
- }
- else
- {
- if (log)
- log->Printf("Failed to extract the class value from objc_super.");
- }
- }
- }
- else
- {
- // In the direct dispatch case, the object->isa is the class pointer we want.
-
- // This is a little cheesy, but since object->isa is the first field,
- // making the object value a load address value and resolving it will get
- // the pointer sized data pointed to by that value...
-
- // Note, it isn't a fatal error not to be able to get the address from the object, since this might
- // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus.
-
- Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
-
- isa_value.SetValueType(Value::eValueTypeLoadAddress);
- isa_value.ResolveValue(&exe_ctx);
- if (isa_value.GetScalar().IsValid())
- {
- isa_addr = isa_value.GetScalar().ULongLong();
- }
- else
- {
- if (log)
- log->Printf("Failed to extract the isa value from object.");
- }
-
- }
-
- // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache:
- lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
-
- if (isa_addr != LLDB_INVALID_ADDRESS)
- {
- if (log)
- {
- log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
- isa_addr, sel_addr);
- }
- ObjCLanguageRuntime *objc_runtime = thread.GetProcess()->GetObjCLanguageRuntime ();
- assert(objc_runtime != NULL);
-
- impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
- }
-
- if (impl_addr != LLDB_INVALID_ADDRESS)
- {
- // Yup, it was in the cache, so we can run to that address directly.
-
- if (log)
- log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
-
- ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
- }
- else
- {
- // We haven't seen this class/selector pair yet. Look it up.
- StreamString errors;
- Address impl_code_address;
-
- ValueList dispatch_values;
-
- // We've will inject a little function in the target that takes the object, selector and some flags,
- // and figures out the implementation. Looks like:
- // void *__lldb_objc_find_implementation_for_selector (void *object,
- // void *sel,
- // int is_stret,
- // int is_super,
- // int is_super2,
- // int is_fixup,
- // int is_fixed,
- // int debug)
- // So set up the arguments for that call.
-
- dispatch_values.PushValue (*(argument_values.GetValueAtIndex(obj_index)));
- dispatch_values.PushValue (*(argument_values.GetValueAtIndex(sel_index)));
-
- Value flag_value;
- CompilerType clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingSint, 32);
- flag_value.SetValueType (Value::eValueTypeScalar);
- //flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
- flag_value.SetCompilerType (clang_int_type);
-
- if (this_dispatch.stret_return)
- flag_value.GetScalar() = 1;
- else
- flag_value.GetScalar() = 0;
- dispatch_values.PushValue (flag_value);
-
- if (this_dispatch.is_super)
- flag_value.GetScalar() = 1;
- else
- flag_value.GetScalar() = 0;
- dispatch_values.PushValue (flag_value);
-
- if (this_dispatch.is_super2)
- flag_value.GetScalar() = 1;
- else
- flag_value.GetScalar() = 0;
- dispatch_values.PushValue (flag_value);
-
- switch (this_dispatch.fixedup)
- {
- case DispatchFunction::eFixUpNone:
- flag_value.GetScalar() = 0;
- dispatch_values.PushValue (flag_value);
- dispatch_values.PushValue (flag_value);
- break;
- case DispatchFunction::eFixUpFixed:
- flag_value.GetScalar() = 1;
- dispatch_values.PushValue (flag_value);
- flag_value.GetScalar() = 1;
- dispatch_values.PushValue (flag_value);
- break;
- case DispatchFunction::eFixUpToFix:
- flag_value.GetScalar() = 1;
- dispatch_values.PushValue (flag_value);
- flag_value.GetScalar() = 0;
- dispatch_values.PushValue (flag_value);
- break;
- }
- if (log && log->GetVerbose())
- flag_value.GetScalar() = 1;
- else
- flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
- dispatch_values.PushValue (flag_value);
-
-
- // The step through code might have to fill in the cache, so it is not safe to run only one thread.
- // So we override the stop_others value passed in to us here:
- const bool trampoline_stop_others = false;
- ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
- this,
- dispatch_values,
- isa_addr,
- sel_addr,
- trampoline_stop_others));
- if (log)
- {
- StreamString s;
- ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
- log->Printf("Using ObjC step plan: %s.\n", s.GetData());
- }
- }
+ lldb::addr_t obj_addr =
+ argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong();
+ if (obj_addr == 0x0) {
+ if (log)
+ log->Printf(
+ "Asked to step to dispatch to nil object, returning empty plan.");
+ return ret_plan_sp;
}
-
- return ret_plan_sp;
+
+ ExecutionContext exe_ctx(thread.shared_from_this());
+ Process *process = exe_ctx.GetProcessPtr();
+ // isa_addr will store the class pointer that the method is being dispatched
+ // to - so either the class
+ // directly or the super class if this is one of the objc_msgSendSuper
+ // flavors. That's mostly used to
+ // look up the class/selector pair in our cache.
+
+ lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t sel_addr =
+ argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
+
+ // Figure out the class this is being dispatched to and see if we've already
+ // cached this method call,
+ // If so we can push a run-to-address plan directly. Otherwise we have to
+ // figure out where
+ // the implementation lives.
+
+ if (this_dispatch.is_super) {
+ if (this_dispatch.is_super2) {
+ // In the objc_msgSendSuper2 case, we don't get the object directly, we
+ // get a structure containing
+ // the object and the class to which the super message is being sent.
+ // So we need to dig the super
+ // out of the class and use that.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue(&exe_ctx);
+
+ if (super_value.GetScalar().IsValid()) {
+
+ // isa_value now holds the class pointer. The second word of the
+ // class pointer is the super-class pointer:
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue(&exe_ctx);
+ if (super_value.GetScalar().IsValid())
+ isa_addr = super_value.GetScalar().ULongLong();
+ else {
+ if (log)
+ log->Printf("Failed to extract the super class value from the "
+ "class in objc_super.");
+ }
+ } else {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ } else {
+ // In the objc_msgSendSuper case, we don't get the object directly, we
+ // get a two element structure containing
+ // the object and the super class to which the super message is being
+ // sent. So the class we want is
+ // the second element of this structure.
+
+ Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
+ super_value.GetScalar() += process->GetAddressByteSize();
+ super_value.ResolveValue(&exe_ctx);
+
+ if (super_value.GetScalar().IsValid()) {
+ isa_addr = super_value.GetScalar().ULongLong();
+ } else {
+ if (log)
+ log->Printf("Failed to extract the class value from objc_super.");
+ }
+ }
+ } else {
+ // In the direct dispatch case, the object->isa is the class pointer we
+ // want.
+
+ // This is a little cheesy, but since object->isa is the first field,
+ // making the object value a load address value and resolving it will get
+ // the pointer sized data pointed to by that value...
+
+ // Note, it isn't a fatal error not to be able to get the address from the
+ // object, since this might
+ // be a "tagged pointer" which isn't a real object, but rather some word
+ // length encoded dingus.
+
+ Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
+
+ isa_value.SetValueType(Value::eValueTypeLoadAddress);
+ isa_value.ResolveValue(&exe_ctx);
+ if (isa_value.GetScalar().IsValid()) {
+ isa_addr = isa_value.GetScalar().ULongLong();
+ } else {
+ if (log)
+ log->Printf("Failed to extract the isa value from object.");
+ }
+ }
+
+ // Okay, we've got the address of the class for which we're resolving this,
+ // let's see if it's in our cache:
+ lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
+
+ if (isa_addr != LLDB_INVALID_ADDRESS) {
+ if (log) {
+ log->Printf("Resolving call for class - 0x%" PRIx64
+ " and selector - 0x%" PRIx64,
+ isa_addr, sel_addr);
+ }
+ ObjCLanguageRuntime *objc_runtime =
+ thread.GetProcess()->GetObjCLanguageRuntime();
+ assert(objc_runtime != NULL);
+
+ impl_addr = objc_runtime->LookupInMethodCache(isa_addr, sel_addr);
+ }
+
+ if (impl_addr != LLDB_INVALID_ADDRESS) {
+ // Yup, it was in the cache, so we can run to that address directly.
+
+ if (log)
+ log->Printf("Found implementation address in cache: 0x%" PRIx64,
+ impl_addr);
+
+ ret_plan_sp.reset(
+ new ThreadPlanRunToAddress(thread, impl_addr, stop_others));
+ } else {
+ // We haven't seen this class/selector pair yet. Look it up.
+ StreamString errors;
+ Address impl_code_address;
+
+ ValueList dispatch_values;
+
+ // We've will inject a little function in the target that takes the
+ // object, selector and some flags,
+ // and figures out the implementation. Looks like:
+ // void *__lldb_objc_find_implementation_for_selector (void *object,
+ // void *sel,
+ // int is_stret,
+ // int is_super,
+ // int is_super2,
+ // int is_fixup,
+ // int is_fixed,
+ // int debug)
+ // So set up the arguments for that call.
+
+ dispatch_values.PushValue(*(argument_values.GetValueAtIndex(obj_index)));
+ dispatch_values.PushValue(*(argument_values.GetValueAtIndex(sel_index)));
+
+ Value flag_value;
+ CompilerType clang_int_type =
+ clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
+ lldb::eEncodingSint, 32);
+ flag_value.SetValueType(Value::eValueTypeScalar);
+ // flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
+ flag_value.SetCompilerType(clang_int_type);
+
+ if (this_dispatch.stret_return)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue(flag_value);
+
+ if (this_dispatch.is_super)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue(flag_value);
+
+ if (this_dispatch.is_super2)
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue(flag_value);
+
+ switch (this_dispatch.fixedup) {
+ case DispatchFunction::eFixUpNone:
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue(flag_value);
+ dispatch_values.PushValue(flag_value);
+ break;
+ case DispatchFunction::eFixUpFixed:
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue(flag_value);
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue(flag_value);
+ break;
+ case DispatchFunction::eFixUpToFix:
+ flag_value.GetScalar() = 1;
+ dispatch_values.PushValue(flag_value);
+ flag_value.GetScalar() = 0;
+ dispatch_values.PushValue(flag_value);
+ break;
+ }
+ if (log && log->GetVerbose())
+ flag_value.GetScalar() = 1;
+ else
+ flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
+ dispatch_values.PushValue(flag_value);
+
+ // The step through code might have to fill in the cache, so it is not
+ // safe to run only one thread.
+ // So we override the stop_others value passed in to us here:
+ const bool trampoline_stop_others = false;
+ ret_plan_sp.reset(new AppleThreadPlanStepThroughObjCTrampoline(
+ thread, this, dispatch_values, isa_addr, sel_addr,
+ trampoline_stop_others));
+ if (log) {
+ StreamString s;
+ ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
+ log->Printf("Using ObjC step plan: %s.\n", s.GetData());
+ }
+ }
+ }
+
+ return ret_plan_sp;
}
FunctionCaller *
-AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller ()
-{
- return m_impl_code->GetFunctionCaller();
+AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller() {
+ return m_impl_code->GetFunctionCaller();
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
index c0d1944..dc58a8b 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -18,190 +18,143 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-public.h"
#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/lldb-public.h"
-namespace lldb_private
-{
-
+namespace lldb_private {
+
class AppleObjCTrampolineHandler {
public:
- AppleObjCTrampolineHandler (const lldb::ProcessSP &process_sp,
- const lldb::ModuleSP &objc_module_sp);
-
- ~AppleObjCTrampolineHandler();
-
- lldb::ThreadPlanSP
- GetStepThroughDispatchPlan (Thread &thread,
- bool stop_others);
-
- FunctionCaller *
- GetLookupImplementationFunctionCaller ();
-
- bool
- AddrIsMsgForward (lldb::addr_t addr) const
- {
- return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr);
- }
+ AppleObjCTrampolineHandler(const lldb::ProcessSP &process_sp,
+ const lldb::ModuleSP &objc_module_sp);
- struct DispatchFunction {
- public:
- typedef enum
- {
- eFixUpNone,
- eFixUpFixed,
- eFixUpToFix
- } FixUpState;
-
- const char *name;
- bool stret_return;
- bool is_super;
- bool is_super2;
- FixUpState fixedup;
- };
+ ~AppleObjCTrampolineHandler();
- lldb::addr_t
- SetupDispatchFunction (Thread &thread, ValueList &dispatch_values);
+ lldb::ThreadPlanSP GetStepThroughDispatchPlan(Thread &thread,
+ bool stop_others);
+
+ FunctionCaller *GetLookupImplementationFunctionCaller();
+
+ bool AddrIsMsgForward(lldb::addr_t addr) const {
+ return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr);
+ }
+
+ struct DispatchFunction {
+ public:
+ typedef enum { eFixUpNone, eFixUpFixed, eFixUpToFix } FixUpState;
+
+ const char *name;
+ bool stret_return;
+ bool is_super;
+ bool is_super2;
+ FixUpState fixedup;
+ };
+
+ lldb::addr_t SetupDispatchFunction(Thread &thread,
+ ValueList &dispatch_values);
private:
- static const char *g_lookup_implementation_function_name;
- static const char *g_lookup_implementation_with_stret_function_code;
- static const char *g_lookup_implementation_no_stret_function_code;
+ static const char *g_lookup_implementation_function_name;
+ static const char *g_lookup_implementation_with_stret_function_code;
+ static const char *g_lookup_implementation_no_stret_function_code;
- class AppleObjCVTables
- {
- public:
- // These come from objc-gdb.h.
- enum VTableFlags
- {
- eOBJC_TRAMPOLINE_MESSAGE = (1<<0), // trampoline acts like objc_msgSend
- eOBJC_TRAMPOLINE_STRET = (1<<1), // trampoline is struct-returning
- eOBJC_TRAMPOLINE_VTABLE = (1<<2) // trampoline is vtable dispatcher
- };
-
- private:
- struct VTableDescriptor
- {
- VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start) :
- flags(in_flags),
- code_start(in_code_start) {}
-
- uint32_t flags;
- lldb::addr_t code_start;
- };
-
- class VTableRegion
- {
- public:
- VTableRegion() :
- m_valid (false),
- m_owner (NULL),
- m_header_addr (LLDB_INVALID_ADDRESS),
- m_code_start_addr(0),
- m_code_end_addr (0),
- m_next_region (0)
- {}
-
- VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
-
- void SetUpRegion();
-
- lldb::addr_t GetNextRegionAddr ()
- {
- return m_next_region;
- }
-
- lldb::addr_t
- GetCodeStart ()
- {
- return m_code_start_addr;
- }
-
- lldb::addr_t
- GetCodeEnd ()
- {
- return m_code_end_addr;
- }
-
- uint32_t
- GetFlagsForVTableAtAddress (lldb::addr_t address)
- {
- return 0;
- }
-
- bool
- IsValid ()
- {
- return m_valid;
- }
-
- bool
- AddressInRegion (lldb::addr_t addr, uint32_t &flags);
-
- void
- Dump (Stream &s);
-
- public:
- bool m_valid;
- AppleObjCVTables *m_owner;
- lldb::addr_t m_header_addr;
- lldb::addr_t m_code_start_addr;
- lldb::addr_t m_code_end_addr;
- std::vector<VTableDescriptor> m_descriptors;
- lldb::addr_t m_next_region;
- };
-
- public:
- AppleObjCVTables(const lldb::ProcessSP &process_sp,
- const lldb::ModuleSP &objc_module_sp);
-
- ~AppleObjCVTables();
-
- bool
- InitializeVTableSymbols ();
-
- static bool RefreshTrampolines (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
- bool
- ReadRegions ();
-
- bool
- ReadRegions (lldb::addr_t region_addr);
-
- bool
- IsAddressInVTables (lldb::addr_t addr, uint32_t &flags);
-
- lldb::ProcessSP
- GetProcessSP ()
- {
- return m_process_wp.lock();
- }
-
- private:
- lldb::ProcessWP m_process_wp;
- typedef std::vector<VTableRegion> region_collection;
- lldb::addr_t m_trampoline_header;
- lldb::break_id_t m_trampolines_changed_bp_id;
- region_collection m_regions;
- lldb::ModuleSP m_objc_module_sp;
+ class AppleObjCVTables {
+ public:
+ // These come from objc-gdb.h.
+ enum VTableFlags {
+ eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend
+ eOBJC_TRAMPOLINE_STRET = (1 << 1), // trampoline is struct-returning
+ eOBJC_TRAMPOLINE_VTABLE = (1 << 2) // trampoline is vtable dispatcher
};
-
- static const DispatchFunction g_dispatch_functions[];
-
- typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch fn address to the index in g_dispatch_functions
- MsgsendMap m_msgSend_map;
+
+ private:
+ struct VTableDescriptor {
+ VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start)
+ : flags(in_flags), code_start(in_code_start) {}
+
+ uint32_t flags;
+ lldb::addr_t code_start;
+ };
+
+ class VTableRegion {
+ public:
+ VTableRegion()
+ : m_valid(false), m_owner(NULL), m_header_addr(LLDB_INVALID_ADDRESS),
+ m_code_start_addr(0), m_code_end_addr(0), m_next_region(0) {}
+
+ VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
+
+ void SetUpRegion();
+
+ lldb::addr_t GetNextRegionAddr() { return m_next_region; }
+
+ lldb::addr_t GetCodeStart() { return m_code_start_addr; }
+
+ lldb::addr_t GetCodeEnd() { return m_code_end_addr; }
+
+ uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; }
+
+ bool IsValid() { return m_valid; }
+
+ bool AddressInRegion(lldb::addr_t addr, uint32_t &flags);
+
+ void Dump(Stream &s);
+
+ public:
+ bool m_valid;
+ AppleObjCVTables *m_owner;
+ lldb::addr_t m_header_addr;
+ lldb::addr_t m_code_start_addr;
+ lldb::addr_t m_code_end_addr;
+ std::vector<VTableDescriptor> m_descriptors;
+ lldb::addr_t m_next_region;
+ };
+
+ public:
+ AppleObjCVTables(const lldb::ProcessSP &process_sp,
+ const lldb::ModuleSP &objc_module_sp);
+
+ ~AppleObjCVTables();
+
+ bool InitializeVTableSymbols();
+
+ static bool RefreshTrampolines(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+ bool ReadRegions();
+
+ bool ReadRegions(lldb::addr_t region_addr);
+
+ bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags);
+
+ lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); }
+
+ private:
lldb::ProcessWP m_process_wp;
+ typedef std::vector<VTableRegion> region_collection;
+ lldb::addr_t m_trampoline_header;
+ lldb::break_id_t m_trampolines_changed_bp_id;
+ region_collection m_regions;
lldb::ModuleSP m_objc_module_sp;
- const char *m_lookup_implementation_function_code;
- std::unique_ptr<UtilityFunction> m_impl_code;
- std::mutex m_impl_function_mutex;
- lldb::addr_t m_impl_fn_addr;
- lldb::addr_t m_impl_stret_fn_addr;
- lldb::addr_t m_msg_forward_addr;
- lldb::addr_t m_msg_forward_stret_addr;
- std::unique_ptr<AppleObjCVTables> m_vtables_ap;
+ };
+
+ static const DispatchFunction g_dispatch_functions[];
+
+ typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch
+ // fn address to the index in
+ // g_dispatch_functions
+ MsgsendMap m_msgSend_map;
+ lldb::ProcessWP m_process_wp;
+ lldb::ModuleSP m_objc_module_sp;
+ const char *m_lookup_implementation_function_code;
+ std::unique_ptr<UtilityFunction> m_impl_code;
+ std::mutex m_impl_function_mutex;
+ lldb::addr_t m_impl_fn_addr;
+ lldb::addr_t m_impl_stret_fn_addr;
+ lldb::addr_t m_msg_forward_addr;
+ lldb::addr_t m_msg_forward_stret_addr;
+ std::unique_ptr<AppleObjCVTables> m_vtables_ap;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index d4adc09..ce78d4d 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -21,379 +21,377 @@
using namespace lldb_private;
using namespace lldb_utility;
-AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime) :
- ObjCLanguageRuntime::EncodingToType(),
- m_runtime(runtime)
-{
- if (!m_scratch_ast_ctx_ap)
- m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().str().c_str()));
+AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser(
+ ObjCLanguageRuntime &runtime)
+ : ObjCLanguageRuntime::EncodingToType(), m_runtime(runtime) {
+ if (!m_scratch_ast_ctx_ap)
+ m_scratch_ast_ctx_ap.reset(new ClangASTContext(runtime.GetProcess()
+ ->GetTarget()
+ .GetArchitecture()
+ .GetTriple()
+ .str()
+ .c_str()));
}
std::string
-AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer& type)
-{
- StreamString buffer;
- while (type.HasAtLeast(1) && type.Peek() != '=')
- buffer.Printf("%c",type.Next());
- return buffer.GetString();
+AppleObjCTypeEncodingParser::ReadStructName(lldb_utility::StringLexer &type) {
+ StreamString buffer;
+ while (type.HasAtLeast(1) && type.Peek() != '=')
+ buffer.Printf("%c", type.Next());
+ return buffer.GetString();
}
std::string
-AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer& type)
-{
- StreamString buffer;
- while (type.HasAtLeast(1) && type.Peek() != '"')
- buffer.Printf("%c",type.Next());
- StringLexer::Character next = type.Next();
- UNUSED_IF_ASSERT_DISABLED(next);
- assert (next == '"');
- return buffer.GetString();
+AppleObjCTypeEncodingParser::ReadQuotedString(lldb_utility::StringLexer &type) {
+ StreamString buffer;
+ while (type.HasAtLeast(1) && type.Peek() != '"')
+ buffer.Printf("%c", type.Next());
+ StringLexer::Character next = type.Next();
+ UNUSED_IF_ASSERT_DISABLED(next);
+ assert(next == '"');
+ return buffer.GetString();
}
uint32_t
-AppleObjCTypeEncodingParser::ReadNumber (lldb_utility::StringLexer& type)
-{
- uint32_t total = 0;
- while (type.HasAtLeast(1) && isdigit(type.Peek()))
- total = 10*total + (type.Next() - '0');
- return total;
+AppleObjCTypeEncodingParser::ReadNumber(lldb_utility::StringLexer &type) {
+ uint32_t total = 0;
+ while (type.HasAtLeast(1) && isdigit(type.Peek()))
+ total = 10 * total + (type.Next() - '0');
+ return total;
}
-// as an extension to the published grammar recent runtimes emit structs like this:
+// as an extension to the published grammar recent runtimes emit structs like
+// this:
// "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}"
-AppleObjCTypeEncodingParser::StructElement::StructElement() :
-name(""),
-type(clang::QualType()),
-bitfield(0)
-{}
+AppleObjCTypeEncodingParser::StructElement::StructElement()
+ : name(""), type(clang::QualType()), bitfield(0) {}
AppleObjCTypeEncodingParser::StructElement
-AppleObjCTypeEncodingParser::ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
-{
- StructElement retval;
- if (type.NextIf('"'))
- retval.name = ReadQuotedString(type);
- if (!type.NextIf('"'))
- return retval;
- uint32_t bitfield_size = 0;
- retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size);
- retval.bitfield = bitfield_size;
+AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression) {
+ StructElement retval;
+ if (type.NextIf('"'))
+ retval.name = ReadQuotedString(type);
+ if (!type.NextIf('"'))
return retval;
+ uint32_t bitfield_size = 0;
+ retval.type = BuildType(ast_ctx, type, for_expression, &bitfield_size);
+ retval.bitfield = bitfield_size;
+ return retval;
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
-{
- return BuildAggregate(ast_ctx, type, for_expression, '{', '}', clang::TTK_Struct);
+AppleObjCTypeEncodingParser::BuildStruct(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression) {
+ return BuildAggregate(ast_ctx, type, for_expression, '{', '}',
+ clang::TTK_Struct);
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
-{
- return BuildAggregate(ast_ctx, type, for_expression, '(', ')', clang::TTK_Union);
+AppleObjCTypeEncodingParser::BuildUnion(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression) {
+ return BuildAggregate(ast_ctx, type, for_expression, '(', ')',
+ clang::TTK_Union);
}
-clang::QualType
-AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, char opener, char closer, uint32_t kind)
-{
- if (!type.NextIf(opener))
- return clang::QualType();
- std::string name(ReadStructName(type));
-
- // We do not handle templated classes/structs at the moment.
- // If the name has a < in it, we are going to abandon this.
- // We're still obliged to parse it, so we just set a flag that
- // means "Don't actually build anything."
-
- const bool is_templated = name.find('<') != std::string::npos;
-
- if (!type.NextIf('='))
- return clang::QualType();
- bool in_union = true;
- std::vector<StructElement> elements;
- while (in_union && type.HasAtLeast(1))
- {
- if (type.NextIf(closer))
- {
- in_union = false;
- break;
- }
- else
- {
- auto element = ReadStructElement(ast_ctx, type, for_expression);
- if (element.type.isNull())
- break;
- else
- elements.push_back(element);
- }
+clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
+ clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type,
+ bool for_expression, char opener, char closer, uint32_t kind) {
+ if (!type.NextIf(opener))
+ return clang::QualType();
+ std::string name(ReadStructName(type));
+
+ // We do not handle templated classes/structs at the moment.
+ // If the name has a < in it, we are going to abandon this.
+ // We're still obliged to parse it, so we just set a flag that
+ // means "Don't actually build anything."
+
+ const bool is_templated = name.find('<') != std::string::npos;
+
+ if (!type.NextIf('='))
+ return clang::QualType();
+ bool in_union = true;
+ std::vector<StructElement> elements;
+ while (in_union && type.HasAtLeast(1)) {
+ if (type.NextIf(closer)) {
+ in_union = false;
+ break;
+ } else {
+ auto element = ReadStructElement(ast_ctx, type, for_expression);
+ if (element.type.isNull())
+ break;
+ else
+ elements.push_back(element);
}
- if (in_union)
- return clang::QualType();
-
- if (is_templated)
- return clang::QualType(); // This is where we bail out. Sorry!
-
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType union_type(lldb_ctx->CreateRecordType(nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
- if (union_type)
- {
- ClangASTContext::StartTagDeclarationDefinition(union_type);
-
- unsigned int count = 0;
- for (auto element: elements)
- {
- if (element.name.empty())
- {
- StreamString elem_name;
- elem_name.Printf("__unnamed_%u",count);
- element.name = std::string(elem_name.GetData());
- }
- ClangASTContext::AddFieldToRecordType(union_type, element.name.c_str(), CompilerType(&ast_ctx, element.type), lldb::eAccessPublic, element.bitfield);
- ++count;
- }
- ClangASTContext::CompleteTagDeclarationDefinition(union_type);
+ }
+ if (in_union)
+ return clang::QualType();
+
+ if (is_templated)
+ return clang::QualType(); // This is where we bail out. Sorry!
+
+ ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ if (!lldb_ctx)
+ return clang::QualType();
+ CompilerType union_type(lldb_ctx->CreateRecordType(
+ nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
+ if (union_type) {
+ ClangASTContext::StartTagDeclarationDefinition(union_type);
+
+ unsigned int count = 0;
+ for (auto element : elements) {
+ if (element.name.empty()) {
+ StreamString elem_name;
+ elem_name.Printf("__unnamed_%u", count);
+ element.name = std::string(elem_name.GetData());
+ }
+ ClangASTContext::AddFieldToRecordType(
+ union_type, element.name.c_str(),
+ CompilerType(&ast_ctx, element.type), lldb::eAccessPublic,
+ element.bitfield);
+ ++count;
}
- return ClangUtil::GetQualType(union_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(union_type);
+ }
+ return ClangUtil::GetQualType(union_type);
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
-{
- if (!type.NextIf('['))
- return clang::QualType();
- uint32_t size = ReadNumber(type);
- clang::QualType element_type(BuildType(ast_ctx, type, for_expression));
- if (!type.NextIf(']'))
- return clang::QualType();
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType array_type(lldb_ctx->CreateArrayType(CompilerType(&ast_ctx, element_type), size, false));
- return ClangUtil::GetQualType(array_type);
+AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression) {
+ if (!type.NextIf('['))
+ return clang::QualType();
+ uint32_t size = ReadNumber(type);
+ clang::QualType element_type(BuildType(ast_ctx, type, for_expression));
+ if (!type.NextIf(']'))
+ return clang::QualType();
+ ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ if (!lldb_ctx)
+ return clang::QualType();
+ CompilerType array_type(lldb_ctx->CreateArrayType(
+ CompilerType(&ast_ctx, element_type), size, false));
+ return ClangUtil::GetQualType(array_type);
}
// the runtime can emit these in the form of @"SomeType", giving more specifics
-// this would be interesting for expression parser interop, but since we actually try
-// to avoid exposing the ivar info to the expression evaluator, consume but ignore the type info
-// and always return an 'id'; if anything, dynamic typing will resolve things for us anyway
-clang::QualType
-AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression)
-{
- if (!type.NextIf('@'))
- return clang::QualType();
-
- std::string name;
-
- if (type.NextIf('"'))
- {
- // We have to be careful here. We're used to seeing
- // @"NSString"
- // but in records it is possible that the string following an @ is the name of the next field and @ means "id".
- // This is the case if anything unquoted except for "}", the end of the type, or another name follows the quoted string.
- //
- // E.g.
- // - @"NSString"@ means "id, followed by a field named NSString of type id"
- // - @"NSString"} means "a pointer to NSString and the end of the struct"
- // - @"NSString""nextField" means "a pointer to NSString and a field named nextField"
- // - @"NSString" followed by the end of the string means "a pointer to NSString"
- //
- // As a result, the rule is: If we see @ followed by a quoted string, we peek.
- // - If we see }, ), ], the end of the string, or a quote ("), the quoted string is a class name.
- // - If we see anything else, the quoted string is a field name and we push it back onto type.
+// this would be interesting for expression parser interop, but since we
+// actually try
+// to avoid exposing the ivar info to the expression evaluator, consume but
+// ignore the type info
+// and always return an 'id'; if anything, dynamic typing will resolve things
+// for us anyway
+clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
+ clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type,
+ bool for_expression) {
+ if (!type.NextIf('@'))
+ return clang::QualType();
- name = ReadQuotedString(type);
-
- if (type.HasAtLeast(1))
- {
- switch (type.Peek())
- {
- default:
- // roll back
- type.PutBack(name.length() + 2); // undo our consumption of the string and of the quotes
- name.clear();
- break;
- case '}':
- case ')':
- case ']':
- case '"':
- // the quoted string is a class name – see the rule
- break;
- }
- }
- else
- {
- // the quoted string is a class name – see the rule
- }
+ std::string name;
+
+ if (type.NextIf('"')) {
+ // We have to be careful here. We're used to seeing
+ // @"NSString"
+ // but in records it is possible that the string following an @ is the name
+ // of the next field and @ means "id".
+ // This is the case if anything unquoted except for "}", the end of the
+ // type, or another name follows the quoted string.
+ //
+ // E.g.
+ // - @"NSString"@ means "id, followed by a field named NSString of type id"
+ // - @"NSString"} means "a pointer to NSString and the end of the struct"
+ // - @"NSString""nextField" means "a pointer to NSString and a field named
+ // nextField"
+ // - @"NSString" followed by the end of the string means "a pointer to
+ // NSString"
+ //
+ // As a result, the rule is: If we see @ followed by a quoted string, we
+ // peek.
+ // - If we see }, ), ], the end of the string, or a quote ("), the quoted
+ // string is a class name.
+ // - If we see anything else, the quoted string is a field name and we push
+ // it back onto type.
+
+ name = ReadQuotedString(type);
+
+ if (type.HasAtLeast(1)) {
+ switch (type.Peek()) {
+ default:
+ // roll back
+ type.PutBack(name.length() +
+ 2); // undo our consumption of the string and of the quotes
+ name.clear();
+ break;
+ case '}':
+ case ')':
+ case ']':
+ case '"':
+ // the quoted string is a class name – see the rule
+ break;
+ }
+ } else {
+ // the quoted string is a class name – see the rule
}
-
- if (for_expression && !name.empty())
- {
- size_t less_than_pos = name.find('<');
-
- if (less_than_pos != std::string::npos)
- {
- if (less_than_pos == 0)
- return ast_ctx.getObjCIdType();
- else
- name.erase(less_than_pos);
- }
-
- DeclVendor *decl_vendor = m_runtime.GetDeclVendor();
-
- assert (decl_vendor); // how are we parsing type encodings for expressions if a type vendor isn't in play?
-
- const bool append = false;
- const uint32_t max_matches = 1;
- std::vector<clang::NamedDecl *> decls;
-
- uint32_t num_types = decl_vendor->FindDecls(ConstString(name),
- append,
- max_matches,
- decls);
+ }
- // The user can forward-declare something that has no definition. The runtime doesn't prohibit this at all.
- // This is a rare and very weird case. We keep this assert in debug builds so we catch other weird cases.
+ if (for_expression && !name.empty()) {
+ size_t less_than_pos = name.find('<');
+
+ if (less_than_pos != std::string::npos) {
+ if (less_than_pos == 0)
+ return ast_ctx.getObjCIdType();
+ else
+ name.erase(less_than_pos);
+ }
+
+ DeclVendor *decl_vendor = m_runtime.GetDeclVendor();
+
+ assert(decl_vendor); // how are we parsing type encodings for expressions if
+ // a type vendor isn't in play?
+
+ const bool append = false;
+ const uint32_t max_matches = 1;
+ std::vector<clang::NamedDecl *> decls;
+
+ uint32_t num_types =
+ decl_vendor->FindDecls(ConstString(name), append, max_matches, decls);
+
+// The user can forward-declare something that has no definition. The runtime
+// doesn't prohibit this at all.
+// This is a rare and very weird case. We keep this assert in debug builds so
+// we catch other weird cases.
#ifdef LLDB_CONFIGURATION_DEBUG
- assert(num_types);
+ assert(num_types);
#else
- if (!num_types)
- return ast_ctx.getObjCIdType();
+ if (!num_types)
+ return ast_ctx.getObjCIdType();
#endif
- return ClangUtil::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType());
- }
- else
- {
- // We're going to resolve this dynamically anyway, so just smile and wave.
- return ast_ctx.getObjCIdType();
- }
+ return ClangUtil::GetQualType(
+ ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType());
+ } else {
+ // We're going to resolve this dynamically anyway, so just smile and wave.
+ return ast_ctx.getObjCIdType();
+ }
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildType (clang::ASTContext &ast_ctx, StringLexer& type, bool for_expression, uint32_t *bitfield_bit_size)
-{
- if (!type.HasAtLeast(1))
+AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
+ StringLexer &type, bool for_expression,
+ uint32_t *bitfield_bit_size) {
+ if (!type.HasAtLeast(1))
+ return clang::QualType();
+
+ switch (type.Peek()) {
+ default:
+ break;
+ case '{':
+ return BuildStruct(ast_ctx, type, for_expression);
+ case '[':
+ return BuildArray(ast_ctx, type, for_expression);
+ case '(':
+ return BuildUnion(ast_ctx, type, for_expression);
+ case '@':
+ return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
+ }
+
+ switch (type.Next()) {
+ default:
+ type.PutBack(1);
+ return clang::QualType();
+ case 'c':
+ return ast_ctx.CharTy;
+ case 'i':
+ return ast_ctx.IntTy;
+ case 's':
+ return ast_ctx.ShortTy;
+ case 'l':
+ return ast_ctx.getIntTypeForBitwidth(32, true);
+ // this used to be done like this:
+ // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
+ // if (!lldb_ctx)
+ // return clang::QualType();
+ // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
+ // which uses one of the constants if one is available, but we don't think all
+ // this work is necessary.
+ case 'q':
+ return ast_ctx.LongLongTy;
+ case 'C':
+ return ast_ctx.UnsignedCharTy;
+ case 'I':
+ return ast_ctx.UnsignedIntTy;
+ case 'S':
+ return ast_ctx.UnsignedShortTy;
+ case 'L':
+ return ast_ctx.getIntTypeForBitwidth(32, false);
+ // see note for 'l'
+ case 'Q':
+ return ast_ctx.UnsignedLongLongTy;
+ case 'f':
+ return ast_ctx.FloatTy;
+ case 'd':
+ return ast_ctx.DoubleTy;
+ case 'B':
+ return ast_ctx.BoolTy;
+ case 'v':
+ return ast_ctx.VoidTy;
+ case '*':
+ return ast_ctx.getPointerType(ast_ctx.CharTy);
+ case '#':
+ return ast_ctx.getObjCClassType();
+ case ':':
+ return ast_ctx.getObjCSelType();
+ case 'b': {
+ uint32_t size = ReadNumber(type);
+ if (bitfield_bit_size) {
+ *bitfield_bit_size = size;
+ return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here.
+ } else
+ return clang::QualType();
+ }
+ case 'r': {
+ clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ if (target_type.isNull())
+ return clang::QualType();
+ else if (target_type == ast_ctx.UnknownAnyTy)
+ return ast_ctx.UnknownAnyTy;
+ else
+ return ast_ctx.getConstType(target_type);
+ }
+ case '^': {
+ if (!for_expression && type.NextIf('?')) {
+ // if we are not supporting the concept of unknownAny, but what is being
+ // created here is an unknownAny*, then
+ // we can just get away with a void*
+ // this is theoretically wrong (in the same sense as 'theoretically
+ // nothing exists') but is way better than outright failure
+ // in many practical cases
+ return ast_ctx.VoidPtrTy;
+ } else {
+ clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ if (target_type.isNull())
return clang::QualType();
-
- switch (type.Peek())
- {
- default:
- break;
- case '{':
- return BuildStruct(ast_ctx, type, for_expression);
- case '[':
- return BuildArray(ast_ctx, type, for_expression);
- case '(':
- return BuildUnion(ast_ctx, type, for_expression);
- case '@':
- return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
+ else if (target_type == ast_ctx.UnknownAnyTy)
+ return ast_ctx.UnknownAnyTy;
+ else
+ return ast_ctx.getPointerType(target_type);
}
-
- switch (type.Next())
- {
- default:
- type.PutBack(1);
- return clang::QualType();
- case 'c':
- return ast_ctx.CharTy;
- case 'i':
- return ast_ctx.IntTy;
- case 's':
- return ast_ctx.ShortTy;
- case 'l':
- return ast_ctx.getIntTypeForBitwidth(32, true);
- // this used to be done like this:
- // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- // if (!lldb_ctx)
- // return clang::QualType();
- // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
- // which uses one of the constants if one is available, but we don't think all this work is necessary.
- case 'q':
- return ast_ctx.LongLongTy;
- case 'C':
- return ast_ctx.UnsignedCharTy;
- case 'I':
- return ast_ctx.UnsignedIntTy;
- case 'S':
- return ast_ctx.UnsignedShortTy;
- case 'L':
- return ast_ctx.getIntTypeForBitwidth(32, false);
- // see note for 'l'
- case 'Q':
- return ast_ctx.UnsignedLongLongTy;
- case 'f':
- return ast_ctx.FloatTy;
- case 'd':
- return ast_ctx.DoubleTy;
- case 'B':
- return ast_ctx.BoolTy;
- case 'v':
- return ast_ctx.VoidTy;
- case '*':
- return ast_ctx.getPointerType(ast_ctx.CharTy);
- case '#':
- return ast_ctx.getObjCClassType();
- case ':':
- return ast_ctx.getObjCSelType();
- case 'b':
- {
- uint32_t size = ReadNumber(type);
- if (bitfield_bit_size)
- {
- *bitfield_bit_size = size;
- return ast_ctx.UnsignedIntTy; // FIXME: the spec is fairly vague here.
- }
- else
- return clang::QualType();
- }
- case 'r':
- {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
- if (target_type.isNull())
- return clang::QualType();
- else if (target_type == ast_ctx.UnknownAnyTy)
- return ast_ctx.UnknownAnyTy;
- else
- return ast_ctx.getConstType(target_type);
- }
- case '^':
- {
- if (!for_expression && type.NextIf('?'))
- {
- // if we are not supporting the concept of unknownAny, but what is being created here is an unknownAny*, then
- // we can just get away with a void*
- // this is theoretically wrong (in the same sense as 'theoretically nothing exists') but is way better than outright failure
- // in many practical cases
- return ast_ctx.VoidPtrTy;
- }
- else
- {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
- if (target_type.isNull())
- return clang::QualType();
- else if (target_type == ast_ctx.UnknownAnyTy)
- return ast_ctx.UnknownAnyTy;
- else
- return ast_ctx.getPointerType(target_type);
- }
- }
- case '?':
- return for_expression ? ast_ctx.UnknownAnyTy : clang::QualType();
- }
+ }
+ case '?':
+ return for_expression ? ast_ctx.UnknownAnyTy : clang::QualType();
+ }
}
-CompilerType
-AppleObjCTypeEncodingParser::RealizeType (clang::ASTContext &ast_ctx, const char* name, bool for_expression)
-{
- if (name && name[0])
- {
- StringLexer lexer(name);
- clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression);
- return CompilerType(&ast_ctx, qual_type);
- }
- return CompilerType();
+CompilerType AppleObjCTypeEncodingParser::RealizeType(
+ clang::ASTContext &ast_ctx, const char *name, bool for_expression) {
+ if (name && name[0]) {
+ StringLexer lexer(name);
+ clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression);
+ return CompilerType(&ast_ctx, qual_type);
+ }
+ return CompilerType();
}
-
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 87c49cb..4da84dd 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -16,66 +16,72 @@
#include "clang/AST/ASTContext.h"
// Project includes
-#include "lldb/lldb-private.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/lldb-private.h"
namespace lldb_utility {
- class StringLexer;
+class StringLexer;
}
namespace lldb_private {
- class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType
- {
- public:
- AppleObjCTypeEncodingParser (ObjCLanguageRuntime& runtime);
- ~AppleObjCTypeEncodingParser() override = default;
-
- CompilerType RealizeType(clang::ASTContext &ast_ctx, const char* name, bool for_expression) override;
+class AppleObjCTypeEncodingParser : public ObjCLanguageRuntime::EncodingToType {
+public:
+ AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime);
+ ~AppleObjCTypeEncodingParser() override = default;
- private:
- struct StructElement {
- std::string name;
- clang::QualType type;
- uint32_t bitfield;
-
- StructElement ();
- ~StructElement () = default;
- };
-
- clang::QualType
- BuildType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, uint32_t *bitfield_bit_size = nullptr);
+ CompilerType RealizeType(clang::ASTContext &ast_ctx, const char *name,
+ bool for_expression) override;
- clang::QualType
- BuildStruct (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
-
- clang::QualType
- BuildAggregate (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression, char opener, char closer, uint32_t kind);
-
- clang::QualType
- BuildUnion (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
-
- clang::QualType
- BuildArray (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
-
- std::string
- ReadStructName(lldb_utility::StringLexer& type);
-
- StructElement
- ReadStructElement (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
-
- clang::QualType
- BuildObjCObjectPointerType (clang::ASTContext &ast_ctx, lldb_utility::StringLexer& type, bool for_expression);
-
- uint32_t
- ReadNumber (lldb_utility::StringLexer& type);
-
- std::string
- ReadQuotedString(lldb_utility::StringLexer& type);
-
- ObjCLanguageRuntime& m_runtime;
- };
-
+private:
+ struct StructElement {
+ std::string name;
+ clang::QualType type;
+ uint32_t bitfield;
+
+ StructElement();
+ ~StructElement() = default;
+ };
+
+ clang::QualType BuildType(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression,
+ uint32_t *bitfield_bit_size = nullptr);
+
+ clang::QualType BuildStruct(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression);
+
+ clang::QualType BuildAggregate(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression, char opener, char closer,
+ uint32_t kind);
+
+ clang::QualType BuildUnion(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression);
+
+ clang::QualType BuildArray(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression);
+
+ std::string ReadStructName(lldb_utility::StringLexer &type);
+
+ StructElement ReadStructElement(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression);
+
+ clang::QualType BuildObjCObjectPointerType(clang::ASTContext &ast_ctx,
+ lldb_utility::StringLexer &type,
+ bool for_expression);
+
+ uint32_t ReadNumber(lldb_utility::StringLexer &type);
+
+ std::string ReadQuotedString(lldb_utility::StringLexer &type);
+
+ ObjCLanguageRuntime &m_runtime;
+};
+
} // namespace lldb_private
#endif // liblldb_AppleObjCTypeEncodingParser_h_
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index a2101c9..e492695 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -1,4 +1,5 @@
-//===-- AppleThreadPlanStepThroughObjCTrampoline.cpp --------------------------*- C++ -*-===//
+//===-- AppleThreadPlanStepThroughObjCTrampoline.cpp
+//--------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,212 +31,183 @@
//----------------------------------------------------------------------
// ThreadPlanStepThroughObjCTrampoline constructor
//----------------------------------------------------------------------
-AppleThreadPlanStepThroughObjCTrampoline::AppleThreadPlanStepThroughObjCTrampoline
-(
- Thread &thread,
- AppleObjCTrampolineHandler *trampoline_handler,
- ValueList &input_values,
- lldb::addr_t isa_addr,
- lldb::addr_t sel_addr,
- bool stop_others
-) :
- ThreadPlan (ThreadPlan::eKindGeneric,
- "MacOSX Step through ObjC Trampoline",
- thread,
- eVoteNoOpinion,
- eVoteNoOpinion),
- m_trampoline_handler (trampoline_handler),
- m_args_addr (LLDB_INVALID_ADDRESS),
- m_input_values (input_values),
- m_isa_addr(isa_addr),
- m_sel_addr(sel_addr),
- m_impl_function (NULL),
- m_stop_others (stop_others)
-{
-
-}
+AppleThreadPlanStepThroughObjCTrampoline::
+ AppleThreadPlanStepThroughObjCTrampoline(
+ Thread &thread, AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
+ bool stop_others)
+ : ThreadPlan(ThreadPlan::eKindGeneric,
+ "MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion,
+ eVoteNoOpinion),
+ m_trampoline_handler(trampoline_handler),
+ m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values),
+ m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(NULL),
+ m_stop_others(stop_others) {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-AppleThreadPlanStepThroughObjCTrampoline::~AppleThreadPlanStepThroughObjCTrampoline()
-{
+AppleThreadPlanStepThroughObjCTrampoline::
+ ~AppleThreadPlanStepThroughObjCTrampoline() {}
+
+void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
+ // Setting up the memory space for the called function text might require
+ // allocations,
+ // i.e. a nested function call. This needs to be done as a PreResumeAction.
+ m_thread.GetProcess()->AddPreResumeAction(PreResumeInitializeFunctionCaller,
+ (void *)this);
}
-void
-AppleThreadPlanStepThroughObjCTrampoline::DidPush ()
-{
- // Setting up the memory space for the called function text might require allocations,
- // i.e. a nested function call. This needs to be done as a PreResumeAction.
- m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeFunctionCaller, (void *) this);
-}
+bool AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller() {
+ if (!m_func_sp) {
+ DiagnosticManager diagnostics;
+ m_args_addr =
+ m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values);
-bool
-AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller ()
-{
- if (!m_func_sp)
- {
- DiagnosticManager diagnostics;
- m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values);
-
- if (m_args_addr == LLDB_INVALID_ADDRESS)
- {
- return false;
- }
- m_impl_function = m_trampoline_handler->GetLookupImplementationFunctionCaller();
- ExecutionContext exc_ctx;
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetStopOthers(m_stop_others);
- m_thread.CalculateExecutionContext(exc_ctx);
- m_func_sp = m_impl_function->GetThreadPlanToCallFunction(exc_ctx, m_args_addr, options, diagnostics);
- m_func_sp->SetOkayToDiscard(true);
- m_thread.QueueThreadPlan(m_func_sp, false);
+ if (m_args_addr == LLDB_INVALID_ADDRESS) {
+ return false;
}
- return true;
+ m_impl_function =
+ m_trampoline_handler->GetLookupImplementationFunctionCaller();
+ ExecutionContext exc_ctx;
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetStopOthers(m_stop_others);
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_func_sp = m_impl_function->GetThreadPlanToCallFunction(
+ exc_ctx, m_args_addr, options, diagnostics);
+ m_func_sp->SetOkayToDiscard(true);
+ m_thread.QueueThreadPlan(m_func_sp, false);
+ }
+ return true;
}
-bool
-AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeFunctionCaller(void *void_myself)
-{
- AppleThreadPlanStepThroughObjCTrampoline *myself = static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
- return myself->InitializeFunctionCaller();
+bool AppleThreadPlanStepThroughObjCTrampoline::
+ PreResumeInitializeFunctionCaller(void *void_myself) {
+ AppleThreadPlanStepThroughObjCTrampoline *myself =
+ static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
+ return myself->InitializeFunctionCaller();
}
-void
-AppleThreadPlanStepThroughObjCTrampoline::GetDescription (Stream *s,
- lldb::DescriptionLevel level)
-{
- if (level == lldb::eDescriptionLevelBrief)
- s->Printf("Step through ObjC trampoline");
- else
- {
- s->Printf ("Stepping to implementation of ObjC method - obj: 0x%llx, isa: 0x%" PRIx64 ", sel: 0x%" PRIx64,
- m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(), m_isa_addr, m_sel_addr);
- }
-}
-
-bool
-AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan (Stream *error)
-{
- return true;
+void AppleThreadPlanStepThroughObjCTrampoline::GetDescription(
+ Stream *s, lldb::DescriptionLevel level) {
+ if (level == lldb::eDescriptionLevelBrief)
+ s->Printf("Step through ObjC trampoline");
+ else {
+ s->Printf("Stepping to implementation of ObjC method - obj: 0x%llx, isa: "
+ "0x%" PRIx64 ", sel: 0x%" PRIx64,
+ m_input_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
+ m_isa_addr, m_sel_addr);
+ }
}
-bool
-AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop (Event *event_ptr)
-{
- // If we get asked to explain the stop it will be because something went
- // wrong (like the implementation for selector function crashed... We're going
- // to figure out what to do about that, so we do explain the stop.
- return true;
+bool AppleThreadPlanStepThroughObjCTrampoline::ValidatePlan(Stream *error) {
+ return true;
}
-lldb::StateType
-AppleThreadPlanStepThroughObjCTrampoline::GetPlanRunState ()
-{
- return eStateRunning;
+bool AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop(
+ Event *event_ptr) {
+ // If we get asked to explain the stop it will be because something went
+ // wrong (like the implementation for selector function crashed... We're
+ // going
+ // to figure out what to do about that, so we do explain the stop.
+ return true;
}
-bool
-AppleThreadPlanStepThroughObjCTrampoline::ShouldStop (Event *event_ptr)
-{
- // First stage: we are still handling the "call a function to get the target of the dispatch"
- if (m_func_sp)
- {
- if (!m_func_sp->IsPlanComplete())
- {
- return false;
- }
- else
- {
- if (!m_func_sp->PlanSucceeded())
- {
- SetPlanComplete(false);
- return true;
- }
- m_func_sp.reset();
- }
- }
-
- // Second stage, if all went well with the function calling, then fetch the target address, and
- // queue up a "run to that address" plan.
- if (!m_run_to_sp)
- {
- Value target_addr_value;
- ExecutionContext exc_ctx;
- m_thread.CalculateExecutionContext(exc_ctx);
- m_impl_function->FetchFunctionResults (exc_ctx, m_args_addr, target_addr_value);
- m_impl_function->DeallocateFunctionResults(exc_ctx, m_args_addr);
- lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
- Address target_so_addr;
- target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (target_addr == 0)
- {
- if (log)
- log->Printf("Got target implementation of 0x0, stopping.");
- SetPlanComplete();
- return true;
- }
- if (m_trampoline_handler->AddrIsMsgForward(target_addr))
- {
- if (log)
- log->Printf ("Implementation lookup returned msgForward function: 0x%" PRIx64 ", stopping.", target_addr);
+lldb::StateType AppleThreadPlanStepThroughObjCTrampoline::GetPlanRunState() {
+ return eStateRunning;
+}
- SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(eSymbolContextEverything);
- const bool abort_other_plans = false;
- const bool first_insn = true;
- const uint32_t frame_idx = 0;
- m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop (abort_other_plans,
- &sc,
- first_insn,
- m_stop_others,
- eVoteNoOpinion,
- eVoteNoOpinion,
- frame_idx);
- m_run_to_sp->SetPrivate(true);
- return false;
- }
-
- if (log)
- log->Printf("Running to ObjC method implementation: 0x%" PRIx64, target_addr);
-
- ObjCLanguageRuntime *objc_runtime = GetThread().GetProcess()->GetObjCLanguageRuntime();
- assert (objc_runtime != NULL);
- objc_runtime->AddToMethodCache (m_isa_addr, m_sel_addr, target_addr);
- if (log)
- log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64 "} = addr=0x%" PRIx64 " to cache.", m_isa_addr, m_sel_addr, target_addr);
-
- // Extract the target address from the value:
-
- m_run_to_sp.reset(new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others));
- m_thread.QueueThreadPlan(m_run_to_sp, false);
- m_run_to_sp->SetPrivate(true);
- return false;
- }
- else if (m_thread.IsThreadPlanDone(m_run_to_sp.get()))
- {
- // Third stage, work the run to target plan.
- SetPlanComplete();
+bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
+ // First stage: we are still handling the "call a function to get the target
+ // of the dispatch"
+ if (m_func_sp) {
+ if (!m_func_sp->IsPlanComplete()) {
+ return false;
+ } else {
+ if (!m_func_sp->PlanSucceeded()) {
+ SetPlanComplete(false);
return true;
+ }
+ m_func_sp.reset();
}
+ }
+
+ // Second stage, if all went well with the function calling, then fetch the
+ // target address, and
+ // queue up a "run to that address" plan.
+ if (!m_run_to_sp) {
+ Value target_addr_value;
+ ExecutionContext exc_ctx;
+ m_thread.CalculateExecutionContext(exc_ctx);
+ m_impl_function->FetchFunctionResults(exc_ctx, m_args_addr,
+ target_addr_value);
+ m_impl_function->DeallocateFunctionResults(exc_ctx, m_args_addr);
+ lldb::addr_t target_addr = target_addr_value.GetScalar().ULongLong();
+ Address target_so_addr;
+ target_so_addr.SetOpcodeLoadAddress(target_addr, exc_ctx.GetTargetPtr());
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (target_addr == 0) {
+ if (log)
+ log->Printf("Got target implementation of 0x0, stopping.");
+ SetPlanComplete();
+ return true;
+ }
+ if (m_trampoline_handler->AddrIsMsgForward(target_addr)) {
+ if (log)
+ log->Printf(
+ "Implementation lookup returned msgForward function: 0x%" PRIx64
+ ", stopping.",
+ target_addr);
+
+ SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(
+ eSymbolContextEverything);
+ const bool abort_other_plans = false;
+ const bool first_insn = true;
+ const uint32_t frame_idx = 0;
+ m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
+ abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
+ eVoteNoOpinion, frame_idx);
+ m_run_to_sp->SetPrivate(true);
+ return false;
+ }
+
+ if (log)
+ log->Printf("Running to ObjC method implementation: 0x%" PRIx64,
+ target_addr);
+
+ ObjCLanguageRuntime *objc_runtime =
+ GetThread().GetProcess()->GetObjCLanguageRuntime();
+ assert(objc_runtime != NULL);
+ objc_runtime->AddToMethodCache(m_isa_addr, m_sel_addr, target_addr);
+ if (log)
+ log->Printf("Adding {isa-addr=0x%" PRIx64 ", sel-addr=0x%" PRIx64
+ "} = addr=0x%" PRIx64 " to cache.",
+ m_isa_addr, m_sel_addr, target_addr);
+
+ // Extract the target address from the value:
+
+ m_run_to_sp.reset(
+ new ThreadPlanRunToAddress(m_thread, target_so_addr, m_stop_others));
+ m_thread.QueueThreadPlan(m_run_to_sp, false);
+ m_run_to_sp->SetPrivate(true);
return false;
+ } else if (m_thread.IsThreadPlanDone(m_run_to_sp.get())) {
+ // Third stage, work the run to target plan.
+ SetPlanComplete();
+ return true;
+ }
+ return false;
}
// The base class MischiefManaged does some cleanup - so you have to call it
// in your MischiefManaged derived class.
-bool
-AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged ()
-{
- if (IsPlanComplete())
- return true;
- else
- return false;
+bool AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged() {
+ if (IsPlanComplete())
+ return true;
+ else
+ return false;
}
-bool
-AppleThreadPlanStepThroughObjCTrampoline::WillStop()
-{
- return true;
-}
+bool AppleThreadPlanStepThroughObjCTrampoline::WillStop() { return true; }
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
index 8db9963..60c8b92 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -14,80 +14,66 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-types.h"
-#include "lldb/lldb-enumerations.h"
+#include "AppleObjCTrampolineHandler.h"
#include "lldb/Core/Value.h"
#include "lldb/Target/ThreadPlan.h"
-#include "AppleObjCTrampolineHandler.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
-namespace lldb_private
-{
+namespace lldb_private {
-class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan
-{
+class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan {
public:
- AppleThreadPlanStepThroughObjCTrampoline(Thread &thread,
- AppleObjCTrampolineHandler *trampoline_handler,
- ValueList &values,
- lldb::addr_t isa_addr,
- lldb::addr_t sel_addr,
- bool stop_others);
+ AppleThreadPlanStepThroughObjCTrampoline(
+ Thread &thread, AppleObjCTrampolineHandler *trampoline_handler,
+ ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr,
+ bool stop_others);
- ~AppleThreadPlanStepThroughObjCTrampoline() override;
+ ~AppleThreadPlanStepThroughObjCTrampoline() override;
- static bool
- PreResumeInitializeFunctionCaller(void *myself);
+ static bool PreResumeInitializeFunctionCaller(void *myself);
- void
- GetDescription(Stream *s,
- lldb::DescriptionLevel level) override;
-
- bool
- ValidatePlan(Stream *error) override;
+ void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
- lldb::StateType
- GetPlanRunState() override;
+ bool ValidatePlan(Stream *error) override;
- bool
- ShouldStop(Event *event_ptr) override;
-
- bool
- StopOthers() override
- {
- return m_stop_others;
- }
+ lldb::StateType GetPlanRunState() override;
- // The base class MischiefManaged does some cleanup - so you have to call it
- // in your MischiefManaged derived class.
- bool
- MischiefManaged() override;
-
- void
- DidPush() override;
-
- bool
- WillStop() override;
+ bool ShouldStop(Event *event_ptr) override;
+
+ bool StopOthers() override { return m_stop_others; }
+
+ // The base class MischiefManaged does some cleanup - so you have to call it
+ // in your MischiefManaged derived class.
+ bool MischiefManaged() override;
+
+ void DidPush() override;
+
+ bool WillStop() override;
protected:
- bool
- DoPlanExplainsStop(Event *event_ptr) override;
-
-private:
- bool
- InitializeFunctionCaller ();
+ bool DoPlanExplainsStop(Event *event_ptr) override;
- AppleObjCTrampolineHandler *m_trampoline_handler; // FIXME - ensure this doesn't go away on us? SP maybe?
- lldb::addr_t m_args_addr; // Stores the address for our step through function result structure.
- //lldb::addr_t m_object_addr; // This is only for Description.
- ValueList m_input_values;
- lldb::addr_t m_isa_addr; // isa_addr and sel_addr are the keys we will use to cache the implementation.
- lldb::addr_t m_sel_addr;
- lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it at start, then set it
- // to NULL when this plan is done. That way we know to go to:
- lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
- FunctionCaller *m_impl_function; // This is a pointer to a impl function that
- // is owned by the client that pushes this plan.
- bool m_stop_others;
+private:
+ bool InitializeFunctionCaller();
+
+ AppleObjCTrampolineHandler *m_trampoline_handler; // FIXME - ensure this
+ // doesn't go away on us?
+ // SP maybe?
+ lldb::addr_t m_args_addr; // Stores the address for our step through function
+ // result structure.
+ // lldb::addr_t m_object_addr; // This is only for Description.
+ ValueList m_input_values;
+ lldb::addr_t m_isa_addr; // isa_addr and sel_addr are the keys we will use to
+ // cache the implementation.
+ lldb::addr_t m_sel_addr;
+ lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it
+ // at start, then set it
+ // to NULL when this plan is done. That way we know to go to:
+ lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
+ FunctionCaller *m_impl_function; // This is a pointer to a impl function that
+ // is owned by the client that pushes this plan.
+ bool m_stop_others;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index 67850db..2471f6a 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -37,165 +37,163 @@
using namespace lldb_renderscript;
// [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang),
-// the compiler frontend for RenderScript embeds an ARM specific triple in IR that is shipped in the app, after
+// the compiler frontend for RenderScript embeds an ARM specific triple in IR
+// that is shipped in the app, after
// generating IR that has some assumptions that an ARM device is the target.
-// As the IR is then compiled on a device of unknown (at time the IR was generated at least) architecture,
-// when calling RenderScript API function as part of debugger expressions, we have to perform a fixup pass that
-// removes those assumptions right before the module is sent to be generated by the llvm backend.
+// As the IR is then compiled on a device of unknown (at time the IR was
+// generated at least) architecture,
+// when calling RenderScript API function as part of debugger expressions, we
+// have to perform a fixup pass that
+// removes those assumptions right before the module is sent to be generated by
+// the llvm backend.
-namespace
-{
-bool
-registerRSDefaultTargetOpts(clang::TargetOptions &proto, const llvm::Triple::ArchType &arch)
-{
- switch (arch)
- {
- case llvm::Triple::ArchType::x86:
- proto.Triple = "i686--linux-android";
- proto.CPU = "atom";
- proto.Features.push_back("+long64");
- // Fallthrough for common x86 family features
- case llvm::Triple::ArchType::x86_64:
- proto.Features.push_back("+mmx");
- proto.Features.push_back("+sse");
- proto.Features.push_back("+sse2");
- proto.Features.push_back("+sse3");
- proto.Features.push_back("+ssse3");
- proto.Features.push_back("+sse4.1");
- proto.Features.push_back("+sse4.2");
- break;
- case llvm::Triple::ArchType::mipsel:
- // pretend this is `arm' for the front-end
- proto.Triple = "armv7-none-linux-android";
- proto.CPU = "";
- proto.Features.push_back("+long64");
- break;
- case llvm::Triple::ArchType::mips64el:
- // pretend this is `aarch64' for the front-end
- proto.Triple = "aarch64-none-linux-android";
- proto.CPU = "";
- break;
- default:
- return false;
- }
- return true;
+namespace {
+bool registerRSDefaultTargetOpts(clang::TargetOptions &proto,
+ const llvm::Triple::ArchType &arch) {
+ switch (arch) {
+ case llvm::Triple::ArchType::x86:
+ proto.Triple = "i686--linux-android";
+ proto.CPU = "atom";
+ proto.Features.push_back("+long64");
+ // Fallthrough for common x86 family features
+ case llvm::Triple::ArchType::x86_64:
+ proto.Features.push_back("+mmx");
+ proto.Features.push_back("+sse");
+ proto.Features.push_back("+sse2");
+ proto.Features.push_back("+sse3");
+ proto.Features.push_back("+ssse3");
+ proto.Features.push_back("+sse4.1");
+ proto.Features.push_back("+sse4.2");
+ break;
+ case llvm::Triple::ArchType::mipsel:
+ // pretend this is `arm' for the front-end
+ proto.Triple = "armv7-none-linux-android";
+ proto.CPU = "";
+ proto.Features.push_back("+long64");
+ break;
+ case llvm::Triple::ArchType::mips64el:
+ // pretend this is `aarch64' for the front-end
+ proto.Triple = "aarch64-none-linux-android";
+ proto.CPU = "";
+ break;
+ default:
+ return false;
+ }
+ return true;
}
} // end anonymous namespace
-bool
-RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module)
-{
- bool changed_module = false;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
+bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
+ bool changed_module = false;
+ Log *log(
+ GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
- std::string err;
- llvm::StringRef real_triple = m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple();
- const llvm::Target *target_info = llvm::TargetRegistry::lookupTarget(real_triple, err);
- if (!target_info)
- {
- if (log)
- log->Warning("couldn't determine real target architecture: '%s'", err.c_str());
- return false;
+ std::string err;
+ llvm::StringRef real_triple =
+ m_process_ptr->GetTarget().GetArchitecture().GetTriple().getTriple();
+ const llvm::Target *target_info =
+ llvm::TargetRegistry::lookupTarget(real_triple, err);
+ if (!target_info) {
+ if (log)
+ log->Warning("couldn't determine real target architecture: '%s'",
+ err.c_str());
+ return false;
+ }
+
+ llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None;
+ assert(m_process_ptr && "no available lldb process");
+ switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine()) {
+ case llvm::Triple::ArchType::x86:
+ changed_module |= fixupX86FunctionCalls(module);
+ // For some reason this triple gets totally missed by the backend, and must
+ // be set manually.
+ // There a reference in bcc/Main.cpp about auto feature-detection being
+ // removed from LLVM3.5, but I can't
+ // see that discussion anywhere public.
+ real_triple = "i686--linux-android";
+ break;
+ case llvm::Triple::ArchType::x86_64:
+ changed_module |= fixupX86_64FunctionCalls(module);
+ break;
+ case llvm::Triple::ArchType::mipsel:
+ case llvm::Triple::ArchType::mips64el:
+ // No actual IR fixup pass is needed on MIPS, but the datalayout
+ // and targetmachine do need to be explicitly set.
+
+ // bcc explicitly compiles MIPS code to use the static relocation
+ // model due to an issue with relocations in mclinker.
+ // see libbcc/support/CompilerConfig.cpp for details
+ reloc_model = llvm::Reloc::Static;
+ changed_module = true;
+ break;
+ case llvm::Triple::ArchType::arm:
+ case llvm::Triple::ArchType::aarch64:
+ // ARM subtargets need no fixup passes as they are the initial target as
+ // generated by the
+ // slang compiler frontend.
+ break;
+ default:
+ if (log)
+ log->Warning("Ignoring unknown renderscript target");
+ return false;
+ }
+
+ if (changed_module) {
+ llvm::TargetOptions options;
+ llvm::TargetMachine *target_machine = target_info->createTargetMachine(
+ real_triple, "", "", options, reloc_model);
+ assert(target_machine &&
+ "failed to identify RenderScriptRuntime target machine");
+ // We've been using a triple and datalayout of some ARM variant all along,
+ // so
+ // we need to let the backend know that this is no longer the case.
+ if (log) {
+ log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__,
+ real_triple.str().c_str());
+ log->Printf(
+ "%s - Changing RS datalayout to '%s'", __FUNCTION__,
+ target_machine->createDataLayout().getStringRepresentation().c_str());
}
-
- llvm::Optional<llvm::Reloc::Model> reloc_model = llvm::None;
- assert(m_process_ptr && "no available lldb process");
- switch (m_process_ptr->GetTarget().GetArchitecture().GetMachine())
- {
- case llvm::Triple::ArchType::x86:
- changed_module |= fixupX86FunctionCalls(module);
- // For some reason this triple gets totally missed by the backend, and must be set manually.
- // There a reference in bcc/Main.cpp about auto feature-detection being removed from LLVM3.5, but I can't
- // see that discussion anywhere public.
- real_triple = "i686--linux-android";
- break;
- case llvm::Triple::ArchType::x86_64:
- changed_module |= fixupX86_64FunctionCalls(module);
- break;
- case llvm::Triple::ArchType::mipsel:
- case llvm::Triple::ArchType::mips64el:
- // No actual IR fixup pass is needed on MIPS, but the datalayout
- // and targetmachine do need to be explicitly set.
-
- // bcc explicitly compiles MIPS code to use the static relocation
- // model due to an issue with relocations in mclinker.
- // see libbcc/support/CompilerConfig.cpp for details
- reloc_model = llvm::Reloc::Static;
- changed_module = true;
- break;
- case llvm::Triple::ArchType::arm:
- case llvm::Triple::ArchType::aarch64:
- // ARM subtargets need no fixup passes as they are the initial target as generated by the
- // slang compiler frontend.
- break;
- default:
- if (log)
- log->Warning("Ignoring unknown renderscript target");
- return false;
- }
-
- if (changed_module)
- {
- llvm::TargetOptions options;
- llvm::TargetMachine *target_machine =
- target_info->createTargetMachine(real_triple, "", "", options, reloc_model);
- assert(target_machine && "failed to identify RenderScriptRuntime target machine");
- // We've been using a triple and datalayout of some ARM variant all along, so
- // we need to let the backend know that this is no longer the case.
- if (log)
- {
- log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__, real_triple.str().c_str());
- log->Printf("%s - Changing RS datalayout to '%s'", __FUNCTION__,
- target_machine->createDataLayout().getStringRepresentation().c_str());
- }
- module.setTargetTriple(real_triple);
- module.setDataLayout(target_machine->createDataLayout());
- }
- return changed_module;
+ module.setTargetTriple(real_triple);
+ module.setDataLayout(target_machine->createDataLayout());
+ }
+ return changed_module;
}
char RenderScriptRuntimeModulePass::ID = 0;
-namespace lldb_private
-{
+namespace lldb_private {
-bool
-RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto)
-{
- auto *process = GetProcess();
- assert(process);
- return registerRSDefaultTargetOpts(proto, process->GetTarget().GetArchitecture().GetMachine());
+bool RenderScriptRuntime::GetOverrideExprOptions(clang::TargetOptions &proto) {
+ auto *process = GetProcess();
+ assert(process);
+ return registerRSDefaultTargetOpts(
+ proto, process->GetTarget().GetArchitecture().GetMachine());
}
-bool
-RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes)
-{
- if (!m_ir_passes)
- m_ir_passes = new RSIRPasses(GetProcess());
- assert(m_ir_passes);
+bool RenderScriptRuntime::GetIRPasses(LLVMUserExpression::IRPasses &passes) {
+ if (!m_ir_passes)
+ m_ir_passes = new RSIRPasses(GetProcess());
+ assert(m_ir_passes);
- passes.EarlyPasses = m_ir_passes->EarlyPasses;
- passes.LatePasses = m_ir_passes->LatePasses;
+ passes.EarlyPasses = m_ir_passes->EarlyPasses;
+ passes.LatePasses = m_ir_passes->LatePasses;
- return true;
+ return true;
}
-namespace lldb_renderscript
-{
+namespace lldb_renderscript {
-RSIRPasses::RSIRPasses(Process *process)
-{
- IRPasses();
- assert(process);
+RSIRPasses::RSIRPasses(Process *process) {
+ IRPasses();
+ assert(process);
- EarlyPasses = std::make_shared<llvm::legacy::PassManager>();
- assert(EarlyPasses);
- EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
+ EarlyPasses = std::make_shared<llvm::legacy::PassManager>();
+ assert(EarlyPasses);
+ EarlyPasses->add(new RenderScriptRuntimeModulePass(process));
}
-RSIRPasses::~RSIRPasses()
-{
-}
+RSIRPasses::~RSIRPasses() {}
} // namespace lldb_renderscript
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
index f998aa4..54d126d 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
@@ -26,34 +26,33 @@
#include "RenderScriptRuntime.h"
#include "RenderScriptx86ABIFixups.h"
-// RenderScriptRuntimeModulePass is a simple llvm::ModulesPass that is used during expression evaluation to apply
+// RenderScriptRuntimeModulePass is a simple llvm::ModulesPass that is used
+// during expression evaluation to apply
// RenderScript-specific fixes for expression evaluation.
-// In particular this is used to make expression IR conformant with the ABI generated by the slang frontend. This
-// ModulePass is executed in ClangExpressionParser::PrepareForExecution whenever an expression's DWARF language is
+// In particular this is used to make expression IR conformant with the ABI
+// generated by the slang frontend. This
+// ModulePass is executed in ClangExpressionParser::PrepareForExecution whenever
+// an expression's DWARF language is
// eLanguageTypeExtRenderscript
-class RenderScriptRuntimeModulePass : public llvm::ModulePass
-{
+class RenderScriptRuntimeModulePass : public llvm::ModulePass {
public:
- static char ID;
- RenderScriptRuntimeModulePass(const lldb_private::Process *process) : ModulePass(ID), m_process_ptr(process) {}
+ static char ID;
+ RenderScriptRuntimeModulePass(const lldb_private::Process *process)
+ : ModulePass(ID), m_process_ptr(process) {}
- bool
- runOnModule(llvm::Module &module);
+ bool runOnModule(llvm::Module &module);
private:
- const lldb_private::Process *m_process_ptr;
+ const lldb_private::Process *m_process_ptr;
};
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
-struct RSIRPasses : public lldb_private::LLVMUserExpression::IRPasses
-{
- RSIRPasses(lldb_private::Process *process);
+namespace lldb_private {
+namespace lldb_renderscript {
+struct RSIRPasses : public lldb_private::LLVMUserExpression::IRPasses {
+ RSIRPasses(lldb_private::Process *process);
- ~RSIRPasses();
+ ~RSIRPasses();
};
} // namespace lldb_renderscript
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 5299169..b2a6309 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -41,652 +41,596 @@
using namespace lldb_private;
using namespace lldb_renderscript;
-namespace
-{
+namespace {
// The empirical_type adds a basic level of validation to arbitrary data
// allowing us to track if data has been discovered and stored or not.
-// An empirical_type will be marked as valid only if it has been explicitly assigned to.
-template <typename type_t> class empirical_type
-{
+// An empirical_type will be marked as valid only if it has been explicitly
+// assigned to.
+template <typename type_t> class empirical_type {
public:
- // Ctor. Contents is invalid when constructed.
- empirical_type() : valid(false) {}
+ // Ctor. Contents is invalid when constructed.
+ empirical_type() : valid(false) {}
- // Return true and copy contents to out if valid, else return false.
- bool
- get(type_t &out) const
- {
- if (valid)
- out = data;
- return valid;
- }
+ // Return true and copy contents to out if valid, else return false.
+ bool get(type_t &out) const {
+ if (valid)
+ out = data;
+ return valid;
+ }
- // Return a pointer to the contents or nullptr if it was not valid.
- const type_t *
- get() const
- {
- return valid ? &data : nullptr;
- }
+ // Return a pointer to the contents or nullptr if it was not valid.
+ const type_t *get() const { return valid ? &data : nullptr; }
- // Assign data explicitly.
- void
- set(const type_t in)
- {
- data = in;
- valid = true;
- }
+ // Assign data explicitly.
+ void set(const type_t in) {
+ data = in;
+ valid = true;
+ }
- // Mark contents as invalid.
- void
- invalidate()
- {
- valid = false;
- }
+ // Mark contents as invalid.
+ void invalidate() { valid = false; }
- // Returns true if this type contains valid data.
- bool
- isValid() const
- {
- return valid;
- }
+ // Returns true if this type contains valid data.
+ bool isValid() const { return valid; }
- // Assignment operator.
- empirical_type<type_t> &
- operator=(const type_t in)
- {
- set(in);
- return *this;
- }
+ // Assignment operator.
+ empirical_type<type_t> &operator=(const type_t in) {
+ set(in);
+ return *this;
+ }
- // Dereference operator returns contents.
- // Warning: Will assert if not valid so use only when you know data is valid.
- const type_t &operator*() const
- {
- assert(valid);
- return data;
- }
+ // Dereference operator returns contents.
+ // Warning: Will assert if not valid so use only when you know data is valid.
+ const type_t &operator*() const {
+ assert(valid);
+ return data;
+ }
protected:
- bool valid;
- type_t data;
+ bool valid;
+ type_t data;
};
-// ArgItem is used by the GetArgs() function when reading function arguments from the target.
-struct ArgItem
-{
- enum
- {
- ePointer,
- eInt32,
- eInt64,
- eLong,
- eBool
- } type;
+// ArgItem is used by the GetArgs() function when reading function arguments
+// from the target.
+struct ArgItem {
+ enum { ePointer, eInt32, eInt64, eLong, eBool } type;
- uint64_t value;
+ uint64_t value;
- explicit operator uint64_t() const { return value; }
+ explicit operator uint64_t() const { return value; }
};
-// Context structure to be passed into GetArgsXXX(), argument reading functions below.
-struct GetArgsCtx
-{
- RegisterContext *reg_ctx;
- Process *process;
+// Context structure to be passed into GetArgsXXX(), argument reading functions
+// below.
+struct GetArgsCtx {
+ RegisterContext *reg_ctx;
+ Process *process;
};
-bool
-GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Error error;
+
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
+
+ for (size_t i = 0; i < num_args; ++i) {
+ ArgItem &arg = arg_list[i];
+ // advance up the stack by one argument
+ sp += sizeof(uint32_t);
+ // get the argument type size
+ size_t arg_size = sizeof(uint32_t);
+ // read the argument from memory
+ arg.value = 0;
Error error;
-
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
-
- for (size_t i = 0; i < num_args; ++i)
- {
- ArgItem &arg = arg_list[i];
- // advance up the stack by one argument
- sp += sizeof(uint32_t);
- // get the argument type size
- size_t arg_size = sizeof(uint32_t);
- // read the argument from memory
- arg.value = 0;
- Error error;
- size_t read = ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), error);
- if (read != arg_size || !error.Success())
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64 " '%s'", __FUNCTION__, uint64_t(i),
- error.AsCString());
- return false;
- }
+ size_t read =
+ ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), error);
+ if (read != arg_size || !error.Success()) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 " '%s'",
+ __FUNCTION__, uint64_t(i), error.AsCString());
+ return false;
}
- return true;
+ }
+ return true;
}
-bool
-GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 6;
- // register passing order
- static const std::array<const char *, c_args_in_reg> c_reg_names{{"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
- // argument type to size mapping
- static const std::array<size_t, 5> arg_size{{
- 8, // ePointer,
- 4, // eInt32,
- 8, // eInt64,
- 8, // eLong,
- 4, // eBool,
- }};
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 6;
+ // register passing order
+ static const std::array<const char *, c_args_in_reg> c_reg_names{
+ {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
+ // argument type to size mapping
+ static const std::array<size_t, 5> arg_size{{
+ 8, // ePointer,
+ 4, // eInt32,
+ 8, // eInt64,
+ 8, // eLong,
+ 4, // eBool,
+ }};
- Error error;
+ Error error;
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
- // step over the return address
- sp += sizeof(uint64_t);
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
+ // step over the return address
+ sp += sizeof(uint64_t);
- // check the stack alignment was correct (16 byte aligned)
- if ((sp & 0xf) != 0x0)
- {
- if (log)
- log->Printf("%s - stack misaligned", __FUNCTION__);
- return false;
+ // check the stack alignment was correct (16 byte aligned)
+ if ((sp & 0xf) != 0x0) {
+ if (log)
+ log->Printf("%s - stack misaligned", __FUNCTION__);
+ return false;
+ }
+
+ // find the start of arguments on the stack
+ uint64_t sp_offset = 0;
+ for (uint32_t i = c_args_in_reg; i < num_args; ++i) {
+ sp_offset += arg_size[arg_list[i].type];
+ }
+ // round up to multiple of 16
+ sp_offset = (sp_offset + 0xf) & 0xf;
+ sp += sp_offset;
+
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoByName(c_reg_names[i]);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
}
-
- // find the start of arguments on the stack
- uint64_t sp_offset = 0;
- for (uint32_t i = c_args_in_reg; i < num_args; ++i)
- {
- sp_offset += arg_size[arg_list[i].type];
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t size = arg_size[arg_list[i].type];
+ // read the argument from memory
+ arg.value = 0;
+ // note: due to little endian layout reading 4 or 8 bytes will give the
+ // correct value.
+ size_t read = ctx.process->ReadMemory(sp, &arg.value, size, error);
+ success = (error.Success() && read == size);
+ // advance past this argument
+ sp -= size;
}
- // round up to multiple of 16
- sp_offset = (sp_offset + 0xf) & 0xf;
- sp += sp_offset;
-
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoByName(c_reg_names[i]);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t size = arg_size[arg_list[i].type];
- // read the argument from memory
- arg.value = 0;
- // note: due to little endian layout reading 4 or 8 bytes will give the correct value.
- size_t read = ctx.process->ReadMemory(sp, &arg.value, size, error);
- success = (error.Success() && read==size);
- // advance past this argument
- sp -= size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
}
- return true;
+ }
+ return true;
}
-bool
-GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 4;
+bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 4;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- Error error;
+ Error error;
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt32(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t arg_size = sizeof(uint32_t);
- // clear all 64bits
- arg.value = 0;
- // read this argument from memory
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += sizeof(uint32_t);
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt32(0, &success);
}
- return true;
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t arg_size = sizeof(uint32_t);
+ // clear all 64bits
+ arg.value = 0;
+ // read this argument from memory
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += sizeof(uint32_t);
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
}
-bool
-GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 8;
+bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 8;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- if (log)
- log->Printf("%s - reading arguments spilled to stack not implemented", __FUNCTION__);
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__,
- uint64_t(i));
- return false;
- }
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
}
- return true;
+ // arguments passed on the stack
+ else {
+ if (log)
+ log->Printf("%s - reading arguments spilled to stack not implemented",
+ __FUNCTION__);
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__,
+ uint64_t(i));
+ return false;
+ }
+ }
+ return true;
}
-bool
-GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 4;
- // register file offset to first argument
- static const uint32_t c_reg_offset = 4;
+bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 4;
+ // register file offset to first argument
+ static const uint32_t c_reg_offset = 4;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- Error error;
+ Error error;
- // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
- uint64_t sp = ctx.reg_ctx->GetSP() + 16;
+ // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
+ uint64_t sp = ctx.reg_ctx->GetSP() + 16;
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- const size_t arg_size = sizeof(uint32_t);
- arg.value = 0;
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += arg_size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
}
- return true;
+ // arguments passed on the stack
+ else {
+ const size_t arg_size = sizeof(uint32_t);
+ arg.value = 0;
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += arg_size;
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
}
-bool
-GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args)
-{
- // number of arguments passed in registers
- static const uint32_t c_args_in_reg = 8;
- // register file offset to first argument
- static const uint32_t c_reg_offset = 4;
+bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
+ // number of arguments passed in registers
+ static const uint32_t c_args_in_reg = 8;
+ // register file offset to first argument
+ static const uint32_t c_reg_offset = 4;
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- Error error;
+ Error error;
- // get the current stack pointer
- uint64_t sp = ctx.reg_ctx->GetSP();
+ // get the current stack pointer
+ uint64_t sp = ctx.reg_ctx->GetSP();
- for (size_t i = 0; i < num_args; ++i)
- {
- bool success = false;
- ArgItem &arg = arg_list[i];
- // arguments passed in registers
- if (i < c_args_in_reg)
- {
- const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
- RegisterValue rVal;
- if (ctx.reg_ctx->ReadRegister(rArg, rVal))
- arg.value = rVal.GetAsUInt64(0, &success);
- }
- // arguments passed on the stack
- else
- {
- // get the argument type size
- const size_t arg_size = sizeof(uint64_t);
- // clear all 64bits
- arg.value = 0;
- // read this argument from memory
- size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
- success = (error.Success() && bytes_read == arg_size);
- // advance the stack pointer
- sp += arg_size;
- }
- // fail if we couldn't read this argument
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading argument: %" PRIu64", reason: %s",
- __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
- return false;
- }
+ for (size_t i = 0; i < num_args; ++i) {
+ bool success = false;
+ ArgItem &arg = arg_list[i];
+ // arguments passed in registers
+ if (i < c_args_in_reg) {
+ const RegisterInfo *rArg =
+ ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset);
+ RegisterValue rVal;
+ if (ctx.reg_ctx->ReadRegister(rArg, rVal))
+ arg.value = rVal.GetAsUInt64(0, &success);
}
- return true;
+ // arguments passed on the stack
+ else {
+ // get the argument type size
+ const size_t arg_size = sizeof(uint64_t);
+ // clear all 64bits
+ arg.value = 0;
+ // read this argument from memory
+ size_t bytes_read =
+ ctx.process->ReadMemory(sp, &arg.value, arg_size, error);
+ success = (error.Success() && bytes_read == arg_size);
+ // advance the stack pointer
+ sp += arg_size;
+ }
+ // fail if we couldn't read this argument
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading argument: %" PRIu64 ", reason: %s",
+ __FUNCTION__, uint64_t(i), error.AsCString("n/a"));
+ return false;
+ }
+ }
+ return true;
}
-bool
-GetArgs(ExecutionContext &context, ArgItem *arg_list, size_t num_args)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+bool GetArgs(ExecutionContext &context, ArgItem *arg_list, size_t num_args) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- // verify that we have a target
- if (!context.GetTargetPtr())
- {
- if (log)
- log->Printf("%s - invalid target", __FUNCTION__);
- return false;
+ // verify that we have a target
+ if (!context.GetTargetPtr()) {
+ if (log)
+ log->Printf("%s - invalid target", __FUNCTION__);
+ return false;
+ }
+
+ GetArgsCtx ctx = {context.GetRegisterContext(), context.GetProcessPtr()};
+ assert(ctx.reg_ctx && ctx.process);
+
+ // dispatch based on architecture
+ switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) {
+ case llvm::Triple::ArchType::x86:
+ return GetArgsX86(ctx, arg_list, num_args);
+
+ case llvm::Triple::ArchType::x86_64:
+ return GetArgsX86_64(ctx, arg_list, num_args);
+
+ case llvm::Triple::ArchType::arm:
+ return GetArgsArm(ctx, arg_list, num_args);
+
+ case llvm::Triple::ArchType::aarch64:
+ return GetArgsAarch64(ctx, arg_list, num_args);
+
+ case llvm::Triple::ArchType::mipsel:
+ return GetArgsMipsel(ctx, arg_list, num_args);
+
+ case llvm::Triple::ArchType::mips64el:
+ return GetArgsMips64el(ctx, arg_list, num_args);
+
+ default:
+ // unsupported architecture
+ if (log) {
+ log->Printf(
+ "%s - architecture not supported: '%s'", __FUNCTION__,
+ context.GetTargetRef().GetArchitecture().GetArchitectureName());
}
-
- GetArgsCtx ctx = {context.GetRegisterContext(), context.GetProcessPtr()};
- assert(ctx.reg_ctx && ctx.process);
-
- // dispatch based on architecture
- switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
- {
- case llvm::Triple::ArchType::x86:
- return GetArgsX86(ctx, arg_list, num_args);
-
- case llvm::Triple::ArchType::x86_64:
- return GetArgsX86_64(ctx, arg_list, num_args);
-
- case llvm::Triple::ArchType::arm:
- return GetArgsArm(ctx, arg_list, num_args);
-
- case llvm::Triple::ArchType::aarch64:
- return GetArgsAarch64(ctx, arg_list, num_args);
-
- case llvm::Triple::ArchType::mipsel:
- return GetArgsMipsel(ctx, arg_list, num_args);
-
- case llvm::Triple::ArchType::mips64el:
- return GetArgsMips64el(ctx, arg_list, num_args);
-
- default:
- // unsupported architecture
- if (log)
- {
- log->Printf("%s - architecture not supported: '%s'", __FUNCTION__,
- context.GetTargetRef().GetArchitecture().GetArchitectureName());
- }
- return false;
- }
+ return false;
+ }
}
} // anonymous namespace
-// The ScriptDetails class collects data associated with a single script instance.
-struct RenderScriptRuntime::ScriptDetails
-{
- ~ScriptDetails() = default;
+// The ScriptDetails class collects data associated with a single script
+// instance.
+struct RenderScriptRuntime::ScriptDetails {
+ ~ScriptDetails() = default;
- enum ScriptType
- {
- eScript,
- eScriptC
- };
+ enum ScriptType { eScript, eScriptC };
- // The derived type of the script.
- empirical_type<ScriptType> type;
- // The name of the original source file.
- empirical_type<std::string> resName;
- // Path to script .so file on the device.
- empirical_type<std::string> scriptDyLib;
- // Directory where kernel objects are cached on device.
- empirical_type<std::string> cacheDir;
- // Pointer to the context which owns this script.
- empirical_type<lldb::addr_t> context;
- // Pointer to the script object itself.
- empirical_type<lldb::addr_t> script;
+ // The derived type of the script.
+ empirical_type<ScriptType> type;
+ // The name of the original source file.
+ empirical_type<std::string> resName;
+ // Path to script .so file on the device.
+ empirical_type<std::string> scriptDyLib;
+ // Directory where kernel objects are cached on device.
+ empirical_type<std::string> cacheDir;
+ // Pointer to the context which owns this script.
+ empirical_type<lldb::addr_t> context;
+ // Pointer to the script object itself.
+ empirical_type<lldb::addr_t> script;
};
// This Element class represents the Element object in RS,
// defining the type associated with an Allocation.
-struct RenderScriptRuntime::Element
-{
- // Taken from rsDefines.h
- enum DataKind
- {
- RS_KIND_USER,
- RS_KIND_PIXEL_L = 7,
- RS_KIND_PIXEL_A,
- RS_KIND_PIXEL_LA,
- RS_KIND_PIXEL_RGB,
- RS_KIND_PIXEL_RGBA,
- RS_KIND_PIXEL_DEPTH,
- RS_KIND_PIXEL_YUV,
- RS_KIND_INVALID = 100
- };
+struct RenderScriptRuntime::Element {
+ // Taken from rsDefines.h
+ enum DataKind {
+ RS_KIND_USER,
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+ RS_KIND_PIXEL_YUV,
+ RS_KIND_INVALID = 100
+ };
- // Taken from rsDefines.h
- enum DataType
- {
- RS_TYPE_NONE = 0,
- RS_TYPE_FLOAT_16,
- RS_TYPE_FLOAT_32,
- RS_TYPE_FLOAT_64,
- RS_TYPE_SIGNED_8,
- RS_TYPE_SIGNED_16,
- RS_TYPE_SIGNED_32,
- RS_TYPE_SIGNED_64,
- RS_TYPE_UNSIGNED_8,
- RS_TYPE_UNSIGNED_16,
- RS_TYPE_UNSIGNED_32,
- RS_TYPE_UNSIGNED_64,
- RS_TYPE_BOOLEAN,
+ // Taken from rsDefines.h
+ enum DataType {
+ RS_TYPE_NONE = 0,
+ RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+ RS_TYPE_BOOLEAN,
- RS_TYPE_UNSIGNED_5_6_5,
- RS_TYPE_UNSIGNED_5_5_5_1,
- RS_TYPE_UNSIGNED_4_4_4_4,
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
- RS_TYPE_MATRIX_4X4,
- RS_TYPE_MATRIX_3X3,
- RS_TYPE_MATRIX_2X2,
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
- RS_TYPE_ELEMENT = 1000,
- RS_TYPE_TYPE,
- RS_TYPE_ALLOCATION,
- RS_TYPE_SAMPLER,
- RS_TYPE_SCRIPT,
- RS_TYPE_MESH,
- RS_TYPE_PROGRAM_FRAGMENT,
- RS_TYPE_PROGRAM_VERTEX,
- RS_TYPE_PROGRAM_RASTER,
- RS_TYPE_PROGRAM_STORE,
- RS_TYPE_FONT,
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+ RS_TYPE_FONT,
- RS_TYPE_INVALID = 10000
- };
+ RS_TYPE_INVALID = 10000
+ };
- std::vector<Element> children; // Child Element fields for structs
- empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
- empirical_type<DataType> type; // Type of each data pointer stored by the allocation
- empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image
- empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4
- empirical_type<uint32_t> field_count; // Number of Subelements
- empirical_type<uint32_t> datum_size; // Size of a single Element with padding
- empirical_type<uint32_t> padding; // Number of padding bytes
- empirical_type<uint32_t> array_size; // Number of items in array, only needed for strucrs
- ConstString type_name; // Name of type, only needed for structs
+ std::vector<Element> children; // Child Element fields for structs
+ empirical_type<lldb::addr_t>
+ element_ptr; // Pointer to the RS Element of the Type
+ empirical_type<DataType>
+ type; // Type of each data pointer stored by the allocation
+ empirical_type<DataKind>
+ type_kind; // Defines pixel type if Allocation is created from an image
+ empirical_type<uint32_t>
+ type_vec_size; // Vector size of each data point, e.g '4' for uchar4
+ empirical_type<uint32_t> field_count; // Number of Subelements
+ empirical_type<uint32_t> datum_size; // Size of a single Element with padding
+ empirical_type<uint32_t> padding; // Number of padding bytes
+ empirical_type<uint32_t>
+ array_size; // Number of items in array, only needed for strucrs
+ ConstString type_name; // Name of type, only needed for structs
- static const ConstString &
- GetFallbackStructName(); // Print this as the type name of a struct Element
- // If we can't resolve the actual struct name
+ static const ConstString &
+ GetFallbackStructName(); // Print this as the type name of a struct Element
+ // If we can't resolve the actual struct name
- bool
- shouldRefresh() const
- {
- const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
- const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid();
- return !valid_ptr || !valid_type || !datum_size.isValid();
- }
+ bool shouldRefresh() const {
+ const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
+ const bool valid_type =
+ type.isValid() && type_vec_size.isValid() && type_kind.isValid();
+ return !valid_ptr || !valid_type || !datum_size.isValid();
+ }
};
// This AllocationDetails class collects data associated with a single
// allocation instance.
-struct RenderScriptRuntime::AllocationDetails
-{
- struct Dimension
- {
- uint32_t dim_1;
- uint32_t dim_2;
- uint32_t dim_3;
- uint32_t cubeMap;
+struct RenderScriptRuntime::AllocationDetails {
+ struct Dimension {
+ uint32_t dim_1;
+ uint32_t dim_2;
+ uint32_t dim_3;
+ uint32_t cubeMap;
- Dimension()
- {
- dim_1 = 0;
- dim_2 = 0;
- dim_3 = 0;
- cubeMap = 0;
- }
- };
-
- // The FileHeader struct specifies the header we use for writing allocations to a binary file.
- // Our format begins with the ASCII characters "RSAD", identifying the file as an allocation dump.
- // Member variables dims and hdr_size are then written consecutively, immediately followed by an instance of
- // the ElementHeader struct. Because Elements can contain subelements, there may be more than one instance
- // of the ElementHeader struct. With this first instance being the root element, and the other instances being
- // the root's descendants. To identify which instances are an ElementHeader's children, each struct
- // is immediately followed by a sequence of consecutive offsets to the start of its child structs.
- // These offsets are 4 bytes in size, and the 0 offset signifies no more children.
- struct FileHeader
- {
- uint8_t ident[4]; // ASCII 'RSAD' identifying the file
- uint32_t dims[3]; // Dimensions
- uint16_t hdr_size; // Header size in bytes, including all element headers
- };
-
- struct ElementHeader
- {
- uint16_t type; // DataType enum
- uint32_t kind; // DataKind enum
- uint32_t element_size; // Size of a single element, including padding
- uint16_t vector_size; // Vector width
- uint32_t array_size; // Number of elements in array
- };
-
- // Monotonically increasing from 1
- static uint32_t ID;
-
- // Maps Allocation DataType enum and vector size to printable strings
- // using mapping from RenderScript numerical types summary documentation
- static const char *RsDataTypeToString[][4];
-
- // Maps Allocation DataKind enum to printable strings
- static const char *RsDataKindToString[];
-
- // Maps allocation types to format sizes for printing.
- static const uint32_t RSTypeToFormat[][3];
-
- // Give each allocation an ID as a way
- // for commands to reference it.
- const uint32_t id;
-
- RenderScriptRuntime::Element element; // Allocation Element type
- empirical_type<Dimension> dimension; // Dimensions of the Allocation
- empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation
- empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation
- empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation
- empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation
- empirical_type<uint32_t> size; // Size of the allocation
- empirical_type<uint32_t> stride; // Stride between rows of the allocation
-
- // Give each allocation an id, so we can reference it in user commands.
- AllocationDetails() : id(ID++) {}
-
- bool
- shouldRefresh() const
- {
- bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
- valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
- return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh();
+ Dimension() {
+ dim_1 = 0;
+ dim_2 = 0;
+ dim_3 = 0;
+ cubeMap = 0;
}
+ };
+
+ // The FileHeader struct specifies the header we use for writing allocations
+ // to a binary file.
+ // Our format begins with the ASCII characters "RSAD", identifying the file as
+ // an allocation dump.
+ // Member variables dims and hdr_size are then written consecutively,
+ // immediately followed by an instance of
+ // the ElementHeader struct. Because Elements can contain subelements, there
+ // may be more than one instance
+ // of the ElementHeader struct. With this first instance being the root
+ // element, and the other instances being
+ // the root's descendants. To identify which instances are an ElementHeader's
+ // children, each struct
+ // is immediately followed by a sequence of consecutive offsets to the start
+ // of its child structs.
+ // These offsets are 4 bytes in size, and the 0 offset signifies no more
+ // children.
+ struct FileHeader {
+ uint8_t ident[4]; // ASCII 'RSAD' identifying the file
+ uint32_t dims[3]; // Dimensions
+ uint16_t hdr_size; // Header size in bytes, including all element headers
+ };
+
+ struct ElementHeader {
+ uint16_t type; // DataType enum
+ uint32_t kind; // DataKind enum
+ uint32_t element_size; // Size of a single element, including padding
+ uint16_t vector_size; // Vector width
+ uint32_t array_size; // Number of elements in array
+ };
+
+ // Monotonically increasing from 1
+ static uint32_t ID;
+
+ // Maps Allocation DataType enum and vector size to printable strings
+ // using mapping from RenderScript numerical types summary documentation
+ static const char *RsDataTypeToString[][4];
+
+ // Maps Allocation DataKind enum to printable strings
+ static const char *RsDataKindToString[];
+
+ // Maps allocation types to format sizes for printing.
+ static const uint32_t RSTypeToFormat[][3];
+
+ // Give each allocation an ID as a way
+ // for commands to reference it.
+ const uint32_t id;
+
+ RenderScriptRuntime::Element element; // Allocation Element type
+ empirical_type<Dimension> dimension; // Dimensions of the Allocation
+ empirical_type<lldb::addr_t>
+ address; // Pointer to address of the RS Allocation
+ empirical_type<lldb::addr_t>
+ data_ptr; // Pointer to the data held by the Allocation
+ empirical_type<lldb::addr_t>
+ type_ptr; // Pointer to the RS Type of the Allocation
+ empirical_type<lldb::addr_t>
+ context; // Pointer to the RS Context of the Allocation
+ empirical_type<uint32_t> size; // Size of the allocation
+ empirical_type<uint32_t> stride; // Stride between rows of the allocation
+
+ // Give each allocation an id, so we can reference it in user commands.
+ AllocationDetails() : id(ID++) {}
+
+ bool shouldRefresh() const {
+ bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
+ valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
+ return !valid_ptrs || !dimension.isValid() || !size.isValid() ||
+ element.shouldRefresh();
+ }
};
-const ConstString &
-RenderScriptRuntime::Element::GetFallbackStructName()
-{
- static const ConstString FallbackStructName("struct");
- return FallbackStructName;
+const ConstString &RenderScriptRuntime::Element::GetFallbackStructName() {
+ static const ConstString FallbackStructName("struct");
+ return FallbackStructName;
}
uint32_t RenderScriptRuntime::AllocationDetails::ID = 1;
const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = {
- "User",
- "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
+ "User", "Undefined", "Undefined", "Undefined",
+ "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
"L Pixel", "A Pixel", "LA Pixel", "RGB Pixel",
"RGBA Pixel", "Pixel Depth", "YUV Pixel"};
@@ -720,54 +664,64 @@
// Deprecated
{"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
- {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"},
- {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"},
- {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"},
- {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"},
+ {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment",
+ "RS Program Fragment"},
+ {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex",
+ "RS Program Vertex"},
+ {"RS Program Raster", "RS Program Raster", "RS Program Raster",
+ "RS Program Raster"},
+ {"RS Program Store", "RS Program Store", "RS Program Store",
+ "RS Program Store"},
{"RS Font", "RS Font", "RS Font", "RS Font"}};
// Used as an index into the RSTypeToFormat array elements
-enum TypeToFormatIndex
-{
- eFormatSingle = 0,
- eFormatVector,
- eElementSize
-};
+enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize };
-// { format enum of single element, format enum of element vector, size of element}
+// { format enum of single element, format enum of element vector, size of
+// element}
const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = {
- {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
- {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
- {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
- {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
- {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
- {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
- {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
- {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
- {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
- {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
- {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
- {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
- {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
- {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
- {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
+ {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
+ {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
+ {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
+ {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
+ {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
+ {eFormatDecimal, eFormatVectorOfSInt16,
+ sizeof(int16_t)}, // RS_TYPE_SIGNED_16
+ {eFormatDecimal, eFormatVectorOfSInt32,
+ sizeof(int32_t)}, // RS_TYPE_SIGNED_32
+ {eFormatDecimal, eFormatVectorOfSInt64,
+ sizeof(int64_t)}, // RS_TYPE_SIGNED_64
+ {eFormatDecimal, eFormatVectorOfUInt8,
+ sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
+ {eFormatDecimal, eFormatVectorOfUInt16,
+ sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
+ {eFormatDecimal, eFormatVectorOfUInt32,
+ sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
+ {eFormatDecimal, eFormatVectorOfUInt64,
+ sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
+ {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32,
+ sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
};
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
LanguageRuntime *
-RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
-{
+RenderScriptRuntime::CreateInstance(Process *process,
+ lldb::LanguageType language) {
- if (language == eLanguageTypeExtRenderScript)
- return new RenderScriptRuntime(process);
- else
- return nullptr;
+ if (language == eLanguageTypeExtRenderScript)
+ return new RenderScriptRuntime(process);
+ else
+ return nullptr;
}
// Callback with a module to search for matching symbols.
@@ -775,1896 +729,1862 @@
// Then look for a symbol which matches our kernel name.
// The breakpoint address is finally set using the address of this symbol.
Searcher::CallbackReturn
-RSBreakpointResolver::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *, bool)
-{
- ModuleSP module = context.module_sp;
+RSBreakpointResolver::SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *, bool) {
+ ModuleSP module = context.module_sp;
- if (!module)
- return Searcher::eCallbackReturnContinue;
-
- // Is this a module containing renderscript kernels?
- if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
- return Searcher::eCallbackReturnContinue;
-
- // Attempt to set a breakpoint on the kernel name symbol within the module library.
- // If it's not found, it's likely debug info is unavailable - try to set a
- // breakpoint on <name>.expand.
-
- const Symbol *kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
- if (!kernel_sym)
- {
- std::string kernel_name_expanded(m_kernel_name.AsCString());
- kernel_name_expanded.append(".expand");
- kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
- }
-
- if (kernel_sym)
- {
- Address bp_addr = kernel_sym->GetAddress();
- if (filter.AddressPasses(bp_addr))
- m_breakpoint->AddLocation(bp_addr);
- }
-
+ if (!module)
return Searcher::eCallbackReturnContinue;
+
+ // Is this a module containing renderscript kernels?
+ if (nullptr ==
+ module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"),
+ eSymbolTypeData))
+ return Searcher::eCallbackReturnContinue;
+
+ // Attempt to set a breakpoint on the kernel name symbol within the module
+ // library.
+ // If it's not found, it's likely debug info is unavailable - try to set a
+ // breakpoint on <name>.expand.
+
+ const Symbol *kernel_sym =
+ module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
+ if (!kernel_sym) {
+ std::string kernel_name_expanded(m_kernel_name.AsCString());
+ kernel_name_expanded.append(".expand");
+ kernel_sym = module->FindFirstSymbolWithNameAndType(
+ ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ }
+
+ if (kernel_sym) {
+ Address bp_addr = kernel_sym->GetAddress();
+ if (filter.AddressPasses(bp_addr))
+ m_breakpoint->AddLocation(bp_addr);
+ }
+
+ return Searcher::eCallbackReturnContinue;
}
-void
-RenderScriptRuntime::Initialize()
-{
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance,
- GetCommandObject);
+void RenderScriptRuntime::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "RenderScript language support", CreateInstance,
+ GetCommandObject);
}
-void
-RenderScriptRuntime::Terminate()
-{
- PluginManager::UnregisterPlugin(CreateInstance);
+void RenderScriptRuntime::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
}
-lldb_private::ConstString
-RenderScriptRuntime::GetPluginNameStatic()
-{
- static ConstString g_name("renderscript");
- return g_name;
+lldb_private::ConstString RenderScriptRuntime::GetPluginNameStatic() {
+ static ConstString g_name("renderscript");
+ return g_name;
}
RenderScriptRuntime::ModuleKind
-RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
-{
- if (module_sp)
- {
- // Is this a module containing renderscript kernels?
- const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
- if (info_sym)
- {
- return eModuleKindKernelObj;
- }
-
- // Is this the main RS runtime library
- const ConstString rs_lib("libRS.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_lib)
- {
- return eModuleKindLibRS;
- }
-
- const ConstString rs_driverlib("libRSDriver.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
- {
- return eModuleKindDriver;
- }
-
- const ConstString rs_cpureflib("libRSCpuRef.so");
- if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
- {
- return eModuleKindImpl;
- }
+RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) {
+ if (module_sp) {
+ // Is this a module containing renderscript kernels?
+ const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(
+ ConstString(".rs.info"), eSymbolTypeData);
+ if (info_sym) {
+ return eModuleKindKernelObj;
}
- return eModuleKindIgnored;
+
+ // Is this the main RS runtime library
+ const ConstString rs_lib("libRS.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_lib) {
+ return eModuleKindLibRS;
+ }
+
+ const ConstString rs_driverlib("libRSDriver.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) {
+ return eModuleKindDriver;
+ }
+
+ const ConstString rs_cpureflib("libRSCpuRef.so");
+ if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) {
+ return eModuleKindImpl;
+ }
+ }
+ return eModuleKindIgnored;
}
-bool
-RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
-{
- return GetModuleKind(module_sp) != eModuleKindIgnored;
+bool RenderScriptRuntime::IsRenderScriptModule(
+ const lldb::ModuleSP &module_sp) {
+ return GetModuleKind(module_sp) != eModuleKindIgnored;
}
-void
-RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list)
-{
- std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
+void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) {
+ std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
- size_t num_modules = module_list.GetSize();
- for (size_t i = 0; i < num_modules; i++)
- {
- auto mod = module_list.GetModuleAtIndex(i);
- if (IsRenderScriptModule(mod))
- {
- LoadModule(mod);
- }
+ size_t num_modules = module_list.GetSize();
+ for (size_t i = 0; i < num_modules; i++) {
+ auto mod = module_list.GetModuleAtIndex(i);
+ if (IsRenderScriptModule(mod)) {
+ LoadModule(mod);
}
+ }
}
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
-lldb_private::ConstString
-RenderScriptRuntime::GetPluginName()
-{
- return GetPluginNameStatic();
+lldb_private::ConstString RenderScriptRuntime::GetPluginName() {
+ return GetPluginNameStatic();
}
-uint32_t
-RenderScriptRuntime::GetPluginVersion()
-{
- return 1;
-}
+uint32_t RenderScriptRuntime::GetPluginVersion() { return 1; }
-bool
-RenderScriptRuntime::IsVTableName(const char *name)
-{
- return false;
-}
+bool RenderScriptRuntime::IsVTableName(const char *name) { return false; }
-bool
-RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type)
-{
- return false;
+bool RenderScriptRuntime::GetDynamicTypeAndAddress(
+ ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) {
+ return false;
}
TypeAndOrName
-RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
-{
- return type_and_or_name;
+RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) {
+ return type_and_or_name;
}
-bool
-RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
-{
- return false;
+bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
+ return false;
}
lldb::BreakpointResolverSP
-RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
-{
- BreakpointResolverSP resolver_sp;
- return resolver_sp;
+RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
+ bool throw_bp) {
+ BreakpointResolverSP resolver_sp;
+ return resolver_sp;
}
-const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = {
- // rsdScript
+const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
{
- "rsdScriptInit",
- "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj",
- "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureScriptInit
- },
- {
- "rsdScriptInvokeForEachMulti",
- "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
- "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti
- },
- {
- "rsdScriptSetGlobalVar",
- "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj",
- "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar
- },
+ // rsdScript
+ {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP"
+ "NS0_7ScriptCEPKcS7_PKhjj",
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_"
+ "7ScriptCEPKcS7_PKhmj",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureScriptInit},
+ {"rsdScriptInvokeForEachMulti",
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
+ "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
+ "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti},
+ {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render"
+ "script7ContextEPKNS0_6ScriptEjPvj",
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_"
+ "6ScriptEjPvm",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar},
- // rsdAllocation
- {
- "rsdAllocationInit",
- "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb",
- "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureAllocationInit
- },
- {
- "rsdAllocationRead2D",
- "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
- "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- nullptr
- },
- {
- "rsdAllocationDestroy",
- "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE",
- "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE",
- 0,
- RenderScriptRuntime::eModuleKindDriver,
- &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy
- },
+ // rsdAllocation
+ {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C"
+ "ontextEPNS0_10AllocationEb",
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_"
+ "10AllocationEb",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureAllocationInit},
+ {"rsdAllocationRead2D",
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
+ "10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
+ "10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
+ 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc"
+ "ript7ContextEPNS0_10AllocationE",
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_"
+ "10AllocationE",
+ 0, RenderScriptRuntime::eModuleKindDriver,
+ &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},
};
-const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
+const size_t RenderScriptRuntime::s_runtimeHookCount =
+ sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
-bool
-RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id)
-{
- RuntimeHook *hook_info = (RuntimeHook *)baton;
- ExecutionContext context(ctx->exe_ctx_ref);
+bool RenderScriptRuntime::HookCallback(void *baton,
+ StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id) {
+ RuntimeHook *hook_info = (RuntimeHook *)baton;
+ ExecutionContext context(ctx->exe_ctx_ref);
- RenderScriptRuntime *lang_rt =
- (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ RenderScriptRuntime *lang_rt =
+ (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
- lang_rt->HookCallback(hook_info, context);
+ lang_rt->HookCallback(hook_info, context);
- return false;
+ return false;
}
-void
-RenderScriptRuntime::HookCallback(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::HookCallback(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log)
+ log->Printf("%s - '%s'", __FUNCTION__, hook_info->defn->name);
+
+ if (hook_info->defn->grabber) {
+ (this->*(hook_info->defn->grabber))(hook_info, context);
+ }
+}
+
+void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
+ RuntimeHook *hook_info, ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum {
+ eRsContext = 0,
+ eRsScript,
+ eRsSlot,
+ eRsAIns,
+ eRsInLen,
+ eRsAOut,
+ eRsUsr,
+ eRsUsrLen,
+ eRsSc,
+ };
+
+ std::array<ArgItem, 9> args{{
+ ArgItem{ArgItem::ePointer, 0}, // const Context *rsc
+ ArgItem{ArgItem::ePointer, 0}, // Script *s
+ ArgItem{ArgItem::eInt32, 0}, // uint32_t slot
+ ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns
+ ArgItem{ArgItem::eInt32, 0}, // size_t inLen
+ ArgItem{ArgItem::ePointer, 0}, // Allocation *aout
+ ArgItem{ArgItem::ePointer, 0}, // const void *usr
+ ArgItem{ArgItem::eInt32, 0}, // size_t usrLen
+ ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc
+ }};
+
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
if (log)
- log->Printf("%s - '%s'", __FUNCTION__, hook_info->defn->name);
+ log->Printf("%s - Error while reading the function parameters",
+ __FUNCTION__);
+ return;
+ }
- if (hook_info->defn->grabber)
- {
- (this->*(hook_info->defn->grabber))(hook_info, context);
+ const uint32_t target_ptr_size = m_process->GetAddressByteSize();
+ Error error;
+ std::vector<uint64_t> allocs;
+
+ // traverse allocation list
+ for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) {
+ // calculate offest to allocation pointer
+ const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;
+
+ // Note: due to little endian layout, reading 32bits or 64bits into res64
+ // will
+ // give the correct results.
+
+ uint64_t res64 = 0;
+ size_t read = m_process->ReadMemory(addr, &res64, target_ptr_size, error);
+ if (read != target_ptr_size || !error.Success()) {
+ if (log)
+ log->Printf(
+ "%s - Error while reading allocation list argument %" PRIu64,
+ __FUNCTION__, i);
+ } else {
+ allocs.push_back(res64);
}
+ }
+
+ // if there is an output allocation track it
+ if (uint64_t aOut = uint64_t(args[eRsAOut])) {
+ allocs.push_back(aOut);
+ }
+
+ // for all allocations we have found
+ for (const uint64_t alloc_addr : allocs) {
+ AllocationDetails *alloc = LookUpAllocation(alloc_addr);
+ if (!alloc)
+ alloc = CreateAllocation(alloc_addr);
+
+ if (alloc) {
+ // save the allocation address
+ if (alloc->address.isValid()) {
+ // check the allocation address we already have matches
+ assert(*alloc->address.get() == alloc_addr);
+ } else {
+ alloc->address = alloc_addr;
+ }
+
+ // save the context
+ if (log) {
+ if (alloc->context.isValid() &&
+ *alloc->context.get() != addr_t(args[eRsContext]))
+ log->Printf("%s - Allocation used by multiple contexts",
+ __FUNCTION__);
+ }
+ alloc->context = addr_t(args[eRsContext]);
+ }
+ }
+
+ // make sure we track this script object
+ if (lldb_private::RenderScriptRuntime::ScriptDetails *script =
+ LookUpScript(addr_t(args[eRsScript]), true)) {
+ if (log) {
+ if (script->context.isValid() &&
+ *script->context.get() != addr_t(args[eRsContext]))
+ log->Printf("%s - Script used by multiple contexts", __FUNCTION__);
+ }
+ script->context = addr_t(args[eRsContext]);
+ }
}
-void
-RenderScriptRuntime::CaptureScriptInvokeForEachMulti(RuntimeHook* hook_info,
- ExecutionContext& context)
-{
- Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- enum
- {
- eRsContext = 0,
- eRsScript,
- eRsSlot,
- eRsAIns,
- eRsInLen,
- eRsAOut,
- eRsUsr,
- eRsUsrLen,
- eRsSc,
- };
+ enum {
+ eRsContext,
+ eRsScript,
+ eRsId,
+ eRsData,
+ eRsLength,
+ };
- std::array<ArgItem, 9> args{{
- ArgItem{ArgItem::ePointer, 0}, // const Context *rsc
- ArgItem{ArgItem::ePointer, 0}, // Script *s
- ArgItem{ArgItem::eInt32, 0}, // uint32_t slot
- ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns
- ArgItem{ArgItem::eInt32, 0}, // size_t inLen
- ArgItem{ArgItem::ePointer, 0}, // Allocation *aout
- ArgItem{ArgItem::ePointer, 0}, // const void *usr
- ArgItem{ArgItem::eInt32, 0}, // size_t usrLen
- ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc
- }};
+ std::array<ArgItem, 5> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsScript
+ ArgItem{ArgItem::eInt32, 0}, // eRsId
+ ArgItem{ArgItem::ePointer, 0}, // eRsData
+ ArgItem{ArgItem::eInt32, 0}, // eRsLength
+ }};
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - Error while reading the function parameters", __FUNCTION__);
- return;
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error reading the function parameters.", __FUNCTION__);
+ return;
+ }
+
+ if (log) {
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64
+ ":%" PRIu64 "bytes.",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
+ uint64_t(args[eRsData]), uint64_t(args[eRsLength]));
+
+ addr_t script_addr = addr_t(args[eRsScript]);
+ if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) {
+ auto rsm = m_scriptMappings[script_addr];
+ if (uint64_t(args[eRsId]) < rsm->m_globals.size()) {
+ auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
+ log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__,
+ rsg.m_name.AsCString(),
+ rsm->m_module->GetFileSpec().GetFilename().AsCString());
+ }
}
-
- const uint32_t target_ptr_size = m_process->GetAddressByteSize();
- Error error;
- std::vector<uint64_t> allocs;
-
- // traverse allocation list
- for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i)
- {
- // calculate offest to allocation pointer
- const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;
-
- // Note: due to little endian layout, reading 32bits or 64bits into res64 will
- // give the correct results.
-
- uint64_t res64 = 0;
- size_t read = m_process->ReadMemory(addr, &res64, target_ptr_size, error);
- if (read != target_ptr_size || !error.Success())
- {
- if (log)
- log->Printf("%s - Error while reading allocation list argument %" PRIu64, __FUNCTION__, i);
- }
- else
- {
- allocs.push_back(res64);
- }
- }
-
- // if there is an output allocation track it
- if (uint64_t aOut = uint64_t(args[eRsAOut]))
- {
- allocs.push_back(aOut);
- }
-
- // for all allocations we have found
- for (const uint64_t alloc_addr : allocs)
- {
- AllocationDetails *alloc = LookUpAllocation(alloc_addr);
- if (!alloc)
- alloc = CreateAllocation(alloc_addr);
-
- if (alloc)
- {
- // save the allocation address
- if (alloc->address.isValid())
- {
- // check the allocation address we already have matches
- assert(*alloc->address.get() == alloc_addr);
- }
- else
- {
- alloc->address = alloc_addr;
- }
-
- // save the context
- if (log)
- {
- if (alloc->context.isValid() && *alloc->context.get() != addr_t(args[eRsContext]))
- log->Printf("%s - Allocation used by multiple contexts", __FUNCTION__);
- }
- alloc->context = addr_t(args[eRsContext]);
- }
- }
-
- // make sure we track this script object
- if (lldb_private::RenderScriptRuntime::ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true))
- {
- if (log)
- {
- if (script->context.isValid() && *script->context.get() != addr_t(args[eRsContext]))
- log->Printf("%s - Script used by multiple contexts", __FUNCTION__);
- }
- script->context = addr_t(args[eRsContext]);
- }
+ }
}
-void
-RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- enum
- {
- eRsContext,
- eRsScript,
- eRsId,
- eRsData,
- eRsLength,
- };
+ enum { eRsContext, eRsAlloc, eRsForceZero };
- std::array<ArgItem, 5> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsScript
- ArgItem{ArgItem::eInt32, 0}, // eRsId
- ArgItem{ArgItem::ePointer, 0}, // eRsData
- ArgItem{ArgItem::eInt32, 0}, // eRsLength
- }};
+ std::array<ArgItem, 3> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
+ ArgItem{ArgItem::eBool, 0}, // eRsForceZero
+ }};
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - error reading the function parameters.", __FUNCTION__);
- return;
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) // error case
+ {
+ if (log)
+ log->Printf("%s - error while reading the function parameters",
+ __FUNCTION__);
+ return; // abort
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero]));
+
+ AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
+ if (alloc)
+ alloc->context = uint64_t(args[eRsContext]);
+}
+
+void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ enum {
+ eRsContext,
+ eRsAlloc,
+ };
+
+ std::array<ArgItem, 2> args{{
+ ArgItem{ArgItem::ePointer, 0}, // eRsContext
+ ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
+ }};
+
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error while reading the function parameters.",
+ __FUNCTION__);
+ return;
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__,
+ uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]));
+
+ for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) {
+ auto &allocation_ap = *iter; // get the unique pointer
+ if (allocation_ap->address.isValid() &&
+ *allocation_ap->address.get() == addr_t(args[eRsAlloc])) {
+ m_allocations.erase(iter);
+ if (log)
+ log->Printf("%s - deleted allocation entry.", __FUNCTION__);
+ return;
+ }
+ }
+
+ if (log)
+ log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__);
+}
+
+void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook_info,
+ ExecutionContext &context) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ Error error;
+ Process *process = context.GetProcessPtr();
+
+ enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr };
+
+ std::array<ArgItem, 4> args{
+ {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
+ ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
+ bool success = GetArgs(context, &args[0], args.size());
+ if (!success) {
+ if (log)
+ log->Printf("%s - error while reading the function parameters.",
+ __FUNCTION__);
+ return;
+ }
+
+ std::string resname;
+ process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), resname, error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - error reading resname: %s.", __FUNCTION__,
+ error.AsCString());
+ }
+
+ std::string cachedir;
+ process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cachedir,
+ error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - error reading cachedir: %s.", __FUNCTION__,
+ error.AsCString());
+ }
+
+ if (log)
+ log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
+ __FUNCTION__, uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]), resname.c_str(), cachedir.c_str());
+
+ if (resname.size() > 0) {
+ StreamString strm;
+ strm.Printf("librs.%s.so", resname.c_str());
+
+ ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
+ if (script) {
+ script->type = ScriptDetails::eScriptC;
+ script->cacheDir = cachedir;
+ script->resName = resname;
+ script->scriptDyLib = strm.GetData();
+ script->context = addr_t(args[eRsContext]);
}
if (log)
- {
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", __FUNCTION__,
- uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
- uint64_t(args[eRsData]), uint64_t(args[eRsLength]));
-
- addr_t script_addr = addr_t(args[eRsScript]);
- if (m_scriptMappings.find(script_addr) != m_scriptMappings.end())
- {
- auto rsm = m_scriptMappings[script_addr];
- if (uint64_t(args[eRsId]) < rsm->m_globals.size())
- {
- auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
- log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__, rsg.m_name.AsCString(),
- rsm->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
- }
+ log->Printf("%s - '%s' tagged with context 0x%" PRIx64
+ " and script 0x%" PRIx64 ".",
+ __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]),
+ uint64_t(args[eRsScript]));
+ } else if (log) {
+ log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__);
+ }
}
-void
-RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
+ ModuleKind kind) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- enum
- {
- eRsContext,
- eRsAlloc,
- eRsForceZero
- };
+ if (!module) {
+ return;
+ }
- std::array<ArgItem, 3> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
- ArgItem{ArgItem::eBool, 0}, // eRsForceZero
- }};
+ Target &target = GetProcess()->GetTarget();
+ llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
- bool success = GetArgs(context, &args[0], args.size());
- if (!success) // error case
- {
- if (log)
- log->Printf("%s - error while reading the function parameters", __FUNCTION__);
- return; // abort
- }
-
+ if (targetArchType != llvm::Triple::ArchType::x86 &&
+ targetArchType != llvm::Triple::ArchType::arm &&
+ targetArchType != llvm::Triple::ArchType::aarch64 &&
+ targetArchType != llvm::Triple::ArchType::mipsel &&
+ targetArchType != llvm::Triple::ArchType::mips64el &&
+ targetArchType != llvm::Triple::ArchType::x86_64) {
if (log)
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero]));
+ log->Printf("%s - unable to hook runtime functions.", __FUNCTION__);
+ return;
+ }
- AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
- if (alloc)
- alloc->context = uint64_t(args[eRsContext]);
+ uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
+
+ for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
+ const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
+ if (hook_defn->kind != kind) {
+ continue;
+ }
+
+ const char *symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32
+ : hook_defn->symbol_name_m64;
+
+ const Symbol *sym = module->FindFirstSymbolWithNameAndType(
+ ConstString(symbol_name), eSymbolTypeCode);
+ if (!sym) {
+ if (log) {
+ log->Printf("%s - symbol '%s' related to the function %s not found",
+ __FUNCTION__, symbol_name, hook_defn->name);
+ }
+ continue;
+ }
+
+ addr_t addr = sym->GetLoadAddress(&target);
+ if (addr == LLDB_INVALID_ADDRESS) {
+ if (log)
+ log->Printf("%s - unable to resolve the address of hook function '%s' "
+ "with symbol '%s'.",
+ __FUNCTION__, hook_defn->name, symbol_name);
+ continue;
+ } else {
+ if (log)
+ log->Printf("%s - function %s, address resolved at 0x%" PRIx64,
+ __FUNCTION__, hook_defn->name, addr);
+ }
+
+ RuntimeHookSP hook(new RuntimeHook());
+ hook->address = addr;
+ hook->defn = hook_defn;
+ hook->bp_sp = target.CreateBreakpoint(addr, true, false);
+ hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
+ m_runtimeHooks[addr] = hook;
+ if (log) {
+ log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64
+ " at 0x%" PRIx64 ".",
+ __FUNCTION__, hook_defn->name,
+ module->GetFileSpec().GetFilename().AsCString(),
+ (uint64_t)hook_defn->version, (uint64_t)addr);
+ }
+ }
}
-void
-RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
+ if (!rsmodule_sp)
+ return;
- enum
- {
- eRsContext,
- eRsAlloc,
- };
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- std::array<ArgItem, 2> args{{
- ArgItem{ArgItem::ePointer, 0}, // eRsContext
- ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
- }};
+ const ModuleSP module = rsmodule_sp->m_module;
+ const FileSpec &file = module->GetPlatformFileSpec();
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
+ // Iterate over all of the scripts that we currently know of.
+ // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ for (const auto &rs_script : m_scripts) {
+ // Extract the expected .so file path for this script.
+ std::string dylib;
+ if (!rs_script->scriptDyLib.get(dylib))
+ continue;
+
+ // Only proceed if the module that has loaded corresponds to this script.
+ if (file.GetFilename() != ConstString(dylib.c_str()))
+ continue;
+
+ // Obtain the script address which we use as a key.
+ lldb::addr_t script;
+ if (!rs_script->script.get(script))
+ continue;
+
+ // If we have a script mapping for the current script.
+ if (m_scriptMappings.find(script) != m_scriptMappings.end()) {
+ // if the module we have stored is different to the one we just received.
+ if (m_scriptMappings[script] != rsmodule_sp) {
if (log)
- log->Printf("%s - error while reading the function parameters.", __FUNCTION__);
- return;
+ log->Printf(
+ "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+ __FUNCTION__, (uint64_t)script,
+ rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
}
-
- if (log)
- log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsAlloc]));
-
- for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter)
- {
- auto &allocation_ap = *iter; // get the unique pointer
- if (allocation_ap->address.isValid() && *allocation_ap->address.get() == addr_t(args[eRsAlloc]))
- {
- m_allocations.erase(iter);
- if (log)
- log->Printf("%s - deleted allocation entry.", __FUNCTION__);
- return;
- }
+ // We don't have a script mapping for the current script.
+ else {
+ // Obtain the script resource name.
+ std::string resName;
+ if (rs_script->resName.get(resName))
+ // Set the modules resource name.
+ rsmodule_sp->m_resname = resName;
+ // Add Script/Module pair to map.
+ m_scriptMappings[script] = rsmodule_sp;
+ if (log)
+ log->Printf(
+ "%s - script %" PRIx64 " associated with rsmodule '%s'.",
+ __FUNCTION__, (uint64_t)script,
+ rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
}
-
- if (log)
- log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__);
+ }
}
-void
-RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- Error error;
- Process *process = context.GetProcessPtr();
-
- enum
- {
- eRsContext,
- eRsScript,
- eRsResNamePtr,
- eRsCachedDirPtr
- };
-
- std::array<ArgItem, 4> args{{ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
- ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
- bool success = GetArgs(context, &args[0], args.size());
- if (!success)
- {
- if (log)
- log->Printf("%s - error while reading the function parameters.", __FUNCTION__);
- return;
- }
-
- std::string resname;
- process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), resname, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - error reading resname: %s.", __FUNCTION__, error.AsCString());
- }
-
- std::string cachedir;
- process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cachedir, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - error reading cachedir: %s.", __FUNCTION__, error.AsCString());
- }
-
- if (log)
- log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", __FUNCTION__, uint64_t(args[eRsContext]),
- uint64_t(args[eRsScript]), resname.c_str(), cachedir.c_str());
-
- if (resname.size() > 0)
- {
- StreamString strm;
- strm.Printf("librs.%s.so", resname.c_str());
-
- ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
- if (script)
- {
- script->type = ScriptDetails::eScriptC;
- script->cacheDir = cachedir;
- script->resName = resname;
- script->scriptDyLib = strm.GetData();
- script->context = addr_t(args[eRsContext]);
- }
-
- if (log)
- log->Printf("%s - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", __FUNCTION__,
- strm.GetData(), uint64_t(args[eRsContext]), uint64_t(args[eRsScript]));
- }
- else if (log)
- {
- log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__);
- }
-}
-
-void
-RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!module)
- {
- return;
- }
-
- Target &target = GetProcess()->GetTarget();
- llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
-
- if (targetArchType != llvm::Triple::ArchType::x86 &&
- targetArchType != llvm::Triple::ArchType::arm &&
- targetArchType != llvm::Triple::ArchType::aarch64 &&
- targetArchType != llvm::Triple::ArchType::mipsel &&
- targetArchType != llvm::Triple::ArchType::mips64el &&
- targetArchType != llvm::Triple::ArchType::x86_64)
- {
- if (log)
- log->Printf("%s - unable to hook runtime functions.", __FUNCTION__);
- return;
- }
-
- uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
-
- for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
- {
- const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
- if (hook_defn->kind != kind)
- {
- continue;
- }
-
- const char *symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
-
- const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
- if (!sym)
- {
- if (log)
- {
- log->Printf("%s - symbol '%s' related to the function %s not found",
- __FUNCTION__, symbol_name, hook_defn->name);
- }
- continue;
- }
-
- addr_t addr = sym->GetLoadAddress(&target);
- if (addr == LLDB_INVALID_ADDRESS)
- {
- if (log)
- log->Printf("%s - unable to resolve the address of hook function '%s' with symbol '%s'.",
- __FUNCTION__, hook_defn->name, symbol_name);
- continue;
- }
- else
- {
- if (log)
- log->Printf("%s - function %s, address resolved at 0x%" PRIx64,
- __FUNCTION__, hook_defn->name, addr);
- }
-
- RuntimeHookSP hook(new RuntimeHook());
- hook->address = addr;
- hook->defn = hook_defn;
- hook->bp_sp = target.CreateBreakpoint(addr, true, false);
- hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
- m_runtimeHooks[addr] = hook;
- if (log)
- {
- log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
- __FUNCTION__, hook_defn->name, module->GetFileSpec().GetFilename().AsCString(),
- (uint64_t)hook_defn->version, (uint64_t)addr);
- }
- }
-}
-
-void
-RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
-{
- if (!rsmodule_sp)
- return;
-
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- const ModuleSP module = rsmodule_sp->m_module;
- const FileSpec &file = module->GetPlatformFileSpec();
-
- // Iterate over all of the scripts that we currently know of.
- // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
- for (const auto &rs_script : m_scripts)
- {
- // Extract the expected .so file path for this script.
- std::string dylib;
- if (!rs_script->scriptDyLib.get(dylib))
- continue;
-
- // Only proceed if the module that has loaded corresponds to this script.
- if (file.GetFilename() != ConstString(dylib.c_str()))
- continue;
-
- // Obtain the script address which we use as a key.
- lldb::addr_t script;
- if (!rs_script->script.get(script))
- continue;
-
- // If we have a script mapping for the current script.
- if (m_scriptMappings.find(script) != m_scriptMappings.end())
- {
- // if the module we have stored is different to the one we just received.
- if (m_scriptMappings[script] != rsmodule_sp)
- {
- if (log)
- log->Printf("%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", __FUNCTION__,
- (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
- // We don't have a script mapping for the current script.
- else
- {
- // Obtain the script resource name.
- std::string resName;
- if (rs_script->resName.get(resName))
- // Set the modules resource name.
- rsmodule_sp->m_resname = resName;
- // Add Script/Module pair to map.
- m_scriptMappings[script] = rsmodule_sp;
- if (log)
- log->Printf("%s - script %" PRIx64 " associated with rsmodule '%s'.", __FUNCTION__,
- (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
- }
-}
-
-// Uses the Target API to evaluate the expression passed as a parameter to the function
-// The result of that expression is returned an unsigned 64 bit int, via the result* parameter.
+// Uses the Target API to evaluate the expression passed as a parameter to the
+// function
+// The result of that expression is returned an unsigned 64 bit int, via the
+// result* parameter.
// Function returns true on success, and false on failure
-bool
-RenderScriptRuntime::EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::EvalRSExpression(const char *expression,
+ StackFrame *frame_ptr,
+ uint64_t *result) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log)
+ log->Printf("%s(%s)", __FUNCTION__, expression);
+
+ ValueObjectSP expr_result;
+ EvaluateExpressionOptions options;
+ options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
+ // Perform the actual expression evaluation
+ GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr,
+ expr_result, options);
+
+ if (!expr_result) {
if (log)
- log->Printf("%s(%s)", __FUNCTION__, expression);
+ log->Printf("%s: couldn't evaluate expression.", __FUNCTION__);
+ return false;
+ }
- ValueObjectSP expr_result;
- EvaluateExpressionOptions options;
- options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
- // Perform the actual expression evaluation
- GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result, options);
-
- if (!expr_result)
+ // The result of the expression is invalid
+ if (!expr_result->GetError().Success()) {
+ Error err = expr_result->GetError();
+ if (err.GetError() == UserExpression::kNoResult) // Expression returned
+ // void, so this is
+ // actually a success
{
- if (log)
- log->Printf("%s: couldn't evaluate expression.", __FUNCTION__);
- return false;
+ if (log)
+ log->Printf("%s - expression returned void.", __FUNCTION__);
+
+ result = nullptr;
+ return true;
}
- // The result of the expression is invalid
- if (!expr_result->GetError().Success())
- {
- Error err = expr_result->GetError();
- if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
- {
- if (log)
- log->Printf("%s - expression returned void.", __FUNCTION__);
+ if (log)
+ log->Printf("%s - error evaluating expression result: %s", __FUNCTION__,
+ err.AsCString());
+ return false;
+ }
- result = nullptr;
- return true;
- }
+ bool success = false;
+ *result = expr_result->GetValueAsUnsigned(
+ 0, &success); // We only read the result as an uint32_t.
- if (log)
- log->Printf("%s - error evaluating expression result: %s", __FUNCTION__,
- err.AsCString());
- return false;
- }
+ if (!success) {
+ if (log)
+ log->Printf("%s - couldn't convert expression result to uint32_t",
+ __FUNCTION__);
+ return false;
+ }
- bool success = false;
- *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an uint32_t.
-
- if (!success)
- {
- if (log)
- log->Printf("%s - couldn't convert expression result to uint32_t", __FUNCTION__);
- return false;
- }
-
- return true;
+ return true;
}
-namespace
-{
+namespace {
// Used to index expression format strings
-enum ExpressionStrings
-{
- eExprGetOffsetPtr = 0,
- eExprAllocGetType,
- eExprTypeDimX,
- eExprTypeDimY,
- eExprTypeDimZ,
- eExprTypeElemPtr,
- eExprElementType,
- eExprElementKind,
- eExprElementVec,
- eExprElementFieldCount,
- eExprSubelementsId,
- eExprSubelementsName,
- eExprSubelementsArrSize,
+enum ExpressionStrings {
+ eExprGetOffsetPtr = 0,
+ eExprAllocGetType,
+ eExprTypeDimX,
+ eExprTypeDimY,
+ eExprTypeDimZ,
+ eExprTypeElemPtr,
+ eExprElementType,
+ eExprElementKind,
+ eExprElementVec,
+ eExprElementFieldCount,
+ eExprSubelementsId,
+ eExprSubelementsName,
+ eExprSubelementsArrSize,
- _eExprLast // keep at the end, implicit size of the array runtimeExpressions
+ _eExprLast // keep at the end, implicit size of the array runtimeExpressions
};
// max length of an expanded expression
const int jit_max_expr_size = 512;
// Retrieve the string to JIT for the given expression
-const char*
-JITTemplate(ExpressionStrings e)
-{
- // Format strings containing the expressions we may need to evaluate.
- static std::array<const char*, _eExprLast> runtimeExpressions = {{
- // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
- "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace"
- "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)",
+const char *JITTemplate(ExpressionStrings e) {
+ // Format strings containing the expressions we may need to evaluate.
+ static std::array<const char *, _eExprLast> runtimeExpressions = {
+ {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "(int*)_"
+ "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
+ "CubemapFace"
+ "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)",
- // Type* rsaAllocationGetType(Context*, Allocation*)
- "(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")",
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")",
- // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
- // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
- // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
- // Need to specify 32 or 64 bit for uint_t since this differs between devices
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[0]", // X dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[1]", // Y dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[2]", // Z dim
- "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[5]", // Element ptr
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY;
+ // mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between
+ // devices
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[0]", // X dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[1]", // Y dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[2]", // Z dim
+ "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 6); data[5]", // Element ptr
- // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
- // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[0]", // Type
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[1]", // Kind
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size
- "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[4]", // Field Count
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
+ // elemData
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[0]", // Type
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[1]", // Kind
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64
+ ", 0x%" PRIx64 ", data, 5); data[4]", // Field Count
- // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
- // size_t *arraySizes, uint32_t dataSize)
- // Needed for Allocations of structs to gather details about fields/Subelements
- // Element* of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]",
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
+ // *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about
+ // fields/Subelements
+ // Element* of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]",
- // Name of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]",
+ // Name of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]",
- // Array size of field
- "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];"
- "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"
- }};
+ // Array size of field
+ "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
+ "]; size_t arr_size[%" PRIu32 "];"
+ "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64
+ ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}};
- return runtimeExpressions[e];
+ return runtimeExpressions[e];
}
} // end of the anonymous namespace
-
// JITs the RS runtime for the internal data pointer of an allocation.
// Is passed x,y,z coordinates for the pointer to a specific element.
// Then sets the data_ptr member in Allocation with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr, uint32_t x,
- uint32_t y, uint32_t z)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITDataPointer(AllocationDetails *allocation,
+ StackFrame *frame_ptr, uint32_t x,
+ uint32_t y, uint32_t z) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->address.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
+ if (!allocation->address.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), x, y, z);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- allocation->data_ptr = mem_ptr;
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->data_ptr = mem_ptr;
- return true;
+ return true;
}
// JITs the RS runtime for the internal pointer to the RS Type of an allocation
// Then sets the type_ptr member in Allocation with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITTypePointer(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->address.isValid() || !allocation->context.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
+ if (!allocation->address.isValid() || !allocation->context.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- const char *expr_cstr = JITTemplate(eExprAllocGetType);
- char buffer[jit_max_expr_size];
+ const char *expr_cstr = JITTemplate(eExprAllocGetType);
+ char buffer[jit_max_expr_size];
- int chars_written =
- snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ int chars_written =
+ snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(),
+ *allocation->address.get());
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t type_ptr = static_cast<lldb::addr_t>(result);
- allocation->type_ptr = type_ptr;
+ addr_t type_ptr = static_cast<lldb::addr_t>(result);
+ allocation->type_ptr = type_ptr;
- return true;
+ return true;
}
-// JITs the RS runtime for information about the dimensions and type of an allocation
+// JITs the RS runtime for information about the dimensions and type of an
+// allocation
// Then sets dimension and element_ptr members in Allocation with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITTypePacked(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
- {
- if (log)
- log->Printf("%s - Failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- // Expression is different depending on if device is 32 or 64 bit
- uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
- const uint32_t bits = archByteSize == 4 ? 32 : 64;
-
- // We want 4 elements from packed data
- const uint32_t num_exprs = 4;
- assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
-
- char buffer[num_exprs][jit_max_expr_size];
- uint64_t results[num_exprs];
-
- for (uint32_t i = 0; i < num_exprs; ++i)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
- int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits, *allocation->context.get(),
- *allocation->type_ptr.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
- return false;
- }
-
- // Assign results to allocation members
- AllocationDetails::Dimension dims;
- dims.dim_1 = static_cast<uint32_t>(results[0]);
- dims.dim_2 = static_cast<uint32_t>(results[1]);
- dims.dim_3 = static_cast<uint32_t>(results[2]);
- allocation->dimension = dims;
-
- addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
- allocation->element.element_ptr = elem_ptr;
-
+ if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) {
if (log)
- log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") Element*: 0x%" PRIx64 ".", __FUNCTION__,
- dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+ log->Printf("%s - Failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- return true;
+ // Expression is different depending on if device is 32 or 64 bit
+ uint32_t archByteSize =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ const uint32_t bits = archByteSize == 4 ? 32 : 64;
+
+ // We want 4 elements from packed data
+ const uint32_t num_exprs = 4;
+ assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) &&
+ "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (uint32_t i = 0; i < num_exprs; ++i) {
+ const char *expr_cstr = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
+ int chars_written =
+ snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits,
+ *allocation->context.get(), *allocation->type_ptr.get());
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ AllocationDetails::Dimension dims;
+ dims.dim_1 = static_cast<uint32_t>(results[0]);
+ dims.dim_2 = static_cast<uint32_t>(results[1]);
+ dims.dim_3 = static_cast<uint32_t>(results[2]);
+ allocation->dimension = dims;
+
+ addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
+ allocation->element.element_ptr = elem_ptr;
+
+ if (log)
+ log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32
+ ") Element*: 0x%" PRIx64 ".",
+ __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+
+ return true;
}
// JITs the RS runtime for information about the Element of an allocation
-// Then sets type, type_vec_size, field_count and type_kind members in Element with the result.
+// Then sets type, type_vec_size, field_count and type_kind members in Element
+// with the result.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITElementPacked(Element &elem,
+ const lldb::addr_t context,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!elem.element_ptr.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
-
- // We want 4 elements from packed data
- const uint32_t num_exprs = 4;
- assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions");
-
- char buffer[num_exprs][jit_max_expr_size];
- uint64_t results[num_exprs];
-
- for (uint32_t i = 0; i < num_exprs; i++)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprElementType + i));
- int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get());
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
- return false;
- }
-
- // Assign results to allocation members
- elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
- elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
- elem.type_vec_size = static_cast<uint32_t>(results[2]);
- elem.field_count = static_cast<uint32_t>(results[3]);
-
+ if (!elem.element_ptr.isValid()) {
if (log)
- log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32 ", vector size %" PRIu32 ", field count %" PRIu32,
- __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get());
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields
- if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
- return false;
+ // We want 4 elements from packed data
+ const uint32_t num_exprs = 4;
+ assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) &&
+ "Invalid number of expressions");
- return true;
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (uint32_t i = 0; i < num_exprs; i++) {
+ const char *expr_cstr =
+ JITTemplate(ExpressionStrings(eExprElementType + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr,
+ context, *elem.element_ptr.get());
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
+ elem.type_kind =
+ static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
+ elem.type_vec_size = static_cast<uint32_t>(results[2]);
+ elem.field_count = static_cast<uint32_t>(results[3]);
+
+ if (log)
+ log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32
+ ", vector size %" PRIu32 ", field count %" PRIu32,
+ __FUNCTION__, *elem.type.get(), *elem.type_kind.get(),
+ *elem.type_vec_size.get(), *elem.field_count.get());
+
+ // If this Element has subelements then JIT rsaElementGetSubElements() for
+ // details about its fields
+ if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
+ return false;
+
+ return true;
}
-// JITs the RS runtime for information about the subelements/fields of a struct allocation
-// This is necessary for infering the struct type so we can pretty print the allocation's contents.
+// JITs the RS runtime for information about the subelements/fields of a struct
+// allocation
+// This is necessary for infering the struct type so we can pretty print the
+// allocation's contents.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITSubelements(Element &elem,
+ const lldb::addr_t context,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!elem.element_ptr.isValid() || !elem.field_count.isValid())
- {
+ if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
+
+ const short num_exprs = 3;
+ assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) &&
+ "Invalid number of expressions");
+
+ char expr_buffer[jit_max_expr_size];
+ uint64_t results;
+
+ // Iterate over struct fields.
+ const uint32_t field_count = *elem.field_count.get();
+ for (uint32_t field_index = 0; field_index < field_count; ++field_index) {
+ Element child;
+ for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) {
+ const char *expr_cstr =
+ JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
+ int chars_written =
+ snprintf(expr_buffer, jit_max_expr_size, expr_cstr, field_count,
+ field_count, field_count, context, *elem.element_ptr.get(),
+ field_count, field_index);
+ if (chars_written < 0) {
if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
return false;
- }
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- const short num_exprs = 3;
- assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions");
+ // Perform expression evaluation
+ if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
+ return false;
- char expr_buffer[jit_max_expr_size];
- uint64_t results;
+ if (log)
+ log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);
- // Iterate over struct fields.
- const uint32_t field_count = *elem.field_count.get();
- for (uint32_t field_index = 0; field_index < field_count; ++field_index)
- {
- Element child;
- for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index)
- {
- const char *expr_cstr = JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
- int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr,
- field_count, field_count, field_count,
- context, *elem.element_ptr.get(), field_count, field_index);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- // Perform expression evaluation
- if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
- return false;
-
- if (log)
- log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);
-
- switch (expr_index)
- {
- case 0: // Element* of child
- child.element_ptr = static_cast<addr_t>(results);
- break;
- case 1: // Name of child
- {
- lldb::addr_t address = static_cast<addr_t>(results);
- Error err;
- std::string name;
- GetProcess()->ReadCStringFromMemory(address, name, err);
- if (!err.Fail())
- child.type_name = ConstString(name);
- else
- {
- if (log)
- log->Printf("%s - warning: Couldn't read field name.", __FUNCTION__);
- }
- break;
- }
- case 2: // Array size of child
- child.array_size = static_cast<uint32_t>(results);
- break;
- }
+ switch (expr_index) {
+ case 0: // Element* of child
+ child.element_ptr = static_cast<addr_t>(results);
+ break;
+ case 1: // Name of child
+ {
+ lldb::addr_t address = static_cast<addr_t>(results);
+ Error err;
+ std::string name;
+ GetProcess()->ReadCStringFromMemory(address, name, err);
+ if (!err.Fail())
+ child.type_name = ConstString(name);
+ else {
+ if (log)
+ log->Printf("%s - warning: Couldn't read field name.",
+ __FUNCTION__);
}
-
- // We need to recursively JIT each Element field of the struct since
- // structs can be nested inside structs.
- if (!JITElementPacked(child, context, frame_ptr))
- return false;
- elem.children.push_back(child);
+ break;
+ }
+ case 2: // Array size of child
+ child.array_size = static_cast<uint32_t>(results);
+ break;
+ }
}
- // Try to infer the name of the struct type so we can pretty print the allocation contents.
- FindStructTypeName(elem, frame_ptr);
+ // We need to recursively JIT each Element field of the struct since
+ // structs can be nested inside structs.
+ if (!JITElementPacked(child, context, frame_ptr))
+ return false;
+ elem.children.push_back(child);
+ }
- return true;
+ // Try to infer the name of the struct type so we can pretty print the
+ // allocation contents.
+ FindStructTypeName(elem, frame_ptr);
+
+ return true;
}
// JITs the RS runtime for the address of the last element in the allocation.
-// The `elem_size` parameter represents the size of a single element, including padding.
+// The `elem_size` parameter represents the size of a single element, including
+// padding.
// Which is needed as an offset from the last element pointer.
-// Using this offset minus the starting address we can calculate the size of the allocation.
+// Using this offset minus the starting address we can calculate the size of the
+// allocation.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->address.isValid() || !allocation->dimension.isValid() || !allocation->data_ptr.isValid() ||
- !allocation->element.datum_size.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
+ if (!allocation->address.isValid() || !allocation->dimension.isValid() ||
+ !allocation->data_ptr.isValid() ||
+ !allocation->element.datum_size.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- // Find dimensions
- uint32_t dim_x = allocation->dimension.get()->dim_1;
- uint32_t dim_y = allocation->dimension.get()->dim_2;
- uint32_t dim_z = allocation->dimension.get()->dim_3;
+ // Find dimensions
+ uint32_t dim_x = allocation->dimension.get()->dim_1;
+ uint32_t dim_y = allocation->dimension.get()->dim_2;
+ uint32_t dim_z = allocation->dimension.get()->dim_3;
- // Our plan of jitting the last element address doesn't seem to work for struct Allocations
- // Instead try to infer the size ourselves without any inter element padding.
- if (allocation->element.children.size() > 0)
- {
- if (dim_x == 0) dim_x = 1;
- if (dim_y == 0) dim_y = 1;
- if (dim_z == 0) dim_z = 1;
+ // Our plan of jitting the last element address doesn't seem to work for
+ // struct Allocations
+ // Instead try to infer the size ourselves without any inter element padding.
+ if (allocation->element.children.size() > 0) {
+ if (dim_x == 0)
+ dim_x = 1;
+ if (dim_y == 0)
+ dim_y = 1;
+ if (dim_z == 0)
+ dim_z = 1;
- allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
-
- if (log)
- log->Printf("%s - inferred size of struct allocation %" PRIu32 ".", __FUNCTION__,
- *allocation->size.get());
- return true;
- }
-
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
-
- // Calculate last element
- dim_x = dim_x == 0 ? 0 : dim_x - 1;
- dim_y = dim_y == 0 ? 0 : dim_y - 1;
- dim_z = dim_z == 0 ? 0 : dim_z - 1;
-
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), dim_x, dim_y, dim_z);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
-
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
-
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- // Find pointer to last element and add on size of an element
allocation->size =
- static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get();
+ dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
+ if (log)
+ log->Printf("%s - inferred size of struct allocation %" PRIu32 ".",
+ __FUNCTION__, *allocation->size.get());
return true;
+ }
+
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ // Calculate last element
+ dim_x = dim_x == 0 ? 0 : dim_x - 1;
+ dim_y = dim_y == 0 ? 0 : dim_y - 1;
+ dim_z = dim_z == 0 ? 0 : dim_z - 1;
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), dim_x, dim_y, dim_z);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ // Find pointer to last element and add on size of an element
+ allocation->size =
+ static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) +
+ *allocation->element.datum_size.get();
+
+ return true;
}
-// JITs the RS runtime for information about the stride between rows in the allocation.
+// JITs the RS runtime for information about the stride between rows in the
+// allocation.
// This is done to detect padding, since allocated memory is 16-byte aligned.
// Returns true on success, false otherwise
-bool
-RenderScriptRuntime::JITAllocationStride(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
- {
- if (log)
- log->Printf("%s - failed to find allocation details.", __FUNCTION__);
- return false;
- }
+ if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) {
+ if (log)
+ log->Printf("%s - failed to find allocation details.", __FUNCTION__);
+ return false;
+ }
- const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
- char buffer[jit_max_expr_size];
+ const char *expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
- int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 0, 1, 0);
- if (chars_written < 0)
- {
- if (log)
- log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
- return false;
- }
- else if (chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - expression too long.", __FUNCTION__);
- return false;
- }
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr,
+ *allocation->address.get(), 0, 1, 0);
+ if (chars_written < 0) {
+ if (log)
+ log->Printf("%s - encoding error in snprintf().", __FUNCTION__);
+ return false;
+ } else if (chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - expression too long.", __FUNCTION__);
+ return false;
+ }
- uint64_t result = 0;
- if (!EvalRSExpression(buffer, frame_ptr, &result))
- return false;
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
- addr_t mem_ptr = static_cast<lldb::addr_t>(result);
- allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->stride =
+ static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
- return true;
+ return true;
}
// JIT all the current runtime info regarding an allocation
-bool
-RenderScriptRuntime::RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- // GetOffsetPointer()
- if (!JITDataPointer(allocation, frame_ptr))
- return false;
+bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ // GetOffsetPointer()
+ if (!JITDataPointer(allocation, frame_ptr))
+ return false;
- // rsaAllocationGetType()
- if (!JITTypePointer(allocation, frame_ptr))
- return false;
+ // rsaAllocationGetType()
+ if (!JITTypePointer(allocation, frame_ptr))
+ return false;
- // rsaTypeGetNativeData()
- if (!JITTypePacked(allocation, frame_ptr))
- return false;
+ // rsaTypeGetNativeData()
+ if (!JITTypePacked(allocation, frame_ptr))
+ return false;
- // rsaElementGetNativeData()
- if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr))
- return false;
+ // rsaElementGetNativeData()
+ if (!JITElementPacked(allocation->element, *allocation->context.get(),
+ frame_ptr))
+ return false;
- // Sets the datum_size member in Element
- SetElementSize(allocation->element);
+ // Sets the datum_size member in Element
+ SetElementSize(allocation->element);
- // Use GetOffsetPointer() to infer size of the allocation
- if (!JITAllocationSize(allocation, frame_ptr))
- return false;
+ // Use GetOffsetPointer() to infer size of the allocation
+ if (!JITAllocationSize(allocation, frame_ptr))
+ return false;
- return true;
+ return true;
}
-// Function attempts to set the type_name member of the paramaterised Element object.
+// Function attempts to set the type_name member of the paramaterised Element
+// object.
// This string should be the name of the struct type the Element represents.
// We need this string for pretty printing the Element to users.
-void
-RenderScriptRuntime::FindStructTypeName(Element &elem, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+void RenderScriptRuntime::FindStructTypeName(Element &elem,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (!elem.type_name.IsEmpty()) // Name already set
- return;
- else
- elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed
+ if (!elem.type_name.IsEmpty()) // Name already set
+ return;
+ else
+ elem.type_name = Element::GetFallbackStructName(); // Default type name if
+ // we don't succeed
- // Find all the global variables from the script rs modules
- VariableList variable_list;
- for (auto module_sp : m_rsmodules)
- module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list);
+ // Find all the global variables from the script rs modules
+ VariableList variable_list;
+ for (auto module_sp : m_rsmodules)
+ module_sp->m_module->FindGlobalVariables(RegularExpression("."), true,
+ UINT32_MAX, variable_list);
- // Iterate over all the global variables looking for one with a matching type to the Element.
- // We make the assumption a match exists since there needs to be a global variable to reflect the
- // struct type back into java host code.
- for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index)
- {
- const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
- if (!var_sp)
- continue;
+ // Iterate over all the global variables looking for one with a matching type
+ // to the Element.
+ // We make the assumption a match exists since there needs to be a global
+ // variable to reflect the
+ // struct type back into java host code.
+ for (uint32_t var_index = 0; var_index < variable_list.GetSize();
+ ++var_index) {
+ const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
+ if (!var_sp)
+ continue;
- ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
- if (!valobj_sp)
- continue;
+ ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
+ if (!valobj_sp)
+ continue;
- // Find the number of variable fields.
- // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for.
- // Don't check for equality since RS can add extra struct members for padding.
- size_t num_children = valobj_sp->GetNumChildren();
- if (num_children > elem.children.size() || num_children == 0)
- continue;
+ // Find the number of variable fields.
+ // If it has no fields, or more fields than our Element, then it can't be
+ // the struct we're looking for.
+ // Don't check for equality since RS can add extra struct members for
+ // padding.
+ size_t num_children = valobj_sp->GetNumChildren();
+ if (num_children > elem.children.size() || num_children == 0)
+ continue;
- // Iterate over children looking for members with matching field names.
- // If all the field names match, this is likely the struct we want.
- //
- // TODO: This could be made more robust by also checking children data sizes, or array size
- bool found = true;
- for (size_t child_index = 0; child_index < num_children; ++child_index)
- {
- ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
- if (!child || (child->GetName() != elem.children[child_index].type_name))
- {
- found = false;
- break;
- }
- }
-
- // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+'
- if (found && num_children < elem.children.size())
- {
- const uint32_t size_diff = elem.children.size() - num_children;
- if (log)
- log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__, size_diff);
-
- for (uint32_t padding_index = 0; padding_index < size_diff; ++padding_index)
- {
- const ConstString &name = elem.children[num_children + padding_index].type_name;
- if (strcmp(name.AsCString(), "#rs_padding") < 0)
- found = false;
- }
- }
-
- // We've found a global var with matching type
- if (found)
- {
- // Dereference since our Element type isn't a pointer.
- if (valobj_sp->IsPointerType())
- {
- Error err;
- ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
- if (!err.Fail())
- valobj_sp = deref_valobj;
- }
-
- // Save name of variable in Element.
- elem.type_name = valobj_sp->GetTypeName();
- if (log)
- log->Printf("%s - element name set to %s", __FUNCTION__, elem.type_name.AsCString());
-
- return;
- }
+ // Iterate over children looking for members with matching field names.
+ // If all the field names match, this is likely the struct we want.
+ //
+ // TODO: This could be made more robust by also checking children data
+ // sizes, or array size
+ bool found = true;
+ for (size_t child_index = 0; child_index < num_children; ++child_index) {
+ ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
+ if (!child ||
+ (child->GetName() != elem.children[child_index].type_name)) {
+ found = false;
+ break;
+ }
}
+
+ // RS can add extra struct members for padding in the format
+ // '#rs_padding_[0-9]+'
+ if (found && num_children < elem.children.size()) {
+ const uint32_t size_diff = elem.children.size() - num_children;
+ if (log)
+ log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__,
+ size_diff);
+
+ for (uint32_t padding_index = 0; padding_index < size_diff;
+ ++padding_index) {
+ const ConstString &name =
+ elem.children[num_children + padding_index].type_name;
+ if (strcmp(name.AsCString(), "#rs_padding") < 0)
+ found = false;
+ }
+ }
+
+ // We've found a global var with matching type
+ if (found) {
+ // Dereference since our Element type isn't a pointer.
+ if (valobj_sp->IsPointerType()) {
+ Error err;
+ ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
+ if (!err.Fail())
+ valobj_sp = deref_valobj;
+ }
+
+ // Save name of variable in Element.
+ elem.type_name = valobj_sp->GetTypeName();
+ if (log)
+ log->Printf("%s - element name set to %s", __FUNCTION__,
+ elem.type_name.AsCString());
+
+ return;
+ }
+ }
}
-// Function sets the datum_size member of Element. Representing the size of a single instance including padding.
+// Function sets the datum_size member of Element. Representing the size of a
+// single instance including padding.
// Assumes the relevant allocation information has already been jitted.
-void
-RenderScriptRuntime::SetElementSize(Element &elem)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- const Element::DataType type = *elem.type.get();
- assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && "Invalid allocation type");
+void RenderScriptRuntime::SetElementSize(Element &elem) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ const Element::DataType type = *elem.type.get();
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
+ "Invalid allocation type");
- const uint32_t vec_size = *elem.type_vec_size.get();
- uint32_t data_size = 0;
- uint32_t padding = 0;
+ const uint32_t vec_size = *elem.type_vec_size.get();
+ uint32_t data_size = 0;
+ uint32_t padding = 0;
- // Element is of a struct type, calculate size recursively.
- if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))
- {
- for (Element &child : elem.children)
- {
- SetElementSize(child);
- const uint32_t array_size = child.array_size.isValid() ? *child.array_size.get() : 1;
- data_size += *child.datum_size.get() * array_size;
- }
+ // Element is of a struct type, calculate size recursively.
+ if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) {
+ for (Element &child : elem.children) {
+ SetElementSize(child);
+ const uint32_t array_size =
+ child.array_size.isValid() ? *child.array_size.get() : 1;
+ data_size += *child.datum_size.get() * array_size;
}
- // These have been packed already
- else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
- type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
- type == Element::RS_TYPE_UNSIGNED_4_4_4_4)
- {
- data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
- }
- else if (type < Element::RS_TYPE_ELEMENT)
- {
- data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
- if (vec_size == 3)
- padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
- }
- else
- data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ }
+ // These have been packed already
+ else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
+ type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
+ type == Element::RS_TYPE_UNSIGNED_4_4_4_4) {
+ data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ } else if (type < Element::RS_TYPE_ELEMENT) {
+ data_size =
+ vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
+ if (vec_size == 3)
+ padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ } else
+ data_size =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
- elem.padding = padding;
- elem.datum_size = data_size + padding;
- if (log)
- log->Printf("%s - element size set to %" PRIu32, __FUNCTION__, data_size + padding);
+ elem.padding = padding;
+ elem.datum_size = data_size + padding;
+ if (log)
+ log->Printf("%s - element size set to %" PRIu32, __FUNCTION__,
+ data_size + padding);
}
-// Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
+// Given an allocation, this function copies the allocation contents from device
+// into a buffer on the heap.
// Returning a shared pointer to the buffer containing the data.
std::shared_ptr<uint8_t>
-RenderScriptRuntime::GetAllocationData(AllocationDetails *allocation, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+RenderScriptRuntime::GetAllocationData(AllocationDetails *allocation,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- // JIT all the allocation details
- if (allocation->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info", __FUNCTION__);
+ // JIT all the allocation details
+ if (allocation->shouldRefresh()) {
+ if (log)
+ log->Printf("%s - allocation details not calculated yet, jitting info",
+ __FUNCTION__);
- if (!RefreshAllocation(allocation, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
- return nullptr;
- }
+ if (!RefreshAllocation(allocation, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
+ return nullptr;
}
+ }
- assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() &&
- allocation->element.type_vec_size.isValid() && allocation->size.isValid() &&
- "Allocation information not available");
+ assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() &&
+ allocation->element.type_vec_size.isValid() &&
+ allocation->size.isValid() && "Allocation information not available");
- // Allocate a buffer to copy data into
- const uint32_t size = *allocation->size.get();
- std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
- if (!buffer)
- {
- if (log)
- log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer", __FUNCTION__, size);
- return nullptr;
- }
+ // Allocate a buffer to copy data into
+ const uint32_t size = *allocation->size.get();
+ std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
+ if (!buffer) {
+ if (log)
+ log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer",
+ __FUNCTION__, size);
+ return nullptr;
+ }
- // Read the inferior memory
- Error error;
- lldb::addr_t data_ptr = *allocation->data_ptr.get();
- GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s - '%s' Couldn't read %" PRIu32 " bytes of allocation data from 0x%" PRIx64,
- __FUNCTION__, error.AsCString(), size, data_ptr);
- return nullptr;
- }
+ // Read the inferior memory
+ Error error;
+ lldb::addr_t data_ptr = *allocation->data_ptr.get();
+ GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s - '%s' Couldn't read %" PRIu32
+ " bytes of allocation data from 0x%" PRIx64,
+ __FUNCTION__, error.AsCString(), size, data_ptr);
+ return nullptr;
+ }
- return buffer;
+ return buffer;
}
// Function copies data from a binary file into an allocation.
-// There is a header at the start of the file, FileHeader, before the data content itself.
-// Information from this header is used to display warnings to the user about incompatibilities
-bool
-RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+// There is a header at the start of the file, FileHeader, before the data
+// content itself.
+// Information from this header is used to display warnings to the user about
+// incompatibilities
+bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- // Find allocation with the given id
- AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
- if (!alloc)
- return false;
+ // Find allocation with the given id
+ AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__,
+ *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh()) {
if (log)
- log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *alloc->address.get());
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
- // JIT all the allocation details
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
-
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
- return false;
- }
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details", __FUNCTION__);
+ return false;
}
+ }
- assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() &&
- alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available");
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
+ alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
+ alloc->element.datum_size.isValid() &&
+ "Allocation information not available");
- // Check we can read from file
- FileSpec file(filename, true);
- if (!file.Exists())
- {
- strm.Printf("Error: File %s does not exist", filename);
- strm.EOL();
- return false;
- }
-
- if (!file.Readable())
- {
- strm.Printf("Error: File %s does not have readable permissions", filename);
- strm.EOL();
- return false;
- }
-
- // Read file into data buffer
- DataBufferSP data_sp(file.ReadFileContents());
-
- // Cast start of buffer to FileHeader and use pointer to read metadata
- void *file_buffer = data_sp->GetBytes();
- if (file_buffer == nullptr ||
- data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader)))
- {
- strm.Printf("Error: File %s does not contain enough data for header", filename);
- strm.EOL();
- return false;
- }
- const AllocationDetails::FileHeader *file_header = static_cast<AllocationDetails::FileHeader *>(file_buffer);
-
- // Check file starts with ascii characters "RSAD"
- if (memcmp(file_header->ident, "RSAD", 4))
- {
- strm.Printf("Error: File doesn't contain identifier for an RS allocation dump. Are you sure this is the correct file?");
- strm.EOL();
- return false;
- }
-
- // Look at the type of the root element in the header
- AllocationDetails::ElementHeader root_element_header;
- memcpy(&root_element_header, static_cast<uint8_t *>(file_buffer) + sizeof(AllocationDetails::FileHeader),
- sizeof(AllocationDetails::ElementHeader));
-
- if (log)
- log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32, __FUNCTION__,
- root_element_header.type, root_element_header.element_size);
-
- // Check if the target allocation and file both have the same number of bytes for an Element
- if (*alloc->element.datum_size.get() != root_element_header.element_size)
- {
- strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32 " bytes, allocation %" PRIu32 " bytes",
- root_element_header.element_size, *alloc->element.datum_size.get());
- strm.EOL();
- }
-
- // Check if the target allocation and file both have the same type
- const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
- const uint32_t file_type = root_element_header.type;
-
- if (file_type > Element::RS_TYPE_FONT)
- {
- strm.Printf("Warning: File has unknown allocation type");
- strm.EOL();
- }
- else if (alloc_type != file_type)
- {
- // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
- uint32_t printable_target_type_index = alloc_type;
- uint32_t printable_head_type_index = file_type;
- if (alloc_type >= Element::RS_TYPE_ELEMENT && alloc_type <= Element::RS_TYPE_FONT)
- printable_target_type_index = static_cast<Element::DataType>((alloc_type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- if (file_type >= Element::RS_TYPE_ELEMENT && file_type <= Element::RS_TYPE_FONT)
- printable_head_type_index = static_cast<Element::DataType>((file_type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- const char *file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
- const char *target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
-
- strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", file_type_cstr,
- target_type_cstr);
- strm.EOL();
- }
-
- // Advance buffer past header
- file_buffer = static_cast<uint8_t *>(file_buffer) + file_header->hdr_size;
-
- // Calculate size of allocation data in file
- size_t length = data_sp->GetByteSize() - file_header->hdr_size;
-
- // Check if the target allocation and file both have the same total data size.
- const uint32_t alloc_size = *alloc->size.get();
- if (alloc_size != length)
- {
- strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%" PRIx32 " bytes",
- (uint64_t)length, alloc_size);
- strm.EOL();
- length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
- }
-
- // Copy file data from our buffer into the target allocation.
- lldb::addr_t alloc_data = *alloc->data_ptr.get();
- Error error;
- size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
- if (!error.Success() || bytes_written != length)
- {
- strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
- strm.EOL();
- return false;
- }
-
- strm.Printf("Contents of file '%s' read into allocation %" PRIu32, filename, alloc->id);
+ // Check we can read from file
+ FileSpec file(filename, true);
+ if (!file.Exists()) {
+ strm.Printf("Error: File %s does not exist", filename);
strm.EOL();
+ return false;
+ }
- return true;
+ if (!file.Readable()) {
+ strm.Printf("Error: File %s does not have readable permissions", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read file into data buffer
+ DataBufferSP data_sp(file.ReadFileContents());
+
+ // Cast start of buffer to FileHeader and use pointer to read metadata
+ void *file_buffer = data_sp->GetBytes();
+ if (file_buffer == nullptr ||
+ data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
+ sizeof(AllocationDetails::ElementHeader))) {
+ strm.Printf("Error: File %s does not contain enough data for header",
+ filename);
+ strm.EOL();
+ return false;
+ }
+ const AllocationDetails::FileHeader *file_header =
+ static_cast<AllocationDetails::FileHeader *>(file_buffer);
+
+ // Check file starts with ascii characters "RSAD"
+ if (memcmp(file_header->ident, "RSAD", 4)) {
+ strm.Printf("Error: File doesn't contain identifier for an RS allocation "
+ "dump. Are you sure this is the correct file?");
+ strm.EOL();
+ return false;
+ }
+
+ // Look at the type of the root element in the header
+ AllocationDetails::ElementHeader root_element_header;
+ memcpy(&root_element_header, static_cast<uint8_t *>(file_buffer) +
+ sizeof(AllocationDetails::FileHeader),
+ sizeof(AllocationDetails::ElementHeader));
+
+ if (log)
+ log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32,
+ __FUNCTION__, root_element_header.type,
+ root_element_header.element_size);
+
+ // Check if the target allocation and file both have the same number of bytes
+ // for an Element
+ if (*alloc->element.datum_size.get() != root_element_header.element_size) {
+ strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32
+ " bytes, allocation %" PRIu32 " bytes",
+ root_element_header.element_size,
+ *alloc->element.datum_size.get());
+ strm.EOL();
+ }
+
+ // Check if the target allocation and file both have the same type
+ const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
+ const uint32_t file_type = root_element_header.type;
+
+ if (file_type > Element::RS_TYPE_FONT) {
+ strm.Printf("Warning: File has unknown allocation type");
+ strm.EOL();
+ } else if (alloc_type != file_type) {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString
+ // array
+ uint32_t printable_target_type_index = alloc_type;
+ uint32_t printable_head_type_index = file_type;
+ if (alloc_type >= Element::RS_TYPE_ELEMENT &&
+ alloc_type <= Element::RS_TYPE_FONT)
+ printable_target_type_index = static_cast<Element::DataType>(
+ (alloc_type - Element::RS_TYPE_ELEMENT) +
+ Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (file_type >= Element::RS_TYPE_ELEMENT &&
+ file_type <= Element::RS_TYPE_FONT)
+ printable_head_type_index = static_cast<Element::DataType>(
+ (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 +
+ 1);
+
+ const char *file_type_cstr =
+ AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
+ const char *target_type_cstr =
+ AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
+
+ strm.Printf(
+ "Warning: Mismatched Types - file '%s' type, allocation '%s' type",
+ file_type_cstr, target_type_cstr);
+ strm.EOL();
+ }
+
+ // Advance buffer past header
+ file_buffer = static_cast<uint8_t *>(file_buffer) + file_header->hdr_size;
+
+ // Calculate size of allocation data in file
+ size_t length = data_sp->GetByteSize() - file_header->hdr_size;
+
+ // Check if the target allocation and file both have the same total data size.
+ const uint32_t alloc_size = *alloc->size.get();
+ if (alloc_size != length) {
+ strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
+ " bytes, allocation 0x%" PRIx32 " bytes",
+ (uint64_t)length, alloc_size);
+ strm.EOL();
+ length = alloc_size < length ? alloc_size
+ : length; // Set length to copy to minimum
+ }
+
+ // Copy file data from our buffer into the target allocation.
+ lldb::addr_t alloc_data = *alloc->data_ptr.get();
+ Error error;
+ size_t bytes_written =
+ GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
+ if (!error.Success() || bytes_written != length) {
+ strm.Printf("Error: Couldn't write data to allocation %s",
+ error.AsCString());
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Contents of file '%s' read into allocation %" PRIu32, filename,
+ alloc->id);
+ strm.EOL();
+
+ return true;
}
-// Function takes as parameters a byte buffer, which will eventually be written to file as the element header,
-// an offset into that buffer, and an Element that will be saved into the buffer at the parametrised offset.
+// Function takes as parameters a byte buffer, which will eventually be written
+// to file as the element header,
+// an offset into that buffer, and an Element that will be saved into the buffer
+// at the parametrised offset.
// Return value is the new offset after writing the element into the buffer.
-// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's
+// Elements are saved to the file as the ElementHeader struct followed by
+// offsets to the structs of all the element's
// children.
-size_t
-RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset,
- const Element &elem)
-{
- // File struct for an element header with all the relevant details copied from elem.
- // We assume members are valid already.
- AllocationDetails::ElementHeader elem_header;
- elem_header.type = *elem.type.get();
- elem_header.kind = *elem.type_kind.get();
- elem_header.element_size = *elem.datum_size.get();
- elem_header.vector_size = *elem.type_vec_size.get();
- elem_header.array_size = elem.array_size.isValid() ? *elem.array_size.get() : 0;
- const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
+size_t RenderScriptRuntime::PopulateElementHeaders(
+ const std::shared_ptr<uint8_t> header_buffer, size_t offset,
+ const Element &elem) {
+ // File struct for an element header with all the relevant details copied from
+ // elem.
+ // We assume members are valid already.
+ AllocationDetails::ElementHeader elem_header;
+ elem_header.type = *elem.type.get();
+ elem_header.kind = *elem.type_kind.get();
+ elem_header.element_size = *elem.datum_size.get();
+ elem_header.vector_size = *elem.type_vec_size.get();
+ elem_header.array_size =
+ elem.array_size.isValid() ? *elem.array_size.get() : 0;
+ const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
- // Copy struct into buffer and advance offset
- // We assume that header_buffer has been checked for nullptr before this method is called
- memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
- offset += elem_header_size;
+ // Copy struct into buffer and advance offset
+ // We assume that header_buffer has been checked for nullptr before this
+ // method is called
+ memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
+ offset += elem_header_size;
- // Starting offset of child ElementHeader struct
- size_t child_offset = offset + ((elem.children.size() + 1) * sizeof(uint32_t));
- for (const RenderScriptRuntime::Element &child : elem.children)
- {
- // Recursively populate the buffer with the element header structs of children.
- // Then save the offsets where they were set after the parent element header.
- memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
- offset += sizeof(uint32_t);
+ // Starting offset of child ElementHeader struct
+ size_t child_offset =
+ offset + ((elem.children.size() + 1) * sizeof(uint32_t));
+ for (const RenderScriptRuntime::Element &child : elem.children) {
+ // Recursively populate the buffer with the element header structs of
+ // children.
+ // Then save the offsets where they were set after the parent element
+ // header.
+ memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
- child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
- }
+ child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
+ }
- // Zero indicates no more children
- memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
+ // Zero indicates no more children
+ memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
- return child_offset;
+ return child_offset;
}
-// Given an Element object this function returns the total size needed in the file header to store the element's
+// Given an Element object this function returns the total size needed in the
+// file header to store the element's
// details.
-// Taking into account the size of the element header struct, plus the offsets to all the element's children.
-// Function is recursive so that the size of all ancestors is taken into account.
-size_t
-RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem)
-{
- size_t size = (elem.children.size() + 1) * sizeof(uint32_t); // Offsets to children plus zero terminator
- size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details
+// Taking into account the size of the element header struct, plus the offsets
+// to all the element's children.
+// Function is recursive so that the size of all ancestors is taken into
+// account.
+size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
+ size_t size = (elem.children.size() + 1) *
+ sizeof(uint32_t); // Offsets to children plus zero terminator
+ size += sizeof(AllocationDetails::ElementHeader); // Size of header struct
+ // with type details
- // Calculate recursively for all descendants
- for (const Element &child : elem.children)
- size += CalculateElementHeaderSize(child);
+ // Calculate recursively for all descendants
+ for (const Element &child : elem.children)
+ size += CalculateElementHeaderSize(child);
- return size;
+ return size;
}
// Function copies allocation contents into a binary file.
// This file can then be loaded later into a different allocation.
-// There is a header, FileHeader, before the allocation data containing meta-data.
-bool
-RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+// There is a header, FileHeader, before the allocation data containing
+// meta-data.
+bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename,
+ StackFrame *frame_ptr) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- // Find allocation with the given id
- AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
- if (!alloc)
- return false;
-
- if (log)
- log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, *alloc->address.get());
-
- // JIT all the allocation details
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
-
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- if (log)
- log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__);
- return false;
- }
- }
-
- assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() &&
- alloc->element.datum_size.get() && alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
- "Allocation information not available");
-
- // Check we can create writable file
- FileSpec file_spec(filename, true);
- File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
- if (!file)
- {
- strm.Printf("Error: Failed to open '%s' for writing", filename);
- strm.EOL();
- return false;
- }
-
- // Read allocation into buffer of heap memory
- const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
- if (!buffer)
- {
- strm.Printf("Error: Couldn't read allocation data into buffer");
- strm.EOL();
- return false;
- }
-
- // Create the file header
- AllocationDetails::FileHeader head;
- memcpy(head.ident, "RSAD", 4);
- head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
- head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
- head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
-
- const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
- assert((sizeof(AllocationDetails::FileHeader) + element_header_size) < UINT16_MAX && "Element header too large");
- head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) + element_header_size);
-
- // Write the file header
- size_t num_bytes = sizeof(AllocationDetails::FileHeader);
- if (log)
- log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes);
-
- Error err = file.Write(&head, num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
-
- // Create the headers describing the element type of the allocation.
- std::shared_ptr<uint8_t> element_header_buffer(new uint8_t[element_header_size]);
- if (element_header_buffer == nullptr)
- {
- strm.Printf("Internal Error: Couldn't allocate %" PRIu64 " bytes on the heap", (uint64_t)element_header_size);
- strm.EOL();
- return false;
- }
-
- PopulateElementHeaders(element_header_buffer, 0, alloc->element);
-
- // Write headers for allocation element type to file
- num_bytes = element_header_size;
- if (log)
- log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.", __FUNCTION__, (uint64_t)num_bytes);
-
- err = file.Write(element_header_buffer.get(), num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
-
- // Write allocation data to file
- num_bytes = static_cast<size_t>(*alloc->size.get());
- if (log)
- log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes);
-
- err = file.Write(buffer.get(), num_bytes);
- if (!err.Success())
- {
- strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
- strm.EOL();
- return false;
- }
-
- strm.Printf("Allocation written to file '%s'", filename);
- strm.EOL();
- return true;
-}
-
-bool
-RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (module_sp)
- {
- for (const auto &rs_module : m_rsmodules)
- {
- if (rs_module->m_module == module_sp)
- {
- // Check if the user has enabled automatically breaking on
- // all RS kernels.
- if (m_breakAllKernels)
- BreakOnModuleKernels(rs_module);
-
- return false;
- }
- }
- bool module_loaded = false;
- switch (GetModuleKind(module_sp))
- {
- case eModuleKindKernelObj:
- {
- RSModuleDescriptorSP module_desc;
- module_desc.reset(new RSModuleDescriptor(module_sp));
- if (module_desc->ParseRSInfo())
- {
- m_rsmodules.push_back(module_desc);
- module_loaded = true;
- }
- if (module_loaded)
- {
- FixupScriptDetails(module_desc);
- }
- break;
- }
- case eModuleKindDriver:
- {
- if (!m_libRSDriver)
- {
- m_libRSDriver = module_sp;
- LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
- }
- break;
- }
- case eModuleKindImpl:
- {
- m_libRSCpuRef = module_sp;
- break;
- }
- case eModuleKindLibRS:
- {
- if (!m_libRS)
- {
- m_libRS = module_sp;
- static ConstString gDbgPresentStr("gDebuggerPresent");
- const Symbol *debug_present =
- m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
- if (debug_present)
- {
- Error error;
- uint32_t flag = 0x00000001U;
- Target &target = GetProcess()->GetTarget();
- addr_t addr = debug_present->GetLoadAddress(&target);
- GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
- if (error.Success())
- {
- if (log)
- log->Printf("%s - debugger present flag set on debugee.", __FUNCTION__);
-
- m_debuggerPresentFlagged = true;
- }
- else if (log)
- {
- log->Printf("%s - error writing debugger present flags '%s' ", __FUNCTION__,
- error.AsCString());
- }
- }
- else if (log)
- {
- log->Printf("%s - error writing debugger present flags - symbol not found", __FUNCTION__);
- }
- }
- break;
- }
- default:
- break;
- }
- if (module_loaded)
- Update();
- return module_loaded;
- }
+ // Find allocation with the given id
+ AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
return false;
+
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__,
+ *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh()) {
+ if (log)
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
+
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ if (log)
+ log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__);
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
+ alloc->element.type_vec_size.isValid() &&
+ alloc->element.datum_size.get() &&
+ alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
+ "Allocation information not available");
+
+ // Check we can create writable file
+ FileSpec file_spec(filename, true);
+ File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
+ File::eOpenOptionTruncate);
+ if (!file) {
+ strm.Printf("Error: Failed to open '%s' for writing", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read allocation into buffer of heap memory
+ const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer) {
+ strm.Printf("Error: Couldn't read allocation data into buffer");
+ strm.EOL();
+ return false;
+ }
+
+ // Create the file header
+ AllocationDetails::FileHeader head;
+ memcpy(head.ident, "RSAD", 4);
+ head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
+ head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
+ head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
+
+ const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
+ assert((sizeof(AllocationDetails::FileHeader) + element_header_size) <
+ UINT16_MAX &&
+ "Element header too large");
+ head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) +
+ element_header_size);
+
+ // Write the file header
+ size_t num_bytes = sizeof(AllocationDetails::FileHeader);
+ if (log)
+ log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
+ (uint64_t)num_bytes);
+
+ Error err = file.Write(&head, num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Create the headers describing the element type of the allocation.
+ std::shared_ptr<uint8_t> element_header_buffer(
+ new uint8_t[element_header_size]);
+ if (element_header_buffer == nullptr) {
+ strm.Printf("Internal Error: Couldn't allocate %" PRIu64
+ " bytes on the heap",
+ (uint64_t)element_header_size);
+ strm.EOL();
+ return false;
+ }
+
+ PopulateElementHeaders(element_header_buffer, 0, alloc->element);
+
+ // Write headers for allocation element type to file
+ num_bytes = element_header_size;
+ if (log)
+ log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.",
+ __FUNCTION__, (uint64_t)num_bytes);
+
+ err = file.Write(element_header_buffer.get(), num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Write allocation data to file
+ num_bytes = static_cast<size_t>(*alloc->size.get());
+ if (log)
+ log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
+ (uint64_t)num_bytes);
+
+ err = file.Write(buffer.get(), num_bytes);
+ if (!err.Success()) {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(),
+ filename);
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Allocation written to file '%s'", filename);
+ strm.EOL();
+ return true;
}
-void
-RenderScriptRuntime::Update()
-{
- if (m_rsmodules.size() > 0)
- {
- if (!m_initiated)
- {
- Initiate();
- }
+bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (module_sp) {
+ for (const auto &rs_module : m_rsmodules) {
+ if (rs_module->m_module == module_sp) {
+ // Check if the user has enabled automatically breaking on
+ // all RS kernels.
+ if (m_breakAllKernels)
+ BreakOnModuleKernels(rs_module);
+
+ return false;
+ }
}
+ bool module_loaded = false;
+ switch (GetModuleKind(module_sp)) {
+ case eModuleKindKernelObj: {
+ RSModuleDescriptorSP module_desc;
+ module_desc.reset(new RSModuleDescriptor(module_sp));
+ if (module_desc->ParseRSInfo()) {
+ m_rsmodules.push_back(module_desc);
+ module_loaded = true;
+ }
+ if (module_loaded) {
+ FixupScriptDetails(module_desc);
+ }
+ break;
+ }
+ case eModuleKindDriver: {
+ if (!m_libRSDriver) {
+ m_libRSDriver = module_sp;
+ LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
+ }
+ break;
+ }
+ case eModuleKindImpl: {
+ m_libRSCpuRef = module_sp;
+ break;
+ }
+ case eModuleKindLibRS: {
+ if (!m_libRS) {
+ m_libRS = module_sp;
+ static ConstString gDbgPresentStr("gDebuggerPresent");
+ const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType(
+ gDbgPresentStr, eSymbolTypeData);
+ if (debug_present) {
+ Error error;
+ uint32_t flag = 0x00000001U;
+ Target &target = GetProcess()->GetTarget();
+ addr_t addr = debug_present->GetLoadAddress(&target);
+ GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
+ if (error.Success()) {
+ if (log)
+ log->Printf("%s - debugger present flag set on debugee.",
+ __FUNCTION__);
+
+ m_debuggerPresentFlagged = true;
+ } else if (log) {
+ log->Printf("%s - error writing debugger present flags '%s' ",
+ __FUNCTION__, error.AsCString());
+ }
+ } else if (log) {
+ log->Printf(
+ "%s - error writing debugger present flags - symbol not found",
+ __FUNCTION__);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (module_loaded)
+ Update();
+ return module_loaded;
+ }
+ return false;
+}
+
+void RenderScriptRuntime::Update() {
+ if (m_rsmodules.size() > 0) {
+ if (!m_initiated) {
+ Initiate();
+ }
+ }
}
// The maximum line length of an .rs.info packet
@@ -2673,501 +2593,477 @@
#define MAXLINESTR_(x) "%" STRINGIFY(x) "s"
#define MAXLINESTR MAXLINESTR_(MAXLINE)
-// The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
+// The .rs.info symbol in renderscript modules contains a string which needs to
+// be parsed.
// The string is basic and is parsed on a line by line basis.
-bool
-RSModuleDescriptor::ParseRSInfo()
-{
- assert(m_module);
- const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
- if (!info_sym)
- return false;
+bool RSModuleDescriptor::ParseRSInfo() {
+ assert(m_module);
+ const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(
+ ConstString(".rs.info"), eSymbolTypeData);
+ if (!info_sym)
+ return false;
- const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
- if (addr == LLDB_INVALID_ADDRESS)
- return false;
+ const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
+ if (addr == LLDB_INVALID_ADDRESS)
+ return false;
- const addr_t size = info_sym->GetByteSize();
- const FileSpec fs = m_module->GetFileSpec();
+ const addr_t size = info_sym->GetByteSize();
+ const FileSpec fs = m_module->GetFileSpec();
- const DataBufferSP buffer = fs.ReadFileContents(addr, size);
- if (!buffer)
- return false;
+ const DataBufferSP buffer = fs.ReadFileContents(addr, size);
+ if (!buffer)
+ return false;
- // split rs.info. contents into lines
- std::vector<std::string> info_lines;
- {
- const std::string info((const char *)buffer->GetBytes());
- for (size_t tail = 0; tail < info.size();)
- {
- // find next new line or end of string
- size_t head = info.find('\n', tail);
- head = (head == std::string::npos) ? info.size() : head;
- std::string line = info.substr(tail, head - tail);
- // add to line list
- info_lines.push_back(line);
- tail = head + 1;
- }
+ // split rs.info. contents into lines
+ std::vector<std::string> info_lines;
+ {
+ const std::string info((const char *)buffer->GetBytes());
+ for (size_t tail = 0; tail < info.size();) {
+ // find next new line or end of string
+ size_t head = info.find('\n', tail);
+ head = (head == std::string::npos) ? info.size() : head;
+ std::string line = info.substr(tail, head - tail);
+ // add to line list
+ info_lines.push_back(line);
+ tail = head + 1;
}
+ }
- std::array<char, MAXLINE> name{{'\0'}};
- std::array<char, MAXLINE> value{{'\0'}};
+ std::array<char, MAXLINE> name{{'\0'}};
+ std::array<char, MAXLINE> value{{'\0'}};
- // parse all text lines of .rs.info
- for (auto line = info_lines.begin(); line != info_lines.end(); ++line)
- {
- uint32_t numDefns = 0;
- if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str()));
+ // parse all text lines of .rs.info
+ for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {
+ uint32_t numDefns = 0;
+ if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1) {
+ while (numDefns--)
+ m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str()));
+ } else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "",
+ &numDefns) == 1) {
+ while (numDefns--) {
+ uint32_t slot = 0;
+ name[0] = '\0';
+ static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR;
+ if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2) {
+ if (name[0] != '\0')
+ m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot));
}
- else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- {
- uint32_t slot = 0;
- name[0] = '\0';
- static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR;
- if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2)
- {
- if (name[0] != '\0')
- m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot));
- }
- }
+ }
+ } else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) ==
+ 1) {
+ while (numDefns--) {
+ name[0] = value[0] = '\0';
+ static const char *fmt_s = MAXLINESTR " - " MAXLINESTR;
+ if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0) {
+ if (name[0] != '\0')
+ m_pragmas[std::string(name.data())] = value.data();
}
- else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) == 1)
- {
- while (numDefns--)
- {
- name[0] = value[0] = '\0';
- static const char *fmt_s = MAXLINESTR " - " MAXLINESTR;
- if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0)
- {
- if (name[0] != '\0')
- m_pragmas[std::string(name.data())] = value.data();
- }
- }
- }
- else
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if (log)
- {
- log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, line->c_str());
- }
- }
+ }
+ } else {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log) {
+ log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__,
+ line->c_str());
+ }
}
+ }
- // 'root' kernel should always be present
- return m_kernels.size() > 0;
+ // 'root' kernel should always be present
+ return m_kernels.size() > 0;
}
-void
-RenderScriptRuntime::Status(Stream &strm) const
-{
- if (m_libRS)
- {
- strm.Printf("Runtime Library discovered.");
- strm.EOL();
- }
- if (m_libRSDriver)
- {
- strm.Printf("Runtime Driver discovered.");
- strm.EOL();
- }
- if (m_libRSCpuRef)
- {
- strm.Printf("CPU Reference Implementation discovered.");
- strm.EOL();
- }
-
- if (m_runtimeHooks.size())
- {
- strm.Printf("Runtime functions hooked:");
- strm.EOL();
- for (auto b : m_runtimeHooks)
- {
- strm.Indent(b.second->defn->name);
- strm.EOL();
- }
- }
- else
- {
- strm.Printf("Runtime is not hooked.");
- strm.EOL();
- }
-}
-
-void
-RenderScriptRuntime::DumpContexts(Stream &strm) const
-{
- strm.Printf("Inferred RenderScript Contexts:");
+void RenderScriptRuntime::Status(Stream &strm) const {
+ if (m_libRS) {
+ strm.Printf("Runtime Library discovered.");
strm.EOL();
- strm.IndentMore();
+ }
+ if (m_libRSDriver) {
+ strm.Printf("Runtime Driver discovered.");
+ strm.EOL();
+ }
+ if (m_libRSCpuRef) {
+ strm.Printf("CPU Reference Implementation discovered.");
+ strm.EOL();
+ }
- std::map<addr_t, uint64_t> contextReferences;
-
- // Iterate over all of the currently discovered scripts.
- // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
- for (const auto &script : m_scripts)
- {
- if (!script->context.isValid())
- continue;
- lldb::addr_t context = *script->context;
-
- if (contextReferences.find(context) != contextReferences.end())
- {
- contextReferences[context]++;
- }
- else
- {
- contextReferences[context] = 1;
- }
+ if (m_runtimeHooks.size()) {
+ strm.Printf("Runtime functions hooked:");
+ strm.EOL();
+ for (auto b : m_runtimeHooks) {
+ strm.Indent(b.second->defn->name);
+ strm.EOL();
}
-
- for (const auto &cRef : contextReferences)
- {
- strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
- strm.EOL();
- }
- strm.IndentLess();
+ } else {
+ strm.Printf("Runtime is not hooked.");
+ strm.EOL();
+ }
}
-void
-RenderScriptRuntime::DumpKernels(Stream &strm) const
-{
- strm.Printf("RenderScript Kernels:");
- strm.EOL();
- strm.IndentMore();
- for (const auto &module : m_rsmodules)
- {
- strm.Printf("Resource '%s':", module->m_resname.c_str());
- strm.EOL();
- for (const auto &kernel : module->m_kernels)
- {
- strm.Indent(kernel.m_name.AsCString());
- strm.EOL();
- }
+void RenderScriptRuntime::DumpContexts(Stream &strm) const {
+ strm.Printf("Inferred RenderScript Contexts:");
+ strm.EOL();
+ strm.IndentMore();
+
+ std::map<addr_t, uint64_t> contextReferences;
+
+ // Iterate over all of the currently discovered scripts.
+ // Note: We cant push or pop from m_scripts inside this loop or it may
+ // invalidate script.
+ for (const auto &script : m_scripts) {
+ if (!script->context.isValid())
+ continue;
+ lldb::addr_t context = *script->context;
+
+ if (contextReferences.find(context) != contextReferences.end()) {
+ contextReferences[context]++;
+ } else {
+ contextReferences[context] = 1;
}
- strm.IndentLess();
+ }
+
+ for (const auto &cRef : contextReferences) {
+ strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances",
+ cRef.first, cRef.second);
+ strm.EOL();
+ }
+ strm.IndentLess();
+}
+
+void RenderScriptRuntime::DumpKernels(Stream &strm) const {
+ strm.Printf("RenderScript Kernels:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules) {
+ strm.Printf("Resource '%s':", module->m_resname.c_str());
+ strm.EOL();
+ for (const auto &kernel : module->m_kernels) {
+ strm.Indent(kernel.m_name.AsCString());
+ strm.EOL();
+ }
+ }
+ strm.IndentLess();
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
-{
- AllocationDetails *alloc = nullptr;
+RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) {
+ AllocationDetails *alloc = nullptr;
- // See if we can find allocation using id as an index;
- if (alloc_id <= m_allocations.size() && alloc_id != 0 && m_allocations[alloc_id - 1]->id == alloc_id)
- {
- alloc = m_allocations[alloc_id - 1].get();
- return alloc;
- }
-
- // Fallback to searching
- for (const auto &a : m_allocations)
- {
- if (a->id == alloc_id)
- {
- alloc = a.get();
- break;
- }
- }
-
- if (alloc == nullptr)
- {
- strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32, alloc_id);
- strm.EOL();
- }
-
+ // See if we can find allocation using id as an index;
+ if (alloc_id <= m_allocations.size() && alloc_id != 0 &&
+ m_allocations[alloc_id - 1]->id == alloc_id) {
+ alloc = m_allocations[alloc_id - 1].get();
return alloc;
-}
+ }
-// Prints the contents of an allocation to the output stream, which may be a file
-bool
-RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- // Check we can find the desired allocation
- AllocationDetails *alloc = FindAllocByID(strm, id);
- if (!alloc)
- return false; // FindAllocByID() will print error message for us here
-
- if (log)
- log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *alloc->address.get());
-
- // Check we have information about the allocation, if not calculate it
- if (alloc->shouldRefresh())
- {
- if (log)
- log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__);
-
- // JIT all the allocation information
- if (!RefreshAllocation(alloc, frame_ptr))
- {
- strm.Printf("Error: Couldn't JIT allocation details");
- strm.EOL();
- return false;
- }
+ // Fallback to searching
+ for (const auto &a : m_allocations) {
+ if (a->id == alloc_id) {
+ alloc = a.get();
+ break;
}
+ }
- // Establish format and size of each data element
- const uint32_t vec_size = *alloc->element.type_vec_size.get();
- const Element::DataType type = *alloc->element.type.get();
-
- assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && "Invalid allocation type");
-
- lldb::Format format;
- if (type >= Element::RS_TYPE_ELEMENT)
- format = eFormatHex;
- else
- format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
- : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
-
- const uint32_t data_size = *alloc->element.datum_size.get();
-
- if (log)
- log->Printf("%s - element size %" PRIu32 " bytes, including padding", __FUNCTION__, data_size);
-
- // Allocate a buffer to copy data into
- std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
- if (!buffer)
- {
- strm.Printf("Error: Couldn't read allocation data");
- strm.EOL();
- return false;
- }
-
- // Calculate stride between rows as there may be padding at end of rows since
- // allocated memory is 16-byte aligned
- if (!alloc->stride.isValid())
- {
- if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
- alloc->stride = 0;
- else if (!JITAllocationStride(alloc, frame_ptr))
- {
- strm.Printf("Error: Couldn't calculate allocation row stride");
- strm.EOL();
- return false;
- }
- }
- const uint32_t stride = *alloc->stride.get();
- const uint32_t size = *alloc->size.get(); // Size of whole allocation
- const uint32_t padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
- if (log)
- log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32 " bytes, padding %" PRIu32,
- __FUNCTION__, stride, size, padding);
-
- // Find dimensions used to index loops, so need to be non-zero
- uint32_t dim_x = alloc->dimension.get()->dim_1;
- dim_x = dim_x == 0 ? 1 : dim_x;
-
- uint32_t dim_y = alloc->dimension.get()->dim_2;
- dim_y = dim_y == 0 ? 1 : dim_y;
-
- uint32_t dim_z = alloc->dimension.get()->dim_3;
- dim_z = dim_z == 0 ? 1 : dim_z;
-
- // Use data extractor to format output
- const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
- DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
-
- uint32_t offset = 0; // Offset in buffer to next element to be printed
- uint32_t prev_row = 0; // Offset to the start of the previous row
-
- // Iterate over allocation dimensions, printing results to user
- strm.Printf("Data (X, Y, Z):");
- for (uint32_t z = 0; z < dim_z; ++z)
- {
- for (uint32_t y = 0; y < dim_y; ++y)
- {
- // Use stride to index start of next row.
- if (!(y == 0 && z == 0))
- offset = prev_row + stride;
- prev_row = offset;
-
- // Print each element in the row individually
- for (uint32_t x = 0; x < dim_x; ++x)
- {
- strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
- if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) &&
- (alloc->element.type_name != Element::GetFallbackStructName()))
- {
- // Here we are dumping an Element of struct type.
- // This is done using expression evaluation with the name of the struct type and pointer to element.
-
- // Don't print the name of the resulting expression, since this will be '$[0-9]+'
- DumpValueObjectOptions expr_options;
- expr_options.SetHideName(true);
-
- // Setup expression as derefrencing a pointer cast to element address.
- char expr_char_buffer[jit_max_expr_size];
- int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
- alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);
-
- if (chars_written < 0 || chars_written >= jit_max_expr_size)
- {
- if (log)
- log->Printf("%s - error in snprintf().", __FUNCTION__);
- continue;
- }
-
- // Evaluate expression
- ValueObjectSP expr_result;
- GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result);
-
- // Print the results to our stream.
- expr_result->Dump(strm, expr_options);
- }
- else
- {
- alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
- }
- offset += data_size;
- }
- }
- }
+ if (alloc == nullptr) {
+ strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32,
+ alloc_id);
strm.EOL();
+ }
- return true;
+ return alloc;
}
-// Function recalculates all our cached information about allocations by jitting the
+// Prints the contents of an allocation to the output stream, which may be a
+// file
+bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t id) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Check we can find the desired allocation
+ AllocationDetails *alloc = FindAllocByID(strm, id);
+ if (!alloc)
+ return false; // FindAllocByID() will print error message for us here
+
+ if (log)
+ log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__,
+ *alloc->address.get());
+
+ // Check we have information about the allocation, if not calculate it
+ if (alloc->shouldRefresh()) {
+ if (log)
+ log->Printf("%s - allocation details not calculated yet, jitting info.",
+ __FUNCTION__);
+
+ // JIT all the allocation information
+ if (!RefreshAllocation(alloc, frame_ptr)) {
+ strm.Printf("Error: Couldn't JIT allocation details");
+ strm.EOL();
+ return false;
+ }
+ }
+
+ // Establish format and size of each data element
+ const uint32_t vec_size = *alloc->element.type_vec_size.get();
+ const Element::DataType type = *alloc->element.type.get();
+
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
+ "Invalid allocation type");
+
+ lldb::Format format;
+ if (type >= Element::RS_TYPE_ELEMENT)
+ format = eFormatHex;
+ else
+ format = vec_size == 1
+ ? static_cast<lldb::Format>(
+ AllocationDetails::RSTypeToFormat[type][eFormatSingle])
+ : static_cast<lldb::Format>(
+ AllocationDetails::RSTypeToFormat[type][eFormatVector]);
+
+ const uint32_t data_size = *alloc->element.datum_size.get();
+
+ if (log)
+ log->Printf("%s - element size %" PRIu32 " bytes, including padding",
+ __FUNCTION__, data_size);
+
+ // Allocate a buffer to copy data into
+ std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer) {
+ strm.Printf("Error: Couldn't read allocation data");
+ strm.EOL();
+ return false;
+ }
+
+ // Calculate stride between rows as there may be padding at end of rows since
+ // allocated memory is 16-byte aligned
+ if (!alloc->stride.isValid()) {
+ if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
+ alloc->stride = 0;
+ else if (!JITAllocationStride(alloc, frame_ptr)) {
+ strm.Printf("Error: Couldn't calculate allocation row stride");
+ strm.EOL();
+ return false;
+ }
+ }
+ const uint32_t stride = *alloc->stride.get();
+ const uint32_t size = *alloc->size.get(); // Size of whole allocation
+ const uint32_t padding =
+ alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
+ if (log)
+ log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32
+ " bytes, padding %" PRIu32,
+ __FUNCTION__, stride, size, padding);
+
+ // Find dimensions used to index loops, so need to be non-zero
+ uint32_t dim_x = alloc->dimension.get()->dim_1;
+ dim_x = dim_x == 0 ? 1 : dim_x;
+
+ uint32_t dim_y = alloc->dimension.get()->dim_2;
+ dim_y = dim_y == 0 ? 1 : dim_y;
+
+ uint32_t dim_z = alloc->dimension.get()->dim_3;
+ dim_z = dim_z == 0 ? 1 : dim_z;
+
+ // Use data extractor to format output
+ const uint32_t archByteSize =
+ GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(),
+ archByteSize);
+
+ uint32_t offset = 0; // Offset in buffer to next element to be printed
+ uint32_t prev_row = 0; // Offset to the start of the previous row
+
+ // Iterate over allocation dimensions, printing results to user
+ strm.Printf("Data (X, Y, Z):");
+ for (uint32_t z = 0; z < dim_z; ++z) {
+ for (uint32_t y = 0; y < dim_y; ++y) {
+ // Use stride to index start of next row.
+ if (!(y == 0 && z == 0))
+ offset = prev_row + stride;
+ prev_row = offset;
+
+ // Print each element in the row individually
+ for (uint32_t x = 0; x < dim_x; ++x) {
+ strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
+ if ((type == Element::RS_TYPE_NONE) &&
+ (alloc->element.children.size() > 0) &&
+ (alloc->element.type_name != Element::GetFallbackStructName())) {
+ // Here we are dumping an Element of struct type.
+ // This is done using expression evaluation with the name of the
+ // struct type and pointer to element.
+
+ // Don't print the name of the resulting expression, since this will
+ // be '$[0-9]+'
+ DumpValueObjectOptions expr_options;
+ expr_options.SetHideName(true);
+
+ // Setup expression as derefrencing a pointer cast to element address.
+ char expr_char_buffer[jit_max_expr_size];
+ int chars_written =
+ snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
+ alloc->element.type_name.AsCString(),
+ *alloc->data_ptr.get() + offset);
+
+ if (chars_written < 0 || chars_written >= jit_max_expr_size) {
+ if (log)
+ log->Printf("%s - error in snprintf().", __FUNCTION__);
+ continue;
+ }
+
+ // Evaluate expression
+ ValueObjectSP expr_result;
+ GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer,
+ frame_ptr, expr_result);
+
+ // Print the results to our stream.
+ expr_result->Dump(strm, expr_options);
+ } else {
+ alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1,
+ LLDB_INVALID_ADDRESS, 0, 0);
+ }
+ offset += data_size;
+ }
+ }
+ }
+ strm.EOL();
+
+ return true;
+}
+
+// Function recalculates all our cached information about allocations by jitting
+// the
// RS runtime regarding each allocation we know about.
// Returns true if all allocations could be recomputed, false otherwise.
-bool
-RenderScriptRuntime::RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr)
-{
- bool success = true;
- for (auto &alloc : m_allocations)
- {
- // JIT current allocation information
- if (!RefreshAllocation(alloc.get(), frame_ptr))
- {
- strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32 "\n", alloc->id);
- success = false;
- }
+bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
+ StackFrame *frame_ptr) {
+ bool success = true;
+ for (auto &alloc : m_allocations) {
+ // JIT current allocation information
+ if (!RefreshAllocation(alloc.get(), frame_ptr)) {
+ strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32
+ "\n",
+ alloc->id);
+ success = false;
}
+ }
- if (success)
- strm.Printf("All allocations successfully recomputed");
- strm.EOL();
+ if (success)
+ strm.Printf("All allocations successfully recomputed");
+ strm.EOL();
- return success;
+ return success;
}
// Prints information regarding currently loaded allocations.
// These details are gathered by jitting the runtime, which has as latency.
-// Index parameter specifies a single allocation ID to print, or a zero value to print them all
-void
-RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index)
-{
- strm.Printf("RenderScript Allocations:");
+// Index parameter specifies a single allocation ID to print, or a zero value to
+// print them all
+void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t index) {
+ strm.Printf("RenderScript Allocations:");
+ strm.EOL();
+ strm.IndentMore();
+
+ for (auto &alloc : m_allocations) {
+ // index will only be zero if we want to print all allocations
+ if (index != 0 && index != alloc->id)
+ continue;
+
+ // JIT current allocation information
+ if (alloc->shouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) {
+ strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32,
+ alloc->id);
+ strm.EOL();
+ continue;
+ }
+
+ strm.Printf("%" PRIu32 ":", alloc->id);
strm.EOL();
strm.IndentMore();
- for (auto &alloc : m_allocations)
- {
- // index will only be zero if we want to print all allocations
- if (index != 0 && index != alloc->id)
- continue;
+ strm.Indent("Context: ");
+ if (!alloc->context.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
- // JIT current allocation information
- if (alloc->shouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr))
- {
- strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32, alloc->id);
- strm.EOL();
- continue;
- }
+ strm.Indent("Address: ");
+ if (!alloc->address.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
- strm.Printf("%" PRIu32 ":", alloc->id);
- strm.EOL();
- strm.IndentMore();
+ strm.Indent("Data pointer: ");
+ if (!alloc->data_ptr.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
- strm.Indent("Context: ");
- if (!alloc->context.isValid())
- strm.Printf("unknown\n");
+ strm.Indent("Dimensions: ");
+ if (!alloc->dimension.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
+ alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2,
+ alloc->dimension.get()->dim_3);
+
+ strm.Indent("Data Type: ");
+ if (!alloc->element.type.isValid() ||
+ !alloc->element.type_vec_size.isValid())
+ strm.Printf("unknown\n");
+ else {
+ const int vector_size = *alloc->element.type_vec_size.get();
+ Element::DataType type = *alloc->element.type.get();
+
+ if (!alloc->element.type_name.IsEmpty())
+ strm.Printf("%s\n", alloc->element.type_name.AsCString());
+ else {
+ // Enum value isn't monotonous, so doesn't always index
+ // RsDataTypeToString array
+ if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ type =
+ static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
+ Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
+ sizeof(AllocationDetails::RsDataTypeToString[0])) ||
+ vector_size > 4 || vector_size < 1)
+ strm.Printf("invalid type\n");
else
- strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
-
- strm.Indent("Address: ");
- if (!alloc->address.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
-
- strm.Indent("Data pointer: ");
- if (!alloc->data_ptr.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
-
- strm.Indent("Dimensions: ");
- if (!alloc->dimension.isValid())
- strm.Printf("unknown\n");
- else
- strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
- alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2, alloc->dimension.get()->dim_3);
-
- strm.Indent("Data Type: ");
- if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())
- strm.Printf("unknown\n");
- else
- {
- const int vector_size = *alloc->element.type_vec_size.get();
- Element::DataType type = *alloc->element.type.get();
-
- if (!alloc->element.type_name.IsEmpty())
- strm.Printf("%s\n", alloc->element.type_name.AsCString());
- else
- {
- // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
- if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
- type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
- Element::RS_TYPE_MATRIX_2X2 + 1);
-
- if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
- sizeof(AllocationDetails::RsDataTypeToString[0])) ||
- vector_size > 4 || vector_size < 1)
- strm.Printf("invalid type\n");
- else
- strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
- [vector_size - 1]);
- }
- }
-
- strm.Indent("Data Kind: ");
- if (!alloc->element.type_kind.isValid())
- strm.Printf("unknown\n");
- else
- {
- const Element::DataKind kind = *alloc->element.type_kind.get();
- if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
- strm.Printf("invalid kind\n");
- else
- strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
- }
-
- strm.EOL();
- strm.IndentLess();
+ strm.Printf(
+ "%s\n",
+ AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
+ [vector_size - 1]);
+ }
}
+
+ strm.Indent("Data Kind: ");
+ if (!alloc->element.type_kind.isValid())
+ strm.Printf("unknown\n");
+ else {
+ const Element::DataKind kind = *alloc->element.type_kind.get();
+ if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
+ strm.Printf("invalid kind\n");
+ else
+ strm.Printf(
+ "%s\n",
+ AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
+ }
+
+ strm.EOL();
strm.IndentLess();
+ }
+ strm.IndentLess();
}
// Set breakpoints on every kernel found in RS module
-void
-RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
-{
- for (const auto &kernel : rsmodule_sp->m_kernels)
- {
- // Don't set breakpoint on 'root' kernel
- if (strcmp(kernel.m_name.AsCString(), "root") == 0)
- continue;
+void RenderScriptRuntime::BreakOnModuleKernels(
+ const RSModuleDescriptorSP rsmodule_sp) {
+ for (const auto &kernel : rsmodule_sp->m_kernels) {
+ // Don't set breakpoint on 'root' kernel
+ if (strcmp(kernel.m_name.AsCString(), "root") == 0)
+ continue;
- CreateKernelBreakpoint(kernel.m_name);
- }
+ CreateKernelBreakpoint(kernel.m_name);
+ }
}
// Method is internally called by the 'kernel breakpoint all' command to
@@ -3175,1200 +3071,1191 @@
//
// When do_break is true we want to enable this functionality.
// When do_break is false we want to disable it.
-void
-RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
- InitSearchFilter(target);
+ InitSearchFilter(target);
- // Set breakpoints on all the kernels
- if (do_break && !m_breakAllKernels)
- {
- m_breakAllKernels = true;
+ // Set breakpoints on all the kernels
+ if (do_break && !m_breakAllKernels) {
+ m_breakAllKernels = true;
- for (const auto &module : m_rsmodules)
- BreakOnModuleKernels(module);
+ for (const auto &module : m_rsmodules)
+ BreakOnModuleKernels(module);
- if (log)
- log->Printf("%s(True) - breakpoints set on all currently loaded kernels.", __FUNCTION__);
- }
- else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
- {
- m_breakAllKernels = false;
+ if (log)
+ log->Printf("%s(True) - breakpoints set on all currently loaded kernels.",
+ __FUNCTION__);
+ } else if (!do_break &&
+ m_breakAllKernels) // Breakpoints won't be set on any new kernels.
+ {
+ m_breakAllKernels = false;
- if (log)
- log->Printf("%s(False) - breakpoints no longer automatically set.", __FUNCTION__);
- }
+ if (log)
+ log->Printf("%s(False) - breakpoints no longer automatically set.",
+ __FUNCTION__);
+ }
}
// Given the name of a kernel this function creates a breakpoint using our
// own breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
-RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
- if (!m_filtersp)
- {
- if (log)
- log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__);
- return nullptr;
- }
+ if (!m_filtersp) {
+ if (log)
+ log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__);
+ return nullptr;
+ }
- BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
+ BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
+ BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(
+ m_filtersp, resolver_sp, false, false, false);
- // Give RS breakpoints a specific name, so the user can manipulate them as a group.
- Error err;
- if (!bp->AddName("RenderScriptKernel", err) && log)
- log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString());
+ // Give RS breakpoints a specific name, so the user can manipulate them as a
+ // group.
+ Error err;
+ if (!bp->AddName("RenderScriptKernel", err) && log)
+ log->Printf("%s - error setting break name, '%s'.", __FUNCTION__,
+ err.AsCString());
- return bp;
+ return bp;
}
-// Given an expression for a variable this function tries to calculate the variable's value.
-// If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
+// Given an expression for a variable this function tries to calculate the
+// variable's value.
+// If this is possible it returns true and sets the uint64_t parameter to the
+// variables unsigned value.
// Otherwise function returns false.
-bool
-RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char *var_name, uint64_t &val)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- Error error;
- VariableSP var_sp;
+bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp,
+ const char *var_name,
+ uint64_t &val) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ Error error;
+ VariableSP var_sp;
- // Find variable in stack frame
- ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
- var_name, eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
- var_sp, error));
- if (!error.Success())
- {
- if (log)
- log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__, var_name);
- return false;
- }
-
- // Find the uint32_t value for the variable
- bool success = false;
- val = value_sp->GetValueAsUnsigned(0, &success);
- if (!success)
- {
- if (log)
- log->Printf("%s - error, couldn't parse '%s' as an uint32_t.", __FUNCTION__, var_name);
- return false;
- }
-
- return true;
-}
-
-// Function attempts to find the current coordinate of a kernel invocation by investigating the
-// values of frame variables in the .expand function. These coordinates are returned via the coord
-// array reference parameter. Returns true if the coordinates could be found, and false otherwise.
-bool
-RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Thread *thread_ptr)
-{
- static const std::string s_runtimeExpandSuffix(".expand");
- static const std::array<const char *, 3> s_runtimeCoordVars{{"rsIndex", "p->current.y", "p->current.z"}};
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (!thread_ptr)
- {
- if (log)
- log->Printf("%s - Error, No thread pointer", __FUNCTION__);
-
- return false;
- }
-
- // Walk the call stack looking for a function whose name has the suffix '.expand'
- // and contains the variables we're looking for.
- for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i)
- {
- if (!thread_ptr->SetSelectedFrameByIndex(i))
- continue;
-
- StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
- if (!frame_sp)
- continue;
-
- // Find the function name
- const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
- const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString();
- if (!func_name_cstr)
- continue;
-
- if (log)
- log->Printf("%s - Inspecting function '%s'", __FUNCTION__, func_name_cstr);
-
- // Check if function name has .expand suffix
- std::string func_name(func_name_cstr);
- const int length_difference = func_name.length() - s_runtimeExpandSuffix.length();
- if (length_difference <= 0)
- continue;
-
- const int32_t has_expand_suffix = func_name.compare(length_difference,
- s_runtimeExpandSuffix.length(),
- s_runtimeExpandSuffix);
-
- if (has_expand_suffix != 0)
- continue;
-
- if (log)
- log->Printf("%s - Found .expand function '%s'", __FUNCTION__, func_name_cstr);
-
- // Get values for variables in .expand frame that tell us the current kernel invocation
- bool found_coord_variables = true;
- assert(s_runtimeCoordVars.size() == coord.size());
-
- for (uint32_t i = 0; i < coord.size(); ++i)
- {
- uint64_t value = 0;
- if (!GetFrameVarAsUnsigned(frame_sp, s_runtimeCoordVars[i], value))
- {
- found_coord_variables = false;
- break;
- }
- coord[i] = value;
- }
-
- if (found_coord_variables)
- return true;
- }
+ // Find variable in stack frame
+ ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
+ var_name, eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+ var_sp, error));
+ if (!error.Success()) {
+ if (log)
+ log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__,
+ var_name);
return false;
+ }
+
+ // Find the uint32_t value for the variable
+ bool success = false;
+ val = value_sp->GetValueAsUnsigned(0, &success);
+ if (!success) {
+ if (log)
+ log->Printf("%s - error, couldn't parse '%s' as an uint32_t.",
+ __FUNCTION__, var_name);
+ return false;
+ }
+
+ return true;
}
-// Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
-// Baton parameter contains a pointer to the target coordinate we want to break on.
-// Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
+// Function attempts to find the current coordinate of a kernel invocation by
+// investigating the
+// values of frame variables in the .expand function. These coordinates are
+// returned via the coord
+// array reference parameter. Returns true if the coordinates could be found,
+// and false otherwise.
+bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
+ Thread *thread_ptr) {
+ static const std::string s_runtimeExpandSuffix(".expand");
+ static const std::array<const char *, 3> s_runtimeCoordVars{
+ {"rsIndex", "p->current.y", "p->current.z"}};
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!thread_ptr) {
+ if (log)
+ log->Printf("%s - Error, No thread pointer", __FUNCTION__);
+
+ return false;
+ }
+
+ // Walk the call stack looking for a function whose name has the suffix
+ // '.expand'
+ // and contains the variables we're looking for.
+ for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) {
+ if (!thread_ptr->SetSelectedFrameByIndex(i))
+ continue;
+
+ StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
+ if (!frame_sp)
+ continue;
+
+ // Find the function name
+ const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
+ const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString();
+ if (!func_name_cstr)
+ continue;
+
+ if (log)
+ log->Printf("%s - Inspecting function '%s'", __FUNCTION__,
+ func_name_cstr);
+
+ // Check if function name has .expand suffix
+ std::string func_name(func_name_cstr);
+ const int length_difference =
+ func_name.length() - s_runtimeExpandSuffix.length();
+ if (length_difference <= 0)
+ continue;
+
+ const int32_t has_expand_suffix =
+ func_name.compare(length_difference, s_runtimeExpandSuffix.length(),
+ s_runtimeExpandSuffix);
+
+ if (has_expand_suffix != 0)
+ continue;
+
+ if (log)
+ log->Printf("%s - Found .expand function '%s'", __FUNCTION__,
+ func_name_cstr);
+
+ // Get values for variables in .expand frame that tell us the current kernel
+ // invocation
+ bool found_coord_variables = true;
+ assert(s_runtimeCoordVars.size() == coord.size());
+
+ for (uint32_t i = 0; i < coord.size(); ++i) {
+ uint64_t value = 0;
+ if (!GetFrameVarAsUnsigned(frame_sp, s_runtimeCoordVars[i], value)) {
+ found_coord_variables = false;
+ break;
+ }
+ coord[i] = value;
+ }
+
+ if (found_coord_variables)
+ return true;
+ }
+ return false;
+}
+
+// Callback when a kernel breakpoint hits and we're looking for a specific
+// coordinate.
+// Baton parameter contains a pointer to the target coordinate we want to break
+// on.
+// Function then checks the .expand frame for the current coordinate and breaks
+// to user if it matches.
// Parameter 'break_id' is the id of the Breakpoint which made the callback.
// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
// a single logical breakpoint can have multiple addresses.
-bool
-RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, user_id_t break_id,
- user_id_t break_loc_id)
-{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
+ StoppointCallbackContext *ctx,
+ user_id_t break_id,
+ user_id_t break_loc_id) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
- assert(baton && "Error: null baton in conditional kernel breakpoint callback");
+ assert(baton &&
+ "Error: null baton in conditional kernel breakpoint callback");
- // Coordinate we want to stop on
- const uint32_t *target_coord = static_cast<const uint32_t *>(baton);
+ // Coordinate we want to stop on
+ const uint32_t *target_coord = static_cast<const uint32_t *>(baton);
+ if (log)
+ log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32
+ ")",
+ __FUNCTION__, break_id, target_coord[0], target_coord[1],
+ target_coord[2]);
+
+ // Select current thread
+ ExecutionContext context(ctx->exe_ctx_ref);
+ Thread *thread_ptr = context.GetThreadPtr();
+ assert(thread_ptr && "Null thread pointer");
+
+ // Find current kernel invocation from .expand frame variables
+ RSCoordinate current_coord{}; // Zero initialise array
+ if (!GetKernelCoordinate(current_coord, thread_ptr)) {
if (log)
- log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", __FUNCTION__, break_id,
- target_coord[0], target_coord[1], target_coord[2]);
-
- // Select current thread
- ExecutionContext context(ctx->exe_ctx_ref);
- Thread *thread_ptr = context.GetThreadPtr();
- assert(thread_ptr && "Null thread pointer");
-
- // Find current kernel invocation from .expand frame variables
- RSCoordinate current_coord{}; // Zero initialise array
- if (!GetKernelCoordinate(current_coord, thread_ptr))
- {
- if (log)
- log->Printf("%s - Error, couldn't select .expand stack frame", __FUNCTION__);
- return false;
- }
-
- if (log)
- log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0], current_coord[1],
- current_coord[2]);
-
- // Check if the current kernel invocation coordinate matches our target coordinate
- if (current_coord[0] == target_coord[0] &&
- current_coord[1] == target_coord[1] &&
- current_coord[2] == target_coord[2])
- {
- if (log)
- log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0],
- current_coord[1], current_coord[2]);
-
- BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
- assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
- breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
- return true;
- }
-
- // No match on coordinate
+ log->Printf("%s - Error, couldn't select .expand stack frame",
+ __FUNCTION__);
return false;
+ }
+
+ if (log)
+ log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__,
+ current_coord[0], current_coord[1], current_coord[2]);
+
+ // Check if the current kernel invocation coordinate matches our target
+ // coordinate
+ if (current_coord[0] == target_coord[0] &&
+ current_coord[1] == target_coord[1] &&
+ current_coord[2] == target_coord[2]) {
+ if (log)
+ log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")",
+ __FUNCTION__, current_coord[0], current_coord[1],
+ current_coord[2]);
+
+ BreakpointSP breakpoint_sp =
+ context.GetTargetPtr()->GetBreakpointByID(break_id);
+ assert(breakpoint_sp != nullptr &&
+ "Error: Couldn't find breakpoint matching break id for callback");
+ breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint
+ // should only be hit once.
+ return true;
+ }
+
+ // No match on coordinate
+ return false;
}
-// Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
-// Argument 'coords', represents a three dimensional coordinate which can be used to specify
-// a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
-void
-RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int, 3> coords,
- Error &error, TargetSP target)
-{
- if (!name)
- {
- error.SetErrorString("invalid kernel name");
- return;
- }
+// Tries to set a breakpoint on the start of a kernel, resolved using the kernel
+// name.
+// Argument 'coords', represents a three dimensional coordinate which can be
+// used to specify
+// a single kernel instance to break on. If this is set then we add a callback
+// to the breakpoint.
+void RenderScriptRuntime::PlaceBreakpointOnKernel(
+ Stream &strm, const char *name, const std::array<int, 3> coords,
+ Error &error, TargetSP target) {
+ if (!name) {
+ error.SetErrorString("invalid kernel name");
+ return;
+ }
- InitSearchFilter(target);
+ InitSearchFilter(target);
- ConstString kernel_name(name);
- BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
+ ConstString kernel_name(name);
+ BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
- // We have a conditional breakpoint on a specific coordinate
- if (coords[0] != -1)
- {
- strm.Printf("Conditional kernel breakpoint on coordinate %" PRId32 ", %" PRId32 ", %" PRId32,
- coords[0], coords[1], coords[2]);
- strm.EOL();
-
- // Allocate memory for the baton, and copy over coordinate
- uint32_t *baton = new uint32_t[coords.size()];
- baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
-
- // Create a callback that will be invoked every time the breakpoint is hit.
- // The baton object passed to the handler is the target coordinate we want to break on.
- bp->SetCallback(KernelBreakpointHit, baton, true);
-
- // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
- m_conditional_breaks[bp->GetID()] = std::shared_ptr<uint32_t>(baton);
- }
-
- if (bp)
- bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
-}
-
-void
-RenderScriptRuntime::DumpModules(Stream &strm) const
-{
- strm.Printf("RenderScript Modules:");
+ // We have a conditional breakpoint on a specific coordinate
+ if (coords[0] != -1) {
+ strm.Printf("Conditional kernel breakpoint on coordinate %" PRId32
+ ", %" PRId32 ", %" PRId32,
+ coords[0], coords[1], coords[2]);
strm.EOL();
- strm.IndentMore();
- for (const auto &module : m_rsmodules)
- {
- module->Dump(strm);
- }
- strm.IndentLess();
+
+ // Allocate memory for the baton, and copy over coordinate
+ uint32_t *baton = new uint32_t[coords.size()];
+ baton[0] = coords[0];
+ baton[1] = coords[1];
+ baton[2] = coords[2];
+
+ // Create a callback that will be invoked every time the breakpoint is hit.
+ // The baton object passed to the handler is the target coordinate we want
+ // to break on.
+ bp->SetCallback(KernelBreakpointHit, baton, true);
+
+ // Store a shared pointer to the baton, so the memory will eventually be
+ // cleaned up after destruction
+ m_conditional_breaks[bp->GetID()] = std::shared_ptr<uint32_t>(baton);
+ }
+
+ if (bp)
+ bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
+}
+
+void RenderScriptRuntime::DumpModules(Stream &strm) const {
+ strm.Printf("RenderScript Modules:");
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &module : m_rsmodules) {
+ module->Dump(strm);
+ }
+ strm.IndentLess();
}
RenderScriptRuntime::ScriptDetails *
-RenderScriptRuntime::LookUpScript(addr_t address, bool create)
-{
- for (const auto &s : m_scripts)
- {
- if (s->script.isValid())
- if (*s->script == address)
- return s.get();
- }
- if (create)
- {
- std::unique_ptr<ScriptDetails> s(new ScriptDetails);
- s->script = address;
- m_scripts.push_back(std::move(s));
- return m_scripts.back().get();
- }
- return nullptr;
+RenderScriptRuntime::LookUpScript(addr_t address, bool create) {
+ for (const auto &s : m_scripts) {
+ if (s->script.isValid())
+ if (*s->script == address)
+ return s.get();
+ }
+ if (create) {
+ std::unique_ptr<ScriptDetails> s(new ScriptDetails);
+ s->script = address;
+ m_scripts.push_back(std::move(s));
+ return m_scripts.back().get();
+ }
+ return nullptr;
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::LookUpAllocation(addr_t address)
-{
- for (const auto &a : m_allocations)
- {
- if (a->address.isValid())
- if (*a->address == address)
- return a.get();
- }
- return nullptr;
+RenderScriptRuntime::LookUpAllocation(addr_t address) {
+ for (const auto &a : m_allocations) {
+ if (a->address.isValid())
+ if (*a->address == address)
+ return a.get();
+ }
+ return nullptr;
}
RenderScriptRuntime::AllocationDetails *
-RenderScriptRuntime::CreateAllocation(addr_t address)
-{
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+RenderScriptRuntime::CreateAllocation(addr_t address) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
- // Remove any previous allocation which contains the same address
- auto it = m_allocations.begin();
- while (it != m_allocations.end())
- {
- if (*((*it)->address) == address)
- {
- if (log)
- log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64, __FUNCTION__, (*it)->id, address);
+ // Remove any previous allocation which contains the same address
+ auto it = m_allocations.begin();
+ while (it != m_allocations.end()) {
+ if (*((*it)->address) == address) {
+ if (log)
+ log->Printf("%s - Removing allocation id: %d, address: 0x%" PRIx64,
+ __FUNCTION__, (*it)->id, address);
- it = m_allocations.erase(it);
- }
+ it = m_allocations.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ std::unique_ptr<AllocationDetails> a(new AllocationDetails);
+ a->address = address;
+ m_allocations.push_back(std::move(a));
+ return m_allocations.back().get();
+}
+
+void RSModuleDescriptor::Dump(Stream &strm) const {
+ strm.Indent();
+ m_module->GetFileSpec().Dump(&strm);
+ if (m_module->GetNumCompileUnits()) {
+ strm.Indent("Debug info loaded.");
+ } else {
+ strm.Indent("Debug info does not exist.");
+ }
+ strm.EOL();
+ strm.IndentMore();
+ strm.Indent();
+ strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &global : m_globals) {
+ global.Dump(strm);
+ }
+ strm.IndentLess();
+ strm.Indent();
+ strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &kernel : m_kernels) {
+ kernel.Dump(strm);
+ }
+ strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
+ strm.EOL();
+ strm.IndentMore();
+ for (const auto &key_val : m_pragmas) {
+ strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
+ strm.EOL();
+ }
+ strm.IndentLess(4);
+}
+
+void RSGlobalDescriptor::Dump(Stream &strm) const {
+ strm.Indent(m_name.AsCString());
+ VariableList var_list;
+ m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
+ if (var_list.GetSize() == 1) {
+ auto var = var_list.GetVariableAtIndex(0);
+ auto type = var->GetType();
+ if (type) {
+ strm.Printf(" - ");
+ type->DumpTypeName(&strm);
+ } else {
+ strm.Printf(" - Unknown Type");
+ }
+ } else {
+ strm.Printf(" - variable identified, but not found in binary");
+ const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(
+ m_name, eSymbolTypeData);
+ if (s) {
+ strm.Printf(" (symbol exists) ");
+ }
+ }
+
+ strm.EOL();
+}
+
+void RSKernelDescriptor::Dump(Stream &strm) const {
+ strm.Indent(m_name.AsCString());
+ strm.EOL();
+}
+
+class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {
+public:
+ CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript module dump",
+ "Dumps renderscript specific information for all modules.",
+ "renderscript module dump",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpModules(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword {
+public:
+ CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript module",
+ "Commands that deal with RenderScript modules.",
+ nullptr) {
+ LoadSubCommand(
+ "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(
+ interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeModule() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed {
+public:
+ CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel list",
+ "Lists renderscript kernel names and associated script resources.",
+ "renderscript kernel list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeKernelList() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpKernels(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpointSet
+ : public CommandObjectParsed {
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpointSet(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel breakpoint set",
+ "Sets a breakpoint on a renderscript kernel.",
+ "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'c':
+ if (!ParseCoordinate(option_arg))
+ error.SetErrorStringWithFormat(
+ "Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
+ option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
+ }
+
+ // -c takes an argument of the form 'num[,num][,num]'.
+ // Where 'id_cstr' is this argument with the whitespace trimmed.
+ // Missing coordinates are defaulted to zero.
+ bool ParseCoordinate(const char *id_cstr) {
+ RegularExpression regex;
+ RegularExpression::Match regex_match(3);
+
+ bool matched = false;
+ if (regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ else if (regex.Compile("^([0-9]+),([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ else if (regex.Compile("^([0-9]+)$") &&
+ regex.Execute(id_cstr, ®ex_match))
+ matched = true;
+ for (uint32_t i = 0; i < 3; i++) {
+ std::string group;
+ if (regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
+ m_coord[i] = (uint32_t)strtoul(group.c_str(), nullptr, 0);
else
- {
- it++;
- }
+ m_coord[i] = 0;
+ }
+ return matched;
}
- std::unique_ptr<AllocationDetails> a(new AllocationDetails);
- a->address = address;
- m_allocations.push_back(std::move(a));
- return m_allocations.back().get();
-}
-
-void
-RSModuleDescriptor::Dump(Stream &strm) const
-{
- strm.Indent();
- m_module->GetFileSpec().Dump(&strm);
- if (m_module->GetNumCompileUnits())
- {
- strm.Indent("Debug info loaded.");
- }
- else
- {
- strm.Indent("Debug info does not exist.");
- }
- strm.EOL();
- strm.IndentMore();
- strm.Indent();
- strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
- strm.EOL();
- strm.IndentMore();
- for (const auto &global : m_globals)
- {
- global.Dump(strm);
- }
- strm.IndentLess();
- strm.Indent();
- strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
- strm.EOL();
- strm.IndentMore();
- for (const auto &kernel : m_kernels)
- {
- kernel.Dump(strm);
- }
- strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
- strm.EOL();
- strm.IndentMore();
- for (const auto &key_val : m_pragmas)
- {
- strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
- strm.EOL();
- }
- strm.IndentLess(4);
-}
-
-void
-RSGlobalDescriptor::Dump(Stream &strm) const
-{
- strm.Indent(m_name.AsCString());
- VariableList var_list;
- m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
- if (var_list.GetSize() == 1)
- {
- auto var = var_list.GetVariableAtIndex(0);
- auto type = var->GetType();
- if (type)
- {
- strm.Printf(" - ");
- type->DumpTypeName(&strm);
- }
- else
- {
- strm.Printf(" - Unknown Type");
- }
- }
- else
- {
- strm.Printf(" - variable identified, but not found in binary");
- const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
- if (s)
- {
- strm.Printf(" (symbol exists) ");
- }
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ // -1 means the -c option hasn't been set
+ m_coord[0] = -1;
+ m_coord[1] = -1;
+ m_coord[2] = -1;
}
- strm.EOL();
-}
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
-void
-RSKernelDescriptor::Dump(Stream &strm) const
-{
- strm.Indent(m_name.AsCString());
- strm.EOL();
-}
+ static OptionDefinition g_option_table[];
+ std::array<int, 3> m_coord;
+ };
-class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
-{
-public:
- CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript module dump",
- "Dumps renderscript specific information for all modules.", "renderscript module dump",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 1 argument of kernel name, and an optional coordinate.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpModules(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
+ Error error;
+ runtime->PlaceBreakpointOnKernel(
+ result.GetOutputStream(), command.GetArgumentAtIndex(0),
+ m_options.m_coord, error, m_exe_ctx.GetTargetSP());
+
+ if (error.Success()) {
+ result.AppendMessage("Breakpoint(s) created");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
}
+ result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Error: %s", error.AsCString());
+ return false;
+ }
+
+private:
+ CommandOptions m_options;
};
-class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
-{
+OptionDefinition CommandObjectRenderScriptRuntimeKernelBreakpointSet::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "coordinate", 'c',
+ OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue,
+ "Set a breakpoint on a single invocation of the kernel with specified "
+ "coordinate.\n"
+ "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
+ "integers representing kernel dimensions. "
+ "Any unset dimensions will be defaulted to zero."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpointAll
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with RenderScript modules.",
- nullptr)
- {
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
+ CommandObjectRenderScriptRuntimeKernelBreakpointAll(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel breakpoint all",
+ "Automatically sets a breakpoint on all renderscript kernels that "
+ "are or will be loaded.\n"
+ "Disabling option means breakpoints will no longer be set on any "
+ "kernels loaded in the future, "
+ "but does not remove currently set breakpoints.",
+ "renderscript kernel breakpoint all <enable/disable>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {}
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 1) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- ~CommandObjectRenderScriptRuntimeModule() override = default;
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ bool do_break = false;
+ const char *argument = command.GetArgumentAtIndex(0);
+ if (strcmp(argument, "enable") == 0) {
+ do_break = true;
+ result.AppendMessage("Breakpoints will be set on all kernels.");
+ } else if (strcmp(argument, "disable") == 0) {
+ do_break = false;
+ result.AppendMessage("Breakpoints will not be set on any new kernels.");
+ } else {
+ result.AppendErrorWithFormat(
+ "Argument must be either 'enable' or 'disable'");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelCoordinate
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel list",
- "Lists renderscript kernel names and associated script resources.",
- "renderscript kernel list", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
+ CommandObjectRenderScriptRuntimeKernelCoordinate(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript kernel coordinate",
+ "Shows the (x,y,z) coordinate of the current kernel invocation.",
+ "renderscript kernel coordinate",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched |
+ eCommandProcessMustBePaused) {}
- ~CommandObjectRenderScriptRuntimeKernelList() override = default;
+ ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpKernels(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RSCoordinate coord{}; // Zero initialize array
+ bool success = RenderScriptRuntime::GetKernelCoordinate(
+ coord, m_exe_ctx.GetThreadPtr());
+ Stream &stream = result.GetOutputStream();
+
+ if (success) {
+ stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")",
+ coord[0], coord[1], coord[2]);
+ stream.EOL();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ } else {
+ stream.Printf("Error: Coordinate could not be found.");
+ stream.EOL();
+ result.SetStatus(eReturnStatusFailed);
}
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeKernelBreakpoint
+ : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
- "Sets a breakpoint on a renderscript kernel.",
- "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
- m_options()
- {
+ CommandObjectRenderScriptRuntimeKernelBreakpoint(
+ CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript kernel",
+ "Commands that generate breakpoints on renderscript kernels.",
+ nullptr) {
+ LoadSubCommand(
+ "set",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(
+ interpreter)));
+ LoadSubCommand(
+ "all",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(
+ interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword {
+public:
+ CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript kernel",
+ "Commands that deal with RenderScript kernels.",
+ nullptr) {
+ LoadSubCommand(
+ "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(
+ interpreter)));
+ LoadSubCommand(
+ "coordinate",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
+ LoadSubCommand(
+ "breakpoint",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernel() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed {
+public:
+ CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript context dump",
+ "Dumps renderscript context information.",
+ "renderscript context dump",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeContextDump() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->DumpContexts(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
+public:
+ CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript context",
+ "Commands that deal with RenderScript contexts.",
+ nullptr) {
+ LoadSubCommand(
+ "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(
+ interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeContext() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeAllocationDump
+ : public CommandObjectParsed {
+public:
+ CommandObjectRenderScriptRuntimeAllocationDump(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation dump",
+ "Displays the contents of a particular allocation",
+ "renderscript allocation dump <ID>",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'f':
+ m_outfile.SetFile(option_arg, true);
+ if (m_outfile.Exists()) {
+ m_outfile.Clear();
+ error.SetErrorStringWithFormat("file already exists: '%s'",
+ option_arg);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_outfile.Clear();
}
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options() {}
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
- ~CommandOptions() override = default;
+ static OptionDefinition g_option_table[];
+ FileSpec m_outfile;
+ };
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1) {
+ result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
+ "As well as an optional -f argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- switch (short_option)
- {
- case 'c':
- if (!ParseCoordinate(option_arg))
- error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
- option_arg);
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
- // -c takes an argument of the form 'num[,num][,num]'.
- // Where 'id_cstr' is this argument with the whitespace trimmed.
- // Missing coordinates are defaulted to zero.
- bool
- ParseCoordinate(const char *id_cstr)
- {
- RegularExpression regex;
- RegularExpression::Match regex_match(3);
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- bool matched = false;
- if (regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- else if (regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- else if (regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match))
- matched = true;
- for (uint32_t i = 0; i < 3; i++)
- {
- std::string group;
- if (regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
- m_coord[i] = (uint32_t)strtoul(group.c_str(), nullptr, 0);
- else
- m_coord[i] = 0;
- }
- return matched;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- // -1 means the -c option hasn't been set
- m_coord[0] = -1;
- m_coord[1] = -1;
- m_coord[2] = -1;
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
-
- static OptionDefinition g_option_table[];
- std::array<int, 3> m_coord;
- };
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc < 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
-
- Error error;
- runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
- error, m_exe_ctx.GetTargetSP());
-
- if (error.Success())
- {
- result.AppendMessage("Breakpoint(s) created");
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ Stream *output_strm = nullptr;
+ StreamFile outfile_stream;
+ const FileSpec &outfile_spec =
+ m_options.m_outfile; // Dump allocation to file instead
+ if (outfile_spec) {
+ // Open output file
+ char path[256];
+ outfile_spec.GetPath(path, sizeof(path));
+ if (outfile_stream.GetFile()
+ .Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)
+ .Success()) {
+ output_strm = &outfile_stream;
+ result.GetOutputStream().Printf("Results written to '%s'", path);
+ result.GetOutputStream().EOL();
+ } else {
+ result.AppendErrorWithFormat("Couldn't open file '%s'", path);
result.SetStatus(eReturnStatusFailed);
- result.AppendErrorWithFormat("Error: %s", error.AsCString());
return false;
- }
+ }
+ } else
+ output_strm = &result.GetOutputStream();
+
+ assert(output_strm != nullptr);
+ bool success =
+ runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
private:
- CommandOptions m_options;
+ CommandOptions m_options;
};
-OptionDefinition CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue,
- "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
- "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
- "Any unset dimensions will be defaulted to zero."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+OptionDefinition CommandObjectRenderScriptRuntimeAllocationDump::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeFilename,
+ "Print results to specified file instead of command line."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationList
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript kernel breakpoint all",
- "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
- "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
- "but does not remove currently set breakpoints.",
- "renderscript kernel breakpoint all <enable/disable>",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
- {
+ CommandObjectRenderScriptRuntimeAllocationList(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript allocation list",
+ "List renderscript allocations and their information.",
+ "renderscript allocation list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched),
+ m_options() {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options(), m_id(0) {}
+
+ ~CommandOptions() override = default;
+
+ Error SetOptionValue(uint32_t option_idx, const char *option_arg,
+ ExecutionContext *execution_context) override {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'i':
+ bool success;
+ m_id = StringConvert::ToUInt32(option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat(
+ "invalid integer value for option '%c'", short_option);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+ return error;
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- bool do_break = false;
- const char *argument = command.GetArgumentAtIndex(0);
- if (strcmp(argument, "enable") == 0)
- {
- do_break = true;
- result.AppendMessage("Breakpoints will be set on all kernels.");
- }
- else if (strcmp(argument, "disable") == 0)
- {
- do_break = false;
- result.AppendMessage("Breakpoints will not be set on any new kernels.");
- }
- else
- {
- result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
-
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
-};
-
-class CommandObjectRenderScriptRuntimeKernelCoordinate : public CommandObjectParsed
-{
-public:
- CommandObjectRenderScriptRuntimeKernelCoordinate(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel coordinate",
- "Shows the (x,y,z) coordinate of the current kernel invocation.",
- "renderscript kernel coordinate",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
- {
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_id = 0;
}
- ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
+ const OptionDefinition *GetDefinitions() override { return g_option_table; }
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RSCoordinate coord{}; // Zero initialize array
- bool success = RenderScriptRuntime::GetKernelCoordinate(coord, m_exe_ctx.GetThreadPtr());
- Stream &stream = result.GetOutputStream();
+ static OptionDefinition g_option_table[];
+ uint32_t m_id;
+ };
- if (success)
- {
- stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", coord[0], coord[1], coord[2]);
- stream.EOL();
- result.SetStatus(eReturnStatusSuccessFinishResult);
- }
- else
- {
- stream.Printf("Error: Coordinate could not be found.");
- stream.EOL();
- result.SetStatus(eReturnStatusFailed);
- }
- return true;
- }
-};
-
-class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
-{
-public:
- CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript kernel",
- "Commands that generate breakpoints on renderscript kernels.", nullptr)
- {
- LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
- LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
- }
-
- ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
-};
-
-class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
-{
-public:
- CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with RenderScript kernels.",
- nullptr)
- {
- LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
- LoadSubCommand("coordinate",
- CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
- LoadSubCommand("breakpoint",
- CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
- }
-
- ~CommandObjectRenderScriptRuntimeKernel() override = default;
-};
-
-class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
-{
-public:
- CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript context dump", "Dumps renderscript context information.",
- "renderscript context dump", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
-
- ~CommandObjectRenderScriptRuntimeContextDump() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->DumpContexts(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
-};
-
-class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
-{
-public:
- CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with RenderScript contexts.",
- nullptr)
- {
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
- }
-
- ~CommandObjectRenderScriptRuntimeContext() override = default;
-};
-
-class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
-{
-public:
- CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation dump",
- "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched),
- m_options()
- {
- }
-
- ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
-
- Options *
- GetOptions() override
- {
- return &m_options;
- }
-
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options() {}
-
- ~CommandOptions() override = default;
-
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'f':
- m_outfile.SetFile(option_arg, true);
- if (m_outfile.Exists())
- {
- m_outfile.Clear();
- error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
- }
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- m_outfile.Clear();
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
-
- static OptionDefinition g_option_table[];
- FileSpec m_outfile;
- };
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc < 1)
- {
- result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- Stream *output_strm = nullptr;
- StreamFile outfile_stream;
- const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
- if (outfile_spec)
- {
- // Open output file
- char path[256];
- outfile_spec.GetPath(path, sizeof(path));
- if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
- {
- output_strm = &outfile_stream;
- result.GetOutputStream().Printf("Results written to '%s'", path);
- result.GetOutputStream().EOL();
- }
- else
- {
- result.AppendErrorWithFormat("Couldn't open file '%s'", path);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
- else
- output_strm = &result.GetOutputStream();
-
- assert(output_strm != nullptr);
- bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
-
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
-
- return true;
- }
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+ runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(),
+ m_options.m_id);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
private:
- CommandOptions m_options;
+ CommandOptions m_options;
};
-OptionDefinition CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename,
- "Print results to specified file instead of command line."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
+OptionDefinition CommandObjectRenderScriptRuntimeAllocationList::
+ CommandOptions::g_option_table[] = {
+ {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument,
+ nullptr, nullptr, 0, eArgTypeIndex,
+ "Only show details of a single allocation with specified id."},
+ {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationLoad
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation list",
- "List renderscript allocations and their information.", "renderscript allocation list",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched),
- m_options()
- {
+ CommandObjectRenderScriptRuntimeAllocationLoad(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "renderscript allocation load",
+ "Loads renderscript allocation contents from a file.",
+ "renderscript allocation load <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 2 arguments, an allocation ID and filename to read from.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
- Options *
- GetOptions() override
- {
- return &m_options;
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- class CommandOptions : public Options
- {
- public:
- CommandOptions() : Options(), m_id(0) {}
+ const char *filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->LoadAllocation(result.GetOutputStream(), id,
+ filename, m_exe_ctx.GetFramePtr());
- ~CommandOptions() override = default;
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
- Error
- SetOptionValue(uint32_t option_idx, const char *option_arg,
- ExecutionContext *execution_context) override
- {
- Error error;
- const int short_option = m_getopt_table[option_idx].val;
-
- switch (short_option)
- {
- case 'i':
- bool success;
- m_id = StringConvert::ToUInt32(option_arg, 0, 0, &success);
- if (!success)
- error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
- break;
- default:
- error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
- break;
- }
- return error;
- }
-
- void
- OptionParsingStarting(ExecutionContext *execution_context) override
- {
- m_id = 0;
- }
-
- const OptionDefinition *
- GetDefinitions() override
- {
- return g_option_table;
- }
-
- static OptionDefinition g_option_table[];
- uint32_t m_id;
- };
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
- runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_id);
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
-
-private:
- CommandOptions m_options;
+ return true;
+ }
};
-OptionDefinition CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = {
- {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex,
- "Only show details of a single allocation with specified id."},
- {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}};
-
-class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationSave
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript allocation load", "Loads renderscript allocation contents from a file.",
- "renderscript allocation load <ID> <filename>", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
+ CommandObjectRenderScriptRuntimeAllocationSave(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation save",
+ "Write renderscript allocation contents to a file.",
+ "renderscript allocation save <ID> <filename>",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2) {
+ result.AppendErrorWithFormat(
+ "'%s' takes 2 arguments, an allocation ID and filename to read from.",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
- ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 2)
- {
- result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char *filename = command.GetArgumentAtIndex(1);
- bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
-
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
-
- return true;
+ const char *id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id =
+ StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete) {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'",
+ id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
+
+ const char *filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->SaveAllocation(result.GetOutputStream(), id,
+ filename, m_exe_ctx.GetFramePtr());
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocationRefresh
+ : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
- : CommandObjectParsed(
- interpreter, "renderscript allocation save", "Write renderscript allocation contents to a file.",
- "renderscript allocation save <ID> <filename>", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
+ CommandObjectRenderScriptRuntimeAllocationRefresh(
+ CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation refresh",
+ "Recomputes the details of all allocations.",
+ "renderscript allocation refresh",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
+
+ ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
+ m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript));
+
+ bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(),
+ m_exe_ctx.GetFramePtr());
+
+ if (success) {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ } else {
+ result.SetStatus(eReturnStatusFailed);
+ return false;
}
-
- ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc != 2)
- {
- result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.",
- m_cmd_name.c_str());
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- const char *id_cstr = command.GetArgumentAtIndex(0);
- bool convert_complete = false;
- const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
- if (!convert_complete)
- {
- result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
- const char *filename = command.GetArgumentAtIndex(1);
- bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
-
- if (success)
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- result.SetStatus(eReturnStatusFailed);
-
- return true;
- }
+ }
};
-class CommandObjectRenderScriptRuntimeAllocationRefresh : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntimeAllocation
+ : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeAllocationRefresh(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript allocation refresh",
- "Recomputes the details of all allocations.", "renderscript allocation refresh",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
+ CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript allocation",
+ "Commands that deal with RenderScript allocations.", nullptr) {
+ LoadSubCommand(
+ "list",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
+ LoadSubCommand(
+ "dump",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
+ LoadSubCommand(
+ "save",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
+ LoadSubCommand(
+ "load",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
+ LoadSubCommand(
+ "refresh",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(
+ interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
- m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
-
- bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr());
-
- if (success)
- {
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
- else
- {
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
- }
+ ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};
-class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
-{
+class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed {
public:
- CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript allocation",
- "Commands that deal with RenderScript allocations.", nullptr)
- {
- LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
- LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
- LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
- LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
- LoadSubCommand("refresh", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(interpreter)));
- }
+ CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript status",
+ "Displays current RenderScript runtime status.",
+ "renderscript status",
+ eCommandRequiresProcess |
+ eCommandProcessMustBeLaunched) {}
- ~CommandObjectRenderScriptRuntimeAllocation() override = default;
+ ~CommandObjectRenderScriptRuntimeStatus() override = default;
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
+ eLanguageTypeExtRenderScript);
+ runtime->Status(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
};
-class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
-{
+class CommandObjectRenderScriptRuntime : public CommandObjectMultiword {
public:
- CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript status", "Displays current RenderScript runtime status.",
- "renderscript status", eCommandRequiresProcess | eCommandProcessMustBeLaunched)
- {
- }
+ CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "renderscript",
+ "Commands for operating on the RenderScript runtime.",
+ "renderscript <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "module", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeModule(interpreter)));
+ LoadSubCommand(
+ "status", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeStatus(interpreter)));
+ LoadSubCommand(
+ "kernel", CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeKernel(interpreter)));
+ LoadSubCommand("context",
+ CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(
+ interpreter)));
+ LoadSubCommand(
+ "allocation",
+ CommandObjectSP(
+ new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
+ }
- ~CommandObjectRenderScriptRuntimeStatus() override = default;
-
- bool
- DoExecute(Args &command, CommandReturnObject &result) override
- {
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
- runtime->Status(result.GetOutputStream());
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
- }
+ ~CommandObjectRenderScriptRuntime() override = default;
};
-class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
-{
-public:
- CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "renderscript", "Commands for operating on the RenderScript runtime.",
- "renderscript <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
- LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
- LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
- LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
- LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
- }
-
- ~CommandObjectRenderScriptRuntime() override = default;
-};
-
-void
-RenderScriptRuntime::Initiate()
-{
- assert(!m_initiated);
-}
+void RenderScriptRuntime::Initiate() { assert(!m_initiated); }
RenderScriptRuntime::RenderScriptRuntime(Process *process)
- : lldb_private::CPPLanguageRuntime(process),
- m_initiated(false),
- m_debuggerPresentFlagged(false),
- m_breakAllKernels(false),
- m_ir_passes(nullptr)
-{
- ModulesDidLoad(process->GetTarget().GetImages());
+ : lldb_private::CPPLanguageRuntime(process), m_initiated(false),
+ m_debuggerPresentFlagged(false), m_breakAllKernels(false),
+ m_ir_passes(nullptr) {
+ ModulesDidLoad(process->GetTarget().GetImages());
}
-lldb::CommandObjectSP
-RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter &interpreter)
-{
- return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
+lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject(
+ lldb_private::CommandInterpreter &interpreter) {
+ return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
}
RenderScriptRuntime::~RenderScriptRuntime() = default;
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 50db2e1..7aad705 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -26,10 +26,8 @@
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
+namespace lldb_private {
+namespace lldb_renderscript {
typedef uint32_t RSSlot;
class RSModuleDescriptor;
@@ -44,383 +42,330 @@
// Breakpoint Resolvers decide where a breakpoint is placed,
// so having our own allows us to limit the search scope to RS kernel modules.
// As well as check for .expand kernels as a fallback.
-class RSBreakpointResolver : public BreakpointResolver
-{
+class RSBreakpointResolver : public BreakpointResolver {
public:
- RSBreakpointResolver(Breakpoint *bkpt, ConstString name)
- : BreakpointResolver(bkpt, BreakpointResolver::NameResolver), m_kernel_name(name)
- {
- }
+ RSBreakpointResolver(Breakpoint *bkpt, ConstString name)
+ : BreakpointResolver(bkpt, BreakpointResolver::NameResolver),
+ m_kernel_name(name) {}
- void
- GetDescription(Stream *strm) override
- {
- if (strm)
- strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
- }
+ void GetDescription(Stream *strm) override {
+ if (strm)
+ strm->Printf("RenderScript kernel breakpoint for '%s'",
+ m_kernel_name.AsCString());
+ }
- void
- Dump(Stream *s) const override
- {
- }
+ void Dump(Stream *s) const override {}
- Searcher::CallbackReturn
- SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) override;
+ Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *addr,
+ bool containing) override;
- Searcher::Depth
- GetDepth() override
- {
- return Searcher::eDepthModule;
- }
+ Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
- lldb::BreakpointResolverSP
- CopyForBreakpoint(Breakpoint &breakpoint) override
- {
- lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
- return ret_sp;
- }
+ lldb::BreakpointResolverSP
+ CopyForBreakpoint(Breakpoint &breakpoint) override {
+ lldb::BreakpointResolverSP ret_sp(
+ new RSBreakpointResolver(&breakpoint, m_kernel_name));
+ return ret_sp;
+ }
protected:
- ConstString m_kernel_name;
+ ConstString m_kernel_name;
};
-struct RSKernelDescriptor
-{
+struct RSKernelDescriptor {
public:
- RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
- : m_module(module), m_name(name), m_slot(slot)
- {
- }
+ RSKernelDescriptor(const RSModuleDescriptor *module, const char *name,
+ uint32_t slot)
+ : m_module(module), m_name(name), m_slot(slot) {}
- void
- Dump(Stream &strm) const;
+ void Dump(Stream &strm) const;
- const RSModuleDescriptor *m_module;
- ConstString m_name;
- RSSlot m_slot;
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
+ RSSlot m_slot;
};
-struct RSGlobalDescriptor
-{
+struct RSGlobalDescriptor {
public:
- RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name) : m_module(module), m_name(name) {}
+ RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name)
+ : m_module(module), m_name(name) {}
- void
- Dump(Stream &strm) const;
+ void Dump(Stream &strm) const;
- const RSModuleDescriptor *m_module;
- ConstString m_name;
+ const RSModuleDescriptor *m_module;
+ ConstString m_name;
};
-class RSModuleDescriptor
-{
+class RSModuleDescriptor {
public:
- RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {}
+ RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {}
- ~RSModuleDescriptor() = default;
+ ~RSModuleDescriptor() = default;
- bool
- ParseRSInfo();
+ bool ParseRSInfo();
- void
- Dump(Stream &strm) const;
+ void Dump(Stream &strm) const;
- const lldb::ModuleSP m_module;
- std::vector<RSKernelDescriptor> m_kernels;
- std::vector<RSGlobalDescriptor> m_globals;
- std::map<std::string, std::string> m_pragmas;
- std::string m_resname;
+ const lldb::ModuleSP m_module;
+ std::vector<RSKernelDescriptor> m_kernels;
+ std::vector<RSGlobalDescriptor> m_globals;
+ std::map<std::string, std::string> m_pragmas;
+ std::string m_resname;
};
} // namespace lldb_renderscript
-class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
-{
+class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime {
public:
- enum ModuleKind
- {
- eModuleKindIgnored,
- eModuleKindLibRS,
- eModuleKindDriver,
- eModuleKindImpl,
- eModuleKindKernelObj
- };
+ enum ModuleKind {
+ eModuleKindIgnored,
+ eModuleKindLibRS,
+ eModuleKindDriver,
+ eModuleKindImpl,
+ eModuleKindKernelObj
+ };
- ~RenderScriptRuntime() override;
+ ~RenderScriptRuntime() override;
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void
- Initialize();
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
- static void
- Terminate();
+ static void Terminate();
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
- static lldb::CommandObjectSP
- GetCommandObject(CommandInterpreter &interpreter);
+ static lldb::CommandObjectSP
+ GetCommandObject(CommandInterpreter &interpreter);
- static lldb_private::ConstString
- GetPluginNameStatic();
+ static lldb_private::ConstString GetPluginNameStatic();
- static bool
- IsRenderScriptModule(const lldb::ModuleSP &module_sp);
+ static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp);
- static ModuleKind
- GetModuleKind(const lldb::ModuleSP &module_sp);
+ static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp);
- static void
- ModulesDidLoad(const lldb::ProcessSP &process_sp, const ModuleList &module_list);
+ static void ModulesDidLoad(const lldb::ProcessSP &process_sp,
+ const ModuleList &module_list);
- bool
- IsVTableName(const char *name) override;
+ bool IsVTableName(const char *name) override;
- bool
- GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address,
- Value::ValueType &value_type) override;
+ bool GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- TypeAndOrName
- FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
+ ValueObject &static_value) override;
- bool
- CouldHaveDynamicValue(ValueObject &in_value) override;
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- lldb::BreakpointResolverSP
- CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
+ bool catch_bp,
+ bool throw_bp) override;
- bool
- LoadModule(const lldb::ModuleSP &module_sp);
+ bool LoadModule(const lldb::ModuleSP &module_sp);
- void
- DumpModules(Stream &strm) const;
+ void DumpModules(Stream &strm) const;
- void
- DumpContexts(Stream &strm) const;
+ void DumpContexts(Stream &strm) const;
- void
- DumpKernels(Stream &strm) const;
+ void DumpKernels(Stream &strm) const;
- bool
- DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id);
+ bool DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id);
- void
- ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index);
+ void ListAllocations(Stream &strm, StackFrame *frame_ptr,
+ const uint32_t index);
- bool
- RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr);
+ bool RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr);
- void
- PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int, 3> coords, Error &error,
- lldb::TargetSP target);
+ void PlaceBreakpointOnKernel(Stream &strm, const char *name,
+ const std::array<int, 3> coords, Error &error,
+ lldb::TargetSP target);
- void
- SetBreakAllKernels(bool do_break, lldb::TargetSP target);
+ void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
- void
- Status(Stream &strm) const;
+ void Status(Stream &strm) const;
- void
- ModulesDidLoad(const ModuleList &module_list) override;
+ void ModulesDidLoad(const ModuleList &module_list) override;
- bool
- LoadAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr);
+ bool LoadAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename, StackFrame *frame_ptr);
- bool
- SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr);
+ bool SaveAllocation(Stream &strm, const uint32_t alloc_id,
+ const char *filename, StackFrame *frame_ptr);
- void
- Update();
+ void Update();
- void
- Initiate();
+ void Initiate();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString
- GetPluginName() override;
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
- uint32_t
- GetPluginVersion() override;
+ uint32_t GetPluginVersion() override;
- static bool
- GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord, Thread *thread_ptr);
+ static bool GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord,
+ Thread *thread_ptr);
protected:
- struct ScriptDetails;
- struct AllocationDetails;
- struct Element;
+ struct ScriptDetails;
+ struct AllocationDetails;
+ struct Element;
- void
- InitSearchFilter(lldb::TargetSP target)
- {
- if (!m_filtersp)
- m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
- }
+ void InitSearchFilter(lldb::TargetSP target) {
+ if (!m_filtersp)
+ m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
+ }
- void
- FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
+ void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
- void
- LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+ void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
- bool
- RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result);
+ bool EvalRSExpression(const char *expression, StackFrame *frame_ptr,
+ uint64_t *result);
- lldb::BreakpointSP
- CreateKernelBreakpoint(const ConstString &name);
+ lldb::BreakpointSP CreateKernelBreakpoint(const ConstString &name);
- void
- BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
+ void BreakOnModuleKernels(
+ const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
- struct RuntimeHook;
- typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook *hook_info,
- ExecutionContext &context); // Please do this!
+ struct RuntimeHook;
+ typedef void (RenderScriptRuntime::*CaptureStateFn)(
+ RuntimeHook *hook_info,
+ ExecutionContext &context); // Please do this!
- struct HookDefn
- {
- const char *name;
- const char *symbol_name_m32; // mangled name for the 32 bit architectures
- const char *symbol_name_m64; // mangled name for the 64 bit archs
- uint32_t version;
- ModuleKind kind;
- CaptureStateFn grabber;
- };
+ struct HookDefn {
+ const char *name;
+ const char *symbol_name_m32; // mangled name for the 32 bit architectures
+ const char *symbol_name_m64; // mangled name for the 64 bit archs
+ uint32_t version;
+ ModuleKind kind;
+ CaptureStateFn grabber;
+ };
- struct RuntimeHook
- {
- lldb::addr_t address;
- const HookDefn *defn;
- lldb::BreakpointSP bp_sp;
- };
+ struct RuntimeHook {
+ lldb::addr_t address;
+ const HookDefn *defn;
+ lldb::BreakpointSP bp_sp;
+ };
- typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
+ typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
- lldb::ModuleSP m_libRS;
- lldb::ModuleSP m_libRSDriver;
- lldb::ModuleSP m_libRSCpuRef;
- std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
+ lldb::ModuleSP m_libRS;
+ lldb::ModuleSP m_libRSDriver;
+ lldb::ModuleSP m_libRSCpuRef;
+ std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
- std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
- std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
+ std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
+ std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
- std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
- std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
- std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks;
+ std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP>
+ m_scriptMappings;
+ std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
+ std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks;
- lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
+ lldb::SearchFilterSP
+ m_filtersp; // Needed to create breakpoints through Target API
- bool m_initiated;
- bool m_debuggerPresentFlagged;
- bool m_breakAllKernels;
- static const HookDefn s_runtimeHookDefns[];
- static const size_t s_runtimeHookCount;
- LLVMUserExpression::IRPasses *m_ir_passes;
+ bool m_initiated;
+ bool m_debuggerPresentFlagged;
+ bool m_breakAllKernels;
+ static const HookDefn s_runtimeHookDefns[];
+ static const size_t s_runtimeHookCount;
+ LLVMUserExpression::IRPasses *m_ir_passes;
private:
- RenderScriptRuntime(Process *process); // Call CreateInstance instead.
+ RenderScriptRuntime(Process *process); // Call CreateInstance instead.
- static bool
- HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+ static bool HookCallback(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
- static bool
- KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
+ static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
- void
- HookCallback(RuntimeHook *hook_info, ExecutionContext &context);
+ void HookCallback(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureAllocationDestroy(RuntimeHook *hook_info,
+ ExecutionContext &context);
- void
- CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context);
- void
- CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info, ExecutionContext &context);
+ void CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info,
+ ExecutionContext &context);
- AllocationDetails *
- FindAllocByID(Stream &strm, const uint32_t alloc_id);
+ AllocationDetails *FindAllocByID(Stream &strm, const uint32_t alloc_id);
- std::shared_ptr<uint8_t>
- GetAllocationData(AllocationDetails *allocation, StackFrame *frame_ptr);
+ std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails *allocation,
+ StackFrame *frame_ptr);
- void
- SetElementSize(Element &elem);
+ void SetElementSize(Element &elem);
- static bool
- GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char *var_name, uint64_t &val);
+ static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP,
+ const char *var_name, uint64_t &val);
- void
- FindStructTypeName(Element &elem, StackFrame *frame_ptr);
+ void FindStructTypeName(Element &elem, StackFrame *frame_ptr);
- size_t
- PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element &elem);
+ size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer,
+ size_t offset, const Element &elem);
- size_t
- CalculateElementHeaderSize(const Element &elem);
+ size_t CalculateElementHeaderSize(const Element &elem);
- //
- // Helper functions for jitting the runtime
- //
+ //
+ // Helper functions for jitting the runtime
+ //
- bool
- JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr,
- uint32_t x = 0, uint32_t y = 0, uint32_t z = 0);
+ bool JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr,
+ uint32_t x = 0, uint32_t y = 0, uint32_t z = 0);
- bool
- JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr);
+ bool JITElementPacked(Element &elem, const lldb::addr_t context,
+ StackFrame *frame_ptr);
- bool
- JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr);
- bool
- JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr);
+ bool JITSubelements(Element &elem, const lldb::addr_t context,
+ StackFrame *frame_ptr);
- bool
- JITAllocationStride(AllocationDetails *allocation, StackFrame *frame_ptr);
+ bool JITAllocationStride(AllocationDetails *allocation,
+ StackFrame *frame_ptr);
- // Search for a script detail object using a target address.
- // If a script does not currently exist this function will return nullptr.
- // If 'create' is true and there is no previous script with this address,
- // then a new Script detail object will be created for this address and returned.
- ScriptDetails *
- LookUpScript(lldb::addr_t address, bool create);
+ // Search for a script detail object using a target address.
+ // If a script does not currently exist this function will return nullptr.
+ // If 'create' is true and there is no previous script with this address,
+ // then a new Script detail object will be created for this address and
+ // returned.
+ ScriptDetails *LookUpScript(lldb::addr_t address, bool create);
- // Search for a previously saved allocation detail object using a target address.
- // If an allocation does not exist for this address then nullptr will be returned.
- AllocationDetails *
- LookUpAllocation(lldb::addr_t address);
+ // Search for a previously saved allocation detail object using a target
+ // address.
+ // If an allocation does not exist for this address then nullptr will be
+ // returned.
+ AllocationDetails *LookUpAllocation(lldb::addr_t address);
- // Creates a new allocation with the specified address assigning a new ID and removes
- // any previous stored allocation which has the same address.
- AllocationDetails *
- CreateAllocation(lldb::addr_t address);
+ // Creates a new allocation with the specified address assigning a new ID and
+ // removes
+ // any previous stored allocation which has the same address.
+ AllocationDetails *CreateAllocation(lldb::addr_t address);
- bool
- GetOverrideExprOptions(clang::TargetOptions &prototype) override;
+ bool GetOverrideExprOptions(clang::TargetOptions &prototype) override;
- bool
- GetIRPasses(LLVMUserExpression::IRPasses &passes) override;
+ bool GetIRPasses(LLVMUserExpression::IRPasses &passes) override;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index 9802263..354d5d6 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -28,258 +28,271 @@
#include "lldb/Target/Process.h"
using namespace lldb_private;
-namespace
-{
+namespace {
-bool
-isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst)
-{
- // TODO get the list of renderscript modules from lldb and check if
- // this llvm::Module calls into any of them.
- (void)module;
- const auto func_name = call_inst->getCalledFunction()->getName();
- if (func_name.startswith("llvm") || func_name.startswith("lldb"))
- return false;
-
- if (call_inst->getCalledFunction()->isIntrinsic())
- return false;
-
- return true;
-}
-
-bool
-isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst)
-{
- // i686 and x86_64 returns for large vectors in the RenderScript API are not handled as normal
- // register pairs, but as a hidden sret type. This is not reflected in the debug info or mangled
- // symbol name, and the android ABI for x86 and x86_64, (as well as the emulators) specifies there is
- // no AVX, so bcc generates an sret function because we cannot natively return 256 bit vectors.
- // This function simply checks whether a function has a > 128bit return type. It is perhaps an
- // unreliable heuristic, and relies on bcc not generating AVX code, so if the android ABI one day
- // provides for AVX, this function may go out of fashion.
- (void)module;
- if (!call_inst || !call_inst->getCalledFunction())
- return false;
-
- return call_inst->getCalledFunction()->getReturnType()->getPrimitiveSizeInBits() > 128;
-}
-
-bool
-isRSAllocationPtrTy(const llvm::Type *type)
-{
- if (!type->isPointerTy())
- return false;
- auto ptr_type = type->getPointerElementType();
-
- return ptr_type->isStructTy() && ptr_type->getStructName().startswith("struct.rs_allocation");
-}
-
-bool
-isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst)
-{
- (void)module;
- if (!call_inst->hasByValArgument())
- return false;
- for (const auto ¶m : call_inst->operand_values())
- if (isRSAllocationPtrTy(param->getType()))
- return true;
+bool isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst) {
+ // TODO get the list of renderscript modules from lldb and check if
+ // this llvm::Module calls into any of them.
+ (void)module;
+ const auto func_name = call_inst->getCalledFunction()->getName();
+ if (func_name.startswith("llvm") || func_name.startswith("lldb"))
return false;
+
+ if (call_inst->getCalledFunction()->isIntrinsic())
+ return false;
+
+ return true;
}
-llvm::FunctionType *
-cloneToStructRetFnTy(llvm::CallInst *call_inst)
-{
- // on x86 StructReturn functions return a pointer to the return value, rather than the return
- // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf section 6).
- // We create a return type by getting the pointer type of the old return type, and inserting a new
- // initial argument of pointer type of the original return type.
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
+bool isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst) {
+ // i686 and x86_64 returns for large vectors in the RenderScript API are not
+ // handled as normal
+ // register pairs, but as a hidden sret type. This is not reflected in the
+ // debug info or mangled
+ // symbol name, and the android ABI for x86 and x86_64, (as well as the
+ // emulators) specifies there is
+ // no AVX, so bcc generates an sret function because we cannot natively return
+ // 256 bit vectors.
+ // This function simply checks whether a function has a > 128bit return type.
+ // It is perhaps an
+ // unreliable heuristic, and relies on bcc not generating AVX code, so if the
+ // android ABI one day
+ // provides for AVX, this function may go out of fashion.
+ (void)module;
+ if (!call_inst || !call_inst->getCalledFunction())
+ return false;
- assert(call_inst && "no CallInst");
- llvm::Function *orig = call_inst->getCalledFunction();
- assert(orig && "CallInst has no called function");
- llvm::FunctionType *orig_type = orig->getFunctionType();
- auto name = orig->getName();
- if (log)
- log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__, name.str().c_str());
-
- unsigned num_params = orig_type->getNumParams();
- std::vector<llvm::Type *> new_params{num_params + 1, nullptr};
- std::vector<llvm::Type *> params{orig_type->param_begin(), orig_type->param_end()};
-
- // This may not work if the function is somehow declared void as llvm is strongly typed
- // and represents void* with i8*
- assert(!orig_type->getReturnType()->isVoidTy() && "Cannot add StructRet attribute to void function");
- llvm::PointerType *return_type_ptr_type = llvm::PointerType::getUnqual(orig->getReturnType());
- assert(return_type_ptr_type && "failed to get function return type PointerType");
- if (!return_type_ptr_type)
- return nullptr;
-
- if (log)
- log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n", __FUNCTION__,
- (void *)return_type_ptr_type);
- // put the the sret pointer argument in place at the beginning of the argument list.
- params.emplace(params.begin(), return_type_ptr_type);
- assert(params.size() == num_params + 1);
- return llvm::FunctionType::get(return_type_ptr_type, params, orig->isVarArg());
+ return call_inst->getCalledFunction()
+ ->getReturnType()
+ ->getPrimitiveSizeInBits() > 128;
}
-bool
-findRSCallSites(llvm::Module &module, std::set<llvm::CallInst *> &rs_callsites,
- bool (*predicate)(llvm::Module &, llvm::CallInst *))
-{
- bool found = false;
+bool isRSAllocationPtrTy(const llvm::Type *type) {
+ if (!type->isPointerTy())
+ return false;
+ auto ptr_type = type->getPointerElementType();
- for (auto &func : module.getFunctionList())
- for (auto &block : func.getBasicBlockList())
- for (auto &inst : block)
- {
- llvm::CallInst *call_inst = llvm::dyn_cast_or_null<llvm::CallInst>(&inst);
- if (!call_inst || !call_inst->getCalledFunction())
- // This is not the call-site you are looking for...
- continue;
- if (isRSAPICall(module, call_inst) && predicate(module, call_inst))
- {
- rs_callsites.insert(call_inst);
- found = true;
- }
- }
- return found;
+ return ptr_type->isStructTy() &&
+ ptr_type->getStructName().startswith("struct.rs_allocation");
}
-bool
-fixupX86StructRetCalls(llvm::Module &module)
-{
- bool changed = false;
- // changing a basic block while iterating over it seems to have some undefined behaviour
- // going on so we find all RS callsites first, then fix them up after consuming
- // the iterator.
- std::set<llvm::CallInst *> rs_callsites;
- if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
- return false;
+bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
+ (void)module;
+ if (!call_inst->hasByValArgument())
+ return false;
+ for (const auto ¶m : call_inst->operand_values())
+ if (isRSAllocationPtrTy(param->getType()))
+ return true;
+ return false;
+}
- for (auto call_inst : rs_callsites)
- {
- llvm::FunctionType *new_func_type = cloneToStructRetFnTy(call_inst);
- assert(new_func_type && "failed to clone functionType for Renderscript ABI fixup");
+llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
+ // on x86 StructReturn functions return a pointer to the return value, rather
+ // than the return
+ // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf
+ // section 6).
+ // We create a return type by getting the pointer type of the old return type,
+ // and inserting a new
+ // initial argument of pointer type of the original return type.
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
- llvm::CallSite call_site(call_inst);
- llvm::Function *func = call_inst->getCalledFunction();
- assert(func && "cannot resolve function in RenderScriptRuntime");
- // Copy the original call arguments
- std::vector<llvm::Value *> new_call_args(call_site.arg_begin(), call_site.arg_end());
+ assert(call_inst && "no CallInst");
+ llvm::Function *orig = call_inst->getCalledFunction();
+ assert(orig && "CallInst has no called function");
+ llvm::FunctionType *orig_type = orig->getFunctionType();
+ auto name = orig->getName();
+ if (log)
+ log->Printf("%s - cloning to StructRet function for '%s'", __FUNCTION__,
+ name.str().c_str());
- // Allocate enough space to store the return value of the original function
- // we pass a pointer to this allocation as the StructRet param, and then copy its
- // value into the lldb return value
- llvm::AllocaInst *return_value_alloc =
- new llvm::AllocaInst(func->getReturnType(), "var_vector_return_alloc", call_inst);
- // use the new allocation as the new first argument
- new_call_args.emplace(new_call_args.begin(), llvm::cast<llvm::Value>(return_value_alloc));
- llvm::PointerType *new_func_ptr_type = llvm::PointerType::get(new_func_type, 0);
- // Create the type cast from the old function type to the new one
- llvm::Constant *new_func_cast =
- llvm::ConstantExpr::getCast(llvm::Instruction::BitCast, func, new_func_ptr_type);
- // create an allocation for a new function pointer
- llvm::AllocaInst *new_func_ptr = new llvm::AllocaInst(new_func_ptr_type, "new_func_ptr", call_inst);
- // store the new_func_cast to the newly allocated space
- (void)new llvm::StoreInst(new_func_cast, new_func_ptr, "new_func_ptr_load_cast", call_inst);
- // load the new function address ready for a jump
- llvm::LoadInst *new_func_addr_load = new llvm::LoadInst(new_func_ptr, "load_func_pointer", call_inst);
- // and create a callinstruction from it
- llvm::CallInst *new_call_inst =
- llvm::CallInst::Create(new_func_addr_load, new_call_args, "new_func_call", call_inst);
- new_call_inst->setCallingConv(call_inst->getCallingConv());
- new_call_inst->setTailCall(call_inst->isTailCall());
- llvm::LoadInst *lldb_save_result_address = new llvm::LoadInst(return_value_alloc, "save_return_val", call_inst);
+ unsigned num_params = orig_type->getNumParams();
+ std::vector<llvm::Type *> new_params{num_params + 1, nullptr};
+ std::vector<llvm::Type *> params{orig_type->param_begin(),
+ orig_type->param_end()};
- // Now remove the old broken call
- call_inst->replaceAllUsesWith(lldb_save_result_address);
- call_inst->eraseFromParent();
+ // This may not work if the function is somehow declared void as llvm is
+ // strongly typed
+ // and represents void* with i8*
+ assert(!orig_type->getReturnType()->isVoidTy() &&
+ "Cannot add StructRet attribute to void function");
+ llvm::PointerType *return_type_ptr_type =
+ llvm::PointerType::getUnqual(orig->getReturnType());
+ assert(return_type_ptr_type &&
+ "failed to get function return type PointerType");
+ if (!return_type_ptr_type)
+ return nullptr;
+
+ if (log)
+ log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n",
+ __FUNCTION__, (void *)return_type_ptr_type);
+ // put the the sret pointer argument in place at the beginning of the argument
+ // list.
+ params.emplace(params.begin(), return_type_ptr_type);
+ assert(params.size() == num_params + 1);
+ return llvm::FunctionType::get(return_type_ptr_type, params,
+ orig->isVarArg());
+}
+
+bool findRSCallSites(llvm::Module &module,
+ std::set<llvm::CallInst *> &rs_callsites,
+ bool (*predicate)(llvm::Module &, llvm::CallInst *)) {
+ bool found = false;
+
+ for (auto &func : module.getFunctionList())
+ for (auto &block : func.getBasicBlockList())
+ for (auto &inst : block) {
+ llvm::CallInst *call_inst =
+ llvm::dyn_cast_or_null<llvm::CallInst>(&inst);
+ if (!call_inst || !call_inst->getCalledFunction())
+ // This is not the call-site you are looking for...
+ continue;
+ if (isRSAPICall(module, call_inst) && predicate(module, call_inst)) {
+ rs_callsites.insert(call_inst);
+ found = true;
+ }
+ }
+ return found;
+}
+
+bool fixupX86StructRetCalls(llvm::Module &module) {
+ bool changed = false;
+ // changing a basic block while iterating over it seems to have some undefined
+ // behaviour
+ // going on so we find all RS callsites first, then fix them up after
+ // consuming
+ // the iterator.
+ std::set<llvm::CallInst *> rs_callsites;
+ if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
+ return false;
+
+ for (auto call_inst : rs_callsites) {
+ llvm::FunctionType *new_func_type = cloneToStructRetFnTy(call_inst);
+ assert(new_func_type &&
+ "failed to clone functionType for Renderscript ABI fixup");
+
+ llvm::CallSite call_site(call_inst);
+ llvm::Function *func = call_inst->getCalledFunction();
+ assert(func && "cannot resolve function in RenderScriptRuntime");
+ // Copy the original call arguments
+ std::vector<llvm::Value *> new_call_args(call_site.arg_begin(),
+ call_site.arg_end());
+
+ // Allocate enough space to store the return value of the original function
+ // we pass a pointer to this allocation as the StructRet param, and then
+ // copy its
+ // value into the lldb return value
+ llvm::AllocaInst *return_value_alloc = new llvm::AllocaInst(
+ func->getReturnType(), "var_vector_return_alloc", call_inst);
+ // use the new allocation as the new first argument
+ new_call_args.emplace(new_call_args.begin(),
+ llvm::cast<llvm::Value>(return_value_alloc));
+ llvm::PointerType *new_func_ptr_type =
+ llvm::PointerType::get(new_func_type, 0);
+ // Create the type cast from the old function type to the new one
+ llvm::Constant *new_func_cast = llvm::ConstantExpr::getCast(
+ llvm::Instruction::BitCast, func, new_func_ptr_type);
+ // create an allocation for a new function pointer
+ llvm::AllocaInst *new_func_ptr =
+ new llvm::AllocaInst(new_func_ptr_type, "new_func_ptr", call_inst);
+ // store the new_func_cast to the newly allocated space
+ (void)new llvm::StoreInst(new_func_cast, new_func_ptr,
+ "new_func_ptr_load_cast", call_inst);
+ // load the new function address ready for a jump
+ llvm::LoadInst *new_func_addr_load =
+ new llvm::LoadInst(new_func_ptr, "load_func_pointer", call_inst);
+ // and create a callinstruction from it
+ llvm::CallInst *new_call_inst = llvm::CallInst::Create(
+ new_func_addr_load, new_call_args, "new_func_call", call_inst);
+ new_call_inst->setCallingConv(call_inst->getCallingConv());
+ new_call_inst->setTailCall(call_inst->isTailCall());
+ llvm::LoadInst *lldb_save_result_address =
+ new llvm::LoadInst(return_value_alloc, "save_return_val", call_inst);
+
+ // Now remove the old broken call
+ call_inst->replaceAllUsesWith(lldb_save_result_address);
+ call_inst->eraseFromParent();
+ changed = true;
+ }
+ return changed;
+}
+
+bool fixupRSAllocationStructByValCalls(llvm::Module &module) {
+ // On x86_64, calls to functions in the RS runtime that take an
+ // `rs_allocation` type argument
+ // are actually handled as by-ref params by bcc, but appear to be passed by
+ // value by lldb (the callsite all use
+ // `struct byval`).
+ // On x86_64 Linux, struct arguments are transferred in registers if the
+ // struct size is no bigger than
+ // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf)
+ // section 7.1 "Passing and returning objects"
+ // otherwise passed on the stack.
+ // an object of type `rs_allocation` is actually 256bits, so should be passed
+ // on the stack. However, code generated
+ // by bcc actually treats formal params of type `rs_allocation` as
+ // `rs_allocation *` so we need to convert the
+ // calling convention to pass by reference, and remove any hint of byval from
+ // formal parameters.
+ bool changed = false;
+ std::set<llvm::CallInst *> rs_callsites;
+ if (!findRSCallSites(module, rs_callsites, isRSAllocationTyCallSite))
+ return false;
+
+ std::set<llvm::Function *> rs_functions;
+
+ // for all call instructions
+ for (auto call_inst : rs_callsites) {
+ // add the called function to a set so that we can strip its byval
+ // attributes in another pass
+ rs_functions.insert(call_inst->getCalledFunction());
+
+ // get the function attributes
+ llvm::AttributeSet call_attribs = call_inst->getAttributes();
+
+ // iterate over the argument attributes
+ for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i) {
+ // if this argument is passed by val
+ if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal)) {
+ // strip away the byval attribute
+ call_inst->removeAttribute(
+ i,
+ llvm::Attribute::get(module.getContext(), llvm::Attribute::ByVal));
changed = true;
+ }
}
- return changed;
-}
+ }
-bool
-fixupRSAllocationStructByValCalls(llvm::Module &module)
-{
- // On x86_64, calls to functions in the RS runtime that take an `rs_allocation` type argument
- // are actually handled as by-ref params by bcc, but appear to be passed by value by lldb (the callsite all use
- // `struct byval`).
- // On x86_64 Linux, struct arguments are transferred in registers if the struct size is no bigger than
- // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf) section 7.1 "Passing and returning objects"
- // otherwise passed on the stack.
- // an object of type `rs_allocation` is actually 256bits, so should be passed on the stack. However, code generated
- // by bcc actually treats formal params of type `rs_allocation` as `rs_allocation *` so we need to convert the
- // calling convention to pass by reference, and remove any hint of byval from formal parameters.
- bool changed = false;
- std::set<llvm::CallInst *> rs_callsites;
- if (!findRSCallSites(module, rs_callsites, isRSAllocationTyCallSite))
- return false;
+ llvm::AttributeSet attr_byval =
+ llvm::AttributeSet::get(module.getContext(), 1u, llvm::Attribute::ByVal);
- std::set<llvm::Function *> rs_functions;
-
- // for all call instructions
- for (auto call_inst : rs_callsites)
- {
- // add the called function to a set so that we can strip its byval attributes in another pass
- rs_functions.insert(call_inst->getCalledFunction());
-
- // get the function attributes
- llvm::AttributeSet call_attribs = call_inst->getAttributes();
-
- // iterate over the argument attributes
- for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i)
- {
- // if this argument is passed by val
- if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal))
- {
- // strip away the byval attribute
- call_inst->removeAttribute(i, llvm::Attribute::get(module.getContext(), llvm::Attribute::ByVal));
- changed = true;
- }
- }
+ // for all called function decls
+ for (auto func : rs_functions) {
+ // inspect all of the arguments in the call
+ llvm::SymbolTableList<llvm::Argument> &argList = func->getArgumentList();
+ for (auto &arg : argList) {
+ if (arg.hasByValAttr()) {
+ arg.removeAttr(attr_byval);
+ changed = true;
+ }
}
-
- llvm::AttributeSet attr_byval = llvm::AttributeSet::get(module.getContext(), 1u, llvm::Attribute::ByVal);
-
- // for all called function decls
- for (auto func : rs_functions)
- {
- // inspect all of the arguments in the call
- llvm::SymbolTableList<llvm::Argument> &argList = func->getArgumentList();
- for (auto &arg : argList)
- {
- if (arg.hasByValAttr())
- {
- arg.removeAttr(attr_byval);
- changed = true;
- }
- }
- }
- return changed;
+ }
+ return changed;
}
} // end anonymous namespace
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
+namespace lldb_private {
+namespace lldb_renderscript {
-bool
-fixupX86FunctionCalls(llvm::Module &module)
-{
- return fixupX86StructRetCalls(module);
+bool fixupX86FunctionCalls(llvm::Module &module) {
+ return fixupX86StructRetCalls(module);
}
-bool
-fixupX86_64FunctionCalls(llvm::Module &module)
-{
- bool changed = false;
- changed |= fixupX86StructRetCalls(module);
- changed |= fixupRSAllocationStructByValCalls(module);
- return changed;
+bool fixupX86_64FunctionCalls(llvm::Module &module) {
+ bool changed = false;
+ changed |= fixupX86StructRetCalls(module);
+ changed |= fixupRSAllocationStructByValCalls(module);
+ return changed;
}
} // end namespace lldb_renderscript
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h
index d6cf965..9fd1026 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.h
@@ -12,16 +12,12 @@
#include "llvm/IR/Module.h"
-namespace lldb_private
-{
-namespace lldb_renderscript
-{
+namespace lldb_private {
+namespace lldb_renderscript {
-bool
-fixupX86FunctionCalls(llvm::Module &module);
+bool fixupX86FunctionCalls(llvm::Module &module);
-bool
-fixupX86_64FunctionCalls(llvm::Module &module);
+bool fixupX86_64FunctionCalls(llvm::Module &module);
}
}
#endif