1254721Semaste//===-- TypeFormat.cpp ----------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste// C Includes 13254721Semaste 14254721Semaste// C++ Includes 15254721Semaste 16254721Semaste// Other libraries and framework includes 17254721Semaste 18254721Semaste// Project includes 19254721Semaste#include "lldb/lldb-public.h" 20254721Semaste#include "lldb/lldb-enumerations.h" 21254721Semaste 22254721Semaste#include "lldb/Core/Debugger.h" 23254721Semaste#include "lldb/Core/StreamString.h" 24254721Semaste#include "lldb/Core/Timer.h" 25254721Semaste#include "lldb/DataFormatters/TypeFormat.h" 26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 27254721Semaste#include "lldb/Symbol/ClangASTType.h" 28269024Semaste#include "lldb/Symbol/TypeList.h" 29254721Semaste#include "lldb/Target/StackFrame.h" 30254721Semaste#include "lldb/Target/Target.h" 31254721Semaste 32254721Semasteusing namespace lldb; 33254721Semasteusing namespace lldb_private; 34254721Semaste 35269024SemasteTypeFormatImpl::TypeFormatImpl (const Flags& flags) : 36254721Semastem_flags(flags), 37269024Semastem_my_revision(0) 38269024Semaste{ 39269024Semaste} 40269024Semaste 41269024Semaste 42269024SemasteTypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f, 43269024Semaste const TypeFormatImpl::Flags& flags) : 44269024SemasteTypeFormatImpl(flags), 45254721Semastem_format (f) 46254721Semaste{ 47254721Semaste} 48254721Semaste 49269024Semastebool 50269024SemasteTypeFormatImpl_Format::FormatObject (ValueObject *valobj, 51269024Semaste std::string& dest) const 52269024Semaste{ 53269024Semaste if (!valobj) 54269024Semaste return false; 55269024Semaste if (valobj->GetClangType().IsAggregateType () == false) 56269024Semaste { 57269024Semaste const Value& value(valobj->GetValue()); 58269024Semaste const Value::ContextType context_type = value.GetContextType(); 59269024Semaste ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); 60269024Semaste DataExtractor data; 61269024Semaste 62269024Semaste if (context_type == Value::eContextTypeRegisterInfo) 63269024Semaste { 64269024Semaste const RegisterInfo *reg_info = value.GetRegisterInfo(); 65269024Semaste if (reg_info) 66269024Semaste { 67269024Semaste valobj->GetData(data); 68269024Semaste 69269024Semaste StreamString reg_sstr; 70269024Semaste data.Dump (®_sstr, 71269024Semaste 0, 72269024Semaste GetFormat(), 73269024Semaste reg_info->byte_size, 74269024Semaste 1, 75269024Semaste UINT32_MAX, 76269024Semaste LLDB_INVALID_ADDRESS, 77269024Semaste 0, 78269024Semaste 0, 79269024Semaste exe_ctx.GetBestExecutionContextScope()); 80269024Semaste dest.swap(reg_sstr.GetString()); 81269024Semaste } 82269024Semaste } 83269024Semaste else 84269024Semaste { 85269024Semaste ClangASTType clang_type = valobj->GetClangType (); 86269024Semaste if (clang_type) 87269024Semaste { 88269024Semaste // put custom bytes to display in the DataExtractor to override the default value logic 89269024Semaste if (GetFormat() == eFormatCString) 90269024Semaste { 91269024Semaste lldb_private::Flags type_flags(clang_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags 92269024Semaste if (type_flags.Test(ClangASTType::eTypeIsPointer) && !type_flags.Test(ClangASTType::eTypeIsObjC)) 93269024Semaste { 94269024Semaste // if we are dumping a pointer as a c-string, get the pointee data as a string 95269024Semaste TargetSP target_sp(valobj->GetTargetSP()); 96269024Semaste if (target_sp) 97269024Semaste { 98269024Semaste size_t max_len = target_sp->GetMaximumSizeOfStringSummary(); 99269024Semaste Error error; 100269024Semaste DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0)); 101269024Semaste Address address(valobj->GetPointerValue()); 102269024Semaste if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success()) 103269024Semaste data.SetData(buffer_sp); 104269024Semaste } 105269024Semaste } 106269024Semaste } 107269024Semaste else 108269024Semaste valobj->GetData(data); 109269024Semaste 110269024Semaste StreamString sstr; 111269024Semaste clang_type.DumpTypeValue (&sstr, // The stream to use for display 112269024Semaste GetFormat(), // Format to display this type with 113269024Semaste data, // Data to extract from 114269024Semaste 0, // Byte offset into "m_data" 115269024Semaste valobj->GetByteSize(), // Byte size of item in "m_data" 116269024Semaste valobj->GetBitfieldBitSize(), // Bitfield bit size 117269024Semaste valobj->GetBitfieldBitOffset(), // Bitfield bit offset 118269024Semaste exe_ctx.GetBestExecutionContextScope()); 119269024Semaste // Given that we do not want to set the ValueObject's m_error 120269024Semaste // for a formatting error (or else we wouldn't be able to reformat 121269024Semaste // until a next update), an empty string is treated as a "false" 122269024Semaste // return from here, but that's about as severe as we get 123269024Semaste // ClangASTType::DumpTypeValue() should always return 124269024Semaste // something, even if that something is an error message 125269024Semaste if (sstr.GetString().empty()) 126269024Semaste dest.clear(); 127269024Semaste else 128269024Semaste dest.swap(sstr.GetString()); 129269024Semaste } 130269024Semaste } 131269024Semaste return !dest.empty(); 132269024Semaste } 133269024Semaste else 134269024Semaste return false; 135269024Semaste} 136269024Semaste 137254721Semastestd::string 138269024SemasteTypeFormatImpl_Format::GetDescription() 139254721Semaste{ 140254721Semaste StreamString sstr; 141263363Semaste sstr.Printf ("%s%s%s%s", 142254721Semaste FormatManager::GetFormatAsCString (GetFormat()), 143254721Semaste Cascades() ? "" : " (not cascading)", 144254721Semaste SkipsPointers() ? " (skip pointers)" : "", 145254721Semaste SkipsReferences() ? " (skip references)" : ""); 146254721Semaste return sstr.GetString(); 147254721Semaste} 148254721Semaste 149269024SemasteTypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name, 150269024Semaste const TypeFormatImpl::Flags& flags) : 151269024SemasteTypeFormatImpl(flags), 152269024Semastem_enum_type(type_name), 153269024Semastem_types() 154269024Semaste{ 155269024Semaste} 156269024Semaste 157269024Semastebool 158269024SemasteTypeFormatImpl_EnumType::FormatObject (ValueObject *valobj, 159269024Semaste std::string& dest) const 160269024Semaste{ 161269024Semaste dest.clear(); 162269024Semaste if (!valobj) 163269024Semaste return false; 164269024Semaste if (valobj->GetClangType().IsAggregateType ()) 165269024Semaste return false; 166269024Semaste ProcessSP process_sp; 167269024Semaste TargetSP target_sp; 168269024Semaste void* valobj_key = (process_sp = valobj->GetProcessSP()).get(); 169269024Semaste if (!valobj_key) 170269024Semaste valobj_key = (target_sp = valobj->GetTargetSP()).get(); 171269024Semaste else 172269024Semaste target_sp = process_sp->GetTarget().shared_from_this(); 173269024Semaste if (!valobj_key) 174269024Semaste return false; 175269024Semaste auto iter = m_types.find(valobj_key), 176269024Semaste end = m_types.end(); 177269024Semaste ClangASTType valobj_enum_type; 178269024Semaste if (iter == end) 179269024Semaste { 180269024Semaste // probably a redundant check 181269024Semaste if (!target_sp) 182269024Semaste return false; 183269024Semaste const ModuleList& images(target_sp->GetImages()); 184269024Semaste SymbolContext sc; 185269024Semaste TypeList types; 186269024Semaste images.FindTypes(sc, m_enum_type, false, UINT32_MAX, types); 187269024Semaste if (types.GetSize() == 0) 188269024Semaste return false; 189269024Semaste for (lldb::TypeSP type_sp : types.Types()) 190269024Semaste { 191269024Semaste if (!type_sp) 192269024Semaste continue; 193269024Semaste if ( (type_sp->GetClangForwardType().GetTypeInfo() & ClangASTType::eTypeIsEnumeration) == ClangASTType::eTypeIsEnumeration) 194269024Semaste { 195269024Semaste valobj_enum_type = type_sp->GetClangFullType(); 196269024Semaste m_types.emplace(valobj_key,valobj_enum_type); 197269024Semaste break; 198269024Semaste } 199269024Semaste } 200269024Semaste } 201269024Semaste else 202269024Semaste valobj_enum_type = iter->second; 203269024Semaste if (valobj_enum_type.IsValid() == false) 204269024Semaste return false; 205269024Semaste DataExtractor data; 206269024Semaste valobj->GetData(data); 207269024Semaste ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); 208269024Semaste StreamString sstr; 209269024Semaste valobj_enum_type.DumpTypeValue(&sstr, 210269024Semaste lldb::eFormatEnum, 211269024Semaste data, 212269024Semaste 0, 213269024Semaste data.GetByteSize(), 214269024Semaste 0, 215269024Semaste 0, 216269024Semaste exe_ctx.GetBestExecutionContextScope()); 217269024Semaste if (!sstr.GetString().empty()) 218269024Semaste dest.swap(sstr.GetString()); 219269024Semaste return !dest.empty(); 220269024Semaste} 221269024Semaste 222269024Semastestd::string 223269024SemasteTypeFormatImpl_EnumType::GetDescription() 224269024Semaste{ 225269024Semaste StreamString sstr; 226269024Semaste sstr.Printf ("as type %s%s%s%s", 227269024Semaste m_enum_type.AsCString("<invalid type>"), 228269024Semaste Cascades() ? "" : " (not cascading)", 229269024Semaste SkipsPointers() ? " (skip pointers)" : "", 230269024Semaste SkipsReferences() ? " (skip references)" : ""); 231269024Semaste return sstr.GetString(); 232269024Semaste} 233