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