1 //===-- TypeFormat.cpp ----------------------------------------------------===// 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 #include <optional> 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 TypeFormatImpl::TypeFormatImpl(const Flags &flags) : m_flags(flags) {} 32 33 TypeFormatImpl::~TypeFormatImpl() = default; 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() = default; 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::ContextType::RegisterInfo) { 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 = std::string(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 WritableDataBufferSP buffer_sp( 82 new DataBufferHeap(max_len + 1, 0)); 83 Address address(valobj->GetPointerValue()); 84 if (target_sp->ReadCStringFromMemory( 85 address, (char *)buffer_sp->GetBytes(), max_len, error) && 86 error.Success()) 87 data.SetData(buffer_sp); 88 } 89 } 90 } else { 91 Status error; 92 valobj->GetData(data, error); 93 if (error.Fail()) 94 return false; 95 } 96 97 ExecutionContextScope *exe_scope = 98 exe_ctx.GetBestExecutionContextScope(); 99 std::optional<uint64_t> size = compiler_type.GetByteSize(exe_scope); 100 if (!size) 101 return false; 102 StreamString sstr; 103 compiler_type.DumpTypeValue( 104 &sstr, // The stream to use for display 105 GetFormat(), // Format to display this type with 106 data, // Data to extract from 107 0, // Byte offset into "m_data" 108 *size, // Byte size of item in "m_data" 109 valobj->GetBitfieldBitSize(), // Bitfield bit size 110 valobj->GetBitfieldBitOffset(), // Bitfield bit offset 111 exe_scope); 112 // Given that we do not want to set the ValueObject's m_error for a 113 // formatting error (or else we wouldn't be able to reformat until a 114 // next update), an empty string is treated as a "false" return from 115 // here, but that's about as severe as we get 116 // CompilerType::DumpTypeValue() should always return something, even 117 // if that something is an error message 118 dest = std::string(sstr.GetString()); 119 } 120 } 121 return !dest.empty(); 122 } else 123 return false; 124 } 125 126 std::string TypeFormatImpl_Format::GetDescription() { 127 StreamString sstr; 128 sstr.Printf("%s%s%s%s", FormatManager::GetFormatAsCString(GetFormat()), 129 Cascades() ? "" : " (not cascading)", 130 SkipsPointers() ? " (skip pointers)" : "", 131 SkipsReferences() ? " (skip references)" : ""); 132 return std::string(sstr.GetString()); 133 } 134 135 TypeFormatImpl_EnumType::TypeFormatImpl_EnumType( 136 ConstString type_name, const TypeFormatImpl::Flags &flags) 137 : TypeFormatImpl(flags), m_enum_type(type_name), m_types() {} 138 139 TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() = default; 140 141 bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj, 142 std::string &dest) const { 143 dest.clear(); 144 if (!valobj) 145 return false; 146 if (!valobj->CanProvideValue()) 147 return false; 148 ProcessSP process_sp; 149 TargetSP target_sp; 150 void *valobj_key = (process_sp = valobj->GetProcessSP()).get(); 151 if (!valobj_key) 152 valobj_key = (target_sp = valobj->GetTargetSP()).get(); 153 else 154 target_sp = process_sp->GetTarget().shared_from_this(); 155 if (!valobj_key) 156 return false; 157 auto iter = m_types.find(valobj_key), end = m_types.end(); 158 CompilerType valobj_enum_type; 159 if (iter == end) { 160 // probably a redundant check 161 if (!target_sp) 162 return false; 163 const ModuleList &images(target_sp->GetImages()); 164 TypeList types; 165 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; 166 images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX, 167 searched_symbol_files, types); 168 if (types.Empty()) 169 return false; 170 for (lldb::TypeSP type_sp : types.Types()) { 171 if (!type_sp) 172 continue; 173 if ((type_sp->GetForwardCompilerType().GetTypeInfo() & 174 eTypeIsEnumeration) == eTypeIsEnumeration) { 175 valobj_enum_type = type_sp->GetFullCompilerType(); 176 m_types.emplace(valobj_key, valobj_enum_type); 177 break; 178 } 179 } 180 } else 181 valobj_enum_type = iter->second; 182 if (!valobj_enum_type.IsValid()) 183 return false; 184 DataExtractor data; 185 Status error; 186 valobj->GetData(data, error); 187 if (error.Fail()) 188 return false; 189 ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); 190 StreamString sstr; 191 valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0, 192 data.GetByteSize(), 0, 0, 193 exe_ctx.GetBestExecutionContextScope()); 194 if (!sstr.GetString().empty()) 195 dest = std::string(sstr.GetString()); 196 return !dest.empty(); 197 } 198 199 std::string TypeFormatImpl_EnumType::GetDescription() { 200 StreamString sstr; 201 sstr.Printf("as type %s%s%s%s", m_enum_type.AsCString("<invalid type>"), 202 Cascades() ? "" : " (not cascading)", 203 SkipsPointers() ? " (skip pointers)" : "", 204 SkipsReferences() ? " (skip references)" : ""); 205 return std::string(sstr.GetString()); 206 } 207