// this code relies on the assumption that an Objective-C object always starts // with an ISA at offset 0. ObjCLanguageRuntime::ObjCISA AppleObjCRuntimeV1::GetISA(ValueObject& valobj) { if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != eLanguageTypeObjC) return 0; // 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.GetValue().GetContextType() == Value::eContextTypeInvalid) return 0; addr_t isa_pointer = valobj.GetPointerValue(); ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); Process *process = exe_ctx.GetProcessPtr(); if (process) { uint8_t pointer_size = process->GetAddressByteSize(); Error error; return process->ReadUnsignedIntegerFromMemory (isa_pointer, pointer_size, 0, error); } return 0; }
bool lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream) { DataExtractor data; valobj.GetData(data); clang::ASTContext* ast = valobj.GetClangAST(); if (!ast) return false; std::string value; uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType()); switch (wchar_size) { case 8: // utf 8 valobj.GetValueAsCString(lldb::eFormatChar, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); return DumpUTFBufferToStream<UTF8>(nullptr, data, stream, 'L', '\'', 1); case 16: // utf 16 valobj.GetValueAsCString(lldb::eFormatUnicode16, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); return DumpUTFBufferToStream<UTF16>(ConvertUTF16toUTF8, data, stream, 'L', '\'', 1); case 32: // utf 32 valobj.GetValueAsCString(lldb::eFormatUnicode32, value); if (!value.empty()) stream.Printf("%s ", value.c_str()); return DumpUTFBufferToStream<UTF32>(ConvertUTF32toUTF8, data, stream, 'L', '\'', 1); default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }
bool lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; lldb::addr_t data_addr = 0; if (valobj.IsPointerType()) data_addr = valobj.GetValueAsUnsigned(0); else if (valobj.IsArrayType()) data_addr = valobj.GetAddressOf(); if (data_addr == 0 || data_addr == LLDB_INVALID_ADDRESS) return false; clang::ASTContext* ast = valobj.GetClangAST(); if (!ast) return false; uint32_t wchar_size = ClangASTType::GetClangTypeBitWidth(ast, ClangASTType::GetBasicType(ast, lldb::eBasicTypeWChar).GetOpaqueQualType()); switch (wchar_size) { case 8: { // utf 8 ReadUTFBufferAndDumpToStreamOptions<UTF8> options; options.SetLocation(data_addr); options.SetConversionFunction(nullptr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } case 16: { // utf 16 ReadUTFBufferAndDumpToStreamOptions<UTF16> options; options.SetLocation(data_addr); options.SetConversionFunction(ConvertUTF16toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } case 32: { // utf 32 ReadUTFBufferAndDumpToStreamOptions<UTF32> options; options.SetLocation(data_addr); options.SetConversionFunction(ConvertUTF32toUTF8); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetPrefixToken('L'); return ReadUTFBufferAndDumpToStream(options); } default: stream.Printf("size for wchar_t is not valid"); return true; } return true; }
bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &dynamic_address) { // 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. // // Only a pointer or reference type can have a different dynamic and static type: if (CouldHaveDynamicValue (in_value)) { // FIXME: Can we get the Clang Type and ask it if the thing is really virtual? That would avoid false positives, // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong. // 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; Target *target = in_value.GetUpdatePoint().GetTargetSP().get(); Process *process = in_value.GetUpdatePoint().GetProcessSP().get(); char memory_buffer[16]; DataExtractor data(memory_buffer, sizeof(memory_buffer), process->GetByteOrder(), process->GetAddressByteSize()); size_t address_byte_size = process->GetAddressByteSize(); Error error; size_t bytes_read = process->ReadMemory (original_ptr, memory_buffer, address_byte_size, error); if (!error.Success() || (bytes_read != address_byte_size)) { return false; } uint32_t offset_ptr = 0; lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr); if (offset_ptr == 0) return false; // Now find the symbol that contains this address: SymbolContext sc; Address address_point_address; if (target && !target->GetSectionLoadList().IsEmpty()) { if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address)) { target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc); Symbol *symbol = sc.symbol; if (symbol != NULL) { const char *name = symbol->GetMangled().GetDemangledName().AsCString(); if (strstr(name, vtable_demangled_prefix) == 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); class_type_or_name.SetName (class_name); TypeList class_types; uint32_t num_matches = target->GetImages().FindTypes (sc, ConstString(class_name), true, UINT32_MAX, class_types); if (num_matches == 1) { class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); } else if (num_matches > 1) { for (size_t i = 0; i < num_matches; i++) { lldb::TypeSP this_type(class_types.GetTypeAtIndex(i)); if (this_type) { if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType())) { // 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: clang::ASTContext *in_ast_ctx = in_value.GetClangAST (); clang::ASTContext *this_ast_ctx = this_type->GetClangAST (); if (in_ast_ctx != this_ast_ctx || !ClangASTContext::AreTypesSame (in_ast_ctx, in_value.GetClangType(), this_type->GetClangFullType())) { class_type_or_name.SetTypeSP (this_type); return true; } return false; } } } } else return false; // The offset_to_top is two pointers above the address. Address offset_to_top_address = address_point_address; int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); offset_to_top_address.Slide (slide); Error error; lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); size_t bytes_read = process->ReadMemory (offset_to_top_location, memory_buffer, address_byte_size, error); if (!error.Success() || (bytes_read != address_byte_size)) { return false; } offset_ptr = 0; int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize()); // 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 (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) { dynamic_address.SetOffset(dynamic_addr); dynamic_address.SetSection(NULL); } return true; } } } } } return false; }