1 //===-- TypeFormat.cpp ----------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/DataFormatters/TypeFormat.h" 10 11 12 13 14 #include "lldb/lldb-enumerations.h" 15 #include "lldb/lldb-public.h" 16 17 #include "lldb/Core/DumpDataExtractor.h" 18 #include "lldb/DataFormatters/FormatManager.h" 19 #include "lldb/Symbol/CompilerType.h" 20 #include "lldb/Symbol/SymbolContext.h" 21 #include "lldb/Symbol/SymbolFile.h" 22 #include "lldb/Symbol/TypeList.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Utility/DataExtractor.h" 25 #include "lldb/Utility/StreamString.h" 26 27 using namespace lldb; 28 using namespace lldb_private; 29 30 TypeFormatImpl::TypeFormatImpl(const Flags &flags) 31 : m_flags(flags), m_my_revision(0) {} 32 33 TypeFormatImpl::~TypeFormatImpl() {} 34 35 TypeFormatImpl_Format::TypeFormatImpl_Format(lldb::Format f, 36 const TypeFormatImpl::Flags &flags) 37 : TypeFormatImpl(flags), m_format(f) {} 38 39 TypeFormatImpl_Format::~TypeFormatImpl_Format() {} 40 41 bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj, 42 std::string &dest) const { 43 if (!valobj) 44 return false; 45 if (valobj->CanProvideValue()) { 46 Value &value(valobj->GetValue()); 47 const Value::ContextType context_type = value.GetContextType(); 48 ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); 49 DataExtractor data; 50 51 if (context_type == Value::eContextTypeRegisterInfo) { 52 const RegisterInfo *reg_info = value.GetRegisterInfo(); 53 if (reg_info) { 54 Status error; 55 valobj->GetData(data, error); 56 if (error.Fail()) 57 return false; 58 59 StreamString reg_sstr; 60 DumpDataExtractor(data, ®_sstr, 0, GetFormat(), reg_info->byte_size, 61 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, 62 exe_ctx.GetBestExecutionContextScope()); 63 dest = reg_sstr.GetString(); 64 } 65 } else { 66 CompilerType compiler_type = value.GetCompilerType(); 67 if (compiler_type) { 68 // put custom bytes to display in the DataExtractor to override the 69 // default value logic 70 if (GetFormat() == eFormatCString) { 71 lldb_private::Flags type_flags(compiler_type.GetTypeInfo( 72 nullptr)); // disambiguate w.r.t. TypeFormatImpl::Flags 73 if (type_flags.Test(eTypeIsPointer) && 74 !type_flags.Test(eTypeIsObjC)) { 75 // if we are dumping a pointer as a c-string, get the pointee data 76 // as a string 77 TargetSP target_sp(valobj->GetTargetSP()); 78 if (target_sp) { 79 size_t max_len = target_sp->GetMaximumSizeOfStringSummary(); 80 Status error; 81 DataBufferSP buffer_sp(new DataBufferHeap(max_len + 1, 0)); 82 Address address(valobj->GetPointerValue()); 83 if (target_sp->ReadCStringFromMemory( 84 address, (char *)buffer_sp->GetBytes(), max_len, error) && 85 error.Success()) 86 data.SetData(buffer_sp); 87 } 88 } 89 } else { 90 Status error; 91 valobj->GetData(data, error); 92 if (error.Fail()) 93 return false; 94 } 95 96 ExecutionContextScope *exe_scope = 97 exe_ctx.GetBestExecutionContextScope(); 98 llvm::Optional<uint64_t> size = compiler_type.GetByteSize(exe_scope); 99 if (!size) 100 return false; 101 StreamString sstr; 102 compiler_type.DumpTypeValue( 103 &sstr, // The stream to use for display 104 GetFormat(), // Format to display this type with 105 data, // Data to extract from 106 0, // Byte offset into "m_data" 107 *size, // Byte size of item in "m_data" 108 valobj->GetBitfieldBitSize(), // Bitfield bit size 109 valobj->GetBitfieldBitOffset(), // Bitfield bit offset 110 exe_scope); 111 // Given that we do not want to set the ValueObject's m_error for a 112 // formatting error (or else we wouldn't be able to reformat until a 113 // next update), an empty string is treated as a "false" return from 114 // here, but that's about as severe as we get 115 // CompilerType::DumpTypeValue() should always return something, even 116 // if that something is an error message 117 dest = sstr.GetString(); 118 } 119 } 120 return !dest.empty(); 121 } else 122 return false; 123 } 124 125 std::string TypeFormatImpl_Format::GetDescription() { 126 StreamString sstr; 127 sstr.Printf("%s%s%s%s", FormatManager::GetFormatAsCString(GetFormat()), 128 Cascades() ? "" : " (not cascading)", 129 SkipsPointers() ? " (skip pointers)" : "", 130 SkipsReferences() ? " (skip references)" : ""); 131 return sstr.GetString(); 132 } 133 134 TypeFormatImpl_EnumType::TypeFormatImpl_EnumType( 135 ConstString type_name, const TypeFormatImpl::Flags &flags) 136 : TypeFormatImpl(flags), m_enum_type(type_name), m_types() {} 137 138 TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() {} 139 140 bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj, 141 std::string &dest) const { 142 dest.clear(); 143 if (!valobj) 144 return false; 145 if (!valobj->CanProvideValue()) 146 return false; 147 ProcessSP process_sp; 148 TargetSP target_sp; 149 void *valobj_key = (process_sp = valobj->GetProcessSP()).get(); 150 if (!valobj_key) 151 valobj_key = (target_sp = valobj->GetTargetSP()).get(); 152 else 153 target_sp = process_sp->GetTarget().shared_from_this(); 154 if (!valobj_key) 155 return false; 156 auto iter = m_types.find(valobj_key), end = m_types.end(); 157 CompilerType valobj_enum_type; 158 if (iter == end) { 159 // probably a redundant check 160 if (!target_sp) 161 return false; 162 const ModuleList &images(target_sp->GetImages()); 163 TypeList types; 164 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; 165 images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX, 166 searched_symbol_files, types); 167 if (types.Empty()) 168 return false; 169 for (lldb::TypeSP type_sp : types.Types()) { 170 if (!type_sp) 171 continue; 172 if ((type_sp->GetForwardCompilerType().GetTypeInfo() & 173 eTypeIsEnumeration) == eTypeIsEnumeration) { 174 valobj_enum_type = type_sp->GetFullCompilerType(); 175 m_types.emplace(valobj_key, valobj_enum_type); 176 break; 177 } 178 } 179 } else 180 valobj_enum_type = iter->second; 181 if (!valobj_enum_type.IsValid()) 182 return false; 183 DataExtractor data; 184 Status error; 185 valobj->GetData(data, error); 186 if (error.Fail()) 187 return false; 188 ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); 189 StreamString sstr; 190 valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0, 191 data.GetByteSize(), 0, 0, 192 exe_ctx.GetBestExecutionContextScope()); 193 if (!sstr.GetString().empty()) 194 dest = sstr.GetString(); 195 return !dest.empty(); 196 } 197 198 std::string TypeFormatImpl_EnumType::GetDescription() { 199 StreamString sstr; 200 sstr.Printf("as type %s%s%s%s", m_enum_type.AsCString("<invalid type>"), 201 Cascades() ? "" : " (not cascading)", 202 SkipsPointers() ? " (skip pointers)" : "", 203 SkipsReferences() ? " (skip references)" : ""); 204 return sstr.GetString(); 205 } 206