//===-- 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-enumerations.h" #include "lldb/lldb-public.h" #include "lldb/Core/DumpDataExtractor.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" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/StreamString.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) { Status error; valobj->GetData(data, error); if (error.Fail()) return false; StreamString reg_sstr; DumpDataExtractor(data, ®_sstr, 0, GetFormat(), reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, exe_ctx.GetBestExecutionContextScope()); dest = 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(); Status 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 { Status error; valobj->GetData(data, error); if (error.Fail()) return false; } StreamString sstr; ExecutionContextScope *exe_scope( exe_ctx.GetBestExecutionContextScope()); 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" compiler_type.GetByteSize( exe_scope), // Byte size of item in "m_data" valobj->GetBitfieldBitSize(), // Bitfield bit size valobj->GetBitfieldBitOffset(), // Bitfield bit offset exe_scope); // 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 dest = 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; Status 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 = 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(); }