]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/DataFormatters/TypeFormat.cpp
Merge ^/head r303250 through r308226.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / DataFormatters / TypeFormat.cpp
1 //===-- TypeFormat.cpp ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/DataFormatters/TypeFormat.h"
11
12 // C Includes
13
14 // C++ Includes
15
16 // Other libraries and framework includes
17
18 // Project includes
19 #include "lldb/lldb-public.h"
20 #include "lldb/lldb-enumerations.h"
21
22 #include "lldb/Core/StreamString.h"
23 #include "lldb/DataFormatters/FormatManager.h"
24 #include "lldb/Symbol/CompilerType.h"
25 #include "lldb/Symbol/SymbolContext.h"
26 #include "lldb/Symbol/SymbolFile.h"
27 #include "lldb/Symbol/TypeList.h"
28 #include "lldb/Target/Target.h"
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 TypeFormatImpl::TypeFormatImpl (const Flags& flags) :
34 m_flags(flags),
35 m_my_revision(0)
36 {
37 }
38
39 TypeFormatImpl::~TypeFormatImpl ()
40 {
41 }
42
43 TypeFormatImpl_Format::TypeFormatImpl_Format (lldb::Format f,
44                                               const TypeFormatImpl::Flags& flags) :
45 TypeFormatImpl(flags),
46 m_format (f)
47 {
48 }
49
50 TypeFormatImpl_Format::~TypeFormatImpl_Format ()
51 {
52 }
53
54 bool
55 TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
56                                      std::string& dest) const
57 {
58     if (!valobj)
59         return false;
60     if (valobj->CanProvideValue())
61     {
62         Value& value(valobj->GetValue());
63         const Value::ContextType context_type = value.GetContextType();
64         ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
65         DataExtractor data;
66         
67         if (context_type == Value::eContextTypeRegisterInfo)
68         {
69             const RegisterInfo *reg_info = value.GetRegisterInfo();
70             if (reg_info)
71             {
72                 Error error;
73                 valobj->GetData(data, error);
74                 if (error.Fail())
75                     return false;
76                 
77                 StreamString reg_sstr;
78                 data.Dump (&reg_sstr,
79                            0,
80                            GetFormat(),
81                            reg_info->byte_size,
82                            1,
83                            UINT32_MAX,
84                            LLDB_INVALID_ADDRESS,
85                            0,
86                            0,
87                            exe_ctx.GetBestExecutionContextScope());
88                 dest.swap(reg_sstr.GetString());
89             }
90         }
91         else
92         {
93             CompilerType compiler_type = value.GetCompilerType ();
94             if (compiler_type)
95             {
96                 // put custom bytes to display in the DataExtractor to override the default value logic
97                 if (GetFormat() == eFormatCString)
98                 {
99                     lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags
100                     if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC))
101                     {
102                         // if we are dumping a pointer as a c-string, get the pointee data as a string
103                         TargetSP target_sp(valobj->GetTargetSP());
104                         if (target_sp)
105                         {
106                             size_t max_len = target_sp->GetMaximumSizeOfStringSummary();
107                             Error error;
108                             DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0));
109                             Address address(valobj->GetPointerValue());
110                             if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success())
111                                 data.SetData(buffer_sp);
112                         }
113                     }
114                 }
115                 else
116                 {
117                     Error error;
118                     valobj->GetData(data, error);
119                     if (error.Fail())
120                         return false;
121                 }
122                 
123                 StreamString sstr;
124                 compiler_type.DumpTypeValue (&sstr,                         // The stream to use for display
125                                           GetFormat(),                  // Format to display this type with
126                                           data,                         // Data to extract from
127                                           0,                             // Byte offset into "m_data"
128                                           valobj->GetByteSize(),                 // Byte size of item in "m_data"
129                                           valobj->GetBitfieldBitSize(),          // Bitfield bit size
130                                           valobj->GetBitfieldBitOffset(),        // Bitfield bit offset
131                                           exe_ctx.GetBestExecutionContextScope());
132                 // Given that we do not want to set the ValueObject's m_error
133                 // for a formatting error (or else we wouldn't be able to reformat
134                 // until a next update), an empty string is treated as a "false"
135                 // return from here, but that's about as severe as we get
136                 // CompilerType::DumpTypeValue() should always return
137                 // something, even if that something is an error message
138                 if (sstr.GetString().empty())
139                     dest.clear();
140                 else
141                     dest.swap(sstr.GetString());
142             }
143         }
144         return !dest.empty();
145     }
146     else
147         return false;
148 }
149
150 std::string
151 TypeFormatImpl_Format::GetDescription()
152 {
153     StreamString sstr;
154     sstr.Printf ("%s%s%s%s",
155                  FormatManager::GetFormatAsCString (GetFormat()),
156                  Cascades() ? "" : " (not cascading)",
157                  SkipsPointers() ? " (skip pointers)" : "",
158                  SkipsReferences() ? " (skip references)" : "");
159     return sstr.GetString();
160 }
161
162 TypeFormatImpl_EnumType::TypeFormatImpl_EnumType (ConstString type_name,
163                                                   const TypeFormatImpl::Flags& flags) :
164 TypeFormatImpl(flags),
165 m_enum_type(type_name),
166 m_types()
167 {
168 }
169
170 TypeFormatImpl_EnumType::~TypeFormatImpl_EnumType ()
171 {
172 }
173
174 bool
175 TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
176                                        std::string& dest) const
177 {
178     dest.clear();
179     if (!valobj)
180         return false;
181     if (!valobj->CanProvideValue())
182         return false;
183     ProcessSP process_sp;
184     TargetSP target_sp;
185     void* valobj_key = (process_sp = valobj->GetProcessSP()).get();
186     if (!valobj_key)
187         valobj_key = (target_sp = valobj->GetTargetSP()).get();
188     else
189         target_sp = process_sp->GetTarget().shared_from_this();
190     if (!valobj_key)
191         return false;
192     auto iter = m_types.find(valobj_key),
193     end = m_types.end();
194     CompilerType valobj_enum_type;
195     if (iter == end)
196     {
197         // probably a redundant check
198         if (!target_sp)
199             return false;
200         const ModuleList& images(target_sp->GetImages());
201         SymbolContext sc;
202         TypeList types;
203         llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
204         images.FindTypes(sc, m_enum_type, false, UINT32_MAX, searched_symbol_files, types);
205         if (types.GetSize() == 0)
206             return false;
207         for (lldb::TypeSP type_sp : types.Types())
208         {
209             if (!type_sp)
210                 continue;
211             if ( (type_sp->GetForwardCompilerType().GetTypeInfo() & eTypeIsEnumeration) == eTypeIsEnumeration)
212             {
213                 valobj_enum_type = type_sp->GetFullCompilerType ();
214                 m_types.emplace(valobj_key,valobj_enum_type);
215                 break;
216             }
217         }
218     }
219     else
220         valobj_enum_type = iter->second;
221     if (valobj_enum_type.IsValid() == false)
222         return false;
223     DataExtractor data;
224     Error error;
225     valobj->GetData(data, error);
226     if (error.Fail())
227         return false;
228     ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
229     StreamString sstr;
230     valobj_enum_type.DumpTypeValue(&sstr,
231                                    lldb::eFormatEnum,
232                                    data,
233                                    0,
234                                    data.GetByteSize(),
235                                    0,
236                                    0,
237                                    exe_ctx.GetBestExecutionContextScope());
238     if (!sstr.GetString().empty())
239         dest.swap(sstr.GetString());
240     return !dest.empty();
241 }
242
243 std::string
244 TypeFormatImpl_EnumType::GetDescription()
245 {
246     StreamString sstr;
247     sstr.Printf ("as type %s%s%s%s",
248                  m_enum_type.AsCString("<invalid type>"),
249                  Cascades() ? "" : " (not cascading)",
250                  SkipsPointers() ? " (skip pointers)" : "",
251                  SkipsReferences() ? " (skip references)" : "");
252     return sstr.GetString();
253 }