Bug Summary

File:tools/lldb/source/Expression/ExpressionSourceCode.cpp
Warning:line 260, column 11
Called C++ object pointer is null

Annotated Source Code

1//===-- ExpressionSourceCode.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/Expression/ExpressionSourceCode.h"
11
12#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
13#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
14#include "lldb/Symbol/Block.h"
15#include "lldb/Symbol/CompileUnit.h"
16#include "lldb/Symbol/DebugMacros.h"
17#include "lldb/Symbol/TypeSystem.h"
18#include "lldb/Symbol/VariableList.h"
19#include "lldb/Target/ExecutionContext.h"
20#include "lldb/Target/Language.h"
21#include "lldb/Target/Platform.h"
22#include "lldb/Target/StackFrame.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Utility/StreamString.h"
25
26using namespace lldb_private;
27
28const char *ExpressionSourceCode::g_expression_prefix = R"(
29#ifndef NULL
30#define NULL (__null)
31#endif
32#ifndef Nil
33#define Nil (__null)
34#endif
35#ifndef nil
36#define nil (__null)
37#endif
38#ifndef YES
39#define YES ((BOOL)1)
40#endif
41#ifndef NO
42#define NO ((BOOL)0)
43#endif
44typedef __INT8_TYPE__ int8_t;
45typedef __UINT8_TYPE__ uint8_t;
46typedef __INT16_TYPE__ int16_t;
47typedef __UINT16_TYPE__ uint16_t;
48typedef __INT32_TYPE__ int32_t;
49typedef __UINT32_TYPE__ uint32_t;
50typedef __INT64_TYPE__ int64_t;
51typedef __UINT64_TYPE__ uint64_t;
52typedef __INTPTR_TYPE__ intptr_t;
53typedef __UINTPTR_TYPE__ uintptr_t;
54typedef __SIZE_TYPE__ size_t;
55typedef __PTRDIFF_TYPE__ ptrdiff_t;
56typedef unsigned short unichar;
57extern "C"
58{
59 int printf(const char * __restrict, ...);
60}
61)";
62
63static const char *c_start_marker = " /*LLDB_BODY_START*/\n ";
64static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n";
65
66namespace {
67
68class AddMacroState {
69 enum State {
70 CURRENT_FILE_NOT_YET_PUSHED,
71 CURRENT_FILE_PUSHED,
72 CURRENT_FILE_POPPED
73 };
74
75public:
76 AddMacroState(const FileSpec &current_file, const uint32_t current_file_line)
77 : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file),
78 m_current_file_line(current_file_line) {}
79
80 void StartFile(const FileSpec &file) {
81 m_file_stack.push_back(file);
82 if (file == m_current_file)
83 m_state = CURRENT_FILE_PUSHED;
84 }
85
86 void EndFile() {
87 if (m_file_stack.size() == 0)
88 return;
89
90 FileSpec old_top = m_file_stack.back();
91 m_file_stack.pop_back();
92 if (old_top == m_current_file)
93 m_state = CURRENT_FILE_POPPED;
94 }
95
96 // An entry is valid if it occurs before the current line in
97 // the current file.
98 bool IsValidEntry(uint32_t line) {
99 switch (m_state) {
100 case CURRENT_FILE_NOT_YET_PUSHED:
101 return true;
102 case CURRENT_FILE_PUSHED:
103 // If we are in file included in the current file,
104 // the entry should be added.
105 if (m_file_stack.back() != m_current_file)
106 return true;
107
108 if (line >= m_current_file_line)
109 return false;
110 else
111 return true;
112 default:
113 return false;
114 }
115 }
116
117private:
118 std::vector<FileSpec> m_file_stack;
119 State m_state;
120 FileSpec m_current_file;
121 uint32_t m_current_file_line;
122};
123
124} // anonymous namespace
125
126static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit,
127 AddMacroState &state, StreamString &stream) {
128 if (dm == nullptr)
129 return;
130
131 for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) {
132 const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
133 uint32_t line;
134
135 switch (entry.GetType()) {
136 case DebugMacroEntry::DEFINE:
137 if (state.IsValidEntry(entry.GetLineNumber()))
138 stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
139 else
140 return;
141 break;
142 case DebugMacroEntry::UNDEF:
143 if (state.IsValidEntry(entry.GetLineNumber()))
144 stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
145 else
146 return;
147 break;
148 case DebugMacroEntry::START_FILE:
149 line = entry.GetLineNumber();
150 if (state.IsValidEntry(line))
151 state.StartFile(entry.GetFileSpec(comp_unit));
152 else
153 return;
154 break;
155 case DebugMacroEntry::END_FILE:
156 state.EndFile();
157 break;
158 case DebugMacroEntry::INDIRECT:
159 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
160 break;
161 default:
162 // This is an unknown/invalid entry. Ignore.
163 break;
164 }
165 }
166}
167
168static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
169 StreamString &stream) {
170 for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
171 lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
172
173 ConstString var_name = var_sp->GetName();
174 if (!var_name || var_name == ConstString("this") ||
175 var_name == ConstString(".block_descriptor"))
176 continue;
177
178 stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
179 }
180}
181
182bool ExpressionSourceCode::GetText(std::string &text,
183 lldb::LanguageType wrapping_language,
184 bool static_method,
185 ExecutionContext &exe_ctx) const {
186 const char *target_specific_defines = "typedef signed char BOOL;\n";
187 std::string module_macros;
188
189 Target *target = exe_ctx.GetTargetPtr();
1
'target' initialized here
190 if (target) {
2
Assuming 'target' is null
3
Taking false branch
191 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) {
192 target_specific_defines = "typedef bool BOOL;\n";
193 }
194 if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
195 if (lldb::PlatformSP platform_sp = target->GetPlatform()) {
196 static ConstString g_platform_ios_simulator("ios-simulator");
197 if (platform_sp->GetPluginName() == g_platform_ios_simulator) {
198 target_specific_defines = "typedef bool BOOL;\n";
199 }
200 }
201 }
202
203 if (ClangModulesDeclVendor *decl_vendor =
204 target->GetClangModulesDeclVendor()) {
205 ClangPersistentVariables *persistent_vars =
206 llvm::cast<ClangPersistentVariables>(
207 target->GetPersistentExpressionStateForLanguage(
208 lldb::eLanguageTypeC));
209 const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
210 persistent_vars->GetHandLoadedClangModules();
211 ClangModulesDeclVendor::ModuleVector modules_for_macros;
212
213 for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
214 modules_for_macros.push_back(module);
215 }
216
217 if (target->GetEnableAutoImportClangModules()) {
218 if (StackFrame *frame = exe_ctx.GetFramePtr()) {
219 if (Block *block = frame->GetFrameBlock()) {
220 SymbolContext sc;
221
222 block->CalculateSymbolContext(&sc);
223
224 if (sc.comp_unit) {
225 StreamString error_stream;
226
227 decl_vendor->AddModulesForCompileUnit(
228 *sc.comp_unit, modules_for_macros, error_stream);
229 }
230 }
231 }
232 }
233
234 decl_vendor->ForEachMacro(
235 modules_for_macros,
236 [&module_macros](const std::string &expansion) -> bool {
237 module_macros.append(expansion);
238 module_macros.append("\n");
239 return false;
240 });
241 }
242 }
243
244 StreamString debug_macros_stream;
245 StreamString lldb_local_var_decls;
246 if (StackFrame *frame = exe_ctx.GetFramePtr()) {
4
Assuming 'frame' is non-null
5
Taking true branch
247 const SymbolContext &sc = frame->GetSymbolContext(
248 lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
249
250 if (sc.comp_unit && sc.line_entry.IsValid()) {
6
Assuming the condition is false
251 DebugMacros *dm = sc.comp_unit->GetDebugMacros();
252 if (dm) {
253 AddMacroState state(sc.line_entry.file, sc.line_entry.line);
254 AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
255 }
256 }
257
258 ConstString object_name;
259 if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
7
Assuming the condition is true
8
Taking true branch
260 if (target->GetInjectLocalVariables(&exe_ctx)) {
9
Called C++ object pointer is null
261 lldb::VariableListSP var_list_sp =
262 frame->GetInScopeVariableList(false, true);
263 AddLocalVariableDecls(var_list_sp, lldb_local_var_decls);
264 }
265 }
266 }
267
268 if (m_wrap) {
269 switch (wrapping_language) {
270 default:
271 return false;
272 case lldb::eLanguageTypeC:
273 case lldb::eLanguageTypeC_plus_plus:
274 case lldb::eLanguageTypeObjC:
275 break;
276 }
277
278 StreamString wrap_stream;
279
280 wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(),
281 debug_macros_stream.GetData(), g_expression_prefix,
282 target_specific_defines, m_prefix.c_str());
283
284 // First construct a tagged form of the user expression so we can find it
285 // later:
286 std::string tagged_body;
287 switch (wrapping_language) {
288 default:
289 tagged_body = m_body;
290 break;
291 case lldb::eLanguageTypeC:
292 case lldb::eLanguageTypeC_plus_plus:
293 case lldb::eLanguageTypeObjC:
294 tagged_body.append(c_start_marker);
295 tagged_body.append(m_body);
296 tagged_body.append(c_end_marker);
297 break;
298 }
299 switch (wrapping_language) {
300 default:
301 break;
302 case lldb::eLanguageTypeC:
303 wrap_stream.Printf("void \n"
304 "%s(void *$__lldb_arg) \n"
305 "{ \n"
306 " %s; \n"
307 "%s"
308 "} \n",
309 m_name.c_str(), lldb_local_var_decls.GetData(),
310 tagged_body.c_str());
311 break;
312 case lldb::eLanguageTypeC_plus_plus:
313 wrap_stream.Printf("void \n"
314 "$__lldb_class::%s(void *$__lldb_arg) \n"
315 "{ \n"
316 " %s; \n"
317 "%s"
318 "} \n",
319 m_name.c_str(), lldb_local_var_decls.GetData(),
320 tagged_body.c_str());
321 break;
322 case lldb::eLanguageTypeObjC:
323 if (static_method) {
324 wrap_stream.Printf(
325 "@interface $__lldb_objc_class ($__lldb_category) \n"
326 "+(void)%s:(void *)$__lldb_arg; \n"
327 "@end \n"
328 "@implementation $__lldb_objc_class ($__lldb_category) \n"
329 "+(void)%s:(void *)$__lldb_arg \n"
330 "{ \n"
331 "%s"
332 "} \n"
333 "@end \n",
334 m_name.c_str(), m_name.c_str(), tagged_body.c_str());
335 } else {
336 wrap_stream.Printf(
337 "@interface $__lldb_objc_class ($__lldb_category) \n"
338 "-(void)%s:(void *)$__lldb_arg; \n"
339 "@end \n"
340 "@implementation $__lldb_objc_class ($__lldb_category) \n"
341 "-(void)%s:(void *)$__lldb_arg \n"
342 "{ \n"
343 "%s"
344 "} \n"
345 "@end \n",
346 m_name.c_str(), m_name.c_str(), tagged_body.c_str());
347 }
348 break;
349 }
350
351 text = wrap_stream.GetString();
352 } else {
353 text.append(m_body);
354 }
355
356 return true;
357}
358
359bool ExpressionSourceCode::GetOriginalBodyBounds(
360 std::string transformed_text, lldb::LanguageType wrapping_language,
361 size_t &start_loc, size_t &end_loc) {
362 const char *start_marker;
363 const char *end_marker;
364
365 switch (wrapping_language) {
366 default:
367 return false;
368 case lldb::eLanguageTypeC:
369 case lldb::eLanguageTypeC_plus_plus:
370 case lldb::eLanguageTypeObjC:
371 start_marker = c_start_marker;
372 end_marker = c_end_marker;
373 break;
374 }
375
376 start_loc = transformed_text.find(start_marker);
377 if (start_loc == std::string::npos)
378 return false;
379 start_loc += strlen(start_marker);
380 end_loc = transformed_text.find(end_marker);
381 if (end_loc == std::string::npos)
382 return false;
383 return true;
384}