1 //===-- CommandObjectExpression.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 "CommandObjectExpression.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 #include "llvm/ADT/StringRef.h" 16 17 // Project includes 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/Value.h" 20 #include "lldb/Core/InputReader.h" 21 #include "lldb/Expression/ClangExpression.h" 22 #include "lldb/Expression/ClangExpressionDeclMap.h" 23 #include "lldb/Expression/ClangExpressionVariable.h" 24 #include "lldb/Expression/DWARFExpression.h" 25 #include "lldb/Host/Host.h" 26 #include "lldb/Interpreter/Args.h" 27 #include "lldb/Interpreter/CommandInterpreter.h" 28 #include "lldb/Interpreter/CommandReturnObject.h" 29 #include "lldb/Symbol/ClangASTType.h" 30 #include "lldb/Symbol/ObjectFile.h" 31 #include "lldb/Symbol/Variable.h" 32 #include "lldb/Target/Process.h" 33 #include "lldb/Target/StackFrame.h" 34 #include "lldb/Target/Target.h" 35 36 using namespace lldb; 37 using namespace lldb_private; 38 39 CommandObjectExpression::CommandOptions::CommandOptions () : 40 Options() 41 { 42 // Keep only one place to reset the values to their defaults 43 ResetOptionValues(); 44 } 45 46 47 CommandObjectExpression::CommandOptions::~CommandOptions () 48 { 49 } 50 51 Error 52 CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) 53 { 54 Error error; 55 56 char short_option = (char) m_getopt_table[option_idx].val; 57 58 switch (short_option) 59 { 60 case 'l': 61 if (language.SetLanguageFromCString (option_arg) == false) 62 { 63 error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg); 64 } 65 break; 66 67 case 'g': 68 debug = true; 69 break; 70 71 case 'f': 72 error = Args::StringToFormat(option_arg, format); 73 break; 74 75 case 'i': 76 use_ir = true; 77 break; 78 79 default: 80 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 81 break; 82 } 83 84 return error; 85 } 86 87 void 88 CommandObjectExpression::CommandOptions::ResetOptionValues () 89 { 90 Options::ResetOptionValues(); 91 language.Clear(); 92 debug = false; 93 format = eFormatDefault; 94 show_types = true; 95 show_summary = true; 96 use_ir = false; 97 } 98 99 const lldb::OptionDefinition* 100 CommandObjectExpression::CommandOptions::GetDefinitions () 101 { 102 return g_option_table; 103 } 104 105 CommandObjectExpression::CommandObjectExpression () : 106 CommandObject ( 107 "expression", 108 "Evaluate a C expression in the current program context, using variables currently in scope.", 109 "expression [<cmd-options>] <expr>"), 110 m_expr_line_count (0), 111 m_expr_lines () 112 { 113 SetHelpLong( 114 "Examples: \n\ 115 \n\ 116 expr my_struct->a = my_array[3] \n\ 117 expr -f bin -- (index * 8) + 5 \n\ 118 expr char c[] = \"foo\"; c[0]\n"); 119 } 120 121 CommandObjectExpression::~CommandObjectExpression () 122 { 123 } 124 125 Options * 126 CommandObjectExpression::GetOptions () 127 { 128 return &m_options; 129 } 130 131 132 bool 133 CommandObjectExpression::Execute 134 ( 135 CommandInterpreter &interpreter, 136 Args& command, 137 CommandReturnObject &result 138 ) 139 { 140 return false; 141 } 142 143 144 size_t 145 CommandObjectExpression::MultiLineExpressionCallback 146 ( 147 void *baton, 148 InputReader &reader, 149 lldb::InputReaderAction notification, 150 const char *bytes, 151 size_t bytes_len 152 ) 153 { 154 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 155 156 switch (notification) 157 { 158 case eInputReaderActivate: 159 reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter expressions, then terminate with an empty line to evaluate:"); 160 // Fall through 161 case eInputReaderReactivate: 162 //if (out_fh) 163 // reader.GetDebugger().GetOutputStream().Printf ("%3u: ", cmd_object_expr->m_expr_line_count); 164 break; 165 166 case eInputReaderDeactivate: 167 break; 168 169 case eInputReaderGotToken: 170 ++cmd_object_expr->m_expr_line_count; 171 if (bytes && bytes_len) 172 { 173 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 174 } 175 176 if (bytes_len == 0) 177 reader.SetIsDone(true); 178 //else if (out_fh && !reader->IsDone()) 179 // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count); 180 break; 181 182 case eInputReaderDone: 183 { 184 bool bare = false; 185 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 186 bare, 187 reader.GetDebugger().GetOutputStream(), 188 reader.GetDebugger().GetErrorStream()); 189 } 190 break; 191 } 192 193 return bytes_len; 194 } 195 196 bool 197 CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream) 198 { 199 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 200 201 //////////////////////////////////// 202 // Set up the target and compiler 203 // 204 205 Target *target = m_exe_ctx.target; 206 207 if (!target) 208 { 209 error_stream.PutCString ("error: invalid target\n"); 210 return false; 211 } 212 213 ConstString target_triple; 214 215 target->GetTargetTriple (target_triple); 216 217 if (!target_triple) 218 target_triple = Host::GetTargetTriple (); 219 220 if (!target_triple) 221 { 222 error_stream.PutCString ("error: invalid target triple\n"); 223 return false; 224 } 225 226 ClangExpressionDeclMap expr_decl_map (&m_exe_ctx); 227 ClangExpression clang_expr (target_triple.AsCString (), &expr_decl_map); 228 229 ////////////////////////// 230 // Parse the expression 231 // 232 233 unsigned num_errors; 234 235 if (bare) 236 num_errors = clang_expr.ParseBareExpression (llvm::StringRef (expr), error_stream); 237 else 238 num_errors = clang_expr.ParseExpression (expr, error_stream, m_options.use_ir); 239 240 if (num_errors) 241 { 242 error_stream.Printf ("error: %d errors parsing expression\n", num_errors); 243 return false; 244 } 245 246 /////////////////////////////////////////////// 247 // Convert the output of the parser to DWARF 248 // 249 250 StreamString dwarf_opcodes; 251 dwarf_opcodes.SetByteOrder (eByteOrderHost); 252 dwarf_opcodes.GetFlags ().Set (Stream::eBinary); 253 254 ClangExpressionVariableList expr_local_vars; 255 256 bool success; 257 bool canInterpret = false; 258 259 if (m_options.use_ir) 260 { 261 canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes); 262 263 if (canInterpret) 264 { 265 if (log) 266 log->Printf("Code can be interpreted."); 267 success = true; 268 } 269 else 270 { 271 if (log) 272 log->Printf("Code cannot be interpreted and must be run in the target."); 273 success = clang_expr.PrepareIRForTarget (expr_local_vars); 274 } 275 276 if (!success) 277 { 278 error_stream.PutCString ("error: expression couldn't be converted to IR\n"); 279 return false; 280 } 281 282 if (canInterpret) 283 { 284 // TODO interpret IR 285 return false; 286 } 287 else 288 { 289 if (!clang_expr.JITFunction (m_exe_ctx, "___clang_expr")) 290 { 291 error_stream.PutCString ("error: IR could not be JIT compiled\n"); 292 return false; 293 } 294 295 if (!clang_expr.WriteJITCode (m_exe_ctx)) 296 { 297 error_stream.PutCString ("error: JIT code could not be written to the target\n"); 298 return false; 299 } 300 301 lldb::addr_t function_address(clang_expr.GetFunctionAddress ("___clang_expr")); 302 303 if (function_address == LLDB_INVALID_ADDRESS) 304 { 305 error_stream.PutCString ("JIT compiled code's address couldn't be found\n"); 306 return false; 307 } 308 309 Error err; 310 lldb::addr_t struct_address; 311 312 if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, err)) 313 { 314 error_stream.Printf ("Couldn't materialize struct: %s\n", err.AsCString("unknown error")); 315 return false; 316 } 317 318 log->Printf("Function address : 0x%llx", (uint64_t)function_address); 319 log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); 320 } 321 322 return true; 323 324 } 325 else 326 { 327 success = (clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes) == 0); 328 329 if (!success) 330 { 331 error_stream.PutCString ("error: expression couldn't be translated to DWARF\n"); 332 return false; 333 } 334 335 ////////////////////////////////////////// 336 // Evaluate the generated DWARF opcodes 337 // 338 339 DataExtractor dwarf_opcodes_data (dwarf_opcodes.GetData (), dwarf_opcodes.GetSize (), eByteOrderHost, 8); 340 DWARFExpression dwarf_expr (dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize (), NULL); 341 342 dwarf_expr.SetExpressionLocalVariableList(&expr_local_vars); 343 344 if (log) 345 { 346 StreamString stream_string; 347 348 log->PutCString ("Expression parsed ok, dwarf opcodes:"); 349 350 stream_string.PutCString ("\n"); 351 stream_string.IndentMore (); 352 dwarf_expr.GetDescription (&stream_string, lldb::eDescriptionLevelVerbose); 353 stream_string.IndentLess (); 354 stream_string.EOL (); 355 356 log->PutCString (stream_string.GetString ().c_str ()); 357 } 358 359 clang::ASTContext *ast_context = clang_expr.GetASTContext (); 360 Value expr_result; 361 Error expr_error; 362 success = dwarf_expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error); 363 364 if (!success) 365 { 366 error_stream.Printf ("error: couldn't evaluate DWARF expression: %s\n", expr_error.AsCString ()); 367 return false; 368 } 369 370 /////////////////////////////////////// 371 // Interpret the result and print it 372 // 373 374 lldb::Format format = m_options.format; 375 376 // Resolve any values that are possible 377 expr_result.ResolveValue (&m_exe_ctx, ast_context); 378 379 if (expr_result.GetContextType () == Value::eContextTypeInvalid && 380 expr_result.GetValueType () == Value::eValueTypeScalar && 381 format == eFormatDefault) 382 { 383 // The expression result is just a scalar with no special formatting 384 expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types); 385 output_stream.EOL (); 386 return true; 387 } 388 389 // The expression result is more complext and requires special handling 390 DataExtractor data; 391 expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0); 392 393 if (!expr_error.Success ()) 394 { 395 error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ()); 396 return false; 397 } 398 399 if (format == eFormatDefault) 400 format = expr_result.GetValueDefaultFormat (); 401 402 void *clang_type = expr_result.GetValueOpaqueClangQualType (); 403 404 if (clang_type) 405 { 406 if (m_options.show_types) 407 { 408 ConstString type_name(ClangASTType::GetClangTypeName (clang_type)); 409 if (type_name) 410 output_stream.Printf("(%s) ", type_name.AsCString("<invalid>")); 411 } 412 413 ClangASTType::DumpValue (ast_context, // The ASTContext that the clang type belongs to 414 clang_type, // The opaque clang type we want to dump that value of 415 &m_exe_ctx, // The execution context for memory and variable access 416 &output_stream, // Stream to dump to 417 format, // Format to use when dumping 418 data, // A buffer containing the bytes for the clang type 419 0, // Byte offset within "data" where value is 420 data.GetByteSize (), // Size in bytes of the value we are dumping 421 0, // Bitfield bit size 422 0, // Bitfield bit offset 423 m_options.show_types, // Show types? 424 m_options.show_summary, // Show summary? 425 m_options.debug, // Debug logging output? 426 UINT32_MAX); // Depth to dump in case this is an aggregate type 427 } 428 else 429 { 430 data.Dump (&output_stream, // Stream to dump to 431 0, // Byte offset within "data" 432 format, // Format to use when dumping 433 data.GetByteSize (), // Size in bytes of each item we are dumping 434 1, // Number of items to dump 435 UINT32_MAX, // Number of items per line 436 LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context 437 0, // Bitfield bit size 438 0); // Bitfield bit offset 439 } 440 output_stream.EOL(); 441 442 return true; 443 } 444 } 445 446 bool 447 CommandObjectExpression::ExecuteRawCommandString 448 ( 449 CommandInterpreter &interpreter, 450 const char *command, 451 CommandReturnObject &result 452 ) 453 { 454 m_exe_ctx = interpreter.GetDebugger().GetExecutionContext(); 455 456 m_options.ResetOptionValues(); 457 458 const char * expr = NULL; 459 460 if (command[0] == '\0') 461 { 462 m_expr_lines.clear(); 463 m_expr_line_count = 0; 464 465 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger())); 466 if (reader_sp) 467 { 468 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 469 this, // baton 470 eInputReaderGranularityLine, // token size, to pass to callback function 471 NULL, // end token 472 NULL, // prompt 473 true)); // echo input 474 if (err.Success()) 475 { 476 interpreter.GetDebugger().PushInputReader (reader_sp); 477 result.SetStatus (eReturnStatusSuccessFinishNoResult); 478 } 479 else 480 { 481 result.AppendError (err.AsCString()); 482 result.SetStatus (eReturnStatusFailed); 483 } 484 } 485 else 486 { 487 result.AppendError("out of memory"); 488 result.SetStatus (eReturnStatusFailed); 489 } 490 return result.Succeeded(); 491 } 492 493 if (command[0] == '-') 494 { 495 // We have some options and these options MUST end with --. 496 const char *end_options = NULL; 497 const char *s = command; 498 while (s && s[0]) 499 { 500 end_options = ::strstr (s, "--"); 501 if (end_options) 502 { 503 end_options += 2; // Get past the "--" 504 if (::isspace (end_options[0])) 505 { 506 expr = end_options; 507 while (::isspace (*expr)) 508 ++expr; 509 break; 510 } 511 } 512 s = end_options; 513 } 514 515 if (end_options) 516 { 517 Args args (command, end_options - command); 518 if (!ParseOptions (interpreter, args, result)) 519 return false; 520 } 521 } 522 523 if (expr == NULL) 524 expr = command; 525 526 return EvaluateExpression (expr, false, result.GetOutputStream(), result.GetErrorStream()); 527 } 528 529 lldb::OptionDefinition 530 CommandObjectExpression::CommandOptions::g_option_table[] = 531 { 532 { LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."}, 533 { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."}, 534 { LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."}, 535 { LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, NULL, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."}, 536 { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL } 537 }; 538 539