clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name GoUserExpression.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-8/lib/clang/8.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/include -I /build/llvm-toolchain-snapshot-8~svn345461/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-8~svn345461/tools/clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/8.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-8/lib/clang/8.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-8~svn345461/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-10-27-211344-32123-1 -x c++ /build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp -faddrsig
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | #include <stdio.h> |
12 | #if HAVE_SYS_TYPES_H |
13 | #include <sys/types.h> |
14 | #endif |
15 | |
16 | |
17 | #include <cstdlib> |
18 | #include <memory> |
19 | #include <string> |
20 | #include <vector> |
21 | |
22 | |
23 | #include "llvm/ADT/StringMap.h" |
24 | #include "llvm/ADT/StringRef.h" |
25 | |
26 | |
27 | #include "GoUserExpression.h" |
28 | |
29 | #include "lldb/Core/Module.h" |
30 | #include "lldb/Core/StreamFile.h" |
31 | #include "lldb/Core/ValueObjectConstResult.h" |
32 | #include "lldb/Core/ValueObjectRegister.h" |
33 | #include "lldb/Expression/DiagnosticManager.h" |
34 | #include "lldb/Expression/ExpressionVariable.h" |
35 | #include "lldb/Symbol/GoASTContext.h" |
36 | #include "lldb/Symbol/SymbolFile.h" |
37 | #include "lldb/Symbol/TypeList.h" |
38 | #include "lldb/Symbol/VariableList.h" |
39 | #include "lldb/Target/ExecutionContext.h" |
40 | #include "lldb/Target/Process.h" |
41 | #include "lldb/Target/RegisterContext.h" |
42 | #include "lldb/Target/StackFrame.h" |
43 | #include "lldb/Target/Target.h" |
44 | #include "lldb/Target/ThreadPlan.h" |
45 | #include "lldb/Target/ThreadPlanCallUserExpression.h" |
46 | #include "lldb/Utility/ConstString.h" |
47 | #include "lldb/Utility/DataBufferHeap.h" |
48 | #include "lldb/Utility/DataEncoder.h" |
49 | #include "lldb/Utility/DataExtractor.h" |
50 | #include "lldb/Utility/Log.h" |
51 | #include "lldb/Utility/StreamString.h" |
52 | #include "lldb/lldb-private.h" |
53 | |
54 | #include "Plugins/ExpressionParser/Go/GoAST.h" |
55 | #include "Plugins/ExpressionParser/Go/GoParser.h" |
56 | |
57 | using namespace lldb_private; |
58 | using namespace lldb; |
59 | |
60 | class GoUserExpression::GoInterpreter { |
61 | public: |
62 | GoInterpreter(ExecutionContext &exe_ctx, const char *expr) |
63 | : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) { |
64 | if (m_frame) { |
65 | const SymbolContext &ctx = |
66 | m_frame->GetSymbolContext(eSymbolContextFunction); |
67 | ConstString fname = ctx.GetFunctionName(); |
68 | if (fname.GetLength() > 0) { |
69 | size_t dot = fname.GetStringRef().find('.'); |
70 | if (dot != llvm::StringRef::npos) |
71 | m_package = llvm::StringRef(fname.AsCString(), dot); |
72 | } |
73 | } |
74 | } |
75 | |
76 | void set_use_dynamic(DynamicValueType use_dynamic) { |
77 | m_use_dynamic = use_dynamic; |
78 | } |
79 | |
80 | bool Parse(); |
81 | lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx); |
82 | lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s); |
83 | lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e); |
84 | |
85 | ValueObjectSP VisitBadExpr(const GoASTBadExpr *e) { |
86 | m_parser.GetError(m_error); |
87 | return nullptr; |
88 | } |
89 | |
90 | ValueObjectSP VisitParenExpr(const GoASTParenExpr *e); |
91 | ValueObjectSP VisitIdent(const GoASTIdent *e); |
92 | ValueObjectSP VisitStarExpr(const GoASTStarExpr *e); |
93 | ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e); |
94 | ValueObjectSP VisitBasicLit(const GoASTBasicLit *e); |
95 | ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e); |
96 | ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e); |
97 | ValueObjectSP VisitCallExpr(const GoASTCallExpr *e); |
98 | |
99 | ValueObjectSP VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) { |
100 | return NotImplemented(e); |
101 | } |
102 | |
103 | ValueObjectSP VisitBinaryExpr(const GoASTBinaryExpr *e) { |
104 | return NotImplemented(e); |
105 | } |
106 | |
107 | ValueObjectSP VisitArrayType(const GoASTArrayType *e) { |
108 | return NotImplemented(e); |
109 | } |
110 | |
111 | ValueObjectSP VisitChanType(const GoASTChanType *e) { |
112 | return NotImplemented(e); |
113 | } |
114 | |
115 | ValueObjectSP VisitCompositeLit(const GoASTCompositeLit *e) { |
116 | return NotImplemented(e); |
117 | } |
118 | |
119 | ValueObjectSP VisitEllipsis(const GoASTEllipsis *e) { |
120 | return NotImplemented(e); |
121 | } |
122 | |
123 | ValueObjectSP VisitFuncType(const GoASTFuncType *e) { |
124 | return NotImplemented(e); |
125 | } |
126 | |
127 | ValueObjectSP VisitFuncLit(const GoASTFuncLit *e) { |
128 | return NotImplemented(e); |
129 | } |
130 | |
131 | ValueObjectSP VisitInterfaceType(const GoASTInterfaceType *e) { |
132 | return NotImplemented(e); |
133 | } |
134 | |
135 | ValueObjectSP VisitKeyValueExpr(const GoASTKeyValueExpr *e) { |
136 | return NotImplemented(e); |
137 | } |
138 | |
139 | ValueObjectSP VisitMapType(const GoASTMapType *e) { |
140 | return NotImplemented(e); |
141 | } |
142 | |
143 | ValueObjectSP VisitSliceExpr(const GoASTSliceExpr *e) { |
144 | return NotImplemented(e); |
145 | } |
146 | |
147 | ValueObjectSP VisitStructType(const GoASTStructType *e) { |
148 | return NotImplemented(e); |
149 | } |
150 | |
151 | CompilerType EvaluateType(const GoASTExpr *e); |
152 | |
153 | Status &error() { return m_error; } |
154 | |
155 | private: |
156 | std::nullptr_t NotImplemented(const GoASTExpr *e) { |
157 | m_error.SetErrorStringWithFormat("%s node not implemented", |
158 | e->GetKindName()); |
159 | return nullptr; |
160 | } |
161 | |
162 | ExecutionContext m_exe_ctx; |
163 | lldb::StackFrameSP m_frame; |
164 | GoParser m_parser; |
165 | DynamicValueType m_use_dynamic; |
166 | Status m_error; |
167 | llvm::StringRef m_package; |
168 | std::vector<std::unique_ptr<GoASTStmt>> m_statements; |
169 | }; |
170 | |
171 | VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) { |
172 | ConstString fullname(name.str()); |
173 | VariableList variable_list; |
174 | if (!target) { |
175 | return nullptr; |
176 | } |
177 | const uint32_t match_count = |
178 | target->GetImages().FindGlobalVariables(fullname, 1, variable_list); |
179 | if (match_count == 1) { |
180 | return variable_list.GetVariableAtIndex(0); |
181 | } |
182 | return nullptr; |
183 | } |
184 | |
185 | CompilerType LookupType(TargetSP target, ConstString name) { |
186 | if (!target) |
187 | return CompilerType(); |
188 | SymbolContext sc; |
189 | TypeList type_list; |
190 | llvm::DenseSet<SymbolFile *> searched_symbol_files; |
191 | uint32_t num_matches = target->GetImages().FindTypes( |
192 | sc, name, false, 2, searched_symbol_files, type_list); |
193 | if (num_matches > 0) { |
194 | return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); |
195 | } |
196 | return CompilerType(); |
197 | } |
198 | |
199 | GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, |
200 | llvm::StringRef expr, llvm::StringRef prefix, |
201 | lldb::LanguageType language, |
202 | ResultType desired_type, |
203 | const EvaluateExpressionOptions &options) |
204 | : UserExpression(exe_scope, expr, prefix, language, desired_type, options) { |
205 | } |
206 | |
207 | bool GoUserExpression::Parse(DiagnosticManager &diagnostic_manager, |
208 | ExecutionContext &exe_ctx, |
209 | lldb_private::ExecutionPolicy execution_policy, |
210 | bool keep_result_in_memory, |
211 | bool generate_debug_info) { |
212 | InstallContext(exe_ctx); |
213 | m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText())); |
214 | if (m_interpreter->Parse()) |
215 | return true; |
216 | const char *error_cstr = m_interpreter->error().AsCString(); |
217 | if (error_cstr && error_cstr[0]) |
218 | diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr); |
219 | else |
220 | diagnostic_manager.Printf(eDiagnosticSeverityError, |
221 | "expression can't be interpreted or run"); |
222 | return false; |
223 | } |
224 | |
225 | lldb::ExpressionResults |
226 | GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, |
227 | ExecutionContext &exe_ctx, |
228 | const EvaluateExpressionOptions &options, |
229 | lldb::UserExpressionSP &shared_ptr_to_me, |
230 | lldb::ExpressionVariableSP &result) { |
231 | Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8) | |
232 | LIBLLDB_LOG_STEP(1u << 7))); |
233 | |
234 | lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); |
235 | lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; |
236 | |
237 | Process *process = exe_ctx.GetProcessPtr(); |
238 | Target *target = exe_ctx.GetTargetPtr(); |
239 | |
240 | if (target == nullptr || process == nullptr || |
241 | process->GetState() != lldb::eStateStopped) { |
242 | if (execution_policy == eExecutionPolicyAlways) { |
243 | if (log) |
244 | log->Printf("== [GoUserExpression::Evaluate] Expression may not run, " |
245 | "but is not constant =="); |
246 | |
247 | diagnostic_manager.PutString(eDiagnosticSeverityError, |
248 | "expression needed to run but couldn't"); |
249 | |
250 | return execution_results; |
251 | } |
252 | } |
253 | |
254 | m_interpreter->set_use_dynamic(options.GetUseDynamic()); |
255 | ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); |
256 | Status err = m_interpreter->error(); |
257 | m_interpreter.reset(); |
258 | |
259 | if (!result_val_sp) { |
260 | const char *error_cstr = err.AsCString(); |
261 | if (error_cstr && error_cstr[0]) |
262 | diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr); |
263 | else |
264 | diagnostic_manager.PutString(eDiagnosticSeverityError, |
265 | "expression can't be interpreted or run"); |
266 | return lldb::eExpressionDiscarded; |
267 | } |
268 | result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); |
269 | result->m_live_sp = result->m_frozen_sp = result_val_sp; |
270 | result->m_flags |= ExpressionVariable::EVIsProgramReference; |
271 | PersistentExpressionState *pv = |
272 | target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); |
273 | if (pv != nullptr) { |
274 | result->SetName(pv->GetNextPersistentVariableName( |
275 | *target, pv->GetPersistentVariablePrefix())); |
276 | pv->AddVariable(result); |
277 | } |
278 | return lldb::eExpressionCompleted; |
279 | } |
280 | |
281 | bool GoUserExpression::GoInterpreter::Parse() { |
282 | for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt; |
283 | stmt.reset(m_parser.Statement())) { |
284 | if (m_parser.Failed()) |
285 | break; |
286 | m_statements.emplace_back(std::move(stmt)); |
287 | } |
288 | if (m_parser.Failed() || !m_parser.AtEOF()) |
289 | m_parser.GetError(m_error); |
290 | |
291 | return m_error.Success(); |
292 | } |
293 | |
294 | ValueObjectSP |
295 | GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) { |
296 | m_exe_ctx = exe_ctx; |
297 | ValueObjectSP result; |
298 | for (const std::unique_ptr<GoASTStmt> &stmt : m_statements) { |
299 | result = EvaluateStatement(stmt.get()); |
300 | if (m_error.Fail()) |
301 | return nullptr; |
302 | } |
303 | return result; |
304 | } |
305 | |
306 | ValueObjectSP GoUserExpression::GoInterpreter::EvaluateStatement( |
307 | const lldb_private::GoASTStmt *stmt) { |
308 | ValueObjectSP result; |
309 | switch (stmt->GetKind()) { |
310 | case GoASTNode::eBlockStmt: { |
311 | const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt); |
312 | for (size_t i = 0; i < block->NumList(); ++i) |
313 | result = EvaluateStatement(block->GetList(i)); |
314 | break; |
315 | } |
316 | case GoASTNode::eBadStmt: |
317 | m_parser.GetError(m_error); |
318 | break; |
319 | case GoASTNode::eExprStmt: { |
320 | const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt); |
321 | return EvaluateExpr(expr->GetX()); |
322 | } |
323 | default: |
324 | m_error.SetErrorStringWithFormat("%s node not supported", |
325 | stmt->GetKindName()); |
326 | } |
327 | return result; |
328 | } |
329 | |
330 | ValueObjectSP GoUserExpression::GoInterpreter::EvaluateExpr( |
331 | const lldb_private::GoASTExpr *e) { |
332 | if (e) |
333 | return e->Visit<ValueObjectSP>(this); |
334 | return ValueObjectSP(); |
335 | } |
336 | |
337 | ValueObjectSP GoUserExpression::GoInterpreter::VisitParenExpr( |
338 | const lldb_private::GoASTParenExpr *e) { |
339 | return EvaluateExpr(e->GetX()); |
340 | } |
341 | |
342 | ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) { |
343 | ValueObjectSP val; |
344 | if (m_frame) { |
345 | VariableSP var_sp; |
346 | std::string varname = e->GetName().m_value.str(); |
347 | if (varname.size() > 1 && varname[0] == '$') { |
348 | RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext(); |
349 | const RegisterInfo *reg = |
350 | reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1); |
351 | if (reg) { |
352 | std::string type; |
353 | switch (reg->encoding) { |
354 | case lldb::eEncodingSint: |
355 | type.append("int"); |
356 | break; |
357 | case lldb::eEncodingUint: |
358 | type.append("uint"); |
359 | break; |
360 | case lldb::eEncodingIEEE754: |
361 | type.append("float"); |
362 | break; |
363 | default: |
364 | m_error.SetErrorString("Invalid register encoding"); |
365 | return nullptr; |
366 | } |
367 | switch (reg->byte_size) { |
368 | case 8: |
369 | type.append("64"); |
370 | break; |
371 | case 4: |
372 | type.append("32"); |
373 | break; |
374 | case 2: |
375 | type.append("16"); |
376 | break; |
377 | case 1: |
378 | type.append("8"); |
379 | break; |
380 | default: |
381 | m_error.SetErrorString("Invalid register size"); |
382 | return nullptr; |
383 | } |
384 | ValueObjectSP regVal = ValueObjectRegister::Create( |
385 | m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]); |
386 | CompilerType goType = |
387 | LookupType(m_frame->CalculateTarget(), ConstString(type)); |
388 | if (regVal) { |
389 | regVal = regVal->Cast(goType); |
390 | return regVal; |
391 | } |
392 | } |
393 | m_error.SetErrorString("Invalid register name"); |
394 | return nullptr; |
395 | } |
396 | VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false)); |
397 | if (var_list_sp) { |
398 | var_sp = var_list_sp->FindVariable(ConstString(varname)); |
399 | if (var_sp) |
400 | val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); |
401 | else { |
402 | |
403 | |
404 | var_sp = var_list_sp->FindVariable(ConstString("&" + varname)); |
405 | if (var_sp) { |
406 | val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); |
407 | if (val) |
408 | val = val->Dereference(m_error); |
409 | if (m_error.Fail()) |
410 | return nullptr; |
411 | } |
412 | } |
413 | } |
414 | if (!val) { |
415 | m_error.Clear(); |
416 | TargetSP target = m_frame->CalculateTarget(); |
417 | if (!target) { |
418 | m_error.SetErrorString("No target"); |
419 | return nullptr; |
420 | } |
421 | var_sp = |
422 | FindGlobalVariable(target, m_package + "." + e->GetName().m_value); |
423 | if (var_sp) |
424 | return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic); |
425 | } |
426 | } |
427 | if (!val) |
428 | m_error.SetErrorStringWithFormat("Unknown variable %s", |
429 | e->GetName().m_value.str().c_str()); |
430 | return val; |
431 | } |
432 | |
433 | ValueObjectSP |
434 | GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) { |
435 | ValueObjectSP target = EvaluateExpr(e->GetX()); |
436 | if (!target) |
437 | return nullptr; |
438 | return target->Dereference(m_error); |
439 | } |
440 | |
441 | ValueObjectSP GoUserExpression::GoInterpreter::VisitSelectorExpr( |
442 | const lldb_private::GoASTSelectorExpr *e) { |
443 | ValueObjectSP target = EvaluateExpr(e->GetX()); |
444 | if (target) { |
445 | if (target->GetCompilerType().IsPointerType()) { |
446 | target = target->Dereference(m_error); |
447 | if (m_error.Fail()) |
448 | return nullptr; |
449 | } |
450 | ConstString field(e->GetSel()->GetName().m_value); |
451 | ValueObjectSP result = target->GetChildMemberWithName(field, true); |
452 | if (!result) |
453 | m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString()); |
454 | return result; |
455 | } |
456 | if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) { |
457 | if (VariableSP global = FindGlobalVariable( |
458 | m_exe_ctx.GetTargetSP(), package->GetName().m_value + "." + |
459 | e->GetSel()->GetName().m_value)) { |
460 | if (m_frame) { |
461 | m_error.Clear(); |
462 | return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic); |
463 | } |
464 | } |
465 | } |
466 | if (const GoASTBasicLit *packageLit = |
467 | llvm::dyn_cast<GoASTBasicLit>(e->GetX())) { |
468 | if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) { |
469 | std::string value = packageLit->GetValue().m_value.str(); |
470 | value = value.substr(1, value.size() - 2); |
471 | if (VariableSP global = FindGlobalVariable( |
472 | m_exe_ctx.GetTargetSP(), |
473 | value + "." + e->GetSel()->GetName().m_value)) { |
474 | if (m_frame) { |
475 | m_error.Clear(); |
476 | return m_frame->TrackGlobalVariable(global, m_use_dynamic); |
477 | } |
478 | } |
479 | } |
480 | } |
481 | |
482 | return target; |
483 | } |
484 | |
485 | ValueObjectSP GoUserExpression::GoInterpreter::VisitBasicLit( |
486 | const lldb_private::GoASTBasicLit *e) { |
487 | std::string value = e->GetValue().m_value.str(); |
488 | if (e->GetValue().m_type != GoLexer::LIT_INTEGER) { |
489 | m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str()); |
490 | return nullptr; |
491 | } |
492 | errno(*__errno_location ()) = 0; |
493 | int64_t intvalue = strtol(value.c_str(), nullptr, 0); |
494 | if (errno(*__errno_location ()) != 0) { |
495 | m_error.SetErrorToErrno(); |
496 | return nullptr; |
497 | } |
498 | DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0)); |
499 | TargetSP target = m_exe_ctx.GetTargetSP(); |
500 | if (!target) { |
501 | m_error.SetErrorString("No target"); |
502 | return nullptr; |
503 | } |
504 | ByteOrder order = target->GetArchitecture().GetByteOrder(); |
505 | uint8_t addr_size = target->GetArchitecture().GetAddressByteSize(); |
506 | DataEncoder enc(buf, order, addr_size); |
507 | enc.PutU64(0, static_cast<uint64_t>(intvalue)); |
508 | DataExtractor data(buf, order, addr_size); |
509 | |
510 | CompilerType type = LookupType(target, ConstString("int64")); |
511 | return ValueObject::CreateValueObjectFromData(llvm::StringRef(), data, |
512 | m_exe_ctx, type); |
513 | } |
514 | |
515 | ValueObjectSP GoUserExpression::GoInterpreter::VisitIndexExpr( |
516 | const lldb_private::GoASTIndexExpr *e) { |
517 | ValueObjectSP target = EvaluateExpr(e->GetX()); |
518 | if (!target) |
519 | return nullptr; |
520 | ValueObjectSP index = EvaluateExpr(e->GetIndex()); |
521 | if (!index) |
522 | return nullptr; |
523 | bool is_signed; |
524 | if (!index->GetCompilerType().IsIntegerType(is_signed)) { |
525 | m_error.SetErrorString("Unsupported index"); |
526 | return nullptr; |
527 | } |
528 | size_t idx; |
529 | if (is_signed) |
530 | idx = index->GetValueAsSigned(0); |
531 | else |
532 | idx = index->GetValueAsUnsigned(0); |
533 | if (GoASTContext::IsGoSlice(target->GetCompilerType())) { |
534 | target = target->GetStaticValue(); |
535 | ValueObjectSP cap = |
536 | target->GetChildMemberWithName(ConstString("cap"), true); |
537 | if (cap) { |
538 | uint64_t capval = cap->GetValueAsUnsigned(0); |
539 | if (idx >= capval) { |
540 | m_error.SetErrorStringWithFormat("Invalid index %" PRIu64"l" "u" |
541 | " , cap = %" PRIu64"l" "u", |
542 | uint64_t(idx), capval); |
543 | return nullptr; |
544 | } |
545 | } |
546 | target = target->GetChildMemberWithName(ConstString("array"), true); |
547 | if (target && m_use_dynamic != eNoDynamicValues) { |
548 | ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic); |
549 | if (dynamic) |
550 | target = dynamic; |
551 | } |
552 | if (!target) |
553 | return nullptr; |
554 | return target->GetSyntheticArrayMember(idx, true); |
555 | } |
556 | return target->GetChildAtIndex(idx, true); |
557 | } |
558 | |
559 | ValueObjectSP |
560 | GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) { |
561 | ValueObjectSP x = EvaluateExpr(e->GetX()); |
562 | if (!x) |
563 | return nullptr; |
564 | switch (e->GetOp()) { |
565 | case GoLexer::OP_AMP: { |
566 | CompilerType type = x->GetCompilerType().GetPointerType(); |
567 | uint64_t address = x->GetAddressOf(); |
568 | return ValueObject::CreateValueObjectFromAddress(llvm::StringRef(), address, |
569 | m_exe_ctx, type); |
570 | } |
571 | case GoLexer::OP_PLUS: |
572 | return x; |
573 | default: |
574 | m_error.SetErrorStringWithFormat( |
575 | "Operator %s not supported", |
576 | GoLexer::LookupToken(e->GetOp()).str().c_str()); |
577 | return nullptr; |
578 | } |
579 | } |
580 | |
581 | CompilerType GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) { |
582 | TargetSP target = m_exe_ctx.GetTargetSP(); |
583 | if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) { |
584 | CompilerType result = |
585 | LookupType(target, ConstString(id->GetName().m_value)); |
586 | if (result.IsValid()) |
587 | return result; |
588 | std::string fullname = (m_package + "." + id->GetName().m_value).str(); |
589 | result = LookupType(target, ConstString(fullname)); |
590 | if (!result) |
591 | m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); |
592 | return result; |
593 | } |
594 | if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) { |
595 | std::string package; |
596 | if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) { |
597 | package = pkg_node->GetName().m_value.str(); |
598 | } else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) { |
599 | if (str_node->GetValue().m_type == GoLexer::LIT_STRING) { |
600 | package = str_node->GetValue().m_value.substr(1).str(); |
601 | package.resize(package.length() - 1); |
602 | } |
603 | } |
604 | if (package.empty()) { |
605 | m_error.SetErrorStringWithFormat("Invalid %s in type expression", |
606 | sel->GetX()->GetKindName()); |
607 | return CompilerType(); |
608 | } |
609 | std::string fullname = |
610 | (package + "." + sel->GetSel()->GetName().m_value).str(); |
611 | CompilerType result = LookupType(target, ConstString(fullname)); |
612 | if (!result) |
613 | m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); |
614 | return result; |
615 | } |
616 | if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) { |
617 | CompilerType elem = EvaluateType(star->GetX()); |
618 | return elem.GetPointerType(); |
619 | } |
620 | if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e)) |
621 | return EvaluateType(paren->GetX()); |
622 | if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) { |
623 | CompilerType elem = EvaluateType(array->GetElt()); |
624 | } |
625 | |
626 | m_error.SetErrorStringWithFormat("Invalid %s in type expression", |
627 | e->GetKindName()); |
628 | return CompilerType(); |
629 | } |
630 | |
631 | ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr( |
632 | const lldb_private::GoASTCallExpr *e) { |
633 | ValueObjectSP x = EvaluateExpr(e->GetFun()); |
634 | if (x || e->NumArgs() != 1) { |
635 | m_error.SetErrorStringWithFormat("Code execution not supported"); |
636 | return nullptr; |
637 | } |
638 | m_error.Clear(); |
639 | CompilerType type = EvaluateType(e->GetFun()); |
640 | if (!type) { |
641 | return nullptr; |
642 | } |
643 | ValueObjectSP value = EvaluateExpr(e->GetArgs(0)); |
644 | if (!value) |
645 | return nullptr; |
646 | |
647 | return value->Cast(type); |
648 | } |
649 | |
650 | GoPersistentExpressionState::GoPersistentExpressionState() |
651 | : PersistentExpressionState(eKindGo) {} |
652 | |
653 | void GoPersistentExpressionState::RemovePersistentVariable( |
654 | lldb::ExpressionVariableSP variable) { |
655 | RemoveVariable(variable); |
656 | |
657 | const char *name = variable->GetName().AsCString(); |
658 | |
659 | if (*(name++) != '$') |
| 1 | Null pointer value stored to 'name' | |
|
| 2 | | Dereference of null pointer |
|
660 | return; |
661 | if (*(name++) != 'g') |
662 | return; |
663 | if (*(name++) != 'o') |
664 | return; |
665 | |
666 | if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) |
667 | m_next_persistent_variable_id--; |
668 | } |