xref: /freebsd/contrib/llvm-project/lldb/source/DataFormatters/TypeFormat.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
TypeFormatImpl(const Flags & flags)31 TypeFormatImpl::TypeFormatImpl(const Flags &flags) : m_flags(flags) {}
32 
33 TypeFormatImpl::~TypeFormatImpl() = default;
34 
TypeFormatImpl_Format(lldb::Format f,const TypeFormatImpl::Flags & flags)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 
FormatObject(ValueObject * valobj,std::string & dest) const41 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, &reg_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().address);
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         auto size_or_err = compiler_type.GetByteSize(exe_scope);
100         if (!size_or_err) {
101           LLDB_LOG_ERRORV(
102               GetLog(LLDBLog::Types), size_or_err.takeError(),
103               "Cannot get size of type while formatting object: {0}");
104           return false;
105         }
106         StreamString sstr;
107         compiler_type.DumpTypeValue(
108             &sstr,                          // The stream to use for display
109             GetFormat(),                    // Format to display this type with
110             data,                           // Data to extract from
111             0,                              // Byte offset into "m_data"
112             *size_or_err,                   // Byte size of item in "m_data"
113             valobj->GetBitfieldBitSize(),   // Bitfield bit size
114             valobj->GetBitfieldBitOffset(), // Bitfield bit offset
115             exe_scope);
116         // Given that we do not want to set the ValueObject's m_error for a
117         // formatting error (or else we wouldn't be able to reformat until a
118         // next update), an empty string is treated as a "false" return from
119         // here, but that's about as severe as we get
120         // CompilerType::DumpTypeValue() should always return something, even
121         // if that something is an error message
122         dest = std::string(sstr.GetString());
123       }
124     }
125     return !dest.empty();
126   } else
127     return false;
128 }
129 
GetDescription()130 std::string TypeFormatImpl_Format::GetDescription() {
131   StreamString sstr;
132   sstr.Printf("%s%s%s%s", FormatManager::GetFormatAsCString(GetFormat()),
133               Cascades() ? "" : " (not cascading)",
134               SkipsPointers() ? " (skip pointers)" : "",
135               SkipsReferences() ? " (skip references)" : "");
136   return std::string(sstr.GetString());
137 }
138 
TypeFormatImpl_EnumType(ConstString type_name,const TypeFormatImpl::Flags & flags)139 TypeFormatImpl_EnumType::TypeFormatImpl_EnumType(
140     ConstString type_name, const TypeFormatImpl::Flags &flags)
141     : TypeFormatImpl(flags), m_enum_type(type_name), m_types() {}
142 
143 TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType() = default;
144 
FormatObject(ValueObject * valobj,std::string & dest) const145 bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
146                                            std::string &dest) const {
147   dest.clear();
148   if (!valobj)
149     return false;
150   if (!valobj->CanProvideValue())
151     return false;
152   ProcessSP process_sp;
153   TargetSP target_sp;
154   void *valobj_key = (process_sp = valobj->GetProcessSP()).get();
155   if (!valobj_key)
156     valobj_key = (target_sp = valobj->GetTargetSP()).get();
157   else
158     target_sp = process_sp->GetTarget().shared_from_this();
159   if (!valobj_key)
160     return false;
161   auto iter = m_types.find(valobj_key), end = m_types.end();
162   CompilerType valobj_enum_type;
163   if (iter == end) {
164     // probably a redundant check
165     if (!target_sp)
166       return false;
167     const ModuleList &images(target_sp->GetImages());
168     TypeQuery query(m_enum_type.GetStringRef());
169     TypeResults results;
170     images.FindTypes(nullptr, query, results);
171     if (results.GetTypeMap().Empty())
172       return false;
173     for (lldb::TypeSP type_sp : results.GetTypeMap().Types()) {
174       if (!type_sp)
175         continue;
176       if ((type_sp->GetForwardCompilerType().GetTypeInfo() &
177            eTypeIsEnumeration) == eTypeIsEnumeration) {
178         valobj_enum_type = type_sp->GetFullCompilerType();
179         m_types.emplace(valobj_key, valobj_enum_type);
180         break;
181       }
182     }
183   } else
184     valobj_enum_type = iter->second;
185   if (!valobj_enum_type.IsValid())
186     return false;
187   DataExtractor data;
188   Status error;
189   valobj->GetData(data, error);
190   if (error.Fail())
191     return false;
192   ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
193   StreamString sstr;
194   valobj_enum_type.DumpTypeValue(&sstr, lldb::eFormatEnum, data, 0,
195                                  data.GetByteSize(), 0, 0,
196                                  exe_ctx.GetBestExecutionContextScope());
197   if (!sstr.GetString().empty())
198     dest = std::string(sstr.GetString());
199   return !dest.empty();
200 }
201 
GetDescription()202 std::string TypeFormatImpl_EnumType::GetDescription() {
203   StreamString sstr;
204   sstr.Printf("as type %s%s%s%s", m_enum_type.AsCString("<invalid type>"),
205               Cascades() ? "" : " (not cascading)",
206               SkipsPointers() ? " (skip pointers)" : "",
207               SkipsReferences() ? " (skip references)" : "");
208   return std::string(sstr.GetString());
209 }
210