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, &reg_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