//===-- TypeFormat.cpp ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/DataFormatters/TypeFormat.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/StreamString.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; TypeFormatImpl::TypeFormatImpl (const Flags& flags) : m_flags(flags), m_my_revision(0) { } TypeFormatImpl::~TypeFormatImpl () { } TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f, const TypeFormatImpl::Flags& flags) : TypeFormatImpl(flags), m_format (f) { } TypeFormatImpl_Format::~TypeFormatImpl_Format () { } bool TypeFormatImpl_Format::FormatObject (ValueObject *valobj, std::string& dest) const { if (!valobj) return false; if (valobj->CanProvideValue()) { Value& value(valobj->GetValue()); const Value::ContextType context_type = value.GetContextType(); ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); DataExtractor data; if (context_type == Value::eContextTypeRegisterInfo) { const RegisterInfo *reg_info = value.GetRegisterInfo(); if (reg_info) { Error error; valobj->GetData(data, error); if (error.Fail()) return false; StreamString reg_sstr; data.Dump (®_sstr, 0, GetFormat(), reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, exe_ctx.GetBestExecutionContextScope()); dest.swap(reg_sstr.GetString()); } } else { CompilerType compiler_type = value.GetCompilerType (); if (compiler_type) { // put custom bytes to display in the DataExtractor to override the default value logic if (GetFormat() == eFormatCString) { lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data as a string TargetSP target_sp(valobj->GetTargetSP()); if (target_sp) { size_t max_len = target_sp->GetMaximumSizeOfStringSummary(); Error error; DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0)); Address address(valobj->GetPointerValue()); if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success()) data.SetData(buffer_sp); } } } else { Error error; valobj->GetData(data, error); if (error.Fail()) return false; } StreamString sstr; compiler_type.DumpTypeValue (&sstr, // The stream to use for display GetFormat(), // Format to display this type with data, // Data to extract from 0, // Byte offset into "m_data" valobj->GetByteSize(), // Byte size of item in "m_data" valobj->GetBitfieldBitSize(), // Bitfield bit size valobj->GetBitfieldBitOffset(), // Bitfield bit offset exe_ctx.GetBestExecutionContextScope()); // Given that we do not want to set the ValueObject's m_error // for a formatting error (or else we wouldn't be able to reformat // until a next update), an empty string is treated as a "false" // return from here, but that's about as severe as we get // CompilerType::DumpTypeValue() should always return // something, even if that something is an error message if (sstr.GetString().empty()) dest.clear(); else dest.swap(sstr.GetString()); } } return !dest.empty(); } else return false; } std::string TypeFormatImpl_Format::GetDescription() { StreamString sstr; sstr.Printf ("%s%s%s%s", FormatManager::GetFormatAsCString (GetFormat()), Cascades() ? "" : " (not cascading)", SkipsPointers() ? " (skip pointers)" : "", SkipsReferences() ? " (skip references)" : ""); return sstr.GetString(); } TypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name, const TypeFormatImpl::Flags& flags) : TypeFormatImpl(flags), m_enum_type(type_name), m_types() { } TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType () { } bool TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, std::string& dest) const { dest.clear(); if (!valobj) return false; if (!valobj->CanProvideValue()) return false; ProcessSP process_sp; TargetSP target_sp; void* valobj_key = (process_sp = valobj->GetProcessSP()).get(); if (!valobj_key) valobj_key = (target_sp = valobj->GetTargetSP()).get(); else target_sp = process_sp->GetTarget().shared_from_this(); if (!valobj_key) return false; auto iter = m_types.find(valobj_key), end = m_types.end(); CompilerType valobj_enum_type; if (iter == end) { // probably a redundant check if (!target_sp) return false; const ModuleList& images(target_sp->GetImages()); SymbolContext sc; TypeList types; llvm::DenseSet searched_symbol_files; images.FindTypes(sc, m_enum_type, false, UINT32_MAX, searched_symbol_files, types); if (types.GetSize() == 0) return false; for (lldb::TypeSP type_sp : types.Types()) { if (!type_sp) continue; if ( (type_sp->GetForwardCompilerType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration) { valobj_enum_type = type_sp->GetFullCompilerType (); m_types.emplace(valobj_key,valobj_enum_type); break; } } } else valobj_enum_type = iter->second; if (valobj_enum_type.IsValid() == false) return false; DataExtractor data; Error error; valobj->GetData(data, error); if (error.Fail()) return false; ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); StreamString sstr; valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0, data.GetByteSize(), 0, 0, exe_ctx.GetBestExecutionContextScope()); if (!sstr.GetString().empty()) dest.swap(sstr.GetString()); return !dest.empty(); } std::string TypeFormatImpl_EnumType::GetDescription() { StreamString sstr; sstr.Printf ("as type %s%s%s%s", m_enum_type.AsCString(""), Cascades() ? "" : " (not cascading)", SkipsPointers() ? " (skip pointers)" : "", SkipsReferences() ? " (skip references)" : ""); return sstr.GetString(); }