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 target_sp->ReadCStringFromMemory( 85 address, (char *)buffer_sp->GetBytes(), max_len, error); 86 if (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 TypeQuery query(m_enum_type.GetStringRef()); 165 TypeResults results; 166 images.FindTypes(nullptr, query, results); 167 if (results.GetTypeMap().Empty()) 168 return false; 169 for (lldb::TypeSP type_sp : results.GetTypeMap().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 = std::string(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 std::string(sstr.GetString()); 205 } 206