Exemple #1
0
bool
lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    TargetSP target_sp(valobj.GetTargetSP());
    if (!target_sp)
        return false;
    uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
    uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
    if (!pointer_value)
        return false;
    pointer_value += addr_size;
    CompilerType type(valobj.GetCompilerType());
    ExecutionContext exe_ctx(target_sp,false);
    ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
    if (!child_ptr_sp)
        return false;
    DataExtractor data;
    Error error;
    child_ptr_sp->GetData(data, error);
    if (error.Fail())
        return false;
    ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
    child_sp->GetValueAsUnsigned(0);
    if (child_sp)
        return NSStringSummaryProvider(*child_sp, stream, options);
    return false;
}
Exemple #2
0
bool OCamlLanguage::IsNilReference(ValueObject &valobj) {
  if (!valobj.GetCompilerType().IsReferenceType())
    return false;

  // If we failed to read the value then it is not a nil reference.
  return valobj.GetValueAsUnsigned(UINT64_MAX) == 0;
}
bool ItaniumABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
  const bool check_cxx = true;
  const bool check_objc = false;
  const bool check_swift = false;
  return in_value.GetCompilerType().IsPossibleDynamicType(
      NULL, check_cxx, check_objc, check_swift);
}
Exemple #4
0
bool
lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
    
    ValueObjectSP real_guy_sp = valobj.GetSP();
    
    if (type_info & eTypeIsPointer)
    {
        Error err;
        real_guy_sp = valobj.Dereference(err);
        if (err.Fail() || !real_guy_sp)
            return false;
    }
    else if (type_info & eTypeIsReference)
    {
        real_guy_sp =  valobj.GetChildAtIndex(0, true);
        if (!real_guy_sp)
            return false;
    }
    uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
    if (value == 0)
    {
        stream.Printf("NO");
        return true;
    }
    stream.Printf("YES");
    return true;
}
Exemple #5
0
bool
lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    lldb::ValueObjectSP valobj_sp;
    
    CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
    
    if (!charstar)
        return false;
    
    ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
    
    if (is_sel_ptr)
    {
        lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
        if (data_address == LLDB_INVALID_ADDRESS)
            return false;
        valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
    }
    else
    {
        DataExtractor data;
        Error error;
        valobj.GetData(data, error);
        if (error.Fail())
            return false;
        valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
    }
    
    if (!valobj_sp)
        return false;
    
    stream.Printf("%s",valobj_sp->GetSummaryAsCString());
    return true;
}
bool
AppleObjCRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
    return in_value.GetCompilerType().IsPossibleDynamicType (NULL,
                                                          false, // do not check C++
                                                          true); // check ObjC
}
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;
}
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
lldb_private::formatters::swift::SwiftMetatype_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    lldb::addr_t metadata_ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    if (metadata_ptr == LLDB_INVALID_ADDRESS || metadata_ptr == 0)
    {
        CompilerType compiler_metatype_type(valobj.GetCompilerType());
        CompilerType instancetype(compiler_metatype_type.GetInstanceType());
        const char* ptr = instancetype.GetDisplayTypeName().AsCString(nullptr);
        if (ptr && *ptr)
        {
            stream.Printf("%s", ptr);
            return true;
        }
    }
    else
    {
        auto swift_runtime = valobj.GetProcessSP()->GetSwiftLanguageRuntime();
        if (!swift_runtime)
            return false;
        SwiftLanguageRuntime::MetadataPromiseSP metadata_promise_sp = swift_runtime->GetMetadataPromise(metadata_ptr);
        if (CompilerType resolved_type = metadata_promise_sp->FulfillTypePromise())
        {
            stream.Printf("%s", resolved_type.GetDisplayTypeName().AsCString());
            return true;
        }
    }
    return false;
}
bool
lldb_private::formatters::swift::SwiftOptionalSummaryProvider::DoesPrintChildren (ValueObject* target_valobj) const
{
    if (!target_valobj)
        return false;

    ValueObject *some = ExtractSomeIfAny(target_valobj,target_valobj->GetDynamicValueType(),true);

    if (!some)
        return true;

    lldb_private::Flags some_flags(some->GetCompilerType().GetTypeInfo());

    if (some_flags.AllSet(eTypeIsSwift | eTypeInstanceIsPointer))
        return true;

    lldb::TypeSummaryImplSP summary_sp = some->GetSummaryFormat();

    if (!summary_sp)
    {
        if (lldb_private::DataVisualization::ShouldPrintAsOneLiner(*some))
            return false;
        else
            return (some->GetNumChildren() > 0);
    }
    else
        return (some->GetNumChildren() > 0) && (summary_sp->DoesPrintChildren(some));
}
std::vector<ConstString>
ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
{
    std::vector<ConstString> result;
    
    if (use_dynamic == lldb::eNoDynamicValues)
        return result;
    
    CompilerType compiler_type(valobj.GetCompilerType());
    
    const bool check_cpp = false;
    const bool check_objc = true;
    bool canBeObjCDynamic = compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
    
    if (canBeObjCDynamic)
    {
        do {
            lldb::ProcessSP process_sp = valobj.GetProcessSP();
            if (!process_sp)
                break;
            ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
            if (runtime == nullptr)
                break;
            ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
            if (!objc_class_sp)
                break;
            if (ConstString name = objc_class_sp->GetClassName())
                result.push_back(name);
        } while (false);
    }
    
    return result;
}
Exemple #12
0
bool
lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return false;
    
    lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
    
    CompilerType valobj_type(valobj.GetCompilerType());
    Flags type_flags(valobj_type.GetTypeInfo());
    if (type_flags.AllClear(eTypeHasValue))
    {
        if (valobj.IsBaseClass() && valobj.GetParent())
            ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    }
    else
        ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);

    if (ptr_value == LLDB_INVALID_ADDRESS)
        return false;
    size_t ptr_size = process_sp->GetAddressByteSize();
    lldb::addr_t code_location = ptr_value + 2 * ptr_size;
    lldb::addr_t domain_location = ptr_value + 3 * ptr_size;
    
    Error error;
    uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error);
    if (error.Fail())
        return false;
    
    lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error);
    if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS)
        return false;
    
    if (!domain_str_value)
    {
        stream.Printf("domain: nil - code: %" PRIu64, code);
        return true;
    }
    
    InferiorSizedWord isw(domain_str_value, *process_sp);
    
    ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType());
    
    if (!domain_str_sp)
        return false;
    
    StreamString domain_str_summary;
    if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty())
    {
        stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code);
        return true;
    }
    else
    {
        stream.Printf("domain: nil - code: %" PRIu64, code);
        return true;
    }
}
BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj)
    : SyntheticChildrenFrontEnd(valobj) {
  m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool);
  if (auto target_sp = m_backend.GetTargetSP()) {
    m_byte_order = target_sp->GetArchitecture().GetByteOrder();
    m_byte_size = target_sp->GetArchitecture().GetAddressByteSize();
    Update();
  }
}
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;
        }
    }
    return false;
}
bool
ObjCLanguage::IsNilReference (ValueObject& valobj)
{
    const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
    bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
    if (!isObjCpointer)
        return false;
    bool canReadValue = true;
    bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0;
    return canReadValue && isZero;
}
TypeAndOrName
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;
}
Exemple #17
0
bool
lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"NSBundle"))
    {
        uint64_t offset = 5 * ptr_size;
        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));

        StreamString summary_stream;
        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
        if (was_nsstring_ok && summary_stream.GetSize() > 0)
        {
            stream.Printf("%s",summary_stream.GetData());
            return true;
        }
    }
    // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
    // which is encoded differently and needs to be handled by running code
    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream);
}
bool lldb_private::formatters::JavaArraySummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
  if (valobj.IsPointerOrReferenceType()) {
    Error error;
    ValueObjectSP deref = valobj.Dereference(error);
    if (error.Fail())
      return false;
    return JavaArraySummaryProvider(*deref, stream, options);
  }

  CompilerType type = valobj.GetCompilerType();
  uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
  if (size == UINT32_MAX)
    return false;
  stream.Printf("[%u]{...}", size);
  return true;
}
Exemple #19
0
bool
lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (!strcmp(class_name,"NSBundle"))
    {
        uint64_t offset = 5 * ptr_size;
        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
        
        StreamString summary_stream;
        bool was_nsstring_ok = NSStringSummaryProvider(*text, summary_stream, options);
        if (was_nsstring_ok && summary_stream.GetSize() > 0)
        {
            stream.Printf("%s",summary_stream.GetData());
            return true;
        }
    }
    
    return false;
}
Exemple #20
0
bool
lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
{
    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;

    // Get a wchar_t basic type from the current type system
    CompilerType wchar_clang_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);

    if (!wchar_clang_type)
        return false;

    const uint32_t wchar_size = wchar_clang_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here

    ReadStringAndDumpToStreamOptions options(valobj);
    options.SetLocation(data_addr);
    options.SetProcessSP(process_sp);
    options.SetStream(&stream);
    options.SetPrefixToken('L');
    
    switch (wchar_size)
    {
        case 8:
            return ReadStringAndDumpToStream<StringElementType::UTF8>(options);
        case 16:
            return ReadStringAndDumpToStream<StringElementType::UTF16>(options);
        case 32:
            return ReadStringAndDumpToStream<StringElementType::UTF32>(options);
        default:
            stream.Printf("size for wchar_t is not valid");
            return true;
    }
    return true;
}
Exemple #21
0
bool lldb_private::formatters::WCharSummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
  DataExtractor data;
  Error error;
  valobj.GetData(data, error);

  if (error.Fail())
    return false;

  // Get a wchar_t basic type from the current type system
  CompilerType wchar_compiler_type =
      valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);

  if (!wchar_compiler_type)
    return false;

  const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
      nullptr); // Safe to pass NULL for exe_scope here

  StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
  options.SetData(data);
  options.SetStream(&stream);
  options.SetPrefixToken("L");
  options.SetQuote('\'');
  options.SetSourceSize(1);
  options.SetBinaryZeroIsTerminator(false);

  switch (wchar_size) {
  case 8:
    return StringPrinter::ReadBufferAndDumpToStream<
        StringPrinter::StringElementType::UTF8>(options);
  case 16:
    return StringPrinter::ReadBufferAndDumpToStream<
        StringPrinter::StringElementType::UTF16>(options);
  case 32:
    return StringPrinter::ReadBufferAndDumpToStream<
        StringPrinter::StringElementType::UTF32>(options);
  default:
    stream.Printf("size for wchar_t is not valid");
    return true;
  }
  return true;
}
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;
    
    ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
    return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope());
                   
}
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptor(ValueObject &valobj) {
  ClassDescriptorSP objc_class_sp;
  // 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();
    if (isa_pointer != LLDB_INVALID_ADDRESS) {
      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);
      }
    }
  }
  return objc_class_sp;
}
Exemple #24
0
static lldb::addr_t DerefToNSErrorPointer(ValueObject &valobj) {
  CompilerType valobj_type(valobj.GetCompilerType());
  Flags type_flags(valobj_type.GetTypeInfo());
  if (type_flags.AllClear(eTypeHasValue)) {
    if (valobj.IsBaseClass() && valobj.GetParent())
      return valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
  } else {
    lldb::addr_t ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    if (type_flags.AllSet(eTypeIsPointer)) {
      CompilerType pointee_type(valobj_type.GetPointeeType());
      Flags pointee_flags(pointee_type.GetTypeInfo());
      if (pointee_flags.AllSet(eTypeIsPointer)) {
        if (ProcessSP process_sp = valobj.GetProcessSP()) {
          Status error;
          ptr_value = process_sp->ReadPointerFromMemory(ptr_value, error);
        }
      }
    }
    return ptr_value;
  }

  return LLDB_INVALID_ADDRESS;
}
static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
                          ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp,
                          ValueObjectSP *reserved_sp) {
  ProcessSP process_sp(valobj.GetProcessSP());
  if (!process_sp)
    return false;

  lldb::addr_t ptr = LLDB_INVALID_ADDRESS;

  CompilerType valobj_type(valobj.GetCompilerType());
  Flags type_flags(valobj_type.GetTypeInfo());
  if (type_flags.AllClear(eTypeHasValue)) {
    if (valobj.IsBaseClass() && valobj.GetParent())
      ptr = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
  } else {
    ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
  }

  if (ptr == LLDB_INVALID_ADDRESS)
    return false;
  size_t ptr_size = process_sp->GetAddressByteSize();

  Status error;
  auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error);
  if (error.Fail() || name == LLDB_INVALID_ADDRESS)
    return false;
  auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error);
  if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
    return false;
  auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error);
  if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS)
    return false;
  auto reserved = process_sp->ReadPointerFromMemory(ptr + 4 * ptr_size, error);
  if (error.Fail() || reserved == LLDB_INVALID_ADDRESS)
    return false;

  InferiorSizedWord name_isw(name, *process_sp);
  InferiorSizedWord reason_isw(reason, *process_sp);
  InferiorSizedWord userinfo_isw(userinfo, *process_sp);
  InferiorSizedWord reserved_isw(reserved, *process_sp);

  CompilerType voidstar = process_sp->GetTarget()
                              .GetScratchClangASTContext()
                              ->GetBasicType(lldb::eBasicTypeVoid)
                              .GetPointerType();

  if (name_sp)
    *name_sp = ValueObject::CreateValueObjectFromData(
        "name", name_isw.GetAsData(process_sp->GetByteOrder()),
        valobj.GetExecutionContextRef(), voidstar);
  if (reason_sp)
    *reason_sp = ValueObject::CreateValueObjectFromData(
        "reason", reason_isw.GetAsData(process_sp->GetByteOrder()),
        valobj.GetExecutionContextRef(), voidstar);
  if (userinfo_sp)
    *userinfo_sp = ValueObject::CreateValueObjectFromData(
        "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()),
        valobj.GetExecutionContextRef(), voidstar);
  if (reserved_sp)
    *reserved_sp = ValueObject::CreateValueObjectFromData(
        "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()),
        valobj.GetExecutionContextRef(), voidstar);

  return true;
}
Exemple #26
0
bool lldb_private::formatters::NSException_SummaryProvider(
    ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
  ProcessSP process_sp(valobj.GetProcessSP());
  if (!process_sp)
    return false;

  lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;

  CompilerType valobj_type(valobj.GetCompilerType());
  Flags type_flags(valobj_type.GetTypeInfo());
  if (type_flags.AllClear(eTypeHasValue)) {
    if (valobj.IsBaseClass() && valobj.GetParent())
      ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
  } else
    ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);

  if (ptr_value == LLDB_INVALID_ADDRESS)
    return false;
  size_t ptr_size = process_sp->GetAddressByteSize();
  lldb::addr_t name_location = ptr_value + 1 * ptr_size;
  lldb::addr_t reason_location = ptr_value + 2 * ptr_size;

  Error error;
  lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error);
  if (error.Fail() || name == LLDB_INVALID_ADDRESS)
    return false;

  lldb::addr_t reason =
      process_sp->ReadPointerFromMemory(reason_location, error);
  if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
    return false;

  InferiorSizedWord name_isw(name, *process_sp);
  InferiorSizedWord reason_isw(reason, *process_sp);

  CompilerType voidstar = process_sp->GetTarget()
                              .GetScratchClangASTContext()
                              ->GetBasicType(lldb::eBasicTypeVoid)
                              .GetPointerType();

  ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData(
      "name_str", name_isw.GetAsData(process_sp->GetByteOrder()),
      valobj.GetExecutionContextRef(), voidstar);
  ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData(
      "reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()),
      valobj.GetExecutionContextRef(), voidstar);

  if (!name_sp || !reason_sp)
    return false;

  StreamString name_str_summary;
  StreamString reason_str_summary;
  if (NSStringSummaryProvider(*name_sp, name_str_summary, options) &&
      NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
      !name_str_summary.Empty() && !reason_str_summary.Empty()) {
    stream.Printf("name: %s - reason: %s", name_str_summary.GetData(),
                  reason_str_summary.GetData());
    return true;
  } else
    return false;
}
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;
      }
    }
  }

  return class_type_or_name.IsEmpty() == false;
}
Exemple #28
0
bool
lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp = valobj.GetProcessSP();
    if (!process_sp)
        return false;
    
    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    
    if (!runtime)
        return false;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return false;
    
    uint32_t ptr_size = process_sp->GetAddressByteSize();
    
    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
    
    if (!valobj_addr)
        return false;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return false;
    
    if (strcmp(class_name, "NSURL") == 0)
    {
        uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit)
        uint64_t offset_base = offset_text + ptr_size;
        CompilerType type(valobj.GetCompilerType());
        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
        ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
        if (!text)
            return false;
        if (text->GetValueAsUnsigned(0) == 0)
            return false;
        StreamString summary;
        if (!NSStringSummaryProvider(*text, summary, options))
            return false;
        if (base && base->GetValueAsUnsigned(0))
        {
            if (summary.GetSize() > 0)
                summary.GetString().resize(summary.GetSize()-1);
            summary.Printf(" -- ");
            StreamString base_summary;
            if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0)
                summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData());
        }
        if (summary.GetSize())
        {
            stream.Printf("%s",summary.GetData());
            return true;
        }
    }
    else
    {
        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream);
    }
    return false;
}
std::unique_ptr<SwiftHashedContainerBufferHandler>
SwiftHashedContainerBufferHandler::CreateBufferHandler (ValueObject& valobj,
                                                        NativeCreatorFunction Native,
                                                        SyntheticCreatorFunction Synthetic,
                                                        ConstString mangled,
                                                        ConstString demangled)
{
    static ConstString g__variantStorage("_variantStorage");
    static ConstString g_Native("native");
    static ConstString g_Cocoa("cocoa");
    static ConstString g_nativeStorage("nativeStorage");
    static ConstString g_buffer("buffer");
    static ConstString g_storage("storage");
    static ConstString g__storage("_storage");
    static ConstString g_Some("some");
    
    Error error;
    
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return nullptr;
    
    ConstString type_name_cs(valobj.GetTypeName());
    if (type_name_cs)
    {
        llvm::StringRef type_name_strref(type_name_cs.GetStringRef());
        
        if (type_name_strref.startswith(mangled.GetCString()) ||
            type_name_strref.startswith(demangled.GetCString()))
        {
            return CreateBufferHandlerForNativeStorageOwner(valobj, valobj.GetPointerValue(), false, Native);
        }
    }
    
    ValueObjectSP valobj_sp = valobj.GetSP()->GetQualifiedRepresentationIfAvailable(lldb::eDynamicCanRunTarget, false);
    
    ValueObjectSP _variantStorageSP(valobj_sp->GetChildMemberWithName(g__variantStorage, true));
    
    if (!_variantStorageSP)
        return nullptr;
    
    ConstString storage_kind(_variantStorageSP->GetValueAsCString());
    
    if (!storage_kind)
        return nullptr;
    
    if (g_Cocoa == storage_kind)
    {
        ValueObjectSP child_sp(_variantStorageSP->GetChildMemberWithName(g_Native, true));
        if (!child_sp)
            return nullptr;
        // it's an NSDictionary in disguise
        uint64_t cocoa_storage_ptr = child_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
        if (cocoa_storage_ptr == LLDB_INVALID_ADDRESS || error.Fail())
            return nullptr;
        cocoa_storage_ptr &= 0x00FFFFFFFFFFFFFF; // for some reason I need to zero out the MSB; figure out why later
        CompilerType id = process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID);
        InferiorSizedWord isw(cocoa_storage_ptr, *process_sp);
        ValueObjectSP cocoarr_sp = ValueObject::CreateValueObjectFromData("cocoarr", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), id);
        if (!cocoarr_sp)
            return nullptr;
        auto objc_runtime = process_sp->GetObjCLanguageRuntime();
        auto descriptor_sp = objc_runtime->GetClassDescriptor(*cocoarr_sp);
        if (!descriptor_sp)
            return nullptr;
        ConstString classname(descriptor_sp->GetClassName());
        if (classname && classname.GetStringRef().startswith(mangled.GetCString()))
        {
            return CreateBufferHandlerForNativeStorageOwner(*_variantStorageSP, cocoa_storage_ptr, true, Native);
        }
        else
        {
            auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Synthetic(cocoarr_sp));
            if (handler && handler->IsValid())
                return handler;
            return nullptr;
        }
    }
    if (g_Native == storage_kind)
    {
        ValueObjectSP native_sp(_variantStorageSP->GetChildAtNamePath({ g_Native }));
        ValueObjectSP nativeStorage_sp(_variantStorageSP->GetChildAtNamePath( { g_Native, g_nativeStorage } ));
        if (!native_sp || !nativeStorage_sp)
            return nullptr;
        
        CompilerType child_type(valobj.GetCompilerType());
        lldb::TemplateArgumentKind kind;
        CompilerType key_type(child_type.GetTemplateArgument(0, kind));
        CompilerType value_type(child_type.GetTemplateArgument(1, kind));
        
        auto handler = std::unique_ptr<SwiftHashedContainerBufferHandler>(Native(nativeStorage_sp, key_type, value_type));
        if (handler && handler->IsValid())
            return handler;
        return nullptr;
    }
    
    return nullptr;
}
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());

        Target *target = exe_ctx.GetTargetPtr();
        Process *process = exe_ctx.GetProcessPtr();

        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;
        }
        
        lldb::offset_t offset = 0;
        lldb::addr_t vtable_address_point = data.GetAddress (&offset);
            
        if (offset == 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(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);
                        class_type_or_name.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.
                        if (sc.module_sp)
                        {
                            num_matches = sc.module_sp->FindTypes (sc,
                                                                   ConstString(class_name),
                                                                   exact_match,
                                                                   1,
                                                                   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,
                                                                         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 false;
                        }
                        if (num_matches == 1)
                        {
                            type_sp = class_types.GetTypeAtIndex(0);
                            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());

                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
                        }
                        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->GetFullCompilerType ()))
                                    {
                                        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());
                                        class_type_or_name.SetTypeSP(type_sp);
                                        break;
                                    }
                                }
                            }
                            
                            if (i == num_matches)
                            {
                                if (log)
                                    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());
                                return false;
                            }
                        }

                        // 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->GetFullCompilerType ()))
                            {
                                // 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 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 = 0;
                            int64_t offset_to_top = data.GetMaxS64(&offset, 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.SetRawAddress(dynamic_addr);
                            }
                            return true;
                        }
                    }
                }
            }
        }
    }
    
    return class_type_or_name.IsEmpty() == false;
}