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 // Project includes 16 #include "lldb/Interpreter/Args.h" 17 #include "lldb/Core/Value.h" 18 #include "lldb/Core/InputReader.h" 19 #include "lldb/Expression/ClangExpression.h" 20 #include "lldb/Expression/ClangExpressionDeclMap.h" 21 #include "lldb/Expression/ClangExpressionVariable.h" 22 #include "lldb/Expression/ClangPersistentVariables.h" 23 #include "lldb/Expression/ClangFunction.h" 24 #include "lldb/Expression/DWARFExpression.h" 25 #include "lldb/Host/Host.h" 26 #include "lldb/Core/Debugger.h" 27 #include "lldb/Interpreter/CommandInterpreter.h" 28 #include "lldb/Interpreter/CommandReturnObject.h" 29 #include "lldb/Symbol/ObjectFile.h" 30 #include "lldb/Symbol/Variable.h" 31 #include "lldb/Target/Process.h" 32 #include "lldb/Target/StackFrame.h" 33 #include "lldb/Target/Target.h" 34 #include "llvm/ADT/StringRef.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 default: 76 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 77 break; 78 } 79 80 return error; 81 } 82 83 void 84 CommandObjectExpression::CommandOptions::ResetOptionValues () 85 { 86 Options::ResetOptionValues(); 87 language.Clear(); 88 debug = false; 89 format = eFormatDefault; 90 show_types = true; 91 show_summary = true; 92 } 93 94 const lldb::OptionDefinition* 95 CommandObjectExpression::CommandOptions::GetDefinitions () 96 { 97 return g_option_table; 98 } 99 100 CommandObjectExpression::CommandObjectExpression () : 101 CommandObject ( 102 "expression", 103 "Evaluate a C expression in the current program context, using variables currently in scope.", 104 "expression [<cmd-options>] <expr>"), 105 m_expr_line_count (0), 106 m_expr_lines () 107 { 108 SetHelpLong( 109 "Examples: \n\ 110 \n\ 111 expr my_struct->a = my_array[3] \n\ 112 expr -f bin -- (index * 8) + 5 \n\ 113 expr char c[] = \"foo\"; c[0]\n"); 114 } 115 116 CommandObjectExpression::~CommandObjectExpression () 117 { 118 } 119 120 Options * 121 CommandObjectExpression::GetOptions () 122 { 123 return &m_options; 124 } 125 126 127 bool 128 CommandObjectExpression::Execute 129 ( 130 CommandInterpreter &interpreter, 131 Args& command, 132 CommandReturnObject &result 133 ) 134 { 135 return false; 136 } 137 138 139 size_t 140 CommandObjectExpression::MultiLineExpressionCallback 141 ( 142 void *baton, 143 InputReader &reader, 144 lldb::InputReaderAction notification, 145 const char *bytes, 146 size_t bytes_len 147 ) 148 { 149 CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton; 150 151 switch (notification) 152 { 153 case eInputReaderActivate: 154 reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter expressions, then terminate with an empty line to evaluate:"); 155 // Fall through 156 case eInputReaderReactivate: 157 //if (out_fh) 158 // reader.GetDebugger().GetOutputStream().Printf ("%3u: ", cmd_object_expr->m_expr_line_count); 159 break; 160 161 case eInputReaderDeactivate: 162 break; 163 164 case eInputReaderGotToken: 165 ++cmd_object_expr->m_expr_line_count; 166 if (bytes && bytes_len) 167 { 168 cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1); 169 } 170 171 if (bytes_len == 0) 172 reader.SetIsDone(true); 173 //else if (out_fh && !reader->IsDone()) 174 // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count); 175 break; 176 177 case eInputReaderDone: 178 { 179 bool bare = false; 180 cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 181 bare, 182 reader.GetDebugger().GetOutputStream(), 183 reader.GetDebugger().GetErrorStream()); 184 } 185 break; 186 } 187 188 return bytes_len; 189 } 190 191 bool 192 CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream, 193 CommandReturnObject *result) 194 { 195 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); 196 197 //////////////////////////////////// 198 // Set up the target and compiler 199 // 200 201 Target *target = m_exe_ctx.target; 202 203 if (!target) 204 { 205 error_stream.PutCString ("error: invalid target\n"); 206 return false; 207 } 208 209 ConstString target_triple; 210 211 target->GetTargetTriple (target_triple); 212 213 if (!target_triple) 214 target_triple = Host::GetTargetTriple (); 215 216 if (!target_triple) 217 { 218 error_stream.PutCString ("error: invalid target triple\n"); 219 return false; 220 } 221 222 ClangExpressionDeclMap expr_decl_map (&m_exe_ctx); 223 ClangExpression clang_expr (target_triple.AsCString (), &expr_decl_map); 224 225 ////////////////////////// 226 // Parse the expression 227 // 228 229 unsigned num_errors; 230 231 if (bare) 232 num_errors = clang_expr.ParseBareExpression (llvm::StringRef (expr), error_stream); 233 else 234 num_errors = clang_expr.ParseExpression (expr, error_stream, true); 235 236 if (num_errors) 237 { 238 error_stream.Printf ("error: %d errors parsing expression\n", num_errors); 239 return false; 240 } 241 242 /////////////////////////////////////////////// 243 // Convert the output of the parser to DWARF 244 // 245 246 StreamString dwarf_opcodes; 247 dwarf_opcodes.SetByteOrder (eByteOrderHost); 248 dwarf_opcodes.GetFlags ().Set (Stream::eBinary); 249 250 ClangExpressionVariableList expr_local_vars; 251 252 bool success; 253 bool canInterpret = false; 254 255 ClangExpressionVariable *expr_result = 0; 256 Error expr_error; 257 258 canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes); 259 260 if (canInterpret) 261 { 262 if (log) 263 log->Printf("Code can be interpreted."); 264 success = true; 265 } 266 else 267 { 268 if (log) 269 log->Printf("Code cannot be interpreted and must be run in the target."); 270 success = clang_expr.PrepareIRForTarget (); 271 } 272 273 if (!success) 274 { 275 error_stream.PutCString ("error: expression couldn't be converted to IR\n"); 276 return false; 277 } 278 279 if (canInterpret) 280 { 281 // TODO interpret IR 282 return false; 283 } 284 else 285 { 286 if (!clang_expr.JITFunction ()) 287 { 288 error_stream.PutCString ("error: IR could not be JIT compiled\n"); 289 return false; 290 } 291 292 if (!clang_expr.WriteJITCode (m_exe_ctx)) 293 { 294 error_stream.PutCString ("error: JIT code could not be written to the target\n"); 295 return false; 296 } 297 298 lldb::addr_t function_address(clang_expr.GetFunctionAddress ()); 299 300 if (function_address == LLDB_INVALID_ADDRESS) 301 { 302 error_stream.PutCString ("JIT compiled code's address couldn't be found\n"); 303 return false; 304 } 305 306 lldb::addr_t struct_address; 307 308 if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, expr_error)) 309 { 310 error_stream.Printf ("Couldn't materialize struct: %s\n", expr_error.AsCString("unknown error")); 311 return false; 312 } 313 314 if (log) 315 { 316 log->Printf("Function address : 0x%llx", (uint64_t)function_address); 317 log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); 318 319 StreamString insns; 320 321 Error err = clang_expr.DisassembleFunction(insns, m_exe_ctx); 322 323 if (!err.Success()) 324 { 325 log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); 326 } 327 else 328 { 329 log->Printf("Function disassembly:\n%s", insns.GetData()); 330 } 331 332 StreamString args; 333 334 if (!expr_decl_map.DumpMaterializedStruct(&m_exe_ctx, args, err)) 335 { 336 log->Printf("Couldn't extract variable values : %s", err.AsCString("unknown error")); 337 } 338 else 339 { 340 log->Printf("Structure contents:\n%s", args.GetData()); 341 } 342 } 343 344 ClangFunction::ExecutionResults execution_result = 345 ClangFunction::ExecuteFunction (m_exe_ctx, function_address, struct_address, true, true, 10000, error_stream); 346 347 if (execution_result != ClangFunction::eExecutionCompleted) 348 { 349 const char *result_name; 350 351 switch (execution_result) 352 { 353 case ClangFunction::eExecutionCompleted: 354 result_name = "eExecutionCompleted"; 355 break; 356 case ClangFunction::eExecutionDiscarded: 357 result_name = "eExecutionDiscarded"; 358 break; 359 case ClangFunction::eExecutionInterrupted: 360 result_name = "eExecutionInterrupted"; 361 break; 362 case ClangFunction::eExecutionSetupError: 363 result_name = "eExecutionSetupError"; 364 break; 365 case ClangFunction::eExecutionTimedOut: 366 result_name = "eExecutionTimedOut"; 367 break; 368 } 369 370 error_stream.Printf ("Couldn't execute function; result was %s\n", result_name); 371 return false; 372 } 373 374 if (!expr_decl_map.Dematerialize(&m_exe_ctx, expr_result, expr_error)) 375 { 376 error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error")); 377 return false; 378 } 379 } 380 381 if (expr_result) 382 { 383 StreamString ss; 384 385 Error rc = expr_result->Print (ss, 386 m_exe_ctx, 387 m_options.format, 388 m_options.show_types, 389 m_options.show_summary, 390 m_options.debug); 391 392 if (rc.Fail()) { 393 error_stream.Printf ("Couldn't print result : %s\n", rc.AsCString()); 394 return false; 395 } 396 397 output_stream.PutCString(ss.GetString().c_str()); 398 if (result) 399 result->SetStatus (eReturnStatusSuccessFinishResult); 400 } 401 else 402 { 403 error_stream.Printf ("Expression produced no result\n"); 404 if (result) 405 result->SetStatus (eReturnStatusSuccessFinishNoResult); 406 } 407 408 return true; 409 } 410 411 bool 412 CommandObjectExpression::ExecuteRawCommandString 413 ( 414 CommandInterpreter &interpreter, 415 const char *command, 416 CommandReturnObject &result 417 ) 418 { 419 m_exe_ctx = interpreter.GetDebugger().GetExecutionContext(); 420 421 m_options.ResetOptionValues(); 422 423 const char * expr = NULL; 424 425 if (command[0] == '\0') 426 { 427 m_expr_lines.clear(); 428 m_expr_line_count = 0; 429 430 InputReaderSP reader_sp (new InputReader(interpreter.GetDebugger())); 431 if (reader_sp) 432 { 433 Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback, 434 this, // baton 435 eInputReaderGranularityLine, // token size, to pass to callback function 436 NULL, // end token 437 NULL, // prompt 438 true)); // echo input 439 if (err.Success()) 440 { 441 interpreter.GetDebugger().PushInputReader (reader_sp); 442 result.SetStatus (eReturnStatusSuccessFinishNoResult); 443 } 444 else 445 { 446 result.AppendError (err.AsCString()); 447 result.SetStatus (eReturnStatusFailed); 448 } 449 } 450 else 451 { 452 result.AppendError("out of memory"); 453 result.SetStatus (eReturnStatusFailed); 454 } 455 return result.Succeeded(); 456 } 457 458 if (command[0] == '-') 459 { 460 // We have some options and these options MUST end with --. 461 const char *end_options = NULL; 462 const char *s = command; 463 while (s && s[0]) 464 { 465 end_options = ::strstr (s, "--"); 466 if (end_options) 467 { 468 end_options += 2; // Get past the "--" 469 if (::isspace (end_options[0])) 470 { 471 expr = end_options; 472 while (::isspace (*expr)) 473 ++expr; 474 break; 475 } 476 } 477 s = end_options; 478 } 479 480 if (end_options) 481 { 482 Args args (command, end_options - command); 483 if (!ParseOptions (interpreter, args, result)) 484 return false; 485 } 486 } 487 488 if (expr == NULL) 489 expr = command; 490 491 if (EvaluateExpression (expr, false, result.GetOutputStream(), result.GetErrorStream(), &result)) 492 return true; 493 494 result.SetStatus (eReturnStatusFailed); 495 return false; 496 } 497 498 lldb::OptionDefinition 499 CommandObjectExpression::CommandOptions::g_option_table[] = 500 { 501 { LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."}, 502 { 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."}, 503 { LLDB_OPT_SET_ALL, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."}, 504 { LLDB_OPT_SET_ALL, false, "use-ir", 'i', no_argument, NULL, 0, NULL, "[Temporary] Instructs the expression evaluator to use IR instead of ASTs."}, 505 { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL } 506 }; 507 508